#12 most of TCHDB tests passed!
authoradam <anton@adamansky.com>
Mon, 15 Apr 2013 19:01:21 +0000 (02:01 +0700)
committeradam <anton@adamansky.com>
Mon, 15 Apr 2013 19:01:21 +0000 (02:01 +0700)
47 files changed:
tcejdb/Makefile.in
tcejdb/basedefs.h [new file with mode: 0644]
tcejdb/bson.c
tcejdb/bson.h
tcejdb/config.sub [new file with mode: 0644]
tcejdb/configure
tcejdb/configure.ac
tcejdb/ejdb.c
tcejdb/ejdb.h
tcejdb/ejdb_private.h
tcejdb/ejdbutl.c
tcejdb/ejdbutl.h
tcejdb/myconf.h
tcejdb/platform.c [new file with mode: 0644]
tcejdb/tcadb.c
tcejdb/tcadb.h
tcejdb/tcamgr.c
tcejdb/tcamttest.c
tcejdb/tcatest.c
tcejdb/tcawmgr.c
tcejdb/tcbdb.c
tcejdb/tcbdb.h
tcejdb/tcbmgr.c
tcejdb/tcbmttest.c
tcejdb/tcbtest.c
tcejdb/tcfdb.c
tcejdb/tcfdb.h
tcejdb/tcfmgr.c
tcejdb/tcfmttest.c
tcejdb/tcftest.c
tcejdb/tchdb.c
tcejdb/tchdb.h
tcejdb/tchmgr.c
tcejdb/tchmttest.c
tcejdb/tchtest.c
tcejdb/tctdb.c
tcejdb/tctdb.h
tcejdb/tctmgr.c
tcejdb/tctmttest.c
tcejdb/tcttest.c
tcejdb/tcucodec.c
tcejdb/tcumttest.c
tcejdb/tcutest.c
tcejdb/tcutil.c
tcejdb/tcutil.h
tcejdb/win32/platform.c [new file with mode: 0644]
tcejdb/win32/platform.h [new file with mode: 0644]

index 7cf1b09..191c52f 100644 (file)
@@ -49,7 +49,7 @@ CC = @CC@
 CPPFLAGS = @MYCPPFLAGS@ \
   -D_TC_PREFIX="\"$(prefix)\"" -D_TC_INCLUDEDIR="\"$(INCLUDEDIR)\"" \
   -D_TC_LIBDIR="\"$(LIBDIR)\"" -D_TC_BINDIR="\"$(BINDIR)\"" -D_TC_LIBEXECDIR="\"$(LIBEXECDIR)\"" \
-  -D_TC_APPINC="\"-I$(INCLUDEDIR)\"" -D_TC_APPLIBS="\"-L$(LIBDIR) -ltcejdb @LIBS@\""
+  -D_TC_APPINC="\"-I$(INCLUDEDIR)\"" -D_TC_APPLIBS="\"-L$(LIBDIR) @LIBS@\""
 CFLAGS = @MYCFLAGS@
 LDFLAGS = @MYLDFLAGS@
 CMDLDFLAGS = @MYCMDLDFLAGS@
@@ -295,7 +295,7 @@ check-hdb :
        $(RUNENV) $(RUNCMD) ./tchmgr get casket four > check.out
        $(RUNENV) $(RUNCMD) ./tchmgr get casket five > check.out
        $(RUNENV) $(RUNCMD) ./tchmgr list -pv casket > check.out
-       rm -rf casket*
+#      rm -rf casket*
 
 
 check-bdb :
@@ -724,6 +724,9 @@ libtcejdb.$(LIBVER).dylib : libtcejdb.$(LIBVER).$(LIBREV).0.dylib
 libtcejdb.dylib : libtcejdb.$(LIBVER).$(LIBREV).0.dylib
        ln -f -s libtcejdb.$(LIBVER).$(LIBREV).0.dylib $@
 
+tcejdb.dll : $(LIBOBJFILES)
+       $(CC) $(CFLAGS) -shared -Wl,--subsystem,windows -o $@ \
+             $(LIBOBJFILES) $(LDFLAGS) $(LIBS)
 
 tcutest : tcutest.o $(LIBRARYFILES)
        $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -ltcejdb $(LIBS)
@@ -800,39 +803,38 @@ tcamgr : tcamgr.o $(LIBRARYFILES)
 tcawmgr.cgi : tcawmgr.o $(LIBRARYFILES)
        $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -ltcejdb $(LIBS)
 
+myconf.o : basedefs.h myconf.h
 
-myconf.o : myconf.h
-
-tcutil.o : myconf.h tcutil.h md5.h
+tcutil.o : basedefs.h myconf.h tcutil.h md5.h
 
-tchdb.o : myconf.h tcutil.h tchdb.h
+tchdb.o : basedefs.h myconf.h tcutil.h tchdb.h
 
-tcbdb.o : myconf.h tcutil.h tchdb.h tcbdb.h
+tcbdb.o : basedefs.h myconf.h tcutil.h tchdb.h tcbdb.h
 
-tcfdb.o : myconf.h tcutil.h tcfdb.h
+tcfdb.o : basedefs.h myconf.h tcutil.h tcfdb.h
 
-tctdb.o : myconf.h tcutil.h tchdb.h tctdb.h
+tctdb.o : basedefs.h myconf.h tcutil.h tchdb.h tctdb.h
 
-tcadb.o : myconf.h tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h
+tcadb.o : basedefs.h myconf.h tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h
 
-tcutest.o tcucodec.o : myconf.h tcutil.h
+tcutest.o tcucodec.o : basedefs.h myconf.h tcutil.h
 
-tchtest.o tchmttest.o tchmgr.o : myconf.h tcutil.h tchdb.h
+tchtest.o tchmttest.o tchmgr.o : basedefs.h myconf.h tcutil.h tchdb.h
 
-tcbtest.o tcbmttest.o tcbmgr.o : myconf.h tcutil.h tchdb.h tcbdb.h
+tcbtest.o tcbmttest.o tcbmgr.o : basedefs.h myconf.h tcutil.h tchdb.h tcbdb.h
 
-tcftest.o tcfmttest.o tcfmgr.o : myconf.h tcutil.h tcfdb.h
+tcftest.o tcfmttest.o tcfmgr.o : basedefs.h myconf.h tcutil.h tcfdb.h
 
-tcttest.o tctmttest.o tctmgr.o : myconf.h tcutil.h tchdb.h tcbdb.h tctdb.h
+tcttest.o tctmttest.o tctmgr.o : basedefs.h myconf.h tcutil.h tchdb.h tcbdb.h tctdb.h
 
 tcatest.o tcamttest.o tcamgr.o tcawmgr.o : \
-  myconf.h tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h
+  basedefs.h myconf.h tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h
 
-ejdb.o : myconf.h ejdb.h ejdb_private.h ejdbutl.h
+ejdb.o : basedefs.h myconf.h ejdb.h ejdb_private.h ejdbutl.h
 
-bson.o : myconf.h bson.h
+bson.o : basedefs.h myconf.h bson.h
 
-ejdbutl.o : ejdbutl.h
+ejdbutl.o : basedefs.h tcutil.h ejdbutl.h
 
 utf8proc.o: utf8proc.h utf8proc.c utf8proc_data.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -c -o utf8proc.o utf8proc.c
@@ -842,6 +844,6 @@ tokyocabinet_all.c : myconf.c tcutil.c md5.c tchdb.c tcbdb.c tcfdb.c tctdb.c tca
 
 tokyocabinet_all.o : myconf.h tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h
 
-
+platform.o : basedefs.h platform.c
 
 # END OF FILE
diff --git a/tcejdb/basedefs.h b/tcejdb/basedefs.h
new file mode 100644 (file)
index 0000000..637b90d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * File:   basic.h
+ * Author: adam
+ *
+ * Created on April 1, 2013, 6:21 PM
+ */
+
+#ifndef BASIC_H
+#define        BASIC_H
+
+#ifdef __cplusplus
+#define EJDB_EXTERN_C_START extern "C" {
+#define EJDB_EXTERN_C_END }
+#else
+#define EJDB_EXTERN_C_START
+#define EJDB_EXTERN_C_END
+#endif
+
+EJDB_EXTERN_C_START
+
+#ifdef __GNUC__
+#define EJDB_INLINE static inline
+#else
+#define EJDB_INLINE static
+#endif
+
+#ifdef _WIN32
+#ifdef EJDB_DLL
+#define EJDB_EXPORT __declspec(dllexport)
+#elif !defined(EJDB_STATIC)
+#define EJDB_EXPORT __declspec(dllimport)
+#else
+#define EJDB_EXPORT
+#endif
+#else
+#define EJDB_EXPORT
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#define INVALIDHANDLE(_HNDL) (((_HNDL) == INVALID_HANDLE_VALUE) || (_HNDL) == NULL)
+#else
+typedef int HANDLE;
+#define INVALID_HANDLE_VALUE (-1)
+#define INVALIDHANDLE(_HNDL) ((_HNDL) < 0 || (_HNDL) == UINT16_MAX)
+#endif
+
+
+#define JDBIDKEYNAME "_id"  /**> Name of PK _id field in BSONs */
+#define JDBIDKEYNAMEL 3
+
+EJDB_EXTERN_C_END
+#endif /* BASIC_H */
+
index bac9afa..fd46bcc 100644 (file)
 #include "encoding.h"
 #include "myconf.h"
 
+#ifdef _MYBIGEND
+#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) )
+#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) )
+#define bson_big_endian64(out, in) ( memcpy(out, in, 8) )
+#define bson_big_endian32(out, in) ( memcpy(out, in, 4) )
+#else
+#define bson_little_endian64(out, in) ( memcpy(out, in, 8) )
+#define bson_little_endian32(out, in) ( memcpy(out, in, 4) )
+#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) )
+#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) )
+#endif
+
 const int initialBufferSize = 128;
 
+#ifndef MIN
 #define        MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef MAX
 #define        MAX(a,b) (((a)>(b))?(a):(b))
+#endif
 
 /* only need one of these */
 static const int zero = 0;
@@ -38,13 +54,6 @@ static const int zero = 0;
 void *(*bson_malloc_func)(size_t) = MYMALLOC;
 void *(*bson_realloc_func)(void *, size_t) = MYREALLOC;
 void ( *bson_free_func)(void *) = MYFREE;
-#ifdef R_SAFETY_NET
-bson_printf_func bson_printf;
-#else
-bson_printf_func bson_printf = printf;
-#endif
-bson_fprintf_func bson_fprintf = fprintf;
-bson_sprintf_func bson_sprintf = sprintf;
 
 static int _bson_errprintf(const char *, ...);
 bson_printf_func bson_errprintf = _bson_errprintf;
@@ -54,7 +63,7 @@ static int ( *oid_fuzz_func)(void) = NULL;
 static int ( *oid_inc_func)(void) = NULL;
 
 
-EJDB_EXPORT const char* bson_first_errormsg(bson *bson) {
+ const char* bson_first_errormsg(bson *bson) {
     if (bson->errstr) {
         return bson->errstr;
     }
@@ -71,7 +80,7 @@ EJDB_EXPORT const char* bson_first_errormsg(bson *bson) {
 }
 
 
-EJDB_EXPORT void bson_reset(bson *b) {
+ void bson_reset(bson *b) {
     b->finished = 0;
     b->stackPos = 0;
     b->err = 0;
@@ -85,15 +94,15 @@ static bson_bool_t bson_isnumstr(const char *str, int len);
    READING
    ------------------------------ */
 
-EJDB_EXPORT bson* bson_create(void) {
+ bson* bson_create(void) {
     return (bson*) bson_malloc(sizeof (bson));
 }
 
-EJDB_EXPORT void bson_dispose(bson* b) {
+ void bson_dispose(bson* b) {
     bson_free(b);
 }
 
-EJDB_EXPORT bson *bson_empty(bson *obj) {
+ bson *bson_empty(bson *obj) {
     static char *data = "\005\0\0\0\0";
     bson_init_data(obj, data);
     obj->finished = 1;
@@ -104,7 +113,7 @@ EJDB_EXPORT bson *bson_empty(bson *obj) {
     return obj;
 }
 
-EJDB_EXPORT int bson_copy(bson *out, const bson *in) {
+ int bson_copy(bson *out, const bson *in) {
     if (!out || !in) return BSON_ERROR;
     if (!in->finished) return BSON_ERROR;
     bson_init_size(out, bson_size(in));
@@ -118,14 +127,14 @@ int bson_init_data(bson *b, char *data) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_init_finished_data(bson *b, const char *data) {
+ int bson_init_finished_data(bson *b, const char *data) {
     bson_init_data(b, (char*) data);
     bson_reset(b);
     b->finished = 1;
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_size(const bson *b) {
+ int bson_size(const bson *b) {
     int i;
     if (!b || !b->data)
         return 0;
@@ -133,7 +142,7 @@ EJDB_EXPORT int bson_size(const bson *b) {
     return i;
 }
 
-EJDB_EXPORT int bson_size2(const void *bsdata) {
+ int bson_size2(const void *bsdata) {
     int i;
     if (!bsdata)
         return 0;
@@ -141,11 +150,11 @@ EJDB_EXPORT int bson_size2(const void *bsdata) {
     return i;
 }
 
-EJDB_EXPORT int bson_buffer_size(const bson *b) {
+ int bson_buffer_size(const bson *b) {
     return (b->cur - b->data + 1);
 }
 
-EJDB_EXPORT const char *bson_data(const bson *b) {
+ const char *bson_data(const bson *b) {
     return (const char *) b->data;
 }
 
@@ -160,14 +169,14 @@ EJDB_INLINE char hexbyte(char hex) {
         return 0x0;
 }
 
-EJDB_EXPORT void bson_oid_from_string(bson_oid_t *oid, const char *str) {
+ void bson_oid_from_string(bson_oid_t *oid, const char *str) {
     int i;
     for (i = 0; i < 12; i++) {
         oid->bytes[i] = (hexbyte(str[2 * i]) << 4) | hexbyte(str[2 * i + 1]);
     }
 }
 
-EJDB_EXPORT void bson_oid_to_string(const bson_oid_t *oid, char *str) {
+ void bson_oid_to_string(const bson_oid_t *oid, char *str) {
     static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
     int i;
     for (i = 0; i < 12; i++) {
@@ -177,15 +186,15 @@ EJDB_EXPORT void bson_oid_to_string(const bson_oid_t *oid, char *str) {
     str[24] = '\0';
 }
 
-EJDB_EXPORT void bson_set_oid_fuzz(int ( *func)(void)) {
+ void bson_set_oid_fuzz(int ( *func)(void)) {
     oid_fuzz_func = func;
 }
 
-EJDB_EXPORT void bson_set_oid_inc(int ( *func)(void)) {
+ void bson_set_oid_inc(int ( *func)(void)) {
     oid_inc_func = func;
 }
 
-EJDB_EXPORT void bson_oid_gen(bson_oid_t *oid) {
+ void bson_oid_gen(bson_oid_t *oid) {
     static int incr = 0;
     static int fuzz = 0;
     int i;
@@ -210,18 +219,18 @@ EJDB_EXPORT void bson_oid_gen(bson_oid_t *oid) {
     bson_big_endian32(&oid->ints[2], &i);
 }
 
-EJDB_EXPORT time_t bson_oid_generated_time(bson_oid_t *oid) {
+ time_t bson_oid_generated_time(bson_oid_t *oid) {
     time_t out;
     bson_big_endian32(&out, &oid->ints[0]);
 
     return out;
 }
 
-EJDB_EXPORT void bson_print(FILE *f, const bson *b) {
+ void bson_print(FILE *f, const bson *b) {
     bson_print_raw(f, b->data, 0);
 }
 
-EJDB_EXPORT void bson_print_raw(FILE *f, const char *data, int depth) {
+ void bson_print_raw(FILE *f, const char *data, int depth) {
     bson_iterator i;
     const char *key;
     int temp;
@@ -237,70 +246,70 @@ EJDB_EXPORT void bson_print_raw(FILE *f, const char *data, int depth) {
         key = bson_iterator_key(&i);
 
         for (temp = 0; temp <= depth; temp++)
-            bson_fprintf(f, "\t");
-        bson_fprintf(f, "%s : %d \t ", key, t);
+            fprintf(f, "\t");
+        fprintf(f, "%s : %d \t ", key, t);
         switch (t) {
             case BSON_DOUBLE:
-                bson_fprintf(f, "%f", bson_iterator_double(&i));
+                fprintf(f, "%f", bson_iterator_double(&i));
                 break;
             case BSON_STRING:
-                bson_fprintf(f, "%s", bson_iterator_string(&i));
+                fprintf(f, "%s", bson_iterator_string(&i));
                 break;
             case BSON_SYMBOL:
-                bson_fprintf(f, "SYMBOL: %s", bson_iterator_string(&i));
+                fprintf(f, "SYMBOL: %s", bson_iterator_string(&i));
                 break;
             case BSON_OID:
                 bson_oid_to_string(bson_iterator_oid(&i), oidhex);
-                bson_fprintf(f, "%s", oidhex);
+                fprintf(f, "%s", oidhex);
                 break;
             case BSON_BOOL:
-                bson_fprintf(f, "%s", bson_iterator_bool(&i) ? "true" : "false");
+                fprintf(f, "%s", bson_iterator_bool(&i) ? "true" : "false");
                 break;
             case BSON_DATE:
-                bson_fprintf(f, "%ld", (long int) bson_iterator_date(&i));
+                fprintf(f, "%ld", (long int) bson_iterator_date(&i));
                 break;
             case BSON_BINDATA:
-                bson_fprintf(f, "BSON_BINDATA");
+                fprintf(f, "BSON_BINDATA");
                 break;
             case BSON_UNDEFINED:
-                bson_fprintf(f, "BSON_UNDEFINED");
+                fprintf(f, "BSON_UNDEFINED");
                 break;
             case BSON_NULL:
-                bson_fprintf(f, "BSON_NULL");
+                fprintf(f, "BSON_NULL");
                 break;
             case BSON_REGEX:
-                bson_fprintf(f, "BSON_REGEX: %s", bson_iterator_regex(&i));
+                fprintf(f, "BSON_REGEX: %s", bson_iterator_regex(&i));
                 break;
             case BSON_CODE:
-                bson_fprintf(f, "BSON_CODE: %s", bson_iterator_code(&i));
+                fprintf(f, "BSON_CODE: %s", bson_iterator_code(&i));
                 break;
             case BSON_CODEWSCOPE:
-                bson_fprintf(f, "BSON_CODE_W_SCOPE: %s", bson_iterator_code(&i));
+                fprintf(f, "BSON_CODE_W_SCOPE: %s", bson_iterator_code(&i));
                 /* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
                 bson_iterator_code_scope(&i, &scope);
-                bson_fprintf(f, "\n\t SCOPE: ");
+                fprintf(f, "\n\t SCOPE: ");
                 bson_print(f, &scope);
                 /* bson_destroy( &scope ); */ /* review - causes free error */
                 break;
             case BSON_INT:
-                bson_fprintf(f, "%d", bson_iterator_int(&i));
+                fprintf(f, "%d", bson_iterator_int(&i));
                 break;
             case BSON_LONG:
-                bson_fprintf(f, "%lld", (uint64_t) bson_iterator_long(&i));
+                fprintf(f, "%" PRIdMAX "", (uint64_t) bson_iterator_long(&i));
                 break;
             case BSON_TIMESTAMP:
                 ts = bson_iterator_timestamp(&i);
-                bson_fprintf(f, "i: %d, t: %d", ts.i, ts.t);
+                fprintf(f, "i: %d, t: %d", ts.i, ts.t);
                 break;
             case BSON_OBJECT:
             case BSON_ARRAY:
-                bson_fprintf(f, "\n");
+                fprintf(f, "\n");
                 bson_print_raw(f, bson_iterator_value(&i), depth + 1);
                 break;
             default:
                 bson_errprintf("can't print type : %d\n", t);
         }
-        bson_fprintf(f, "\n");
+        fprintf(f, "\n");
     }
 }
 
@@ -308,25 +317,25 @@ EJDB_EXPORT void bson_print_raw(FILE *f, const char *data, int depth) {
    ITERATOR
    ------------------------------ */
 
-EJDB_EXPORT bson_iterator* bson_iterator_create(void) {
+ bson_iterator* bson_iterator_create(void) {
     return (bson_iterator*) malloc(sizeof ( bson_iterator));
 }
 
-EJDB_EXPORT void bson_iterator_dispose(bson_iterator* i) {
+ void bson_iterator_dispose(bson_iterator* i) {
     free(i);
 }
 
-EJDB_EXPORT void bson_iterator_init(bson_iterator *i, const bson *b) {
+ void bson_iterator_init(bson_iterator *i, const bson *b) {
     i->cur = b->data + 4;
     i->first = 1;
 }
 
-EJDB_EXPORT void bson_iterator_from_buffer(bson_iterator *i, const char *buffer) {
+ void bson_iterator_from_buffer(bson_iterator *i, const char *buffer) {
     i->cur = buffer + 4;
     i->first = 1;
 }
 
-EJDB_EXPORT bson_type bson_find(bson_iterator *it, const bson *obj, const char *name) {
+ bson_type bson_find(bson_iterator *it, const bson *obj, const char *name) {
     bson_iterator_init(it, (bson *) obj);
     while (bson_iterator_next(it)) {
         if (strcmp(name, bson_iterator_key(it)) == 0)
@@ -335,7 +344,7 @@ EJDB_EXPORT bson_type bson_find(bson_iterator *it, const bson *obj, const char *
     return bson_iterator_type(it);
 }
 
-EJDB_EXPORT bson_type bson_find_from_buffer(bson_iterator *it, const char *buffer, const char *name) {
+ bson_type bson_find_from_buffer(bson_iterator *it, const char *buffer, const char *name) {
     bson_iterator_from_buffer(it, buffer);
     while (bson_iterator_next(it)) {
         if (strcmp(name, bson_iterator_key(it)) == 0)
@@ -385,7 +394,7 @@ static void bson_visit_fields_impl(bson_traverse_flags_t flags, char* pstack, in
     }
 }
 
-EJDB_EXPORT void bson_visit_fields(bson_iterator *it, bson_traverse_flags_t flags, BSONVISITOR visitor, void *op) {
+ void bson_visit_fields(bson_iterator *it, bson_traverse_flags_t flags, BSONVISITOR visitor, void *op) {
     char pstack[BSON_MAX_FPATH_LEN + 1];
     bson_visit_fields_impl(flags, pstack, 0, it, visitor, op);
 }
@@ -442,11 +451,11 @@ static bson_type bson_find_fieldpath_value_impl(char* pstack, int curr, FFPCTX *
     return BSON_EOO;
 }
 
-EJDB_EXPORT bson_type bson_find_fieldpath_value(const char *fpath, bson_iterator *it) {
+ bson_type bson_find_fieldpath_value(const char *fpath, bson_iterator *it) {
     return bson_find_fieldpath_value2(fpath, strlen(fpath), it);
 }
 
-EJDB_EXPORT bson_type bson_find_fieldpath_value2(const char *fpath, int fplen, bson_iterator *it) {
+ bson_type bson_find_fieldpath_value2(const char *fpath, int fplen, bson_iterator *it) {
     FFPCTX ffctx = {
         .fpath = fpath,
         .fplen = fplen,
@@ -457,7 +466,7 @@ EJDB_EXPORT bson_type bson_find_fieldpath_value2(const char *fpath, int fplen, b
     return bson_find_fieldpath_value3(&ffctx);
 }
 
-EJDB_EXPORT bson_type bson_find_fieldpath_value3(FFPCTX* ffctx) {
+ bson_type bson_find_fieldpath_value3(FFPCTX* ffctx) {
     char pstackstack[BSON_MAX_FPATH_LEN + 1];
     char *pstack;
     if (ffctx->fplen <= BSON_MAX_FPATH_LEN) {
@@ -475,11 +484,11 @@ EJDB_EXPORT bson_type bson_find_fieldpath_value3(FFPCTX* ffctx) {
     return bt;
 }
 
-EJDB_EXPORT bson_bool_t bson_iterator_more(const bson_iterator *i) {
+ bson_bool_t bson_iterator_more(const bson_iterator *i) {
     return *(i->cur);
 }
 
-EJDB_EXPORT bson_type bson_iterator_next(bson_iterator *i) {
+ bson_type bson_iterator_next(bson_iterator *i) {
     int ds;
 
     if (i->first) {
@@ -549,15 +558,15 @@ EJDB_EXPORT bson_type bson_iterator_next(bson_iterator *i) {
     return (bson_type) (*i->cur);
 }
 
-EJDB_EXPORT bson_type bson_iterator_type(const bson_iterator *i) {
+ bson_type bson_iterator_type(const bson_iterator *i) {
     return (bson_type) i->cur[0];
 }
 
-EJDB_EXPORT const char *bson_iterator_key(const bson_iterator *i) {
+ const char *bson_iterator_key(const bson_iterator *i) {
     return i->cur + 1;
 }
 
-EJDB_EXPORT const char *bson_iterator_value(const bson_iterator *i) {
+ const char *bson_iterator_value(const bson_iterator *i) {
     const char *t = i->cur + 1;
     t += strlen(t) + 1;
     return t;
@@ -565,33 +574,33 @@ EJDB_EXPORT const char *bson_iterator_value(const bson_iterator *i) {
 
 /* types */
 
-EJDB_EXPORT int bson_iterator_int_raw(const bson_iterator *i) {
+ int bson_iterator_int_raw(const bson_iterator *i) {
     int out;
     bson_little_endian32(&out, bson_iterator_value(i));
     return out;
 }
 
-EJDB_EXPORT double bson_iterator_double_raw(const bson_iterator *i) {
+ double bson_iterator_double_raw(const bson_iterator *i) {
     double out;
     bson_little_endian64(&out, bson_iterator_value(i));
     return out;
 }
 
-EJDB_EXPORT int64_t bson_iterator_long_raw(const bson_iterator *i) {
+ int64_t bson_iterator_long_raw(const bson_iterator *i) {
     int64_t out;
     bson_little_endian64(&out, bson_iterator_value(i));
     return out;
 }
 
-EJDB_EXPORT bson_bool_t bson_iterator_bool_raw(const bson_iterator *i) {
+ bson_bool_t bson_iterator_bool_raw(const bson_iterator *i) {
     return bson_iterator_value(i)[0];
 }
 
-EJDB_EXPORT bson_oid_t *bson_iterator_oid(const bson_iterator *i) {
+ bson_oid_t *bson_iterator_oid(const bson_iterator *i) {
     return (bson_oid_t *) bson_iterator_value(i);
 }
 
-EJDB_EXPORT int bson_iterator_int(const bson_iterator *i) {
+ int bson_iterator_int(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_INT:
             return bson_iterator_int_raw(i);
@@ -606,7 +615,7 @@ EJDB_EXPORT int bson_iterator_int(const bson_iterator *i) {
     }
 }
 
-EJDB_EXPORT double bson_iterator_double(const bson_iterator *i) {
+ double bson_iterator_double(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_INT:
             return bson_iterator_int_raw(i);
@@ -622,7 +631,7 @@ EJDB_EXPORT double bson_iterator_double(const bson_iterator *i) {
     }
 }
 
-EJDB_EXPORT int64_t bson_iterator_long(const bson_iterator *i) {
+ int64_t bson_iterator_long(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_INT:
             return bson_iterator_int_raw(i);
@@ -655,26 +664,26 @@ static int64_t bson_iterator_long_ext(const bson_iterator *i) {
     }
 }
 
-EJDB_EXPORT bson_timestamp_t bson_iterator_timestamp(const bson_iterator *i) {
+ bson_timestamp_t bson_iterator_timestamp(const bson_iterator *i) {
     bson_timestamp_t ts;
     bson_little_endian32(&(ts.i), bson_iterator_value(i));
     bson_little_endian32(&(ts.t), bson_iterator_value(i) + 4);
     return ts;
 }
 
-EJDB_EXPORT int bson_iterator_timestamp_time(const bson_iterator *i) {
+ int bson_iterator_timestamp_time(const bson_iterator *i) {
     int time;
     bson_little_endian32(&time, bson_iterator_value(i) + 4);
     return time;
 }
 
-EJDB_EXPORT int bson_iterator_timestamp_increment(const bson_iterator *i) {
+ int bson_iterator_timestamp_increment(const bson_iterator *i) {
     int increment;
     bson_little_endian32(&increment, bson_iterator_value(i));
     return increment;
 }
 
-EJDB_EXPORT bson_bool_t bson_iterator_bool(const bson_iterator *i) {
+ bson_bool_t bson_iterator_bool(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_BOOL:
             return bson_iterator_bool_raw(i);
@@ -694,7 +703,7 @@ EJDB_EXPORT bson_bool_t bson_iterator_bool(const bson_iterator *i) {
     }
 }
 
-EJDB_EXPORT const char *bson_iterator_string(const bson_iterator *i) {
+ const char *bson_iterator_string(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_STRING:
         case BSON_SYMBOL:
@@ -708,7 +717,7 @@ int bson_iterator_string_len(const bson_iterator *i) {
     return bson_iterator_int_raw(i);
 }
 
-EJDB_EXPORT const char *bson_iterator_code(const bson_iterator *i) {
+ const char *bson_iterator_code(const bson_iterator *i) {
     switch (bson_iterator_type(i)) {
         case BSON_STRING:
         case BSON_CODE:
@@ -720,7 +729,7 @@ EJDB_EXPORT const char *bson_iterator_code(const bson_iterator *i) {
     }
 }
 
-EJDB_EXPORT void bson_iterator_code_scope(const bson_iterator *i, bson *scope) {
+ void bson_iterator_code_scope(const bson_iterator *i, bson *scope) {
     if (bson_iterator_type(i) == BSON_CODEWSCOPE) {
         int code_len;
         bson_little_endian32(&code_len, bson_iterator_value(i) + 4);
@@ -732,47 +741,47 @@ EJDB_EXPORT void bson_iterator_code_scope(const bson_iterator *i, bson *scope) {
     }
 }
 
-EJDB_EXPORT bson_date_t bson_iterator_date(const bson_iterator *i) {
+ bson_date_t bson_iterator_date(const bson_iterator *i) {
     return bson_iterator_long_raw(i);
 }
 
-EJDB_EXPORT time_t bson_iterator_time_t(const bson_iterator *i) {
+ time_t bson_iterator_time_t(const bson_iterator *i) {
     return bson_iterator_date(i) / 1000;
 }
 
-EJDB_EXPORT int bson_iterator_bin_len(const bson_iterator *i) {
+ int bson_iterator_bin_len(const bson_iterator *i) {
     return ( bson_iterator_bin_type(i) == BSON_BIN_BINARY_OLD)
             ? bson_iterator_int_raw(i) - 4
             : bson_iterator_int_raw(i);
 }
 
-EJDB_EXPORT char bson_iterator_bin_type(const bson_iterator *i) {
+ char bson_iterator_bin_type(const bson_iterator *i) {
     return bson_iterator_value(i)[4];
 }
 
-EJDB_EXPORT const char *bson_iterator_bin_data(const bson_iterator *i) {
+ const char *bson_iterator_bin_data(const bson_iterator *i) {
     return ( bson_iterator_bin_type(i) == BSON_BIN_BINARY_OLD)
             ? bson_iterator_value(i) + 9
             : bson_iterator_value(i) + 5;
 }
 
-EJDB_EXPORT const char *bson_iterator_regex(const bson_iterator *i) {
+ const char *bson_iterator_regex(const bson_iterator *i) {
     return bson_iterator_value(i);
 }
 
-EJDB_EXPORT const char *bson_iterator_regex_opts(const bson_iterator *i) {
+ const char *bson_iterator_regex_opts(const bson_iterator *i) {
     const char *p = bson_iterator_value(i);
     return p + strlen(p) + 1;
 
 }
 
-EJDB_EXPORT void bson_iterator_subobject(const bson_iterator *i, bson *sub) {
+ void bson_iterator_subobject(const bson_iterator *i, bson *sub) {
     bson_init_data(sub, (char *) bson_iterator_value(i));
     bson_reset(sub);
     sub->finished = 1;
 }
 
-EJDB_EXPORT void bson_iterator_subiterator(const bson_iterator *i, bson_iterator *sub) {
+ void bson_iterator_subiterator(const bson_iterator *i, bson_iterator *sub) {
     bson_iterator_from_buffer(sub, bson_iterator_value(i));
 }
 
@@ -791,11 +800,11 @@ static void _bson_init_size(bson *b, int size) {
     bson_reset(b);
 }
 
-EJDB_EXPORT void bson_init(bson *b) {
+ void bson_init(bson *b) {
     _bson_init_size(b, initialBufferSize);
 }
 
-EJDB_EXPORT void bson_init_as_query(bson *b) {
+ void bson_init_as_query(bson *b) {
     bson_init(b);
     b->flags |= BSON_FLAG_QUERY_MODE;
 }
@@ -819,7 +828,7 @@ void bson_append_byte(bson *b, char c) {
     b->cur++;
 }
 
-EJDB_EXPORT void bson_append(bson *b, const void *data, int len) {
+ void bson_append(bson *b, const void *data, int len) {
     memcpy(b->cur, data, len);
     b->cur += len;
 }
@@ -878,7 +887,7 @@ int bson_ensure_space(bson *b, const int bytesNeeded) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_finish(bson *b) {
+ int bson_finish(bson *b) {
     int i;
 
     if (b->err & BSON_NOT_UTF8)
@@ -895,7 +904,7 @@ EJDB_EXPORT int bson_finish(bson *b) {
     return BSON_OK;
 }
 
-EJDB_EXPORT void bson_destroy(bson *b) {
+ void bson_destroy(bson *b) {
     if (b) {
         if (b->data && !(b->flags & BSON_FLAG_STACK_ALLOCATED)) {
             bson_free(b->data);
@@ -911,7 +920,7 @@ EJDB_EXPORT void bson_destroy(bson *b) {
     }
 }
 
-EJDB_EXPORT void bson_del(bson *b) {
+ void bson_del(bson *b) {
     if (b) {
         bson_destroy(b);
         bson_free(b);
@@ -953,41 +962,41 @@ static int bson_append_estart2(bson *b, int type, const char *name, int namelen,
    BUILDING TYPES
    ------------------------------ */
 
-EJDB_EXPORT int bson_append_int(bson *b, const char *name, const int i) {
+ int bson_append_int(bson *b, const char *name, const int i) {
     if (bson_append_estart(b, BSON_INT, name, 4) == BSON_ERROR)
         return BSON_ERROR;
     bson_append32(b, &i);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_long(bson *b, const char *name, const int64_t i) {
+ int bson_append_long(bson *b, const char *name, const int64_t i) {
     if (bson_append_estart(b, BSON_LONG, name, 8) == BSON_ERROR)
         return BSON_ERROR;
     bson_append64(b, &i);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_double(bson *b, const char *name, const double d) {
+ int bson_append_double(bson *b, const char *name, const double d) {
     if (bson_append_estart(b, BSON_DOUBLE, name, 8) == BSON_ERROR)
         return BSON_ERROR;
     bson_append64(b, &d);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_bool(bson *b, const char *name, const bson_bool_t i) {
+ int bson_append_bool(bson *b, const char *name, const bson_bool_t i) {
     if (bson_append_estart(b, BSON_BOOL, name, 1) == BSON_ERROR)
         return BSON_ERROR;
     bson_append_byte(b, i != 0);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_null(bson *b, const char *name) {
+ int bson_append_null(bson *b, const char *name) {
     if (bson_append_estart(b, BSON_NULL, name, 0) == BSON_ERROR)
         return BSON_ERROR;
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_undefined(bson *b, const char *name) {
+ int bson_append_undefined(bson *b, const char *name) {
     if (bson_append_estart(b, BSON_UNDEFINED, name, 0) == BSON_ERROR)
         return BSON_ERROR;
     return BSON_OK;
@@ -1008,31 +1017,31 @@ int bson_append_string_base(bson *b, const char *name,
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_string(bson *b, const char *name, const char *value) {
+ int bson_append_string(bson *b, const char *name, const char *value) {
     return bson_append_string_base(b, name, value, strlen(value), BSON_STRING);
 }
 
-EJDB_EXPORT int bson_append_symbol(bson *b, const char *name, const char *value) {
+ int bson_append_symbol(bson *b, const char *name, const char *value) {
     return bson_append_string_base(b, name, value, strlen(value), BSON_SYMBOL);
 }
 
-EJDB_EXPORT int bson_append_code(bson *b, const char *name, const char *value) {
+ int bson_append_code(bson *b, const char *name, const char *value) {
     return bson_append_string_base(b, name, value, strlen(value), BSON_CODE);
 }
 
-EJDB_EXPORT int bson_append_string_n(bson *b, const char *name, const char *value, int len) {
+ int bson_append_string_n(bson *b, const char *name, const char *value, int len) {
     return bson_append_string_base(b, name, value, len, BSON_STRING);
 }
 
-EJDB_EXPORT int bson_append_symbol_n(bson *b, const char *name, const char *value, int len) {
+ int bson_append_symbol_n(bson *b, const char *name, const char *value, int len) {
     return bson_append_string_base(b, name, value, len, BSON_SYMBOL);
 }
 
-EJDB_EXPORT int bson_append_code_n(bson *b, const char *name, const char *value, int len) {
+ int bson_append_code_n(bson *b, const char *name, const char *value, int len) {
     return bson_append_string_base(b, name, value, len, BSON_CODE);
 }
 
-EJDB_EXPORT int bson_append_code_w_scope_n(bson *b, const char *name,
+ int bson_append_code_w_scope_n(bson *b, const char *name,
         const char *code, int len, const bson *scope) {
 
     int sl, size;
@@ -1048,11 +1057,11 @@ EJDB_EXPORT int bson_append_code_w_scope_n(bson *b, const char *name,
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_code_w_scope(bson *b, const char *name, const char *code, const bson *scope) {
+ int bson_append_code_w_scope(bson *b, const char *name, const char *code, const bson *scope) {
     return bson_append_code_w_scope_n(b, name, code, strlen(code), scope);
 }
 
-EJDB_EXPORT int bson_append_binary(bson *b, const char *name, char type, const char *str, int len) {
+ int bson_append_binary(bson *b, const char *name, char type, const char *str, int len) {
     if (type == BSON_BIN_BINARY_OLD) {
         int subtwolen = len + 4;
         if (bson_append_estart(b, BSON_BINDATA, name, 4 + 1 + 4 + len) == BSON_ERROR)
@@ -1071,20 +1080,20 @@ EJDB_EXPORT int bson_append_binary(bson *b, const char *name, char type, const c
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_oid(bson *b, const char *name, const bson_oid_t *oid) {
+ int bson_append_oid(bson *b, const char *name, const bson_oid_t *oid) {
     if (bson_append_estart(b, BSON_OID, name, 12) == BSON_ERROR)
         return BSON_ERROR;
     bson_append(b, oid, 12);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_new_oid(bson *b, const char *name) {
+ int bson_append_new_oid(bson *b, const char *name) {
     bson_oid_t oid;
     bson_oid_gen(&oid);
     return bson_append_oid(b, name, &oid);
 }
 
-EJDB_EXPORT int bson_append_regex(bson *b, const char *name, const char *pattern, const char *opts) {
+ int bson_append_regex(bson *b, const char *name, const char *pattern, const char *opts) {
     const int plen = strlen(pattern) + 1;
     const int olen = strlen(opts) + 1;
     if (bson_append_estart(b, BSON_REGEX, name, plen + olen) == BSON_ERROR)
@@ -1096,7 +1105,7 @@ EJDB_EXPORT int bson_append_regex(bson *b, const char *name, const char *pattern
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_bson(bson *b, const char *name, const bson *bson) {
+ int bson_append_bson(bson *b, const char *name, const bson *bson) {
     if (!bson) return BSON_ERROR;
     if (bson_append_estart(b, BSON_OBJECT, name, bson_size(bson)) == BSON_ERROR)
         return BSON_ERROR;
@@ -1104,7 +1113,7 @@ EJDB_EXPORT int bson_append_bson(bson *b, const char *name, const bson *bson) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_element(bson *b, const char *name_or_null, const bson_iterator *elem) {
+ int bson_append_element(bson *b, const char *name_or_null, const bson_iterator *elem) {
     bson_iterator next = *elem;
     int size;
 
@@ -1124,7 +1133,7 @@ EJDB_EXPORT int bson_append_element(bson *b, const char *name_or_null, const bso
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_timestamp(bson *b, const char *name, bson_timestamp_t *ts) {
+ int bson_append_timestamp(bson *b, const char *name, bson_timestamp_t *ts) {
     if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
 
     bson_append32(b, &(ts->i));
@@ -1133,7 +1142,7 @@ EJDB_EXPORT int bson_append_timestamp(bson *b, const char *name, bson_timestamp_
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_timestamp2(bson *b, const char *name, int time, int increment) {
+ int bson_append_timestamp2(bson *b, const char *name, int time, int increment) {
     if (bson_append_estart(b, BSON_TIMESTAMP, name, 8) == BSON_ERROR) return BSON_ERROR;
 
     bson_append32(b, &increment);
@@ -1141,42 +1150,42 @@ EJDB_EXPORT int bson_append_timestamp2(bson *b, const char *name, int time, int
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_date(bson *b, const char *name, bson_date_t millis) {
+ int bson_append_date(bson *b, const char *name, bson_date_t millis) {
     if (bson_append_estart(b, BSON_DATE, name, 8) == BSON_ERROR) return BSON_ERROR;
     bson_append64(b, &millis);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_time_t(bson *b, const char *name, time_t secs) {
+ int bson_append_time_t(bson *b, const char *name, time_t secs) {
     return bson_append_date(b, name, (bson_date_t) secs * 1000);
 }
 
-EJDB_EXPORT int bson_append_start_object(bson *b, const char *name) {
+ int bson_append_start_object(bson *b, const char *name) {
     if (bson_append_estart(b, BSON_OBJECT, name, 5) == BSON_ERROR) return BSON_ERROR;
     b->stack[ b->stackPos++ ] = b->cur - b->data;
     bson_append32(b, &zero);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_start_object2(bson *b, const char *name, int namelen) {
+ int bson_append_start_object2(bson *b, const char *name, int namelen) {
     if (bson_append_estart2(b, BSON_OBJECT, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
     b->stack[ b->stackPos++ ] = b->cur - b->data;
     bson_append32(b, &zero);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_start_array(bson *b, const char *name) {
+ int bson_append_start_array(bson *b, const char *name) {
     return bson_append_start_array2(b, name, strlen(name));
 }
 
-EJDB_EXPORT int bson_append_start_array2(bson *b, const char *name, int namelen) {
+ int bson_append_start_array2(bson *b, const char *name, int namelen) {
     if (bson_append_estart2(b, BSON_ARRAY, name, namelen, 5) == BSON_ERROR) return BSON_ERROR;
     b->stack[ b->stackPos++ ] = b->cur - b->data;
     bson_append32(b, &zero);
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_finish_object(bson *b) {
+ int bson_append_finish_object(bson *b) {
     char *start;
     int i;
     if (bson_ensure_space(b, 1) == BSON_ERROR) return BSON_ERROR;
@@ -1189,11 +1198,11 @@ EJDB_EXPORT int bson_append_finish_object(bson *b) {
     return BSON_OK;
 }
 
-EJDB_EXPORT double bson_int64_to_double(int64_t i64) {
+ double bson_int64_to_double(int64_t i64) {
     return (double) i64;
 }
 
-EJDB_EXPORT int bson_append_finish_array(bson *b) {
+ int bson_append_finish_array(bson *b) {
     return bson_append_finish_object(b);
 }
 
@@ -1201,17 +1210,17 @@ EJDB_EXPORT int bson_append_finish_array(bson *b) {
 
 static bson_err_handler err_handler = NULL;
 
-EJDB_EXPORT bson_err_handler set_bson_err_handler(bson_err_handler func) {
+ bson_err_handler set_bson_err_handler(bson_err_handler func) {
     bson_err_handler old = err_handler;
     err_handler = func;
     return old;
 }
 
-EJDB_EXPORT void bson_free(void *ptr) {
+ void bson_free(void *ptr) {
     bson_free_func(ptr);
 }
 
-EJDB_EXPORT void *bson_malloc(int size) {
+ void *bson_malloc(int size) {
     void *p;
     p = bson_malloc_func(size);
     bson_fatal_msg(!!p, "malloc() failed");
@@ -1229,11 +1238,8 @@ int _bson_errprintf(const char *format, ...) {
     va_list ap;
     int ret;
     va_start(ap, format);
-#ifndef R_SAFETY_NET
     ret = vfprintf(stderr, format, ap);
-#endif
     va_end(ap);
-
     return ret;
 }
 
@@ -1259,31 +1265,31 @@ void bson_fatal_msg(int ok, const char *msg) {
     if (err_handler) {
         err_handler(msg);
     }
-#ifndef R_SAFETY_NET
     bson_errprintf("error: %s\n", msg);
-    exit(-5);
-#endif
 }
 
 
 /* Efficiently copy an integer to a string. */
 extern const char bson_numstrs[1000][4];
 
-EJDB_EXPORT void bson_numstr(char *str, int64_t i) {
+ void bson_numstr(char *str, int64_t i) {
     if (i >= 0 && i < 1000)
         memcpy(str, bson_numstrs[i], 4);
     else
-        bson_sprintf(str, "%lld", (long long int) i);
+        sprintf(str, "%" PRIdMAX "", (long long int) i);
 }
 
-EJDB_EXPORT int bson_numstrn(char *str, int maxbuf, int64_t i) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+ int bson_numstrn(char *str, int maxbuf, int64_t i)  {
     if (i >= 0 && i < 1000 && maxbuf > 4) {
         memcpy(str, bson_numstrs[i], 4);
         return strlen(bson_numstrs[i]);
     } else {
-        return snprintf(str, maxbuf, "%lld", (long long int) i);
+        return snprintf(str, maxbuf, "%" PRIdMAX "", (long long int) i);
     }
 }
+ #pragma GCC diagnostic pop
 
 static bson_bool_t bson_isnumstr(const char *str, int len) {
     assert(str);
@@ -1304,7 +1310,7 @@ static bson_bool_t bson_isnumstr(const char *str, int len) {
     return (isnum && (*str == '\0' || len == 0));
 }
 
-EJDB_EXPORT void bson_swap_endian64(void *outp, const void *inp) {
+ void bson_swap_endian64(void *outp, const void *inp) {
     const char *in = (const char *) inp;
     char *out = (char *) outp;
     out[0] = in[7];
@@ -1318,7 +1324,7 @@ EJDB_EXPORT void bson_swap_endian64(void *outp, const void *inp) {
 
 }
 
-EJDB_EXPORT void bson_swap_endian32(void *outp, const void *inp) {
+ void bson_swap_endian32(void *outp, const void *inp) {
     const char *in = (const char *) inp;
     char *out = (char *) outp;
     out[0] = in[3];
@@ -1327,7 +1333,7 @@ EJDB_EXPORT void bson_swap_endian32(void *outp, const void *inp) {
     out[3] = in[0];
 }
 
-EJDB_EXPORT int bson_append_array_from_iterator(const char *key, bson_iterator *from, bson *into) {
+ int bson_append_array_from_iterator(const char *key, bson_iterator *from, bson *into) {
     assert(key && from && into);
     bson_type bt;
     bson_append_start_array(into, key);
@@ -1338,7 +1344,7 @@ EJDB_EXPORT int bson_append_array_from_iterator(const char *key, bson_iterator *
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_object_from_iterator(const char *key, bson_iterator *from, bson *into) {
+ int bson_append_object_from_iterator(const char *key, bson_iterator *from, bson *into) {
     assert(key && from && into);
     bson_type bt;
     bson_append_start_object(into, key);
@@ -1349,7 +1355,7 @@ EJDB_EXPORT int bson_append_object_from_iterator(const char *key, bson_iterator
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_field_from_iterator2(const char *key, const bson_iterator *from, bson *into) {
+ int bson_append_field_from_iterator2(const char *key, const bson_iterator *from, bson *into) {
     assert(key && from && into);
     bson_type t = bson_iterator_type(from);
     if (t == BSON_EOO || into->finished) {
@@ -1427,12 +1433,12 @@ EJDB_EXPORT int bson_append_field_from_iterator2(const char *key, const bson_ite
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_append_field_from_iterator(const bson_iterator *from, bson *into) {
+ int bson_append_field_from_iterator(const bson_iterator *from, bson *into) {
     assert(from && into);
     return bson_append_field_from_iterator2(bson_iterator_key(from), from, into);
 }
 
-EJDB_EXPORT int bson_merge2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
+ int bson_merge2(const void *b1data, const void *b2data, bson_bool_t overwrite, bson *out) {
     bson_iterator it1, it2;
     bson_type bt1, bt2;
 
@@ -1459,7 +1465,7 @@ EJDB_EXPORT int bson_merge2(const void *b1data, const void *b2data, bson_bool_t
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
+ int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out) {
     assert(b1 && b2 && out);
     if (!b1->finished || !b2->finished || out->finished) {
         return BSON_ERROR;
@@ -1467,7 +1473,7 @@ EJDB_EXPORT int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite
     return bson_merge2(bson_data(b1), bson_data(b2), overwrite, out);
 }
 
-EJDB_EXPORT int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
+ int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
     assert(pos);
     bson_type bt = bson_iterator_type(pos);
     if (bt != BSON_BOOL) {
@@ -1479,7 +1485,7 @@ EJDB_EXPORT int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_inplace_set_long(bson_iterator *pos, int64_t val) {
+ int bson_inplace_set_long(bson_iterator *pos, int64_t val) {
     assert(pos);
     bson_type bt = bson_iterator_type(pos);
     if (!BSON_IS_NUM_TYPE(bt)) {
@@ -1500,7 +1506,7 @@ EJDB_EXPORT int bson_inplace_set_long(bson_iterator *pos, int64_t val) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_inplace_set_double(bson_iterator *pos, double val) {
+ int bson_inplace_set_double(bson_iterator *pos, double val) {
     assert(pos);
     bson_type bt = bson_iterator_type(pos);
     if (!BSON_IS_NUM_TYPE(bt)) {
@@ -1521,7 +1527,7 @@ EJDB_EXPORT int bson_inplace_set_double(bson_iterator *pos, double val) {
     return BSON_OK;
 }
 
-EJDB_EXPORT int bson_compare_fpaths(const void *bsdata1, const void *bsdata2, const char *fpath1, int fplen1, const char *fpath2, int fplen2) {
+ int bson_compare_fpaths(const void *bsdata1, const void *bsdata2, const char *fpath1, int fplen1, const char *fpath2, int fplen2) {
     assert(bsdata1 && bsdata2 && fpath1 && fpath2);
     bson_iterator it1, it2;
     bson_iterator_from_buffer(&it1, bsdata1);
@@ -1541,7 +1547,7 @@ EJDB_EXPORT int bson_compare_fpaths(const void *bsdata1, const void *bsdata2, co
  * @param i
  * @return
  */
-EJDB_EXPORT int bson_compare_it_current(const bson_iterator *it1, const bson_iterator *it2) {
+ int bson_compare_it_current(const bson_iterator *it1, const bson_iterator *it2) {
     bson_type t1 = bson_iterator_type(it1);
     bson_type t2 = bson_iterator_type(it2);
     if (t1 == BSON_BOOL || t1 == BSON_EOO || t1 == BSON_NULL || t1 == BSON_UNDEFINED) {
@@ -1595,11 +1601,11 @@ EJDB_EXPORT int bson_compare_it_current(const bson_iterator *it1, const bson_ite
     return (t1 - t2);
 }
 
-EJDB_EXPORT int bson_compare(const void *bsdata1, const void *bsdata2, const char* fpath, int fplen) {
+ int bson_compare(const void *bsdata1, const void *bsdata2, const char* fpath, int fplen) {
     return bson_compare_fpaths(bsdata1, bsdata2, fpath, fplen, fpath, fplen);
 }
 
-EJDB_EXPORT int bson_compare_string(const char *cv, const void *bsdata, const char *fpath) {
+ int bson_compare_string(const char *cv, const void *bsdata, const char *fpath) {
     assert(cv && bsdata && fpath);
     bson *bs1 = bson_create();
     bson_init(bs1);
@@ -1610,7 +1616,7 @@ EJDB_EXPORT int bson_compare_string(const char *cv, const void *bsdata, const ch
     return res;
 }
 
-EJDB_EXPORT int bson_compare_long(long cv, const void *bsdata, const char *fpath) {
+ int bson_compare_long(long cv, const void *bsdata, const char *fpath) {
     bson *bs1 = bson_create();
     bson_init(bs1);
     bson_append_long(bs1, "$", cv);
@@ -1620,7 +1626,7 @@ EJDB_EXPORT int bson_compare_long(long cv, const void *bsdata, const char *fpath
     return res;
 }
 
-EJDB_EXPORT int bson_compare_double(double cv, const void *bsdata, const char *fpath) {
+ int bson_compare_double(double cv, const void *bsdata, const char *fpath) {
     bson *bs1 = bson_create();
     bson_init(bs1);
     bson_append_double(bs1, "$", cv);
@@ -1630,7 +1636,7 @@ EJDB_EXPORT int bson_compare_double(double cv, const void *bsdata, const char *f
     return res;
 }
 
-EJDB_EXPORT int bson_compare_bool(bson_bool_t cv, const void *bsdata, const char *fpath) {
+ int bson_compare_bool(bson_bool_t cv, const void *bsdata, const char *fpath) {
     bson *bs1 = bson_create();
     bson_init(bs1);
     bson_append_bool(bs1, "$", cv);
@@ -1640,7 +1646,7 @@ EJDB_EXPORT int bson_compare_bool(bson_bool_t cv, const void *bsdata, const char
     return res;
 }
 
-EJDB_EXPORT bson* bson_dup(const bson *src) {
+ bson* bson_dup(const bson *src) {
     assert(src);
     bson *rv = bson_create();
     int s = bson_size(src);
@@ -1650,11 +1656,11 @@ EJDB_EXPORT bson* bson_dup(const bson *src) {
     return rv;
 }
 
-EJDB_EXPORT bson* bson_create_from_buffer(const void* buf, int bufsz) {
+ bson* bson_create_from_buffer(const void* buf, int bufsz) {
     return bson_create_from_buffer2(bson_create(), buf, bufsz);
 }
 
-EJDB_EXPORT bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz) {
+ bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz) {
     assert(buf);
     assert(bufsz - 4 > 0);
     bson_init_size(rv, bufsz);
@@ -1664,7 +1670,7 @@ EJDB_EXPORT bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz)
     return rv;
 }
 
-EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf, bool expandall) {
+ bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf, bool expandall) {
     assert(mbuf && inbuf);
     bool found = false;
     bson_iterator it, it2;
@@ -1703,7 +1709,7 @@ EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf
     return found;
 }
 
-EJDB_EXPORT bool bson_find_unmerged_array_sets(const void *mbuf, const void *inbuf) {
+ bool bson_find_unmerged_array_sets(const void *mbuf, const void *inbuf) {
     assert(mbuf && inbuf);
     bool allfound = false;
     bson_iterator it, it2;
@@ -1885,7 +1891,7 @@ static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathl
 
 }
 
-EJDB_EXPORT int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bool expandall, bson *bsout) {
+ int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bool expandall, bson *bsout) {
     assert(mbuf && inbuf && bsout);
     if (bsout->finished) {
         return BSON_ERROR;
index b2b7b67..774605d 100644 (file)
 #ifndef BSON_H_
 #define BSON_H_
 
-#include "myconf.h"
-
-#ifdef EJDB_BIG_ENDIAN
-#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) )
-#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) )
-#define bson_big_endian64(out, in) ( memcpy(out, in, 8) )
-#define bson_big_endian32(out, in) ( memcpy(out, in, 4) )
-#else
-#define bson_little_endian64(out, in) ( memcpy(out, in, 8) )
-#define bson_little_endian32(out, in) ( memcpy(out, in, 4) )
-#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) )
-#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) )
-#endif
+#include "basedefs.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
 
 #define BSON_IS_NUM_TYPE(atype) (atype == BSON_INT || atype == BSON_LONG || atype == BSON_DOUBLE)
 
@@ -993,18 +984,12 @@ EJDB_EXPORT int bson_numstrn(char *str, int maxbuf, int64_t i);
 
 /* bson_err_handlers shouldn't return!!! */
 typedef void( *bson_err_handler)(const char *errmsg);
-
 typedef int (*bson_printf_func)(const char *, ...);
-typedef int (*bson_fprintf_func)(FILE *, const char *, ...);
-typedef int (*bson_sprintf_func)(char *, const char *, ...);
 
 extern void *(*bson_malloc_func)(size_t);
 extern void *(*bson_realloc_func)(void *, size_t);
 extern void ( *bson_free_func)(void *);
 
-extern bson_printf_func bson_printf;
-extern bson_fprintf_func bson_fprintf;
-extern bson_sprintf_func bson_sprintf;
 extern bson_printf_func bson_errprintf;
 
 EJDB_EXPORT void bson_free(void *ptr);
diff --git a/tcejdb/config.sub b/tcejdb/config.sub
new file mode 100644 (file)
index 0000000..4b4284f
--- /dev/null
@@ -0,0 +1,1788 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
+
+timestamp='2013-02-12'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# 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.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+#
+# 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.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# 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 1992-2013 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 ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # 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 ;;
+
+    * )
+       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* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    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 | -knuth | -cray | -microblaze*)
+               os=
+               basic_machine=$1
+               ;;
+       -bluegene*)
+               os=-cnk
+               ;;
+       -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
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -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/'`
+               ;;
+       -sco5v6*)
+               # 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*178)
+               os=-lynxos178
+               ;;
+       -lynx*5)
+               os=-lynxos5
+               ;;
+       -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 \
+       | aarch64 | aarch64_be \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc \
+       | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+       | avr | avr32 \
+       | be32 | be64 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | epiphany \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | hexagon \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | le32 | le64 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipsr5900 | mipsr5900el \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | moxie \
+       | mt \
+       | msp430 \
+       | nds32 | nds32le | nds32be \
+       | nios | nios2 | nios2eb | nios2el \
+       | ns16k | ns32k \
+       | open8 \
+       | or1k | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle \
+       | pyramid \
+       | rl78 | rx \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu \
+       | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+       | ubicom32 \
+       | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+       | we32k \
+       | x86 | xc16x | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       c54x)
+               basic_machine=tic54x-unknown
+               ;;
+       c55x)
+               basic_machine=tic55x-unknown
+               ;;
+       c6x)
+               basic_machine=tic6x-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       strongarm | thumb | xscale)
+               basic_machine=arm-unknown
+               ;;
+       xgate)
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       xscaleeb)
+               basic_machine=armeb-unknown
+               ;;
+
+       xscaleel)
+               basic_machine=armel-unknown
+               ;;
+
+       # 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-* \
+       | aarch64-* | aarch64_be-* \
+       | 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-* | avr32-* \
+       | be32-* | be64-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | hexagon-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | le32-* | le64-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+       | microblaze-* | microblazeel-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipsr5900-* | mipsr5900el-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nds32-* | nds32le-* | nds32be-* \
+       | nios-* | nios2-* | nios2eb-* | nios2el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | open8-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+       | pyramid-* \
+       | rl78-* | romp-* | rs6000-* | rx-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+       | tahoe-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tile*-* \
+       | tron-* \
+       | ubicom32-* \
+       | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+       | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # 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
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       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
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       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
+               ;;
+       aros)
+               basic_machine=i386-pc
+               os=-aros
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       bluegene*)
+               basic_machine=powerpc-ibm
+               os=-cnk
+               ;;
+       c54x-*)
+               basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c55x-*)
+               basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c6x-*)
+               basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       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
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16 | cr16-*)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       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
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       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*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
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       microblaze*)
+               basic_machine=microblaze-xilinx
+               ;;
+       mingw64)
+               basic_machine=x86_64-pc
+               os=-mingw64
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       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
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       msys)
+               basic_machine=i386-pc
+               os=-msys
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       nacl)
+               basic_machine=le32-unknown
+               os=-nacl
+               ;;
+       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
+               ;;
+       neo-tandem)
+               basic_machine=neo-tandem
+               ;;
+       nse-tandem)
+               basic_machine=nse-tandem
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       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
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-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-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc | ppcbe)    basic_machine=powerpc-unknown
+               ;;
+       ppc-* | ppcbe-*)
+               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
+               ;;
+       rdos | rdos64)
+               basic_machine=x86_64-pc
+               os=-rdos
+               ;;
+       rdos32)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       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
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       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
+               ;;
+       strongarm-* | thumb-*)
+               basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       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
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tile*)
+               basic_machine=$basic_machine-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       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
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       xscale-* | xscalee[bl]-*)
+               basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-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
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       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
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               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
+               ;;
+       *-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.
+       -auroraux)
+               os=-auroraux
+               ;;
+       -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* | -cnk* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+             | -sym* | -kopensolaris* | -plan9* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* | -aros* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -bitrig* | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+             | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -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* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -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
+               ;;
+       -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -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
+               ;;
+       -tpf*)
+               os=-tpf
+               ;;
+       -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
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+       -nacl*)
+               ;;
+       -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
+       score-*)
+               os=-elf
+               ;;
+       spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+       c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       hexagon-*)
+               os=-elf
+               ;;
+       tic54x-*)
+               os=-coff
+               ;;
+       tic55x-*)
+               os=-coff
+               ;;
+       tic6x-*)
+               os=-coff
+               ;;
+       # 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
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or1k-*)
+               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
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-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
+                               ;;
+                       -cnk*|-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
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -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
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
\ No newline at end of file
index f91a2b6..55865aa 100755 (executable)
@@ -1,9 +1,11 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tcejdb 1.0.68.
+# Generated by GNU Autoconf 2.68 for tcejdb 1.0.68.
 #
 #
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -132,31 +134,6 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
-# Use a proper internal environment variable to ensure we don't fall
-  # into an infinite loop, continuously re-executing ourselves.
-  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
-    _as_can_reexec=no; export _as_can_reexec;
-    # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
-  fi
-  # We don't want this to propagate to other subprocesses.
-          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -190,8 +167,7 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1
-test -x / || exit 1"
+test x\$exitcode = x0 || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -236,25 +212,21 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  export CONFIG_SHELL
-             # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-exit 255
+  # We cannot yet assume a decent shell, so we have to provide a
+       # neutralization value for shells without unset; and this also
+       # works around shells that cannot unset nonexistent variables.
+       # Preserve -v and -x to the replacement shell.
+       BASH_ENV=/dev/null
+       ENV=/dev/null
+       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+       export CONFIG_SHELL
+       case $- in # ((((
+         *v*x* | *x*v* ) as_opts=-vx ;;
+         *v* ) as_opts=-v ;;
+         *x* ) as_opts=-x ;;
+         * ) as_opts= ;;
+       esac
+       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
 fi
 
     if test x$as_have_required = xno; then :
@@ -356,14 +328,6 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -485,10 +449,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
-  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
-  # already done that, so ensure we don't try to do so again and fall
-  # in an infinite loop.  This has already happened in practice.
-  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -523,16 +483,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
+    # In both cases, we have to default to `cp -p'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
+      as_ln_s='cp -p'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -pR'
+    as_ln_s='cp -p'
   fi
 else
-  as_ln_s='cp -pR'
+  as_ln_s='cp -p'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -544,8 +504,28 @@ else
   as_mkdir_p=false
 fi
 
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -652,6 +632,14 @@ CPPFLAGS
 LDFLAGS
 CFLAGS
 CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
 target_alias
 host_alias
 build_alias
@@ -705,7 +693,6 @@ enable_tests
 enable_bzip
 enable_ubc
 enable_zlib
-enable_pthread
 enable_shared
 enable_exlzma
 enable_exlzo
@@ -1176,6 +1163,8 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
+    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1317,6 +1306,10 @@ Fine tuning of the installation directories:
 _ACEOF
 
   cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
 _ACEOF
 fi
 
@@ -1342,7 +1335,6 @@ Optional Features:
   --enable-bzip           build with BZIP2 compression
   --disable-ubc           build without the unified buffer cache assumption
   --disable-zlib          build without ZLIB compression
-  --disable-pthread       build without POSIX thread support
   --disable-shared        avoid to build shared libraries
   --disable-exlzma        build with the custom codec of LZMA
   --disable-exlzo         build with the custom codec of LZO
@@ -1430,9 +1422,9 @@ test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 tcejdb configure 1.0.68
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.68
 
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1618,7 +1610,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        test -x conftest$ac_exeext
+        $as_test_x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -1728,7 +1720,7 @@ This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by tcejdb $as_me 1.0.68, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
 
@@ -1986,7 +1978,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
       || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
   fi
 done
 
@@ -2075,6 +2067,106 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; 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
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
 
 # Package information
 MYLIBVER=9
@@ -2082,10 +2174,12 @@ MYLIBREV=11
 MYFORMATVER="1.0"
 
 # Targets
-MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h ejdb.h ejdb_private.h bson.h myconf.h"
+MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h ejdb.h ejdb_private.h bson.h myconf.h basedefs.h"
 MYLIBRARYFILES="libtcejdb.a"
+
 MYLIBOBJFILES="tcutil.o tchdb.o tcbdb.o tcfdb.o tctdb.o tcadb.o myconf.o md5.o ejdb.o \
-bson.o numbers.o encoding.o utf8proc.o ejdbutl.o"
+bson.o numbers.o encoding.o utf8proc.o ejdbutl.o platform.o"
+
 MYCOMMANDFILES="tcutest tcumttest tcucodec tchtest tchmttest tchmgr"
 MYCOMMANDFILES="$MYCOMMANDFILES tcbtest tcbmttest tcbmgr tcftest tcfmttest tcfmgr"
 MYCOMMANDFILES="$MYCOMMANDFILES tcttest tctmttest tctmgr tcatest tcamttest tcamgr"
@@ -2097,10 +2191,10 @@ MYDOCUMENTFILES="COPYING Changelog"
 MYPCFILES="tcejdb.pc"
 
 # Building flags
-MYCFLAGS="$MYCFLAGS -std=c99 -Wall -fPIC -fsigned-char -O2"
-MYCPPFLAGS="-I. -I\$(INCLUDEDIR) -I$HOME/include -I/usr/local/include"
+MYCFLAGS="$MYCFLAGS -std=gnu99 -Wall -fsigned-char -O2 -Wfatal-errors"
+MYCPPFLAGS="-I. -I$HOME/include -I\$(INCLUDEDIR) -I/usr/local/include"
 MYCPPFLAGS="$MYCPPFLAGS -D_UNICODE -DNDEBUG -D_GNU_SOURCE=1 -D_REENTRANT -D__EXTENSIONS__"
-MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib"
+MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib -L/usr/lib -Wl,-Bstatic"
 MYCMDLDFLAGS=""
 MYRUNPATH="\$(LIBDIR)"
 MYLDLIBPATHENV="LD_LIBRARY_PATH"
@@ -2132,8 +2226,8 @@ fi
 
 if test "$enable_debug" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O0"
-  MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -O0 -Wfatal-errors -Werror"
+  MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG -DEJDB_STATIC"
   MYCMDLDFLAGS="$MYCMDLDFLAGS -static"
   enables="$enables (debug)"
 fi
@@ -2146,7 +2240,7 @@ fi
 
 if test "$enable_devel" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O2 -pipe"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -O2 -pipe"
   MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
   enables="$enables (devel)"
 fi
@@ -2159,7 +2253,7 @@ fi
 
 if test "$enable_profile" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -pg -O2 -pipe"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -pg -O2 -pipe"
   enables="$enables (profile)"
 fi
 
@@ -2184,7 +2278,7 @@ fi
 if test "$enable_fastest" = "yes"
 then
   MYLIBOBJFILES="tokyocabinet_all.o"
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -O3"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -O3"
   MYCFLAGS="$MYCFLAGS -fomit-frame-pointer -fforce-addr -minline-all-stringops"
   MYCPPFLAGS="$MYCPPFLAGS -D_MYFASTEST"
   enables="$enables (fastest)"
@@ -2274,18 +2368,6 @@ then
   enables="$enables (no-zlib)"
 fi
 
-# Disable POSIX thread
-# Check whether --enable-pthread was given.
-if test "${enable_pthread+set}" = set; then :
-  enableval=$enable_pthread;
-fi
-
-if test "$enable_pthread" = "no"
-then
-  MYCPPFLAGS="$MYCPPFLAGS -D_MYNOPTHREAD"
-  enables="$enables (no-pthread)"
-fi
-
 # Disable shared object
 # Check whether --enable-shared was given.
 if test "${enable_shared+set}" = set; then :
@@ -2389,7 +2471,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2429,7 +2511,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2482,7 +2564,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2523,7 +2605,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -2581,7 +2663,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2625,7 +2707,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2668,7 +2750,7 @@ fi
 test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
 
 # Provide some information about the compiler.
 $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -2783,7 +2865,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -2826,7 +2908,7 @@ else
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
 fi
 rm -f conftest conftest$ac_cv_exeext
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -2885,7 +2967,7 @@ $as_echo "$ac_try_echo"; } >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot run C compiled programs.
 If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
     fi
   fi
 fi
@@ -2937,7 +3019,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
 fi
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
@@ -3071,7 +3153,8 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-struct stat;
+#include <sys/types.h>
+#include <sys/stat.h>
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3158,35 +3241,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 # BSD install
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; 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
-  elif test -f "$ac_dir/shtool"; then
-    ac_aux_dir=$ac_dir
-    ac_install_sh="$ac_aux_dir/shtool install -c"
-    break
-  fi
-done
-if test -z "$ac_aux_dir"; then
-  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
-fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
-
-
 # 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:
@@ -3224,7 +3278,7 @@ case $as_dir/ in #((
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
          if test $ac_prog = install &&
            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
@@ -3419,7 +3473,7 @@ else
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
 fi
 
 ac_ext=c
@@ -3445,7 +3499,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_GREP" || continue
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -3511,7 +3565,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_EGREP" || continue
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -3908,7 +3962,7 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
      ;; #(
    *)
      as_fn_error $? "unknown endianness
- presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5  ;;
  esac
 
 
@@ -3991,48 +4045,7 @@ _ACEOF
 
 fi
 
-if test "$enable_pthread" != "no"
-then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
-$as_echo_n "checking for main in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_main+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpthread  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-int
-main ()
-{
-return main ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_pthread_main=yes
-else
-  ac_cv_lib_pthread_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
-$as_echo "$ac_cv_lib_pthread_main" >&6; }
-if test "x$ac_cv_lib_pthread_main" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBPTHREAD 1
-_ACEOF
-
-  LIBS="-lpthread $LIBS"
-
-fi
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrt" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrt" >&5
 $as_echo_n "checking for main in -lrt... " >&6; }
 if ${ac_cv_lib_rt_main+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -4071,7 +4084,7 @@ _ACEOF
 
 fi
 
-fi
+
 if test "$enable_zlib" != "no"
 then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5
@@ -4240,41 +4253,6 @@ _ACEOF
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ltcejdb" >&5
-$as_echo_n "checking for main in -ltcejdb... " >&6; }
-if ${ac_cv_lib_tcejdb_main+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ltcejdb  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-int
-main ()
-{
-return main ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_tcejdb_main=yes
-else
-  ac_cv_lib_tcejdb_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tcejdb_main" >&5
-$as_echo "$ac_cv_lib_tcejdb_main" >&6; }
-if test "x$ac_cv_lib_tcejdb_main" = xyes; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: old version of EJDB was found" >&5
-$as_echo "$as_me: WARNING: old version of EJDB was found" >&2;}
-fi
-
 
 if test "$enable_tests" = "yes"
 then
@@ -4357,25 +4335,15 @@ else
 fi
 
 
-ac_fn_c_check_header_mongrel "$LINENO" "regex.h" "ac_cv_header_regex_h" "$ac_includes_default"
-if test "x$ac_cv_header_regex_h" = xyes; then :
+ac_fn_c_check_header_mongrel "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default"
+if test "x$ac_cv_header_stddef_h" = xyes; then :
   true
 else
-  as_fn_error $? "regex.h is required" "$LINENO" 5
+  as_fn_error $? "stddef.h is required" "$LINENO" 5
 fi
 
 
-ac_fn_c_check_header_mongrel "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
-if test "x$ac_cv_header_glob_h" = xyes; then :
-  true
-else
-  as_fn_error $? "glob.h is required" "$LINENO" 5
-fi
-
-
-if test "$enable_pthread" != "no"
-then
-  ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
 if test "x$ac_cv_header_pthread_h" = xyes; then :
   true
 else
@@ -4383,7 +4351,7 @@ else
 fi
 
 
-fi
+
 if test "$enable_zlib" != "no"
 then
   ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
 
 fi
 
+case $host_os in
+  mingw*)
+      ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
+if test "x$ac_cv_header_windows_h" = xyes; then :
+  true
+else
+  as_fn_error $? "windows.h is required" "$LINENO" 5
+fi
+
+
+      ac_fn_c_check_header_mongrel "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default"
+if test "x$ac_cv_header_time_h" = xyes; then :
+  true
+else
+  as_fn_error $? "time.h is required" "$LINENO" 5
+fi
+
+
+      ;;
+  *)
+      ac_fn_c_check_header_mongrel "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
+if test "x$ac_cv_header_glob_h" = xyes; then :
+  true
+else
+  as_fn_error $? "glob.h is required" "$LINENO" 5
+fi
+
+
+      ;;
+esac
+
+
 # Shared libraries
 if test "$enable_shared" != "no" && test "$enable_profile" != "yes"
 then
-  if uname | grep Darwin >/dev/null
-  then
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.$MYLIBREV.0.dylib"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.dylib"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.dylib"
-    MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
-  else
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER.$MYLIBREV.0"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so"
-  fi
+  case $host_os in
+    darwin*)
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.$MYLIBREV.0.dylib"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.dylib"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.dylib"
+        MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
+        ;;
+    mingw*)
+        MYLIBRARYFILES="$MYLIBRARYFILES tcejdb.dll"
+        MYCPPFLAGS="$MYCPPFLAGS -DEJDB_DLL"
+        ;;
+    *)
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER.$MYLIBREV.0"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so"
+        ;;
+  esac
+fi
+
+
+
+case $host_os in
+    mingw*)
+        ac_fn_c_check_header_mongrel "$LINENO" "pcre.h" "ac_cv_header_pcre_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcre_h" = xyes; then :
+  true
+else
+  as_fn_error $? "pcre.h is required" "$LINENO" 5
+fi
+
+
+        ac_fn_c_check_header_mongrel "$LINENO" "pcreposix.h" "ac_cv_header_pcreposix_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcreposix_h" = xyes; then :
+  true
+else
+  as_fn_error $? "pcreposix.h is required" "$LINENO" 5
+fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_compile in -lpcre" >&5
+$as_echo_n "checking for pcre_compile in -lpcre... " >&6; }
+if ${ac_cv_lib_pcre_pcre_compile+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcre  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcre_compile ();
+int
+main ()
+{
+return pcre_compile ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pcre_pcre_compile=yes
+else
+  ac_cv_lib_pcre_pcre_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_compile" >&5
+$as_echo "$ac_cv_lib_pcre_pcre_compile" >&6; }
+if test "x$ac_cv_lib_pcre_pcre_compile" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPCRE 1
+_ACEOF
+
+  LIBS="-lpcre $LIBS"
+
+else
+  as_fn_error $? "pcre lib is required" "$LINENO" 5
+fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lpcreposix" >&5
+$as_echo_n "checking for regcomp in -lpcreposix... " >&6; }
+if ${ac_cv_lib_pcreposix_regcomp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcreposix  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char regcomp ();
+int
+main ()
+{
+return regcomp ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pcreposix_regcomp=yes
+else
+  ac_cv_lib_pcreposix_regcomp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcreposix_regcomp" >&5
+$as_echo "$ac_cv_lib_pcreposix_regcomp" >&6; }
+if test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPCREPOSIX 1
+_ACEOF
+
+  LIBS="-lpcreposix $LIBS"
+
+else
+  as_fn_error $? "pcreposix lib is required" "$LINENO" 5
 fi
 
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthreadGC2" >&5
+$as_echo_n "checking for main in -lpthreadGC2... " >&6; }
+if ${ac_cv_lib_pthreadGC2_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreadGC2  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthreadGC2_main=yes
+else
+  ac_cv_lib_pthreadGC2_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreadGC2_main" >&5
+$as_echo "$ac_cv_lib_pthreadGC2_main" >&6; }
+if test "x$ac_cv_lib_pthreadGC2_main" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREADGC2 1
+_ACEOF
+
+  LIBS="-lpthreadGC2 $LIBS"
+
+else
+  as_fn_error $? "pthreadGC2 lubrary is required" "$LINENO" 5
+fi
+
+        MYLDFLAGS="-static-libgcc -static-libstdc++ $MYLDFLAGS"
+        MYHEADERFILES="$MYHEADERFILES win32/platform.h"
+        MYCPPFLAGS="$MYCPPFLAGS -DPCRE_STATIC -DPTW32_STATIC_LIB"
+        ;;
+    *)
+        ac_fn_c_check_header_mongrel "$LINENO" "regex.h" "ac_cv_header_regex_h" "$ac_includes_default"
+if test "x$ac_cv_header_regex_h" = xyes; then :
+  true
+else
+  as_fn_error $? "regex.h is required" "$LINENO" 5
+fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regcomp in -lregex" >&5
+$as_echo_n "checking for regcomp in -lregex... " >&6; }
+if ${ac_cv_lib_regex_regcomp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lregex  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char regcomp ();
+int
+main ()
+{
+return regcomp ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_regex_regcomp=yes
+else
+  ac_cv_lib_regex_regcomp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_regex_regcomp" >&5
+$as_echo "$ac_cv_lib_regex_regcomp" >&6; }
+if test "x$ac_cv_lib_regex_regcomp" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBREGEX 1
+_ACEOF
+
+  LIBS="-lregex $LIBS"
+
+else
+  as_fn_error $? "regex lib is required" "$LINENO" 5
+fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
+$as_echo_n "checking for main in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_main=yes
+else
+  ac_cv_lib_pthread_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
+$as_echo "$ac_cv_lib_pthread_main" >&6; }
+if test "x$ac_cv_lib_pthread_main" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+  LIBS="-lpthread $LIBS"
+
+else
+  as_fn_error $? "pthread lubrary is required" "$LINENO" 5
+fi
+
+        MYCFLAGS="$MYCFLAGS -fPIC"
+        ;;
+esac
+
 
 
 #================================================================
@@ -4921,16 +5187,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
+    # In both cases, we have to default to `cp -p'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
+      as_ln_s='cp -p'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -pR'
+    as_ln_s='cp -p'
   fi
 else
-  as_ln_s='cp -pR'
+  as_ln_s='cp -p'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -4990,16 +5256,28 @@ else
   as_mkdir_p=false
 fi
 
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -5021,7 +5299,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # values after options handling.
 ac_log="
 This file was extended by tcejdb $as_me 1.0.68, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -5074,10 +5352,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 tcejdb config.status 1.0.68
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -5155,7 +5433,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
@@ -5187,7 +5465,7 @@ do
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "tcejdb.pc") CONFIG_FILES="$CONFIG_FILES tcejdb.pc" ;;
 
-  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
   esac
 done
 
@@ -5395,7 +5673,7 @@ do
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -5423,7 +5701,7 @@ do
           [\\/$]*) false;;
           *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
           esac ||
-          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
       esac
       case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
       as_fn_append ac_file_inputs " '$ac_f'"
@@ -5450,7 +5728,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
 
     case $ac_tag in
     *:-:* | *:-) cat >"$ac_tmp/stdin" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5  ;;
     esac
     ;;
   esac
index b2e57df..6b78ad1 100644 (file)
@@ -1,7 +1,6 @@
 # Source of configuration for Tokyo Cabinet
 
 
-
 #================================================================
 # Generic Settings
 #================================================================
@@ -12,6 +11,7 @@ test -n "$LDFLAGS" && MYLDFLAGS="$LDFLAGS $MYLDFLAGS"
 
 # Package name
 AC_INIT(tcejdb, 1.0.68)
+AC_CANONICAL_HOST
 
 # Package information
 MYLIBVER=9
@@ -19,10 +19,12 @@ MYLIBREV=11
 MYFORMATVER="1.0"
 
 # Targets
-MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h ejdb.h ejdb_private.h bson.h myconf.h"
+MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h ejdb.h ejdb_private.h bson.h myconf.h basedefs.h"
 MYLIBRARYFILES="libtcejdb.a"
+
 MYLIBOBJFILES="tcutil.o tchdb.o tcbdb.o tcfdb.o tctdb.o tcadb.o myconf.o md5.o ejdb.o \
-bson.o numbers.o encoding.o utf8proc.o ejdbutl.o"
+bson.o numbers.o encoding.o utf8proc.o ejdbutl.o platform.o"
+
 MYCOMMANDFILES="tcutest tcumttest tcucodec tchtest tchmttest tchmgr"
 MYCOMMANDFILES="$MYCOMMANDFILES tcbtest tcbmttest tcbmgr tcftest tcfmttest tcfmgr"
 MYCOMMANDFILES="$MYCOMMANDFILES tcttest tctmttest tctmgr tcatest tcamttest tcamgr"
@@ -34,10 +36,10 @@ MYDOCUMENTFILES="COPYING Changelog"
 MYPCFILES="tcejdb.pc"
 
 # Building flags
-MYCFLAGS="$MYCFLAGS -std=c99 -Wall -fPIC -fsigned-char -O2"
-MYCPPFLAGS="-I. -I\$(INCLUDEDIR) -I$HOME/include -I/usr/local/include"
+MYCFLAGS="$MYCFLAGS -std=gnu99 -Wall -fsigned-char -O2 -Wfatal-errors"
+MYCPPFLAGS="-I. -I$HOME/include -I\$(INCLUDEDIR) -I/usr/local/include"
 MYCPPFLAGS="$MYCPPFLAGS -D_UNICODE -DNDEBUG -D_GNU_SOURCE=1 -D_REENTRANT -D__EXTENSIONS__"
-MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib"
+MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib -L/usr/lib -Wl,-Bstatic"
 MYCMDLDFLAGS=""
 MYRUNPATH="\$(LIBDIR)"
 MYLDLIBPATHENV="LD_LIBRARY_PATH"
@@ -66,8 +68,8 @@ AC_ARG_ENABLE(debug,
   AC_HELP_STRING([--enable-debug], [build for debugging]))
 if test "$enable_debug" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O0"
-  MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -O0 -Wfatal-errors -Werror"
+  MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG -DEJDB_STATIC"
   MYCMDLDFLAGS="$MYCMDLDFLAGS -static"
   enables="$enables (debug)"
 fi
@@ -77,7 +79,7 @@ AC_ARG_ENABLE(devel,
   AC_HELP_STRING([--enable-devel], [build for development]))
 if test "$enable_devel" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O2 -pipe"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -O2 -pipe"
   MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
   enables="$enables (devel)"
 fi
@@ -87,7 +89,7 @@ AC_ARG_ENABLE(profile,
   AC_HELP_STRING([--enable-profile], [build for profiling]))
 if test "$enable_profile" = "yes"
 then
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -pg -O2 -pipe"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -g -pg -O2 -pipe"
   enables="$enables (profile)"
 fi
 
@@ -106,7 +108,7 @@ AC_ARG_ENABLE(fastest,
 if test "$enable_fastest" = "yes"
 then
   MYLIBOBJFILES="tokyocabinet_all.o"
-  MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -O3"
+  MYCFLAGS="-std=gnu99 -Wall -pedantic -fsigned-char -O3"
   MYCFLAGS="$MYCFLAGS -fomit-frame-pointer -fforce-addr -minline-all-stringops"
   MYCPPFLAGS="$MYCPPFLAGS -D_MYFASTEST"
   enables="$enables (fastest)"
@@ -175,15 +177,6 @@ then
   enables="$enables (no-zlib)"
 fi
 
-# Disable POSIX thread
-AC_ARG_ENABLE(pthread,
-  AC_HELP_STRING([--disable-pthread], [build without POSIX thread support]))
-if test "$enable_pthread" = "no"
-then
-  MYCPPFLAGS="$MYCPPFLAGS -D_MYNOPTHREAD"
-  enables="$enables (no-pthread)"
-fi
-
 # Disable shared object
 AC_ARG_ENABLE(shared,
   AC_HELP_STRING([--disable-shared], [avoid to build shared libraries]))
@@ -266,11 +259,8 @@ AC_C_BIGENDIAN(MYCPPFLAGS="$MYCPPFLAGS -D_MYBIGEND")
 # Underlying libraries
 AC_CHECK_LIB(c, main)
 AC_CHECK_LIB(m, main)
-if test "$enable_pthread" != "no"
-then
-  AC_CHECK_LIB(pthread, main)
-  AC_CHECK_LIB(rt, main)
-fi
+AC_CHECK_LIB(rt, main)
+
 if test "$enable_zlib" != "no"
 then
   AC_CHECK_LIB(z, main)
@@ -287,7 +277,6 @@ if test "$enable_exlzo" = "yes"
 then
   AC_CHECK_LIB(lzo2, main)
 fi
-AC_CHECK_LIB(tcejdb, main, AC_MSG_WARN([old version of EJDB was found]))
 
 if test "$enable_tests" = "yes"
 then
@@ -300,12 +289,9 @@ AC_CHECK_HEADER(stdlib.h, true, AC_MSG_ERROR([stdlib.h is required]))
 AC_CHECK_HEADER(stdint.h, true, AC_MSG_ERROR([stdint.h is required]))
 AC_CHECK_HEADER(unistd.h, true, AC_MSG_ERROR([unistd.h is required]))
 AC_CHECK_HEADER(dirent.h, true, AC_MSG_ERROR([dirent.h is required]))
-AC_CHECK_HEADER(regex.h, true, AC_MSG_ERROR([regex.h is required]))
-AC_CHECK_HEADER(glob.h, true, AC_MSG_ERROR([glob.h is required]))
-if test "$enable_pthread" != "no"
-then
-  AC_CHECK_HEADER(pthread.h, true, AC_MSG_ERROR([pthread.h is required]))
-fi
+AC_CHECK_HEADER(stddef.h, true, AC_MSG_ERROR([stddef.h is required]))
+AC_CHECK_HEADER(pthread.h, true, AC_MSG_ERROR([pthread.h is required]))
+
 if test "$enable_zlib" != "no"
 then
   AC_CHECK_HEADER(zlib.h, true, AC_MSG_ERROR([zlib.h is required]))
@@ -323,24 +309,62 @@ then
   AC_CHECK_HEADER(lzo/lzo1x.h, true, AC_MSG_ERROR([lzo/lzo1x.h is required]))
 fi
 
+case $host_os in
+  mingw*)
+      AC_CHECK_HEADER(windows.h, true, AC_MSG_ERROR([windows.h is required]))
+      AC_CHECK_HEADER(time.h, true, AC_MSG_ERROR([time.h is required]))
+      ;;
+  *)
+      AC_CHECK_HEADER(glob.h, true, AC_MSG_ERROR([glob.h is required]))
+      ;;
+esac
+
+
 # Shared libraries
 if test "$enable_shared" != "no" && test "$enable_profile" != "yes"
 then
-  if uname | grep Darwin >/dev/null
-  then
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.$MYLIBREV.0.dylib"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.dylib"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.dylib"
-    MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
-  else
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER.$MYLIBREV.0"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER"
-    MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so"
-  fi
+  case $host_os in
+    darwin*)
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.$MYLIBREV.0.dylib"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.$MYLIBVER.dylib"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.dylib"
+        MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
+        ;;
+    mingw*)
+        MYLIBRARYFILES="$MYLIBRARYFILES tcejdb.dll"
+        MYCPPFLAGS="$MYCPPFLAGS -DEJDB_DLL"
+        ;;
+    *)
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER.$MYLIBREV.0"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so.$MYLIBVER"
+        MYLIBRARYFILES="$MYLIBRARYFILES libtcejdb.so"
+        ;;
+  esac
 fi
 
 
 
+case $host_os in
+    mingw*)
+        AC_CHECK_HEADER(pcre.h, true, AC_MSG_ERROR([pcre.h is required]))
+        AC_CHECK_HEADER(pcreposix.h, true, AC_MSG_ERROR([pcreposix.h is required]))
+        AC_CHECK_LIB(pcre, pcre_compile, [], AC_MSG_ERROR([pcre lib is required]))
+        AC_CHECK_LIB(pcreposix, regcomp, [], AC_MSG_ERROR([pcreposix lib is required]))
+        AC_CHECK_LIB(pthreadGC2, main, [], AC_MSG_ERROR([pthreadGC2 lubrary is required]))
+        MYLDFLAGS="-static-libgcc -static-libstdc++ $MYLDFLAGS"
+        MYHEADERFILES="$MYHEADERFILES win32/platform.h"
+        MYCPPFLAGS="$MYCPPFLAGS -DPCRE_STATIC -DPTW32_STATIC_LIB"
+        ;;
+    *)
+        AC_CHECK_HEADER(regex.h, true, AC_MSG_ERROR([regex.h is required]))
+        AC_CHECK_LIB(regex, regcomp, [], AC_MSG_ERROR([regex lib is required]))
+        AC_CHECK_LIB(pthread, main, [], AC_MSG_ERROR([pthread lubrary is required]))
+        MYCFLAGS="$MYCFLAGS -fPIC"
+        ;;
+esac
+
+
+
 #================================================================
 # Generic Settings
 #================================================================
index 2b81768..799c32d 100644 (file)
  *  Boston, MA 02111-1307 USA.
  *************************************************************************************************/
 
+#include "myconf.h"
 #include "bson.h"
-
-
-#include <regex.h>
 #include "ejdb_private.h"
 #include "ejdbutl.h"
 
@@ -34,7 +32,7 @@
 
 #define JBISOPEN(JB_jb) ((JB_jb) && (JB_jb)->metadb && (JB_jb)->metadb->open) ? true : false
 
-#define JBISVALCOLNAME(JB_cname) ((JB_cname) && strlen(JB_cname) < JBMAXCOLNAMELEN && !index((JB_cname), '.'))
+#define JBISVALCOLNAME(JB_cname) ((JB_cname) && strlen(JB_cname) < JBMAXCOLNAMELEN && !strchr((JB_cname), '.'))
 
 #define JBENSUREOPENLOCK(JB_jb, JB_lock, JB_ret)  \
                             assert(JB_jb); \
@@ -99,7 +97,7 @@ static bool _updatebsonidx(EJCOLL *jcoll, const bson_oid_t *oid, const bson *bs,
 static bool _metasetopts(EJDB *jb, const char *colname, EJCOLLOPTS *opts);
 static bool _metagetopts(EJDB *jb, const char *colname, EJCOLLOPTS *opts);
 static bson* _metagetbson(EJDB *jb, const char *colname, int colnamesz, const char *mkey);
-static bson* _metagetbson2(EJCOLL *jcoll, const char *mkey);
+static bson* _metagetbson2(EJCOLL *jcoll, const char *mkey) __attribute__ ((unused));
 static bool _metasetbson(EJDB *jb, const char *colname, int colnamesz,
         const char *mkey, bson *val, bool merge, bool mergeoverwrt);
 static bool _metasetbson2(EJCOLL *jcoll, const char *mkey, bson *val, bool merge, bool mergeoverwrt);
@@ -132,7 +130,7 @@ extern const char *utf8proc_errmsg(ssize_t errcode);
 static const bool yes = true;
 static const bool no = false;
 
-EJDB_EXPORT const char* ejdberrmsg(int ecode) {
+ const char* ejdberrmsg(int ecode) {
     if (ecode > -6 && ecode < 0) { //Hook for negative error codes of utf8proc library
         return utf8proc_errmsg(ecode);
     }
@@ -157,7 +155,7 @@ EJDB_EXPORT const char* ejdberrmsg(int ecode) {
     }
 }
 
-EJDB_EXPORT bool ejdbisvalidoidstr(const char *oid) {
+ bool ejdbisvalidoidstr(const char *oid) {
     if (!oid) {
         return false;
     }
@@ -169,12 +167,12 @@ EJDB_EXPORT bool ejdbisvalidoidstr(const char *oid) {
 }
 
 /* Get the last happened error code of a database object. */
-EJDB_EXPORT int ejdbecode(EJDB *jb) {
+ int ejdbecode(EJDB *jb) {
     assert(jb && jb->metadb);
     return tctdbecode(jb->metadb);
 }
 
-EJDB_EXPORT EJDB* ejdbnew(void) {
+ EJDB* ejdbnew(void) {
     EJDB *jb;
     TCCALLOC(jb, 1, sizeof (*jb));
     jb->metadb = tctdbnew();
@@ -191,7 +189,7 @@ EJDB_EXPORT EJDB* ejdbnew(void) {
     return jb;
 }
 
-EJDB_EXPORT void ejdbdel(EJDB *jb) {
+ void ejdbdel(EJDB *jb) {
     assert(jb && jb->metadb);
     if (JBISOPEN(jb)) ejdbclose(jb);
     for (int i = 0; i < jb->cdbsnum; ++i) {
@@ -209,7 +207,7 @@ EJDB_EXPORT void ejdbdel(EJDB *jb) {
     TCFREE(jb);
 }
 
-EJDB_EXPORT bool ejdbclose(EJDB *jb) {
+ bool ejdbclose(EJDB *jb) {
     JBENSUREOPENLOCK(jb, true, false);
     bool rv = true;
     for (int i = 0; i < jb->cdbsnum; ++i) {
@@ -227,11 +225,11 @@ EJDB_EXPORT bool ejdbclose(EJDB *jb) {
     return rv;
 }
 
-EJDB_EXPORT bool ejdbisopen(EJDB *jb) {
+ bool ejdbisopen(EJDB *jb) {
     return JBISOPEN(jb);
 }
 
-EJDB_EXPORT bool ejdbopen(EJDB *jb, const char *path, int mode) {
+ bool ejdbopen(EJDB *jb, const char *path, int mode) {
     assert(jb && path);
     assert(jb->metadb);
     if (!JBLOCKMETHOD(jb, true)) return false;
@@ -263,7 +261,7 @@ finish:
     return rv;
 }
 
-EJDB_EXPORT EJCOLL* ejdbgetcoll(EJDB *jb, const char *colname) {
+ EJCOLL* ejdbgetcoll(EJDB *jb, const char *colname) {
     assert(colname);
     EJCOLL *coll = NULL;
     JBENSUREOPENLOCK(jb, false, NULL);
@@ -272,7 +270,7 @@ EJDB_EXPORT EJCOLL* ejdbgetcoll(EJDB *jb, const char *colname) {
     return coll;
 }
 
-EJDB_EXPORT TCLIST* ejdbgetcolls(EJDB *jb) {
+ TCLIST* ejdbgetcolls(EJDB *jb) {
     assert(jb);
     EJCOLL *coll = NULL;
     JBENSUREOPENLOCK(jb, false, NULL);
@@ -285,7 +283,7 @@ EJDB_EXPORT TCLIST* ejdbgetcolls(EJDB *jb) {
     return ret;
 }
 
-EJDB_EXPORT EJCOLL* ejdbcreatecoll(EJDB *jb, const char *colname, EJCOLLOPTS *opts) {
+ EJCOLL* ejdbcreatecoll(EJDB *jb, const char *colname, EJCOLLOPTS *opts) {
     assert(colname);
     EJCOLL *coll = ejdbgetcoll(jb, colname);
     if (coll) {
@@ -314,7 +312,7 @@ finish:
     return coll;
 }
 
-EJDB_EXPORT bool ejdbrmcoll(EJDB *jb, const char *colname, bool unlinkfile) {
+ bool ejdbrmcoll(EJDB *jb, const char *colname, bool unlinkfile) {
     assert(colname);
     JBENSUREOPENLOCK(jb, true, false);
     bool rv = true;
@@ -364,11 +362,11 @@ finish:
 }
 
 /* Save/Update BSON  */
-EJDB_EXPORT bool ejdbsavebson(EJCOLL *jcoll, bson *bs, bson_oid_t *oid) {
+ bool ejdbsavebson(EJCOLL *jcoll, bson *bs, bson_oid_t *oid) {
     return ejdbsavebson2(jcoll, bs, oid, false);
 }
 
-EJDB_EXPORT bool ejdbsavebson2(EJCOLL *jcoll, bson *bs, bson_oid_t *oid, bool merge) {
+ bool ejdbsavebson2(EJCOLL *jcoll, bson *bs, bson_oid_t *oid, bool merge) {
     assert(jcoll);
     if (!bs || bs->err || !bs->finished) {
         _ejdbsetecode(jcoll->jb, JBEINVALIDBSON, __FILE__, __LINE__, __func__);
@@ -384,7 +382,7 @@ EJDB_EXPORT bool ejdbsavebson2(EJCOLL *jcoll, bson *bs, bson_oid_t *oid, bool me
     return rv;
 }
 
-EJDB_EXPORT bool ejdbrmbson(EJCOLL *jcoll, bson_oid_t *oid) {
+ bool ejdbrmbson(EJCOLL *jcoll, bson_oid_t *oid) {
     assert(jcoll && oid);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -411,7 +409,7 @@ finish:
     return rv;
 }
 
-EJDB_EXPORT bson* ejdbloadbson(EJCOLL *jcoll, const bson_oid_t *oid) {
+ bson* ejdbloadbson(EJCOLL *jcoll, const bson_oid_t *oid) {
     assert(jcoll && oid);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -442,7 +440,7 @@ finish:
     return ret;
 }
 
-EJDB_EXPORT EJQ* ejdbcreatequery(EJDB *jb, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints) {
+ EJQ* ejdbcreatequery(EJDB *jb, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints) {
     assert(jb);
     if (!qobj || qobj->err || !qobj->finished) {
         _ejdbsetecode(jb, JBEINVALIDBSON, __FILE__, __LINE__, __func__);
@@ -486,12 +484,12 @@ error:
     return NULL;
 }
 
-EJDB_EXPORT void ejdbquerydel(EJQ *q) {
+ void ejdbquerydel(EJQ *q) {
     _qrydel(q, true);
 }
 
 /** Set index */
-EJDB_EXPORT bool ejdbsetindex(EJCOLL *jcoll, const char *fpath, int flags) {
+ bool ejdbsetindex(EJCOLL *jcoll, const char *fpath, int flags) {
     assert(jcoll && fpath);
     bool rv = true;
     bson *imeta = NULL;
@@ -646,7 +644,7 @@ finish:
     return rv;
 }
 
-EJDB_EXPORT uint32_t ejdbupdate(EJCOLL *jcoll, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints, TCXSTR *log) {
+ uint32_t ejdbupdate(EJCOLL *jcoll, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints, TCXSTR *log) {
     assert(jcoll);
     uint32_t count = 0;
     EJQ *q = ejdbcreatequery(jcoll->jb, qobj, orqobjs, orqobjsnum, hints);
@@ -658,7 +656,7 @@ EJDB_EXPORT uint32_t ejdbupdate(EJCOLL *jcoll, bson *qobj, bson *orqobjs, int or
     return count;
 }
 
-EJDB_EXPORT TCLIST* ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log) {
+ TCLIST* ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log) {
     assert(jcoll && q && q->qobjlist);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -675,7 +673,7 @@ EJDB_EXPORT TCLIST* ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count,
     return res;
 }
 
-EJDB_EXPORT bool ejdbsyncoll(EJCOLL *jcoll) {
+ bool ejdbsyncoll(EJCOLL *jcoll) {
     assert(jcoll);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -688,7 +686,7 @@ EJDB_EXPORT bool ejdbsyncoll(EJCOLL *jcoll) {
     return rv;
 }
 
-EJDB_EXPORT bool ejdbsyncdb(EJDB *jb) {
+ bool ejdbsyncdb(EJDB *jb) {
     assert(jb);
     JBENSUREOPENLOCK(jb, true, false);
     bool rv = true;
@@ -704,13 +702,13 @@ EJDB_EXPORT bool ejdbsyncdb(EJDB *jb) {
     return rv;
 }
 
-EJDB_EXPORT bool ejdbtranbegin(EJCOLL *jcoll) {
+ bool ejdbtranbegin(EJCOLL *jcoll) {
     assert(jcoll);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
         return false;
     }
-    for (double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2) {
+    for (double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2) {
         if (!JBCLOCKMETHOD(jcoll, true)) return false;
         if (!jcoll->tdb->open || !jcoll->tdb->wmode) {
             _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -731,7 +729,7 @@ EJDB_EXPORT bool ejdbtranbegin(EJCOLL *jcoll) {
     return true;
 }
 
-EJDB_EXPORT bool ejdbtrancommit(EJCOLL *jcoll) {
+ bool ejdbtrancommit(EJCOLL *jcoll) {
     assert(jcoll);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -750,7 +748,7 @@ EJDB_EXPORT bool ejdbtrancommit(EJCOLL *jcoll) {
     return !err;
 }
 
-EJDB_EXPORT bool ejdbtranabort(EJCOLL *jcoll) {
+ bool ejdbtranabort(EJCOLL *jcoll) {
     assert(jcoll);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -769,7 +767,7 @@ EJDB_EXPORT bool ejdbtranabort(EJCOLL *jcoll) {
     return !err;
 }
 
-EJDB_EXPORT bool ejdbtranstatus(EJCOLL *jcoll, bool *txactive) {
+ bool ejdbtranstatus(EJCOLL *jcoll, bool *txactive) {
     assert(jcoll && txactive);
     if (!JBISOPEN(jcoll->jb)) {
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -805,7 +803,6 @@ static EJCOLL* _getcoll(EJDB *jb, const char *colname) {
 /* Set mutual exclusion control of a table database object for threading. */
 static bool _ejdbsetmutex(EJDB *ejdb) {
     assert(ejdb);
-    if (!TCUSEPTHREAD) return true;
     if (ejdb->mmtx || JBISOPEN(ejdb)) {
         _ejdbsetecode(ejdb, TCEINVALID, __FILE__, __LINE__, __func__);
         return false;
@@ -850,7 +847,6 @@ static bool _ejdbunlockmethod(EJDB *ejdb) {
 
 static bool _ejdbcolsetmutex(EJCOLL *coll) {
     assert(coll && coll->jb);
-    if (!TCUSEPTHREAD) return true;
     if (coll->mmtx) {
         _ejdbsetecode(coll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
         return false;
index b9c8d3c..baeb4e3 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef EJDB_H
 #define        EJDB_H
 
-#include "myconf.h"
 #include "bson.h"
 #include "tcutil.h"
 
index d172f58..4c9bd40 100644 (file)
  *************************************************************************************************/
 
 #ifndef EJDB_PRIVATE_H
-#define        EJDB_PRIVATE_H
+#define EJDB_PRIVATE_H
 
 #include "ejdb.h"
-
-#include "myconf.h"
 #include "tcutil.h"
 #include "tctdb.h"
 #include "tchdb.h"
index 77247e5..d1cbe95 100644 (file)
@@ -32,6 +32,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 /* Byte-wise swap two items of size SIZE. */
 #define SWAP(a, b, size)                                                     \
index 72b02cc..aeb7030 100644 (file)
@@ -15,9 +15,8 @@
  *************************************************************************************************/
 
 #ifndef EJDBUTL_H
-#define        EJDBUTL_H
+#define EJDBUTL_H
 
-#include "myconf.h"
 #include "tcutil.h"
 
 EJDB_EXTERN_C_START
index bd46046..a125808 100644 (file)
 
 #endif
 
-
+#include "basedefs.h"
 
 /*************************************************************************************************
  * common settings
  *************************************************************************************************/
 
-#ifdef __cplusplus
-#define EJDB_EXTERN_C_START extern "C" {
-#define EJDB_EXTERN_C_END }
-#else
-#define EJDB_EXTERN_C_START
-#define EJDB_EXTERN_C_END
-#endif
-
-#ifdef __GNUC__
-#define EJDB_INLINE static __inline__
-#define EJDB_EXPORT
-#else
-#define EJDB_INLINE static
-#ifdef EJDB_STATIC_BUILD
-#define EJDB_EXPORT
-#elif defined(MONGO_DLL_BUILD)
-#define EJDB_EXPORT __declspec(dllexport)
-#else
-#define EJDB_EXPORT __declspec(dllimport)
-#endif
-#endif
-
 
 #if defined(NDEBUG)
 #define TCDODEBUG(TC_expr) \
 #if defined(_MYNOUBC) || defined(__hppa__)
 #define TCUBCACHE      0
 #elif defined(_SYS_LINUX_) || defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || \
-  defined(_SYS_MACOSX_) || defined(_SYS_SUNOS_)
+  defined(_SYS_MACOSX_) || defined(_SYS_SUNOS_) || defined(_WIN32)
 #define TCUBCACHE      1
 #else
 #define TCUBCACHE      0
 #define TCUSEEXLZO     0
 #endif
 
-#if defined(_MYNOPTHREAD)
-#define TCUSEPTHREAD   0
-#else
-#define TCUSEPTHREAD   1
-#endif
-
 #if defined(_MYMICROYIELD)
 #define TCMICROYIELD   1
 #else
  *************************************************************************************************/
 
 
+#ifdef _WIN32
+#include <pcreposix.h>
+#include "win32/platform.h"
+#define GET_STDOUT_HANDLE() GetStdHandle(STD_OUTPUT_HANDLE)
+#define GET_STDERR_HANDLE() GetStdHandle(STD_ERROR_HANDLE)
+#define GET_STDIN_HANDLE() GetStdHandle(STD_INPUT_HANDLE)
+#define CLOSEFH(_fd) (CloseHandle(_fd))
+#else
+#include <regex.h>
+#include <glob.h>
+#include <sys/mman.h>
+#include <sys/times.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#define GET_STDOUT_HANDLE() (1)
+#define GET_STDERR_HANDLE() (2)
+#define GET_STDIN_HANDLE() (0)
+#define CLOSEFH(_fd) (close(_fd) != -1)
+#define sysconf_SC_CLK_TCK sysconf(_SC_CLK_TCK)
+#endif
+
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/mman.h>
 #include <sys/time.h>
-#include <sys/times.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
+
 #include <fcntl.h>
 #include <dirent.h>
-#include <regex.h>
-#include <glob.h>
-
-#if TCUSEPTHREAD
 #include <pthread.h>
+
 #if defined(_POSIX_PRIORITY_SCHEDULING)
 #include <sched.h>
 #endif
-#endif
-
-
 
 /*************************************************************************************************
  * miscellaneous hacks
@@ -327,9 +311,14 @@ int _tc_dummyfuncv(int a, ...);
  * notation of filesystems
  *************************************************************************************************/
 
-
+#ifdef _WIN32
+#define MYPATHCHR       '\\'
+#define MYPATHSTR       "\\"
+#else
 #define MYPATHCHR       '/'
 #define MYPATHSTR       "/"
+#endif
+
 #define MYEXTCHR        '.'
 #define MYEXTSTR        "."
 #define MYCDIRSTR       "."
@@ -377,61 +366,7 @@ void *_tc_recencode(const void *ptr, int size, int *sp, void *op);
 
 void *_tc_recdecode(const void *ptr, int size, int *sp, void *op);
 
-
-
-/*************************************************************************************************
- * for POSIX thread disability
- *************************************************************************************************/
-
-
-#if ! TCUSEPTHREAD
-
-#define pthread_t                        intptr_t
-
-#define pthread_once_t                   intptr_t
-#undef PTHREAD_ONCE_INIT
-#define PTHREAD_ONCE_INIT                0
-#define pthread_once(TC_a, TC_b)         _tc_dummyfuncv((intptr_t)(TC_a), (TC_b))
-
-#define pthread_mutexattr_t              intptr_t
-#undef PTHREAD_MUTEX_RECURSIVE
-#define PTHREAD_MUTEX_RECURSIVE          0
-#define pthread_mutexattr_init(TC_a)     _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_mutexattr_destroy(TC_a)  _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_mutexattr_settype(TC_a, TC_b)  _tc_dummyfuncv((intptr_t)(TC_a), (TC_b))
-
-#define pthread_mutex_t                  intptr_t
-#undef PTHREAD_MUTEX_INITIALIZER
-#define PTHREAD_MUTEX_INITIALIZER        0
-#define pthread_mutex_init(TC_a, TC_b)   _tc_dummyfuncv((intptr_t)(TC_a), (TC_b))
-#define pthread_mutex_destroy(TC_a)      _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_mutex_lock(TC_a)         _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_mutex_unlock(TC_a)       _tc_dummyfuncv((intptr_t)(TC_a))
-
-#define pthread_rwlock_t                 intptr_t
-#undef PTHREAD_RWLOCK_INITIALIZER
-#define PTHREAD_RWLOCK_INITIALIZER       0
-#define pthread_rwlock_init(TC_a, TC_b)  _tc_dummyfuncv((intptr_t)(TC_a), (TC_b))
-#define pthread_rwlock_destroy(TC_a)     _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_rwlock_rdlock(TC_a)      _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_rwlock_wrlock(TC_a)      _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_rwlock_unlock(TC_a)      _tc_dummyfuncv((intptr_t)(TC_a))
-
-#define pthread_key_t                    intptr_t
-#define pthread_key_create(TC_a, TC_b)   _tc_dummyfuncv((intptr_t)(TC_a), (TC_b))
-#define pthread_key_delete(TC_a)         _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_setspecific(TC_a, TC_b)  _tc_dummyfuncv((intptr_t)(TC_a))
-#define pthread_getspecific(TC_a)        _tc_dummyfuncv((intptr_t)(TC_a))
-
-#define pthread_create(TC_th, TC_attr, TC_func, TC_arg) \
-  (*(TC_th) = 0, (TC_func)(TC_arg), 0)
-#define pthread_join(TC_th, TC_rv)       (*(TC_rv) = NULL, 0)
-#define pthread_detach(TC_th)            0
-#define sched_yield()                    _tc_dummyfunc()
-
-#endif
-
-#if TCUSEPTHREAD && TCMICROYIELD
+#if TCMICROYIELD
 #define TCTESTYIELD() \
   do { \
     if(((++_tc_dummy_cnt) & (0x20 - 1)) == 0){ \
@@ -458,7 +393,7 @@ void *_tc_recdecode(const void *ptr, int size, int *sp, void *op);
   } while(false)
 #endif
 
-#if !defined(_POSIX_PRIORITY_SCHEDULING) && TCUSEPTHREAD
+#ifndef _POSIX_PRIORITY_SCHEDULING
 #define sched_yield()                    usleep(1000 * 20)
 #endif
 
@@ -571,11 +506,4 @@ void *_tc_recdecode(const void *ptr, int size, int *sp, void *op);
 
 #endif                                   // duplication check
 
-
-//EJDB Shared
-
-#define JDBIDKEYNAME "_id"  /**> Name of PK _id field in BSONs */
-#define JDBIDKEYNAMEL 3
-
-
 // END OF FILE
diff --git a/tcejdb/platform.c b/tcejdb/platform.c
new file mode 100644 (file)
index 0000000..20fd85a
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef _WIN32
+#include "win32/platform.c"
+#endif
index 9777d66..f426cf3 100644 (file)
@@ -132,7 +132,7 @@ bool tcadbopen(TCADB *adb, const char *name){
     tclistdel(elems);
     return false;
   }
-  int dbgfd = -1;
+  HANDLE dbgfd = INVALID_HANDLE_VALUE;
   int64_t bnum = -1;
   int64_t capnum = -1;
   int64_t capsiz = -1;
@@ -164,7 +164,12 @@ bool tcadbopen(TCADB *adb, const char *name){
     if(!pv) continue;
     *(pv++) = '\0';
     if(!tcstricmp(elem, "dbgfd")){
-      dbgfd = tcatoi(pv);
+       int dbgdescr = tcatoi(pv);
+#ifndef _WIN32
+       dbgfd = dbgdescr;
+#else
+       dbgfd = (HANDLE)_get_osfhandle(dbgdescr);
+#endif
     } else if(!tcstricmp(elem, "bnum")){
       bnum = tcatoix(pv);
     } else if(!tcstricmp(elem, "capnum")){
@@ -233,7 +238,7 @@ bool tcadbopen(TCADB *adb, const char *name){
     adb->omode = ADBONDB;
   } else if(tcstribwm(path, ".tch") || tcstribwm(path, ".hdb")){
     TCHDB *hdb = tchdbnew();
-    if(dbgfd >= 0) tchdbsetdbgfd(hdb, dbgfd);
+    if(!INVALIDHANDLE(dbgfd)) tchdbsetdbgfd(hdb, dbgfd);
     tchdbsetmutex(hdb);
     int opts = 0;
     if(tlmode) opts |= HDBTLARGE;
@@ -259,7 +264,7 @@ bool tcadbopen(TCADB *adb, const char *name){
     adb->omode = ADBOHDB;
   } else if(tcstribwm(path, ".tcb") || tcstribwm(path, ".bdb")){
     TCBDB *bdb = tcbdbnew();
-    if(dbgfd >= 0) tcbdbsetdbgfd(bdb, dbgfd);
+    if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(bdb, dbgfd);
     tcbdbsetmutex(bdb);
     int opts = 0;
     if(tlmode) opts |= BDBTLARGE;
@@ -287,7 +292,7 @@ bool tcadbopen(TCADB *adb, const char *name){
     adb->omode = ADBOBDB;
   } else if(tcstribwm(path, ".tcf") || tcstribwm(path, ".fdb")){
     TCFDB *fdb = tcfdbnew();
-    if(dbgfd >= 0) tcfdbsetdbgfd(fdb, dbgfd);
+    if(!INVALIDHANDLE(dbgfd)) tcfdbsetdbgfd(fdb, dbgfd);
     tcfdbsetmutex(fdb);
     tcfdbtune(fdb, width, limsiz);
     int omode = owmode ? FDBOWRITER : FDBOREADER;
@@ -305,7 +310,7 @@ bool tcadbopen(TCADB *adb, const char *name){
     adb->omode = ADBOFDB;
   } else if(tcstribwm(path, ".tct") || tcstribwm(path, ".tdb")){
     TCTDB *tdb = tctdbnew();
-    if(dbgfd >= 0) tctdbsetdbgfd(tdb, dbgfd);
+    if(!INVALIDHANDLE(dbgfd)) tctdbsetdbgfd(tdb, dbgfd);
     tctdbsetmutex(tdb);
     int opts = 0;
     if(tlmode) opts |= TDBTLARGE;
@@ -446,7 +451,7 @@ bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
       break;
     case ADBOTDB:
       if(ksiz < 1){
-        ksiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        ksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         kbuf = numbuf;
       }
       if(!tctdbput2(adb->tdb, kbuf, ksiz, vbuf, vsiz)) err = true;
@@ -522,7 +527,7 @@ bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int
       break;
     case ADBOTDB:
       if(ksiz < 1){
-        ksiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        ksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         kbuf = numbuf;
       }
       if(!tctdbputkeep2(adb->tdb, kbuf, ksiz, vbuf, vsiz)) err = true;
@@ -594,7 +599,7 @@ bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int v
       break;
     case ADBOTDB:
       if(ksiz < 1){
-        ksiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        ksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         kbuf = numbuf;
       }
       if(!tctdbputcat2(adb->tdb, kbuf, ksiz, vbuf, vsiz)) err = true;
@@ -946,7 +951,7 @@ int tcadbaddint(TCADB *adb, const void *kbuf, int ksiz, int num){
       break;
     case ADBOTDB:
       if(ksiz < 1){
-        ksiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        ksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         kbuf = numbuf;
       }
       rv = tctdbaddint(adb->tdb, kbuf, ksiz, num);
@@ -1009,7 +1014,7 @@ double tcadbadddouble(TCADB *adb, const void *kbuf, int ksiz, double num){
       break;
     case ADBOTDB:
       if(ksiz < 1){
-        ksiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        ksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         kbuf = numbuf;
       }
       rv = tctdbadddouble(adb->tdb, kbuf, ksiz, num);
@@ -1257,7 +1262,7 @@ bool tcadbcopy(TCADB *adb, const char *path){
     case ADBONDB:
       if(*path == '@'){
         char tsbuf[TCNUMBUFSIZ];
-        sprintf(tsbuf, "%llu", (unsigned long long)(tctime() * 1000000));
+        sprintf(tsbuf, "%" PRIuMAX "", (unsigned long long)(tctime() * 1000000));
         const char *args[2];
         args[0] = path + 1;
         args[1] = tsbuf;
@@ -3236,7 +3241,7 @@ TCLIST *tcadbmisc(TCADB *adb, const char *name, const TCLIST *args){
       } else if(!strcmp(name, "genuid")){
         rv = tclistnew2(1);
         char numbuf[TCNUMBUFSIZ];
-        int nsiz = sprintf(numbuf, "%lld", (long long)tctdbgenuid(adb->tdb));
+        int nsiz = sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(adb->tdb));
         TCLISTPUSH(rv, numbuf, nsiz);
       } else {
         rv = NULL;
@@ -3930,7 +3935,7 @@ static bool tcadbmulcopy(ADBMUL *mul, const char *path){
       if(!tcadbcopy(adbs[i], path)) err = true;
     }
   } else {
-    if(mkdir(path, ADBDIRMODE) == -1 && errno != EEXIST) return false;
+    if(mkdir(path, ADBDIRMODE) && errno != EEXIST) return false;
     for(int i = 0; i < num; i++){
       TCADB *adb = adbs[i];
       const char *cpath = tcadbpath(adb);
index 2340fba..63656e0 100644 (file)
@@ -69,12 +69,12 @@ enum {                                   /* enumeration for open modes */
 
 /* Create an abstract database object.
    The return value is the new abstract database object. */
-TCADB *tcadbnew(void);
+EJDB_EXPORT TCADB *tcadbnew(void);
 
 
 /* Delete an abstract database object.
    `adb' specifies the abstract database object. */
-void tcadbdel(TCADB *adb);
+EJDB_EXPORT void tcadbdel(TCADB *adb);
 
 
 /* Open an abstract database.
@@ -101,7 +101,7 @@ void tcadbdel(TCADB *adb);
    of TCBS option.  "idx" specifies the column name of an index and its type separated by ":".
    For example, "casket.tch#bnum=1000000#opts=ld" means that the name of the database file is
    "casket.tch", and the bucket number is 1000000, and the options are large and Deflate. */
-bool tcadbopen(TCADB *adb, const char *name);
+EJDB_EXPORT bool tcadbopen(TCADB *adb, const char *name);
 
 
 /* Close an abstract database object.
@@ -109,7 +109,7 @@ bool tcadbopen(TCADB *adb, const char *name);
    If successful, the return value is true, else, it is false.
    Update of a database is assured to be written when the database is closed.  If a writer opens
    a database but does not close it appropriately, the database will be broken. */
-bool tcadbclose(TCADB *adb);
+EJDB_EXPORT bool tcadbclose(TCADB *adb);
 
 
 /* Store a record into an abstract database object.
@@ -120,7 +120,7 @@ bool tcadbclose(TCADB *adb);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into an abstract object.
@@ -129,7 +129,7 @@ bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr);
 
 
 /* Store a new record into an abstract database object.
@@ -140,7 +140,7 @@ bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into an abstract database object.
@@ -149,7 +149,7 @@ bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the existing record in an abstract database object.
@@ -160,7 +160,7 @@ bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string value at the end of the existing record in an abstract database object.
@@ -169,7 +169,7 @@ bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int v
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr);
 
 
 /* Remove a record of an abstract database object.
@@ -177,14 +177,14 @@ bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr);
    `kbuf' specifies the pointer to the region of the key.
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true, else, it is false. */
-bool tcadbout(TCADB *adb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcadbout(TCADB *adb, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of an abstract database object.
    `adb' specifies the abstract database object.
    `kstr' specifies the string of the key.
    If successful, the return value is true, else, it is false. */
-bool tcadbout2(TCADB *adb, const char *kstr);
+EJDB_EXPORT bool tcadbout2(TCADB *adb, const char *kstr);
 
 
 /* Retrieve a record in an abstract database object.
@@ -199,7 +199,7 @@ bool tcadbout2(TCADB *adb, const char *kstr);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in an abstract database object.
@@ -209,7 +209,7 @@ void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp);
    `NULL' is returned if no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcadbget2(TCADB *adb, const char *kstr);
+EJDB_EXPORT char *tcadbget2(TCADB *adb, const char *kstr);
 
 
 /* Get the size of the value of a record in an abstract database object.
@@ -218,7 +218,7 @@ char *tcadbget2(TCADB *adb, const char *kstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz);
 
 
 /* Get the size of the value of a string record in an abstract database object.
@@ -226,14 +226,14 @@ int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcadbvsiz2(TCADB *adb, const char *kstr);
+EJDB_EXPORT int tcadbvsiz2(TCADB *adb, const char *kstr);
 
 
 /* Initialize the iterator of an abstract database object.
    `adb' specifies the abstract database object.
    If successful, the return value is true, else, it is false.
    The iterator is used in order to access the key of every record stored in a database. */
-bool tcadbiterinit(TCADB *adb);
+EJDB_EXPORT bool tcadbiterinit(TCADB *adb);
 
 
 /* Get the next key of the iterator of an abstract database object.
@@ -250,7 +250,7 @@ bool tcadbiterinit(TCADB *adb);
    However, it is not assured if updating the database is occurred while the iteration.  Besides,
    the order of this traversal access method is arbitrary, so it is not assured that the order of
    storing matches the one of the traversal access. */
-void *tcadbiternext(TCADB *adb, int *sp);
+EJDB_EXPORT void *tcadbiternext(TCADB *adb, int *sp);
 
 
 /* Get the next key string of the iterator of an abstract database object.
@@ -263,7 +263,7 @@ void *tcadbiternext(TCADB *adb, int *sp);
    database is occurred while the iteration.  Besides, the order of this traversal access method
    is arbitrary, so it is not assured that the order of storing matches the one of the traversal
    access. */
-char *tcadbiternext2(TCADB *adb);
+EJDB_EXPORT char *tcadbiternext2(TCADB *adb);
 
 
 /* Get forward matching keys in an abstract database object.
@@ -277,7 +277,7 @@ char *tcadbiternext2(TCADB *adb);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string keys in an abstract database object.
@@ -290,7 +290,7 @@ TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max);
 
 
 /* Add an integer to a record in an abstract database object.
@@ -301,7 +301,7 @@ TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max);
    If successful, the return value is the summation value, else, it is `INT_MIN'.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tcadbaddint(TCADB *adb, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tcadbaddint(TCADB *adb, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in an abstract database object.
@@ -312,13 +312,13 @@ int tcadbaddint(TCADB *adb, const void *kbuf, int ksiz, int num);
    If successful, the return value is the summation value, else, it is Not-a-Number.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tcadbadddouble(TCADB *adb, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tcadbadddouble(TCADB *adb, const void *kbuf, int ksiz, double num);
 
 
 /* Synchronize updated contents of an abstract database object with the file and the device.
    `adb' specifies the abstract database object.
    If successful, the return value is true, else, it is false. */
-bool tcadbsync(TCADB *adb);
+EJDB_EXPORT bool tcadbsync(TCADB *adb);
 
 
 /* Optimize the storage of an abstract database object.
@@ -328,13 +328,13 @@ bool tcadbsync(TCADB *adb);
    If successful, the return value is true, else, it is false.
    This function is useful to reduce the size of the database storage with data fragmentation by
    successive updating. */
-bool tcadboptimize(TCADB *adb, const char *params);
+EJDB_EXPORT bool tcadboptimize(TCADB *adb, const char *params);
 
 
 /* Remove all records of an abstract database object.
    `adb' specifies the abstract database object.
    If successful, the return value is true, else, it is false. */
-bool tcadbvanish(TCADB *adb);
+EJDB_EXPORT bool tcadbvanish(TCADB *adb);
 
 
 /* Copy the database file of an abstract database object.
@@ -346,7 +346,7 @@ bool tcadbvanish(TCADB *adb);
    The database file is assured to be kept synchronized and not modified while the copying or
    executing operation is in progress.  So, this function is useful to create a backup file of
    the database file. */
-bool tcadbcopy(TCADB *adb, const char *path);
+EJDB_EXPORT bool tcadbcopy(TCADB *adb, const char *path);
 
 
 /* Begin the transaction of an abstract database object.
@@ -357,14 +357,14 @@ bool tcadbcopy(TCADB *adb, const char *path);
    assumed if every database operation is performed in the transaction.  All updated regions are
    kept track of by write ahead logging while the transaction.  If the database is closed during
    transaction, the transaction is aborted implicitly. */
-bool tcadbtranbegin(TCADB *adb);
+EJDB_EXPORT bool tcadbtranbegin(TCADB *adb);
 
 
 /* Commit the transaction of an abstract database object.
    `adb' specifies the abstract database object.
    If successful, the return value is true, else, it is false.
    Update in the transaction is fixed when it is committed successfully. */
-bool tcadbtrancommit(TCADB *adb);
+EJDB_EXPORT bool tcadbtrancommit(TCADB *adb);
 
 
 /* Abort the transaction of an abstract database object.
@@ -372,7 +372,7 @@ bool tcadbtrancommit(TCADB *adb);
    If successful, the return value is true, else, it is false.
    Update in the transaction is discarded when it is aborted.  The state of the database is
    rollbacked to before transaction. */
-bool tcadbtranabort(TCADB *adb);
+EJDB_EXPORT bool tcadbtranabort(TCADB *adb);
 
 
 /* Get the file path of an abstract database object.
@@ -380,21 +380,21 @@ bool tcadbtranabort(TCADB *adb);
    The return value is the path of the database file or `NULL' if the object does not connect to
    any database.  "*" stands for on-memory hash database.  "+" stands for on-memory tree
    database. */
-const char *tcadbpath(TCADB *adb);
+EJDB_EXPORT const char *tcadbpath(TCADB *adb);
 
 
 /* Get the number of records of an abstract database object.
    `adb' specifies the abstract database object.
    The return value is the number of records or 0 if the object does not connect to any database
    instance. */
-uint64_t tcadbrnum(TCADB *adb);
+EJDB_EXPORT uint64_t tcadbrnum(TCADB *adb);
 
 
 /* Get the size of the database of an abstract database object.
    `adb' specifies the abstract database object.
    The return value is the size of the database or 0 if the object does not connect to any
    database instance. */
-uint64_t tcadbsize(TCADB *adb);
+EJDB_EXPORT uint64_t tcadbsize(TCADB *adb);
 
 
 /* Call a versatile function for miscellaneous operations of an abstract database object.
@@ -412,7 +412,7 @@ uint64_t tcadbsize(TCADB *adb);
    If successful, the return value is a list object of the result.  `NULL' is returned on failure.
    Because the object of the return value is created with the function `tclistnew', it
    should be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcadbmisc(TCADB *adb, const char *name, const TCLIST *args);
+EJDB_EXPORT TCLIST *tcadbmisc(TCADB *adb, const char *name, const TCLIST *args);
 
 
 
@@ -468,14 +468,14 @@ typedef bool (*ADBMAPPROC)(void *map, const char *kbuf, int ksiz, const char *vb
    `adb' specifies the abstract database object.
    `skel' specifies the extra database skeleton.
    If successful, the return value is true, else, it is false. */
-bool tcadbsetskel(TCADB *adb, ADBSKEL *skel);
+EJDB_EXPORT bool tcadbsetskel(TCADB *adb, ADBSKEL *skel);
 
 
 /* Set the multiple database skeleton to an abstract database object.
    `adb' specifies the abstract database object.
    `num' specifies the number of inner databases.
    If successful, the return value is true, else, it is false. */
-bool tcadbsetskelmulti(TCADB *adb, int num);
+EJDB_EXPORT bool tcadbsetskelmulti(TCADB *adb, int num);
 
 
 /* Get the open mode of an abstract database object.
@@ -483,14 +483,14 @@ bool tcadbsetskelmulti(TCADB *adb, int num);
    The return value is `ADBOVOID' for not opened database, `ADBOMDB' for on-memory hash database,
   `ADBONDB' for on-memory tree database, `ADBOHDB' for hash database, `ADBOBDB' for B+ tree
   database, `ADBOFDB' for fixed-length database, `ADBOTDB' for table database. */
-int tcadbomode(TCADB *adb);
+EJDB_EXPORT int tcadbomode(TCADB *adb);
 
 
 /* Get the concrete database object of an abstract database object.
    `adb' specifies the abstract database object.
    The return value is the concrete database object depend on the open mode or 0 if the object
    does not connect to any database instance. */
-void *tcadbreveal(TCADB *adb);
+EJDB_EXPORT void *tcadbreveal(TCADB *adb);
 
 
 /* Store a record into an abstract database object with a duplication handler.
@@ -504,7 +504,7 @@ void *tcadbreveal(TCADB *adb);
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false.
    This function does not work for the table database. */
-bool tcadbputproc(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tcadbputproc(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -514,7 +514,7 @@ bool tcadbputproc(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int
    `op' specifies an arbitrary pointer to be given as a parameter of the iterator function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tcadbforeach(TCADB *adb, TCITER iter, void *op);
+EJDB_EXPORT bool tcadbforeach(TCADB *adb, TCITER iter, void *op);
 
 
 /* Map records of an abstract database object into another B+ tree database.
@@ -528,7 +528,7 @@ bool tcadbforeach(TCADB *adb, TCITER iter, void *op);
    `csiz' specifies the size of the cache to sort emitted records.  If it is negative, the
    default size is specified.  The default size is 268435456.
    If successful, the return value is true, else, it is false. */
-bool tcadbmapbdb(TCADB *adb, TCLIST *keys, TCBDB *bdb, ADBMAPPROC proc, void *op, int64_t csiz);
+EJDB_EXPORT bool tcadbmapbdb(TCADB *adb, TCLIST *keys, TCBDB *bdb, ADBMAPPROC proc, void *op, int64_t csiz);
 
 
 /* Emit records generated by the mapping function into the result map.
@@ -537,7 +537,7 @@ bool tcadbmapbdb(TCADB *adb, TCLIST *keys, TCBDB *bdb, ADBMAPPROC proc, void *op
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false. */
-bool tcadbmapbdbemit(void *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
+EJDB_EXPORT bool tcadbmapbdbemit(void *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
 
 
 
index 3677559..73d5008 100644 (file)
@@ -612,8 +612,8 @@ static int procinform(const char *name){
     case ADBOSKEL: type = "skeleton database"; break;
   }
   printf("database type: %s\n", type);
-  printf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  printf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  printf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  printf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   if(!tcadbclose(adb)){
     printerr(adb);
     err = true;
index 943c406..355e64a 100644 (file)
@@ -43,7 +43,7 @@ typedef struct {                         // type of structure for remove thread
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -72,7 +72,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -310,8 +317,8 @@ static int procwrite(const char *name, int tnum, int rnum){
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -380,8 +387,8 @@ static int procread(const char *name, int tnum){
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -450,8 +457,8 @@ static int procremove(const char *name, int tnum){
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
index 254bba0..1cc4d9c 100644 (file)
@@ -123,12 +123,38 @@ static void iputchar(int c){
   putchar(c);
   fflush(stdout);
 }
-
-
 /* print error message of abstract database */
-static void eprint(TCADB *adb, int line, const char *func){
-  const char *path = adb ? tcadbpath(adb) : NULL;
-  fprintf(stderr, "%s: %s: %d: %s: error\n", g_progname, path ? path : "-", line, func);
+static void eprint(TCADB *adb, int line, const char *func) {
+    const char *path = adb ? tcadbpath(adb) : NULL;
+#ifdef _WIN32
+    DWORD winerrno = GetLastError();
+#endif
+    int stderrno = errno;
+#ifdef _WIN32
+    LPTSTR errorText = NULL;
+    if (winerrno > 0) {
+        DWORD ret = FormatMessage(
+                FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
+                NULL, winerrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & errorText, 0, NULL);
+        if (!ret) {
+            if (errorText) LocalFree(errorText);
+            errorText = NULL;
+        }
+    }
+    fprintf(stderr,
+            "ERROR:%s:%d:%s:%s:%d:%s:%d:%s\n",
+            g_progname, line,
+            func, (path ? path : "-"),
+            winerrno, (errorText ? errorText : "-"),
+            stderrno, (stderrno > 0 ? strerror(stderrno) : "-"));
+    if (errorText) LocalFree(errorText);
+#else
+    fprintf(stderr,
+            "ERROR:%s:%d:%s:%s:%d:%s\n",
+            g_progname, line,
+            func, (path ? path : "-"),
+            stderrno, strerror(stderrno));
+#endif
 }
 
 
@@ -410,8 +436,8 @@ static int procwrite(const char *name, int rnum){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -467,8 +493,8 @@ static int procread(const char *name){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -521,8 +547,8 @@ static int procremove(const char *name){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -576,8 +602,8 @@ static int procrcat(const char *name, int rnum){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -1078,8 +1104,8 @@ static int procmisc(const char *name, int rnum){
     eprint(adb, __LINE__, "tcadbforeach");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   if(!tcadbclose(adb)){
     eprint(adb, __LINE__, "tcadbclose");
@@ -1283,8 +1309,8 @@ static int procwicked(const char *name, int rnum){
     eprint(adb, __LINE__, "(validation)");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
-  iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcadbrnum(adb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcadbsize(adb));
   sysprint();
   tcmapdel(map);
   if(!tcadbclose(adb)){
@@ -1308,7 +1334,7 @@ static int proccompare(const char *name, int tnum, int rnum){
   TCMDB *mdb = tcmdbnew2(rnum / 2);
   TCNDB *ndb = tcndbnew();
   TCHDB *hdb = tchdbnew();
-  tchdbsetdbgfd(hdb, UINT16_MAX);
+  tchdbsetdbgfd(hdb, INVALID_HANDLE_VALUE);
   int hopts = 0;
   if(myrand(2) == 1) hopts |= HDBTLARGE;
   if(myrand(2) == 1) hopts |= HDBTBZIP;
@@ -1336,7 +1362,7 @@ static int proccompare(const char *name, int tnum, int rnum){
     err = true;
   }
   TCBDB *bdb = tcbdbnew();
-  tcbdbsetdbgfd(bdb, UINT16_MAX);
+  tcbdbsetdbgfd(bdb, INVALID_HANDLE_VALUE);
   int bopts = 0;
   if(myrand(2) == 1) bopts |= BDBTLARGE;
   if(myrand(2) == 1) bopts |= BDBTBZIP;
index 97412e1..303c12b 100644 (file)
@@ -380,8 +380,8 @@ static void sethtmlheader(PARAMS *params, TCXSTR *obuf, TCADB *db){
 /* set the footer of HTML */
 static void sethtmlfooter(PARAMS *params, TCXSTR *obuf, TCADB *db){
   XP("<hr />\n");
-  XP("<div>record number: %lld</div>\n", (long long)tcadbrnum(db));
-  XP("<div>size: %lld</div>\n", (long long)tcadbsize(db));
+  XP("<div>record number: %" PRIdMAX "</div>\n", (long long)tcadbrnum(db));
+  XP("<div>size: %" PRIdMAX "</div>\n", (long long)tcadbsize(db));
   XP("</body>\n");
   XP("\n");
   XP("</html>\n");
index b056e70..b725057 100644 (file)
@@ -211,7 +211,6 @@ int tcbdbecode(TCBDB *bdb){
 /* Set mutual exclusion control of a B+ tree database object for threading. */
 bool tcbdbsetmutex(TCBDB *bdb){
   assert(bdb);
-  if(!TCUSEPTHREAD) return true;
   if(bdb->mmtx || bdb->open){
     tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
@@ -818,7 +817,7 @@ bool tcbdbcopy(TCBDB *bdb, const char *path){
 /* Begin the transaction of a B+ tree database object. */
 bool tcbdbtranbegin(TCBDB *bdb){
   assert(bdb);
-  for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){
+  for(double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2){
     if(!BDBLOCKMETHOD(bdb, true)) return false;
     if(!bdb->open || !bdb->wmode){
       tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -839,7 +838,8 @@ bool tcbdbtranbegin(TCBDB *bdb){
     return false;
   }
   bdb->tran = true;
-  TCMEMDUP(bdb->rbopaque, bdb->opaque, BDBOPAQUESIZ);
+  TCMALLOC(bdb->rbopaque, BDBOPAQUESIZ);
+  tchdbreadopaque(bdb->hdb, bdb->rbopaque, 0, BDBOPAQUESIZ);
   BDBUNLOCKMETHOD(bdb);
   return true;
 }
@@ -880,7 +880,7 @@ bool tcbdbtranabort(TCBDB *bdb){
     return false;
   }
   tcbdbcachepurge(bdb);
-  memcpy(bdb->opaque, bdb->rbopaque, BDBOPAQUESIZ);
+  tchdbwriteopaque(bdb->hdb, bdb->rbopaque, 0, BDBOPAQUESIZ);
   tcbdbloadmeta(bdb);
   TCFREE(bdb->rbopaque);
   bdb->tran = false;
@@ -1311,14 +1311,14 @@ void tcbdbsetecode(TCBDB *bdb, int ecode, const char *filename, int line, const
 
 
 /* Set the file descriptor for debugging output. */
-void tcbdbsetdbgfd(TCBDB *bdb, int fd){
-  assert(bdb && fd >= 0);
+void tcbdbsetdbgfd(TCBDB *bdb, HANDLE fd){
+  assert(bdb && !INVALIDHANDLE(fd));
   tchdbsetdbgfd(bdb->hdb, fd);
 }
 
 
 /* Get the file descriptor for debugging output. */
-int tcbdbdbgfd(TCBDB *bdb){
+HANDLE tcbdbdbgfd(TCBDB *bdb){
   assert(bdb);
   return tchdbdbgfd(bdb->hdb);
 }
@@ -1490,17 +1490,6 @@ uint8_t tcbdbopts(TCBDB *bdb){
 }
 
 
-/* Get the pointer to the opaque field of a B+ tree database object. */
-char *tcbdbopaque(TCBDB *bdb){
-  assert(bdb);
-  if(!bdb->open){
-    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
-    return NULL;
-  }
-  return bdb->opaque + BDBOPAQUESIZ;
-}
-
-
 /* Get the number of used elements of the bucket array of a B+ tree database object. */
 uint64_t tcbdbbnumused(TCBDB *bdb){
   assert(bdb);
@@ -1721,7 +1710,6 @@ static void tcbdbclear(TCBDB *bdb){
   bdb->mmtx = NULL;
   bdb->cmtx = NULL;
   bdb->hdb = NULL;
-  bdb->opaque = NULL;
   bdb->open = false;
   bdb->wmode = false;
   bdb->lmemb = BDBDEFLMEMB;
@@ -1770,8 +1758,9 @@ static void tcbdbclear(TCBDB *bdb){
    `bdb' specifies the B+ tree database object. */
 static void tcbdbdumpmeta(TCBDB *bdb){
   assert(bdb);
-  memset(bdb->opaque, 0, 64);
-  char *wp = bdb->opaque;
+  char odata[BDBOPAQUESIZ];
+  memset(odata, 0, BDBOPAQUESIZ);
+  char *wp = odata;
   if(bdb->cmp == tccmplexical){
     *(uint8_t *)(wp++) = 0x0;
   } else if(bdb->cmp == tccmpdecimal){
@@ -1818,13 +1807,16 @@ static void tcbdbdumpmeta(TCBDB *bdb){
   llnum = TCHTOILL(llnum);
   memcpy(wp, &llnum, sizeof(llnum));
   wp += sizeof(llnum);
+  tchdbwriteopaque(bdb->hdb, odata, 0, BDBOPAQUESIZ);
 }
 
 
 /* Deserialize meta data from the opaque field.
    `bdb' specifies the B+ tree database object. */
 static void tcbdbloadmeta(TCBDB *bdb){
-  const char *rp = bdb->opaque;
+  char odata[BDBOPAQUESIZ];
+  tchdbreadopaque(bdb->hdb, odata, 0, BDBOPAQUESIZ);
+  const char *rp = odata;
   uint8_t cnum = *(uint8_t *)(rp++);
   if(cnum == 0x0){
     bdb->cmp = tccmplexical;
@@ -1956,7 +1948,7 @@ static bool tcbdbleafsave(TCBDB *bdb, BDBLEAF *leaf){
     }
   }
   bool err = false;
-  step = sprintf(hbuf, "%llx", (unsigned long long)leaf->id);
+  step = sprintf(hbuf, "%" PRIxMAX "", (unsigned long long)leaf->id);
   if(ln < 1 && !tchdbout(bdb->hdb, hbuf, step) && tchdbecode(bdb->hdb) != TCENOREC)
     err = true;
   if(!leaf->dead && !tchdbput(bdb->hdb, hbuf, step, TCXSTRPTR(rbuf), TCXSTRSIZE(rbuf)))
@@ -1985,7 +1977,7 @@ static BDBLEAF *tcbdbleafload(TCBDB *bdb, uint64_t id){
   TCDODEBUG(bdb->cnt_loadleaf++);
   char hbuf[(sizeof(uint64_t)+1)*3];
   int step;
-  step = sprintf(hbuf, "%llx", (unsigned long long)id);
+  step = sprintf(hbuf, "%" PRIxMAX "", (unsigned long long)id);
   char *rbuf = NULL;
   char wbuf[BDBPAGEBUFSIZ];
   const char *rp = NULL;
@@ -2104,7 +2096,7 @@ static bool tcbdbleafcheck(TCBDB *bdb, uint64_t id){
   if(clk) BDBUNLOCKCACHE(bdb);
   if(leaf) return true;
   char hbuf[(sizeof(uint64_t)+1)*3];
-  int step = sprintf(hbuf, "%llx", (unsigned long long)id);
+  int step = sprintf(hbuf, "%" PRIxMAX "", (unsigned long long)id);
   return tchdbvsiz(bdb->hdb, hbuf, step) > 0;
 }
 
@@ -2503,7 +2495,7 @@ static bool tcbdbnodesave(TCBDB *bdb, BDBNODE *node){
     TCXSTRCAT(rbuf, ebuf, idx->ksiz);
   }
   bool err = false;
-  step = sprintf(hbuf, "#%llx", (unsigned long long)(node->id - BDBNODEIDBASE));
+  step = sprintf(hbuf, "#%" PRIxMAX "", (unsigned long long)(node->id - BDBNODEIDBASE));
   if(ln < 1 && !tchdbout(bdb->hdb, hbuf, step) && tchdbecode(bdb->hdb) != TCENOREC)
     err = true;
   if(!node->dead && !tchdbput(bdb->hdb, hbuf, step, TCXSTRPTR(rbuf), TCXSTRSIZE(rbuf)))
@@ -2532,7 +2524,7 @@ static BDBNODE *tcbdbnodeload(TCBDB *bdb, uint64_t id){
   TCDODEBUG(bdb->cnt_loadnode++);
   char hbuf[(sizeof(uint64_t)+1)*2];
   int step;
-  step = sprintf(hbuf, "#%llx", (unsigned long long)(id - BDBNODEIDBASE));
+  step = sprintf(hbuf, "#%" PRIxMAX "", (unsigned long long)(id - BDBNODEIDBASE));
   char *rbuf = NULL;
   char wbuf[BDBPAGEBUFSIZ];
   const char *rp = NULL;
@@ -2983,7 +2975,6 @@ static bool tcbdbopenimpl(TCBDB *bdb, const char *path, int omode){
   bdb->lnum = 0;
   bdb->nnum = 0;
   bdb->rnum = 0;
-  bdb->opaque = tchdbopaque(bdb->hdb);
   bdb->leafc = tcmapnew2(bdb->lcnum * 2 + 1);
   bdb->nodec = tcmapnew2(bdb->ncnum * 2 + 1);
   if(bdb->wmode && tchdbrnum(bdb->hdb) < 1){
@@ -3049,7 +3040,7 @@ static bool tcbdbcloseimpl(TCBDB *bdb){
   bool err = false;
   if(bdb->tran){
     tcbdbcachepurge(bdb);
-    memcpy(bdb->opaque, bdb->rbopaque, BDBOPAQUESIZ);
+    tchdbwriteopaque(bdb->hdb, bdb->rbopaque, 0, BDBOPAQUESIZ);
     tcbdbloadmeta(bdb);
     TCFREE(bdb->rbopaque);
     bdb->tran = false;
@@ -3451,11 +3442,12 @@ static bool tcbdbrangefwm(TCBDB *bdb, const char *pbuf, int psiz, int max, TCLIS
 static bool tcbdboptimizeimpl(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
                               int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
   assert(bdb);
-  const char *path = tchdbpath(bdb->hdb);
-  char *tpath = tcsprintf("%s%ctmp%c%llu", path, MYEXTCHR, MYEXTCHR, tchdbinode(bdb->hdb));
+  char *opath = tcstrdup(tchdbpath(bdb->hdb));
+  char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", opath, MYEXTCHR, MYEXTCHR, tchdbinode(bdb->hdb));
+  int omode = (tchdbomode(bdb->hdb) & ~BDBOCREAT) & ~BDBOTRUNC;
   TCBDB *tbdb = tcbdbnew();
-  int dbgfd = tchdbdbgfd(bdb->hdb);
-  if(dbgfd >= 0) tcbdbsetdbgfd(tbdb, dbgfd);
+  HANDLE dbgfd = tchdbdbgfd(bdb->hdb);
+  if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(tbdb, dbgfd);
   tcbdbsetcmpfunc(tbdb, bdb->cmp, bdb->cmpop);
   TCCODEC enc, dec;
   void *encop, *decop;
@@ -3476,13 +3468,13 @@ static bool tcbdboptimizeimpl(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
   bdb->ncnum = BDBCACHEOUT * 2;
   tbdb->lcnum = BDBLEVELMAX;
   tbdb->ncnum = BDBCACHEOUT * 2;
-  if(!tcbdbopen(tbdb, tpath, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
-    tcbdbsetecode(bdb, tcbdbecode(tbdb), __FILE__, __LINE__, __func__);
+  if(!tcbdbopen(tbdb, tpath, BDBOWRITER | BDBOCREAT | BDBOTRUNC) ||
+          !tchdbcopyopaque(tbdb->hdb, bdb->hdb, 0, -1)){
     tcbdbdel(tbdb);
     TCFREE(tpath);
+    TCFREE(opath);
     return false;
   }
-  memcpy(tcbdbopaque(tbdb), tcbdbopaque(bdb), BDBLEFTOPQSIZ);
   bool err = false;
   BDBCUR *cur = tcbdbcurnew(bdb);
   tcbdbcurfirstimpl(cur);
@@ -3505,24 +3497,30 @@ static bool tcbdboptimizeimpl(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
   bdb->lcnum = lcnum;
   bdb->ncnum = ncnum;
   tcbdbdel(tbdb);
-  if(unlink(path) == -1){
+  if(err){
+    TCFREE(tpath);
+    TCFREE(opath);
+    return false;
+  }
+  if(!tcbdbcloseimpl(bdb)){
+    TCFREE(opath);
+    return false;
+  }
+  if(unlink(opath)){
     tcbdbsetecode(bdb, TCEUNLINK, __FILE__, __LINE__, __func__);
     err = true;
   }
-  if(rename(tpath, path) == -1){
+  if(rename(tpath, opath)){
     tcbdbsetecode(bdb, TCERENAME, __FILE__, __LINE__, __func__);
     err = true;
   }
   TCFREE(tpath);
-  if(err) return false;
-  tpath = tcstrdup(path);
-  int omode = (tchdbomode(bdb->hdb) & ~BDBOCREAT) & ~BDBOTRUNC;
-  if(!tcbdbcloseimpl(bdb)){
-    TCFREE(tpath);
+  if(err){
+         TCFREE(opath);
     return false;
   }
-  bool rv = tcbdbopenimpl(bdb, tpath, omode);
-  TCFREE(tpath);
+  bool rv = tcbdbopenimpl(bdb, opath, omode);
+  TCFREE(opath);
   return rv;
 }
 
@@ -4082,27 +4080,28 @@ static bool tcbdbforeachimpl(TCBDB *bdb, TCITER iter, void *op){
    `bdb' specifies the B+ tree database object. */
 void tcbdbprintmeta(TCBDB *bdb){
   assert(bdb);
-  int dbgfd = tchdbdbgfd(bdb->hdb);
-  if(dbgfd < 0) return;
-  if(dbgfd == UINT16_MAX) dbgfd = 1;
+  HANDLE dbgfd = tchdbdbgfd(bdb->hdb);
+  if (INVALIDHANDLE(dbgfd)) {
+      dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[BDBPAGEBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "META:");
   wp += sprintf(wp, " mmtx=%p", (void *)bdb->mmtx);
   wp += sprintf(wp, " cmtx=%p", (void *)bdb->cmtx);
   wp += sprintf(wp, " hdb=%p", (void *)bdb->hdb);
-  wp += sprintf(wp, " opaque=%p", (void *)bdb->opaque);
+  //wp += sprintf(wp, " opaque=%p", (void *)bdb->opaque);
   wp += sprintf(wp, " open=%d", bdb->open);
   wp += sprintf(wp, " wmode=%d", bdb->wmode);
   wp += sprintf(wp, " lmemb=%u", bdb->lmemb);
   wp += sprintf(wp, " nmemb=%u", bdb->nmemb);
   wp += sprintf(wp, " opts=%u", bdb->opts);
-  wp += sprintf(wp, " root=%llx", (unsigned long long)bdb->root);
-  wp += sprintf(wp, " first=%llx", (unsigned long long)bdb->first);
-  wp += sprintf(wp, " last=%llx", (unsigned long long)bdb->last);
-  wp += sprintf(wp, " lnum=%llu", (unsigned long long)bdb->lnum);
-  wp += sprintf(wp, " nnum=%llu", (unsigned long long)bdb->nnum);
-  wp += sprintf(wp, " rnum=%llu", (unsigned long long)bdb->rnum);
+  wp += sprintf(wp, " root=%" PRIxMAX "", (unsigned long long)bdb->root);
+  wp += sprintf(wp, " first=%" PRIxMAX "", (unsigned long long)bdb->first);
+  wp += sprintf(wp, " last=%" PRIxMAX "", (unsigned long long)bdb->last);
+  wp += sprintf(wp, " lnum=%" PRIuMAX "", (unsigned long long)bdb->lnum);
+  wp += sprintf(wp, " nnum=%" PRIuMAX "", (unsigned long long)bdb->nnum);
+  wp += sprintf(wp, " rnum=%" PRIuMAX "", (unsigned long long)bdb->rnum);
   wp += sprintf(wp, " leafc=%p", (void *)bdb->leafc);
   wp += sprintf(wp, " nodec=%p", (void *)bdb->nodec);
   wp += sprintf(wp, " cmp=%p", (void *)(intptr_t)bdb->cmp);
@@ -4111,21 +4110,21 @@ void tcbdbprintmeta(TCBDB *bdb){
   wp += sprintf(wp, " ncnum=%u", bdb->ncnum);
   wp += sprintf(wp, " lsmax=%u", bdb->lsmax);
   wp += sprintf(wp, " lschk=%u", bdb->lschk);
-  wp += sprintf(wp, " capnum=%llu", (unsigned long long)bdb->capnum);
+  wp += sprintf(wp, " capnum=%" PRIuMAX "", (unsigned long long)bdb->capnum);
   wp += sprintf(wp, " hist=%p", (void *)bdb->hist);
   wp += sprintf(wp, " hnum=%d", bdb->hnum);
-  wp += sprintf(wp, " hleaf=%llu", (unsigned long long)bdb->hleaf);
-  wp += sprintf(wp, " lleaf=%llu", (unsigned long long)bdb->lleaf);
+  wp += sprintf(wp, " hleaf=%" PRIuMAX "", (unsigned long long)bdb->hleaf);
+  wp += sprintf(wp, " lleaf=%" PRIuMAX "", (unsigned long long)bdb->lleaf);
   wp += sprintf(wp, " tran=%d", bdb->tran);
-  wp += sprintf(wp, " rbopaque=%p", (void *)bdb->rbopaque);
-  wp += sprintf(wp, " clock=%llu", (unsigned long long)bdb->clock);
-  wp += sprintf(wp, " cnt_saveleaf=%lld", (long long)bdb->cnt_saveleaf);
-  wp += sprintf(wp, " cnt_loadleaf=%lld", (long long)bdb->cnt_loadleaf);
-  wp += sprintf(wp, " cnt_killleaf=%lld", (long long)bdb->cnt_killleaf);
-  wp += sprintf(wp, " cnt_adjleafc=%lld", (long long)bdb->cnt_adjleafc);
-  wp += sprintf(wp, " cnt_savenode=%lld", (long long)bdb->cnt_savenode);
-  wp += sprintf(wp, " cnt_loadnode=%lld", (long long)bdb->cnt_loadnode);
-  wp += sprintf(wp, " cnt_adjnodec=%lld", (long long)bdb->cnt_adjnodec);
+  //wp += sprintf(wp, " rbopaque=%p", (void *)bdb->rbopaque);
+  wp += sprintf(wp, " clock=%" PRIuMAX "", (unsigned long long)bdb->clock);
+  wp += sprintf(wp, " cnt_saveleaf=%" PRIdMAX "", (long long)bdb->cnt_saveleaf);
+  wp += sprintf(wp, " cnt_loadleaf=%" PRIdMAX "", (long long)bdb->cnt_loadleaf);
+  wp += sprintf(wp, " cnt_killleaf=%" PRIdMAX "", (long long)bdb->cnt_killleaf);
+  wp += sprintf(wp, " cnt_adjleafc=%" PRIdMAX "", (long long)bdb->cnt_adjleafc);
+  wp += sprintf(wp, " cnt_savenode=%" PRIdMAX "", (long long)bdb->cnt_savenode);
+  wp += sprintf(wp, " cnt_loadnode=%" PRIdMAX "", (long long)bdb->cnt_loadnode);
+  wp += sprintf(wp, " cnt_adjnodec=%" PRIdMAX "", (long long)bdb->cnt_adjnodec);
   *(wp++) = '\n';
   tcwrite(dbgfd, buf, wp - buf);
 }
@@ -4136,17 +4135,18 @@ void tcbdbprintmeta(TCBDB *bdb){
    `leaf' specifies the leaf object. */
 void tcbdbprintleaf(TCBDB *bdb, BDBLEAF *leaf){
   assert(bdb && leaf);
-  int dbgfd = tchdbdbgfd(bdb->hdb);
+  HANDLE dbgfd = tchdbdbgfd(bdb->hdb);
   TCPTRLIST *recs = leaf->recs;
-  if(dbgfd < 0) return;
-  if(dbgfd == UINT16_MAX) dbgfd = 1;
+  if(INVALIDHANDLE(dbgfd)) {
+      dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[BDBPAGEBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "LEAF:");
-  wp += sprintf(wp, " id:%llx", (unsigned long long)leaf->id);
+  wp += sprintf(wp, " id:%" PRIxMAX "", (unsigned long long)leaf->id);
   wp += sprintf(wp, " size:%u", leaf->size);
-  wp += sprintf(wp, " prev:%llx", (unsigned long long)leaf->prev);
-  wp += sprintf(wp, " next:%llx", (unsigned long long)leaf->next);
+  wp += sprintf(wp, " prev:%" PRIxMAX "", (unsigned long long)leaf->prev);
+  wp += sprintf(wp, " next:%" PRIxMAX "", (unsigned long long)leaf->next);
   wp += sprintf(wp, " dirty:%d", leaf->dirty);
   wp += sprintf(wp, " dead:%d", leaf->dead);
   wp += sprintf(wp, " rnum:%d", TCPTRLISTNUM(recs));
@@ -4174,15 +4174,16 @@ void tcbdbprintleaf(TCBDB *bdb, BDBLEAF *leaf){
    `node' specifies the node object. */
 void tcbdbprintnode(TCBDB *bdb, BDBNODE *node){
   assert(bdb && node);
-  int dbgfd = tchdbdbgfd(bdb->hdb);
+  HANDLE dbgfd = tchdbdbgfd(bdb->hdb);
   TCPTRLIST *idxs = node->idxs;
-  if(dbgfd < 0) return;
-  if(dbgfd == UINT16_MAX) dbgfd = 1;
+  if(INVALIDHANDLE(dbgfd)) {
+      dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[BDBPAGEBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "NODE:");
-  wp += sprintf(wp, " id:%llx", (unsigned long long)node->id);
-  wp += sprintf(wp, " heir:%llx", (unsigned long long)node->heir);
+  wp += sprintf(wp, " id:%" PRIxMAX "", (unsigned long long)node->id);
+  wp += sprintf(wp, " heir:%" PRIxMAX "", (unsigned long long)node->heir);
   wp += sprintf(wp, " dirty:%d", node->dirty);
   wp += sprintf(wp, " dead:%d", node->dead);
   wp += sprintf(wp, " rnum:%d", TCPTRLISTNUM(idxs));
@@ -4192,7 +4193,7 @@ void tcbdbprintnode(TCBDB *bdb, BDBNODE *node){
     wp = buf;
     BDBIDX *idx = TCPTRLISTVAL(idxs, i);
     char *ebuf = (char *)idx + sizeof(*idx);
-    wp += sprintf(wp, " [%llx:%s]", (unsigned long long)idx->pid, ebuf);
+    wp += sprintf(wp, " [%" PRIxMAX ":%s]", (unsigned long long)idx->pid, ebuf);
   }
   *(wp++) = '\n';
   tcwrite(dbgfd, buf, wp - buf);
index da29c9d..940df67 100644 (file)
@@ -41,7 +41,6 @@ typedef struct {                         /* type of structure for a B+ tree data
   void *mmtx;                            /* mutex for method */
   void *cmtx;                            /* mutex for cache */
   TCHDB *hdb;                            /* internal database object */
-  char *opaque;                          /* opaque buffer */
   bool open;                             /* whether the internal database is opened */
   bool wmode;                            /* whether to be writable */
   uint32_t lmemb;                        /* number of members in each leaf */
@@ -119,19 +118,19 @@ enum {                                   /* enumeration for cursor put mode */
 /* Get the message string corresponding to an error code.
    `ecode' specifies the error code.
    The return value is the message string of the error code. */
-const char *tcbdberrmsg(int ecode);
+EJDB_EXPORT const char *tcbdberrmsg(int ecode);
 
 
 /* Create a B+ tree database object.
    The return value is the new B+ tree database object. */
-TCBDB *tcbdbnew(void);
+EJDB_EXPORT TCBDB *tcbdbnew(void);
 
 
 /* Delete a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    If the database is not closed, it is closed implicitly.  Note that the deleted object and its
    derivatives can not be used anymore. */
-void tcbdbdel(TCBDB *bdb);
+EJDB_EXPORT void tcbdbdel(TCBDB *bdb);
 
 
 /* Get the last happened error code of a B+ tree database object.
@@ -146,7 +145,7 @@ void tcbdbdel(TCBDB *bdb);
    for unlink error, `TCERENAME' for rename error, `TCEMKDIR' for mkdir error, `TCERMDIR' for
    rmdir error, `TCEKEEP' for existing record, `TCENOREC' for no record found, and `TCEMISC' for
    miscellaneous error. */
-int tcbdbecode(TCBDB *bdb);
+EJDB_EXPORT int tcbdbecode(TCBDB *bdb);
 
 
 /* Set mutual exclusion control of a B+ tree database object for threading.
@@ -154,7 +153,7 @@ int tcbdbecode(TCBDB *bdb);
    If successful, the return value is true, else, it is false.
    Note that the mutual exclusion control is needed if the object is shared by plural threads and
    this function should be called before the database is opened. */
-bool tcbdbsetmutex(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbsetmutex(TCBDB *bdb);
 
 
 /* Set the custom comparison function of a B+ tree database object.
@@ -172,7 +171,7 @@ bool tcbdbsetmutex(TCBDB *bdb);
    `tctccmplexical' (dafault), `tctccmpdecimal', `tctccmpint32', and `tctccmpint64' are built-in.
    Note that the comparison function should be set before the database is opened.  Moreover,
    user-defined comparison functions should be set every time the database is being opened. */
-bool tcbdbsetcmpfunc(TCBDB *bdb, TCCMP cmp, void *cmpop);
+EJDB_EXPORT bool tcbdbsetcmpfunc(TCBDB *bdb, TCCMP cmp, void *cmpop);
 
 
 /* Set the tuning parameters of a B+ tree database object.
@@ -194,7 +193,7 @@ bool tcbdbsetcmpfunc(TCBDB *bdb, TCCMP cmp, void *cmpop);
    BZIP2 encoding, `BDBTTCBS' specifies that each page is compressed with TCBS encoding.
    If successful, the return value is true, else, it is false.
    Note that the tuning parameters should be set before the database is opened. */
-bool tcbdbtune(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
+EJDB_EXPORT bool tcbdbtune(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
                int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
@@ -206,7 +205,7 @@ bool tcbdbtune(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
    the default value is specified.  The default value is 512.
    If successful, the return value is true, else, it is false.
    Note that the caching parameters should be set before the database is opened. */
-bool tcbdbsetcache(TCBDB *bdb, int32_t lcnum, int32_t ncnum);
+EJDB_EXPORT bool tcbdbsetcache(TCBDB *bdb, int32_t lcnum, int32_t ncnum);
 
 
 /* Set the size of the extra mapped memory of a B+ tree database object.
@@ -215,7 +214,7 @@ bool tcbdbsetcache(TCBDB *bdb, int32_t lcnum, int32_t ncnum);
    mapped memory is disabled.  It is disabled by default.
    If successful, the return value is true, else, it is false.
    Note that the mapping parameters should be set before the database is opened. */
-bool tcbdbsetxmsiz(TCBDB *bdb, int64_t xmsiz);
+EJDB_EXPORT bool tcbdbsetxmsiz(TCBDB *bdb, int64_t xmsiz);
 
 
 /* Set the unit step number of auto defragmentation of a B+ tree database object.
@@ -224,7 +223,7 @@ bool tcbdbsetxmsiz(TCBDB *bdb, int64_t xmsiz);
    is disabled.  It is disabled by default.
    If successful, the return value is true, else, it is false.
    Note that the defragmentation parameter should be set before the database is opened. */
-bool tcbdbsetdfunit(TCBDB *bdb, int32_t dfunit);
+EJDB_EXPORT bool tcbdbsetdfunit(TCBDB *bdb, int32_t dfunit);
 
 
 /* Open a database file and connect a B+ tree database object.
@@ -238,7 +237,7 @@ bool tcbdbsetdfunit(TCBDB *bdb, int32_t dfunit);
    bitwise-or: `BDBONOLCK', which means it opens the database file without file locking, or
    `BDBOLCKNB', which means locking is performed without blocking.
    If successful, the return value is true, else, it is false. */
-bool tcbdbopen(TCBDB *bdb, const char *path, int omode);
+EJDB_EXPORT bool tcbdbopen(TCBDB *bdb, const char *path, int omode);
 
 
 /* Close a B+ tree database object.
@@ -246,7 +245,7 @@ bool tcbdbopen(TCBDB *bdb, const char *path, int omode);
    If successful, the return value is true, else, it is false.
    Update of a database is assured to be written when the database is closed.  If a writer opens
    a database but does not close it appropriately, the database will be broken. */
-bool tcbdbclose(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbclose(TCBDB *bdb);
 
 
 /* Store a record into a B+ tree database object.
@@ -257,7 +256,7 @@ bool tcbdbclose(TCBDB *bdb);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tcbdbput(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcbdbput(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a B+ tree database object.
@@ -266,7 +265,7 @@ bool tcbdbput(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tcbdbput2(TCBDB *bdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcbdbput2(TCBDB *bdb, const char *kstr, const char *vstr);
 
 
 /* Store a new record into a B+ tree database object.
@@ -277,7 +276,7 @@ bool tcbdbput2(TCBDB *bdb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcbdbputkeep(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcbdbputkeep(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into a B+ tree database object.
@@ -286,7 +285,7 @@ bool tcbdbputkeep(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcbdbputkeep2(TCBDB *bdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcbdbputkeep2(TCBDB *bdb, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the existing record in a B+ tree database object.
@@ -297,7 +296,7 @@ bool tcbdbputkeep2(TCBDB *bdb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tcbdbputcat(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcbdbputcat(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string value at the end of the existing record in a B+ tree database object.
@@ -306,7 +305,7 @@ bool tcbdbputcat(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int v
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tcbdbputcat2(TCBDB *bdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcbdbputcat2(TCBDB *bdb, const char *kstr, const char *vstr);
 
 
 /* Store a record into a B+ tree database object with allowing duplication of keys.
@@ -318,7 +317,7 @@ bool tcbdbputcat2(TCBDB *bdb, const char *kstr, const char *vstr);
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, the new record is placed after the
    existing one. */
-bool tcbdbputdup(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcbdbputdup(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a B+ tree database object with allowing duplication of keys.
@@ -328,7 +327,7 @@ bool tcbdbputdup(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int v
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, the new record is placed after the
    existing one. */
-bool tcbdbputdup2(TCBDB *bdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcbdbputdup2(TCBDB *bdb, const char *kstr, const char *vstr);
 
 
 /* Store records into a B+ tree database object with allowing duplication of keys.
@@ -339,7 +338,7 @@ bool tcbdbputdup2(TCBDB *bdb, const char *kstr, const char *vstr);
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, the new records are placed after the
    existing one. */
-bool tcbdbputdup3(TCBDB *bdb, const void *kbuf, int ksiz, const TCLIST *vals);
+EJDB_EXPORT bool tcbdbputdup3(TCBDB *bdb, const void *kbuf, int ksiz, const TCLIST *vals);
 
 
 /* Remove a record of a B+ tree database object.
@@ -348,7 +347,7 @@ bool tcbdbputdup3(TCBDB *bdb, const void *kbuf, int ksiz, const TCLIST *vals);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true, else, it is false.
    If the key of duplicated records is specified, the first one is selected. */
-bool tcbdbout(TCBDB *bdb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcbdbout(TCBDB *bdb, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of a B+ tree database object.
@@ -356,7 +355,7 @@ bool tcbdbout(TCBDB *bdb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true, else, it is false.
    If the key of duplicated records is specified, the first one is selected. */
-bool tcbdbout2(TCBDB *bdb, const char *kstr);
+EJDB_EXPORT bool tcbdbout2(TCBDB *bdb, const char *kstr);
 
 
 /* Remove records of a B+ tree database object.
@@ -365,7 +364,7 @@ bool tcbdbout2(TCBDB *bdb, const char *kstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true, else, it is false.
    If the key of duplicated records is specified, all of them are removed. */
-bool tcbdbout3(TCBDB *bdb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcbdbout3(TCBDB *bdb, const void *kbuf, int ksiz);
 
 
 /* Retrieve a record in a B+ tree database object.
@@ -381,7 +380,7 @@ bool tcbdbout3(TCBDB *bdb, const void *kbuf, int ksiz);
    value can be treated as a character string.  Because the region of the return value is
    allocated with the `malloc' call, it should be released with the `free' call when it is no
    longer in use. */
-void *tcbdbget(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcbdbget(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in a B+ tree database object.
@@ -392,7 +391,7 @@ void *tcbdbget(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
    If the key of duplicated records is specified, the first one is selected.  Because the region
    of the return value is allocated with the `malloc' call, it should be released with the `free'
    call when it is no longer in use. */
-char *tcbdbget2(TCBDB *bdb, const char *kstr);
+EJDB_EXPORT char *tcbdbget2(TCBDB *bdb, const char *kstr);
 
 
 /* Retrieve a record in a B+ tree database object as a volatile buffer.
@@ -408,7 +407,7 @@ char *tcbdbget2(TCBDB *bdb, const char *kstr);
    value can be treated as a character string.  Because the region of the return value is
    volatile and it may be spoiled by another operation of the database, the data should be copied
    into another involatile buffer immediately. */
-const void *tcbdbget3(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT const void *tcbdbget3(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve records in a B+ tree database object.
@@ -419,7 +418,7 @@ const void *tcbdbget3(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
    `NULL' is returned if no record corresponds.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbget4(TCBDB *bdb, const void *kbuf, int ksiz);
+EJDB_EXPORT TCLIST *tcbdbget4(TCBDB *bdb, const void *kbuf, int ksiz);
 
 
 /* Get the number of records corresponding a key in a B+ tree database object.
@@ -427,14 +426,14 @@ TCLIST *tcbdbget4(TCBDB *bdb, const void *kbuf, int ksiz);
    `kbuf' specifies the pointer to the region of the key.
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is the number of the corresponding records, else, it is 0. */
-int tcbdbvnum(TCBDB *bdb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tcbdbvnum(TCBDB *bdb, const void *kbuf, int ksiz);
 
 
 /* Get the number of records corresponding a string key in a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    `kstr' specifies the string of the key.
    If successful, the return value is the number of the corresponding records, else, it is 0. */
-int tcbdbvnum2(TCBDB *bdb, const char *kstr);
+EJDB_EXPORT int tcbdbvnum2(TCBDB *bdb, const char *kstr);
 
 
 /* Get the size of the value of a record in a B+ tree database object.
@@ -444,7 +443,7 @@ int tcbdbvnum2(TCBDB *bdb, const char *kstr);
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1.
    If the key of duplicated records is specified, the first one is selected. */
-int tcbdbvsiz(TCBDB *bdb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tcbdbvsiz(TCBDB *bdb, const void *kbuf, int ksiz);
 
 
 /* Get the size of the value of a string record in a B+ tree database object.
@@ -453,7 +452,7 @@ int tcbdbvsiz(TCBDB *bdb, const void *kbuf, int ksiz);
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1.
    If the key of duplicated records is specified, the first one is selected. */
-int tcbdbvsiz2(TCBDB *bdb, const char *kstr);
+EJDB_EXPORT int tcbdbvsiz2(TCBDB *bdb, const char *kstr);
 
 
 /* Get keys of ranged records in a B+ tree database object.
@@ -472,7 +471,7 @@ int tcbdbvsiz2(TCBDB *bdb, const char *kstr);
    does never fail.  It returns an empty list even if no record corresponds.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbrange(TCBDB *bdb, const void *bkbuf, int bksiz, bool binc,
+EJDB_EXPORT TCLIST *tcbdbrange(TCBDB *bdb, const void *bkbuf, int bksiz, bool binc,
                    const void *ekbuf, int eksiz, bool einc, int max);
 
 
@@ -490,7 +489,7 @@ TCLIST *tcbdbrange(TCBDB *bdb, const void *bkbuf, int bksiz, bool binc,
    does never fail.  It returns an empty list even if no record corresponds.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbrange2(TCBDB *bdb, const char *bkstr, bool binc,
+EJDB_EXPORT TCLIST *tcbdbrange2(TCBDB *bdb, const char *bkstr, bool binc,
                     const char *ekstr, bool einc, int max);
 
 
@@ -504,7 +503,7 @@ TCLIST *tcbdbrange2(TCBDB *bdb, const char *bkstr, bool binc,
    It returns an empty list even if no key corresponds.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbfwmkeys(TCBDB *bdb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tcbdbfwmkeys(TCBDB *bdb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string keys in a B+ tree database object.
@@ -516,7 +515,7 @@ TCLIST *tcbdbfwmkeys(TCBDB *bdb, const void *pbuf, int psiz, int max);
    It returns an empty list even if no key corresponds.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbfwmkeys2(TCBDB *bdb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tcbdbfwmkeys2(TCBDB *bdb, const char *pstr, int max);
 
 
 /* Add an integer to a record in a B+ tree database object.
@@ -527,7 +526,7 @@ TCLIST *tcbdbfwmkeys2(TCBDB *bdb, const char *pstr, int max);
    If successful, the return value is the summation value, else, it is `INT_MIN'.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tcbdbaddint(TCBDB *bdb, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tcbdbaddint(TCBDB *bdb, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in a B+ tree database object.
@@ -538,14 +537,14 @@ int tcbdbaddint(TCBDB *bdb, const void *kbuf, int ksiz, int num);
    If successful, the return value is the summation value, else, it is Not-a-Number.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tcbdbadddouble(TCBDB *bdb, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tcbdbadddouble(TCBDB *bdb, const void *kbuf, int ksiz, double num);
 
 
 /* Synchronize updated contents of a B+ tree database object with the file and the device.
    `bdb' specifies the B+ tree database object connected as a writer.
    If successful, the return value is true, else, it is false.
    This function is useful when another process connects to the same database file. */
-bool tcbdbsync(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbsync(TCBDB *bdb);
 
 
 /* Optimize the file of a B+ tree database object.
@@ -568,14 +567,14 @@ bool tcbdbsync(TCBDB *bdb);
    If successful, the return value is true, else, it is false.
    This function is useful to reduce the size of the database file with data fragmentation by
    successive updating. */
-bool tcbdboptimize(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
+EJDB_EXPORT bool tcbdboptimize(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
                    int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
 /* Remove all records of a B+ tree database object.
    `bdb' specifies the B+ tree database object connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tcbdbvanish(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbvanish(TCBDB *bdb);
 
 
 /* Copy the database file of a B+ tree database object.
@@ -587,7 +586,7 @@ bool tcbdbvanish(TCBDB *bdb);
    The database file is assured to be kept synchronized and not modified while the copying or
    executing operation is in progress.  So, this function is useful to create a backup file of
    the database file. */
-bool tcbdbcopy(TCBDB *bdb, const char *path);
+EJDB_EXPORT bool tcbdbcopy(TCBDB *bdb, const char *path);
 
 
 /* Begin the transaction of a B+ tree database object.
@@ -599,14 +598,14 @@ bool tcbdbcopy(TCBDB *bdb, const char *path);
    cached on memory while the transaction, the amount of referred records is limited by the
    memory capacity.  If the database is closed during transaction, the transaction is aborted
    implicitly. */
-bool tcbdbtranbegin(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbtranbegin(TCBDB *bdb);
 
 
 /* Commit the transaction of a B+ tree database object.
    `bdb' specifies the B+ tree database object connected as a writer.
    If successful, the return value is true, else, it is false.
    Update in the transaction is fixed when it is committed successfully. */
-bool tcbdbtrancommit(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbtrancommit(TCBDB *bdb);
 
 
 /* Abort the transaction of a B+ tree database object.
@@ -614,28 +613,28 @@ bool tcbdbtrancommit(TCBDB *bdb);
    If successful, the return value is true, else, it is false.
    Update in the transaction is discarded when it is aborted.  The state of the database is
    rollbacked to before transaction. */
-bool tcbdbtranabort(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbtranabort(TCBDB *bdb);
 
 
 /* Get the file path of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the path of the database file or `NULL' if the object does not connect to
    any database file. */
-const char *tcbdbpath(TCBDB *bdb);
+EJDB_EXPORT const char *tcbdbpath(TCBDB *bdb);
 
 
 /* Get the number of records of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the number of records or 0 if the object does not connect to any database
    file. */
-uint64_t tcbdbrnum(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbrnum(TCBDB *bdb);
 
 
 /* Get the size of the database file of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the size of the database file or 0 if the object does not connect to any
    database file. */
-uint64_t tcbdbfsiz(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbfsiz(TCBDB *bdb);
 
 
 /* Create a cursor object.
@@ -644,26 +643,26 @@ uint64_t tcbdbfsiz(TCBDB *bdb);
    Note that the cursor is available only after initialization with the `tcbdbcurfirst' or the
    `tcbdbcurjump' functions and so on.  Moreover, the position of the cursor will be indefinite
    when the database is updated after the initialization of the cursor. */
-BDBCUR *tcbdbcurnew(TCBDB *bdb);
+EJDB_EXPORT BDBCUR *tcbdbcurnew(TCBDB *bdb);
 
 
 /* Delete a cursor object.
    `cur' specifies the cursor object. */
-void tcbdbcurdel(BDBCUR *cur);
+EJDB_EXPORT void tcbdbcurdel(BDBCUR *cur);
 
 
 /* Move a cursor object to the first record.
    `cur' specifies the cursor object.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record in the database. */
-bool tcbdbcurfirst(BDBCUR *cur);
+EJDB_EXPORT bool tcbdbcurfirst(BDBCUR *cur);
 
 
 /* Move a cursor object to the last record.
    `cur' specifies the cursor object.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record in the database. */
-bool tcbdbcurlast(BDBCUR *cur);
+EJDB_EXPORT bool tcbdbcurlast(BDBCUR *cur);
 
 
 /* Move a cursor object to the front of records corresponding a key.
@@ -674,7 +673,7 @@ bool tcbdbcurlast(BDBCUR *cur);
    no record corresponding the condition.
    The cursor is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-bool tcbdbcurjump(BDBCUR *cur, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcbdbcurjump(BDBCUR *cur, const void *kbuf, int ksiz);
 
 
 /* Move a cursor object to the front of records corresponding a key string.
@@ -684,21 +683,21 @@ bool tcbdbcurjump(BDBCUR *cur, const void *kbuf, int ksiz);
    no record corresponding the condition.
    The cursor is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-bool tcbdbcurjump2(BDBCUR *cur, const char *kstr);
+EJDB_EXPORT bool tcbdbcurjump2(BDBCUR *cur, const char *kstr);
 
 
 /* Move a cursor object to the previous record.
    `cur' specifies the cursor object.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no previous record. */
-bool tcbdbcurprev(BDBCUR *cur);
+EJDB_EXPORT bool tcbdbcurprev(BDBCUR *cur);
 
 
 /* Move a cursor object to the next record.
    `cur' specifies the cursor object.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no next record. */
-bool tcbdbcurnext(BDBCUR *cur);
+EJDB_EXPORT bool tcbdbcurnext(BDBCUR *cur);
 
 
 /* Insert a record around a cursor object.
@@ -712,7 +711,7 @@ bool tcbdbcurnext(BDBCUR *cur);
    If successful, the return value is true, else, it is false.  False is returned when the cursor
    is at invalid position.
    After insertion, the cursor is moved to the inserted record. */
-bool tcbdbcurput(BDBCUR *cur, const void *vbuf, int vsiz, int cpmode);
+EJDB_EXPORT bool tcbdbcurput(BDBCUR *cur, const void *vbuf, int vsiz, int cpmode);
 
 
 /* Insert a string record around a cursor object.
@@ -725,7 +724,7 @@ bool tcbdbcurput(BDBCUR *cur, const void *vbuf, int vsiz, int cpmode);
    If successful, the return value is true, else, it is false.  False is returned when the cursor
    is at invalid position.
    After insertion, the cursor is moved to the inserted record. */
-bool tcbdbcurput2(BDBCUR *cur, const char *vstr, int cpmode);
+EJDB_EXPORT bool tcbdbcurput2(BDBCUR *cur, const char *vstr, int cpmode);
 
 
 /* Remove the record where a cursor object is.
@@ -733,7 +732,7 @@ bool tcbdbcurput2(BDBCUR *cur, const char *vstr, int cpmode);
    If successful, the return value is true, else, it is false.  False is returned when the cursor
    is at invalid position.
    After deletion, the cursor is moved to the next record if possible. */
-bool tcbdbcurout(BDBCUR *cur);
+EJDB_EXPORT bool tcbdbcurout(BDBCUR *cur);
 
 
 /* Get the key of the record where the cursor object is.
@@ -746,7 +745,7 @@ bool tcbdbcurout(BDBCUR *cur);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcbdbcurkey(BDBCUR *cur, int *sp);
+EJDB_EXPORT void *tcbdbcurkey(BDBCUR *cur, int *sp);
 
 
 /* Get the key string of the record where the cursor object is.
@@ -755,7 +754,7 @@ void *tcbdbcurkey(BDBCUR *cur, int *sp);
    returned when the cursor is at invalid position.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcbdbcurkey2(BDBCUR *cur);
+EJDB_EXPORT char *tcbdbcurkey2(BDBCUR *cur);
 
 
 /* Get the key of the record where the cursor object is, as a volatile buffer.
@@ -768,7 +767,7 @@ char *tcbdbcurkey2(BDBCUR *cur);
    the return value can be treated as a character string.  Because the region of the return value
    is volatile and it may be spoiled by another operation of the database, the data should be
    copied into another involatile buffer immediately. */
-const void *tcbdbcurkey3(BDBCUR *cur, int *sp);
+EJDB_EXPORT const void *tcbdbcurkey3(BDBCUR *cur, int *sp);
 
 
 /* Get the value of the record where the cursor object is.
@@ -781,7 +780,7 @@ const void *tcbdbcurkey3(BDBCUR *cur, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcbdbcurval(BDBCUR *cur, int *sp);
+EJDB_EXPORT void *tcbdbcurval(BDBCUR *cur, int *sp);
 
 
 /* Get the value string of the record where the cursor object is.
@@ -790,7 +789,7 @@ void *tcbdbcurval(BDBCUR *cur, int *sp);
    returned when the cursor is at invalid position.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcbdbcurval2(BDBCUR *cur);
+EJDB_EXPORT char *tcbdbcurval2(BDBCUR *cur);
 
 
 /* Get the value of the record where the cursor object is, as a volatile buffer.
@@ -803,7 +802,7 @@ char *tcbdbcurval2(BDBCUR *cur);
    the return value can be treated as a character string.  Because the region of the return value
    is volatile and it may be spoiled by another operation of the database, the data should be
    copied into another involatile buffer immediately. */
-const void *tcbdbcurval3(BDBCUR *cur, int *sp);
+EJDB_EXPORT const void *tcbdbcurval3(BDBCUR *cur, int *sp);
 
 
 /* Get the key and the value of the record where the cursor object is.
@@ -812,7 +811,7 @@ const void *tcbdbcurval3(BDBCUR *cur, int *sp);
    `vxstr' specifies the object into which the value is wrote down.
    If successful, the return value is true, else, it is false.  False is returned when the cursor
    is at invalid position. */
-bool tcbdbcurrec(BDBCUR *cur, TCXSTR *kxstr, TCXSTR *vxstr);
+EJDB_EXPORT bool tcbdbcurrec(BDBCUR *cur, TCXSTR *kxstr, TCXSTR *vxstr);
 
 
 
@@ -827,130 +826,124 @@ bool tcbdbcurrec(BDBCUR *cur, TCXSTR *kxstr, TCXSTR *vxstr);
    `file' specifies the file name of the code.
    `line' specifies the line number of the code.
    `func' specifies the function name of the code. */
-void tcbdbsetecode(TCBDB *bdb, int ecode, const char *filename, int line, const char *func);
+EJDB_EXPORT void tcbdbsetecode(TCBDB *bdb, int ecode, const char *filename, int line, const char *func);
 
 
 /* Set the file descriptor for debugging output.
    `bdb' specifies the B+ tree database object.
    `fd' specifies the file descriptor for debugging output. */
-void tcbdbsetdbgfd(TCBDB *bdb, int fd);
+EJDB_EXPORT void tcbdbsetdbgfd(TCBDB *bdb, HANDLE fd);
 
 
 /* Get the file descriptor for debugging output.
    `bdb' specifies the B+ tree database object.
    The return value is the file descriptor for debugging output. */
-int tcbdbdbgfd(TCBDB *bdb);
+EJDB_EXPORT HANDLE tcbdbdbgfd(TCBDB *bdb);
 
 
 /* Check whether mutual exclusion control is set to a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    If mutual exclusion control is set, it is true, else it is false. */
-bool tcbdbhasmutex(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbhasmutex(TCBDB *bdb);
 
 
 /* Synchronize updating contents on memory of a B+ tree database object.
    `bdb' specifies the B+ tree database object connected as a writer.
    `phys' specifies whether to synchronize physically.
    If successful, the return value is true, else, it is false. */
-bool tcbdbmemsync(TCBDB *bdb, bool phys);
+EJDB_EXPORT bool tcbdbmemsync(TCBDB *bdb, bool phys);
 
 
 /* Get the comparison function of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the pointer to the comparison function. */
-TCCMP tcbdbcmpfunc(TCBDB *bdb);
+EJDB_EXPORT TCCMP tcbdbcmpfunc(TCBDB *bdb);
 
 
 /* Get the opaque object for the comparison function of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the opaque object for the comparison function. */
-void *tcbdbcmpop(TCBDB *bdb);
+EJDB_EXPORT void *tcbdbcmpop(TCBDB *bdb);
 
 
 /* Get the maximum number of cached leaf nodes of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the maximum number of cached leaf nodes. */
-uint32_t tcbdblmemb(TCBDB *bdb);
+EJDB_EXPORT uint32_t tcbdblmemb(TCBDB *bdb);
 
 
 /* Get the maximum number of cached non-leaf nodes of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the maximum number of cached non-leaf nodes. */
-uint32_t tcbdbnmemb(TCBDB *bdb);
+EJDB_EXPORT uint32_t tcbdbnmemb(TCBDB *bdb);
 
 
 /* Get the number of the leaf nodes of B+ tree database object.
    `bdb' specifies the B+ tree database object.
    If successful, the return value is the number of the leaf nodes or 0 if the object does not
    connect to any database file. */
-uint64_t tcbdblnum(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdblnum(TCBDB *bdb);
 
 
 /* Get the number of the non-leaf nodes of B+ tree database object.
    `bdb' specifies the B+ tree database object.
    If successful, the return value is the number of the non-leaf nodes or 0 if the object does
    not connect to any database file. */
-uint64_t tcbdbnnum(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbnnum(TCBDB *bdb);
 
 
 /* Get the number of elements of the bucket array of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the number of elements of the bucket array or 0 if the object does not
    connect to any database file. */
-uint64_t tcbdbbnum(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbbnum(TCBDB *bdb);
 
 
 /* Get the record alignment of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the record alignment or 0 if the object does not connect to any database
    file. */
-uint32_t tcbdbalign(TCBDB *bdb);
+EJDB_EXPORT uint32_t tcbdbalign(TCBDB *bdb);
 
 
 /* Get the maximum number of the free block pool of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the maximum number of the free block pool or 0 if the object does not
    connect to any database file. */
-uint32_t tcbdbfbpmax(TCBDB *bdb);
+EJDB_EXPORT uint32_t tcbdbfbpmax(TCBDB *bdb);
 
 
 /* Get the inode number of the database file of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-uint64_t tcbdbinode(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbinode(TCBDB *bdb);
 
 
 /* Get the modification time of the database file of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-time_t tcbdbmtime(TCBDB *bdb);
+EJDB_EXPORT time_t tcbdbmtime(TCBDB *bdb);
 
 
 /* Get the additional flags of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the additional flags. */
-uint8_t tcbdbflags(TCBDB *bdb);
+EJDB_EXPORT uint8_t tcbdbflags(TCBDB *bdb);
 
 
 /* Get the options of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the options. */
-uint8_t tcbdbopts(TCBDB *bdb);
-
-
-/* Get the pointer to the opaque field of a B+ tree database object.
-   `bdb' specifies the B+ tree database object.
-   The return value is the pointer to the opaque field whose size is 128 bytes. */
-char *tcbdbopaque(TCBDB *bdb);
+EJDB_EXPORT uint8_t tcbdbopts(TCBDB *bdb);
 
 
 /* Get the number of used elements of the bucket array of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the number of used elements of the bucket array or 0 if the object does not
    connect to any database file. */
-uint64_t tcbdbbnumused(TCBDB *bdb);
+EJDB_EXPORT uint64_t tcbdbbnumused(TCBDB *bdb);
 
 
 /* Set the maximum size of each leaf node.
@@ -959,7 +952,7 @@ uint64_t tcbdbbnumused(TCBDB *bdb);
    value is specified.  The default value is 16386.
    If successful, the return value is true, else, it is false.
    Note that the tuning parameters of the database should be set before the database is opened. */
-bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax);
+EJDB_EXPORT bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax);
 
 
 /* Set the capacity number of records.
@@ -969,7 +962,7 @@ bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax);
    If successful, the return value is true, else, it is false.
    When the number of records exceeds the capacity, forehand records are removed implicitly.
    Note that the tuning parameters of the database should be set before the database is opened. */
-bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum);
+EJDB_EXPORT bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum);
 
 
 /* Set the custom codec functions of a B+ tree database object.
@@ -988,13 +981,13 @@ bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum);
    If successful, the return value is true, else, it is false.
    Note that the custom codec functions should be set before the database is opened and should be
    set every time the database is being opened. */
-bool tcbdbsetcodecfunc(TCBDB *bdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
+EJDB_EXPORT bool tcbdbsetcodecfunc(TCBDB *bdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
 
 
 /* Get the unit step number of auto defragmentation of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    The return value is the unit step number of auto defragmentation. */
-uint32_t tcbdbdfunit(TCBDB *bdb);
+EJDB_EXPORT uint32_t tcbdbdfunit(TCBDB *bdb);
 
 
 /* Perform dynamic defragmentation of a B+ tree database object.
@@ -1002,13 +995,13 @@ uint32_t tcbdbdfunit(TCBDB *bdb);
    `step' specifie the number of steps.  If it is not more than 0, the whole file is defragmented
    gradually without keeping a continuous lock.
    If successful, the return value is true, else, it is false. */
-bool tcbdbdefrag(TCBDB *bdb, int64_t step);
+EJDB_EXPORT bool tcbdbdefrag(TCBDB *bdb, int64_t step);
 
 
 /* Clear the cache of a B+ tree database object.
    `bdb' specifies the B+ tree database object.
    If successful, the return value is true, else, it is false. */
-bool tcbdbcacheclear(TCBDB *bdb);
+EJDB_EXPORT bool tcbdbcacheclear(TCBDB *bdb);
 
 
 /* Store a new record into a B+ tree database object with backward duplication.
@@ -1020,7 +1013,7 @@ bool tcbdbcacheclear(TCBDB *bdb);
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, the new record is placed after the
    existing one. */
-bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into a B+ tree database object with backward duplication.
@@ -1030,7 +1023,7 @@ bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, i
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, the new record is placed after the
    existing one. */
-bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr);
 
 
 /* Store a record into a B+ tree database object with a duplication handler.
@@ -1052,7 +1045,7 @@ bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tcbdbputproc(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tcbdbputproc(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -1064,7 +1057,7 @@ bool tcbdbputproc(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int
    no record corresponding the condition.
    The cursor is set to the last record corresponding the key or the previous substitute if
    completely matching record does not exist. */
-bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz);
 
 
 /* Move a cursor object to the rear of records corresponding a key string.
@@ -1074,7 +1067,7 @@ bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz);
    no record corresponding the condition.
    The cursor is set to the last record corresponding the key or the previous substitute if
    completely matching record does not exist. */
-bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr);
+EJDB_EXPORT bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr);
 
 
 /* Process each record atomically of a B+ tree database object.
@@ -1090,7 +1083,7 @@ bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tcbdbforeach(TCBDB *bdb, TCITER iter, void *op);
+EJDB_EXPORT bool tcbdbforeach(TCBDB *bdb, TCITER iter, void *op);
 
 
 
index af27ac4..55458aa 100644 (file)
@@ -21,7 +21,7 @@
 
 /* global variables */
 const char *g_progname;                  // program name
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -59,9 +59,16 @@ static int procversion(void);
 /* main routine */
 int main(int argc, char **argv){
   g_progname = argv[0];
-  g_dbgfd = -1;
+  g_dbgfd = INVALID_HANDLE_VALUE;
   const char *ebuf = getenv("TCDBGFD");
-  if(ebuf) g_dbgfd = tcatoix(ebuf);
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "create")){
@@ -595,7 +602,7 @@ static int runversion(int argc, char **argv){
 static int proccreate(const char *path, int lmemb, int nmemb,
                       int bnum, int apow, int fpow, TCCMP cmp, int opts){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
@@ -621,7 +628,7 @@ static int proccreate(const char *path, int lmemb, int nmemb,
 /* perform inform command */
 static int procinform(const char *path, int omode){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   tcbdbsetcmpfunc(bdb, mycmpfunc, NULL);
   tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL);
   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
@@ -655,14 +662,14 @@ static int procinform(const char *path, int omode){
   printf("\n");
   printf("max leaf member: %d\n", tcbdblmemb(bdb));
   printf("max node member: %d\n", tcbdbnmemb(bdb));
-  printf("leaf number: %llu\n", (unsigned long long)tcbdblnum(bdb));
-  printf("node number: %llu\n", (unsigned long long)tcbdbnnum(bdb));
-  printf("bucket number: %llu\n", (unsigned long long)tcbdbbnum(bdb));
+  printf("leaf number: %" PRIuMAX "\n", (unsigned long long)tcbdblnum(bdb));
+  printf("node number: %" PRIuMAX "\n", (unsigned long long)tcbdbnnum(bdb));
+  printf("bucket number: %" PRIuMAX "\n", (unsigned long long)tcbdbbnum(bdb));
   if(bdb->hdb->cnt_writerec >= 0)
-    printf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
+    printf("used bucket number: %" PRIdMAX "\n", (long long)tcbdbbnumused(bdb));
   printf("alignment: %u\n", tcbdbalign(bdb));
   printf("free block pool: %u\n", tcbdbfbpmax(bdb));
-  printf("inode number: %lld\n", (long long)tcbdbinode(bdb));
+  printf("inode number: %" PRIdMAX "\n", (long long)tcbdbinode(bdb));
   char date[48];
   tcdatestrwww(tcbdbmtime(bdb), INT_MAX, date);
   printf("modified time: %s\n", date);
@@ -674,8 +681,8 @@ static int procinform(const char *path, int omode){
   if(opts & BDBTTCBS) printf(" tcbs");
   if(opts & BDBTEXCODEC) printf(" excodec");
   printf("\n");
-  printf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  printf("file size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  printf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  printf("file size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   if(!tcbdbclose(bdb)){
     if(!err) printerr(bdb);
     err = true;
@@ -689,7 +696,7 @@ static int procinform(const char *path, int omode){
 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
                    TCCMP cmp, int omode, int dmode){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
@@ -762,7 +769,7 @@ static int procput(const char *path, const char *kbuf, int ksiz, const char *vbu
 /* perform out command */
 static int procout(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
@@ -788,7 +795,7 @@ static int procout(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int
 static int procget(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode,
                    bool px, bool pz){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
@@ -820,7 +827,7 @@ static int procget(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int
 static int proclist(const char *path, TCCMP cmp, int omode, int max, bool pv, bool px, bool bk,
                     const char *jstr, const char *bstr, const char *estr, const char *fmstr){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
@@ -928,7 +935,7 @@ static int proclist(const char *path, TCCMP cmp, int omode, int max, bool pv, bo
 static int procoptimize(const char *path, int lmemb, int nmemb,
                         int bnum, int apow, int fpow, TCCMP cmp, int opts, int omode, bool df){
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
@@ -965,7 +972,7 @@ static int procimporttsv(const char *path, const char *file, int omode, bool sc)
     return 1;
   }
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
   if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | omode)){
     printerr(bdb);
index d8bf5c3..c11dd81 100644 (file)
@@ -68,7 +68,7 @@ typedef struct {                         // type of structure for race thread
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -115,7 +115,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -196,34 +203,34 @@ static void mprint(TCBDB *bdb){
   if(bdb->hdb->cnt_writerec < 0) return;
   iprintf("max leaf member: %d\n", tcbdblmemb(bdb));
   iprintf("max node member: %d\n", tcbdbnmemb(bdb));
-  iprintf("leaf number: %lld\n", (long long)tcbdblnum(bdb));
-  iprintf("node number: %lld\n", (long long)tcbdbnnum(bdb));
-  iprintf("bucket number: %lld\n", (long long)tcbdbbnum(bdb));
-  iprintf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
-  iprintf("cnt_saveleaf: %lld\n", (long long)bdb->cnt_saveleaf);
-  iprintf("cnt_loadleaf: %lld\n", (long long)bdb->cnt_loadleaf);
-  iprintf("cnt_killleaf: %lld\n", (long long)bdb->cnt_killleaf);
-  iprintf("cnt_adjleafc: %lld\n", (long long)bdb->cnt_adjleafc);
-  iprintf("cnt_savenode: %lld\n", (long long)bdb->cnt_savenode);
-  iprintf("cnt_loadnode: %lld\n", (long long)bdb->cnt_loadnode);
-  iprintf("cnt_adjnodec: %lld\n", (long long)bdb->cnt_adjnodec);
-  iprintf("cnt_writerec: %lld\n", (long long)bdb->hdb->cnt_writerec);
-  iprintf("cnt_reuserec: %lld\n", (long long)bdb->hdb->cnt_reuserec);
-  iprintf("cnt_moverec: %lld\n", (long long)bdb->hdb->cnt_moverec);
-  iprintf("cnt_readrec: %lld\n", (long long)bdb->hdb->cnt_readrec);
-  iprintf("cnt_searchfbp: %lld\n", (long long)bdb->hdb->cnt_searchfbp);
-  iprintf("cnt_insertfbp: %lld\n", (long long)bdb->hdb->cnt_insertfbp);
-  iprintf("cnt_splicefbp: %lld\n", (long long)bdb->hdb->cnt_splicefbp);
-  iprintf("cnt_dividefbp: %lld\n", (long long)bdb->hdb->cnt_dividefbp);
-  iprintf("cnt_mergefbp: %lld\n", (long long)bdb->hdb->cnt_mergefbp);
-  iprintf("cnt_reducefbp: %lld\n", (long long)bdb->hdb->cnt_reducefbp);
-  iprintf("cnt_appenddrp: %lld\n", (long long)bdb->hdb->cnt_appenddrp);
-  iprintf("cnt_deferdrp: %lld\n", (long long)bdb->hdb->cnt_deferdrp);
-  iprintf("cnt_flushdrp: %lld\n", (long long)bdb->hdb->cnt_flushdrp);
-  iprintf("cnt_adjrecc: %lld\n", (long long)bdb->hdb->cnt_adjrecc);
-  iprintf("cnt_defrag: %lld\n", (long long)bdb->hdb->cnt_defrag);
-  iprintf("cnt_shiftrec: %lld\n", (long long)bdb->hdb->cnt_shiftrec);
-  iprintf("cnt_trunc: %lld\n", (long long)bdb->hdb->cnt_trunc);
+  iprintf("leaf number: %" PRIdMAX "\n", (long long)tcbdblnum(bdb));
+  iprintf("node number: %" PRIdMAX "\n", (long long)tcbdbnnum(bdb));
+  iprintf("bucket number: %" PRIdMAX "\n", (long long)tcbdbbnum(bdb));
+  iprintf("used bucket number: %" PRIdMAX "\n", (long long)tcbdbbnumused(bdb));
+  iprintf("cnt_saveleaf: %" PRIdMAX "\n", (long long)bdb->cnt_saveleaf);
+  iprintf("cnt_loadleaf: %" PRIdMAX "\n", (long long)bdb->cnt_loadleaf);
+  iprintf("cnt_killleaf: %" PRIdMAX "\n", (long long)bdb->cnt_killleaf);
+  iprintf("cnt_adjleafc: %" PRIdMAX "\n", (long long)bdb->cnt_adjleafc);
+  iprintf("cnt_savenode: %" PRIdMAX "\n", (long long)bdb->cnt_savenode);
+  iprintf("cnt_loadnode: %" PRIdMAX "\n", (long long)bdb->cnt_loadnode);
+  iprintf("cnt_adjnodec: %" PRIdMAX "\n", (long long)bdb->cnt_adjnodec);
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_writerec);
+  iprintf("cnt_reuserec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_reuserec);
+  iprintf("cnt_moverec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_moverec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_readrec);
+  iprintf("cnt_searchfbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_searchfbp);
+  iprintf("cnt_insertfbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_insertfbp);
+  iprintf("cnt_splicefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_splicefbp);
+  iprintf("cnt_dividefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_dividefbp);
+  iprintf("cnt_mergefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_mergefbp);
+  iprintf("cnt_reducefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_reducefbp);
+  iprintf("cnt_appenddrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_appenddrp);
+  iprintf("cnt_deferdrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_deferdrp);
+  iprintf("cnt_flushdrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_flushdrp);
+  iprintf("cnt_adjrecc: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_adjrecc);
+  iprintf("cnt_defrag: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_defrag);
+  iprintf("cnt_shiftrec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_shiftrec);
+  iprintf("cnt_trunc: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_trunc);
 }
 
 
@@ -647,7 +654,7 @@ static int procwrite(const char *path, int tnum, int rnum, int lmemb, int nmemb,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -703,8 +710,8 @@ static int procwrite(const char *path, int tnum, int rnum, int lmemb, int nmemb,
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -726,7 +733,7 @@ static int procread(const char *path, int tnum, int xmsiz, int dfunit, int omode
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -781,8 +788,8 @@ static int procread(const char *path, int tnum, int xmsiz, int dfunit, int omode
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -803,7 +810,7 @@ static int procremove(const char *path, int tnum, int xmsiz, int dfunit, int omo
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -856,8 +863,8 @@ static int procremove(const char *path, int tnum, int xmsiz, int dfunit, int omo
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -878,7 +885,7 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -968,8 +975,8 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode,
     if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
   }
   tcmapdel(map);
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -995,7 +1002,7 @@ static int proctypical(const char *path, int tnum, int rnum, int lmemb, int nmem
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1053,8 +1060,8 @@ static int proctypical(const char *path, int tnum, int rnum, int lmemb, int nmem
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -1078,7 +1085,7 @@ static int procrace(const char *path, int tnum, int rnum, int lmemb, int nmemb,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(!tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1132,8 +1139,8 @@ static int procrace(const char *path, int tnum, int rnum, int lmemb, int nmemb,
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
index 23e007d..c0d998a 100644 (file)
@@ -24,7 +24,7 @@
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -72,7 +72,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -159,34 +166,34 @@ static void mprint(TCBDB *bdb){
   if(bdb->hdb->cnt_writerec < 0) return;
   iprintf("max leaf member: %d\n", tcbdblmemb(bdb));
   iprintf("max node member: %d\n", tcbdbnmemb(bdb));
-  iprintf("leaf number: %lld\n", (long long)tcbdblnum(bdb));
-  iprintf("node number: %lld\n", (long long)tcbdbnnum(bdb));
-  iprintf("bucket number: %lld\n", (long long)tcbdbbnum(bdb));
-  iprintf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
-  iprintf("cnt_saveleaf: %lld\n", (long long)bdb->cnt_saveleaf);
-  iprintf("cnt_loadleaf: %lld\n", (long long)bdb->cnt_loadleaf);
-  iprintf("cnt_killleaf: %lld\n", (long long)bdb->cnt_killleaf);
-  iprintf("cnt_adjleafc: %lld\n", (long long)bdb->cnt_adjleafc);
-  iprintf("cnt_savenode: %lld\n", (long long)bdb->cnt_savenode);
-  iprintf("cnt_loadnode: %lld\n", (long long)bdb->cnt_loadnode);
-  iprintf("cnt_adjnodec: %lld\n", (long long)bdb->cnt_adjnodec);
-  iprintf("cnt_writerec: %lld\n", (long long)bdb->hdb->cnt_writerec);
-  iprintf("cnt_reuserec: %lld\n", (long long)bdb->hdb->cnt_reuserec);
-  iprintf("cnt_moverec: %lld\n", (long long)bdb->hdb->cnt_moverec);
-  iprintf("cnt_readrec: %lld\n", (long long)bdb->hdb->cnt_readrec);
-  iprintf("cnt_searchfbp: %lld\n", (long long)bdb->hdb->cnt_searchfbp);
-  iprintf("cnt_insertfbp: %lld\n", (long long)bdb->hdb->cnt_insertfbp);
-  iprintf("cnt_splicefbp: %lld\n", (long long)bdb->hdb->cnt_splicefbp);
-  iprintf("cnt_dividefbp: %lld\n", (long long)bdb->hdb->cnt_dividefbp);
-  iprintf("cnt_mergefbp: %lld\n", (long long)bdb->hdb->cnt_mergefbp);
-  iprintf("cnt_reducefbp: %lld\n", (long long)bdb->hdb->cnt_reducefbp);
-  iprintf("cnt_appenddrp: %lld\n", (long long)bdb->hdb->cnt_appenddrp);
-  iprintf("cnt_deferdrp: %lld\n", (long long)bdb->hdb->cnt_deferdrp);
-  iprintf("cnt_flushdrp: %lld\n", (long long)bdb->hdb->cnt_flushdrp);
-  iprintf("cnt_adjrecc: %lld\n", (long long)bdb->hdb->cnt_adjrecc);
-  iprintf("cnt_defrag: %lld\n", (long long)bdb->hdb->cnt_defrag);
-  iprintf("cnt_shiftrec: %lld\n", (long long)bdb->hdb->cnt_shiftrec);
-  iprintf("cnt_trunc: %lld\n", (long long)bdb->hdb->cnt_trunc);
+  iprintf("leaf number: %" PRIdMAX "\n", (long long)tcbdblnum(bdb));
+  iprintf("node number: %" PRIdMAX "\n", (long long)tcbdbnnum(bdb));
+  iprintf("bucket number: %" PRIdMAX "\n", (long long)tcbdbbnum(bdb));
+  iprintf("used bucket number: %" PRIdMAX "\n", (long long)tcbdbbnumused(bdb));
+  iprintf("cnt_saveleaf: %" PRIdMAX "\n", (long long)bdb->cnt_saveleaf);
+  iprintf("cnt_loadleaf: %" PRIdMAX "\n", (long long)bdb->cnt_loadleaf);
+  iprintf("cnt_killleaf: %" PRIdMAX "\n", (long long)bdb->cnt_killleaf);
+  iprintf("cnt_adjleafc: %" PRIdMAX "\n", (long long)bdb->cnt_adjleafc);
+  iprintf("cnt_savenode: %" PRIdMAX "\n", (long long)bdb->cnt_savenode);
+  iprintf("cnt_loadnode: %" PRIdMAX "\n", (long long)bdb->cnt_loadnode);
+  iprintf("cnt_adjnodec: %" PRIdMAX "\n", (long long)bdb->cnt_adjnodec);
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_writerec);
+  iprintf("cnt_reuserec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_reuserec);
+  iprintf("cnt_moverec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_moverec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_readrec);
+  iprintf("cnt_searchfbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_searchfbp);
+  iprintf("cnt_insertfbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_insertfbp);
+  iprintf("cnt_splicefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_splicefbp);
+  iprintf("cnt_dividefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_dividefbp);
+  iprintf("cnt_mergefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_mergefbp);
+  iprintf("cnt_reducefbp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_reducefbp);
+  iprintf("cnt_appenddrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_appenddrp);
+  iprintf("cnt_deferdrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_deferdrp);
+  iprintf("cnt_flushdrp: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_flushdrp);
+  iprintf("cnt_adjrecc: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_adjrecc);
+  iprintf("cnt_defrag: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_defrag);
+  iprintf("cnt_shiftrec: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_shiftrec);
+  iprintf("cnt_trunc: %" PRIdMAX "\n", (long long)bdb->hdb->cnt_trunc);
 }
 
 
@@ -773,7 +780,7 @@ static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -841,8 +848,8 @@ static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -866,7 +873,7 @@ static int procread(const char *path, bool mt, TCCMP cmp, int lcnum, int ncnum,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -935,8 +942,8 @@ static int procread(const char *path, bool mt, TCCMP cmp, int lcnum, int ncnum,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -959,7 +966,7 @@ static int procremove(const char *path, bool mt, TCCMP cmp, int lcnum, int ncnum
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1015,8 +1022,8 @@ static int procremove(const char *path, bool mt, TCCMP cmp, int lcnum, int ncnum
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -1046,7 +1053,7 @@ static int procrcat(const char *path, int rnum,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1211,8 +1218,8 @@ static int procrcat(const char *path, int rnum,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -1239,7 +1246,7 @@ static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1341,8 +1348,8 @@ static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
     break;
   }
   tcbdbcurdel(cur);
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -1363,7 +1370,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -1392,7 +1399,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(bdb, __LINE__, "tcbdbopen");
     err = true;
   }
-  if(TCUSEPTHREAD){
+  if(1){
     TCBDB *bdbdup = tcbdbnew();
     if(tcbdbopen(bdbdup, path, BDBOREADER)){
       eprint(bdb, __LINE__, "(validation)");
@@ -2176,8 +2183,8 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     err = true;
   }
   tcbdbcurdel(cur);
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   if(!tcbdbclose(bdb)){
@@ -2198,7 +2205,7 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCBDB *bdb = tcbdbnew();
-  if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd);
   if(mt && !tcbdbsetmutex(bdb)){
     eprint(bdb, __LINE__, "tcbdbsetmutex");
     err = true;
@@ -2566,8 +2573,8 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
     err = true;
   }
   tcbdbcurdel(cur);
-  iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
-  iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcbdbrnum(bdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcbdbfsiz(bdb));
   mprint(bdb);
   sysprint();
   tcmapdel(map);
index 7526262..87b77dc 100644 (file)
@@ -144,7 +144,7 @@ TCFDB *tcfdbnew(void){
 /* Delete a fixed-length database object. */
 void tcfdbdel(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd >= 0) tcfdbclose(fdb);
+  if(!INVALIDHANDLE(fdb->fd)) tcfdbclose(fdb);
   if(fdb->mmtx){
     pthread_key_delete(*(pthread_key_t *)fdb->eckey);
     pthread_mutex_destroy(fdb->wmtx);
@@ -176,8 +176,7 @@ int tcfdbecode(TCFDB *fdb){
 /* Set mutual exclusion control of a fixed-length database object for threading. */
 bool tcfdbsetmutex(TCFDB *fdb){
   assert(fdb);
-  if(!TCUSEPTHREAD) return true;
-  if(fdb->mmtx || fdb->fd >= 0){
+  if(fdb->mmtx || !INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -218,7 +217,7 @@ bool tcfdbsetmutex(TCFDB *fdb){
 /* Set the tuning parameters of a fixed-length database object. */
 bool tcfdbtune(TCFDB *fdb, int32_t width, int64_t limsiz){
   assert(fdb);
-  if(fdb->fd >= 0){
+  if(!INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -235,7 +234,7 @@ bool tcfdbtune(TCFDB *fdb, int32_t width, int64_t limsiz){
 bool tcfdbopen(TCFDB *fdb, const char *path, int omode){
   assert(fdb && path);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd >= 0){
+  if(!INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -274,7 +273,7 @@ bool tcfdbopen(TCFDB *fdb, const char *path, int omode){
 bool tcfdbclose(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -292,7 +291,7 @@ bool tcfdbclose(TCFDB *fdb){
 bool tcfdbput(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz){
   assert(fdb && vbuf && vsiz >= 0);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -340,7 +339,7 @@ bool tcfdbput3(TCFDB *fdb, const char *kstr, const void *vstr){
 bool tcfdbputkeep(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz){
   assert(fdb && vbuf && vsiz >= 0);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -388,7 +387,7 @@ bool tcfdbputkeep3(TCFDB *fdb, const char *kstr, const void *vstr){
 bool tcfdbputcat(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz){
   assert(fdb && vbuf && vsiz >= 0);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -436,7 +435,7 @@ bool tcfdbputcat3(TCFDB *fdb, const char *kstr, const void *vstr){
 bool tcfdbout(TCFDB *fdb, int64_t id){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -480,7 +479,7 @@ bool tcfdbout3(TCFDB *fdb, const char *kstr){
 void *tcfdbget(TCFDB *fdb, int64_t id, int *sp){
   assert(fdb && sp);
   if(!FDBLOCKMETHOD(fdb, false)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -526,7 +525,7 @@ char *tcfdbget3(TCFDB *fdb, const char *kstr){
 int tcfdbget4(TCFDB *fdb, int64_t id, void *vbuf, int max){
   assert(fdb && vbuf && max >= 0);
   if(!FDBLOCKMETHOD(fdb, false)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -563,7 +562,7 @@ int tcfdbget4(TCFDB *fdb, int64_t id, void *vbuf, int max){
 int tcfdbvsiz(TCFDB *fdb, int64_t id){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, false)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -609,7 +608,7 @@ int tcfdbvsiz3(TCFDB *fdb, const char *kstr){
 bool tcfdbiterinit(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -624,7 +623,7 @@ bool tcfdbiterinit(TCFDB *fdb){
 uint64_t tcfdbiternext(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -641,7 +640,7 @@ void *tcfdbiternext2(TCFDB *fdb, int *sp){
   uint64_t id = tcfdbiternextimpl(fdb);
   if(id < 1) return NULL;
   char kbuf[TCNUMBUFSIZ];
-  int ksiz = sprintf(kbuf, "%llu", (unsigned long long)id);
+  int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)id);
   *sp = ksiz;
   return tcmemdup(kbuf, ksiz);
 }
@@ -659,7 +658,7 @@ char *tcfdbiternext3(TCFDB *fdb){
 uint64_t *tcfdbrange(TCFDB *fdb, int64_t lower, int64_t upper, int max, int *np){
   assert(fdb && np);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     *np = 0;
@@ -687,7 +686,7 @@ TCLIST *tcfdbrange2(TCFDB *fdb, const void *lbuf, int lsiz, const void *ubuf, in
   TCLIST *keys = tclistnew2(num);
   for(int i = 0; i < num; i++){
     char kbuf[TCNUMBUFSIZ];
-    int ksiz = sprintf(kbuf, "%llu", (unsigned long long)ids[i]);
+    int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)ids[i]);
     TCLISTPUSH(keys, kbuf, ksiz);
   }
   TCFREE(ids);
@@ -769,7 +768,7 @@ TCLIST *tcfdbrange4(TCFDB *fdb, const void *ibuf, int isiz, int max){
   TCLIST *keys = tclistnew2(num);
   for(int i = 0; i < num; i++){
     char kbuf[TCNUMBUFSIZ];
-    int ksiz = sprintf(kbuf, "%llu", (unsigned long long)ids[i]);
+    int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)ids[i]);
     TCLISTPUSH(keys, kbuf, ksiz);
   }
   TCFREE(ids);
@@ -788,7 +787,7 @@ TCLIST *tcfdbrange5(TCFDB *fdb, const void *istr, int max){
 int tcfdbaddint(TCFDB *fdb, int64_t id, int num){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return INT_MIN;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return INT_MIN;
@@ -822,7 +821,7 @@ int tcfdbaddint(TCFDB *fdb, int64_t id, int num){
 double tcfdbadddouble(TCFDB *fdb, int64_t id, double num){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return nan("");
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return nan("");
@@ -856,7 +855,7 @@ double tcfdbadddouble(TCFDB *fdb, int64_t id, double num){
 bool tcfdbsync(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || fdb->tran){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || fdb->tran){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -871,7 +870,7 @@ bool tcfdbsync(TCFDB *fdb){
 bool tcfdboptimize(TCFDB *fdb, int32_t width, int64_t limsiz){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || fdb->tran){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || fdb->tran){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -887,7 +886,7 @@ bool tcfdboptimize(TCFDB *fdb, int32_t width, int64_t limsiz){
 bool tcfdbvanish(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || fdb->tran){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || fdb->tran){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -903,7 +902,7 @@ bool tcfdbvanish(TCFDB *fdb){
 bool tcfdbcopy(TCFDB *fdb, const char *path){
   assert(fdb && path);
   if(!FDBLOCKMETHOD(fdb, false)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -923,9 +922,9 @@ bool tcfdbcopy(TCFDB *fdb, const char *path){
 /* Begin the transaction of a fixed-length database object. */
 bool tcfdbtranbegin(TCFDB *fdb){
   assert(fdb);
-  for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){
+  for(double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2){
     if(!FDBLOCKMETHOD(fdb, true)) return false;
-    if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || fdb->fatal){
+    if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || fdb->fatal){
       tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
       FDBUNLOCKMETHOD(fdb);
       return false;
@@ -939,22 +938,21 @@ bool tcfdbtranbegin(TCFDB *fdb){
     FDBUNLOCKMETHOD(fdb);
     return false;
   }
-  if((fdb->omode & FDBOTSYNC) && fsync(fdb->fd) == -1){
+  if((fdb->omode & FDBOTSYNC) && fsync(fdb->fd)){
     tcfdbsetecode(fdb, TCESYNC, __FILE__, __LINE__, __func__);
     return false;
   }
-  if(fdb->walfd < 0){
+  if(INVALIDHANDLE(fdb->walfd)){
     char *tpath = tcsprintf("%s%c%s", fdb->path, MYEXTCHR, FDBWALSUFFIX);
-    int walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, FDBFILEMODE);
+    HANDLE walfd;
+#ifndef _WIN32
+    walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, FDBFILEMODE);
+#else
+    walfd = CreateFile(tpath, (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
     TCFREE(tpath);
-    if(walfd < 0){
-      int ecode = TCEOPEN;
-      switch(errno){
-        case EACCES: ecode = TCENOPERM; break;
-        case ENOENT: ecode = TCENOFILE; break;
-        case ENOTDIR: ecode = TCENOFILE; break;
-      }
-      tcfdbsetecode(fdb, ecode, __FILE__, __LINE__, __func__);
+    if(INVALIDHANDLE(walfd)){
+      tcfdbsetecode(fdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
       FDBUNLOCKMETHOD(fdb);
       return false;
     }
@@ -977,14 +975,14 @@ bool tcfdbtranbegin(TCFDB *fdb){
 bool tcfdbtrancommit(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || fdb->fatal || !fdb->tran){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || fdb->fatal || !fdb->tran){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
   }
   bool err = false;
   if(!tcfdbmemsync(fdb, fdb->omode & FDBOTSYNC)) err = true;
-  if(!err && ftruncate(fdb->walfd, 0) == -1){
+  if(!err && !tcftruncate(fdb->walfd, 0)){
     tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -998,7 +996,7 @@ bool tcfdbtrancommit(TCFDB *fdb){
 bool tcfdbtranabort(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER) || !fdb->tran){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER) || !fdb->tran){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -1007,7 +1005,7 @@ bool tcfdbtranabort(TCFDB *fdb){
   if(!tcfdbmemsync(fdb, false)) err = true;
   if(!tcfdbwalrestore(fdb, fdb->path)) err = true;
   char hbuf[FDBHEADSIZ];
-  if(lseek(fdb->fd, 0, SEEK_SET) == -1){
+  if(!tcfseek(fdb->fd, 0, TCFSTART)){
     tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);
     err = false;
   } else if(!tcread(fdb->fd, hbuf, FDBHEADSIZ)){
@@ -1026,7 +1024,7 @@ bool tcfdbtranabort(TCFDB *fdb){
 const char *tcfdbpath(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, false)) return NULL;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return NULL;
@@ -1041,7 +1039,7 @@ const char *tcfdbpath(TCFDB *fdb){
 uint64_t tcfdbrnum(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, false)) return 0;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return 0;
@@ -1056,7 +1054,7 @@ uint64_t tcfdbrnum(TCFDB *fdb){
 uint64_t tcfdbfsiz(TCFDB *fdb){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, false)) return 0;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return 0;
@@ -1076,35 +1074,91 @@ uint64_t tcfdbfsiz(TCFDB *fdb){
 /* Set the error code of a fixed-length database object. */
 void tcfdbsetecode(TCFDB *fdb, int ecode, const char *filename, int line, const char *func){
   assert(fdb && filename && line >= 1 && func);
-  int myerrno = errno;
-  if(!fdb->fatal){
-    fdb->ecode = ecode;
-    if(fdb->mmtx) pthread_setspecific(*(pthread_key_t *)fdb->eckey, (void *)(intptr_t)ecode);
-  }
-  if(ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC){
-    fdb->fatal = true;
-    if(fdb->fd >= 0 && (fdb->omode & FDBOWRITER)) tcfdbsetflag(fdb, FDBFFATAL, true);
+  if(!fdb->fatal) {
+      if (fdb->eckey) {
+          pthread_setspecific(*(pthread_key_t *)fdb->eckey, (void *)(intptr_t)ecode);
+      }
+      fdb->ecode = ecode;
+  }
+  switch (ecode) { //Fatal errors
+        case TCETHREAD:
+        case TCENOFILE:
+        case TCENOPERM:
+        case TCEMETA:
+        case TCERHEAD:
+        case TCEOPEN:
+        case TCECLOSE:
+        case TCETRUNC:
+        case TCESYNC:
+        case TCESTAT:
+        case TCESEEK:
+        case TCEREAD:
+        case TCEWRITE:
+        case TCEMMAP:
+        case TCELOCK:
+        case TCEUNLINK:
+        case TCERENAME:
+        case TCEMKDIR:
+        case TCERMDIR:
+        {
+            fdb->fatal = true;
+            if (!INVALIDHANDLE(fdb->fd) && (fdb->omode & FDBOWRITER)) tcfdbsetflag(fdb, FDBFFATAL, true);
+            break;
+        }
+        case TCESUCCESS:
+        case TCENOREC:
+        case TCEKEEP:
+          return;
+          break;
+        default:
+          break;
   }
-  if(fdb->dbgfd >= 0 && (fdb->dbgfd != UINT16_MAX || fdb->fatal)){
-    int dbgfd = (fdb->dbgfd == UINT16_MAX) ? 1 : fdb->dbgfd;
+#ifdef _WIN32
+  DWORD winerrno = GetLastError();
+#endif
+  int stderrno = errno;
+  if(!INVALIDHANDLE(fdb->dbgfd) || fdb->fatal) {
+    HANDLE dbgfd = INVALIDHANDLE(fdb->dbgfd) ? GET_STDERR_HANDLE() : (fdb->dbgfd);
     char obuf[FDBIOBUFSIZ];
-    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s\n", filename, line, func,
-                       fdb->path ? fdb->path : "-", ecode, tcfdberrmsg(ecode),
-                       myerrno, strerror(myerrno));
+#ifdef _WIN32
+    LPTSTR errorText = NULL;
+    if (winerrno > 0) {
+        DWORD ret = FormatMessage(
+            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
+            NULL, winerrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &errorText, 0, NULL);
+        if (!ret) {
+            if (errorText) LocalFree(errorText);
+            errorText = NULL;
+        }
+    }
+    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s:%d:%s\n",
+                       filename, line,
+                       func, (fdb->path ? fdb->path : "-"),
+                       ecode, tcfdberrmsg(ecode),
+                       winerrno, (errorText ? errorText : "-"),
+                       stderrno, (stderrno > 0 ? strerror(stderrno) : "-"));
+    if (errorText) LocalFree(errorText);
+#else
+    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s\n",
+                       filename, line,
+                       func, (fdb->path ? fdb->path : "-"),
+                       ecode, tcfdberrmsg(ecode),
+                       stderrno, strerror(stderrno));
+#endif
     tcwrite(dbgfd, obuf, osiz);
   }
 }
 
 
 /* Set the file descriptor for debugging output. */
-void tcfdbsetdbgfd(TCFDB *fdb, int fd){
-  assert(fdb && fd >= 0);
+void tcfdbsetdbgfd(TCFDB *fdb, HANDLE fd){
+  assert(fdb);
   fdb->dbgfd = fd;
 }
 
 
 /* Get the file descriptor for debugging output. */
-int tcfdbdbgfd(TCFDB *fdb){
+HANDLE tcfdbdbgfd(TCFDB *fdb){
   assert(fdb);
   return fdb->dbgfd;
 }
@@ -1120,7 +1174,7 @@ bool tcfdbhasmutex(TCFDB *fdb){
 /* Synchronize updating contents on memory of a fixed-length database object. */
 bool tcfdbmemsync(TCFDB *fdb, bool phys){
   assert(fdb);
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -1129,13 +1183,18 @@ bool tcfdbmemsync(TCFDB *fdb, bool phys){
   tcfdbdumpmeta(fdb, hbuf);
   memcpy(fdb->map, hbuf, FDBOPAQUEOFF);
   if(phys){
-#ifndef __GNU__
-    if(msync(fdb->map, fdb->limsiz, MS_SYNC) == -1){
+#ifdef _WIN32
+    if(!FlushViewOfFile(fdb->map, fdb->limsiz)){
+      tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);
+      err = true;
+    }
+#elif !defined  __GNU__
+    if(msync(fdb->map, fdb->limsiz, MS_SYNC)){
       tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);
       err = true;
     }
 #endif
-    if(fsync(fdb->fd) == -1){
+    if(fsync(fdb->fd)){
       tcfdbsetecode(fdb, TCESYNC, __FILE__, __LINE__, __func__);
       err = true;
     }
@@ -1147,7 +1206,7 @@ bool tcfdbmemsync(TCFDB *fdb, bool phys){
 /* Get the minimum ID number of records of a fixed-length database object. */
 uint64_t tcfdbmin(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1158,7 +1217,7 @@ uint64_t tcfdbmin(TCFDB *fdb){
 /* Get the maximum ID number of records of a fixed-length database object. */
 uint64_t tcfdbmax(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1169,7 +1228,7 @@ uint64_t tcfdbmax(TCFDB *fdb){
 /* Get the width of the value of each record of a fixed-length database object. */
 uint32_t tcfdbwidth(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1180,7 +1239,7 @@ uint32_t tcfdbwidth(TCFDB *fdb){
 /* Get the limit file size of a fixed-length database object. */
 uint64_t tcfdblimsiz(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1191,7 +1250,7 @@ uint64_t tcfdblimsiz(TCFDB *fdb){
 /* Get the limit ID number of a fixed-length database object. */
 uint64_t tcfdblimid(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1202,7 +1261,7 @@ uint64_t tcfdblimid(TCFDB *fdb){
 /* Get the inode number of the database file of a fixed-length database object. */
 uint64_t tcfdbinode(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1213,7 +1272,7 @@ uint64_t tcfdbinode(TCFDB *fdb){
 /* Get the modification time of the database file of a fixed-length database object. */
 time_t tcfdbmtime(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1224,7 +1283,7 @@ time_t tcfdbmtime(TCFDB *fdb){
 /* Get the connection mode of a fixed-length database object. */
 int tcfdbomode(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1235,7 +1294,7 @@ int tcfdbomode(TCFDB *fdb){
 /* Get the database type of a fixed-length database object. */
 uint8_t tcfdbtype(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1246,7 +1305,7 @@ uint8_t tcfdbtype(TCFDB *fdb){
 /* Get the additional flags of a fixed-length database object. */
 uint8_t tcfdbflags(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1257,7 +1316,7 @@ uint8_t tcfdbflags(TCFDB *fdb){
 /* Get the pointer to the opaque field of a fixed-length database object. */
 char *tcfdbopaque(TCFDB *fdb){
   assert(fdb);
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return NULL;
   }
@@ -1269,7 +1328,7 @@ char *tcfdbopaque(TCFDB *fdb){
 bool tcfdbputproc(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, TCPDPROC proc, void *op){
   assert(fdb && proc);
   if(!FDBLOCKMETHOD(fdb, id < 1)) return false;
-  if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){
+  if(INVALIDHANDLE(fdb->fd) || !(fdb->omode & FDBOWRITER)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -1327,7 +1386,7 @@ bool tcfdbputproc(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, TCPDPROC p
 bool tcfdbiterinit2(TCFDB *fdb, int64_t id){
   assert(fdb);
   if(!FDBLOCKMETHOD(fdb, true)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -1366,7 +1425,7 @@ bool tcfdbiterinit4(TCFDB *fdb, const char *kstr){
 bool tcfdbforeach(TCFDB *fdb, TCITER iter, void *op){
   assert(fdb && iter);
   if(!FDBLOCKMETHOD(fdb, false)) return false;
-  if(fdb->fd < 0){
+  if(INVALIDHANDLE(fdb->fd)){
     tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
     FDBUNLOCKMETHOD(fdb);
     return false;
@@ -1482,7 +1541,7 @@ static void tcfdbclear(TCFDB *fdb){
   fdb->rsiz = 0;
   fdb->limid = 0;
   fdb->path = NULL;
-  fdb->fd = -1;
+  fdb->fd = INVALID_HANDLE_VALUE;
   fdb->omode = 0;
   fdb->rnum = 0;
   fdb->fsiz = 0;
@@ -1496,9 +1555,9 @@ static void tcfdbclear(TCFDB *fdb){
   fdb->inode = 0;
   fdb->mtime = 0;
   fdb->tran = false;
-  fdb->walfd = -1;
+  fdb->walfd = INVALID_HANDLE_VALUE;
   fdb->walend = 0;
-  fdb->dbgfd = -1;
+  fdb->dbgfd = INVALID_HANDLE_VALUE;
   fdb->cnt_writerec = -1;
   fdb->cnt_readrec = -1;
   fdb->cnt_truncfile = -1;
@@ -1529,11 +1588,11 @@ static void tcfdbsetflag(TCFDB *fdb, int flag, bool sign){
    If successful, the return value is true, else, it is false. */
 static bool tcfdbwalinit(TCFDB *fdb){
   assert(fdb);
-  if(lseek(fdb->walfd, 0, SEEK_SET) == -1){
+  if(!tcfseek(fdb->walfd, 0, TCFSTART)){
     tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);
     return false;
   }
-  if(ftruncate(fdb->walfd, 0) == -1){
+  if(!tcftruncate(fdb->walfd, 0)){
     tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -1582,7 +1641,7 @@ static bool tcfdbwalwrite(TCFDB *fdb, uint64_t off, int64_t size){
     return false;
   }
   if(buf != stack) TCFREE(buf);
-  if((fdb->omode & FDBOTSYNC) && fsync(fdb->walfd) == -1){
+  if((fdb->omode & FDBOTSYNC) && fsync(fdb->walfd)){
     tcfdbsetecode(fdb, TCESYNC, __FILE__, __LINE__, __func__);
     FDBUNLOCKWAL(fdb);
     return false;
@@ -1599,33 +1658,36 @@ static bool tcfdbwalwrite(TCFDB *fdb, uint64_t off, int64_t size){
 static int tcfdbwalrestore(TCFDB *fdb, const char *path){
   assert(fdb && path);
   char *tpath = tcsprintf("%s%c%s", path, MYEXTCHR, FDBWALSUFFIX);
-  int walfd = open(tpath, O_RDONLY, FDBFILEMODE);
+  HANDLE walfd;
+#ifndef _WIN32
+  walfd = open(tpath, O_RDONLY, FDBFILEMODE);
+#else
+  walfd = CreateFile(tpath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
   TCFREE(tpath);
-  if(walfd < 0) return false;
+  if(INVALIDHANDLE(walfd)) return false;
   bool err = false;
   uint64_t walsiz = 0;
   struct stat sbuf;
-  if(fstat(walfd, &sbuf) == 0){
+  if(!fstat(walfd, &sbuf)){
     walsiz = sbuf.st_size;
   } else {
     tcfdbsetecode(fdb, TCESTAT, __FILE__, __LINE__, __func__);
     err = true;
   }
   if(walsiz >= sizeof(walsiz) + FDBHEADSIZ){
-    int dbfd = fdb->fd;
-    int tfd = -1;
+    HANDLE dbfd = fdb->fd;
+    HANDLE tfd = INVALID_HANDLE_VALUE;
     if(!(fdb->omode & FDBOWRITER)){
+#ifndef _WIN32
       tfd = open(path, O_WRONLY, FDBFILEMODE);
-      if(tfd >= 0){
+#else
+      tfd = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+      if(!INVALIDHANDLE(tfd)){
         dbfd = tfd;
       } else {
-        int ecode = TCEOPEN;
-        switch(errno){
-          case EACCES: ecode = TCENOPERM; break;
-          case ENOENT: ecode = TCENOFILE; break;
-          case ENOTDIR: ecode = TCENOFILE; break;
-        }
-        tcfdbsetecode(fdb, ecode, __FILE__, __LINE__, __func__);
+        tcfdbsetecode(fdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
         err = true;
       }
     }
@@ -1675,7 +1737,7 @@ static int tcfdbwalrestore(TCFDB *fdb, const char *path){
       uint64_t off = *(uint64_t *)rec;
       rec += sizeof(off);
       size -= sizeof(off);
-      if(lseek(dbfd, off, SEEK_SET) == -1){
+      if(!tcfseek(dbfd, off, TCFSTART)){
         tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);
         err = true;
         break;
@@ -1687,22 +1749,22 @@ static int tcfdbwalrestore(TCFDB *fdb, const char *path){
       }
     }
     tclistdel(list);
-    if(ftruncate(dbfd, fsiz) == -1){
+    if(!tcftruncate(dbfd, fsiz)){
       tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);
       err = true;
     }
-    if((fdb->omode & FDBOTSYNC) && fsync(dbfd) == -1){
+    if((fdb->omode & FDBOTSYNC) && fsync(dbfd)){
       tcfdbsetecode(fdb, TCESYNC, __FILE__, __LINE__, __func__);
       err = true;
     }
-    if(tfd >= 0 && close(tfd) == -1){
+    if(!INVALIDHANDLE(tfd) && !CLOSEFH(tfd)){
       tcfdbsetecode(fdb, TCECLOSE, __FILE__, __LINE__, __func__);
       err = true;
     }
   } else {
     err = true;
   }
-  if(close(walfd) == -1){
+  if(!CLOSEFH(walfd)){
     tcfdbsetecode(fdb, TCECLOSE, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -1718,7 +1780,7 @@ static bool tcfdbwalremove(TCFDB *fdb, const char *path){
   assert(fdb && path);
   char *tpath = tcsprintf("%s%c%s", path, MYEXTCHR, FDBWALSUFFIX);
   bool err = false;
-  if(unlink(tpath) == -1 && errno != ENOENT){
+  if(unlink(tpath) && errno != ENOENT){
     tcfdbsetecode(fdb, TCEUNLINK, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -1734,44 +1796,55 @@ static bool tcfdbwalremove(TCFDB *fdb, const char *path){
    If successful, the return value is true, else, it is false. */
 static bool tcfdbopenimpl(TCFDB *fdb, const char *path, int omode){
   assert(fdb && path);
+  HANDLE fd;
+#ifndef _WIN32
   int mode = O_RDONLY;
   if(omode & FDBOWRITER){
     mode = O_RDWR;
     if(omode & FDBOCREAT) mode |= O_CREAT;
   }
-  int fd = open(path, mode, FDBFILEMODE);
-  if(fd < 0){
-    int ecode = TCEOPEN;
-    switch(errno){
-      case EACCES: ecode = TCENOPERM; break;
-      case ENOENT: ecode = TCENOFILE; break;
-      case ENOTDIR: ecode = TCENOFILE; break;
-    }
-    tcfdbsetecode(fdb, ecode, __FILE__, __LINE__, __func__);
+  fd = open(path, mode, FDBFILEMODE);
+#else
+  DWORD mode, cmode;
+  mode = GENERIC_READ;
+  cmode = OPEN_EXISTING;
+  if(omode & FDBOWRITER) {
+    mode |= GENERIC_WRITE;
+  if(omode & (FDBOTRUNC|FDBOCREAT))
+       cmode = CREATE_ALWAYS;
+  else if(omode & FDBOTRUNC)
+       cmode = TRUNCATE_EXISTING;
+  else if(omode & FDBOCREAT)
+       cmode = CREATE_NEW;
+  }
+  fd = CreateFile(path, mode, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, cmode, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+  if(INVALIDHANDLE(fd)){
+    tcfdbsetecode(fdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
     return false;
   }
   if(!(omode & FDBONOLCK)){
     if(!tclock(fd, omode & FDBOWRITER, omode & FDBOLCKNB)){
       tcfdbsetecode(fdb, TCELOCK, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
   if((omode & FDBOWRITER) && (omode & FDBOTRUNC)){
-    if(ftruncate(fd, 0) == -1){
+    if(!tcftruncate(fd, 0)){
       tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     if(!tcfdbwalremove(fdb, path)){
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
   struct stat sbuf;
-  if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
+  if(fstat(fd, &sbuf) || !S_ISREG(sbuf.st_mode)){
     tcfdbsetecode(fdb, TCESTAT, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   char hbuf[FDBHEADSIZ];
@@ -1784,37 +1857,37 @@ static bool tcfdbopenimpl(TCFDB *fdb, const char *path, int omode){
     tcfdbdumpmeta(fdb, hbuf);
     if(!tcwrite(fd, hbuf, FDBHEADSIZ)){
       tcfdbsetecode(fdb, TCEWRITE, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     sbuf.st_size = fdb->fsiz;
   }
-  if(lseek(fd, 0, SEEK_SET) == -1){
+  if(!tcfseek(fd, 0, TCFSTART)){
     tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   if(!tcread(fd, hbuf, FDBHEADSIZ)){
     tcfdbsetecode(fdb, TCEREAD, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   int type = fdb->type;
   tcfdbloadmeta(fdb, hbuf);
   if((fdb->flags & FDBFOPEN) && tcfdbwalrestore(fdb, path)){
-    if(lseek(fd, 0, SEEK_SET) == -1){
+    if(!tcfseek(fd, 0, TCFSTART)){
       tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     if(!tcread(fd, hbuf, FDBHEADSIZ)){
       tcfdbsetecode(fdb, TCEREAD, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     tcfdbloadmeta(fdb, hbuf);
     if(!tcfdbwalremove(fdb, path)){
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
@@ -1823,16 +1896,28 @@ static bool tcfdbopenimpl(TCFDB *fdb, const char *path, int omode){
        fdb->width < 1 || sbuf.st_size < fdb->fsiz || fdb->limsiz < FDBHEADSIZ ||
        fdb->fsiz > fdb->limsiz){
       tcfdbsetecode(fdb, TCEMETA, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     if(sbuf.st_size > fdb->fsiz) fdb->fsiz = sbuf.st_size;
   }
-  void *map = mmap(0, fdb->limsiz, PROT_READ | ((omode & FDBOWRITER) ? PROT_WRITE : 0),
+#ifndef _WIN32
+  void *map = mmap(0, fdb->limsiz, (PROT_READ | ((omode & FDBOWRITER) ? PROT_WRITE : 0)),
                    MAP_SHARED, fd, 0);
   if(map == MAP_FAILED){
+#else
+  LARGE_INTEGER limit;
+  limit.QuadPart = fdb->limsiz;
+  fdb->fileMapping = CreateFileMapping(fd, NULL,
+                                      ((omode & FDBOWRITER) ? PAGE_READWRITE : PAGE_READONLY),
+                                      limit.HighPart, limit.LowPart, NULL);
+  void *map = MapViewOfFile(fdb->fileMapping,
+                           ((omode & FDBOWRITER) ? FILE_MAP_WRITE : FILE_MAP_READ),
+                           0, 0, 0);
+  if(map == NULL){
+#endif
     tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   if(fdb->width <= UINT8_MAX){
@@ -1855,7 +1940,7 @@ static bool tcfdbopenimpl(TCFDB *fdb, const char *path, int omode){
   fdb->inode = (uint64_t)sbuf.st_ino;
   fdb->mtime = sbuf.st_mtime;
   fdb->tran = false;
-  fdb->walfd = -1;
+  fdb->walfd = INVALID_HANDLE_VALUE;
   fdb->walend = 0;
   if(fdb->omode & FDBOWRITER) tcfdbsetflag(fdb, FDBFOPEN, true);
   return true;
@@ -1870,7 +1955,12 @@ static bool tcfdbcloseimpl(TCFDB *fdb){
   bool err = false;
   if(fdb->omode & FDBOWRITER) tcfdbsetflag(fdb, FDBFOPEN, false);
   if((fdb->omode & FDBOWRITER) && !tcfdbmemsync(fdb, false)) err = true;
-  if(munmap(fdb->map, fdb->limsiz) == -1){
+#ifndef _WIN32
+  if(munmap(fdb->map, fdb->limsiz)){
+#else
+  if(UnmapViewOfFile(fdb->map) && CloseHandle(fdb->fileMapping));
+  else{
+#endif
     tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -1878,20 +1968,20 @@ static bool tcfdbcloseimpl(TCFDB *fdb){
     if(!tcfdbwalrestore(fdb, fdb->path)) err = true;
     fdb->tran = false;
   }
-  if(fdb->walfd >= 0){
-    if(close(fdb->walfd) == -1){
+  if(!INVALIDHANDLE(fdb->walfd)){
+    if(!CLOSEFH(fdb->walfd)){
       tcfdbsetecode(fdb, TCECLOSE, __FILE__, __LINE__, __func__);
       err = true;
     }
     if(!fdb->fatal && !tcfdbwalremove(fdb, fdb->path)) err = true;
   }
-  if(close(fdb->fd) == -1){
+  if(!CLOSEFH(fdb->fd)){
     tcfdbsetecode(fdb, TCECLOSE, __FILE__, __LINE__, __func__);
     err = true;
   }
   TCFREE(fdb->path);
   fdb->path = NULL;
-  fdb->fd = -1;
+  fdb->fd = INVALID_HANDLE_VALUE;
   return !err;
 }
 
@@ -1994,7 +2084,7 @@ static bool tcfdbputimpl(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, int
         return false;
       }
       if(nsiz + fdb->rsiz * FDBTRUNCALW < fdb->limsiz) nsiz += fdb->rsiz * FDBTRUNCALW;
-      if(ftruncate(fdb->fd, nsiz) == -1){
+      if(!tcftruncate(fdb->fd, nsiz)){
         tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);
         FDBUNLOCKATTR(fdb);
         return false;
@@ -2387,7 +2477,9 @@ static uint64_t *tcfdbrangeimpl(TCFDB *fdb, int64_t lower, int64_t upper, int ma
    If successful, the return value is true, else, it is false. */
 static bool tcfdboptimizeimpl(TCFDB *fdb, int32_t width, int64_t limsiz){
   assert(fdb);
-  char *tpath = tcsprintf("%s%ctmp%c%llu", fdb->path, MYEXTCHR, MYEXTCHR, fdb->inode);
+  char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", fdb->path, MYEXTCHR, MYEXTCHR, fdb->inode);
+  char *opath;
+  int omode = (fdb->omode & ~FDBOCREAT) & ~FDBOTRUNC;
   TCFDB *tfdb = tcfdbnew();
   tfdb->dbgfd = fdb->dbgfd;
   if(width < 1) width = fdb->width;
@@ -2414,24 +2506,27 @@ static bool tcfdboptimizeimpl(TCFDB *fdb, int32_t width, int64_t limsiz){
     err = true;
   }
   tcfdbdel(tfdb);
-  if(unlink(fdb->path) == -1){
+  opath = tcstrdup(fdb->path);
+  if(!tcfdbcloseimpl(fdb)){
+    TCFREE(tpath);
+    TCFREE(opath);
+    return false;
+  }
+  if(unlink(opath)){
     tcfdbsetecode(fdb, TCEUNLINK, __FILE__, __LINE__, __func__);
     err = true;
   }
-  if(rename(tpath, fdb->path) == -1){
+  if(rename(tpath, opath)){
     tcfdbsetecode(fdb, TCERENAME, __FILE__, __LINE__, __func__);
     err = true;
   }
   TCFREE(tpath);
-  if(err) return false;
-  tpath = tcstrdup(fdb->path);
-  int omode = (fdb->omode & ~FDBOCREAT) & ~FDBOTRUNC;
-  if(!tcfdbcloseimpl(fdb)){
-    TCFREE(tpath);
+  if(err) {
+         TCFREE(opath);
     return false;
   }
-  bool rv = tcfdbopenimpl(fdb, tpath, omode);
-  TCFREE(tpath);
+  bool rv = tcfdbopenimpl(fdb, opath, omode);
+  TCFREE(opath);
   return rv;
 }
 
@@ -2468,7 +2563,7 @@ static bool tcfdbcopyimpl(TCFDB *fdb, const char *path){
   }
   if(*path == '@'){
     char tsbuf[TCNUMBUFSIZ];
-    sprintf(tsbuf, "%llu", (unsigned long long)(tctime() * 1000000));
+    sprintf(tsbuf, "%" PRIuMAX "", (unsigned long long)(tctime() * 1000000));
     const char *args[3];
     args[0] = path + 1;
     args[1] = fdb->path;
@@ -2523,7 +2618,7 @@ static bool tcfdbforeachimpl(TCFDB *fdb, TCITER iter, void *op){
     const void *vbuf = tcfdbgetimpl(fdb, id, &vsiz);
     if(vbuf){
       char kbuf[TCNUMBUFSIZ];
-      int ksiz = sprintf(kbuf, "%llu", (unsigned long long)id);
+      int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)id);
       if(!iter(kbuf, ksiz, vbuf, vsiz, op)) break;
     } else {
       tcfdbsetecode(fdb, TCEMISC, __FILE__, __LINE__, __func__);
@@ -2699,8 +2794,7 @@ static bool tcfdbunlockwal(TCFDB *fdb){
    `fdb' specifies the fixed-length database object. */
 void tcfdbprintmeta(TCFDB *fdb){
   assert(fdb);
-  if(fdb->dbgfd < 0) return;
-  int dbgfd = (fdb->dbgfd == UINT16_MAX) ? 1 : fdb->dbgfd;
+  HANDLE dbgfd = INVALIDHANDLE(fdb->dbgfd) ? GET_STDOUT_HANDLE() : fdb->dbgfd;
   char buf[FDBIOBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "META:");
@@ -2714,31 +2808,31 @@ void tcfdbprintmeta(TCFDB *fdb){
   wp += sprintf(wp, " type=%02X", fdb->type);
   wp += sprintf(wp, " flags=%02X", fdb->flags);
   wp += sprintf(wp, " width=%u", fdb->width);
-  wp += sprintf(wp, " limsiz=%llu", (unsigned long long)fdb->limsiz);
+  wp += sprintf(wp, " limsiz=%" PRIuMAX "", (unsigned long long)fdb->limsiz);
   wp += sprintf(wp, " wsiz=%u", fdb->wsiz);
   wp += sprintf(wp, " rsiz=%u", fdb->rsiz);
-  wp += sprintf(wp, " limid=%llu", (unsigned long long)fdb->limid);
+  wp += sprintf(wp, " limid=%" PRIuMAX "", (unsigned long long)fdb->limid);
   wp += sprintf(wp, " path=%s", fdb->path ? fdb->path : "-");
   wp += sprintf(wp, " fd=%d", fdb->fd);
   wp += sprintf(wp, " omode=%u", fdb->omode);
-  wp += sprintf(wp, " rnum=%llu", (unsigned long long)fdb->rnum);
-  wp += sprintf(wp, " fsiz=%llu", (unsigned long long)fdb->fsiz);
-  wp += sprintf(wp, " min=%llu", (unsigned long long)fdb->min);
-  wp += sprintf(wp, " max=%llu", (unsigned long long)fdb->max);
-  wp += sprintf(wp, " iter=%llu", (unsigned long long)fdb->iter);
+  wp += sprintf(wp, " rnum=%" PRIuMAX "", (unsigned long long)fdb->rnum);
+  wp += sprintf(wp, " fsiz=%" PRIuMAX "", (unsigned long long)fdb->fsiz);
+  wp += sprintf(wp, " min=%" PRIuMAX "", (unsigned long long)fdb->min);
+  wp += sprintf(wp, " max=%" PRIuMAX "", (unsigned long long)fdb->max);
+  wp += sprintf(wp, " iter=%" PRIuMAX "", (unsigned long long)fdb->iter);
   wp += sprintf(wp, " map=%p", (void *)fdb->map);
   wp += sprintf(wp, " array=%p", (void *)fdb->array);
   wp += sprintf(wp, " ecode=%d", fdb->ecode);
   wp += sprintf(wp, " fatal=%u", fdb->fatal);
-  wp += sprintf(wp, " inode=%llu", (unsigned long long)fdb->inode);
-  wp += sprintf(wp, " mtime=%llu", (unsigned long long)fdb->mtime);
+  wp += sprintf(wp, " inode=%" PRIuMAX "", (unsigned long long)fdb->inode);
+  wp += sprintf(wp, " mtime=%" PRIuMAX "", (unsigned long long)fdb->mtime);
   wp += sprintf(wp, " tran=%d", fdb->tran);
   wp += sprintf(wp, " walfd=%d", fdb->walfd);
-  wp += sprintf(wp, " walend=%llu", (unsigned long long)fdb->walend);
+  wp += sprintf(wp, " walend=%" PRIuMAX "", (unsigned long long)fdb->walend);
   wp += sprintf(wp, " dbgfd=%d", fdb->dbgfd);
-  wp += sprintf(wp, " cnt_writerec=%lld", (long long)fdb->cnt_writerec);
-  wp += sprintf(wp, " cnt_readrec=%lld", (long long)fdb->cnt_readrec);
-  wp += sprintf(wp, " cnt_truncfile=%lld", (long long)fdb->cnt_truncfile);
+  wp += sprintf(wp, " cnt_writerec=%" PRIdMAX "", (long long)fdb->cnt_writerec);
+  wp += sprintf(wp, " cnt_readrec=%" PRIdMAX "", (long long)fdb->cnt_readrec);
+  wp += sprintf(wp, " cnt_truncfile=%" PRIdMAX "", (long long)fdb->cnt_truncfile);
   *(wp++) = '\n';
   tcwrite(dbgfd, buf, wp - buf);
 }
index ffb5f44..2747d04 100644 (file)
@@ -52,7 +52,7 @@ typedef struct {                         /* type of structure for a fixed-length
   int rsiz;                              /* size of each record */
   uint64_t limid;                        /* limit ID number */
   char *path;                            /* path of the database file */
-  int fd;                                /* file descriptor of the database file */
+  HANDLE fd;                                /* file descriptor of the database file */
   uint32_t omode;                        /* open mode */
   uint64_t rnum;                         /* number of the records */
   uint64_t fsiz;                         /* size of the database file */
@@ -61,17 +61,20 @@ typedef struct {                         /* type of structure for a fixed-length
   uint64_t iter;                         /* ID number of the iterator */
   char *map;                             /* pointer to the mapped memory */
   unsigned char *array;                  /* pointer to the array region */
-  int ecode;                             /* last happened error code */
+  volatile int ecode;                    /* last happened error code */
   bool fatal;                            /* whether a fatal error occured */
   uint64_t inode;                        /* inode number */
   time_t mtime;                          /* modification time */
   bool tran;                             /* whether in the transaction */
-  int walfd;                             /* file descriptor of write ahead logging */
+  HANDLE walfd;                             /* file descriptor of write ahead logging */
   uint64_t walend;                       /* end offset of write ahead logging */
-  int dbgfd;                             /* file descriptor for debugging */
+  HANDLE dbgfd;                             /* file descriptor for debugging */
   int64_t cnt_writerec;                  /* tesing counter for record write times */
   int64_t cnt_readrec;                   /* tesing counter for record read times */
   int64_t cnt_truncfile;                 /* tesing counter for file truncate times */
+#ifdef _WIN32
+  volatile HANDLE fileMapping;                  /* win32 file mappings for mmap */
+#endif
 } TCFDB;
 
 enum {                                   /* enumeration for additional flags */
@@ -675,13 +678,13 @@ void tcfdbsetecode(TCFDB *fdb, int ecode, const char *filename, int line, const
 /* Set the file descriptor for debugging output.
    `fdb' specifies the fixed-length database object.
    `fd' specifies the file descriptor for debugging output. */
-void tcfdbsetdbgfd(TCFDB *fdb, int fd);
+void tcfdbsetdbgfd(TCFDB *fdb, HANDLE fd);
 
 
 /* Get the file descriptor for debugging output.
    `fdb' specifies the fixed-length database object.
    The return value is the file descriptor for debugging output. */
-int tcfdbdbgfd(TCFDB *fdb);
+HANDLE tcfdbdbgfd(TCFDB *fdb);
 
 
 /* Check whether mutual exclusion control is set to a fixed-length database object.
index 85c2eda..f577db0 100644 (file)
@@ -21,7 +21,7 @@
 
 /* global variables */
 const char *g_progname;                  // program name
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -55,9 +55,16 @@ static int procversion(void);
 /* main routine */
 int main(int argc, char **argv){
   g_progname = argv[0];
-  g_dbgfd = -1;
+  g_dbgfd = INVALID_HANDLE_VALUE;
   const char *ebuf = getenv("TCDBGFD");
-  if(ebuf) g_dbgfd = tcatoix(ebuf);
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "create")){
@@ -470,7 +477,7 @@ static int runversion(int argc, char **argv){
 /* perform create command */
 static int proccreate(const char *path, int width, int64_t limsiz){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbtune(fdb, width, limsiz)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -494,7 +501,7 @@ static int proccreate(const char *path, int width, int64_t limsiz){
 /* perform inform command */
 static int procinform(const char *path, int omode){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOREADER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -517,17 +524,17 @@ static int procinform(const char *path, int omode){
   if(flags & FDBFOPEN) printf(" open");
   if(flags & FDBFFATAL) printf(" fatal");
   printf("\n");
-  printf("minimum ID number: %llu\n", (unsigned long long)tcfdbmin(fdb));
-  printf("maximum ID number: %llu\n", (unsigned long long)tcfdbmax(fdb));
+  printf("minimum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmin(fdb));
+  printf("maximum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmax(fdb));
   printf("width of the value: %u\n", (unsigned int)tcfdbwidth(fdb));
-  printf("limit file size: %llu\n", (unsigned long long)tcfdblimsiz(fdb));
-  printf("limit ID number: %llu\n", (unsigned long long)tcfdblimid(fdb));
-  printf("inode number: %lld\n", (long long)tcfdbinode(fdb));
+  printf("limit file size: %" PRIuMAX "\n", (unsigned long long)tcfdblimsiz(fdb));
+  printf("limit ID number: %" PRIuMAX "\n", (unsigned long long)tcfdblimid(fdb));
+  printf("inode number: %" PRIdMAX "\n", (long long)tcfdbinode(fdb));
   char date[48];
   tcdatestrwww(tcfdbmtime(fdb), INT_MAX, date);
   printf("modified time: %s\n", date);
-  printf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  printf("file size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  printf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  printf("file size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   if(!tcfdbclose(fdb)){
     if(!err) printerr(fdb);
     err = true;
@@ -541,7 +548,7 @@ static int procinform(const char *path, int omode){
 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
                    int omode, int dmode){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOWRITER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -600,7 +607,7 @@ static int procput(const char *path, const char *kbuf, int ksiz, const char *vbu
 /* perform out command */
 static int procout(const char *path, const char *kbuf, int ksiz, int omode){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOWRITER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -623,7 +630,7 @@ static int procout(const char *path, const char *kbuf, int ksiz, int omode){
 /* perform get command */
 static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOREADER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -653,7 +660,7 @@ static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool
 static int proclist(const char *path, int omode, int max, bool pv, bool px,
                     const char *rlstr, const char *rustr, const char *ristr){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOREADER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -686,7 +693,7 @@ static int proclist(const char *path, int omode, int max, bool pv, bool px,
     int cnt = 0;
     uint64_t id;
     while((id = tcfdbiternext(fdb)) > 0){
-      printf("%llu", (unsigned long long)id);
+      printf("%" PRIuMAX "", (unsigned long long)id);
       if(pv){
         int vsiz;
         char *vbuf = tcfdbget(fdb, id, &vsiz);
@@ -712,7 +719,7 @@ static int proclist(const char *path, int omode, int max, bool pv, bool px,
 /* perform optimize command */
 static int procoptimize(const char *path, int width, int64_t limsiz, int omode){
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOWRITER | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
@@ -740,7 +747,7 @@ static int procimporttsv(const char *path, const char *file, int omode, bool sc)
     return 1;
   }
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbopen(fdb, path, FDBOWRITER | FDBOCREAT | omode)){
     printerr(fdb);
     tcfdbdel(fdb);
index 8b9124d..2202031 100644 (file)
@@ -63,7 +63,7 @@ typedef struct {                         // type of structure for typical thread
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -103,7 +103,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -176,14 +183,14 @@ static void eprint(TCFDB *fdb, int line, const char *func){
 /* print members of fixed-length database */
 static void mprint(TCFDB *fdb){
   if(fdb->cnt_writerec < 0) return;
-  iprintf("minimum ID number: %llu\n", (unsigned long long)tcfdbmin(fdb));
-  iprintf("maximum ID number: %llu\n", (unsigned long long)tcfdbmax(fdb));
+  iprintf("minimum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmin(fdb));
+  iprintf("maximum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmax(fdb));
   iprintf("width of the value: %u\n", (unsigned int)tcfdbwidth(fdb));
-  iprintf("limit file size: %llu\n", (unsigned long long)tcfdblimsiz(fdb));
-  iprintf("limit ID number: %llu\n", (unsigned long long)tcfdblimid(fdb));
-  iprintf("cnt_writerec: %lld\n", (long long)fdb->cnt_writerec);
-  iprintf("cnt_readrec: %lld\n", (long long)fdb->cnt_readrec);
-  iprintf("cnt_truncfile: %lld\n", (long long)fdb->cnt_truncfile);
+  iprintf("limit file size: %" PRIuMAX "\n", (unsigned long long)tcfdblimsiz(fdb));
+  iprintf("limit ID number: %" PRIuMAX "\n", (unsigned long long)tcfdblimid(fdb));
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)fdb->cnt_writerec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)fdb->cnt_readrec);
+  iprintf("cnt_truncfile: %" PRIdMAX "\n", (long long)fdb->cnt_truncfile);
 }
 
 
@@ -434,13 +441,12 @@ static int runtypical(int argc, char **argv){
 /* perform write command */
 static int procwrite(const char *path, int tnum, int rnum, int width, int64_t limsiz,
                      int omode, bool rnd){
-  iprintf("<Writing Test>\n  seed=%u  path=%s  tnum=%d  rnum=%d  width=%d  limsiz=%lld"
-          "  omode=%d  rnd=%d\n\n",
+  iprintf("<Writing Test>\n  seed=%u  path=%s  tnum=%d  rnum=%d  width=%d  limsiz=%" PRIdMAX "  omode=%d  rnd=%d\n\n",
           g_randseed, path, tnum, rnum, width, (long long)limsiz, omode, rnd);
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -484,8 +490,8 @@ static int procwrite(const char *path, int tnum, int rnum, int width, int64_t li
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -506,7 +512,7 @@ static int procread(const char *path, int tnum, int omode, bool wb, bool rnd){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -549,8 +555,8 @@ static int procread(const char *path, int tnum, int omode, bool wb, bool rnd){
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -571,7 +577,7 @@ static int procremove(const char *path, int tnum, int omode, bool rnd){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -612,8 +618,8 @@ static int procremove(const char *path, int tnum, int omode, bool rnd){
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -634,7 +640,7 @@ static int procwicked(const char *path, int tnum, int rnum, int omode, bool nc){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -725,8 +731,8 @@ static int procwicked(const char *path, int tnum, int rnum, int omode, bool nc){
     if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
   }
   tcmapdel(map);
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -743,13 +749,12 @@ static int procwicked(const char *path, int tnum, int rnum, int omode, bool nc){
 /* perform typical command */
 static int proctypical(const char *path, int tnum, int rnum, int width, int64_t limsiz,
                        int omode, bool nc, int rratio){
-  iprintf("<Typical Access Test>\n  seed=%u  path=%s  tnum=%d  rnum=%d  width=%d  limsiz=%lld"
-          "  omode=%d  nc=%d  rratio=%d\n\n",
+  iprintf("<Typical Access Test>\n  seed=%u  path=%s  tnum=%d  rnum=%d  width=%d  limsiz=%" PRIdMAX "  omode=%d  nc=%d  rratio=%d\n\n",
           g_randseed, path, tnum, rnum, width, (long long)limsiz, omode, nc, rratio);
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(!tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -795,8 +800,8 @@ static int proctypical(const char *path, int tnum, int rnum, int width, int64_t
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -907,7 +912,7 @@ static void *threadwicked(void *targ){
   for(int i = 1; i <= rnum && !err; i++){
     uint64_t kid = myrand(rnum * (id + 1)) + 1;
     char kbuf[RECBUFSIZ];
-    int ksiz = sprintf(kbuf, "%llu", (unsigned long long)kid);
+    int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)kid);
     char vbuf[RECBUFSIZ];
     int vsiz = myrand(RECBUFSIZ);
     memset(vbuf, '*', vsiz);
index a11c273..b239b80 100644 (file)
@@ -25,7 +25,7 @@
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -61,8 +61,16 @@ int main(int argc, char **argv){
   const char *ebuf = getenv("TCRNDSEED");
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
+  g_dbgfd = INVALID_HANDLE_VALUE;
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -130,22 +138,57 @@ static void iputchar(int c){
 static void eprint(TCFDB *fdb, int line, const char *func){
   const char *path = tcfdbpath(fdb);
   int ecode = tcfdbecode(fdb);
-  fprintf(stderr, "%s: %s: %d: %s: error: %d: %s\n",
-          g_progname, path ? path : "-", line, func, ecode, tcfdberrmsg(ecode));
+  int stderrno = errno;
+#ifdef _WIN32
+ DWORD myerrno = GetLastError();
+ LPTSTR errorText = NULL;
+ DWORD ret = FormatMessage(
+    // use system message tables to retrieve error text
+    FORMAT_MESSAGE_FROM_SYSTEM
+    // allocate buffer on local heap for error text
+    |FORMAT_MESSAGE_ALLOCATE_BUFFER
+    // Important! will fail otherwise, since we're not
+    // (and CANNOT) pass insertion parameters
+    |FORMAT_MESSAGE_IGNORE_INSERTS,
+    NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
+    myerrno,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+    (LPTSTR)&errorText,  // output
+    0, // minimum size for output buffer
+    NULL);   // arguments - see note
+    if (!ret) {
+       if (errorText) LocalFree(errorText);
+       errorText = NULL;
+    }
+    fprintf(stderr, "%s: %s: %d: %s: error: %d:%s:%d:%s:%d:%s\n",
+          g_progname, path ? path : "-",
+          line, func,
+          ecode, tcfdberrmsg(ecode),
+          myerrno, errorText ? errorText : "-",
+          stderrno, strerror(stderrno));
+
+    if (errorText) LocalFree(errorText);
+#else
+  fprintf(stderr, "%s: %s: %d: %s: error: %d:%s:%d:%s\n",
+          g_progname, path ? path : "-",
+          line, func,
+          ecode, tcfdberrmsg(ecode),
+          stderrno, strerror(stderrno));
+#endif
 }
 
 
 /* print members of fixed-length database */
 static void mprint(TCFDB *fdb){
   if(fdb->cnt_writerec < 0) return;
-  iprintf("minimum ID number: %llu\n", (unsigned long long)tcfdbmin(fdb));
-  iprintf("maximum ID number: %llu\n", (unsigned long long)tcfdbmax(fdb));
+  iprintf("minimum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmin(fdb));
+  iprintf("maximum ID number: %" PRIuMAX "\n", (unsigned long long)tcfdbmax(fdb));
   iprintf("width of the value: %u\n", (unsigned int)tcfdbwidth(fdb));
-  iprintf("limit file size: %llu\n", (unsigned long long)tcfdblimsiz(fdb));
-  iprintf("limit ID number: %llu\n", (unsigned long long)tcfdblimid(fdb));
-  iprintf("cnt_writerec: %lld\n", (long long)fdb->cnt_writerec);
-  iprintf("cnt_readrec: %lld\n", (long long)fdb->cnt_readrec);
-  iprintf("cnt_truncfile: %lld\n", (long long)fdb->cnt_truncfile);
+  iprintf("limit file size: %" PRIuMAX "\n", (unsigned long long)tcfdblimsiz(fdb));
+  iprintf("limit ID number: %" PRIuMAX "\n", (unsigned long long)tcfdblimid(fdb));
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)fdb->cnt_writerec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)fdb->cnt_readrec);
+  iprintf("cnt_truncfile: %" PRIdMAX "\n", (long long)fdb->cnt_truncfile);
 }
 
 
@@ -449,12 +492,12 @@ static int runwicked(int argc, char **argv){
 /* perform write command */
 static int procwrite(const char *path, int rnum, int width, int64_t limsiz,
                      bool mt, int omode, bool rnd){
-  iprintf("<Writing Test>\n  seed=%u  path=%s  rnum=%d  width=%d  limsiz=%lld  mt=%d  omode=%d"
+  iprintf("<Writing Test>\n  seed=%u  path=%s  rnum=%d  width=%d  limsiz=%" PRIdMAX "  mt=%d  omode=%d"
           "  rnd=%d\n\n", g_randseed, path, rnum, width, (long long)limsiz, mt, omode, rnd);
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -481,8 +524,8 @@ static int procwrite(const char *path, int rnum, int width, int64_t limsiz,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -503,7 +546,7 @@ static int procread(const char *path, bool mt, int omode, bool wb, bool rnd){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -539,8 +582,8 @@ static int procread(const char *path, bool mt, int omode, bool wb, bool rnd){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -561,7 +604,7 @@ static int procremove(const char *path, bool mt, int omode, bool rnd){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -584,8 +627,8 @@ static int procremove(const char *path, bool mt, int omode, bool rnd){
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -603,14 +646,14 @@ static int procremove(const char *path, bool mt, int omode, bool rnd){
 static int procrcat(const char *path, int rnum, int width, int64_t limsiz,
                     bool mt, int omode, int pnum, bool dai, bool dad, bool rl, bool ru){
   iprintf("<Random Concatenating Test>\n"
-          "  seed=%u  path=%s  rnum=%d  width=%d  limsiz=%lld  mt=%d  omode=%d  pnum=%d"
+          "  seed=%u  path=%s  rnum=%d  width=%d  limsiz=%" PRIdMAX "  mt=%d  omode=%d  pnum=%d"
           "  dai=%d  dad=%d  rl=%d  ru=%d\n\n",
           g_randseed, path, rnum, width, (long long)limsiz, mt, omode, pnum, dai, dad, rl, ru);
   if(pnum < 1) pnum = rnum;
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -717,8 +760,8 @@ static int procrcat(const char *path, int rnum, int width, int64_t limsiz,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -739,7 +782,7 @@ static int procmisc(const char *path, int rnum, bool mt, int omode){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -752,7 +795,7 @@ static int procmisc(const char *path, int rnum, bool mt, int omode){
     eprint(fdb, __LINE__, "tcfdbopen");
     err = true;
   }
-  if(TCUSEPTHREAD){
+  if(1){
     TCFDB *fdbdup = tcfdbnew();
     if(tcfdbopen(fdbdup, path, FDBOREADER)){
       eprint(fdb, __LINE__, "(validation)");
@@ -1356,8 +1399,8 @@ static int procmisc(const char *path, int rnum, bool mt, int omode){
       err = true;
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   if(!tcfdbclose(fdb)){
@@ -1378,7 +1421,7 @@ static int procwicked(const char *path, int rnum, bool mt, int omode){
   bool err = false;
   double stime = tctime();
   TCFDB *fdb = tcfdbnew();
-  if(g_dbgfd >= 0) tcfdbsetdbgfd(fdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tcfdbsetdbgfd(fdb, g_dbgfd);
   if(mt && !tcfdbsetmutex(fdb)){
     eprint(fdb, __LINE__, "tcfdbsetmutex");
     err = true;
@@ -1399,7 +1442,7 @@ static int procwicked(const char *path, int rnum, bool mt, int omode){
   for(int i = 1; i <= rnum && !err; i++){
     uint64_t id = myrand(rnum) + 1;
     char kbuf[RECBUFSIZ];
-    int ksiz = sprintf(kbuf, "%llu", (unsigned long long)id);
+    int ksiz = sprintf(kbuf, "%" PRIuMAX "", (unsigned long long)id);
     char vbuf[RECBUFSIZ];
     int vsiz = myrand(RECBUFSIZ);
     memset(vbuf, '*', vsiz);
@@ -1675,8 +1718,8 @@ static int procwicked(const char *path, int rnum, bool mt, int omode){
     eprint(fdb, __LINE__, "(validation)");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcfdbrnum(fdb));
-  iprintf("size: %llu\n", (unsigned long long)tcfdbfsiz(fdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcfdbrnum(fdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcfdbfsiz(fdb));
   mprint(fdb);
   sysprint();
   tcmapdel(map);
index 525aeb4..ba10139 100644 (file)
@@ -23,7 +23,7 @@
 #define HDBIOBUFSIZ    8192              // size of an I/O buffer
 
 #define HDBMAGICDATA   "ToKyO CaBiNeT"   // magic data for identification
-#define HDBHEADSIZ     256               // size of the reagion of the header
+#define HDBHEADSIZ     256               // size of the region of the header
 #define HDBTYPEOFF     32                // offset of the region for the database type
 #define HDBFLAGSOFF    33                // offset of the region for the additional flags
 #define HDBAPOWOFF     34                // offset of the region for the alignment power
 #define HDBFSIZOFF     56                // offset of the region for the file size
 #define HDBFRECOFF     64                // offset of the region for the first record offset
 #define HDBOPAQUEOFF   128               // offset of the region for the opaque field
+#define HDBOPAQUESZ    HDBHEADSIZ - HDBOPAQUEOFF //opaque data size
+#define HDBB64(TC_hdb)  ((uint64_t *) ((char *)((TC_hdb)->map) + HDBHEADSIZ))
+#define HDBB32(TC_hdb)  ((uint32_t *) ((char *)((TC_hdb)->map) + HDBHEADSIZ))
 
 #define HDBDEFBNUM     131071            // default bucket number
 #define HDBDEFAPOW     4                 // default alignment power
 #define HDBMAXAPOW     16                // maximum alignment power
 #define HDBDEFFPOW     10                // default free block pool power
 #define HDBMAXFPOW     20                // maximum free block pool power
+
+#ifdef _WIN32
+#define HDBDEFXMSIZ    _maxof(off_t)     // default size of the extra mapped memory
+#define HDBXFSIZINC    1048576           // 1MB on win32
+#else
 #define HDBDEFXMSIZ    (64LL<<20)        // default size of the extra mapped memory
 #define HDBXFSIZINC    32768             // increment of extra file size
+#endif
 #define HDBMINRUNIT    48                // minimum record reading unit
 #define HDBMAXHSIZ     32                // maximum record header size
 #define HDBFBPALWRAT   2                 // allowance ratio of the free block pool
@@ -96,6 +105,11 @@ typedef struct {                         // type of structure for a duplication
 } HDBPDPROCOP;
 
 
+enum {
+    HDBWRITENOWALL = 1,                 //do not write into wall in tchdbseekwrite
+    HDBWRITENOLOCK = 1 << 1             //do not use shared write lock in tchdbseekwrite & tchdbftruncate
+};
+
 /* private macros */
 #define HDBLOCKMETHOD(TC_hdb, TC_wr)                            \
   ((TC_hdb)->mmtx ? tchdblockmethod((TC_hdb), (TC_wr)) : true)
@@ -113,6 +127,12 @@ typedef struct {                         // type of structure for a duplication
   ((TC_hdb)->mmtx ? tchdblockdb(TC_hdb) : true)
 #define HDBUNLOCKDB(TC_hdb)                             \
   ((TC_hdb)->mmtx ? tchdbunlockdb(TC_hdb) : true)
+
+#define HDBLOCKSMEM(TC_hdb, TC_wr)                       \
+  ((TC_hdb)->smtx ? tchdblocksmem((TC_hdb), (TC_wr)) : true)
+#define HDBUNLOCKSMEM(TC_hdb)                             \
+  ((TC_hdb)->smtx ? tchdbunlocksmem(TC_hdb) : true)
+
 #define HDBLOCKWAL(TC_hdb)                              \
   ((TC_hdb)->mmtx ? tchdblockwal(TC_hdb) : true)
 #define HDBUNLOCKWAL(TC_hdb)                            \
@@ -124,6 +144,7 @@ typedef struct {                         // type of structure for a duplication
 /* private function prototypes */
 static uint64_t tcgetprime(uint64_t num);
 static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size);
+static bool tchdbseekwrite2(TCHDB *hdb, off_t off, const void *buf, size_t size, int opts);
 static bool tchdbseekread(TCHDB *hdb, off_t off, void *buf, size_t size);
 static bool tchdbseekreadtry(TCHDB *hdb, off_t off, void *buf, size_t size);
 static void tchdbdumpmeta(TCHDB *hdb, char *hbuf);
@@ -154,7 +175,7 @@ static bool tchdbflushdrp(TCHDB *hdb);
 static void tchdbcacheadjust(TCHDB *hdb);
 static bool tchdbwalinit(TCHDB *hdb);
 static bool tchdbwalwrite(TCHDB *hdb, uint64_t off, int64_t size);
-static int tchdbwalrestore(TCHDB *hdb, const char *path);
+static bool tchdbwalrestore(TCHDB *hdb, const char *path);
 static bool tchdbwalremove(TCHDB *hdb, const char *path);
 static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode);
 static bool tchdbcloseimpl(TCHDB *hdb);
@@ -184,17 +205,21 @@ static bool tchdbcopyimpl(TCHDB *hdb, const char *path);
 static bool tchdbdefragimpl(TCHDB *hdb, int64_t step);
 static bool tchdbiterjumpimpl(TCHDB *hdb, const char *kbuf, int ksiz);
 static bool tchdbforeachimpl(TCHDB *hdb, TCITER iter, void *op);
-static bool tchdblockmethod(TCHDB *hdb, bool wr);
-static bool tchdbunlockmethod(TCHDB *hdb);
-static bool tchdblockrecord(TCHDB *hdb, uint8_t bidx, bool wr);
-static bool tchdbunlockrecord(TCHDB *hdb, uint8_t bidx);
-static bool tchdblockallrecords(TCHDB *hdb, bool wr);
-static bool tchdbunlockallrecords(TCHDB *hdb);
-static bool tchdblockdb(TCHDB *hdb);
-static bool tchdbunlockdb(TCHDB *hdb);
-static bool tchdblockwal(TCHDB *hdb);
-static bool tchdbunlockwal(TCHDB *hdb);
-
+static bool tchdbftruncate(TCHDB *hdb, off_t length);
+static bool tchdbftruncate2(TCHDB *hdb, off_t length, int opts);
+
+EJDB_INLINE bool tchdblockmethod(TCHDB *hdb, bool wr);
+EJDB_INLINE bool tchdbunlockmethod(TCHDB *hdb);
+EJDB_INLINE bool tchdblocksmem(TCHDB *hdb, bool wr);
+EJDB_INLINE bool tchdbunlocksmem(TCHDB *hdb);
+EJDB_INLINE bool tchdblockrecord(TCHDB *hdb, uint8_t bidx, bool wr);
+EJDB_INLINE bool tchdbunlockrecord(TCHDB *hdb, uint8_t bidx);
+EJDB_INLINE bool tchdblockallrecords(TCHDB *hdb, bool wr);
+EJDB_INLINE bool tchdbunlockallrecords(TCHDB *hdb);
+EJDB_INLINE bool tchdblockdb(TCHDB *hdb);
+EJDB_INLINE bool tchdbunlockdb(TCHDB *hdb);
+EJDB_INLINE bool tchdblockwal(TCHDB *hdb);
+EJDB_INLINE bool tchdbunlockwal(TCHDB *hdb);
 
 /* debugging function prototypes */
 void tchdbprintmeta(TCHDB *hdb);
@@ -225,7 +250,7 @@ TCHDB *tchdbnew(void){
 /* Delete a hash database object. */
 void tchdbdel(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd >= 0) tchdbclose(hdb);
+  if(!INVALIDHANDLE(hdb->fd)) tchdbclose(hdb);
   if(hdb->mmtx){
     pthread_mutex_destroy(hdb->wmtx);
     pthread_mutex_destroy(hdb->dmtx);
@@ -233,8 +258,10 @@ void tchdbdel(TCHDB *hdb){
       pthread_rwlock_destroy((pthread_rwlock_t *)hdb->rmtxs + i);
     }
     pthread_rwlock_destroy(hdb->mmtx);
+    pthread_rwlock_destroy(hdb->smtx);
     TCFREE(hdb->wmtx);
     TCFREE(hdb->dmtx);
+    TCFREE(hdb->smtx);
     TCFREE(hdb->rmtxs);
     TCFREE(hdb->mmtx);
   }
@@ -256,19 +283,20 @@ int tchdbecode(TCHDB *hdb){
 /* Set mutual exclusion control of a hash database object for threading. */
 bool tchdbsetmutex(TCHDB *hdb){
   assert(hdb);
-  if(!TCUSEPTHREAD) return true;
-  if(hdb->mmtx || hdb->fd >= 0){
+  if(hdb->mmtx || !INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
   pthread_mutexattr_t rma;
   pthread_mutexattr_init(&rma);
   TCMALLOC(hdb->mmtx, sizeof(pthread_rwlock_t));
+  TCMALLOC(hdb->smtx, sizeof(pthread_rwlock_t));
   TCMALLOC(hdb->rmtxs, (UINT8_MAX + 1) * sizeof(pthread_rwlock_t));
   TCMALLOC(hdb->dmtx, sizeof(pthread_mutex_t));
   TCMALLOC(hdb->wmtx, sizeof(pthread_mutex_t));
   bool err = false;
   if(pthread_mutexattr_settype(&rma, PTHREAD_MUTEX_RECURSIVE) != 0) err = true;
+  if(pthread_rwlock_init(hdb->smtx, NULL) != 0) err = true;
   if(pthread_rwlock_init(hdb->mmtx, NULL) != 0) err = true;
   for(int i = 0; i <= UINT8_MAX; i++){
     if(pthread_rwlock_init((pthread_rwlock_t *)hdb->rmtxs + i, NULL) != 0) err = true;
@@ -281,10 +309,12 @@ bool tchdbsetmutex(TCHDB *hdb){
     TCFREE(hdb->wmtx);
     TCFREE(hdb->dmtx);
     TCFREE(hdb->rmtxs);
+    TCFREE(hdb->smtx);
     TCFREE(hdb->mmtx);
     hdb->wmtx = NULL;
     hdb->dmtx = NULL;
     hdb->rmtxs = NULL;
+    hdb->smtx = NULL;
     hdb->mmtx = NULL;
     return false;
   }
@@ -296,7 +326,7 @@ bool tchdbsetmutex(TCHDB *hdb){
 /* Set the tuning parameters of a hash database object. */
 bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
   assert(hdb);
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -313,7 +343,7 @@ bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts)
 /* Set the caching parameters of a hash database object. */
 bool tchdbsetcache(TCHDB *hdb, int32_t rcnum){
   assert(hdb);
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -324,20 +354,25 @@ bool tchdbsetcache(TCHDB *hdb, int32_t rcnum){
 
 /* Set the size of the extra mapped memory of a hash database object. */
 bool tchdbsetxmsiz(TCHDB *hdb, int64_t xmsiz){
+#ifdef _WIN32
+  fprintf(stderr, "\ntchdbsetxmsiz does not takes effect on windows platform\n");
+  return true;
+#else
   assert(hdb);
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
   hdb->xmsiz = (xmsiz > 0) ? tcpagealign(xmsiz) : 0;
   return true;
+#endif
 }
 
 
 /* Set the unit step number of auto defragmentation of a hash database object. */
 bool tchdbsetdfunit(TCHDB *hdb, int32_t dfunit){
   assert(hdb);
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -350,6 +385,11 @@ bool tchdbsetdfunit(TCHDB *hdb, int32_t dfunit){
 bool tchdbopen(TCHDB *hdb, const char *path, int omode){
   assert(hdb && path);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
+  if(!INVALIDHANDLE(hdb->fd)){
+    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
+    HDBUNLOCKMETHOD(hdb);
+    return false;
+  }
   if (!hdb->eckey) {
       TCMALLOC(hdb->eckey, sizeof(pthread_key_t));
       if(pthread_key_create(hdb->eckey, NULL)) {
@@ -359,20 +399,9 @@ bool tchdbopen(TCHDB *hdb, const char *path, int omode){
           return false;
       }
   }
-  if(hdb->fd >= 0){
-    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
-    HDBUNLOCKMETHOD(hdb);
-    return false;
-  }
   char *rpath = tcrealpath(path);
   if(!rpath){
-    int ecode = TCEOPEN;
-    switch(errno){
-      case EACCES: ecode = TCENOPERM; break;
-      case ENOENT: ecode = TCENOFILE; break;
-      case ENOTDIR: ecode = TCENOFILE; break;
-    }
-    tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);
+    tchdbsetecode(hdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
   }
@@ -398,7 +427,7 @@ bool tchdbopen(TCHDB *hdb, const char *path, int omode){
 bool tchdbclose(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -418,7 +447,7 @@ bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
   if(!HDBLOCKMETHOD(hdb, false)) return false;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -478,7 +507,7 @@ bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
   if(!HDBLOCKMETHOD(hdb, false)) return false;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -537,7 +566,7 @@ bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int v
   if(!HDBLOCKMETHOD(hdb, false)) return false;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -615,7 +644,7 @@ bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
   hdb->async = true;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -660,7 +689,7 @@ bool tchdbout(TCHDB *hdb, const void *kbuf, int ksiz){
   if(!HDBLOCKMETHOD(hdb, false)) return false;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -695,7 +724,7 @@ void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp){
   if(!HDBLOCKMETHOD(hdb, false)) return NULL;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return NULL;
@@ -719,7 +748,7 @@ int tchdbgetintoxstr(TCHDB *hdb, const void *kbuf, int ksiz, TCXSTR *xstr) {
     if (!HDBLOCKMETHOD(hdb, false)) return -1;
     uint8_t hash;
     uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-    if (hdb->fd < 0) {
+    if (INVALIDHANDLE(hdb->fd)) {
         tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
         HDBUNLOCKMETHOD(hdb);
         return -1;
@@ -753,7 +782,7 @@ int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max){
   if(!HDBLOCKMETHOD(hdb, false)) return -1;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return -1;
@@ -779,7 +808,7 @@ int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz){
   if(!HDBLOCKMETHOD(hdb, false)) return -1;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return -1;
@@ -810,7 +839,7 @@ int tchdbvsiz2(TCHDB *hdb, const char *kstr){
 bool tchdbiterinit(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -828,7 +857,7 @@ bool tchdbiterinit(TCHDB *hdb){
 bool tchdbiterinit4(TCHDB *hdb, uint64_t *iter){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -842,12 +871,11 @@ bool tchdbiterinit4(TCHDB *hdb, uint64_t *iter){
   return true;
 }
 
-
 /* Get the next key of the iterator of a hash database object. */
 void *tchdbiternext(TCHDB *hdb, int *sp){
   assert(hdb && sp);
   if(!HDBLOCKMETHOD(hdb, true)) return NULL;
-  if(hdb->fd < 0 || hdb->iter < 1){
+  if(INVALIDHANDLE(hdb->fd) || hdb->iter < 1){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return NULL;
@@ -874,7 +902,7 @@ char *tchdbiternext2(TCHDB *hdb){
 bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr){
   assert(hdb && kxstr && vxstr);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || hdb->iter < 1){
+  if(INVALIDHANDLE(hdb->fd) || hdb->iter < 1){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -893,7 +921,7 @@ bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr){
 bool tchdbiternext4(TCHDB *hdb, uint64_t *iter, TCXSTR *kxstr, TCXSTR *vxstr){
   assert(hdb && kxstr && vxstr && iter);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || *iter < 1){
+  if(INVALIDHANDLE(hdb->fd) || *iter < 1){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -913,7 +941,7 @@ TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max){
   assert(hdb && pbuf && psiz >= 0);
   TCLIST* keys = tclistnew();
   if(!HDBLOCKMETHOD(hdb, true)) return keys;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return keys;
@@ -953,7 +981,7 @@ int tchdbaddint(TCHDB *hdb, const void *kbuf, int ksiz, int num){
   if(!HDBLOCKMETHOD(hdb, false)) return INT_MIN;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return INT_MIN;
@@ -1020,7 +1048,7 @@ double tchdbadddouble(TCHDB *hdb, const void *kbuf, int ksiz, double num){
   if(!HDBLOCKMETHOD(hdb, false)) return nan("");
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return nan("");
@@ -1085,7 +1113,12 @@ double tchdbadddouble(TCHDB *hdb, const void *kbuf, int ksiz, double num){
 bool tchdbsync(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){
+  if (hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1104,7 +1137,12 @@ bool tchdbsync(TCHDB *hdb){
 bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){
+  if (hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1124,7 +1162,12 @@ bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t o
 bool tchdbvanish(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){
+  if (hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1144,7 +1187,7 @@ bool tchdbvanish(TCHDB *hdb){
 bool tchdbcopy(TCHDB *hdb, const char *path){
   assert(hdb && path);
   if(!HDBLOCKMETHOD(hdb, false)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1168,9 +1211,9 @@ bool tchdbcopy(TCHDB *hdb, const char *path){
 /* Begin the transaction of a hash database object. */
 bool tchdbtranbegin(TCHDB *hdb){
   assert(hdb);
-  for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){
+  for(double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2){
     if(!HDBLOCKMETHOD(hdb, true)) return false;
-    if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal){
+    if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER) || hdb->fatal){
       tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
       HDBUNLOCKMETHOD(hdb);
       return false;
@@ -1184,26 +1227,20 @@ bool tchdbtranbegin(TCHDB *hdb){
     HDBUNLOCKMETHOD(hdb);
     return false;
   }
-  if(!tchdbmemsync(hdb, false)){
+  if(!tchdbmemsync(hdb, (hdb->omode & HDBOTSYNC))){
     HDBUNLOCKMETHOD(hdb);
     return false;
   }
-  if((hdb->omode & HDBOTSYNC) && fsync(hdb->fd) == -1){
-    tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
-    return false;
-  }
-  if(hdb->walfd < 0){
+  if(INVALIDHANDLE(hdb->walfd)){
     char *tpath = tcsprintf("%s%c%s", hdb->path, MYEXTCHR, HDBWALSUFFIX);
-    int walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, HDBFILEMODE);
+#ifndef _WIN32
+    HANDLE walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, HDBFILEMODE);
+#else
+    HANDLE walfd = CreateFile(tpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
     TCFREE(tpath);
-    if(walfd < 0){
-      int ecode = TCEOPEN;
-      switch(errno){
-        case EACCES: ecode = TCENOPERM; break;
-        case ENOENT: ecode = TCENOFILE; break;
-        case ENOTDIR: ecode = TCENOFILE; break;
-      }
-      tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);
+    if(INVALIDHANDLE(walfd)){
+      tchdbsetecode(hdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
       HDBUNLOCKMETHOD(hdb);
       return false;
     }
@@ -1226,15 +1263,20 @@ bool tchdbtranbegin(TCHDB *hdb){
 bool tchdbtrancommit(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal || !hdb->tran){
+  if (!hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER) || hdb->fatal){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
   }
   bool err = false;
   if(hdb->async && !tchdbflushdrp(hdb)) err = true;
-  if(!tchdbmemsync(hdb, hdb->omode & HDBOTSYNC)) err = true;
-  if(!err && ftruncate(hdb->walfd, 0) == -1){
+  if(!tchdbmemsync(hdb, (hdb->omode & HDBOTSYNC))) err = true;
+  if(!err && !tcftruncate(hdb->walfd, 0)){
     tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -1248,7 +1290,12 @@ bool tchdbtrancommit(TCHDB *hdb){
 bool tchdbtranabort(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || !hdb->tran){
+  if (!hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1257,19 +1304,8 @@ bool tchdbtranabort(TCHDB *hdb){
   if(hdb->async && !tchdbflushdrp(hdb)) err = true;
   if(!tchdbmemsync(hdb, false)) err = true;
   if(!tchdbwalrestore(hdb, hdb->path)) err = true;
-  char hbuf[HDBHEADSIZ];
-  if(lseek(hdb->fd, 0, SEEK_SET) == -1){
-    tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
-    err = false;
-  } else if(!tcread(hdb->fd, hbuf, HDBHEADSIZ)){
-    tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-    err = false;
-  } else {
-    tchdbloadmeta(hdb, hbuf);
-  }
   hdb->dfcur = hdb->frec;
   hdb->iter = 0;
-  hdb->xfsiz = 0;
   hdb->fbpnum = 0;
   if(hdb->recc) tcmdbvanish(hdb->recc);
   hdb->tran = false;
@@ -1282,7 +1318,7 @@ bool tchdbtranabort(TCHDB *hdb){
 const char *tchdbpath(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, false)) return NULL;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return NULL;
@@ -1297,7 +1333,7 @@ const char *tchdbpath(TCHDB *hdb){
 uint64_t tchdbrnum(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, false)) return 0;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return 0;
@@ -1312,7 +1348,7 @@ uint64_t tchdbrnum(TCHDB *hdb){
 uint64_t tchdbfsiz(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, false)) return 0;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return 0;
@@ -1332,18 +1368,12 @@ uint64_t tchdbfsiz(TCHDB *hdb){
 /* Set the error code of a hash database object. */
 void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func){
   assert(hdb && filename && line >= 1 && func);
-  int myerrno = errno;
-  if(!hdb->fatal){
+  if(!hdb->fatal) {
       if (hdb->eckey) {
           pthread_setspecific(*(pthread_key_t *)hdb->eckey, (void *)(intptr_t)ecode);
-      } else {
-          hdb->ecode = ecode;
       }
+      hdb->ecode = ecode;
   }
-  if (ecode == TCESUCCESS) {
-      return;
-  }
-
   switch (ecode) { //Fatal errors
         case TCETHREAD:
         case TCENOFILE:
@@ -1364,31 +1394,59 @@ void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const
         case TCERENAME:
         case TCEMKDIR:
         case TCERMDIR:
-        case TCEMISC:
         {
             hdb->fatal = true;
-            if (hdb->fd >= 0 && (hdb->omode & HDBOWRITER)) tchdbsetflag(hdb, HDBFFATAL, true);
+            if (!INVALIDHANDLE(hdb->fd) && (hdb->omode & HDBOWRITER)) tchdbsetflag(hdb, HDBFFATAL, true);
             break;
         }
+        case TCESUCCESS:
+        case TCENOREC:
+        case TCEKEEP:
+          return;
+          break;
         default:
             break;
   }
-
-  if(ecode != TCENOREC && hdb->dbgfd >= 0 && (hdb->dbgfd != UINT16_MAX || hdb->fatal)){
-    int dbgfd = (hdb->dbgfd == UINT16_MAX) ? 1 : hdb->dbgfd;
+#ifdef _WIN32
+  DWORD winerrno = GetLastError();
+#endif
+  int stderrno = errno;
+  if(!INVALIDHANDLE(hdb->dbgfd) || hdb->fatal) {
+    HANDLE dbgfd = INVALIDHANDLE(hdb->dbgfd) ? GET_STDERR_HANDLE() : (hdb->dbgfd);
     char obuf[HDBIOBUFSIZ];
-    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s\n", filename, line, func,
-                       hdb->path ? hdb->path : "-", ecode, tchdberrmsg(ecode),
-                       myerrno, strerror(myerrno));
+#ifdef _WIN32
+    LPTSTR errorText = NULL;
+    if (winerrno > 0) {
+        DWORD ret = FormatMessage(
+            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
+            NULL, winerrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &errorText, 0, NULL);
+        if (!ret) {
+            if (errorText) LocalFree(errorText);
+            errorText = NULL;
+        }
+    }
+    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s:%d:%s\n",
+                       filename, line,
+                       func, (hdb->path ? hdb->path : "-"),
+                       ecode, tchdberrmsg(ecode),
+                       winerrno, (errorText ? errorText : "-"),
+                       stderrno, (stderrno > 0 ? strerror(stderrno) : "-"));
+    if (errorText) LocalFree(errorText);
+#else
+    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s:%d:%s\n",
+                       filename, line,
+                       func, (hdb->path ? hdb->path : "-"),
+                       ecode, tchdberrmsg(ecode),
+                       stderrno, strerror(stderrno));
+#endif
     tcwrite(dbgfd, obuf, osiz);
   }
 }
 
-
 /* Set the type of a hash database object. */
 void tchdbsettype(TCHDB *hdb, uint8_t type){
   assert(hdb);
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return;
   }
@@ -1397,14 +1455,14 @@ void tchdbsettype(TCHDB *hdb, uint8_t type){
 
 
 /* Set the file descriptor for debugging output. */
-void tchdbsetdbgfd(TCHDB *hdb, int fd){
-  assert(hdb && fd >= 0);
+void tchdbsetdbgfd(TCHDB *hdb, HANDLE fd){
+  assert(hdb);
   hdb->dbgfd = fd;
 }
 
 
 /* Get the file descriptor for debugging output. */
-int tchdbdbgfd(TCHDB *hdb){
+HANDLE tchdbdbgfd(TCHDB *hdb){
   assert(hdb);
   return hdb->dbgfd;
 }
@@ -1420,26 +1478,35 @@ bool tchdbhasmutex(TCHDB *hdb){
 /* Synchronize updating contents on memory of a hash database object. */
 bool tchdbmemsync(TCHDB *hdb, bool phys){
   assert(hdb);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  bool err = false;
+  char hbuf[HDBHEADSIZ];
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
   }
-  bool err = false;
-  char hbuf[HDBHEADSIZ];
   tchdbdumpmeta(hdb, hbuf);
-  memcpy(hdb->map, hbuf, HDBOPAQUEOFF);
+  if (!HDBLOCKSMEM(hdb, true)) return false;
+  memcpy((void *) hdb->map, hbuf, HDBOPAQUEOFF);
+  HDBUNLOCKSMEM(hdb);
   if(phys){
+    if (!HDBLOCKSMEM(hdb, false)) return false;
+#ifdef _WIN32
+    if(!FlushViewOfFile((PCVOID) hdb->map, 0)){
+      tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
+      err = true;
+    }
+#elif !defined __GNU__
     size_t xmsiz = (hdb->xmsiz > hdb->msiz) ? hdb->xmsiz : hdb->msiz;
-#ifndef __GNU__
-    if(msync(hdb->map, xmsiz, MS_SYNC) == -1){
+    if(msync(hdb->map, xmsiz, MS_SYNC)){
       tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
       err = true;
     }
-#endif        
-    if(fsync(hdb->fd) == -1){
+#endif
+    if(fsync(hdb->fd)){
       tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
       err = true;
     }
+    HDBUNLOCKSMEM(hdb);
   }
   return !err;
 }
@@ -1448,7 +1515,7 @@ bool tchdbmemsync(TCHDB *hdb, bool phys){
 /* Get the number of elements of the bucket array of a hash database object. */
 uint64_t tchdbbnum(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1459,7 +1526,7 @@ uint64_t tchdbbnum(TCHDB *hdb){
 /* Get the record alignment a hash database object. */
 uint32_t tchdbalign(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1470,7 +1537,7 @@ uint32_t tchdbalign(TCHDB *hdb){
 /* Get the maximum number of the free block pool of a a hash database object. */
 uint32_t tchdbfbpmax(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1481,7 +1548,7 @@ uint32_t tchdbfbpmax(TCHDB *hdb){
 /* Get the size of the extra mapped memory of a hash database object. */
 uint64_t tchdbxmsiz(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1492,7 +1559,7 @@ uint64_t tchdbxmsiz(TCHDB *hdb){
 /* Get the inode number of the database file of a hash database object. */
 uint64_t tchdbinode(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1503,7 +1570,7 @@ uint64_t tchdbinode(TCHDB *hdb){
 /* Get the modification time of the database file of a hash database object. */
 time_t tchdbmtime(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1514,7 +1581,7 @@ time_t tchdbmtime(TCHDB *hdb){
 /* Get the connection mode of a hash database object. */
 int tchdbomode(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1525,7 +1592,7 @@ int tchdbomode(TCHDB *hdb){
 /* Get the database type of a hash database object. */
 uint8_t tchdbtype(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1536,7 +1603,7 @@ uint8_t tchdbtype(TCHDB *hdb){
 /* Get the additional flags of a hash database object. */
 uint8_t tchdbflags(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
@@ -1547,44 +1614,89 @@ uint8_t tchdbflags(TCHDB *hdb){
 /* Get the options of a hash database object. */
 uint8_t tchdbopts(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
   return hdb->opts;
 }
 
-
-/* Get the pointer to the opaque field of a hash database object. */
-char *tchdbopaque(TCHDB *hdb){
-  assert(hdb);
-  if(hdb->fd < 0){
-    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
-    return NULL;
-  }
-  return hdb->map + HDBOPAQUEOFF;
+bool tchdbcopyopaque(TCHDB *dst, TCHDB *src, int off, int rsz) {
+    assert(dst && src);
+    if (rsz == -1) {
+        rsz = HDBOPAQUESZ;
+    }
+    char odata[HDBOPAQUESZ];
+    rsz = tchdbreadopaque(src, odata, off, rsz);
+    if (rsz == -1) {
+       tchdbsetecode(dst, tchdbecode(src), __FILE__, __LINE__, __func__);
+       return false;
+    }
+    return (tchdbwriteopaque(dst, odata, off, rsz) == rsz);
 }
 
+int tchdbreadopaque(TCHDB *hdb, void *dst, int off, int bsiz) {
+    assert(hdb && dst);
+    if (bsiz == -1) {
+        bsiz = HDBOPAQUESZ;
+    }
+    if (off > HDBOPAQUESZ) {
+        tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
+        return -1;
+    }
+    bsiz = MIN(bsiz, HDBOPAQUESZ - off);
+    if (bsiz <= 0) {
+        tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
+        return -1;
+    }
+    if (!HDBLOCKSMEM(hdb, false)) return -1;
+    assert(hdb->map);
+    memcpy((void *) dst, (void *) (hdb->map + HDBOPAQUEOFF + off), bsiz);
+    HDBUNLOCKSMEM(hdb);
+    return bsiz;
+}
+
+int tchdbwriteopaque(TCHDB *hdb, const void *src, int off, int nb) {
+   assert(hdb && src);
+   if (nb == -1) {
+        nb = HDBOPAQUESZ;
+   }
+   if (off > HDBOPAQUESZ) {
+        tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
+        return -1;
+   }
+   nb = MIN(nb, HDBOPAQUESZ - off);
+   if (nb <= 0) {
+       tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
+       return -1;
+   }
+   if (!HDBLOCKSMEM(hdb, true)) return -1;
+   memcpy((void *) (hdb->map + HDBOPAQUEOFF + off), src,  nb);
+   HDBUNLOCKSMEM(hdb);
+   return nb;
+}
 
 /* Get the number of used elements of the bucket array of a hash database object. */
 uint64_t tchdbbnumused(TCHDB *hdb){
   assert(hdb);
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return 0;
   }
+  if (!HDBLOCKSMEM(hdb, false)) return false;
   uint64_t unum = 0;
   if(hdb->ba64){
-    uint64_t *buckets = hdb->ba64;
+    uint64_t *buckets = HDBB64(hdb);
     for(int i = 0; i < hdb->bnum; i++){
       if(buckets[i]) unum++;
     }
   } else {
-    uint32_t *buckets = hdb->ba32;
+    uint32_t *buckets = HDBB32(hdb);
     for(int i = 0; i < hdb->bnum; i++){
       if(buckets[i]) unum++;
     }
   }
+  HDBUNLOCKSMEM(hdb);
   return unum;
 }
 
@@ -1593,7 +1705,7 @@ uint64_t tchdbbnumused(TCHDB *hdb){
 bool tchdbsetcodecfunc(TCHDB *hdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop){
   assert(hdb && enc && dec);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd >= 0){
+  if(!INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1619,7 +1731,7 @@ bool tchdbdefrag(TCHDB *hdb, int64_t step){
   assert(hdb);
   if(step > 0){
     if(!HDBLOCKMETHOD(hdb, true)) return false;
-    if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+    if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
       tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
       HDBUNLOCKMETHOD(hdb);
       return false;
@@ -1633,7 +1745,7 @@ bool tchdbdefrag(TCHDB *hdb, int64_t step){
     return rv;
   }
   if(!HDBLOCKMETHOD(hdb, false)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1670,7 +1782,7 @@ bool tchdbdefrag(TCHDB *hdb, int64_t step){
 bool tchdbcacheclear(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1689,7 +1801,7 @@ bool tchdbputproc(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
   if(!HDBLOCKMETHOD(hdb, false)) return false;
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1800,7 +1912,7 @@ void tchdbcodecfunc(TCHDB *hdb, TCCODEC *ep, void **eop, TCCODEC *dp, void **dop
 void *tchdbgetnext(TCHDB *hdb, const void *kbuf, int ksiz, int *sp){
   assert(hdb && sp);
   if(!HDBLOCKMETHOD(hdb, true)) return NULL;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return NULL;
@@ -1827,7 +1939,7 @@ char *tchdbgetnext2(TCHDB *hdb, const char *kstr){
 char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char **vbp, int *vsp){
   assert(hdb && sp && vbp && vsp);
   if(!HDBLOCKMETHOD(hdb, true)) return NULL;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return NULL;
@@ -1846,7 +1958,7 @@ char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char
 bool tchdbiterinit2(TCHDB *hdb, const void *kbuf, int ksiz){
   assert(hdb && kbuf && ksiz >= 0);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1872,7 +1984,7 @@ bool tchdbiterinit3(TCHDB *hdb, const char *kstr){
 bool tchdbforeach(TCHDB *hdb, TCITER iter, void *op){
   assert(hdb && iter);
   if(!HDBLOCKMETHOD(hdb, false)) return false;
-  if(hdb->fd < 0){
+  if(INVALIDHANDLE(hdb->fd)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1897,7 +2009,12 @@ bool tchdbforeach(TCHDB *hdb, TCITER iter, void *op){
 bool tchdbtranvoid(TCHDB *hdb){
   assert(hdb);
   if(!HDBLOCKMETHOD(hdb, true)) return false;
-  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal || !hdb->tran){
+  if (!hdb->tran) {
+      tchdbsetecode(hdb, TCETR, __FILE__, __LINE__, __func__);
+      HDBUNLOCKMETHOD(hdb);
+      return false;
+  }
+  if(INVALIDHANDLE(hdb->fd) || !(hdb->omode & HDBOWRITER) || hdb->fatal){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
     HDBUNLOCKMETHOD(hdb);
     return false;
@@ -1913,7 +2030,6 @@ bool tchdbtranvoid(TCHDB *hdb){
  * private features
  *************************************************************************************************/
 
-
 /* Get a natural prime number not less than a floor number.
    `num' specified the floor number.
    The return value is a prime number not less than the floor number. */
@@ -1952,6 +2068,10 @@ static uint64_t tcgetprime(uint64_t num){
   return primes[i-1];
 }
 
+static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){
+    return tchdbseekwrite2(hdb, off, buf, size, 0);
+}
+
 
 /* Seek and write data into a file.
    `hdb' specifies the hash database object.
@@ -1959,33 +2079,35 @@ static uint64_t tcgetprime(uint64_t num){
    `buf' specifies the buffer to store into.
    `size' specifies the size of the buffer.
    The return value is true if successful, else, it is false. */
-static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){
+static bool tchdbseekwrite2(TCHDB *hdb, off_t off, const void *buf, size_t size, int opts){
   assert(hdb && off >= 0 && buf && size >= 0);
-  if(hdb->tran && !tchdbwalwrite(hdb, off, size)) return false;
+  if(hdb->tran && !(opts & HDBWRITENOWALL) && !tchdbwalwrite(hdb, off, size)) return false;
   off_t end = off + size;
-  if(end <= hdb->xmsiz){
-    if(end >= hdb->fsiz && end >= hdb->xfsiz){
-      uint64_t xfsiz = end + HDBXFSIZINC;
-      if(ftruncate(hdb->fd, xfsiz) == -1){
+  if(end >= hdb->xfsiz){
+      if(!tchdbftruncate2(hdb, end + HDBXFSIZINC, opts)){
         tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
         return false;
       }
-      hdb->xfsiz = xfsiz;
+  }
+  if(end <= hdb->xmsiz){
+    if (opts & HDBWRITENOLOCK) {
+        memcpy((void *) (hdb->map + off), buf, size);
+    } else {
+        if (!HDBLOCKSMEM(hdb, true)) return false;
+        memcpy((void *) (hdb->map + off), buf, size);
+        HDBUNLOCKSMEM(hdb);
     }
-    memcpy(hdb->map + off, buf, size);
     return true;
   }
   if(!TCUBCACHE && off < hdb->xmsiz){
-    if(end >= hdb->fsiz && end >= hdb->xfsiz){
-      uint64_t xfsiz = end + HDBXFSIZINC;
-      if(ftruncate(hdb->fd, xfsiz) == -1){
-        tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
-        return false;
-      }
-      hdb->xfsiz = xfsiz;
-    }
     int head = hdb->xmsiz - off;
-    memcpy(hdb->map + off, buf, head);
+    if (opts & HDBWRITENOLOCK) {
+        memcpy((void *) (hdb->map + off), buf, head);
+    } else {
+        if (!HDBLOCKSMEM(hdb, true)) return false;
+        memcpy((void *) (hdb->map + off), buf, head);
+        HDBUNLOCKSMEM(hdb);
+    }
     off += head;
     buf = (char *)buf + head;
     size -= head;
@@ -2000,12 +2122,12 @@ static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){
       off += wb;
     } else if(wb == -1){
       if(errno != EINTR){
-        tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
+        tchdbsetecode(hdb, tcfilerrno2tcerr(TCEWRITE), __FILE__, __LINE__, __func__);
         return false;
       }
     } else {
       if(size > 0){
-        tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
+        tchdbsetecode(hdb, tcfilerrno2tcerr(TCEWRITE), __FILE__, __LINE__, __func__);
         return false;
       }
     }
@@ -2023,12 +2145,16 @@ static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){
 static bool tchdbseekread(TCHDB *hdb, off_t off, void *buf, size_t size){
   assert(hdb && off >= 0 && buf && size >= 0);
   if(off + size <= hdb->xmsiz){
-    memcpy(buf, hdb->map + off, size);
+    if (!HDBLOCKSMEM(hdb, false)) return false;
+    memcpy(buf, (void *) (hdb->map + off), size);
+    HDBUNLOCKSMEM(hdb);
     return true;
   }
   if(!TCUBCACHE && off < hdb->xmsiz){
     int head = hdb->xmsiz - off;
-    memcpy(buf, hdb->map + off, head);
+    if (!HDBLOCKSMEM(hdb, false)) return false;
+    memcpy(buf, (void *) (hdb->map + off), head);
+    HDBUNLOCKSMEM(hdb);
     off += head;
     buf = (char *)buf + head;
     size -= head;
@@ -2068,12 +2194,16 @@ static bool tchdbseekreadtry(TCHDB *hdb, off_t off, void *buf, size_t size){
   off_t end = off + size;
   if(end > hdb->fsiz) return false;
   if(end <= hdb->xmsiz){
-    memcpy(buf, hdb->map + off, size);
+    if (!HDBLOCKSMEM(hdb, false)) return false;
+    memcpy(buf, (void *) (hdb->map + off), size);
+    HDBUNLOCKSMEM(hdb);
     return true;
   }
   if(!TCUBCACHE && off < hdb->xmsiz){
     int head = hdb->xmsiz - off;
-    memcpy(buf, hdb->map + off, head);
+    if (!HDBLOCKSMEM(hdb, false)) return false;
+    memcpy(buf, (void *)(hdb->map + off), head);
+    HDBUNLOCKSMEM(hdb);
     off += head;
     buf = (char *)buf + head;
     size -= head;
@@ -2138,6 +2268,7 @@ static void tchdbloadmeta(TCHDB *hdb, const char *hbuf){
 static void tchdbclear(TCHDB *hdb){
   assert(hdb);
   hdb->mmtx = NULL;
+  hdb->smtx = NULL;
   hdb->rmtxs = NULL;
   hdb->dmtx = NULL;
   hdb->wmtx = NULL;
@@ -2150,7 +2281,7 @@ static void tchdbclear(TCHDB *hdb){
   hdb->fpow = HDBDEFFPOW;
   hdb->opts = 0;
   hdb->path = NULL;
-  hdb->fd = -1;
+  hdb->fd = INVALID_HANDLE_VALUE;
   hdb->omode = 0;
   hdb->rnum = 0;
   hdb->fsiz = 0;
@@ -2161,8 +2292,7 @@ static void tchdbclear(TCHDB *hdb){
   hdb->msiz = 0;
   hdb->xmsiz = HDBDEFXMSIZ;
   hdb->xfsiz = 0;
-  hdb->ba32 = NULL;
-  hdb->ba64 = NULL;
+  hdb->ba64 = false;
   hdb->align = 0;
   hdb->runit = 0;
   hdb->zmode = false;
@@ -2187,9 +2317,9 @@ static void tchdbclear(TCHDB *hdb){
   hdb->dfunit = 0;
   hdb->dfcnt = 0;
   hdb->tran = false;
-  hdb->walfd = -1;
+  hdb->walfd = INVALID_HANDLE_VALUE;
   hdb->walend = 0;
-  hdb->dbgfd = -1;
+  hdb->dbgfd = INVALID_HANDLE_VALUE;
   hdb->cnt_writerec = -1;
   hdb->cnt_reuserec = -1;
   hdb->cnt_moverec = -1;
@@ -2207,6 +2337,9 @@ static void tchdbclear(TCHDB *hdb){
   hdb->cnt_defrag = -1;
   hdb->cnt_shiftrec = -1;
   hdb->cnt_trunc = -1;
+#ifdef _WIN32
+  hdb->w32hmap = INVALID_HANDLE_VALUE;
+#endif
   TCDODEBUG(hdb->cnt_writerec = 0);
   TCDODEBUG(hdb->cnt_reuserec = 0);
   TCDODEBUG(hdb->cnt_moverec = 0);
@@ -2244,6 +2377,7 @@ static int32_t tchdbpadsize(TCHDB *hdb, uint64_t off){
    `sign' specifies the sign. */
 static void tchdbsetflag(TCHDB *hdb, int flag, bool sign){
   assert(hdb);
+  if (!HDBLOCKSMEM(hdb, true)) return;
   char *fp = (char *)hdb->map + HDBFLAGSOFF;
   if(sign){
     *fp |= (uint8_t)flag;
@@ -2251,6 +2385,7 @@ static void tchdbsetflag(TCHDB *hdb, int flag, bool sign){
     *fp &= ~(uint8_t)flag;
   }
   hdb->flags = *fp;
+  HDBUNLOCKSMEM(hdb);
 }
 
 
@@ -2280,12 +2415,17 @@ static uint64_t tchdbbidx(TCHDB *hdb, const char *kbuf, int ksiz, uint8_t *hp){
    The return value is the offset of the record. */
 static off_t tchdbgetbucket(TCHDB *hdb, uint64_t bidx){
   assert(hdb && bidx >= 0);
+  if (!HDBLOCKSMEM(hdb, false)) return -1;
+  off_t ret;
   if(hdb->ba64){
-    uint64_t llnum = hdb->ba64[bidx];
-    return TCITOHLL(llnum) << hdb->apow;
+    uint64_t llnum = HDBB64(hdb)[bidx];
+    ret =  TCITOHLL(llnum) << hdb->apow;
+  } else {
+    uint32_t lnum = HDBB32(hdb)[bidx];
+    ret = (off_t)TCITOHL(lnum) << hdb->apow;
   }
-  uint32_t lnum = hdb->ba32[bidx];
-  return (off_t)TCITOHL(lnum) << hdb->apow;
+  HDBUNLOCKSMEM(hdb);
+  return ret;
 }
 
 
@@ -2298,11 +2438,17 @@ static void tchdbsetbucket(TCHDB *hdb, uint64_t bidx, uint64_t off){
   if(hdb->ba64){
     uint64_t llnum = off >> hdb->apow;
     if(hdb->tran) tchdbwalwrite(hdb, HDBHEADSIZ + bidx * sizeof(llnum), sizeof(llnum));
-    hdb->ba64[bidx] = TCHTOILL(llnum);
+    bool l = HDBLOCKSMEM(hdb, true);
+    uint64_t *ba = HDBB64(hdb);
+    ba[bidx] = TCHTOILL(llnum);
+    if (l) HDBUNLOCKSMEM(hdb);
   } else {
     uint32_t lnum = off >> hdb->apow;
     if(hdb->tran) tchdbwalwrite(hdb, HDBHEADSIZ + bidx * sizeof(lnum), sizeof(lnum));
-    hdb->ba32[bidx] = TCHTOIL(lnum);
+    bool l = HDBLOCKSMEM(hdb, true);
+    uint32_t *ba = HDBB32(hdb);
+    ba[bidx] = TCHTOIL(lnum);
+    if (l) HDBUNLOCKSMEM(hdb);
   }
 }
 
@@ -2733,8 +2879,7 @@ static bool tchdbwritefb(TCHDB *hdb, uint64_t off, uint32_t rsiz){
   uint32_t lnum = TCHTOIL(rsiz);
   memcpy(wp, &lnum, sizeof(lnum));
   wp += sizeof(lnum);
-  if(!tchdbseekwrite(hdb, off, rbuf, wp - rbuf)) return false;
-  return true;
+  return tchdbseekwrite(hdb, off, rbuf, wp - rbuf);
 }
 
 
@@ -2861,7 +3006,9 @@ static bool tchdbwriterec(TCHDB *hdb, TCHREC *rec, uint64_t bidx, off_t entoff){
     hdb->fsiz += finc;
     uint64_t llnum = hdb->fsiz;
     llnum = TCHTOILL(llnum);
-    memcpy(hdb->map + HDBFSIZOFF, &llnum, sizeof(llnum));
+    if (!HDBLOCKSMEM(hdb, true)) return false;
+    memcpy((void *)(hdb->map + HDBFSIZOFF), &llnum, sizeof(llnum));
+    HDBUNLOCKSMEM(hdb);
   }
   if(rbuf != stack) TCFREE(rbuf);
   if(entoff > 0){
@@ -2988,6 +3135,7 @@ static bool tchdbreadrecbody(TCHDB *hdb, TCHREC *rec){
    The return value is true if successful, else, it is false. */
 static bool tchdbremoverec(TCHDB *hdb, TCHREC *rec, char *rbuf, uint64_t bidx, off_t entoff){
   assert(hdb && rec);
+  bool err = false;
   if(!tchdbwritefb(hdb, rec->off, rec->rsiz)) return false;
   if(!HDBLOCKDB(hdb)) return false;
   tchdbfbpinsert(hdb, rec->off, rec->rsiz);
@@ -3017,10 +3165,10 @@ static bool tchdbremoverec(TCHDB *hdb, TCHREC *rec, char *rbuf, uint64_t bidx, o
       uint32_t lnum = right >> hdb->apow;
       lnum = TCHTOIL(lnum);
       if(!tchdbseekwrite(hdb, toff, &lnum, sizeof(uint32_t))) return false;
+      }
     }
-  }
   if(entoff > 0){
-    if(hdb->ba64){
+      if(hdb->ba64){
       uint64_t llnum = child >> hdb->apow;
       llnum = TCHTOILL(llnum);
       if(!tchdbseekwrite(hdb, entoff, &llnum, sizeof(uint64_t))) return false;
@@ -3028,7 +3176,7 @@ static bool tchdbremoverec(TCHDB *hdb, TCHREC *rec, char *rbuf, uint64_t bidx, o
       uint32_t lnum = child >> hdb->apow;
       lnum = TCHTOIL(lnum);
       if(!tchdbseekwrite(hdb, entoff, &lnum, sizeof(uint32_t))) return false;
-    }
+      }
   } else {
     tchdbsetbucket(hdb, bidx, child);
   }
@@ -3036,9 +3184,14 @@ static bool tchdbremoverec(TCHDB *hdb, TCHREC *rec, char *rbuf, uint64_t bidx, o
   hdb->rnum--;
   uint64_t llnum = hdb->rnum;
   llnum = TCHTOILL(llnum);
-  memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
+  if (HDBLOCKSMEM(hdb, true)) {
+    memcpy((void *)(hdb->map + HDBRNUMOFF), &llnum, sizeof(llnum));
+    HDBUNLOCKSMEM(hdb);
+  } else {
+      err = true;
+  }
   HDBUNLOCKDB(hdb);
-  return true;
+  return !err;
 }
 
 
@@ -3051,10 +3204,13 @@ static bool tchdbremoverec(TCHDB *hdb, TCHREC *rec, char *rbuf, uint64_t bidx, o
 static bool tchdbshiftrec(TCHDB *hdb, TCHREC *rec, char *rbuf, off_t destoff){
   assert(hdb && rec && rbuf && destoff >= 0);
   TCDODEBUG(hdb->cnt_shiftrec++);
-  if(!rec->vbuf && !tchdbreadrecbody(hdb, rec)) return false;
+  if(!rec->vbuf && !tchdbreadrecbody(hdb, rec)) {
+      return false;
+  }
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, rec->kbuf, rec->ksiz, &hash);
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return false;
   if(rec->off == off){
     bool err = false;
     rec->off = destoff;
@@ -3148,6 +3304,7 @@ static int tcreckeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){
    The return value is true if successful, else, it is false. */
 static bool tchdbflushdrp(TCHDB *hdb){
   assert(hdb);
+  bool err = false;
   if(!HDBLOCKDB(hdb)) return false;
   if(!hdb->drpool){
     HDBUNLOCKDB(hdb);
@@ -3188,15 +3345,20 @@ static bool tchdbflushdrp(TCHDB *hdb){
   hdb->drpool = NULL;
   hdb->drpdef = NULL;
   hdb->drpoff = 0;
-  uint64_t llnum;
-  llnum = hdb->rnum;
-  llnum = TCHTOILL(llnum);
-  memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
-  llnum = hdb->fsiz;
-  llnum = TCHTOILL(llnum);
-  memcpy(hdb->map + HDBFSIZOFF, &llnum, sizeof(llnum));
+  if (HDBLOCKSMEM(hdb, true)) {
+    uint64_t llnum;
+    llnum = hdb->rnum;
+    llnum = TCHTOILL(llnum);
+    memcpy((void *)(hdb->map + HDBRNUMOFF), &llnum, sizeof(llnum));
+    llnum = hdb->fsiz;
+    llnum = TCHTOILL(llnum);
+    memcpy((void *)(hdb->map + HDBFSIZOFF), &llnum, sizeof(llnum));
+    HDBUNLOCKSMEM(hdb);
+  } else {
+      err = true;
+  }
   HDBUNLOCKDB(hdb);
-  return true;
+  return !err;
 }
 
 
@@ -3214,11 +3376,11 @@ static void tchdbcacheadjust(TCHDB *hdb){
    If successful, the return value is true, else, it is false. */
 static bool tchdbwalinit(TCHDB *hdb){
   assert(hdb);
-  if(lseek(hdb->walfd, 0, SEEK_SET) == -1){
+  if(!tcfseek(hdb->walfd, 0, TCFSTART)){
     tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
     return false;
   }
-  if(ftruncate(hdb->walfd, 0) == -1){
+  if(!tcftruncate(hdb->walfd, 0)){
     tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
     return false;
   }
@@ -3262,7 +3424,10 @@ static bool tchdbwalwrite(TCHDB *hdb, uint64_t off, int64_t size){
     return false;
   }
   wp += size;
-  if(!HDBLOCKWAL(hdb)) return false;
+  if(!HDBLOCKWAL(hdb)) {
+    if(buf != stack) TCFREE(buf);
+    return false;
+  }
   if(!tcwrite(hdb->walfd, buf, wp - buf)){
     tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
     if(buf != stack) TCFREE(buf);
@@ -3270,7 +3435,7 @@ static bool tchdbwalwrite(TCHDB *hdb, uint64_t off, int64_t size){
     return false;
   }
   if(buf != stack) TCFREE(buf);
-  if((hdb->omode & HDBOTSYNC) && fsync(hdb->walfd) == -1){
+  if((hdb->omode & HDBOTSYNC) && fsync(hdb->walfd)){
     tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
     HDBUNLOCKWAL(hdb);
     return false;
@@ -3284,123 +3449,112 @@ static bool tchdbwalwrite(TCHDB *hdb, uint64_t off, int64_t size){
    `hdb' specifies the hash database object.
    `path' specifies the path of the database file.
    If successful, the return value is true, else, it is false. */
-static int tchdbwalrestore(TCHDB *hdb, const char *path){
-  assert(hdb && path);
-  char *tpath = tcsprintf("%s%c%s", path, MYEXTCHR, HDBWALSUFFIX);
-  int walfd = open(tpath, O_RDONLY, HDBFILEMODE);
-  TCFREE(tpath);
-  if(walfd < 0) return false;
-  bool err = false;
-  uint64_t walsiz = 0;
-  struct stat sbuf;
-  if(fstat(walfd, &sbuf) == 0){
-    walsiz = sbuf.st_size;
-  } else {
-    tchdbsetecode(hdb, TCESTAT, __FILE__, __LINE__, __func__);
-    err = true;
-  }
-  if(walsiz >= sizeof(walsiz) + HDBHEADSIZ){
-    int dbfd = hdb->fd;
-    int tfd = -1;
-    if(!(hdb->omode & HDBOWRITER)){
-      tfd = open(path, O_WRONLY, HDBFILEMODE);
-      if(tfd >= 0){
-        dbfd = tfd;
-      } else {
-        int ecode = TCEOPEN;
-        switch(errno){
-          case EACCES: ecode = TCENOPERM; break;
-          case ENOENT: ecode = TCENOFILE; break;
-          case ENOTDIR: ecode = TCENOFILE; break;
-        }
-        tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);
+static bool tchdbwalrestore(TCHDB *hdb, const char *path) {
+    bool err = false;
+    uint64_t walsiz = 0;
+    HANDLE walfd;
+    if (!HDBLOCKWAL(hdb)) {
+        return false;
+    }
+    char *tpath = tcsprintf("%s%c%s", path, MYEXTCHR, HDBWALSUFFIX);
+#ifndef _WIN32
+    walfd = open(tpath, O_RDONLY, HDBFILEMODE);
+#else
+    walfd = CreateFile(tpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+    TCFREE(tpath);
+    if (INVALIDHANDLE(walfd)) {
+        tchdbsetecode(hdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
+        HDBUNLOCKWAL(hdb);
         err = true;
-      }
+        goto finish;
+    }
+    struct stat sbuf;
+    if (!fstat(walfd, &sbuf)) {
+        walsiz = sbuf.st_size;
+    }
+    if (!(hdb->omode & HDBOWRITER) || walsiz < sizeof (walsiz) + HDBHEADSIZ) {
+        HDBUNLOCKWAL(hdb);
+        err = true;
+        goto finish;
     }
     uint64_t fsiz = 0;
-    if(tcread(walfd, &fsiz, sizeof(fsiz))){
-      fsiz = TCITOHLL(fsiz);
+    if (tcread(walfd, &fsiz, sizeof (fsiz))) {
+        fsiz = TCITOHLL(fsiz);
     } else {
-      tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-      err = true;
+        HDBUNLOCKWAL(hdb);
+        tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
+        err = true;
+        goto finish;
     }
     TCLIST *list = tclistnew();
-    uint64_t waloff = sizeof(fsiz);
+    uint64_t waloff = sizeof (fsiz);
     char stack[HDBIOBUFSIZ];
-    while(waloff < walsiz){
-      uint64_t off;
-      uint32_t size;
-      if(!tcread(walfd, stack, sizeof(off) + sizeof(size))){
-        tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-        err = true;
-        break;
-      }
-      memcpy(&off, stack, sizeof(off));
-      off = TCITOHLL(off);
-      memcpy(&size, stack + sizeof(off), sizeof(size));
-      size = TCITOHL(size);
-      char *buf;
-      if(sizeof(off) + size <= HDBIOBUFSIZ){
-        buf = stack;
-      } else {
-        TCMALLOC(buf, sizeof(off) + size);
-      }
-      *(uint64_t *)buf = off;
-      if(!tcread(walfd, buf + sizeof(off), size)){
-        tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-        err = true;
-        if(buf != stack) TCFREE(buf);
-        break;
-      }
-      TCLISTPUSH(list, buf, sizeof(off) + size);
-      if(buf != stack) TCFREE(buf);
-      waloff += sizeof(off) + sizeof(size) + size;
-    }
-    size_t xmsiz = 0;
-    if(hdb->fd >= 0 && hdb->map) xmsiz = (hdb->xmsiz > hdb->msiz) ? hdb->xmsiz : hdb->msiz;
-    for(int i = TCLISTNUM(list) - 1; i >= 0; i--){
-      const char *rec;
-      int size;
-      TCLISTVAL(rec, list, i, size);
-      uint64_t off = *(uint64_t *)rec;
-      rec += sizeof(off);
-      size -= sizeof(off);
-      if(lseek(dbfd, off, SEEK_SET) == -1){
-        tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
-        err = true;
-        break;
-      }
-      if(!tcwrite(dbfd, rec, size)){
-        tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
+    while (waloff < walsiz) {
+        uint64_t off;
+        uint32_t size;
+        if (!tcread(walfd, stack, sizeof (off) + sizeof (size))) {
+            tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
+            err = true;
+            break;
+        }
+        memcpy(&off, stack, sizeof (off));
+        off = TCITOHLL(off);
+        memcpy(&size, stack + sizeof (off), sizeof (size));
+        size = TCITOHL(size);
+        char *buf;
+        if (sizeof (off) + size <= HDBIOBUFSIZ) {
+            buf = stack;
+        } else {
+            TCMALLOC(buf, sizeof (off) + size);
+        }
+        *(uint64_t *) buf = off;
+        if (!tcread(walfd, buf + sizeof (off), size)) {
+            tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
+            err = true;
+            if (buf != stack) TCFREE(buf);
+            break;
+        }
+        TCLISTPUSH(list, buf, sizeof (off) + size);
+        if (buf != stack) TCFREE(buf);
+        waloff += sizeof (off) + sizeof (size) + size;
+    }
+    HDBUNLOCKWAL(hdb);
+
+    if (HDBLOCKSMEM(hdb, true)) {
+        for (int i = TCLISTNUM(list) - 1; i >= 0; i--) {
+            const char *rec;
+            int size;
+            TCLISTVAL(rec, list, i, size);
+            uint64_t off = *(uint64_t *) rec;
+            rec += sizeof (off);
+            size -= sizeof (off);
+            if (!tchdbseekwrite2(hdb, off, rec, size, HDBWRITENOWALL | HDBWRITENOLOCK)) {
+                err = true;
+                break;
+            }
+        }
+        HDBUNLOCKSMEM(hdb);
+    } else {
         err = true;
-        break;
-      }
-      if(!TCUBCACHE && off < xmsiz){
-        size = (size <= xmsiz - off) ? size : xmsiz - off;
-        memcpy(hdb->map + off, rec, size);
-      }
     }
     tclistdel(list);
-    if(ftruncate(dbfd, fsiz) == -1){
-      tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
-      err = true;
+
+    char hbuf[HDBHEADSIZ];
+    if (!err && tchdbseekread(hdb, 0, hbuf, HDBHEADSIZ)) {
+        tchdbloadmeta(hdb, hbuf);
+    } else {
+        err = true;
     }
-    if((hdb->omode & HDBOTSYNC) && fsync(dbfd) == -1){
-      tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
-      err = true;
+    if (!tchdbmemsync(hdb, (hdb->omode & HDBOTSYNC))) {
+        tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
+        err = true;
     }
-    if(tfd >= 0 && close(tfd) == -1){
-      tchdbsetecode(hdb, TCECLOSE, __FILE__, __LINE__, __func__);
-      err = true;
+finish:
+    if (!INVALIDHANDLE(walfd) && !CLOSEFH(walfd)) {
+        err = true;
     }
-  } else {
-    err = true;
-  }
-  if(close(walfd) == -1){
-    tchdbsetecode(hdb, TCECLOSE, __FILE__, __LINE__, __func__);
-    err = true;
-  }
-  return !err;
+    return !err;
 }
 
 
@@ -3412,7 +3566,7 @@ static bool tchdbwalremove(TCHDB *hdb, const char *path){
   assert(hdb && path);
   char *tpath = tcsprintf("%s%c%s", path, MYEXTCHR, HDBWALSUFFIX);
   bool err = false;
-  if(unlink(tpath) == -1 && errno != ENOENT){
+  if(unlink(tpath) && errno != ENOENT){
     tchdbsetecode(hdb, TCEUNLINK, __FILE__, __LINE__, __func__);
     err = true;
   }
@@ -3428,48 +3582,62 @@ static bool tchdbwalremove(TCHDB *hdb, const char *path){
    If successful, the return value is true, else, it is false. */
 static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
   assert(hdb && path);
+  HANDLE fd;
+#ifndef _WIN32
   int mode = O_RDONLY;
   if(omode & HDBOWRITER){
     mode = O_RDWR;
     if(omode & HDBOCREAT) mode |= O_CREAT;
   }
-  int fd = open(path, mode, HDBFILEMODE);
-  if(fd < 0){
-    int ecode = TCEOPEN;
-    switch(errno){
-      case EACCES: ecode = TCENOPERM; break;
-      case ENOENT: ecode = TCENOFILE; break;
-      case ENOTDIR: ecode = TCENOFILE; break;
-    }
-    tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);
+  fd = open(path, mode, HDBFILEMODE);
+#else
+  DWORD mode, cmode;
+  mode = GENERIC_READ;
+  cmode = OPEN_EXISTING;
+  if (omode & HDBOWRITER) {
+    mode |= GENERIC_WRITE;
+  }
+  if (omode & (HDBOTRUNC | HDBOCREAT)) {
+       cmode = CREATE_ALWAYS;
+  } else if (omode & HDBOTRUNC) {
+       cmode = TRUNCATE_EXISTING;
+  } else if (omode & HDBOCREAT) {
+       cmode = CREATE_NEW;
+  }
+  fd = CreateFile(path, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, cmode, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+  if(INVALIDHANDLE(fd)){
+    tchdbsetecode(hdb, tcfilerrno2tcerr(TCEOPEN), __FILE__, __LINE__, __func__);
     return false;
   }
   if(!(omode & HDBONOLCK)){
     if(!tclock(fd, omode & HDBOWRITER, omode & HDBOLCKNB)){
       tchdbsetecode(hdb, TCELOCK, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
+  hdb->omode = omode;
+  hdb->fd = fd;
   if((omode & HDBOWRITER) && (omode & HDBOTRUNC)){
-    if(ftruncate(fd, 0) == -1){
+    if(!tchdbftruncate(hdb, 0)){
       tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     if(!tchdbwalremove(hdb, path)){
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
   struct stat sbuf;
-  if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
+  if(fstat(fd, &sbuf) || !S_ISREG(sbuf.st_mode)){
     tchdbsetecode(hdb, TCESTAT, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   char hbuf[HDBHEADSIZ];
-  if((omode & HDBOWRITER) && sbuf.st_size < 1){
+  if((omode & HDBOWRITER) && (sbuf.st_size < 1 || (omode & HDBOTRUNC))){
     hdb->flags = 0;
     hdb->rnum = 0;
     uint32_t fbpmax = 1 << hdb->fpow;
@@ -3496,37 +3664,37 @@ static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
     }
     if(err){
       tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     sbuf.st_size = hdb->fsiz;
   }
-  if(lseek(fd, 0, SEEK_SET) == -1){
+  if(!tcfseek(fd, 0, TCFSTART)){
     tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   if(!tcread(fd, hbuf, HDBHEADSIZ)){
     tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
   int type = hdb->type;
   tchdbloadmeta(hdb, hbuf);
   if((hdb->flags & HDBFOPEN) && tchdbwalrestore(hdb, path)){
-    if(lseek(fd, 0, SEEK_SET) == -1){
+    if(!tcfseek(fd, 0, TCFSTART)){
       tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     if(!tcread(fd, hbuf, HDBHEADSIZ)){
       tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
     tchdbloadmeta(hdb, hbuf);
     if(!tchdbwalremove(hdb, path)){
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
@@ -3536,25 +3704,36 @@ static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
     if(memcmp(hbuf, HDBMAGICDATA, strlen(HDBMAGICDATA)) || hdb->type != type ||
        hdb->frec < msiz + HDBFBPBSIZ || hdb->frec > hdb->fsiz || sbuf.st_size < hdb->fsiz){
       tchdbsetecode(hdb, TCEMETA, __FILE__, __LINE__, __func__);
-      close(fd);
+      CLOSEFH(fd);
       return false;
     }
   }
   if(((hdb->opts & HDBTDEFLATE) && !_tc_deflate) ||
-     ((hdb->opts & HDBTBZIP) && !_tc_bzcompress) || ((hdb->opts & HDBTEXCODEC) && !hdb->enc)){
+     ((hdb->opts & HDBTBZIP) && !_tc_bzcompress) ||
+     ((hdb->opts & HDBTEXCODEC) && !hdb->enc)){
     tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
+#ifndef _WIN32
   size_t xmsiz = (hdb->xmsiz > msiz) ? hdb->xmsiz : msiz;
   if(!(omode & HDBOWRITER) && xmsiz > hdb->fsiz) xmsiz = hdb->fsiz;
   void *map = mmap(0, xmsiz, PROT_READ | ((omode & HDBOWRITER) ? PROT_WRITE : 0),
                    MAP_SHARED, fd, 0);
   if(map == MAP_FAILED){
     tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
-    close(fd);
+    CLOSEFH(fd);
     return false;
   }
+  hdb->map = map;
+  hdb->xfsiz = sbuf.st_size;
+#else
+  if(!tchdbftruncate(hdb, sbuf.st_size)){
+      tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
+      CLOSEFH(fd);
+      return false;
+  }
+#endif
   hdb->fbpmax = 1 << hdb->fpow;
   if(omode & HDBOWRITER){
     TCMALLOC(hdb->fbpool, hdb->fbpmax * HDBFBPALWRAT * sizeof(HDBFB));
@@ -3569,20 +3748,10 @@ static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
   hdb->drpoff = 0;
   hdb->recc = (hdb->rcnum > 0) ? tcmdbnew2(hdb->rcnum * 2 + 1) : NULL;
   hdb->path = tcstrdup(path);
-  hdb->fd = fd;
-  hdb->omode = omode;
   hdb->dfcur = hdb->frec;
   hdb->iter = 0;
-  hdb->map = map;
+  hdb->ba64 = (hdb->opts & HDBTLARGE);
   hdb->msiz = msiz;
-  hdb->xfsiz = 0;
-  if(hdb->opts & HDBTLARGE){
-    hdb->ba32 = NULL;
-    hdb->ba64 = (uint64_t *)((char *)map + HDBHEADSIZ);
-  } else {
-    hdb->ba32 = (uint32_t *)((char *)map + HDBHEADSIZ);
-    hdb->ba64 = NULL;
-  }
   hdb->align = 1 << hdb->apow;
   hdb->runit = tclmin(tclmax(hdb->align, HDBMINRUNIT), HDBIOBUFSIZ);
   hdb->zmode = (hdb->opts & HDBTDEFLATE) || (hdb->opts & HDBTBZIP) ||
@@ -3593,7 +3762,7 @@ static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
   hdb->mtime = sbuf.st_mtime;
   hdb->dfcnt = 0;
   hdb->tran = false;
-  hdb->walfd = -1;
+  hdb->walfd = INVALID_HANDLE_VALUE;
   hdb->walend = 0;
   if(hdb->omode & HDBOWRITER){
     bool err = false;
@@ -3603,9 +3772,17 @@ static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
     if(err){
       TCFREE(hdb->path);
       TCFREE(hdb->fbpool);
+      bool l = HDBLOCKSMEM(hdb, true);
+#ifdef _WIN32
+      FlushViewOfFile((PCVOID) hdb->map, 0);
+      UnmapViewOfFile((LPCVOID) hdb->map);
+      CLOSEFH(hdb->w32hmap);
+#else
       munmap(hdb->map, xmsiz);
-      close(fd);
-      hdb->fd = -1;
+#endif
+      if (l) HDBUNLOCKSMEM(hdb);
+      CLOSEFH(fd);
+      hdb->fd = INVALID_HANDLE_VALUE;
       return false;
     }
     tchdbsetflag(hdb, HDBFOPEN, true);
@@ -3632,35 +3809,51 @@ static bool tchdbcloseimpl(TCHDB *hdb){
     tchdbsetflag(hdb, HDBFOPEN, false);
   }
   if((hdb->omode & HDBOWRITER) && !tchdbmemsync(hdb, false)) err = true;
+  if((hdb->omode & HDBOWRITER) && !tchdbftruncate(hdb, hdb->fsiz)){
+    tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
+    err = true;
+  }
+  if(hdb->tran){ //todo!!
+    if(!tchdbwalrestore(hdb, hdb->path)) {
+        err = true;
+    }
+    hdb->tran = false;
+  }
+
+  if (!HDBLOCKSMEM(hdb, true)) err = true;
+#ifndef _WIN32
   size_t xmsiz = (hdb->xmsiz > hdb->msiz) ? hdb->xmsiz : hdb->msiz;
   if(!(hdb->omode & HDBOWRITER) && xmsiz > hdb->fsiz) xmsiz = hdb->fsiz;
   if(munmap(hdb->map, xmsiz) == -1){
+#else
+  FlushViewOfFile((PCVOID) hdb->map, 0);
+  if (UnmapViewOfFile((LPVOID) hdb->map) && CloseHandle(hdb->w32hmap)) {
+         hdb->w32hmap = INVALID_HANDLE_VALUE;
+  }else{
+#endif
     tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
     err = true;
   }
   hdb->map = NULL;
-  if((hdb->omode & HDBOWRITER) && ftruncate(hdb->fd, hdb->fsiz) == -1){
-    tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
-    err = true;
-  }
-  if(hdb->tran){
-    if(!tchdbwalrestore(hdb, hdb->path)) err = true;
-    hdb->tran = false;
-  }
-  if(hdb->walfd >= 0){
-    if(close(hdb->walfd) == -1){
+  HDBUNLOCKSMEM(hdb);
+
+  if(!INVALIDHANDLE(hdb->walfd)){
+    if(!CLOSEFH(hdb->walfd)){
       tchdbsetecode(hdb, TCECLOSE, __FILE__, __LINE__, __func__);
       err = true;
     }
-    if(!hdb->fatal && !tchdbwalremove(hdb, hdb->path)) err = true;
+    if(!hdb->fatal && !tchdbwalremove(hdb, hdb->path)) {
+      err = true;
+    }
   }
-  if(close(hdb->fd) == -1){
+  if(!CLOSEFH(hdb->fd)){
     tchdbsetecode(hdb, TCECLOSE, __FILE__, __LINE__, __func__);
     err = true;
   }
   TCFREE(hdb->path);
   hdb->path = NULL;
-  hdb->fd = -1;
+  hdb->fd = INVALID_HANDLE_VALUE;
+  hdb->walfd = INVALID_HANDLE_VALUE;
   return !err;
 }
 
@@ -3680,9 +3873,11 @@ static bool tchdbputimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx,
   assert(hdb && kbuf && ksiz >= 0);
   if(hdb->recc) tcmdbout(hdb->recc, kbuf, ksiz);
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return false;
   off_t entoff = 0;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
+  bool err = false;
   while(off > 0){
     rec.off = off;
     if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
@@ -3872,9 +4067,14 @@ static bool tchdbputimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx,
   hdb->rnum++;
   uint64_t llnum = hdb->rnum;
   llnum = TCHTOILL(llnum);
-  memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
+  if (HDBLOCKSMEM(hdb, true)) {
+    memcpy((void *)(hdb->map + HDBRNUMOFF), &llnum, sizeof(llnum));
+    HDBUNLOCKSMEM(hdb);
+  } else {
+    err = true;
+  }
   HDBUNLOCKDB(hdb);
-  return true;
+  return !err;
 }
 
 
@@ -3945,6 +4145,7 @@ static bool tchdbputasyncimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t b
     hdb->drpoff = hdb->fsiz;
   }
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return false;
   off_t entoff = 0;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
@@ -4010,6 +4211,7 @@ static bool tchdboutimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx,
   assert(hdb && kbuf && ksiz >= 0);
   if(hdb->recc) tcmdbout(hdb->recc, kbuf, ksiz);
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return false;
   off_t entoff = 0;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
@@ -4079,6 +4281,7 @@ static char *tchdbgetimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx,
     }
   }
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return NULL;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -4170,6 +4373,7 @@ static int tchdbgetintoxstrimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t
     }
   }
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return -1;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -4266,6 +4470,7 @@ static int tchdbgetintobuf(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx
     }
   }
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return -1;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -4422,6 +4627,7 @@ static char *tchdbgetnextimpl(TCHDB *hdb, const char *kbuf, int ksiz, int *sp,
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return NULL;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -4546,6 +4752,7 @@ static int tchdbvsizimpl(TCHDB *hdb, const char *kbuf, int ksiz, uint64_t bidx,
     }
   }
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return -1;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -4712,7 +4919,9 @@ static bool tchdbiternextintoxstr2(TCHDB *hdb, uint64_t *iter, TCXSTR *kxstr, TC
    If successful, the return value is true, else, it is false. */
 static bool tchdboptimizeimpl(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
   assert(hdb);
-  char *tpath = tcsprintf("%s%ctmp%c%llu", hdb->path, MYEXTCHR, MYEXTCHR, hdb->inode);
+  bool err = false;
+  char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", hdb->path, MYEXTCHR, MYEXTCHR, hdb->inode);
+  int omode = (hdb->omode & ~HDBOCREAT) & ~HDBOTRUNC;
   TCHDB *thdb = tchdbnew();
   thdb->dbgfd = hdb->dbgfd;
   thdb->enc = hdb->enc;
@@ -4727,14 +4936,13 @@ static bool tchdboptimizeimpl(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow
   if(fpow < 0) fpow = hdb->fpow;
   if(opts == UINT8_MAX) opts = hdb->opts;
   tchdbtune(thdb, bnum, apow, fpow, opts);
-  if(!tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
-    tchdbsetecode(hdb, thdb->ecode, __FILE__, __LINE__, __func__);
+  if(!tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC) ||
+          !tchdbcopyopaque(thdb, hdb, 0, HDBOPAQUESZ)){
     tchdbdel(thdb);
     TCFREE(tpath);
     return false;
   }
-  memcpy(tchdbopaque(thdb), tchdbopaque(hdb), HDBHEADSIZ - HDBOPAQUEOFF);
-  bool err = false;
+
   uint64_t off = hdb->frec;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
@@ -4796,33 +5004,36 @@ static bool tchdboptimizeimpl(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow
     TCFREE(tpath);
     return false;
   }
+  char *opath = tcstrdup(hdb->path);
+  if(!tchdbcloseimpl(hdb)){
+    TCFREE(opath);
+    TCFREE(tpath);
+    return false;
+  }
   if(esc){
     char *bpath = tcsprintf("%s%cbroken", tpath, MYEXTCHR);
-    if(rename(hdb->path, bpath) == -1){
+    if(rename(opath, bpath)){
       tchdbsetecode(hdb, TCEUNLINK, __FILE__, __LINE__, __func__);
       err = true;
     }
     TCFREE(bpath);
   } else {
-    if(unlink(hdb->path) == -1){
+    if(unlink(opath)){
       tchdbsetecode(hdb, TCEUNLINK, __FILE__, __LINE__, __func__);
       err = true;
     }
   }
-  if(rename(tpath, hdb->path) == -1){
+  if(rename(tpath, opath)){
     tchdbsetecode(hdb, TCERENAME, __FILE__, __LINE__, __func__);
     err = true;
   }
   TCFREE(tpath);
-  if(err) return false;
-  tpath = tcstrdup(hdb->path);
-  int omode = (hdb->omode & ~HDBOCREAT) & ~HDBOTRUNC;
-  if(!tchdbcloseimpl(hdb)){
-    TCFREE(tpath);
+  if(err) {
+    TCFREE(opath);
     return false;
   }
-  bool rv = tchdbopenimpl(hdb, tpath, omode);
-  TCFREE(tpath);
+  bool rv = tchdbopenimpl(hdb, opath, omode);
+  TCFREE(opath);
   return rv;
 }
 
@@ -4860,7 +5071,7 @@ static bool tchdbcopyimpl(TCHDB *hdb, const char *path){
   }
   if(*path == '@'){
     char tsbuf[TCNUMBUFSIZ];
-    sprintf(tsbuf, "%llu", (unsigned long long)(tctime() * 1000000));
+    sprintf(tsbuf, "%" PRIuMAX "", (unsigned long long)(tctime() * 1000000));
     const char *args[3];
     args[0] = path + 1;
     args[1] = hdb->path;
@@ -4887,6 +5098,7 @@ static bool tchdbdefragimpl(TCHDB *hdb, int64_t step){
   hdb->dfcnt = 0;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
+  bool err = false;
   while(true){
     if(hdb->dfcur >= hdb->fsiz){
       hdb->dfcur = hdb->frec;
@@ -4917,7 +5129,10 @@ static bool tchdbdefragimpl(TCHDB *hdb, int64_t step){
         rec.rsiz -= diff;
         fbsiz += diff;
       }
-      if(!tchdbshiftrec(hdb, &rec, rbuf, dest)) return false;
+      if(!tchdbshiftrec(hdb, &rec, rbuf, dest)) {
+          fprintf(stderr, "\n %d %d %d %d @000010\n", (int) cur, (int) hdb->fsiz, (int) (hdb->fsiz - cur), (int) rsiz);
+          return false;
+      }
       if(hdb->iter == cur) hdb->iter = dest;
       dest += rec.rsiz;
       step--;
@@ -4947,23 +5162,29 @@ static bool tchdbdefragimpl(TCHDB *hdb, int64_t step){
     hdb->dfcur = cur - fbsiz;
   } else {
     TCDODEBUG(hdb->cnt_trunc++);
-    if(hdb->tran && !tchdbwalwrite(hdb, dest, fbsiz)) return false;
+    if(hdb->tran && !tchdbwalwrite(hdb, dest, fbsiz)) {
+        return false;
+    }
     tchdbfbptrim(hdb, base, cur, 0, 0);
     hdb->dfcur = hdb->frec;
     hdb->fsiz = dest;
     uint64_t llnum = hdb->fsiz;
     llnum = TCHTOILL(llnum);
-    memcpy(hdb->map + HDBFSIZOFF, &llnum, sizeof(llnum));
+    if (HDBLOCKSMEM(hdb, true)) {
+        memcpy((void *)(hdb->map + HDBFSIZOFF), &llnum, sizeof(llnum));
+        HDBUNLOCKSMEM(hdb);
+    } else {
+        err = true;
+    }
     if(hdb->iter >= hdb->fsiz) hdb->iter = UINT64_MAX;
     if(!hdb->tran){
-      if(ftruncate(hdb->fd, hdb->fsiz) == -1){
+      if(!tchdbftruncate(hdb, hdb->fsiz)){
         tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
         return false;
       }
-      hdb->xfsiz = 0;
     }
   }
-  return true;
+  return !err;
 }
 
 
@@ -4977,6 +5198,7 @@ static bool tchdbiterjumpimpl(TCHDB *hdb, const char *kbuf, int ksiz){
   uint8_t hash;
   uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
   off_t off = tchdbgetbucket(hdb, bidx);
+  if (off == -1) return false;
   TCHREC rec;
   char rbuf[HDBIOBUFSIZ];
   while(off > 0){
@@ -5068,7 +5290,7 @@ static bool tchdbforeachimpl(TCHDB *hdb, TCITER iter, void *op){
    `hdb' specifies the hash database object.
    `wr' specifies whether the lock is writer or not.
    If successful, the return value is true, else, it is false. */
-static bool tchdblockmethod(TCHDB *hdb, bool wr){
+EJDB_INLINE bool tchdblockmethod(TCHDB *hdb, bool wr){
   assert(hdb);
   if(wr ? pthread_rwlock_wrlock(hdb->mmtx) != 0 : pthread_rwlock_rdlock(hdb->mmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5082,7 +5304,7 @@ static bool tchdblockmethod(TCHDB *hdb, bool wr){
 /* Unlock a method of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdbunlockmethod(TCHDB *hdb){
+EJDB_INLINE bool tchdbunlockmethod(TCHDB *hdb){
   assert(hdb);
   if(pthread_rwlock_unlock(hdb->mmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5092,13 +5314,34 @@ static bool tchdbunlockmethod(TCHDB *hdb){
   return true;
 }
 
+/* Lock shared memory  */
+EJDB_INLINE bool tchdblocksmem(TCHDB *hdb, bool wr){
+  assert(hdb);
+  if(wr ? pthread_rwlock_wrlock(hdb->smtx) != 0 : pthread_rwlock_rdlock(hdb->smtx) != 0){
+    tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
+    return false;
+  }
+  TCTESTYIELD();
+  return true;
+}
+
+/* Unlock shared memory */
+EJDB_INLINE bool tchdbunlocksmem(TCHDB *hdb){
+  assert(hdb);
+  if(pthread_rwlock_unlock(hdb->smtx) != 0){
+    tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
+    return false;
+  }
+  TCTESTYIELD();
+  return true;
+}
 
 /* Lock a record of the hash database object.
    `hdb' specifies the hash database object.
    `bidx' specifies the bucket index of the record.
    `wr' specifies whether the lock is writer or not.
    If successful, the return value is true, else, it is false. */
-static bool tchdblockrecord(TCHDB *hdb, uint8_t bidx, bool wr){
+EJDB_INLINE bool tchdblockrecord(TCHDB *hdb, uint8_t bidx, bool wr){
   assert(hdb);
   if(wr ? pthread_rwlock_wrlock((pthread_rwlock_t *)hdb->rmtxs + bidx) != 0 :
      pthread_rwlock_rdlock((pthread_rwlock_t *)hdb->rmtxs + bidx) != 0){
@@ -5114,7 +5357,7 @@ static bool tchdblockrecord(TCHDB *hdb, uint8_t bidx, bool wr){
    `hdb' specifies the hash database object.
    `bidx' specifies the bucket index of the record.
    If successful, the return value is true, else, it is false. */
-static bool tchdbunlockrecord(TCHDB *hdb, uint8_t bidx){
+EJDB_INLINE bool tchdbunlockrecord(TCHDB *hdb, uint8_t bidx){
   assert(hdb);
   if(pthread_rwlock_unlock((pthread_rwlock_t *)hdb->rmtxs + bidx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5129,7 +5372,7 @@ static bool tchdbunlockrecord(TCHDB *hdb, uint8_t bidx){
    `hdb' specifies the hash database object.
    `wr' specifies whether the lock is writer or not.
    If successful, the return value is true, else, it is false. */
-static bool tchdblockallrecords(TCHDB *hdb, bool wr){
+EJDB_INLINE bool tchdblockallrecords(TCHDB *hdb, bool wr){
   assert(hdb);
   for(int i = 0; i <= UINT8_MAX; i++){
     if(wr ? pthread_rwlock_wrlock((pthread_rwlock_t *)hdb->rmtxs + i) != 0 :
@@ -5149,7 +5392,7 @@ static bool tchdblockallrecords(TCHDB *hdb, bool wr){
 /* Unlock all records of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdbunlockallrecords(TCHDB *hdb){
+EJDB_INLINE bool tchdbunlockallrecords(TCHDB *hdb){
   assert(hdb);
   bool err = false;
   for(int i = UINT8_MAX; i >= 0; i--){
@@ -5167,7 +5410,7 @@ static bool tchdbunlockallrecords(TCHDB *hdb){
 /* Lock the whole database of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdblockdb(TCHDB *hdb){
+EJDB_INLINE bool tchdblockdb(TCHDB *hdb){
   assert(hdb);
   if(pthread_mutex_lock(hdb->dmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5181,7 +5424,7 @@ static bool tchdblockdb(TCHDB *hdb){
 /* Unlock the whole database of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdbunlockdb(TCHDB *hdb){
+EJDB_INLINE bool tchdbunlockdb(TCHDB *hdb){
   assert(hdb);
   if(pthread_mutex_unlock(hdb->dmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5195,7 +5438,7 @@ static bool tchdbunlockdb(TCHDB *hdb){
 /* Lock the write ahead logging file of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdblockwal(TCHDB *hdb){
+EJDB_INLINE bool tchdblockwal(TCHDB *hdb){
   assert(hdb);
   if(pthread_mutex_lock(hdb->wmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5209,7 +5452,7 @@ static bool tchdblockwal(TCHDB *hdb){
 /* Unlock the write ahead logging file of the hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false. */
-static bool tchdbunlockwal(TCHDB *hdb){
+EJDB_INLINE bool tchdbunlockwal(TCHDB *hdb){
   assert(hdb);
   if(pthread_mutex_unlock(hdb->wmtx) != 0){
     tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
@@ -5219,7 +5462,75 @@ static bool tchdbunlockwal(TCHDB *hdb){
   return true;
 }
 
+static bool tchdbftruncate(TCHDB *hdb, off_t length) {
+    return tchdbftruncate2(hdb, length, 0);
+}
 
+static bool tchdbftruncate2(TCHDB *hdb, off_t length, int opts) {
+#ifndef _WIN32
+    if (!(hdb->omode & HDBOWRITER)) {
+        return true;
+    }
+    bool err = (ftruncate(hdb->fd, length) != -1);
+    hdb->xfsiz = (err ? 0 : length);
+    return !err;
+#else
+    bool err = false;
+    LARGE_INTEGER size;
+    size.QuadPart = (hdb->omode & HDBOWRITER) ?  tcpagealign((length == 0) ? 1 : length) : length; //MSDN: Applications should test for files with a length of 0 (zero) and reject those files.
+    if (hdb->map && length > 0 && (size.QuadPart <= hdb->xfsiz || size.QuadPart <= hdb->fsiz || !(hdb->omode & HDBOWRITER))) {
+        return true;
+    }
+    if (!(opts & HDBWRITENOLOCK) && !HDBLOCKSMEM(hdb, true)) {
+        return false;
+    }
+    if (hdb->map) {
+        FlushViewOfFile((PCVOID) hdb->map, 0);
+        if (!UnmapViewOfFile((LPCVOID) hdb->map) || !CloseHandle(hdb->w32hmap)) {
+            tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
+            err = true;
+            goto finish;
+        }
+        hdb->map = NULL;
+        hdb->w32hmap = INVALID_HANDLE_VALUE;
+    }
+    if (hdb->omode & HDBOWRITER) {
+        if (!SetFilePointerEx(hdb->fd, size, NULL, FILE_BEGIN) || !SetEndOfFile(hdb->fd)) {
+            tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
+            err = true;
+            goto finish;
+        }
+    }
+    hdb->w32hmap = CreateFileMapping(hdb->fd, NULL,
+            ((hdb->omode & HDBOWRITER) ? PAGE_READWRITE : PAGE_READONLY),
+            size.HighPart, size.LowPart, NULL);
+    if (INVALIDHANDLE(hdb->w32hmap)) {
+        tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
+        err = true;
+        goto finish;
+    }
+    hdb->map = MapViewOfFile(hdb->w32hmap,
+            ((hdb->omode & HDBOWRITER) ? FILE_MAP_WRITE : FILE_MAP_READ),
+            0, 0, 0);
+    if (hdb->map == NULL) {
+        tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
+        err = true;
+        goto finish;
+    }
+    hdb->xfsiz = size.QuadPart;
+    if (length == 0) {
+        size.QuadPart = 0;
+        if (!SetFilePointerEx(hdb->fd, size, NULL, FILE_BEGIN)) {
+            tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
+            err = true;
+            goto finish;
+        }
+    }
+finish:
+    if (!(opts & HDBWRITENOLOCK)) HDBUNLOCKSMEM(hdb);
+    return !err;
+#endif
+}
 
 /*************************************************************************************************
  * debugging functions
@@ -5230,35 +5541,37 @@ static bool tchdbunlockwal(TCHDB *hdb){
    `hdb' specifies the hash database object. */
 void tchdbprintmeta(TCHDB *hdb){
   assert(hdb);
-  if(hdb->dbgfd < 0) return;
-  int dbgfd = (hdb->dbgfd == UINT16_MAX) ? 1 : hdb->dbgfd;
+  HANDLE dbgfd = hdb->dbgfd;
+  if(INVALIDHANDLE(dbgfd)) {
+      dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[HDBIOBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "META:");
   wp += sprintf(wp, " mmtx=%p", (void *)hdb->mmtx);
   wp += sprintf(wp, " rmtxs=%p", (void *)hdb->rmtxs);
   wp += sprintf(wp, " dmtx=%p", (void *)hdb->dmtx);
+  wp += sprintf(wp, " smtx=%p", (void *)hdb->smtx);
   wp += sprintf(wp, " wmtx=%p", (void *)hdb->wmtx);
   wp += sprintf(wp, " eckey=%p", (void *)hdb->eckey);
   wp += sprintf(wp, " rpath=%s", hdb->rpath ? hdb->rpath : "-");
   wp += sprintf(wp, " type=%02X", hdb->type);
   wp += sprintf(wp, " flags=%02X", hdb->flags);
-  wp += sprintf(wp, " bnum=%llu", (unsigned long long)hdb->bnum);
+  wp += sprintf(wp, " bnum=%" PRIuMAX "", (unsigned long long)hdb->bnum);
   wp += sprintf(wp, " apow=%u", hdb->apow);
   wp += sprintf(wp, " fpow=%u", hdb->fpow);
   wp += sprintf(wp, " opts=%u", hdb->opts);
   wp += sprintf(wp, " path=%s", hdb->path ? hdb->path : "-");
   wp += sprintf(wp, " fd=%d", hdb->fd);
   wp += sprintf(wp, " omode=%u", hdb->omode);
-  wp += sprintf(wp, " rnum=%llu", (unsigned long long)hdb->rnum);
-  wp += sprintf(wp, " fsiz=%llu", (unsigned long long)hdb->fsiz);
-  wp += sprintf(wp, " frec=%llu", (unsigned long long)hdb->frec);
-  wp += sprintf(wp, " dfcur=%llu", (unsigned long long)hdb->dfcur);
-  wp += sprintf(wp, " iter=%llu", (unsigned long long)hdb->iter);
+  wp += sprintf(wp, " rnum=%" PRIuMAX "", (unsigned long long)hdb->rnum);
+  wp += sprintf(wp, " fsiz=%" PRIuMAX "", (unsigned long long)hdb->fsiz);
+  wp += sprintf(wp, " frec=%" PRIuMAX "", (unsigned long long)hdb->frec);
+  wp += sprintf(wp, " dfcur=%" PRIuMAX "", (unsigned long long)hdb->dfcur);
+  wp += sprintf(wp, " iter=%" PRIuMAX "", (unsigned long long)hdb->iter);
   wp += sprintf(wp, " map=%p", (void *)hdb->map);
-  wp += sprintf(wp, " msiz=%llu", (unsigned long long)hdb->msiz);
-  wp += sprintf(wp, " ba32=%p", (void *)hdb->ba32);
-  wp += sprintf(wp, " ba64=%p", (void *)hdb->ba64);
+  wp += sprintf(wp, " msiz=%" PRIuMAX "", (unsigned long long)hdb->msiz);
+  wp += sprintf(wp, " ba64=%d", hdb->ba64);
   wp += sprintf(wp, " align=%u", hdb->align);
   wp += sprintf(wp, " runit=%u", hdb->runit);
   wp += sprintf(wp, " zmode=%u", hdb->zmode);
@@ -5268,36 +5581,36 @@ void tchdbprintmeta(TCHDB *hdb){
   wp += sprintf(wp, " fbpmis=%d", hdb->fbpmis);
   wp += sprintf(wp, " drpool=%p", (void *)hdb->drpool);
   wp += sprintf(wp, " drpdef=%p", (void *)hdb->drpdef);
-  wp += sprintf(wp, " drpoff=%llu", (unsigned long long)hdb->drpoff);
+  wp += sprintf(wp, " drpoff=%" PRIuMAX "", (unsigned long long)hdb->drpoff);
   wp += sprintf(wp, " recc=%p", (void *)hdb->recc);
   wp += sprintf(wp, " rcnum=%u", hdb->rcnum);
   wp += sprintf(wp, " ecode=%d", hdb->ecode);
   wp += sprintf(wp, " fatal=%u", hdb->fatal);
-  wp += sprintf(wp, " inode=%llu", (unsigned long long)(uint64_t)hdb->inode);
-  wp += sprintf(wp, " mtime=%llu", (unsigned long long)(uint64_t)hdb->mtime);
+  wp += sprintf(wp, " inode=%" PRIuMAX "", (unsigned long long)(uint64_t)hdb->inode);
+  wp += sprintf(wp, " mtime=%" PRIuMAX "", (unsigned long long)(uint64_t)hdb->mtime);
   wp += sprintf(wp, " dfunit=%u", hdb->dfunit);
   wp += sprintf(wp, " dfcnt=%u", hdb->dfcnt);
   wp += sprintf(wp, " tran=%d", hdb->tran);
   wp += sprintf(wp, " walfd=%d", hdb->walfd);
-  wp += sprintf(wp, " walend=%llu", (unsigned long long)hdb->walend);
+  wp += sprintf(wp, " walend=%" PRIuMAX "", (unsigned long long)hdb->walend);
   wp += sprintf(wp, " dbgfd=%d", hdb->dbgfd);
-  wp += sprintf(wp, " cnt_writerec=%lld", (long long)hdb->cnt_writerec);
-  wp += sprintf(wp, " cnt_reuserec=%lld", (long long)hdb->cnt_reuserec);
-  wp += sprintf(wp, " cnt_moverec=%lld", (long long)hdb->cnt_moverec);
-  wp += sprintf(wp, " cnt_readrec=%lld", (long long)hdb->cnt_readrec);
-  wp += sprintf(wp, " cnt_searchfbp=%lld", (long long)hdb->cnt_searchfbp);
-  wp += sprintf(wp, " cnt_insertfbp=%lld", (long long)hdb->cnt_insertfbp);
-  wp += sprintf(wp, " cnt_splicefbp=%lld", (long long)hdb->cnt_splicefbp);
-  wp += sprintf(wp, " cnt_dividefbp=%lld", (long long)hdb->cnt_dividefbp);
-  wp += sprintf(wp, " cnt_mergefbp=%lld", (long long)hdb->cnt_mergefbp);
-  wp += sprintf(wp, " cnt_reducefbp=%lld", (long long)hdb->cnt_reducefbp);
-  wp += sprintf(wp, " cnt_appenddrp=%lld", (long long)hdb->cnt_appenddrp);
-  wp += sprintf(wp, " cnt_deferdrp=%lld", (long long)hdb->cnt_deferdrp);
-  wp += sprintf(wp, " cnt_flushdrp=%lld", (long long)hdb->cnt_flushdrp);
-  wp += sprintf(wp, " cnt_adjrecc=%lld", (long long)hdb->cnt_adjrecc);
-  wp += sprintf(wp, " cnt_defrag=%lld", (long long)hdb->cnt_defrag);
-  wp += sprintf(wp, " cnt_shiftrec=%lld", (long long)hdb->cnt_shiftrec);
-  wp += sprintf(wp, " cnt_trunc=%lld", (long long)hdb->cnt_trunc);
+  wp += sprintf(wp, " cnt_writerec=%" PRIdMAX "", (long long)hdb->cnt_writerec);
+  wp += sprintf(wp, " cnt_reuserec=%" PRIdMAX "", (long long)hdb->cnt_reuserec);
+  wp += sprintf(wp, " cnt_moverec=%" PRIdMAX "", (long long)hdb->cnt_moverec);
+  wp += sprintf(wp, " cnt_readrec=%" PRIdMAX "", (long long)hdb->cnt_readrec);
+  wp += sprintf(wp, " cnt_searchfbp=%" PRIdMAX "", (long long)hdb->cnt_searchfbp);
+  wp += sprintf(wp, " cnt_insertfbp=%" PRIdMAX "", (long long)hdb->cnt_insertfbp);
+  wp += sprintf(wp, " cnt_splicefbp=%" PRIdMAX "", (long long)hdb->cnt_splicefbp);
+  wp += sprintf(wp, " cnt_dividefbp=%" PRIdMAX "", (long long)hdb->cnt_dividefbp);
+  wp += sprintf(wp, " cnt_mergefbp=%" PRIdMAX "", (long long)hdb->cnt_mergefbp);
+  wp += sprintf(wp, " cnt_reducefbp=%" PRIdMAX "", (long long)hdb->cnt_reducefbp);
+  wp += sprintf(wp, " cnt_appenddrp=%" PRIdMAX "", (long long)hdb->cnt_appenddrp);
+  wp += sprintf(wp, " cnt_deferdrp=%" PRIdMAX "", (long long)hdb->cnt_deferdrp);
+  wp += sprintf(wp, " cnt_flushdrp=%" PRIdMAX "", (long long)hdb->cnt_flushdrp);
+  wp += sprintf(wp, " cnt_adjrecc=%" PRIdMAX "", (long long)hdb->cnt_adjrecc);
+  wp += sprintf(wp, " cnt_defrag=%" PRIdMAX "", (long long)hdb->cnt_defrag);
+  wp += sprintf(wp, " cnt_shiftrec=%" PRIdMAX "", (long long)hdb->cnt_shiftrec);
+  wp += sprintf(wp, " cnt_trunc=%" PRIdMAX "", (long long)hdb->cnt_trunc);
   *(wp++) = '\n';
   tcwrite(dbgfd, buf, wp - buf);
 }
@@ -5308,23 +5621,25 @@ void tchdbprintmeta(TCHDB *hdb){
    `rec' specifies the record. */
 void tchdbprintrec(TCHDB *hdb, TCHREC *rec){
   assert(hdb && rec);
-  if(hdb->dbgfd < 0) return;
-  int dbgfd = (hdb->dbgfd == UINT16_MAX) ? 1 : hdb->dbgfd;
+  HANDLE dbgfd = hdb->dbgfd;
+  if(INVALIDHANDLE(dbgfd)) {
+      dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[HDBIOBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "REC:");
-  wp += sprintf(wp, " off=%llu", (unsigned long long)rec->off);
+  wp += sprintf(wp, " off=%" PRIuMAX "", (unsigned long long)rec->off);
   wp += sprintf(wp, " rsiz=%u", rec->rsiz);
   wp += sprintf(wp, " magic=%02X", rec->magic);
   wp += sprintf(wp, " hash=%02X", rec->hash);
-  wp += sprintf(wp, " left=%llu", (unsigned long long)rec->left);
-  wp += sprintf(wp, " right=%llu", (unsigned long long)rec->right);
+  wp += sprintf(wp, " left=%" PRIuMAX "", (unsigned long long)rec->left);
+  wp += sprintf(wp, " right=%" PRIuMAX "", (unsigned long long)rec->right);
   wp += sprintf(wp, " ksiz=%u", rec->ksiz);
   wp += sprintf(wp, " vsiz=%u", rec->vsiz);
   wp += sprintf(wp, " psiz=%u", rec->psiz);
   wp += sprintf(wp, " kbuf=%p", (void *)rec->kbuf);
   wp += sprintf(wp, " vbuf=%p", (void *)rec->vbuf);
-  wp += sprintf(wp, " boff=%llu", (unsigned long long)rec->boff);
+  wp += sprintf(wp, " boff=%" PRIuMAX "", (unsigned long long)rec->boff);
   wp += sprintf(wp, " bbuf=%p", (void *)rec->bbuf);
   *(wp++) = '\n';
   tcwrite(dbgfd, buf, wp - buf);
index 3a0fd2e..130391e 100644 (file)
@@ -40,6 +40,7 @@ typedef struct {                         /* type of structure for a hash databas
   void *mmtx;                            /* mutex for method */
   void *rmtxs;                           /* mutexes for records */
   void *dmtx;                            /* mutex for the while database */
+  void *smtx;                            /* rw mutex for shared memory */
   void *wmtx;                            /* mutex for write ahead logging */
   void *eckey;                           /* key for thread specific error code */
   char *rpath;                           /* real path for locking */
@@ -50,19 +51,18 @@ typedef struct {                         /* type of structure for a hash databas
   uint8_t fpow;                          /* power of free block pool number */
   uint8_t opts;                          /* options */
   char *path;                            /* path of the database file */
-  int fd;                                /* file descriptor of the database file */
+  HANDLE fd;                             /* file descriptor of the database file */
   uint32_t omode;                        /* open mode */
   uint64_t rnum;                         /* number of the records */
   uint64_t fsiz;                         /* size of the database file */
   uint64_t frec;                         /* offset of the first record */
   uint64_t dfcur;                        /* offset of the cursor for defragmentation */
   uint64_t iter;                         /* offset of the iterator */
-  char *map;                             /* pointer to the mapped memory */
+  volatile char *map;                    /* pointer to the mapped memory */
   uint64_t msiz;                         /* size of the mapped memory */
   uint64_t xmsiz;                        /* size of the extra mapped memory */
   uint64_t xfsiz;                        /* extra size of the file for mapped memory */
-  uint32_t *ba32;                        /* 32-bit bucket array */
-  uint64_t *ba64;                        /* 64-bit bucket array */
+  bool ba64;                             /* using of 64-bit bucket array */
   uint32_t align;                        /* record alignment */
   uint32_t runit;                        /* record reading unit */
   bool zmode;                            /* whether compression is used */
@@ -80,16 +80,16 @@ typedef struct {                         /* type of structure for a hash databas
   void *encop;                           /* opaque object for the encoding functions */
   TCCODEC dec;                           /* pointer to the decoding function */
   void *decop;                           /* opaque object for the decoding functions */
-  int ecode;                             /* last happened error code */
+  volatile int ecode;                    /* last happened error code */
   bool fatal;                            /* whether a fatal error occured */
   uint64_t inode;                        /* inode number */
   time_t mtime;                          /* modification time */
   uint32_t dfunit;                       /* unit step number of auto defragmentation */
   uint32_t dfcnt;                        /* counter of auto defragmentation */
   bool tran;                             /* whether in the transaction */
-  int walfd;                             /* file descriptor of write ahead logging */
+  HANDLE walfd;                          /* file descriptor of write ahead logging */
   uint64_t walend;                       /* end offset of write ahead logging */
-  int dbgfd;                             /* file descriptor for debugging */
+  HANDLE dbgfd;                          /* file descriptor for debugging */
   volatile int64_t cnt_writerec;         /* tesing counter for record write times */
   volatile int64_t cnt_reuserec;         /* tesing counter for record reuse times */
   volatile int64_t cnt_moverec;          /* tesing counter for record move times */
@@ -107,6 +107,9 @@ typedef struct {                         /* type of structure for a hash databas
   volatile int64_t cnt_defrag;           /* tesing counter for defragmentation times */
   volatile int64_t cnt_shiftrec;         /* tesing counter for record shift times */
   volatile int64_t cnt_trunc;            /* tesing counter for truncation times */
+#ifdef _WIN32
+  volatile HANDLE w32hmap;                /* win32 file mappings for mmap */
+#endif
 } TCHDB;
 
 enum {                                   /* enumeration for additional flags */
@@ -136,19 +139,19 @@ enum {                                   /* enumeration for open modes */
 /* Get the message string corresponding to an error code.
    `ecode' specifies the error code.
    The return value is the message string of the error code. */
-const char *tchdberrmsg(int ecode);
+EJDB_EXPORT const char *tchdberrmsg(int ecode);
 
 
 /* Create a hash database object.
    The return value is the new hash database object. */
-TCHDB *tchdbnew(void);
+EJDB_EXPORT TCHDB *tchdbnew(void);
 
 
 /* Delete a hash database object.
    `hdb' specifies the hash database object.
    If the database is not closed, it is closed implicitly.  Note that the deleted object and its
    derivatives can not be used anymore. */
-void tchdbdel(TCHDB *hdb);
+EJDB_EXPORT void tchdbdel(TCHDB *hdb);
 
 
 /* Get the last happened error code of a hash database object.
@@ -163,7 +166,7 @@ void tchdbdel(TCHDB *hdb);
    for unlink error, `TCERENAME' for rename error, `TCEMKDIR' for mkdir error, `TCERMDIR' for
    rmdir error, `TCEKEEP' for existing record, `TCENOREC' for no record found, and `TCEMISC' for
    miscellaneous error. */
-int tchdbecode(TCHDB *hdb);
+EJDB_EXPORT int tchdbecode(TCHDB *hdb);
 
 
 /* Set mutual exclusion control of a hash database object for threading.
@@ -171,7 +174,7 @@ int tchdbecode(TCHDB *hdb);
    If successful, the return value is true, else, it is false.
    Note that the mutual exclusion control is needed if the object is shared by plural threads and
    this function should be called before the database is opened. */
-bool tchdbsetmutex(TCHDB *hdb);
+EJDB_EXPORT bool tchdbsetmutex(TCHDB *hdb);
 
 
 /* Set the tuning parameters of a hash database object.
@@ -189,7 +192,7 @@ bool tchdbsetmutex(TCHDB *hdb);
    BZIP2 encoding, `HDBTTCBS' specifies that each record is compressed with TCBS encoding.
    If successful, the return value is true, else, it is false.
    Note that the tuning parameters should be set before the database is opened. */
-bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
+EJDB_EXPORT bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
 /* Set the caching parameters of a hash database object.
@@ -198,7 +201,7 @@ bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts)
    record cache is disabled.  It is disabled by default.
    If successful, the return value is true, else, it is false.
    Note that the caching parameters should be set before the database is opened. */
-bool tchdbsetcache(TCHDB *hdb, int32_t rcnum);
+EJDB_EXPORT bool tchdbsetcache(TCHDB *hdb, int32_t rcnum);
 
 
 /* Set the size of the extra mapped memory of a hash database object.
@@ -207,7 +210,7 @@ bool tchdbsetcache(TCHDB *hdb, int32_t rcnum);
    mapped memory is disabled.  The default size is 67108864.
    If successful, the return value is true, else, it is false.
    Note that the mapping parameters should be set before the database is opened. */
-bool tchdbsetxmsiz(TCHDB *hdb, int64_t xmsiz);
+EJDB_EXPORT bool tchdbsetxmsiz(TCHDB *hdb, int64_t xmsiz);
 
 
 /* Set the unit step number of auto defragmentation of a hash database object.
@@ -216,7 +219,7 @@ bool tchdbsetxmsiz(TCHDB *hdb, int64_t xmsiz);
    is disabled.  It is disabled by default.
    If successful, the return value is true, else, it is false.
    Note that the defragmentation parameters should be set before the database is opened. */
-bool tchdbsetdfunit(TCHDB *hdb, int32_t dfunit);
+EJDB_EXPORT bool tchdbsetdfunit(TCHDB *hdb, int32_t dfunit);
 
 
 /* Open a database file and connect a hash database object.
@@ -230,7 +233,7 @@ bool tchdbsetdfunit(TCHDB *hdb, int32_t dfunit);
    bitwise-or: `HDBONOLCK', which means it opens the database file without file locking, or
    `HDBOLCKNB', which means locking is performed without blocking.
    If successful, the return value is true, else, it is false. */
-bool tchdbopen(TCHDB *hdb, const char *path, int omode);
+EJDB_EXPORT bool tchdbopen(TCHDB *hdb, const char *path, int omode);
 
 
 /* Close a hash database object.
@@ -238,7 +241,7 @@ bool tchdbopen(TCHDB *hdb, const char *path, int omode);
    If successful, the return value is true, else, it is false.
    Update of a database is assured to be written when the database is closed.  If a writer opens
    a database but does not close it appropriately, the database will be broken. */
-bool tchdbclose(TCHDB *hdb);
+EJDB_EXPORT bool tchdbclose(TCHDB *hdb);
 
 
 /* Store a record into a hash database object.
@@ -249,7 +252,7 @@ bool tchdbclose(TCHDB *hdb);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a hash database object.
@@ -258,7 +261,7 @@ bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tchdbput2(TCHDB *hdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tchdbput2(TCHDB *hdb, const char *kstr, const char *vstr);
 
 
 /* Store a new record into a hash database object.
@@ -269,7 +272,7 @@ bool tchdbput2(TCHDB *hdb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into a hash database object.
@@ -278,7 +281,7 @@ bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tchdbputkeep2(TCHDB *hdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tchdbputkeep2(TCHDB *hdb, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the existing record in a hash database object.
@@ -289,7 +292,7 @@ bool tchdbputkeep2(TCHDB *hdb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string value at the end of the existing record in a hash database object.
@@ -298,7 +301,7 @@ bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int v
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tchdbputcat2(TCHDB *hdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tchdbputcat2(TCHDB *hdb, const char *kstr, const char *vstr);
 
 
 /* Store a record into a hash database object in asynchronous fashion.
@@ -310,7 +313,7 @@ bool tchdbputcat2(TCHDB *hdb, const char *kstr, const char *vstr);
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten.  Records passed to
    this function are accumulated into the inner buffer and wrote into the file at a blast. */
-bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a hash database object in asynchronous fashion.
@@ -320,7 +323,7 @@ bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten.  Records passed to
    this function are accumulated into the inner buffer and wrote into the file at a blast. */
-bool tchdbputasync2(TCHDB *hdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tchdbputasync2(TCHDB *hdb, const char *kstr, const char *vstr);
 
 
 /* Remove a record of a hash database object.
@@ -328,14 +331,14 @@ bool tchdbputasync2(TCHDB *hdb, const char *kstr, const char *vstr);
    `kbuf' specifies the pointer to the region of the key.
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true, else, it is false. */
-bool tchdbout(TCHDB *hdb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tchdbout(TCHDB *hdb, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of a hash database object.
    `hdb' specifies the hash database object connected as a writer.
    `kstr' specifies the string of the key.
    If successful, the return value is true, else, it is false. */
-bool tchdbout2(TCHDB *hdb, const char *kstr);
+EJDB_EXPORT bool tchdbout2(TCHDB *hdb, const char *kstr);
 
 
 /* Retrieve a record in a hash database object.
@@ -350,7 +353,7 @@ bool tchdbout2(TCHDB *hdb, const char *kstr);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
 
 
 /**
@@ -361,7 +364,7 @@ void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
  * @param xstr specifies extensible string object data will be stored into.
  * @return
  */
-int tchdbgetintoxstr(TCHDB *hdb, const void *kbuf, int ksiz, TCXSTR *xstr);
+EJDB_EXPORT int tchdbgetintoxstr(TCHDB *hdb, const void *kbuf, int ksiz, TCXSTR *xstr);
 
 
 /* Retrieve a string record in a hash database object.
@@ -371,7 +374,7 @@ int tchdbgetintoxstr(TCHDB *hdb, const void *kbuf, int ksiz, TCXSTR *xstr);
    `NULL' is returned if no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tchdbget2(TCHDB *hdb, const char *kstr);
+EJDB_EXPORT char *tchdbget2(TCHDB *hdb, const char *kstr);
 
 
 /* Retrieve a record in a hash database object and write the value into a buffer.
@@ -385,7 +388,7 @@ char *tchdbget2(TCHDB *hdb, const char *kstr);
    returned if no record corresponds to the specified key.
    Note that an additional zero code is not appended at the end of the region of the writing
    buffer. */
-int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max);
+EJDB_EXPORT int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max);
 
 
 /* Get the size of the value of a record in a hash database object.
@@ -394,7 +397,7 @@ int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz);
 
 
 /* Get the size of the value of a string record in a hash database object.
@@ -402,15 +405,15 @@ int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tchdbvsiz2(TCHDB *hdb, const char *kstr);
+EJDB_EXPORT int tchdbvsiz2(TCHDB *hdb, const char *kstr);
 
 
 /* Initialize the iterator of a hash database object.
    `hdb' specifies the hash database object.
    If successful, the return value is true, else, it is false.
    The iterator is used in order to access the key of every record stored in a database. */
-bool tchdbiterinit(TCHDB *hdb);
-bool tchdbiterinit4(TCHDB *hdb, uint64_t *iter);
+EJDB_EXPORT bool tchdbiterinit(TCHDB *hdb);
+EJDB_EXPORT bool tchdbiterinit4(TCHDB *hdb, uint64_t *iter);
 
 
 /* Get the next key of the iterator of a hash database object.
@@ -427,7 +430,7 @@ bool tchdbiterinit4(TCHDB *hdb, uint64_t *iter);
    However, it is not assured if updating the database is occurred while the iteration.  Besides,
    the order of this traversal access method is arbitrary, so it is not assured that the order of
    storing matches the one of the traversal access. */
-void *tchdbiternext(TCHDB *hdb, int *sp);
+EJDB_EXPORT void *tchdbiternext(TCHDB *hdb, int *sp);
 
 
 /* Get the next key string of the iterator of a hash database object.
@@ -440,7 +443,7 @@ void *tchdbiternext(TCHDB *hdb, int *sp);
    database is occurred while the iteration.  Besides, the order of this traversal access method
    is arbitrary, so it is not assured that the order of storing matches the one of the traversal
    access. */
-char *tchdbiternext2(TCHDB *hdb);
+EJDB_EXPORT char *tchdbiternext2(TCHDB *hdb);
 
 
 /* Get the next extensible objects of the iterator of a hash database object.
@@ -449,8 +452,8 @@ char *tchdbiternext2(TCHDB *hdb);
    `vxstr' specifies the object into which the next value is wrote down.
    If successful, the return value is true, else, it is false.  False is returned when no record
    is to be get out of the iterator. */
-bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr);
-bool tchdbiternext4(TCHDB *hdb, uint64_t *iter, TCXSTR *kxstr, TCXSTR *vxstr);
+EJDB_EXPORT bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr);
+EJDB_EXPORT bool tchdbiternext4(TCHDB *hdb, uint64_t *iter, TCXSTR *kxstr, TCXSTR *vxstr);
 
 
 /* Get forward matching keys in a hash database object.
@@ -464,7 +467,7 @@ bool tchdbiternext4(TCHDB *hdb, uint64_t *iter, TCXSTR *kxstr, TCXSTR *vxstr);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string keys in a hash database object.
@@ -477,7 +480,7 @@ TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tchdbfwmkeys2(TCHDB *hdb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tchdbfwmkeys2(TCHDB *hdb, const char *pstr, int max);
 
 
 /* Add an integer to a record in a hash database object.
@@ -488,7 +491,7 @@ TCLIST *tchdbfwmkeys2(TCHDB *hdb, const char *pstr, int max);
    If successful, the return value is the summation value, else, it is `INT_MIN'.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tchdbaddint(TCHDB *hdb, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tchdbaddint(TCHDB *hdb, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in a hash database object.
@@ -499,14 +502,14 @@ int tchdbaddint(TCHDB *hdb, const void *kbuf, int ksiz, int num);
    If successful, the return value is the summation value, else, it is Not-a-Number.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tchdbadddouble(TCHDB *hdb, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tchdbadddouble(TCHDB *hdb, const void *kbuf, int ksiz, double num);
 
 
 /* Synchronize updated contents of a hash database object with the file and the device.
    `hdb' specifies the hash database object connected as a writer.
    If successful, the return value is true, else, it is false.
    This function is useful when another process connects to the same database file. */
-bool tchdbsync(TCHDB *hdb);
+EJDB_EXPORT bool tchdbsync(TCHDB *hdb);
 
 
 /* Optimize the file of a hash database object.
@@ -525,13 +528,13 @@ bool tchdbsync(TCHDB *hdb);
    If successful, the return value is true, else, it is false.
    This function is useful to reduce the size of the database file with data fragmentation by
    successive updating. */
-bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
+EJDB_EXPORT bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
 /* Remove all records of a hash database object.
    `hdb' specifies the hash database object connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tchdbvanish(TCHDB *hdb);
+EJDB_EXPORT bool tchdbvanish(TCHDB *hdb);
 
 
 /* Copy the database file of a hash database object.
@@ -543,7 +546,7 @@ bool tchdbvanish(TCHDB *hdb);
    The database file is assured to be kept synchronized and not modified while the copying or
    executing operation is in progress.  So, this function is useful to create a backup file of
    the database file. */
-bool tchdbcopy(TCHDB *hdb, const char *path);
+EJDB_EXPORT bool tchdbcopy(TCHDB *hdb, const char *path);
 
 
 /* Begin the transaction of a hash database object.
@@ -554,14 +557,14 @@ bool tchdbcopy(TCHDB *hdb, const char *path);
    assumed if every database operation is performed in the transaction.  All updated regions are
    kept track of by write ahead logging while the transaction.  If the database is closed during
    transaction, the transaction is aborted implicitly. */
-bool tchdbtranbegin(TCHDB *hdb);
+EJDB_EXPORT bool tchdbtranbegin(TCHDB *hdb);
 
 
 /* Commit the transaction of a hash database object.
    `hdb' specifies the hash database object connected as a writer.
    If successful, the return value is true, else, it is false.
    Update in the transaction is fixed when it is committed successfully. */
-bool tchdbtrancommit(TCHDB *hdb);
+EJDB_EXPORT bool tchdbtrancommit(TCHDB *hdb);
 
 
 /* Abort the transaction of a hash database object.
@@ -569,28 +572,28 @@ bool tchdbtrancommit(TCHDB *hdb);
    If successful, the return value is true, else, it is false.
    Update in the transaction is discarded when it is aborted.  The state of the database is
    rollbacked to before transaction. */
-bool tchdbtranabort(TCHDB *hdb);
+EJDB_EXPORT bool tchdbtranabort(TCHDB *hdb);
 
 
 /* Get the file path of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the path of the database file or `NULL' if the object does not connect to
    any database file. */
-const char *tchdbpath(TCHDB *hdb);
+EJDB_EXPORT const char *tchdbpath(TCHDB *hdb);
 
 
 /* Get the number of records of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the number of records or 0 if the object does not connect to any database
    file. */
-uint64_t tchdbrnum(TCHDB *hdb);
+EJDB_EXPORT uint64_t tchdbrnum(TCHDB *hdb);
 
 
 /* Get the size of the database file of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the size of the database file or 0 if the object does not connect to any
    database file. */
-uint64_t tchdbfsiz(TCHDB *hdb);
+EJDB_EXPORT uint64_t tchdbfsiz(TCHDB *hdb);
 
 
 
@@ -605,31 +608,31 @@ uint64_t tchdbfsiz(TCHDB *hdb);
    `file' specifies the file name of the code.
    `line' specifies the line number of the code.
    `func' specifies the function name of the code. */
-void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func);
+EJDB_EXPORT void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func);
 
 
 /* Set the type of a hash database object.
    `hdb' specifies the hash database object.
    `type' specifies the database type. */
-void tchdbsettype(TCHDB *hdb, uint8_t type);
+EJDB_EXPORT void tchdbsettype(TCHDB *hdb, uint8_t type);
 
 
 /* Set the file descriptor for debugging output.
    `hdb' specifies the hash database object.
    `fd' specifies the file descriptor for debugging output. */
-void tchdbsetdbgfd(TCHDB *hdb, int fd);
+EJDB_EXPORT void tchdbsetdbgfd(TCHDB *hdb, HANDLE fd);
 
 
 /* Get the file descriptor for debugging output.
    `hdb' specifies the hash database object.
    The return value is the file descriptor for debugging output. */
-int tchdbdbgfd(TCHDB *hdb);
+EJDB_EXPORT HANDLE tchdbdbgfd(TCHDB *hdb);
 
 
 /* Check whether mutual exclusion control is set to a hash database object.
    `hdb' specifies the hash database object.
    If mutual exclusion control is set, it is true, else it is false. */
-bool tchdbhasmutex(TCHDB *hdb);
+EJDB_EXPORT bool tchdbhasmutex(TCHDB *hdb);
 
 
 /* Synchronize updating contents on memory of a hash database object.
@@ -643,80 +646,93 @@ bool tchdbmemsync(TCHDB *hdb, bool phys);
    `hdb' specifies the hash database object.
    The return value is the number of elements of the bucket array or 0 if the object does not
    connect to any database file. */
-uint64_t tchdbbnum(TCHDB *hdb);
+EJDB_EXPORT uint64_t tchdbbnum(TCHDB *hdb);
 
 
 /* Get the record alignment of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the record alignment or 0 if the object does not connect to any database
    file. */
-uint32_t tchdbalign(TCHDB *hdb);
+EJDB_EXPORT uint32_t tchdbalign(TCHDB *hdb);
 
 
 /* Get the maximum number of the free block pool of a a hash database object.
    `hdb' specifies the hash database object.
    The return value is the maximum number of the free block pool or 0 if the object does not
    connect to any database file. */
-uint32_t tchdbfbpmax(TCHDB *hdb);
+EJDB_EXPORT uint32_t tchdbfbpmax(TCHDB *hdb);
 
 
 /* Get the size of the extra mapped memory of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the size of the extra mapped memory or 0 if the object does not connect to
    any database file. */
-uint64_t tchdbxmsiz(TCHDB *hdb);
+EJDB_EXPORT uint64_t tchdbxmsiz(TCHDB *hdb);
 
 
 /* Get the inode number of the database file of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-uint64_t tchdbinode(TCHDB *hdb);
+EJDB_EXPORT uint64_t tchdbinode(TCHDB *hdb);
 
 
 /* Get the modification time of the database file of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-time_t tchdbmtime(TCHDB *hdb);
+EJDB_EXPORT time_t tchdbmtime(TCHDB *hdb);
 
 
 /* Get the connection mode of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the connection mode. */
-int tchdbomode(TCHDB *hdb);
+EJDB_EXPORT int tchdbomode(TCHDB *hdb);
 
 
 /* Get the database type of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the database type. */
-uint8_t tchdbtype(TCHDB *hdb);
+EJDB_EXPORT uint8_t tchdbtype(TCHDB *hdb);
 
 
 /* Get the additional flags of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the additional flags. */
-uint8_t tchdbflags(TCHDB *hdb);
+EJDB_EXPORT uint8_t tchdbflags(TCHDB *hdb);
 
 
 /* Get the options of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the options. */
-uint8_t tchdbopts(TCHDB *hdb);
+EJDB_EXPORT uint8_t tchdbopts(TCHDB *hdb);
 
 
-/* Get the pointer to the opaque field of a hash database object.
-   `hdb' specifies the hash database object.
-   The return value is the pointer to the opaque field whose size is 128 bytes. */
-char *tchdbopaque(TCHDB *hdb);
+/**
+ * Get opaque data into specified buffer `dst`
+ * `bsiz` Max size to be read.
+ *  Return -1 if error, otherwise number of bytes writen in dst.
+ */
+int tchdbreadopaque(TCHDB *hdb, void *dst, int off, int bsiz);
+
+/**
+ * Write opaque data.
+ * Number of bytes specified bt `nb`
+ * can be truncated if it greater than max opaque data size.
+ * Return -1 if error, otherwise number of bytes read from src.
+ */
+int tchdbwriteopaque(TCHDB *hdb, const void *src, int off, int nb);
 
+/**
+ * Copy opaque data between databases
+ */
+bool tchdbcopyopaque(TCHDB *dst, TCHDB *src, int off, int nb);
 
 /* Get the number of used elements of the bucket array of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the number of used elements of the bucket array or 0 if the object does
    not connect to any database file. */
-uint64_t tchdbbnumused(TCHDB *hdb);
-
+EJDB_EXPORT uint64_t tchdbbnumused(TCHDB *hdb);
 
 /* Set the custom codec functions of a hash database object.
    `hdb' specifies the hash database object.
@@ -734,7 +750,7 @@ uint64_t tchdbbnumused(TCHDB *hdb);
    If successful, the return value is true, else, it is false.
    Note that the custom codec functions should be set before the database is opened and should be
    set every time the database is being opened. */
-bool tchdbsetcodecfunc(TCHDB *hdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
+EJDB_EXPORT bool tchdbsetcodecfunc(TCHDB *hdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
 
 
 /* Get the custom codec functions of a hash database object.
@@ -747,13 +763,13 @@ bool tchdbsetcodecfunc(TCHDB *hdb, TCCODEC enc, void *encop, TCCODEC dec, void *
    function is assigned
    `dop' specifies the pointer to a variable into which the arbitrary pointer to be given to the
    decoding function is assigned. */
-void tchdbcodecfunc(TCHDB *hdb, TCCODEC *ep, void **eop, TCCODEC *dp, void **dop);
+EJDB_EXPORT void tchdbcodecfunc(TCHDB *hdb, TCCODEC *ep, void **eop, TCCODEC *dp, void **dop);
 
 
 /* Get the unit step number of auto defragmentation of a hash database object.
    `hdb' specifies the hash database object.
    The return value is the unit step number of auto defragmentation. */
-uint32_t tchdbdfunit(TCHDB *hdb);
+EJDB_EXPORT uint32_t tchdbdfunit(TCHDB *hdb);
 
 
 /* Perform dynamic defragmentation of a hash database object.
@@ -761,13 +777,13 @@ uint32_t tchdbdfunit(TCHDB *hdb);
    `step' specifie the number of steps.  If it is not more than 0, the whole file is defragmented
    gradually without keeping a continuous lock.
    If successful, the return value is true, else, it is false. */
-bool tchdbdefrag(TCHDB *hdb, int64_t step);
+EJDB_EXPORT bool tchdbdefrag(TCHDB *hdb, int64_t step);
 
 
 /* Clear the cache of a hash tree database object.
    `hdb' specifies the hash tree database object.
    If successful, the return value is true, else, it is false. */
-bool tchdbcacheclear(TCHDB *hdb);
+EJDB_EXPORT bool tchdbcacheclear(TCHDB *hdb);
 
 
 /* Store a record into a hash database object with a duplication handler.
@@ -789,7 +805,7 @@ bool tchdbcacheclear(TCHDB *hdb);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tchdbputproc(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tchdbputproc(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -806,7 +822,7 @@ bool tchdbputproc(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tchdbgetnext(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tchdbgetnext(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve the next string record in a hash database object.
@@ -816,7 +832,7 @@ void *tchdbgetnext(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
    returned if no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tchdbgetnext2(TCHDB *hdb, const char *kstr);
+EJDB_EXPORT char *tchdbgetnext2(TCHDB *hdb, const char *kstr);
 
 
 /* Retrieve the key and the value of the next record of a record in a hash database object.
@@ -832,7 +848,7 @@ char *tchdbgetnext2(TCHDB *hdb, const char *kstr);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  The retion pointed to by `vbp'
    should not be released. */
-char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char **vbp, int *vsp);
+EJDB_EXPORT char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char **vbp, int *vsp);
 
 
 /* Move the iterator to the record corresponding a key of a hash database object.
@@ -841,7 +857,7 @@ char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record corresponding the condition. */
-bool tchdbiterinit2(TCHDB *hdb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tchdbiterinit2(TCHDB *hdb, const void *kbuf, int ksiz);
 
 
 /* Move the iterator to the record corresponding a key string of a hash database object.
@@ -849,7 +865,7 @@ bool tchdbiterinit2(TCHDB *hdb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record corresponding the condition. */
-bool tchdbiterinit3(TCHDB *hdb, const char *kstr);
+EJDB_EXPORT bool tchdbiterinit3(TCHDB *hdb, const char *kstr);
 
 
 /* Process each record atomically of a hash database object.
@@ -865,14 +881,14 @@ bool tchdbiterinit3(TCHDB *hdb, const char *kstr);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tchdbforeach(TCHDB *hdb, TCITER iter, void *op);
+EJDB_EXPORT bool tchdbforeach(TCHDB *hdb, TCITER iter, void *op);
 
 
 /* Void the transaction of a hash database object.
    `hdb' specifies the hash database object connected as a writer.
    If successful, the return value is true, else, it is false.
    This function should be called only when no update in the transaction. */
-bool tchdbtranvoid(TCHDB *hdb);
+EJDB_EXPORT bool tchdbtranvoid(TCHDB *hdb);
 
 
 
index f68dabe..e1150eb 100644 (file)
@@ -21,7 +21,7 @@
 
 /* global variables */
 const char *g_progname;                  // program name
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -55,9 +55,16 @@ static int procversion(void);
 /* main routine */
 int main(int argc, char **argv){
   g_progname = argv[0];
-  g_dbgfd = -1;
+  g_dbgfd = INVALID_HANDLE_VALUE;
   const char *ebuf = getenv("TCDBGFD");
-  if(ebuf) g_dbgfd = tcatoix(ebuf);
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "create")){
@@ -505,7 +512,7 @@ static int runversion(int argc, char **argv){
 /* perform create command */
 static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
     printerr(hdb);
@@ -530,7 +537,7 @@ static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
 /* perform inform command */
 static int procinform(const char *path, int omode){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL);
   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
     printerr(hdb);
@@ -554,12 +561,12 @@ static int procinform(const char *path, int omode){
   if(flags & HDBFOPEN) printf(" open");
   if(flags & HDBFFATAL) printf(" fatal");
   printf("\n");
-  printf("bucket number: %llu\n", (unsigned long long)tchdbbnum(hdb));
+  printf("bucket number: %" PRIuMAX "\n", (unsigned long long)tchdbbnum(hdb));
   if(hdb->cnt_writerec >= 0)
-    printf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
+    printf("used bucket number: %" PRIdMAX "\n", (long long)tchdbbnumused(hdb));
   printf("alignment: %u\n", tchdbalign(hdb));
   printf("free block pool: %u\n", tchdbfbpmax(hdb));
-  printf("inode number: %lld\n", (long long)tchdbinode(hdb));
+  printf("inode number: %" PRIdMAX "\n", (long long)tchdbinode(hdb));
   char date[48];
   tcdatestrwww(tchdbmtime(hdb), INT_MAX, date);
   printf("modified time: %s\n", date);
@@ -571,8 +578,8 @@ static int procinform(const char *path, int omode){
   if(opts & HDBTTCBS) printf(" tcbs");
   if(opts & HDBTEXCODEC) printf(" excodec");
   printf("\n");
-  printf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  printf("file size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  printf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  printf("file size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   if(!tchdbclose(hdb)){
     if(!err) printerr(hdb);
     err = true;
@@ -586,7 +593,7 @@ static int procinform(const char *path, int omode){
 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
                    int omode, int dmode){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
     printerr(hdb);
@@ -646,7 +653,7 @@ static int procput(const char *path, const char *kbuf, int ksiz, const char *vbu
 /* perform out command */
 static int procout(const char *path, const char *kbuf, int ksiz, int omode){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
     printerr(hdb);
@@ -670,7 +677,7 @@ static int procout(const char *path, const char *kbuf, int ksiz, int omode){
 /* perform get command */
 static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
     printerr(hdb);
@@ -700,7 +707,7 @@ static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool
 /* perform list command */
 static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
     printerr(hdb);
@@ -759,7 +766,7 @@ static int proclist(const char *path, int omode, int max, bool pv, bool px, cons
 static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode,
                         bool df){
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
     printerr(hdb);
@@ -795,7 +802,7 @@ static int procimporttsv(const char *path, const char *file, int omode, bool sc)
     return 1;
   }
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetcodecfunc(hdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(hdb);
   if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | omode)){
     printerr(hdb);
index d46b5b5..68e265d 100644 (file)
@@ -69,7 +69,7 @@ typedef struct {                         // type of structure for race thread
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                             // debugging output
 
 
 /* function prototypes */
@@ -116,7 +116,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -196,25 +203,25 @@ static void eprint(TCHDB *hdb, int line, const char *func){
 /* print members of hash database */
 static void mprint(TCHDB *hdb){
   if(hdb->cnt_writerec < 0) return;
-  iprintf("bucket number: %lld\n", (long long)tchdbbnum(hdb));
-  iprintf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
-  iprintf("cnt_writerec: %lld\n", (long long)hdb->cnt_writerec);
-  iprintf("cnt_reuserec: %lld\n", (long long)hdb->cnt_reuserec);
-  iprintf("cnt_moverec: %lld\n", (long long)hdb->cnt_moverec);
-  iprintf("cnt_readrec: %lld\n", (long long)hdb->cnt_readrec);
-  iprintf("cnt_searchfbp: %lld\n", (long long)hdb->cnt_searchfbp);
-  iprintf("cnt_insertfbp: %lld\n", (long long)hdb->cnt_insertfbp);
-  iprintf("cnt_splicefbp: %lld\n", (long long)hdb->cnt_splicefbp);
-  iprintf("cnt_dividefbp: %lld\n", (long long)hdb->cnt_dividefbp);
-  iprintf("cnt_mergefbp: %lld\n", (long long)hdb->cnt_mergefbp);
-  iprintf("cnt_reducefbp: %lld\n", (long long)hdb->cnt_reducefbp);
-  iprintf("cnt_appenddrp: %lld\n", (long long)hdb->cnt_appenddrp);
-  iprintf("cnt_deferdrp: %lld\n", (long long)hdb->cnt_deferdrp);
-  iprintf("cnt_flushdrp: %lld\n", (long long)hdb->cnt_flushdrp);
-  iprintf("cnt_adjrecc: %lld\n", (long long)hdb->cnt_adjrecc);
-  iprintf("cnt_defrag: %lld\n", (long long)hdb->cnt_defrag);
-  iprintf("cnt_shiftrec: %lld\n", (long long)hdb->cnt_shiftrec);
-  iprintf("cnt_trunc: %lld\n", (long long)hdb->cnt_trunc);
+  iprintf("bucket number: %" PRIdMAX "\n", (long long)tchdbbnum(hdb));
+  iprintf("used bucket number: %" PRIdMAX "\n", (long long)tchdbbnumused(hdb));
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)hdb->cnt_writerec);
+  iprintf("cnt_reuserec: %" PRIdMAX "\n", (long long)hdb->cnt_reuserec);
+  iprintf("cnt_moverec: %" PRIdMAX "\n", (long long)hdb->cnt_moverec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)hdb->cnt_readrec);
+  iprintf("cnt_searchfbp: %" PRIdMAX "\n", (long long)hdb->cnt_searchfbp);
+  iprintf("cnt_insertfbp: %" PRIdMAX "\n", (long long)hdb->cnt_insertfbp);
+  iprintf("cnt_splicefbp: %" PRIdMAX "\n", (long long)hdb->cnt_splicefbp);
+  iprintf("cnt_dividefbp: %" PRIdMAX "\n", (long long)hdb->cnt_dividefbp);
+  iprintf("cnt_mergefbp: %" PRIdMAX "\n", (long long)hdb->cnt_mergefbp);
+  iprintf("cnt_reducefbp: %" PRIdMAX "\n", (long long)hdb->cnt_reducefbp);
+  iprintf("cnt_appenddrp: %" PRIdMAX "\n", (long long)hdb->cnt_appenddrp);
+  iprintf("cnt_deferdrp: %" PRIdMAX "\n", (long long)hdb->cnt_deferdrp);
+  iprintf("cnt_flushdrp: %" PRIdMAX "\n", (long long)hdb->cnt_flushdrp);
+  iprintf("cnt_adjrecc: %" PRIdMAX "\n", (long long)hdb->cnt_adjrecc);
+  iprintf("cnt_defrag: %" PRIdMAX "\n", (long long)hdb->cnt_defrag);
+  iprintf("cnt_shiftrec: %" PRIdMAX "\n", (long long)hdb->cnt_shiftrec);
+  iprintf("cnt_trunc: %" PRIdMAX "\n", (long long)hdb->cnt_trunc);
 }
 
 
@@ -631,7 +638,7 @@ static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, i
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -693,8 +700,8 @@ static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, i
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -716,7 +723,7 @@ static int procread(const char *path, int tnum, int rcnum, int xmsiz, int dfunit
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -775,8 +782,8 @@ static int procread(const char *path, int tnum, int rcnum, int xmsiz, int dfunit
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -798,7 +805,7 @@ static int procremove(const char *path, int tnum, int rcnum, int xmsiz, int dfun
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -855,8 +862,8 @@ static int procremove(const char *path, int tnum, int rcnum, int xmsiz, int dfun
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -877,7 +884,7 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode,
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -983,8 +990,8 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode,
     if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
   }
   tcmapdel(map);
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -1009,7 +1016,7 @@ static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow,
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -1071,8 +1078,8 @@ static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow,
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -1095,7 +1102,7 @@ static int procrace(const char *path, int tnum, int rnum, int bnum, int apow, in
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(!tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -1149,8 +1156,8 @@ static int procrace(const char *path, int tnum, int rnum, int bnum, int apow, in
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
index 7d63b9e..2f3036b 100644 (file)
@@ -24,7 +24,7 @@
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -60,12 +60,21 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode);
 
 /* main routine */
 int main(int argc, char **argv){
+
   g_progname = argv[0];
   const char *ebuf = getenv("TCRNDSEED");
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
+  g_dbgfd = INVALID_HANDLE_VALUE;
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -144,25 +153,29 @@ static void eprint(TCHDB *hdb, int line, const char *func){
 /* print members of hash database */
 static void mprint(TCHDB *hdb){
   if(hdb->cnt_writerec < 0) return;
-  iprintf("bucket number: %lld\n", (long long)tchdbbnum(hdb));
-  iprintf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
-  iprintf("cnt_writerec: %lld\n", (long long)hdb->cnt_writerec);
-  iprintf("cnt_reuserec: %lld\n", (long long)hdb->cnt_reuserec);
-  iprintf("cnt_moverec: %lld\n", (long long)hdb->cnt_moverec);
-  iprintf("cnt_readrec: %lld\n", (long long)hdb->cnt_readrec);
-  iprintf("cnt_searchfbp: %lld\n", (long long)hdb->cnt_searchfbp);
-  iprintf("cnt_insertfbp: %lld\n", (long long)hdb->cnt_insertfbp);
-  iprintf("cnt_splicefbp: %lld\n", (long long)hdb->cnt_splicefbp);
-  iprintf("cnt_dividefbp: %lld\n", (long long)hdb->cnt_dividefbp);
-  iprintf("cnt_mergefbp: %lld\n", (long long)hdb->cnt_mergefbp);
-  iprintf("cnt_reducefbp: %lld\n", (long long)hdb->cnt_reducefbp);
-  iprintf("cnt_appenddrp: %lld\n", (long long)hdb->cnt_appenddrp);
-  iprintf("cnt_deferdrp: %lld\n", (long long)hdb->cnt_deferdrp);
-  iprintf("cnt_flushdrp: %lld\n", (long long)hdb->cnt_flushdrp);
-  iprintf("cnt_adjrecc: %lld\n", (long long)hdb->cnt_adjrecc);
-  iprintf("cnt_defrag: %lld\n", (long long)hdb->cnt_defrag);
-  iprintf("cnt_shiftrec: %lld\n", (long long)hdb->cnt_shiftrec);
-  iprintf("cnt_trunc: %lld\n", (long long)hdb->cnt_trunc);
+  iprintf("bucket number: %" PRIdMAX "\n", (long long)tchdbbnum(hdb));
+  iprintf("used bucket number: %" PRIdMAX "\n", (long long)tchdbbnumused(hdb));
+  iprintf("msiz: %" PRIdMAX "\n", hdb->msiz);
+  iprintf("xmsiz: %" PRIdMAX "\n", hdb->xmsiz);
+  iprintf("fbpnum: %" PRIdMAX "\n", hdb->fbpnum);
+  iprintf("fbpool: %p\n", hdb->fbpool);
+  iprintf("cnt_writerec: %" PRIdMAX "\n", (long long)hdb->cnt_writerec);
+  iprintf("cnt_reuserec: %" PRIdMAX "\n", (long long)hdb->cnt_reuserec);
+  iprintf("cnt_moverec: %" PRIdMAX "\n", (long long)hdb->cnt_moverec);
+  iprintf("cnt_readrec: %" PRIdMAX "\n", (long long)hdb->cnt_readrec);
+  iprintf("cnt_searchfbp: %" PRIdMAX "\n", (long long)hdb->cnt_searchfbp);
+  iprintf("cnt_insertfbp: %" PRIdMAX "\n", (long long)hdb->cnt_insertfbp);
+  iprintf("cnt_splicefbp: %" PRIdMAX "\n", (long long)hdb->cnt_splicefbp);
+  iprintf("cnt_dividefbp: %" PRIdMAX "\n", (long long)hdb->cnt_dividefbp);
+  iprintf("cnt_mergefbp: %" PRIdMAX "\n", (long long)hdb->cnt_mergefbp);
+  iprintf("cnt_reducefbp: %" PRIdMAX "\n", (long long)hdb->cnt_reducefbp);
+  iprintf("cnt_appenddrp: %" PRIdMAX "\n", (long long)hdb->cnt_appenddrp);
+  iprintf("cnt_deferdrp: %" PRIdMAX "\n", (long long)hdb->cnt_deferdrp);
+  iprintf("cnt_flushdrp: %" PRIdMAX "\n", (long long)hdb->cnt_flushdrp);
+  iprintf("cnt_adjrecc: %" PRIdMAX "\n", (long long)hdb->cnt_adjrecc);
+  iprintf("cnt_defrag: %" PRIdMAX "\n", (long long)hdb->cnt_defrag);
+  iprintf("cnt_shiftrec: %" PRIdMAX "\n", (long long)hdb->cnt_shiftrec);
+  iprintf("cnt_trunc: %" PRIdMAX "\n", (long long)hdb->cnt_trunc);
 }
 
 
@@ -579,7 +592,7 @@ static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -630,8 +643,8 @@ static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -653,7 +666,7 @@ static int procread(const char *path, bool mt, int rcnum, int xmsiz, int dfunit,
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -705,8 +718,8 @@ static int procread(const char *path, bool mt, int rcnum, int xmsiz, int dfunit,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -728,7 +741,7 @@ static int procremove(const char *path, bool mt, int rcnum, int xmsiz, int dfuni
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -767,8 +780,8 @@ static int procremove(const char *path, bool mt, int rcnum, int xmsiz, int dfuni
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -795,7 +808,7 @@ static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -923,8 +936,8 @@ static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -945,7 +958,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -974,7 +987,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(hdb, __LINE__, "tchdbopen");
     err = true;
   }
-  if(TCUSEPTHREAD){
+  if(1){
     TCHDB *hdbdup = tchdbnew();
     if(tchdbopen(hdbdup, path, HDBOREADER)){
       eprint(hdb, __LINE__, "(validation)");
@@ -1585,7 +1598,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(hdb, __LINE__, "tchdbtranabort");
     err = true;
   }
-  iprintf("checking consistency:\n");
+  iprintf("checking consistency: %d %d\n", (int)tchdbrnum(hdb), (int)  ornum);
   if(tchdbrnum(hdb) != ornum || tchdbfsiz(hdb) != ofsiz || tchdbrnum(hdb) != tcmaprnum(map)){
     eprint(hdb, __LINE__, "(validation)");
     err = true;
@@ -1684,8 +1697,8 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(hdb, __LINE__, "tchdbforeach");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   if(!tchdbclose(hdb)){
@@ -1706,7 +1719,7 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCHDB *hdb = tchdbnew();
-  if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tchdbsetdbgfd(hdb, g_dbgfd);
   if(mt && !tchdbsetmutex(hdb)){
     eprint(hdb, __LINE__, "tchdbsetmutex");
     err = true;
@@ -2109,8 +2122,8 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(hdb, __LINE__, "(validation)");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
-  iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tchdbrnum(hdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tchdbfsiz(hdb));
   mprint(hdb);
   sysprint();
   tcmapdel(map);
index f857cb1..31add83 100644 (file)
@@ -206,7 +206,6 @@ int tctdbecode(TCTDB *tdb){
 /* Set mutual exclusion control of a table database object for threading. */
 bool tctdbsetmutex(TCTDB *tdb){
   assert(tdb);
-  if(!TCUSEPTHREAD) return true;
   if(tdb->mmtx || tdb->open){
     tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
     return false;
@@ -682,7 +681,7 @@ bool tctdbcopy(TCTDB *tdb, const char *path){
 /* Begin the transaction of a table database object. */
 bool tctdbtranbegin(TCTDB *tdb){
   assert(tdb);
-  for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){
+  for(double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2){
     if(!TDBLOCKMETHOD(tdb, true)) return false;
     if(!tdb->open || !tdb->wmode){
       tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -1016,7 +1015,7 @@ bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op){
     if(flags & TDBQPSTOP) break;
   }
   tclistdel(res);
-  tcxstrprintf(qry->hint, "post treatment: get=%lld, put=%lld, out=%lld\n",
+  tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
                (long long)getnum, (long long)putnum, (long long)outnum);
   TDBUNLOCKMETHOD(tdb);
   return !err;
@@ -1250,14 +1249,14 @@ void tctdbsetecode(TCTDB *tdb, int ecode, const char *filename, int line, const
 
 
 /* Set the file descriptor for debugging output. */
-void tctdbsetdbgfd(TCTDB *tdb, int fd){
-  assert(tdb && fd >= 0);
+void tctdbsetdbgfd(TCTDB *tdb, HANDLE fd){
+  assert(tdb);
   tchdbsetdbgfd(tdb->hdb, fd);
 }
 
 
 /* Get the file descriptor for debugging output. */
-int tctdbdbgfd(TCTDB *tdb){
+HANDLE tctdbdbgfd(TCTDB *tdb){
   assert(tdb);
   return tchdbdbgfd(tdb->hdb);
 }
@@ -1385,17 +1384,6 @@ uint8_t tctdbopts(TCTDB *tdb){
 }
 
 
-/* Get the pointer to the opaque field of a table database object. */
-char *tctdbopaque(TCTDB *tdb){
-  assert(tdb);
-  if(!tdb->open){
-    tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
-    return NULL;
-  }
-  return tchdbopaque(tdb->hdb) + TDBOPAQUESIZ;
-}
-
-
 /* Get the number of used elements of the bucket array of a table database object. */
 uint64_t tctdbbnumused(TCTDB *tdb){
   assert(tdb);
@@ -1686,7 +1674,7 @@ bool tctdbqryproc2(TDBQRY *qry, TDBQRYPROC proc, void *op){
     TDBUNLOCKMETHOD(tdb);
   }
   tclistdel(res);
-  tcxstrprintf(qry->hint, "post treatment: get=%lld, put=%lld, out=%lld\n",
+  tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
                (long long)getnum, (long long)putnum, (long long)outnum);
   return !err;
 }
@@ -1934,7 +1922,7 @@ static void tctdbclear(TCTDB *tdb){
    If successful, the return value is true, else, it is false. */
 static bool tctdbopenimpl(TCTDB *tdb, const char *path, int omode){
   assert(tdb && path);
-  int dbgfd = tchdbdbgfd(tdb->hdb);
+  HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
   TCCODEC enc, dec;
   void *encop, *decop;
   tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
@@ -2001,7 +1989,7 @@ static bool tctdbopenimpl(TCTDB *tdb, const char *path, int omode){
     char *name = tcurldecode(stem, &nsiz);
     if(!strcmp(ep, "lex") || !strcmp(ep, "dec") || !strcmp(ep, "tok") || !strcmp(ep, "qgr")){
       TCBDB *bdb = tcbdbnew();
-      if(dbgfd >= 0) tcbdbsetdbgfd(bdb, dbgfd);
+      if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(bdb, dbgfd);
       if(tdb->mmtx) tcbdbsetmutex(bdb);
       if(enc && dec) tcbdbsetcodecfunc(bdb, enc, encop, dec, decop);
       tcbdbsetcache(bdb, tdb->lcnum, tdb->ncnum);
@@ -2295,11 +2283,11 @@ static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow
     }
   }
   const char *path = tchdbpath(tdb->hdb);
-  char *tpath = tcsprintf("%s%ctmp%c%llu", path, MYEXTCHR, MYEXTCHR, tchdbinode(tdb->hdb));
+  char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", path, MYEXTCHR, MYEXTCHR, tchdbinode(tdb->hdb));
   TCHDB *thdb = tchdbnew();
   tchdbsettype(thdb, TCDBTTABLE);
-  int dbgfd = tchdbdbgfd(tdb->hdb);
-  if(dbgfd >= 0) tchdbsetdbgfd(thdb, dbgfd);
+  HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+  if(!INVALIDHANDLE(dbgfd)) tchdbsetdbgfd(thdb, dbgfd);
   TCCODEC enc, dec;
   void *encop, *decop;
   tchdbcodecfunc(hdb, &enc, &encop, &dec, &decop);
@@ -2315,8 +2303,7 @@ static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow
   if(opts & TDBTTCBS) hopts |= HDBTTCBS;
   if(opts & TDBTEXCODEC) hopts |= HDBTEXCODEC;
   tchdbtune(thdb, bnum, apow, fpow, hopts);
-  if(tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
-    memcpy(tchdbopaque(thdb), tchdbopaque(hdb), TDBOPAQUESIZ + TDBLEFTOPQSIZ);
+  if(tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC) && tchdbcopyopaque(thdb, hdb, 0, -1)) {
     if(!tchdbiterinit(hdb)) err = true;
     TCXSTR *kxstr = tcxstrnew();
     TCXSTR *vxstr = tcxstrnew();
@@ -2337,17 +2324,17 @@ static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow
       err = true;
     }
     if(!err){
-      if(unlink(path) == -1){
+      char *npath = tcstrdup(path);
+      int omode = (tchdbomode(hdb) & ~HDBOCREAT) & ~HDBOTRUNC;
+      if(!tchdbclose(hdb)) err = true;
+      if(unlink(npath)){
         tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
         err = true;
       }
-      if(rename(tpath, path) == -1){
+      if(rename(tpath, npath)){
         tctdbsetecode(tdb, TCERENAME, __FILE__, __LINE__, __func__);
         err = true;
       }
-      char *npath = tcstrdup(path);
-      int omode = (tchdbomode(hdb) & ~HDBOCREAT) & ~HDBOTRUNC;
-      if(!tchdbclose(hdb)) err = true;
       if(!tchdbopen(hdb, npath, omode)) err = true;
       TCFREE(npath);
     }
@@ -2634,7 +2621,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
   int inum = tdb->inum;
   for(int i = 0; i < inum; i++){
     TDBIDX *idx = idxs + i;
-    const char *path;
+    char *path;
     if(!strcmp(idx->name, name)){
       if(keep){
         tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
@@ -2672,12 +2659,13 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
         case TDBITDECIMAL:
         case TDBITTOKEN:
         case TDBITQGRAM:
-          path = tcbdbpath(idx->db);
+          path = tcstrdup(tcbdbpath(idx->db));
+          tcbdbdel(idx->db);
           if(path && unlink(path)){
             tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
             err = true;
           }
-          tcbdbdel(idx->db);
+          TCFREE(path);
           break;
       }
       TCFREE(idx->name);
@@ -2704,7 +2692,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
   if(homode & HDBONOLCK) bomode |= BDBONOLCK;
   if(homode & HDBOLCKNB) bomode |= BDBOLCKNB;
   if(homode & HDBOTSYNC) bomode |= BDBOTSYNC;
-  int dbgfd = tchdbdbgfd(tdb->hdb);
+  HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
   TCCODEC enc, dec;
   void *encop, *decop;
   tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
@@ -2722,7 +2710,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
       idx->db = tcbdbnew();
       idx->name = tcstrdup(name);
       tcxstrprintf(pbuf, "%clex", MYEXTCHR);
-      if(dbgfd >= 0) tcbdbsetdbgfd(idx->db, dbgfd);
+      if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
       if(tdb->mmtx) tcbdbsetmutex(idx->db);
       if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
       tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
@@ -2740,7 +2728,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
       idx->db = tcbdbnew();
       idx->name = tcstrdup(name);
       tcxstrprintf(pbuf, "%cdec", MYEXTCHR);
-      if(dbgfd >= 0) tcbdbsetdbgfd(idx->db, dbgfd);
+      if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
       if(tdb->mmtx) tcbdbsetmutex(idx->db);
       tcbdbsetcmpfunc(idx->db, tccmpdecimal, NULL);
       if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
@@ -2760,7 +2748,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
       idx->cc = tcmapnew2(TDBIDXICCBNUM);
       idx->name = tcstrdup(name);
       tcxstrprintf(pbuf, "%ctok", MYEXTCHR);
-      if(dbgfd >= 0) tcbdbsetdbgfd(idx->db, dbgfd);
+      if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
       if(tdb->mmtx) tcbdbsetmutex(idx->db);
       if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
       tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
@@ -2779,7 +2767,7 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
       idx->cc = tcmapnew2(TDBIDXICCBNUM);
       idx->name = tcstrdup(name);
       tcxstrprintf(pbuf, "%cqgr", MYEXTCHR);
-      if(dbgfd >= 0) tcbdbsetdbgfd(idx->db, dbgfd);
+      if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
       if(tdb->mmtx) tcbdbsetmutex(idx->db);
       if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
       tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
@@ -2861,17 +2849,16 @@ static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOAD
    The return value is the new unique ID number or -1 on failure. */
 static int64_t tctdbgenuidimpl(TCTDB *tdb, int64_t inc){
   assert(tdb);
-  void *opq = tchdbopaque(tdb->hdb);
   uint64_t llnum, uid;
   if(inc < 0){
     uid = -inc - 1;
   } else {
-    memcpy(&llnum, opq, sizeof(llnum));
+    tchdbreadopaque(tdb->hdb, &llnum, 0, sizeof(llnum));
     if(inc == 0) return TCITOHLL(llnum);
     uid = TCITOHLL(llnum) + inc;
   }
   llnum = TCITOHLL(uid);
-  memcpy(opq, &llnum, sizeof(llnum));
+  tchdbwriteopaque(tdb->hdb, &llnum, 0, sizeof(llnum));
   return uid;
 }
 
@@ -4052,7 +4039,7 @@ static TCMAP *tctdbqryidxfetch(TDBQRY *qry, TDBCOND *cond, TDBIDX *idx){
     tcmapdel(nmap);
     nmap = tctdbidxgetbyfts(tdb, idx, cond, hint);
   }
-  tcxstrprintf(hint, "auxiliary result set size: %lld\n", (long long)TCMAPRNUM(nmap));
+  tcxstrprintf(hint, "auxiliary result set size: %" PRIdMAX "\n", (long long)TCMAPRNUM(nmap));
   return nmap;
 }
 
@@ -4793,7 +4780,6 @@ bool tctdbidxput2(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
   return !err;
 }
 
-
 /* Add a column of a record into an index of a table database object.
    `tdb' specifies the table database object.
    `idx' specifies the index object.
@@ -5651,7 +5637,7 @@ TCMAP *tctdbidxgetbytokens(TCTDB *tdb, const TDBIDX *idx, const TCLIST *tokens,
           int step;
           TCREADVNUMBUF64(cbuf, tid, step);
           char pkbuf[TCNUMBUFSIZ];
-          int pksiz = sprintf(pkbuf, "%lld", (long long)tid);
+          int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)tid);
           if(cnt < 1){
             tcmapput(res, pkbuf, pksiz, "", 0);
           } else if(wring){
@@ -5691,7 +5677,7 @@ TCMAP *tctdbidxgetbytokens(TCTDB *tdb, const TDBIDX *idx, const TCLIST *tokens,
           int step;
           TCREADVNUMBUF64(cbuf, tid, step);
           char pkbuf[TCNUMBUFSIZ];
-          int pksiz = sprintf(pkbuf, "%lld", (long long)tid);
+          int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)tid);
           if(cnt < 1){
             tcmapput(res, pkbuf, pksiz, "", 0);
           } else if(wring){
@@ -6103,7 +6089,7 @@ static void tctdbidxgetbyftsunion(TDBIDX *idx, const TCLIST *tokens, bool sign,
         if(off == ocr->off + rem){
           onum++;
           char pkbuf[TCNUMBUFSIZ];
-          int pksiz = sprintf(pkbuf, "%lld", (long long)pkid);
+          int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)pkid);
           if(ores){
             int rsiz;
             if(tcmapget(ores, pkbuf, pksiz, &rsiz)){
@@ -6175,7 +6161,7 @@ static void tctdbidxgetbyftsunion(TDBIDX *idx, const TCLIST *tokens, bool sign,
               if(uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
             } else {
               char numbuf[TCNUMBUFSIZ];
-              int pksiz = sprintf(numbuf, "%lld", (long long)pkid);
+              int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)pkid);
               if(ores){
                 int rsiz;
                 if(tcmapget(ores, numbuf, pksiz, &rsiz)){
@@ -6244,7 +6230,7 @@ static void tctdbidxgetbyftsunion(TDBIDX *idx, const TCLIST *tokens, bool sign,
               if(uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
             } else {
               char numbuf[TCNUMBUFSIZ];
-              int pksiz = sprintf(numbuf, "%lld", (long long)pkid);
+              int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)pkid);
               if(ores){
                 int rsiz;
                 if(tcmapget(ores, numbuf, pksiz, &rsiz)){
@@ -6541,9 +6527,10 @@ static bool tctdbunlockmethod(TCTDB *tdb){
    `tdb' specifies the table database object. */
 void tctdbprintmeta(TCTDB *tdb){
   assert(tdb);
-  int dbgfd = tchdbdbgfd(tdb->hdb);
-  if(dbgfd < 0) return;
-  if(dbgfd == UINT16_MAX) dbgfd = 1;
+  HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+  if(!INVALIDHANDLE(dbgfd)) {
+         dbgfd = GET_STDOUT_HANDLE();
+  }
   char buf[TDBPAGEBUFSIZ];
   char *wp = buf;
   wp += sprintf(wp, "META:");
@@ -6554,7 +6541,7 @@ void tctdbprintmeta(TCTDB *tdb){
   wp += sprintf(wp, " opts=%u", tdb->opts);
   wp += sprintf(wp, " lcnum=%d", tdb->lcnum);
   wp += sprintf(wp, " ncnum=%d", tdb->ncnum);
-  wp += sprintf(wp, " iccmax=%lld", (long long)tdb->iccmax);
+  wp += sprintf(wp, " iccmax=%" PRIdMAX "", (long long)tdb->iccmax);
   wp += sprintf(wp, " iccsync=%f", tdb->iccsync);
   wp += sprintf(wp, " idxs=%p", (void *)tdb->idxs);
   wp += sprintf(wp, " inum=%d", tdb->inum);
index be6f68f..f9878e6 100644 (file)
@@ -193,19 +193,19 @@ typedef char* (*TDBRVALOADER)(TCLIST *tokens,
 /* Get the message string corresponding to an error code.
    `ecode' specifies the error code.
    The return value is the message string of the error code. */
-const char *tctdberrmsg(int ecode);
+EJDB_EXPORT const char *tctdberrmsg(int ecode);
 
 
 /* Create a table database object.
    The return value is the new table database object. */
-TCTDB *tctdbnew(void);
+EJDB_EXPORT TCTDB *tctdbnew(void);
 
 
 /* Delete a table database object.
    `tdb' specifies the table database object.
    If the database is not closed, it is closed implicitly.  Note that the deleted object and its
    derivatives can not be used anymore. */
-void tctdbdel(TCTDB *tdb);
+EJDB_EXPORT void tctdbdel(TCTDB *tdb);
 
 
 /* Get the last happened error code of a table database object.
@@ -220,7 +220,7 @@ void tctdbdel(TCTDB *tdb);
    for unlink error, `TCERENAME' for rename error, `TCEMKDIR' for mkdir error, `TCERMDIR' for
    rmdir error, `TCEKEEP' for existing record, `TCENOREC' for no record found, and `TCEMISC' for
    miscellaneous error. */
-int tctdbecode(TCTDB *tdb);
+EJDB_EXPORT int tctdbecode(TCTDB *tdb);
 
 
 /* Set mutual exclusion control of a table database object for threading.
@@ -228,7 +228,7 @@ int tctdbecode(TCTDB *tdb);
    If successful, the return value is true, else, it is false.
    Note that the mutual exclusion control is needed if the object is shared by plural threads and
    this function should be called before the database is opened. */
-bool tctdbsetmutex(TCTDB *tdb);
+EJDB_EXPORT bool tctdbsetmutex(TCTDB *tdb);
 
 
 /* Set the tuning parameters of a table database object.
@@ -246,7 +246,7 @@ bool tctdbsetmutex(TCTDB *tdb);
    BZIP2 encoding, `TDBTTCBS' specifies that each record is compressed with TCBS encoding.
    If successful, the return value is true, else, it is false.
    Note that the tuning parameters should be set before the database is opened. */
-bool tctdbtune(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
+EJDB_EXPORT bool tctdbtune(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
 /* Set the caching parameters of a table database object.
@@ -260,7 +260,7 @@ bool tctdbtune(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts)
    If successful, the return value is true, else, it is false.
    Note that the caching parameters should be set before the database is opened.  Leaf nodes and
    non-leaf nodes are used in column indices. */
-bool tctdbsetcache(TCTDB *tdb, int32_t rcnum, int32_t lcnum, int32_t ncnum);
+EJDB_EXPORT bool tctdbsetcache(TCTDB *tdb, int32_t rcnum, int32_t lcnum, int32_t ncnum);
 
 
 /* Set the size of the extra mapped memory of a table database object.
@@ -269,7 +269,7 @@ bool tctdbsetcache(TCTDB *tdb, int32_t rcnum, int32_t lcnum, int32_t ncnum);
    mapped memory is disabled.  The default size is 67108864.
    If successful, the return value is true, else, it is false.
    Note that the mapping parameters should be set before the database is opened. */
-bool tctdbsetxmsiz(TCTDB *tdb, int64_t xmsiz);
+EJDB_EXPORT bool tctdbsetxmsiz(TCTDB *tdb, int64_t xmsiz);
 
 
 /* Set the unit step number of auto defragmentation of a table database object.
@@ -278,7 +278,7 @@ bool tctdbsetxmsiz(TCTDB *tdb, int64_t xmsiz);
    is disabled.  It is disabled by default.
    If successful, the return value is true, else, it is false.
    Note that the defragmentation parameters should be set before the database is opened. */
-bool tctdbsetdfunit(TCTDB *tdb, int32_t dfunit);
+EJDB_EXPORT bool tctdbsetdfunit(TCTDB *tdb, int32_t dfunit);
 
 
 /* Open a database file and connect a table database object.
@@ -292,7 +292,7 @@ bool tctdbsetdfunit(TCTDB *tdb, int32_t dfunit);
    bitwise-or: `TDBONOLCK', which means it opens the database file without file locking, or
    `TDBOLCKNB', which means locking is performed without blocking.
    If successful, the return value is true, else, it is false. */
-bool tctdbopen(TCTDB *tdb, const char *path, int omode);
+EJDB_EXPORT bool tctdbopen(TCTDB *tdb, const char *path, int omode);
 
 
 /* Close a table database object.
@@ -300,7 +300,7 @@ bool tctdbopen(TCTDB *tdb, const char *path, int omode);
    If successful, the return value is true, else, it is false.
    Update of a database is assured to be written when the database is closed.  If a writer opens
    a database but does not close it appropriately, the database will be broken. */
-bool tctdbclose(TCTDB *tdb);
+EJDB_EXPORT bool tctdbclose(TCTDB *tdb);
 
 
 /* Store a record into a table database object.
@@ -310,7 +310,7 @@ bool tctdbclose(TCTDB *tdb);
    `cols' specifies a map object containing columns.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
+EJDB_EXPORT bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
 
 
 /* Store a string record into a table database object with a zero separated column string.
@@ -322,7 +322,7 @@ bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
    `csiz' specifies the size of the region of the column string.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tctdbput2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
+EJDB_EXPORT bool tctdbput2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
 
 
 /* Store a string record into a table database object with a tab separated column string.
@@ -332,7 +332,7 @@ bool tctdbput2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int c
    value of each column are situated one after the other.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, it is overwritten. */
-bool tctdbput3(TCTDB *tdb, const char *pkstr, const char *cstr);
+EJDB_EXPORT bool tctdbput3(TCTDB *tdb, const char *pkstr, const char *cstr);
 
 
 /* Store a new record into a table database object.
@@ -342,7 +342,7 @@ bool tctdbput3(TCTDB *tdb, const char *pkstr, const char *cstr);
    `cols' specifies a map object containing columns.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tctdbputkeep(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
+EJDB_EXPORT bool tctdbputkeep(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
 
 
 /* Store a new string record into a table database object with a zero separated column string.
@@ -354,7 +354,7 @@ bool tctdbputkeep(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
    `csiz' specifies the size of the region of the column string.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tctdbputkeep2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
+EJDB_EXPORT bool tctdbputkeep2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
 
 
 /* Store a new string record into a table database object with a tab separated column string.
@@ -364,7 +364,7 @@ bool tctdbputkeep2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, i
    value of each column are situated one after the other.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tctdbputkeep3(TCTDB *tdb, const char *pkstr, const char *cstr);
+EJDB_EXPORT bool tctdbputkeep3(TCTDB *tdb, const char *pkstr, const char *cstr);
 
 
 /* Concatenate columns of the existing record in a table database object.
@@ -374,7 +374,7 @@ bool tctdbputkeep3(TCTDB *tdb, const char *pkstr, const char *cstr);
    `cols' specifies a map object containing columns.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tctdbputcat(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
+EJDB_EXPORT bool tctdbputcat(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
 
 
 /* Concatenate columns in a table database object with a zero separated column string.
@@ -386,7 +386,7 @@ bool tctdbputcat(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);
    `csiz' specifies the size of the region of the column string.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tctdbputcat2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
+EJDB_EXPORT bool tctdbputcat2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz);
 
 
 /* Concatenate columns in a table database object with with a tab separated column string.
@@ -396,7 +396,7 @@ bool tctdbputcat2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, in
    value of each column are situated one after the other.
    If successful, the return value is true, else, it is false.
    If there is no corresponding record, a new record is created. */
-bool tctdbputcat3(TCTDB *tdb, const char *pkstr, const char *cstr);
+EJDB_EXPORT bool tctdbputcat3(TCTDB *tdb, const char *pkstr, const char *cstr);
 
 
 /* Remove a record of a table database object.
@@ -404,14 +404,14 @@ bool tctdbputcat3(TCTDB *tdb, const char *pkstr, const char *cstr);
    `pkbuf' specifies the pointer to the region of the primary key.
    `pksiz' specifies the size of the region of the primary key.
    If successful, the return value is true, else, it is false. */
-bool tctdbout(TCTDB *tdb, const void *pkbuf, int pksiz);
+EJDB_EXPORT bool tctdbout(TCTDB *tdb, const void *pkbuf, int pksiz);
 
 
 /* Remove a string record of a table database object.
    `tdb' specifies the table database object connected as a writer.
    `pkstr' specifies the string of the primary key.
    If successful, the return value is true, else, it is false. */
-bool tctdbout2(TCTDB *tdb, const char *pkstr);
+EJDB_EXPORT bool tctdbout2(TCTDB *tdb, const char *pkstr);
 
 
 /* Retrieve a record in a table database object.
@@ -422,7 +422,7 @@ bool tctdbout2(TCTDB *tdb, const char *pkstr);
    `NULL' is returned if no record corresponds.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz);
+EJDB_EXPORT TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz);
 
 
 /* Retrieve a record in a table database object as a zero separated column string.
@@ -437,7 +437,7 @@ TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tctdbget2(TCTDB *tdb, const void *pkbuf, int pksiz, int *sp);
+EJDB_EXPORT char *tctdbget2(TCTDB *tdb, const void *pkbuf, int pksiz, int *sp);
 
 
 /* Retrieve a string record in a table database object as a tab separated column string.
@@ -447,7 +447,7 @@ char *tctdbget2(TCTDB *tdb, const void *pkbuf, int pksiz, int *sp);
    record.  `NULL' is returned if no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tctdbget3(TCTDB *tdb, const char *pkstr);
+EJDB_EXPORT char *tctdbget3(TCTDB *tdb, const char *pkstr);
 
 
 /* Get the size of the value of a record in a table database object.
@@ -456,7 +456,7 @@ char *tctdbget3(TCTDB *tdb, const char *pkstr);
    `ksiz' specifies the size of the region of the primary key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tctdbvsiz(TCTDB *tdb, const void *pkbuf, int pksiz);
+EJDB_EXPORT int tctdbvsiz(TCTDB *tdb, const void *pkbuf, int pksiz);
 
 
 /* Get the size of the value of a string record in a table database object.
@@ -464,7 +464,7 @@ int tctdbvsiz(TCTDB *tdb, const void *pkbuf, int pksiz);
    `kstr' specifies the string of the primary key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tctdbvsiz2(TCTDB *tdb, const char *pkstr);
+EJDB_EXPORT int tctdbvsiz2(TCTDB *tdb, const char *pkstr);
 
 
 /* Initialize the iterator of a table database object.
@@ -472,7 +472,7 @@ int tctdbvsiz2(TCTDB *tdb, const char *pkstr);
    If successful, the return value is true, else, it is false.
    The iterator is used in order to access the primary key of every record stored in a
    database. */
-bool tctdbiterinit(TCTDB *tdb);
+EJDB_EXPORT bool tctdbiterinit(TCTDB *tdb);
 
 
 /* Get the next primary key of the iterator of a table database object.
@@ -489,7 +489,7 @@ bool tctdbiterinit(TCTDB *tdb);
    However, it is not assured if updating the database is occurred while the iteration.  Besides,
    the order of this traversal access method is arbitrary, so it is not assured that the order of
    storing matches the one of the traversal access. */
-void *tctdbiternext(TCTDB *tdb, int *sp);
+EJDB_EXPORT void *tctdbiternext(TCTDB *tdb, int *sp);
 
 
 /* Get the next primary key string of the iterator of a table database object.
@@ -502,7 +502,7 @@ void *tctdbiternext(TCTDB *tdb, int *sp);
    database is occurred while the iteration.  Besides, the order of this traversal access method
    is arbitrary, so it is not assured that the order of storing matches the one of the traversal
    access. */
-char *tctdbiternext2(TCTDB *tdb);
+EJDB_EXPORT char *tctdbiternext2(TCTDB *tdb);
 
 
 /* Get the columns of the next record of the iterator of a table database object.
@@ -516,7 +516,7 @@ char *tctdbiternext2(TCTDB *tdb);
    the database is occurred while the iteration.  Besides, the order of this traversal access
    method is arbitrary, so it is not assured that the order of storing matches the one of the
    traversal access. */
-TCMAP *tctdbiternext3(TCTDB *tdb);
+EJDB_EXPORT TCMAP *tctdbiternext3(TCTDB *tdb);
 
 
 /* Get forward matching primary keys in a table database object.
@@ -530,7 +530,7 @@ TCMAP *tctdbiternext3(TCTDB *tdb);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tctdbfwmkeys(TCTDB *tdb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tctdbfwmkeys(TCTDB *tdb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string primary keys in a table database object.
@@ -543,7 +543,7 @@ TCLIST *tctdbfwmkeys(TCTDB *tdb, const void *pbuf, int psiz, int max);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tctdbfwmkeys2(TCTDB *tdb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tctdbfwmkeys2(TCTDB *tdb, const char *pstr, int max);
 
 
 /* Add an integer to a column of a record in a table database object.
@@ -554,7 +554,7 @@ TCLIST *tctdbfwmkeys2(TCTDB *tdb, const char *pstr, int max);
    If successful, the return value is the summation value, else, it is `INT_MIN'.
    The additional value is stored as a decimal string value of a column whose name is "_num".
    If no record corresponds, a new record with the additional value is stored. */
-int tctdbaddint(TCTDB *tdb, const void *pkbuf, int pksiz, int num);
+EJDB_EXPORT int tctdbaddint(TCTDB *tdb, const void *pkbuf, int pksiz, int num);
 
 
 /* Add a real number to a column of a record in a table database object.
@@ -565,14 +565,14 @@ int tctdbaddint(TCTDB *tdb, const void *pkbuf, int pksiz, int num);
    If successful, the return value is the summation value, else, it is Not-a-Number.
    The additional value is stored as a decimal string value of a column whose name is "_num".
    If no record corresponds, a new record with the additional value is stored. */
-double tctdbadddouble(TCTDB *tdb, const void *pkbuf, int pksiz, double num);
+EJDB_EXPORT double tctdbadddouble(TCTDB *tdb, const void *pkbuf, int pksiz, double num);
 
 
 /* Synchronize updated contents of a table database object with the file and the device.
    `tdb' specifies the table database object connected as a writer.
    If successful, the return value is true, else, it is false.
    This function is useful when another process connects to the same database file. */
-bool tctdbsync(TCTDB *tdb);
+EJDB_EXPORT bool tctdbsync(TCTDB *tdb);
 
 
 /* Optimize the file of a table database object.
@@ -591,13 +591,13 @@ bool tctdbsync(TCTDB *tdb);
    If successful, the return value is true, else, it is false.
    This function is useful to reduce the size of the database file with data fragmentation by
    successive updating. */
-bool tctdboptimize(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
+EJDB_EXPORT bool tctdboptimize(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
 
 
 /* Remove all records of a table database object.
    `tdb' specifies the table database object connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tctdbvanish(TCTDB *tdb);
+EJDB_EXPORT bool tctdbvanish(TCTDB *tdb);
 
 
 /* Copy the database file of a table database object.
@@ -609,7 +609,7 @@ bool tctdbvanish(TCTDB *tdb);
    The database file is assured to be kept synchronized and not modified while the copying or
    executing operation is in progress.  So, this function is useful to create a backup file of
    the database file. */
-bool tctdbcopy(TCTDB *tdb, const char *path);
+EJDB_EXPORT bool tctdbcopy(TCTDB *tdb, const char *path);
 
 
 /* Begin the transaction of a table database object.
@@ -621,14 +621,14 @@ bool tctdbcopy(TCTDB *tdb, const char *path);
    cached on memory while the transaction, the amount of referred records is limited by the
    memory capacity.  If the database is closed during transaction, the transaction is aborted
    implicitly. */
-bool tctdbtranbegin(TCTDB *tdb);
+EJDB_EXPORT bool tctdbtranbegin(TCTDB *tdb);
 
 
 /* Commit the transaction of a table database object.
    `tdb' specifies the table database object connected as a writer.
    If successful, the return value is true, else, it is false.
    Update in the transaction is fixed when it is committed successfully. */
-bool tctdbtrancommit(TCTDB *tdb);
+EJDB_EXPORT bool tctdbtrancommit(TCTDB *tdb);
 
 
 /* Abort the transaction of a table database object.
@@ -636,28 +636,28 @@ bool tctdbtrancommit(TCTDB *tdb);
    If successful, the return value is true, else, it is false.
    Update in the transaction is discarded when it is aborted.  The state of the database is
    rollbacked to before transaction. */
-bool tctdbtranabort(TCTDB *tdb);
+EJDB_EXPORT bool tctdbtranabort(TCTDB *tdb);
 
 
 /* Get the file path of a table database object.
    `tdb' specifies the table database object.
    The return value is the path of the database file or `NULL' if the object does not connect to
    any database file. */
-const char *tctdbpath(TCTDB *tdb);
+EJDB_EXPORT const char *tctdbpath(TCTDB *tdb);
 
 
 /* Get the number of records ccccof a table database object.
    `tdb' specifies the table database object.
    The return value is the number of records or 0 if the object does not connect to any database
    file. */
-uint64_t tctdbrnum(TCTDB *tdb);
+EJDB_EXPORT uint64_t tctdbrnum(TCTDB *tdb);
 
 
 /* Get the size of the database file of a table database object.
    `tdb' specifies the table database object.
    The return value is the size of the database file or 0 if the object does not connect to any
    database file. */
-uint64_t tctdbfsiz(TCTDB *tdb);
+EJDB_EXPORT uint64_t tctdbfsiz(TCTDB *tdb);
 
 
 /* Set a column index to a table database object.
@@ -670,26 +670,26 @@ uint64_t tctdbfsiz(TCTDB *tdb);
    `TDBITKEEP' is added by bitwise-or and the index exists, this function merely returns failure.
    If successful, the return value is true, else, it is false.
    Note that the setting indices should be set after the database is opened. */
-bool tctdbsetindex(TCTDB *tdb, const char *name, int type);
+EJDB_EXPORT bool tctdbsetindex(TCTDB *tdb, const char *name, int type);
 
-bool tctdbsetindexrldr(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop);
+EJDB_EXPORT bool tctdbsetindexrldr(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop);
 
 
 /* Generate a unique ID number of a table database object.
    `tdb' specifies the table database object connected as a writer.
    The return value is the new unique ID number or -1 on failure. */
-int64_t tctdbgenuid(TCTDB *tdb);
+EJDB_EXPORT int64_t tctdbgenuid(TCTDB *tdb);
 
 
 /* Create a query object.
    `tdb' specifies the table database object.
    The return value is the new query object. */
-TDBQRY *tctdbqrynew(TCTDB *tdb);
+EJDB_EXPORT TDBQRY *tctdbqrynew(TCTDB *tdb);
 
 
 /* Delete a query object.
    `qry' specifies the query object. */
-void tctdbqrydel(TDBQRY *qry);
+EJDB_EXPORT void tctdbqrydel(TDBQRY *qry);
 
 
 /* Add a narrowing condition to a query object.
@@ -712,7 +712,7 @@ void tctdbqrydel(TDBQRY *qry);
    full-text search with the compound expression.  All operations can be flagged by bitwise-or:
    `TDBQCNEGATE' for negation, `TDBQCNOIDX' for using no index.
    `expr' specifies an operand exression. */
-void tctdbqryaddcond(TDBQRY *qry, const char *name, int op, const char *expr);
+EJDB_EXPORT void tctdbqryaddcond(TDBQRY *qry, const char *name, int op, const char *expr);
 
 
 /* Set the order of a query object.
@@ -720,7 +720,7 @@ void tctdbqryaddcond(TDBQRY *qry, const char *name, int op, const char *expr);
    `name' specifies the name of a column.  An empty string means the primary key.
    `type' specifies the order type: `TDBQOSTRASC' for string ascending, `TDBQOSTRDESC' for
    string descending, `TDBQONUMASC' for number ascending, `TDBQONUMDESC' for number descending. */
-void tctdbqrysetorder(TDBQRY *qry, const char *name, int type);
+EJDB_EXPORT void tctdbqrysetorder(TDBQRY *qry, const char *name, int type);
 
 
 /* Set the limit number of records of the result of a query object.
@@ -729,7 +729,7 @@ void tctdbqrysetorder(TDBQRY *qry, const char *name, int type);
    specified.
    `skip' specifies the number of skipped records of the result.  If it is not more than 0, no
    record is skipped. */
-void tctdbqrysetlimit(TDBQRY *qry, int max, int skip);
+EJDB_EXPORT void tctdbqrysetlimit(TDBQRY *qry, int max, int skip);
 
 
 /* Execute the search of a query object.
@@ -738,13 +738,13 @@ void tctdbqrysetlimit(TDBQRY *qry, int max, int skip);
    function does never fail.  It returns an empty list even if no record corresponds.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tctdbqrysearch(TDBQRY *qry);
+EJDB_EXPORT TCLIST *tctdbqrysearch(TDBQRY *qry);
 
 
 /* Remove each record corresponding to a query object.
    `qry' specifies the query object of the database connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tctdbqrysearchout(TDBQRY *qry);
+EJDB_EXPORT bool tctdbqrysearchout(TDBQRY *qry);
 
 
 /* Process each record corresponding to a query object.
@@ -758,7 +758,7 @@ bool tctdbqrysearchout(TDBQRY *qry);
    `op' specifies an arbitrary pointer to be given as a parameter of the iterator function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op);
+EJDB_EXPORT bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op);
 
 
 /* Get the hint string of a query object.
@@ -766,7 +766,7 @@ bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op);
    The return value is the hint string.
    This function should be called after the query execution by `tctdbqrysearch' and so on.  The
    region of the return value is overwritten when this function is called again. */
-const char *tctdbqryhint(TDBQRY *qry);
+EJDB_EXPORT const char *tctdbqryhint(TDBQRY *qry);
 
 
 /* Retrieve records with multiple query objects and get the set of the result.
@@ -779,7 +779,7 @@ const char *tctdbqryhint(TDBQRY *qry);
    If the first query object has the order setting, the result array is sorted by the order.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tctdbmetasearch(TDBQRY **qrys, int num, int type);
+EJDB_EXPORT TCLIST *tctdbmetasearch(TDBQRY **qrys, int num, int type);
 
 
 
@@ -794,25 +794,25 @@ TCLIST *tctdbmetasearch(TDBQRY **qrys, int num, int type);
    `file' specifies the file name of the code.
    `line' specifies the line number of the code.
    `func' specifies the function name of the code. */
-void tctdbsetecode(TCTDB *tdb, int ecode, const char *filename, int line, const char *func);
+EJDB_EXPORT void tctdbsetecode(TCTDB *tdb, int ecode, const char *filename, int line, const char *func);
 
 
 /* Set the file descriptor for debugging output.
    `tdb' specifies the table database object.
    `fd' specifies the file descriptor for debugging output. */
-void tctdbsetdbgfd(TCTDB *tdb, int fd);
+EJDB_EXPORT void tctdbsetdbgfd(TCTDB *tdb, HANDLE fd);
 
 
 /* Get the file descriptor for debugging output.
    `tdb' specifies the table database object.
    The return value is the file descriptor for debugging output. */
-int tctdbdbgfd(TCTDB *tdb);
+EJDB_EXPORT HANDLE tctdbdbgfd(TCTDB *tdb);
 
 
 /* Check whether mutual exclusion control is set to a table database object.
    `tdb' specifies the table database object.
    If mutual exclusion control is set, it is true, else it is false. */
-bool tctdbhasmutex(TCTDB *tdb);
+EJDB_EXPORT bool tctdbhasmutex(TCTDB *tdb);
 
 
 /* Synchronize updating contents on memory of a table database object.
@@ -826,79 +826,73 @@ bool tctdbmemsync(TCTDB *tdb, bool phys);
    `tdb' specifies the table database object.
    The return value is the number of elements of the bucket array or 0 if the object does not
    connect to any database file. */
-uint64_t tctdbbnum(TCTDB *tdb);
+EJDB_EXPORT uint64_t tctdbbnum(TCTDB *tdb);
 
 
 /* Get the record alignment of a table database object.
    `tdb' specifies the table database object.
    The return value is the record alignment or 0 if the object does not connect to any database
    file. */
-uint32_t tctdbalign(TCTDB *tdb);
+EJDB_EXPORT uint32_t tctdbalign(TCTDB *tdb);
 
 
 /* Get the maximum number of the free block pool of a table database object.
    `tdb' specifies the table database object.
    The return value is the maximum number of the free block pool or 0 if the object does not
    connect to any database file. */
-uint32_t tctdbfbpmax(TCTDB *tdb);
+EJDB_EXPORT uint32_t tctdbfbpmax(TCTDB *tdb);
 
 
 /* Get the inode number of the database file of a table database object.
    `tdb' specifies the table database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-uint64_t tctdbinode(TCTDB *tdb);
+EJDB_EXPORT uint64_t tctdbinode(TCTDB *tdb);
 
 
 /* Get the modification time of the database file of a table database object.
    `tdb' specifies the table database object.
    The return value is the inode number of the database file or 0 if the object does not connect
    to any database file. */
-time_t tctdbmtime(TCTDB *tdb);
+EJDB_EXPORT time_t tctdbmtime(TCTDB *tdb);
 
 
 /* Get the additional flags of a table database object.
    `tdb' specifies the table database object.
    The return value is the additional flags. */
-uint8_t tctdbflags(TCTDB *tdb);
+EJDB_EXPORT uint8_t tctdbflags(TCTDB *tdb);
 
 
 /* Get the options of a table database object.
    `tdb' specifies the table database object.
    The return value is the options. */
-uint8_t tctdbopts(TCTDB *tdb);
-
-
-/* Get the pointer to the opaque field of a table database object.
-   `tdb' specifies the table database object.
-   The return value is the pointer to the opaque field whose size is 128 bytes. */
-char *tctdbopaque(TCTDB *tdb);
+EJDB_EXPORT uint8_t tctdbopts(TCTDB *tdb);
 
 
 /* Get the number of used elements of the bucket array of a table database object.
    `tdb' specifies the table database object.
    The return value is the number of used elements of the bucket array or 0 if the object does not
    connect to any database file. */
-uint64_t tctdbbnumused(TCTDB *tdb);
+EJDB_EXPORT uint64_t tctdbbnumused(TCTDB *tdb);
 
 
 /* Get the number of column indices of a table database object.
    `tdb' specifies the table database object.
    The return value is the number of column indices or 0 if the object does not connect to any
    database file. */
-int tctdbinum(TCTDB *tdb);
+EJDB_EXPORT int tctdbinum(TCTDB *tdb);
 
 
 /* Get the seed of unique ID unumbers of a table database object.
    `tdb' specifies the table database object.
    The return value is the seed of unique ID numbers or -1 on failure. */
-int64_t tctdbuidseed(TCTDB *tdb);
+EJDB_EXPORT int64_t tctdbuidseed(TCTDB *tdb);
 
 
 /* Set the seed of unique ID unumbers of a table database object.
    `tdb' specifies the table database object connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tctdbsetuidseed(TCTDB *tdb, int64_t seed);
+EJDB_EXPORT bool tctdbsetuidseed(TCTDB *tdb, int64_t seed);
 
 
 /* Set the parameters of the inverted cache of a table database object.
@@ -909,7 +903,7 @@ bool tctdbsetuidseed(TCTDB *tdb, int64_t seed);
    specified.  The default value is 0.01.
    If successful, the return value is true, else, it is false.
    Note that the caching parameters should be set before the database is opened. */
-bool tctdbsetinvcache(TCTDB *tdb, int64_t iccmax, double iccsync);
+EJDB_EXPORT bool tctdbsetinvcache(TCTDB *tdb, int64_t iccmax, double iccsync);
 
 
 /* Set the custom codec functions of a table database object.
@@ -928,13 +922,13 @@ bool tctdbsetinvcache(TCTDB *tdb, int64_t iccmax, double iccsync);
    If successful, the return value is true, else, it is false.
    Note that the custom codec functions should be set before the database is opened and should be
    set every time the database is being opened. */
-bool tctdbsetcodecfunc(TCTDB *tdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
+EJDB_EXPORT bool tctdbsetcodecfunc(TCTDB *tdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop);
 
 
 /* Get the unit step number of auto defragmentation of a table database object.
    `tdb' specifies the table database object.
    The return value is the unit step number of auto defragmentation. */
-uint32_t tctdbdfunit(TCTDB *tdb);
+EJDB_EXPORT uint32_t tctdbdfunit(TCTDB *tdb);
 
 
 /* Perform dynamic defragmentation of a table database object.
@@ -942,13 +936,13 @@ uint32_t tctdbdfunit(TCTDB *tdb);
    `step' specifie the number of steps.  If it is not more than 0, the whole file is defragmented
    gradually without keeping a continuous lock.
    If successful, the return value is true, else, it is false. */
-bool tctdbdefrag(TCTDB *tdb, int64_t step);
+EJDB_EXPORT bool tctdbdefrag(TCTDB *tdb, int64_t step);
 
 
 /* Clear the cache of a table tree database object.
    `tdb' specifies the table tree database object.
    If successful, the return value is true, else, it is false. */
-bool tctdbcacheclear(TCTDB *tdb);
+EJDB_EXPORT bool tctdbcacheclear(TCTDB *tdb);
 
 
 /* Store a record into a table database object with a duplication handler.
@@ -971,7 +965,7 @@ bool tctdbcacheclear(TCTDB *tdb);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tctdbputproc(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz,
+EJDB_EXPORT bool tctdbputproc(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz,
         TCPDPROC proc, void *op);
 
 
@@ -989,7 +983,7 @@ bool tctdbputproc(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, in
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tctdbget4(TCTDB *tdb, const void *pkbuf, int pksiz, const void *nbuf, int nsiz, int *sp);
+EJDB_EXPORT char *tctdbget4(TCTDB *tdb, const void *pkbuf, int pksiz, const void *nbuf, int nsiz, int *sp);
 
 
 /* Move the iterator to the record corresponding a key of a table database object.
@@ -998,7 +992,7 @@ char *tctdbget4(TCTDB *tdb, const void *pkbuf, int pksiz, const void *nbuf, int
    `pksiz' specifies the size of the region of the primary key.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record corresponding the condition. */
-bool tctdbiterinit2(TCTDB *tdb, const void *pkbuf, int pksiz);
+EJDB_EXPORT bool tctdbiterinit2(TCTDB *tdb, const void *pkbuf, int pksiz);
 
 
 /* Move the iterator to the record corresponding a key string of a table database object.
@@ -1006,7 +1000,7 @@ bool tctdbiterinit2(TCTDB *tdb, const void *pkbuf, int pksiz);
    `kstr' specifies the string of the primary key.
    If successful, the return value is true, else, it is false.  False is returned if there is
    no record corresponding the condition. */
-bool tctdbiterinit3(TCTDB *tdb, const char *kstr);
+EJDB_EXPORT bool tctdbiterinit3(TCTDB *tdb, const char *kstr);
 
 
 /* Process each record atomically of a table database object.
@@ -1022,7 +1016,7 @@ bool tctdbiterinit3(TCTDB *tdb, const char *kstr);
    If successful, the return value is true, else, it is false.
    Note that the callback function can not perform any database operation because the function
    is called in the critical section guarded by the same locks of database operations. */
-bool tctdbforeach(TCTDB *tdb, TCITER iter, void *op);
+EJDB_EXPORT bool tctdbforeach(TCTDB *tdb, TCITER iter, void *op);
 
 
 /* Process each record corresponding to a query object with non-atomic fashion.
@@ -1036,31 +1030,31 @@ bool tctdbforeach(TCTDB *tdb, TCITER iter, void *op);
    `op' specifies an arbitrary pointer to be given as a parameter of the iterator function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tctdbqryproc2(TDBQRY *qry, TDBQRYPROC proc, void *op);
+EJDB_EXPORT bool tctdbqryproc2(TDBQRY *qry, TDBQRYPROC proc, void *op);
 
 
 /* Remove each record corresponding to a query object with non-atomic fashion.
    `qry' specifies the query object of the database connected as a writer.
    If successful, the return value is true, else, it is false. */
-bool tctdbqrysearchout2(TDBQRY *qry);
+EJDB_EXPORT bool tctdbqrysearchout2(TDBQRY *qry);
 
 
 /* Convert a string into the index type number.
    `str' specifies a string.
    The return value is the index type number or -1 on failure. */
-int tctdbstrtoindextype(const char *str);
+EJDB_EXPORT int tctdbstrtoindextype(const char *str);
 
 
 /* Convert a string into the meta search type number.
    `str' specifies a string.
    The return value is the meta search type number or -1 on failure. */
-int tctdbstrtometasearcytype(const char *str);
+EJDB_EXPORT int tctdbstrtometasearcytype(const char *str);
 
 
 /* Get the count of corresponding records of a query object.
    `qry' specifies the query object.
    The return value is the count of corresponding records. */
-int tctdbqrycount(TDBQRY *qry);
+EJDB_EXPORT int tctdbqrycount(TDBQRY *qry);
 
 
 /* Generate keyword-in-context strings from a query object.
@@ -1077,25 +1071,25 @@ int tctdbqrycount(TDBQRY *qry);
    The return value is the list object whose elements are strings around keywords.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tctdbqrykwic(TDBQRY *qry, TCMAP *cols, const char *name, int width, int opts);
+EJDB_EXPORT TCLIST *tctdbqrykwic(TDBQRY *qry, TCMAP *cols, const char *name, int width, int opts);
 
 
 /* Convert a string into the query operation number.
    `str' specifies a string.
    The return value is the query operation number or -1 on failure. */
-int tctdbqrystrtocondop(const char *str);
+EJDB_EXPORT int tctdbqrystrtocondop(const char *str);
 
 
 /* Convert a string into the query order type number.
    `str' specifies a string.
    The return value is the query order type or -1 on failure. */
-int tctdbqrystrtoordertype(const char *str);
+EJDB_EXPORT int tctdbqrystrtoordertype(const char *str);
 
 
 /* Convert a string into the set operation type number.
    `str' specifies a string.
    The return value is the set operation type or -1 on failure. */
-int tctdbmetastrtosettype(const char *str);
+EJDB_EXPORT int tctdbmetastrtosettype(const char *str);
 
 
 /* Add a record into indices of a table database object.
@@ -1162,7 +1156,9 @@ int tdbcmppkeynumdesc(const TCLISTDATUM *a, const TCLISTDATUM *b);
 TCMAP *tctdbidxgetbytokens(TCTDB *tdb, const TDBIDX *idx, const TCLIST *tokens, int op, TCXSTR *hint);
 
 bool tctdbtranbeginimpl(TCTDB *tdb);
+
 bool tctdbtrancommitimpl(TCTDB *tdb);
+
 bool tctdbtranabortimpl(TCTDB *tdb);
 
 #define TDBDEFBNUM     131071            // default bucket number
index bd7b622..cf0fc05 100644 (file)
@@ -21,7 +21,7 @@
 
 /* global variables */
 const char *g_progname;                  // program name
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -61,9 +61,16 @@ static int procversion(void);
 /* main routine */
 int main(int argc, char **argv){
   g_progname = argv[0];
-  g_dbgfd = -1;
+  g_dbgfd = INVALID_HANDLE_VALUE;
   const char *ebuf = getenv("TCDBGFD");
-  if(ebuf) g_dbgfd = tcatoix(ebuf);
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "create")){
@@ -633,7 +640,7 @@ static int runversion(int argc, char **argv){
 /* perform create command */
 static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbtune(tdb, bnum, apow, fpow, opts)){
     printerr(tdb);
@@ -658,7 +665,7 @@ static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
 /* perform inform command */
 static int procinform(const char *path, int omode){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL);
   if(!tctdbopen(tdb, path, TDBOREADER | omode)){
     printerr(tdb);
@@ -675,9 +682,9 @@ static int procinform(const char *path, int omode){
   if(flags & TDBFOPEN) printf(" open");
   if(flags & TDBFFATAL) printf(" fatal");
   printf("\n");
-  printf("bucket number: %llu\n", (unsigned long long)tctdbbnum(tdb));
+  printf("bucket number: %" PRIuMAX "\n", (unsigned long long)tctdbbnum(tdb));
   if(tdb->hdb->cnt_writerec >= 0)
-    printf("used bucket number: %lld\n", (long long)tctdbbnumused(tdb));
+    printf("used bucket number: %" PRIdMAX "\n", (long long)tctdbbnumused(tdb));
   printf("alignment: %u\n", tctdbalign(tdb));
   printf("free block pool: %u\n", tctdbfbpmax(tdb));
   printf("index number: %d\n", tctdbinum(tdb));
@@ -687,25 +694,25 @@ static int procinform(const char *path, int omode){
     TDBIDX *idxp = idxs + i;
     switch(idxp->type){
       case TDBITLEXICAL:
-        printf("  name=%s, type=lexical, rnum=%lld, fsiz=%lld\n",
+        printf("  name=%s, type=lexical, rnum=%" PRIdMAX ", fsiz=%" PRIdMAX "\n",
                idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db));
         break;
       case TDBITDECIMAL:
-        printf("  name=%s, type=decimal, rnum=%lld, fsiz=%lld\n",
+        printf("  name=%s, type=decimal, rnum=%" PRIdMAX ", fsiz=%" PRIdMAX "\n",
                idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db));
         break;
       case TDBITTOKEN:
-        printf("  name=%s, type=token, rnum=%lld, fsiz=%lld\n",
+        printf("  name=%s, type=token, rnum=%" PRIdMAX ", fsiz=%" PRIdMAX "\n",
                idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db));
         break;
       case TDBITQGRAM:
-        printf("  name=%s, type=qgram, rnum=%lld, fsiz=%lld\n",
+        printf("  name=%s, type=qgram, rnum=%" PRIdMAX ", fsiz=%" PRIdMAX "\n",
                idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db));
         break;
     }
   }
-  printf("unique ID seed: %lld\n", (long long)tctdbuidseed(tdb));
-  printf("inode number: %lld\n", (long long)tctdbinode(tdb));
+  printf("unique ID seed: %" PRIdMAX "\n", (long long)tctdbuidseed(tdb));
+  printf("inode number: %" PRIdMAX "\n", (long long)tctdbinode(tdb));
   char date[48];
   tcdatestrwww(tctdbmtime(tdb), INT_MAX, date);
   printf("modified time: %s\n", date);
@@ -717,8 +724,8 @@ static int procinform(const char *path, int omode){
   if(opts & TDBTTCBS) printf(" tcbs");
   if(opts & TDBTEXCODEC) printf(" excodec");
   printf("\n");
-  printf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  printf("file size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  printf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  printf("file size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   if(!tctdbclose(tdb)){
     if(!err) printerr(tdb);
     err = true;
@@ -732,7 +739,7 @@ static int procinform(const char *path, int omode){
 static int procput(const char *path, const char *pkbuf, int pksiz, TCMAP *cols,
                    int omode, int dmode){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbopen(tdb, path, TDBOWRITER | omode)){
     printerr(tdb);
@@ -742,7 +749,7 @@ static int procput(const char *path, const char *pkbuf, int pksiz, TCMAP *cols,
   bool err = false;
   char pknumbuf[TCNUMBUFSIZ];
   if(pksiz < 1){
-    pksiz = sprintf(pknumbuf, "%lld", (long long)tctdbgenuid(tdb));
+    pksiz = sprintf(pknumbuf, "%" PRIdMAX "", (long long)tctdbgenuid(tdb));
     pkbuf = pknumbuf;
   }
   const char *vbuf;
@@ -794,7 +801,7 @@ static int procput(const char *path, const char *pkbuf, int pksiz, TCMAP *cols,
 /* perform out command */
 static int procout(const char *path, const char *pkbuf, int pksiz, int omode){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbopen(tdb, path, TDBOWRITER | omode)){
     printerr(tdb);
@@ -818,7 +825,7 @@ static int procout(const char *path, const char *pkbuf, int pksiz, int omode){
 /* perform get command */
 static int procget(const char *path, const char *pkbuf, int pksiz, int omode, bool px, bool pz){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbopen(tdb, path, TDBOREADER | omode)){
     printerr(tdb);
@@ -856,7 +863,7 @@ static int procget(const char *path, const char *pkbuf, int pksiz, int omode, bo
 /* perform list command */
 static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbopen(tdb, path, TDBOREADER | omode)){
     printerr(tdb);
@@ -936,7 +943,7 @@ static int procsearch(const char *path, TCLIST *conds, const char *oname, const
                       int omode, int max, int skip, bool pv, bool px, bool kw, bool ph, int bt,
                       bool rm, const char *mtype){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   if(!tctdbopen(tdb, path, (rm ? TDBOWRITER : TDBOREADER) | omode)){
     printerr(tdb);
@@ -1098,7 +1105,7 @@ static int procsearch(const char *path, TCLIST *conds, const char *oname, const
 static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode,
                         bool df){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   int64_t msiz = 0;
   TCMAP *info = tcsysinfo();
@@ -1136,7 +1143,7 @@ static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts
 /* perform setindex command */
 static int procsetindex(const char *path, const char *name, int omode, int type){
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   int64_t msiz = 0;
   TCMAP *info = tcsysinfo();
@@ -1172,7 +1179,7 @@ static int procimporttsv(const char *path, const char *file, int omode, bool sc)
     return 1;
   }
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb);
   int64_t msiz = 0;
   TCMAP *info = tcsysinfo();
@@ -1200,7 +1207,7 @@ static int procimporttsv(const char *path, const char *file, int omode, bool sc)
     if(sc) tcstrutfnorm(line, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
     const char *pkey;
     if(*line == '\0'){
-      sprintf(numbuf, "%lld", (long long)tctdbgenuid(tdb));
+      sprintf(numbuf, "%" PRIdMAX "", (long long)tctdbgenuid(tdb));
       pkey = numbuf;
     } else {
       pkey = line;
index 4c9d351..b9e8162 100644 (file)
@@ -58,7 +58,7 @@ typedef struct {                         // type of structure for typical thread
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -100,7 +100,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -544,7 +551,7 @@ static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, i
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -628,8 +635,8 @@ static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, i
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -651,7 +658,7 @@ static int procread(const char *path, int tnum, int rcnum, int lcnum, int ncnum,
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -708,8 +715,8 @@ static int procread(const char *path, int tnum, int rcnum, int lcnum, int ncnum,
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -731,7 +738,7 @@ static int procremove(const char *path, int tnum, int rcnum, int lcnum, int ncnu
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -788,8 +795,8 @@ static int procremove(const char *path, int tnum, int rcnum, int lcnum, int ncnu
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -809,7 +816,7 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode)
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -899,8 +906,8 @@ static int procwicked(const char *path, int tnum, int rnum, int opts, int omode)
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -925,7 +932,7 @@ static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow,
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(!tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -1009,8 +1016,8 @@ static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow,
       }
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
index 7feed4a..3cb43a6 100644 (file)
@@ -24,7 +24,7 @@
 /* global variables */
 const char *g_progname;                  // program name
 unsigned int g_randseed;                 // random seed
-int g_dbgfd;                             // debugging output
+HANDLE g_dbgfd;                          // debugging output
 
 
 /* function prototypes */
@@ -64,7 +64,14 @@ int main(int argc, char **argv){
   g_randseed = ebuf ? tcatoix(ebuf) : tctime() * 1000;
   srand(g_randseed);
   ebuf = getenv("TCDBGFD");
-  g_dbgfd = ebuf ? tcatoix(ebuf) : UINT16_MAX;
+  if (ebuf) {
+         int debugfd = tcatoix(ebuf);
+#ifdef _WIN32
+         g_dbgfd = (HANDLE) _get_osfhandle(debugfd);
+#else
+         g_dbgfd = debugfd;
+#endif
+  }
   if(argc < 2) usage();
   int rv = 0;
   if(!strcmp(argv[1], "write")){
@@ -592,7 +599,7 @@ static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -686,8 +693,8 @@ static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -709,7 +716,7 @@ static int procread(const char *path, bool mt, int rcnum, int lcnum, int ncnum,
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -751,8 +758,8 @@ static int procread(const char *path, bool mt, int rcnum, int lcnum, int ncnum,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -774,7 +781,7 @@ static int procremove(const char *path, bool mt, int rcnum, int lcnum, int ncnum
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -813,8 +820,8 @@ static int procremove(const char *path, bool mt, int rcnum, int lcnum, int ncnum
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -841,7 +848,7 @@ static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -1021,8 +1028,8 @@ static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
     }
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -1042,7 +1049,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -1099,7 +1106,7 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(tdb, __LINE__, "tctdbsetindex");
     err = true;
   }
-  if(TCUSEPTHREAD){
+  if(1){
     TCTDB *tdbdup = tctdbnew();
     if(tctdbopen(tdbdup, path, TDBOREADER)){
       eprint(tdb, __LINE__, "(validation)");
@@ -1630,8 +1637,8 @@ static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(tdb, __LINE__, "tctdbforeach");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
@@ -1651,7 +1658,7 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
   bool err = false;
   double stime = tctime();
   TCTDB *tdb = tctdbnew();
-  if(g_dbgfd >= 0) tctdbsetdbgfd(tdb, g_dbgfd);
+  if(!INVALIDHANDLE(g_dbgfd)) tctdbsetdbgfd(tdb, g_dbgfd);
   if(mt && !tctdbsetmutex(tdb)){
     eprint(tdb, __LINE__, "tctdbsetmutex");
     err = true;
@@ -2044,8 +2051,8 @@ static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
     eprint(tdb, __LINE__, "tctdbsync");
     err = true;
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb));
-  iprintf("size: %llu\n", (unsigned long long)tctdbfsiz(tdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctdbrnum(tdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctdbfsiz(tdb));
   sysprint();
   if(!tctdbclose(tdb)){
     eprint(tdb, __LINE__, "tctdbclose");
index 149dac3..6cff393 100644 (file)
@@ -1223,7 +1223,7 @@ static int procdate(const char *str, int jl, bool wf, bool rf){
     tcdatestrhttp(t, jl, buf);
     printf("%s\n", buf);
   } else {
-    printf("%lld\n", (long long int)t);
+    printf("%" PRIdMAX "\n", (long long int)t);
   }
   return 0;
 }
@@ -1271,22 +1271,22 @@ static int procconf(int mode){
       printf("myconf(bigend): %d\n", TCBIGEND);
       printf("myconf(usezlib): %d\n", TCUSEZLIB);
       printf("myconf(usebzip): %d\n", TCUSEBZIP);
-      printf("type(bool): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(bool): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(bool), (int)_alignof(bool), TCALIGNOF(bool),
              (unsigned long long)true);
-      printf("type(char): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(char): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(char), (int)_alignof(char), TCALIGNOF(char),
              (unsigned long long)CHAR_MAX);
-      printf("type(short): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(short): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(short), (int)_alignof(short), TCALIGNOF(short),
              (unsigned long long)SHRT_MAX);
-      printf("type(int): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(int): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(int), (int)_alignof(int), TCALIGNOF(int),
              (unsigned long long)INT_MAX);
-      printf("type(long): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(long): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(long), (int)_alignof(long), TCALIGNOF(long),
              (unsigned long long)LONG_MAX);
-      printf("type(long long): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(long long): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(long long), (int)_alignof(long long), TCALIGNOF(long long),
              (unsigned long long)LLONG_MAX);
       printf("type(float): size=%d align=%d offset=%d max=%g\n",
@@ -1300,39 +1300,41 @@ static int procconf(int mode){
              (long double)LDBL_MAX);
       printf("type(void *): size=%d align=%d offset=%d\n",
              (int)sizeof(void *), (int)_alignof(void *), TCALIGNOF(void *));
-      printf("type(intptr_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(intptr_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(intptr_t), (int)_alignof(intptr_t), TCALIGNOF(intptr_t),
              (unsigned long long)INTPTR_MAX);
-      printf("type(size_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(size_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(size_t), (int)_alignof(size_t), TCALIGNOF(size_t),
              (unsigned long long)SIZE_MAX);
-      printf("type(ptrdiff_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(ptrdiff_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(ptrdiff_t), (int)_alignof(ptrdiff_t), TCALIGNOF(ptrdiff_t),
              (unsigned long long)PTRDIFF_MAX);
-      printf("type(wchar_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(wchar_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(wchar_t), (int)_alignof(wchar_t), TCALIGNOF(wchar_t),
              (unsigned long long)WCHAR_MAX);
-      printf("type(sig_atomic_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(sig_atomic_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(sig_atomic_t), (int)_alignof(sig_atomic_t), TCALIGNOF(sig_atomic_t),
              (unsigned long long)SIG_ATOMIC_MAX);
-      printf("type(time_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(time_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(time_t), (int)_alignof(time_t), TCALIGNOF(time_t),
              (unsigned long long)_maxof(time_t));
-      printf("type(off_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(off_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(off_t), (int)_alignof(off_t), TCALIGNOF(off_t),
              (unsigned long long)_maxof(off_t));
-      printf("type(ino_t): size=%d align=%d offset=%d max=%llu\n",
+      printf("type(ino_t): size=%d align=%d offset=%d max=%" PRIuMAX "\n",
              (int)sizeof(ino_t), (int)_alignof(ino_t), TCALIGNOF(ino_t),
              (unsigned long long)_maxof(ino_t));
       printf("type(tcgeneric_t): size=%d align=%d offset=%d\n",
              (int)sizeof(tcgeneric_t), (int)_alignof(tcgeneric_t), TCALIGNOF(tcgeneric_t));
-      printf("macro(RAND_MAX): %llu\n", (unsigned long long)RAND_MAX);
-      printf("macro(PATH_MAX): %llu\n", (unsigned long long)PATH_MAX);
-      printf("macro(NAME_MAX): %llu\n", (unsigned long long)NAME_MAX);
+      printf("macro(RAND_MAX): %" PRIuMAX "\n", (unsigned long long)RAND_MAX);
+      printf("macro(PATH_MAX): %" PRIuMAX "\n", (unsigned long long)PATH_MAX);
+      printf("macro(NAME_MAX): %" PRIuMAX "\n", (unsigned long long)NAME_MAX);
+#ifndef _WIN32
       printf("macro(P_tmpdir): %s\n", P_tmpdir);
-      printf("sysconf(_SC_CLK_TCK): %ld\n", sysconf(_SC_CLK_TCK));
       printf("sysconf(_SC_OPEN_MAX): %ld\n", sysconf(_SC_OPEN_MAX));
-      printf("sysconf(_SC_PAGESIZE): %ld\n", sysconf(_SC_PAGESIZE));
+#endif
+      printf("sysconf(_SC_CLK_TCK): %ld\n", sysconf_SC_CLK_TCK);
+      printf("sysconf(_SC_PAGESIZE): %ld\n", tcpagsize());
       TCMAP *info = tcsysinfo();
       if(info){
         tcmapiterinit(info);
@@ -1346,7 +1348,9 @@ static int procconf(int mode){
       if(stat(MYCDIRSTR, &sbuf) == 0){
         printf("stat(st_uid): %d\n", (int)sbuf.st_uid);
         printf("stat(st_gid): %d\n", (int)sbuf.st_gid);
+#ifndef _WIN32
         printf("stat(st_blksize): %d\n", (int)sbuf.st_blksize);
+#endif
       }
   }
   return 0;
index 46de087..c555ca4 100644 (file)
@@ -318,11 +318,11 @@ static int proccombo(int tnum, int rnum, int bnum, bool tr, bool rnd){
     }
   }
   if(tr){
-    iprintf("record number: %llu\n", (unsigned long long)tcndbrnum(ndb));
-    iprintf("size: %llu\n", (unsigned long long)tcndbmsiz(ndb));
+    iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcndbrnum(ndb));
+    iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcndbmsiz(ndb));
   } else {
-    iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
-    iprintf("size: %llu\n", (unsigned long long)tcmdbmsiz(mdb));
+    iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcmdbrnum(mdb));
+    iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcmdbmsiz(mdb));
   }
   tcndbdel(ndb);
   tcmdbdel(mdb);
@@ -376,11 +376,11 @@ static int proctypical(int tnum, int rnum, int bnum, bool tr, bool nc, int rrati
     }
   }
   if(tr){
-    iprintf("record number: %llu\n", (unsigned long long)tcndbrnum(ndb));
-    iprintf("size: %llu\n", (unsigned long long)tcndbmsiz(ndb));
+    iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcndbrnum(ndb));
+    iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcndbmsiz(ndb));
   } else {
-    iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
-    iprintf("size: %llu\n", (unsigned long long)tcmdbmsiz(mdb));
+    iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcmdbrnum(mdb));
+    iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcmdbmsiz(mdb));
   }
   tcndbdel(ndb);
   tcmdbdel(mdb);
index bf2cb4d..84b157d 100644 (file)
@@ -576,8 +576,8 @@ static int procmap(int rnum, int bnum, bool rd, bool tr, bool rnd, int dmode){
     }
     if(rnd && rnum > 250) iprintf(" (%08d)\n", inum);
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcmaprnum(map));
-  iprintf("size: %llu\n", (unsigned long long)tcmapmsiz(map));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcmaprnum(map));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcmapmsiz(map));
   sysprint();
   tcmapdel(map);
   iprintf("time: %.3f\n", tctime() - stime);
@@ -652,8 +652,8 @@ static int proctree(int rnum, bool rd, bool tr, bool rnd, int dmode){
     }
     if(rnd && rnum > 250) iprintf(" (%08d)\n", inum);
   }
-  iprintf("record number: %llu\n", (unsigned long long)tctreernum(tree));
-  iprintf("size: %llu\n", (unsigned long long)tctreemsiz(tree));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tctreernum(tree));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tctreemsiz(tree));
   sysprint();
   tctreedel(tree);
   iprintf("time: %.3f\n", tctime() - stime);
@@ -728,8 +728,8 @@ static int procmdb(int rnum, int bnum, bool rd, bool tr, bool rnd, int dmode){
     }
     if(rnd && rnum > 250) iprintf(" (%08d)\n", inum);
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
-  iprintf("size: %llu\n", (unsigned long long)tcmdbmsiz(mdb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcmdbrnum(mdb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcmdbmsiz(mdb));
   sysprint();
   tcmdbdel(mdb);
   iprintf("time: %.3f\n", tctime() - stime);
@@ -804,8 +804,8 @@ static int procndb(int rnum, bool rd, bool tr, bool rnd, int dmode){
     }
     if(rnd && rnum > 250) iprintf(" (%08d)\n", inum);
   }
-  iprintf("record number: %llu\n", (unsigned long long)tcndbrnum(ndb));
-  iprintf("size: %llu\n", (unsigned long long)tcndbmsiz(ndb));
+  iprintf("record number: %" PRIuMAX "\n", (unsigned long long)tcndbrnum(ndb));
+  iprintf("size: %" PRIuMAX "\n", (unsigned long long)tcndbmsiz(ndb));
   sysprint();
   tcndbdel(ndb);
   iprintf("time: %.3f\n", tctime() - stime);
@@ -971,7 +971,7 @@ static int procmisc(int rnum){
       buf = tczeromap(myrand(1024*256) + 1);
       tczerounmap(buf);
     }
-    buf = tcmalloc(48);
+    buf = tcmalloc(64);
     date = myrand(INT_MAX - 1000000);
     jl = 3600 * (myrand(23) - 11);
     tcdatestrwww(date, jl, buf);
index e638daa..e4308bb 100644 (file)
@@ -18,6 +18,9 @@
 #include "myconf.h"
 #include "md5.h"
 
+#ifdef _WIN32
+#include <wincrypt.h>
+#endif
 
 
 /*************************************************************************************************
@@ -253,9 +256,13 @@ static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap){
       int cblen = 1;
       int lnum = 0;
       format++;
-      while(strchr("0123456789 .+-hlLz", *format) && *format != '\0' &&
+      while(strchr("0123456789 .+-hlLzI", *format) && *format != '\0' &&
             cblen < TCNUMBUFSIZ - 1){
-        if(*format == 'l' || *format == 'L') lnum++;
+        if(*format == 'l' || *format == 'L') {
+            lnum++;
+        } else if (*format == 'I' && *(format + 1) == '6' && *(format + 2) == '4') {
+            lnum += 2;
+        }
         cbuf[cblen++] = *(format++);
       }
       cbuf[cblen++] = *format;
@@ -2328,7 +2335,6 @@ int tcmaploadoneintoxstr(const void *ptr, int size, const void *kbuf, int ksiz,
     return -1;
 }
 
-
 /* Perform formatted output into a map object. */
 void tcmapprintf(TCMAP *map, const char *kstr, const char *format, ...){
   assert(map && kstr && format);
@@ -4405,7 +4411,7 @@ double tcndbadddouble(TCNDB *ndb, const void *kbuf, int ksiz, double num){
 /* Clear an on-memory tree database object. */
 void tcndbvanish(TCNDB *ndb){
   assert(ndb);
-  if(pthread_mutex_lock((pthread_mutex_t *)ndb->mmtx) != 0);
+  if (pthread_mutex_lock((pthread_mutex_t *)ndb->mmtx) != 0) return;
   tctreeclear(ndb->tree);
   pthread_mutex_unlock((pthread_mutex_t *)ndb->mmtx);
 }
@@ -4414,7 +4420,7 @@ void tcndbvanish(TCNDB *ndb){
 /* Remove fringe records of an on-memory tree database object. */
 void tcndbcutfringe(TCNDB *ndb, int num){
   assert(ndb && num >= 0);
-  if(pthread_mutex_lock((pthread_mutex_t *)ndb->mmtx) != 0);
+  if (pthread_mutex_lock((pthread_mutex_t *)ndb->mmtx) != 0) return;
   tctreecutfringe(ndb->tree, num);
   pthread_mutex_unlock((pthread_mutex_t *)ndb->mmtx);
 }
@@ -4709,16 +4715,11 @@ static void tcmpooldelglobal(void){
  *************************************************************************************************/
 
 
-#define TCRANDDEV      "/dev/urandom"    // path of the random device file
+
 #define TCDISTMAXLEN   4096              // maximum size of a string for distance checking
 #define TCDISTBUFSIZ   16384             // size of a distance buffer
 #define TCLDBLCOLMAX   16                // maximum number of columns of the long double
 
-
-/* File descriptor of random number generator. */
-int tcrandomdevfd = -1;
-
-
 /* private function prototypes */
 static void tcrandomfdclose(void);
 static time_t tcmkgmtime(struct tm *tm);
@@ -4735,7 +4736,10 @@ long tclmin(long a, long b){
   return (a < b) ? a : b;
 }
 
-
+#ifndef _WIN32
+#define TCRANDDEV      "/dev/urandom"    // path of the random device file
+/* File descriptor of random number generator. */
+int tcrandomdevfd = -1;
 /* Get a random number as long integer based on uniform distribution. */
 unsigned long tclrand(void){
   static uint32_t cnt = 0;
@@ -4744,8 +4748,9 @@ unsigned long tclrand(void){
   static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
   if((cnt & 0xff) == 0 && pthread_mutex_lock(&mutex) == 0){
     if(cnt == 0) seed += time(NULL);
-    if(tcrandomdevfd == -1 && (tcrandomdevfd = open(TCRANDDEV, O_RDONLY, 00644)) != -1)
+    if(tcrandomdevfd == -1 && (tcrandomdevfd = open(TCRANDDEV, O_RDONLY, 00644)) != -1) {
       atexit(tcrandomfdclose);
+    }
     if(tcrandomdevfd == -1 || read(tcrandomdevfd, &mask, sizeof(mask)) != sizeof(mask)){
       double t = tctime();
       uint64_t tmask;
@@ -4759,6 +4764,50 @@ unsigned long tclrand(void){
   return TCSWAB64(num);
 }
 
+/* Close the random number generator. */
+static void tcrandomfdclose(void){
+  close(tcrandomdevfd);
+}
+#else
+static HCRYPTPROV hcprov = 0;
+unsigned long tclrand(void) {
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    static bool acquired = false;
+    static uint32_t cnt = 0;
+    static uint64_t seed = 0;
+    static uint64_t mask = 0;
+    uint64_t num = 0;
+    if ((cnt & 0xff) == 0 && pthread_mutex_lock(&mutex) == 0) {
+        if(cnt == 0) seed += time(NULL);
+        if (!hcprov) {
+            if (!CryptAcquireContext(&hcprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+                hcprov = 0;
+            }
+            if (!acquired) {
+                acquired = true;
+                atexit(tcrandomfdclose);
+            }
+            if (!hcprov || !CryptGenRandom(hcprov, sizeof (mask), (PBYTE) &mask)) {
+                double t = tctime();
+                uint64_t tmask;
+                memcpy(&tmask, &t, tclmin(sizeof (t), sizeof (tmask)));
+                mask = (mask << 8) ^ tmask;
+            }
+        }
+        pthread_mutex_unlock(&mutex);
+    }
+    seed = seed * 123456789012301LL + 211;
+    num = (mask ^ cnt++) ^ seed;
+    return TCSWAB64(num);
+}
+static void tcrandomfdclose(void){
+    if (hcprov) {
+        CryptReleaseContext(hcprov, 0);
+        hcprov = 0;
+    }
+}
+#endif
+
 
 /* Get a random number as double decimal based on uniform distribution. */
 double tcdrand(void){
@@ -5508,18 +5557,17 @@ void tcarccipher(const void *ptr, int size, const void *kbuf, int ksiz, void *ob
 /* Get the time of day in seconds. */
 double tctime(void){
   struct timeval tv;
-  if(gettimeofday(&tv, NULL) == -1) return 0.0;
+  if(gettimeofday(&tv, NULL)) return 0.0;
   return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
 }
 
 /* Get time in milleconds since Epoch. */
 unsigned long tcmstime(void) {
   struct timeval tv;
-  if(gettimeofday(&tv, NULL) == -1) return 0;
+  if(gettimeofday(&tv, NULL)) return 0;
   return (unsigned long long) (tv.tv_sec) * 1000 + (unsigned long long) (tv.tv_usec) / 1000;
 }
 
-
 /* Get the Gregorian calendar of a time. */
 void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
                 int *hourp, int *minp, int *secp){
@@ -5834,11 +5882,6 @@ int tcdayofweek(int year, int mon, int day){
 }
 
 
-/* Close the random number generator. */
-static void tcrandomfdclose(void){
-  close(tcrandomdevfd);
-}
-
 
 /* Make the GMT from a time structure.
    `tm' specifies the pointer to the time structure.
@@ -5911,7 +5954,6 @@ bool tcstrisintnum(const char *str, int len){
   return isnum && (*str == '\0' || len == 0);
 }
 
-
 /* Convert a hexadecimal string to an integer. */
 int64_t tcatoih(const char *str){
   assert(str);
@@ -6513,7 +6555,7 @@ TCLIST *tcstrkwic(const char *str, const TCLIST *words, int width, int opts){
         TCMALLOC(tbuf, ti * 5 + 1);
         int wi = 0;
         wi += tcstrutfkwicputtext(oary, nary, 0, ti, nanum, tbuf + wi, uwords, opts);
-        if(!(opts & TCKWNOOVER) && opts & TCKWMUTAB){
+        if(!(opts & TCKWNOOVER) && (opts & TCKWMUTAB)){
           tbuf[wi++] = '\t';
           tbuf[wi++] = '\t';
         }
@@ -6819,7 +6861,10 @@ void tctopsort(void *base, size_t nmemb, size_t size, size_t top,
 /* Suspend execution of the current thread. */
 bool tcsleep(double sec){
   if(!isnormal(sec) || sec <= 0.0) return false;
-  if(sec <= 1.0 / sysconf(_SC_CLK_TCK)) return sched_yield() == 0;
+#ifdef _WIN32
+  Sleep(sec * 1000);
+#else
+  if(sec <= 1.0 / sysconf_SC_CLK_TCK) return sched_yield() == 0;
   double integ, fract;
   fract = modf(sec, &integ);
   struct timespec req, rem;
@@ -6829,6 +6874,7 @@ bool tcsleep(double sec){
     if(errno != EINTR) return false;
     req = rem;
   }
+#endif
   return true;
 }
 
@@ -6858,10 +6904,10 @@ TCMAP *tcsysinfo(void){
       }
       if(tcstrifwm(line, "VmSize:")){
         int64_t size = tcatoix(rp);
-        if(size > 0) tcmapprintf(info, "size", "%lld", (long long)size);
+        if(size > 0) tcmapprintf(info, "size", "%" PRIdMAX "", (long long)size);
       } else if(tcstrifwm(line, "VmRSS:")){
         int64_t size = tcatoix(rp);
-        if(size > 0) tcmapprintf(info, "rss", "%lld", (long long)size);
+        if(size > 0) tcmapprintf(info, "rss", "%" PRIdMAX "", (long long)size);
       }
     }
     tclistdel(lines);
@@ -6879,13 +6925,13 @@ TCMAP *tcsysinfo(void){
       }
       if(tcstrifwm(line, "MemTotal:")){
         int64_t size = tcatoix(rp);
-        if(size > 0) tcmapprintf(info, "total", "%lld", (long long)size);
+        if(size > 0) tcmapprintf(info, "total", "%" PRIdMAX "", (long long)size);
       } else if(tcstrifwm(line, "MemFree:")){
         int64_t size = tcatoix(rp);
-        if(size > 0) tcmapprintf(info, "free", "%lld", (long long)size);
+        if(size > 0) tcmapprintf(info, "free", "%" PRIdMAX "", (long long)size);
       } else if(tcstrifwm(line, "Cached:")){
         int64_t size = tcatoix(rp);
-        if(size > 0) tcmapprintf(info, "cached", "%lld", (long long)size);
+        if(size > 0) tcmapprintf(info, "cached", "%" PRIdMAX "", (long long)size);
       }
     }
     tclistdel(lines);
@@ -6898,7 +6944,7 @@ TCMAP *tcsysinfo(void){
       const char *line = TCLISTVALPTR(lines, i);
       if(tcstrifwm(line, "processor")) cnum++;
     }
-    if(cnum > 0) tcmapprintf(info, "corenum", "%lld", (long long)cnum);
+    if(cnum > 0) tcmapprintf(info, "corenum", "%" PRIdMAX "", (long long)cnum);
     tclistdel(lines);
   }
   return info;
@@ -6911,9 +6957,22 @@ TCMAP *tcsysinfo(void){
                 rbuf.ru_utime.tv_sec + rbuf.ru_utime.tv_usec / 1000000.0);
     tcmapprintf(info, "stime", "%0.6f",
                 rbuf.ru_stime.tv_sec + rbuf.ru_stime.tv_usec / 1000000.0);
-    long tck = sysconf(_SC_CLK_TCK);
+    long tck = sysconf_SC_CLK_TCK;
     int64_t size = (((double)rbuf.ru_ixrss + rbuf.ru_idrss + rbuf.ru_isrss) / tck) * 1024.0;
-    if(size > 0) tcmapprintf(info, "rss", "%lld", (long long)size);
+    if(size > 0) tcmapprintf(info, "rss", "%" PRIdMAX "", (long long)size);
+  }
+  return info;
+#elif defined(_WIN32)
+  TCMAP *info = tcmapnew2(TCMAPTINYBNUM);
+  FILETIME creat, exit, kernel, user;
+  ULARGE_INTEGER largetime;
+  if (GetProcessTimes(GetCurrentProcess(), &creat, &exit, &kernel, &user)){
+    largetime.LowPart = user.dwLowDateTime;
+    largetime.HighPart = user.dwHighDateTime;
+    tcmapprintf(info, "utime", "%0.6f", largetime.QuadPart / 10000000.0);
+    largetime.LowPart = kernel.dwLowDateTime;
+    largetime.HighPart = kernel.dwHighDateTime;
+    tcmapprintf(info, "stime", "%0.6f", largetime.QuadPart / 10000000.0);
   }
   return info;
 #else
@@ -7073,10 +7132,16 @@ static int tcchidxcmp(const void *a, const void *b){
 
 
 #define TCFILEMODE     00644             // permission of a creating file
+#ifdef _WIN32
+#define TCIOBUFSIZ     65536             // size of an I/O buffer
+#else
 #define TCIOBUFSIZ     16384             // size of an I/O buffer
+#endif
+
 
 
 /* Get the canonicalized absolute path of a file. */
+#ifndef _WIN32
 char *tcrealpath(const char *path){
   assert(path);
   char buf[PATH_MAX+1];
@@ -7104,6 +7169,16 @@ char *tcrealpath(const char *path){
   }
   return NULL;
 }
+#else
+char *tcrealpath(const char *path) {
+    char *ret = _fullpath(NULL, path, _MAX_PATH);
+    if (!ret) {
+        SetLastError(ERROR_INVALID_ACCESS);
+        return NULL;
+    }
+    return ret;
+}
+#endif
 
 
 /* Get the status information of a file. */
@@ -7119,38 +7194,76 @@ bool tcstatfile(const char *path, bool *isdirp, int64_t *sizep, int64_t *mtimep)
 
 
 /* Read whole data of a file. */
-void *tcreadfile(const char *path, int limit, int *sp){
-  int fd = path ? open(path, O_RDONLY, TCFILEMODE) : 0;
-  if(fd == -1) return NULL;
-  if(fd == 0){
-    TCXSTR *xstr = tcxstrnew();
-    char buf[TCIOBUFSIZ];
-    limit = limit > 0 ? limit : INT_MAX;
+void *tcreadfile(const char *path, int limit, int *sp) {
+    HANDLE fd;
+    if (path) {
+#ifndef _WIN32
+        fd = open(path, O_RDONLY, TCFILEMODE);
+#else
+        fd = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+    } else {
+        fd = GET_STDIN_HANDLE();
+    }
+    if (INVALIDHANDLE(fd)) {
+        return NULL;
+    }
+    if (path == NULL) { //stdin
+        TCXSTR *xstr = tcxstrnew();
+        char buf[TCIOBUFSIZ];
+        limit = limit > 0 ? limit : INT_MAX;
+        int rsiz;
+
+        while (1) {
+#ifndef _WIN32
+            rsiz = read(fd, buf, tclmin(TCIOBUFSIZ, limit));
+#else
+            DWORD red;
+            if (!ReadFile(fd, buf, tclmin(TCIOBUFSIZ, limit), &red, NULL)) {
+                rsiz = -1;
+            } else {
+                rsiz = red;
+            }
+#endif
+            if (rsiz <= 0) {
+                break;
+            }
+            TCXSTRCAT(xstr, buf, rsiz);
+            limit -= rsiz;
+        }
+        if (sp) *sp = TCXSTRSIZE(xstr);
+        return tcxstrtomalloc(xstr);
+    }
+    struct stat sbuf;
+    if (fstat(fd, &sbuf) || !S_ISREG(sbuf.st_mode)) {
+        CLOSEFH(fd);
+        return NULL;
+    }
+    limit = (limit > 0) ? tclmin((int) sbuf.st_size, limit) : sbuf.st_size;
+    char *buf;
+    TCMALLOC(buf, limit + 1);
+    char *wp = buf;
     int rsiz;
-    while((rsiz = read(fd, buf, tclmin(TCIOBUFSIZ, limit))) > 0){
-      TCXSTRCAT(xstr, buf, rsiz);
-      limit -= rsiz;
+    while (1) {
+#ifndef _WIN32
+        rsiz = read(fd, wp, limit - (wp - buf)));
+#else
+        DWORD red;
+        if (!ReadFile(fd, wp, limit - (wp - buf), &red, NULL)) {
+            rsiz = -1;
+        } else {
+            rsiz = red;
+        }
+#endif
+        if (rsiz <= 0) {
+            break;
+        }
+        wp += rsiz;
     }
-    if(sp) *sp = TCXSTRSIZE(xstr);
-    return tcxstrtomalloc(xstr);
-  }
-  struct stat sbuf;
-  if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
-    close(fd);
-    return NULL;
-  }
-  limit = limit > 0 ? tclmin((int)sbuf.st_size, limit) : sbuf.st_size;
-  char *buf;
-  TCMALLOC(buf, sbuf.st_size + 1);
-  char *wp = buf;
-  int rsiz;
-  while((rsiz = read(fd, wp, limit - (wp - buf))) > 0){
-    wp += rsiz;
-  }
-  *wp = '\0';
-  close(fd);
-  if(sp) *sp = wp - buf;
-  return buf;
+    *wp = '\0';
+    CLOSEFH(fd);
+    if (sp) *sp = wp - buf;
+    return buf;
 }
 
 
@@ -7187,29 +7300,83 @@ TCLIST *tcreadfilelines(const char *path){
 /* Write data into a file. */
 bool tcwritefile(const char *path, const void *ptr, int size){
   assert(ptr && size >= 0);
-  int fd = 1;
-  if(path && (fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE)) == -1) return false;
+  HANDLE fd;
+  if (path) {
+#ifdef _WIN32
+      fd = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#else
+      fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE);
+#endif
+  } else {
+      fd = GET_STDOUT_HANDLE();
+  }
+  if (INVALIDHANDLE(fd)) {
+      return false;
+  }
   bool err = false;
   if(!tcwrite(fd, ptr, size)) err = true;
-  if(close(fd) == -1) err = true;
+  if(path && !CLOSEFH(fd)) err = true;
   return !err;
 }
 
 
 /* Copy a file. */
 bool tccopyfile(const char *src, const char *dest){
-  int ifd = open(src, O_RDONLY, TCFILEMODE);
-  if(ifd == -1) return false;
-  int ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE);
-  if(ofd == -1){
-    close(ifd);
+  HANDLE ifd, ofd;
+#ifndef _WIN32
+  ifd = open(src, O_RDONLY, TCFILEMODE);
+#else
+  ifd = CreateFile(src, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+  if (INVALIDHANDLE(ifd)) return false;
+
+#ifndef _WIN32
+  ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE);
+#else
+  ofd = CreateFile(dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
+  if(INVALIDHANDLE(ofd)){
+    CLOSEFH(ifd);
     return false;
   }
   bool err = false;
-  while(true){
+  struct stat stat;
+  if (fstat(ifd, &stat)) {
+         CLOSEFH(ifd);
+         CLOSEFH(ofd);
+         return false;
+  }
+  off_t togo = stat.st_size;
+#ifdef _WIN32
+  HANDLE map = CreateFileMapping(ifd, NULL, PAGE_READONLY, 0, 0, NULL);
+  void *mmaped;
+  if (INVALIDHANDLE(map)) {
+         CLOSEFH(ifd);
+         CLOSEFH(ofd);
+         return false;
+  }
+#endif
+  while(togo > 0){
     char buf[TCIOBUFSIZ];
+#ifndef _WIN32
     int size = read(ifd, buf, TCIOBUFSIZ);
+#else
+    size_t toread = min(togo, TCIOBUFSIZ);
+    int size;
+    LARGE_INTEGER offset;
+    offset.QuadPart = stat.st_size - togo;
+    mmaped = MapViewOfFileEx(map, FILE_MAP_READ, offset.HighPart, offset.LowPart, toread, NULL);
+    if (mmaped == NULL){
+       size = -1;
+       errno = ESPIPE;
+    } else{
+       size = toread;
+       memcpy(buf, mmaped, toread);
+       UnmapViewOfFile(mmaped);
+    }
+#endif
     if(size > 0){
+      togo -= size;
       if(!tcwrite(ofd, buf, size)){
         err = true;
         break;
@@ -7223,8 +7390,11 @@ bool tccopyfile(const char *src, const char *dest){
       break;
     }
   }
-  if(close(ofd) == -1) err = true;
-  if(close(ifd) == -1) err = true;
+#ifdef _WIN32
+  if(!CLOSEFH(map)) err = true;
+#endif
+  if(!CLOSEFH(ofd)) err = true;
+  if(!CLOSEFH(ifd)) err = true;
   return !err;
 }
 
@@ -7265,7 +7435,7 @@ TCLIST *tcglobpat(const char *pattern){
 bool tcremovelink(const char *path){
   assert(path);
   struct stat sbuf;
-  if(lstat(path, &sbuf) == -1) return false;
+  if(lstat(path, &sbuf)) return false;
   if(unlink(path) == 0) return true;
   TCLIST *list;
   if(!S_ISDIR(sbuf.st_mode) || !(list = tcreaddir(path))) return false;
@@ -7286,13 +7456,59 @@ bool tcremovelink(const char *path){
   return rmdir(path) == 0 ? true : false;
 }
 
+bool tcfseek(HANDLE fd, off_t off, int whence) {
+#ifdef _WIN32
+LARGE_INTEGER loff;
+loff.QuadPart = off;
+int w = FILE_BEGIN;
+if (whence == TCFCUR) {
+    w = FILE_CURRENT;
+} else if (whence == TCFEND) {
+    w = FILE_END;
+}
+return SetFilePointerEx(fd, loff, NULL, w);
+#else
+int w = SEEK_SET;
+if (whence == TCFCUR) {
+    w = SEEK_CUR;
+} else if (whence == TCFEND) {
+    w = SEEK_END;
+}
+return (lseek(fd, off, w) != -1)
+#endif
+}
+
+bool tcftruncate(HANDLE fd, off_t length) {
+#ifdef _WIN32
+    LARGE_INTEGER size;
+    size.QuadPart = length;
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    bool err = false;
+    pthread_mutex_lock(&mutex);
+    if (!SetFilePointerEx(fd, size, NULL, FILE_BEGIN)) err = true;
+    if (err == false && !SetEndOfFile(fd)) err = true;
+    pthread_mutex_unlock(&mutex);
+    return !err;
+#else
+    return (ftruncate(fd, length) != -1);
+#endif
+}
 
 /* Write data into a file. */
-bool tcwrite(int fd, const void *buf, size_t size){
-  assert(fd >= 0 && buf && size >= 0);
+bool tcwrite(HANDLE fd, const void *buf, size_t size){
+  assert(!INVALIDHANDLE(fd) && buf && size >= 0);
   const char *rp = buf;
   do {
+#ifndef _WIN32
     int wb = write(fd, rp, size);
+#else
+    DWORD written;
+    int wb;
+    if (!WriteFile(fd, rp, size, &written, NULL))
+       wb = -1;
+    else
+       wb = written;
+#endif
     switch(wb){
       case -1: if(errno != EINTR) return false;
       case 0: break;
@@ -7307,11 +7523,20 @@ bool tcwrite(int fd, const void *buf, size_t size){
 
 
 /* Read data from a file. */
-bool tcread(int fd, void *buf, size_t size){
-  assert(fd >= 0 && buf && size >= 0);
+bool tcread(HANDLE fd, void *buf, size_t size){
+  assert(!INVALIDHANDLE(fd) && buf && size >= 0);
   char *wp = buf;
   do {
+#ifndef _WIN32
     int rb = read(fd, wp, size);
+#else
+    int rb;
+    DWORD r;
+    if(!ReadFile(fd, wp, size, &r, NULL))
+       rb = -1;
+    else
+       rb = r;
+#endif
     switch(rb){
       case -1: if(errno != EINTR) return false;
       case 0: return size < 1;
@@ -7325,8 +7550,9 @@ bool tcread(int fd, void *buf, size_t size){
 
 
 /* Lock a file. */
-bool tclock(int fd, bool ex, bool nb){
-  assert(fd >= 0);
+bool tclock(HANDLE fd, bool ex, bool nb){
+  assert(!INVALIDHANDLE(fd));
+#ifndef _WIN32
   struct flock lock;
   memset(&lock, 0, sizeof(struct flock));
   lock.l_type = ex ? F_WRLCK : F_RDLCK;
@@ -7338,12 +7564,25 @@ bool tclock(int fd, bool ex, bool nb){
     if(errno != EINTR) return false;
   }
   return true;
+#else
+  DWORD type = 0;      /* shared lock with waiting */
+  OVERLAPPED offset;
+  memset(&offset, 0, sizeof(OVERLAPPED));
+  if (ex) type  = LOCKFILE_EXCLUSIVE_LOCK;
+  if (nb) type |= LOCKFILE_FAIL_IMMEDIATELY;
+  if (LockFileEx(fd, type, 0, ULONG_MAX, ULONG_MAX, &offset)) {
+    return true;
+  } else {
+    return false;
+  }
+#endif
 }
 
 
 /* Unlock a file. */
-bool tcunlock(int fd){
-  assert(fd >= 0);
+bool tcunlock(HANDLE fd){
+  assert(!INVALIDHANDLE(fd));
+#ifndef _WIN32
   struct flock lock;
   memset(&lock, 0, sizeof(struct flock));
   lock.l_type = F_UNLCK;
@@ -7355,6 +7594,15 @@ bool tcunlock(int fd){
     if(errno != EINTR) return false;
   }
   return true;
+#else
+  OVERLAPPED offset;
+  memset(&offset, 0, sizeof(OVERLAPPED));
+  if (UnlockFileEx(fd, 0, ULONG_MAX, ULONG_MAX, &offset)) {
+    return true;
+  } else {
+    return false;
+  }
+#endif
 }
 
 
@@ -9700,6 +9948,48 @@ static void tcmtfdecode(char *ptr, int size);
 static int tcgammaencode(const char *ptr, int size, char *obuf);
 static int tcgammadecode(const char *ptr, int size, char *obuf);
 
+int tcfilerrno2tcerr(int tcerrdef) {
+#ifdef _WIN32
+    switch (GetLastError()) {
+        case ERROR_PATH_NOT_FOUND:
+        case ERROR_FILE_NOT_FOUND:
+            return TCENOFILE;
+        case ERROR_ACCESS_DENIED:
+        case ERROR_WRITE_PROTECT:
+        case ERROR_SHARING_VIOLATION:
+            return TCENOPERM;
+            break;
+        case ERROR_SEEK:
+            return TCESEEK;
+            break;
+        case ERROR_READ_FAULT:
+            return TCEREAD;
+            break;
+        case ERROR_WRITE_FAULT:
+            return TCEWRITE;
+            break;
+        case ERROR_LOCK_VIOLATION:
+            return TCELOCK;
+            break;
+        case ERROR_FILE_EXISTS:
+        case ERROR_ALREADY_EXISTS:
+            return TCEOPEN;
+            break;
+    }
+#endif
+    switch (errno) {
+        case EACCES:
+        case EROFS:
+            return TCENOPERM;
+            break;
+        case ENOENT:
+        case ENOTDIR:
+            return TCENOFILE;
+            break;
+    }
+    return tcerrdef;
+}
+
 
 /* Get the message string corresponding to an error code. */
 const char *tcerrmsg(int ecode){
@@ -9727,6 +10017,7 @@ const char *tcerrmsg(int ecode){
     case TCERMDIR: return "rmdir error";
     case TCEKEEP: return "existing record";
     case TCENOREC: return "no record found";
+    case TCETR: return "illegal transaction state";
     case TCEMISC: return "miscellaneous error";
   }
   return "unknown error";
@@ -10226,21 +10517,30 @@ double tclog2d(double num){
   return log(num) / log(2);
 }
 
+off_t tcpagsize(void) {
+#ifdef _WIN32
+    static off_t g_pagesize = 0;
+    if (!g_pagesize) {
+        SYSTEM_INFO system_info;
+        GetSystemInfo(&system_info);
+        g_pagesize = system_info.dwPageSize;
+    }
+    return g_pagesize;
+#else
+    return sysconf(_SC_PAGESIZE);
+#endif
+}
 
 /* Get the aligned offset of a file offset. */
 uint64_t tcpagealign(uint64_t off){
-  int ps = sysconf(_SC_PAGESIZE);
+  off_t ps = tcpagsize();
   int diff = off & (ps - 1);
-  return (diff > 0) ? off + ps - diff : off;
+  return (diff > 0) ? (off + ps - diff) : off;
 }
 
 
 /* Initialize the global mutex object */
 static void tcglobalinit(void){
-  if(!TCUSEPTHREAD){
-    memset(&tcglobalmutex, 0, sizeof(tcglobalmutex));
-    memset(&tcpathmutex, 0, sizeof(tcpathmutex));
-  }
   if(pthread_rwlock_init(&tcglobalmutex, NULL) != 0) tcmyfatal("rwlock error");
   if(pthread_mutex_init(&tcpathmutex, NULL) != 0) tcmyfatal("mutex error");
   tcpathmap = tcmapnew2(TCMAPTINYBNUM);
index 2cb09fb..62abf3b 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 __TCUTIL_CLINKAGEBEGIN
 
+#include "basedefs.h"
 
 #include <stdlib.h>
 #if ! defined(__cplusplus)
@@ -35,6 +36,7 @@ __TCUTIL_CLINKAGEBEGIN
 #include <time.h>
 #include <limits.h>
 #include <math.h>
+#include <sys/types.h>
 
 
 
@@ -44,14 +46,14 @@ __TCUTIL_CLINKAGEBEGIN
 
 
 /* String containing the version information. */
-extern const char *tcversion;
+extern EJDB_EXPORT const char *tcversion;
 
 
 /* Pointer to the call back function for handling a fatal error.
    The argument specifies the error message.
    The initial value of this variable is `NULL'.  If the value is `NULL', the default function is
    called when a fatal error occurs.  A fatal error occurs when memory allocation is failed. */
-extern void (*tcfatalfunc)(const char *);
+extern EJDB_EXPORT void (*tcfatalfunc)(const char *);
 
 
 /* Allocate a region on memory.
@@ -60,7 +62,7 @@ extern void (*tcfatalfunc)(const char *);
    This function handles failure of memory allocation implicitly.  Because the region of the
    return value is allocated with the `malloc' call, it should be released with the `free' call
    when it is no longer in use. */
-void *tcmalloc(size_t size);
+ EJDB_EXPORT void *tcmalloc(size_t size);
 
 
 /* Allocate a nullified region on memory.
@@ -70,7 +72,7 @@ void *tcmalloc(size_t size);
    This function handles failure of memory allocation implicitly.  Because the region of the
    return value is allocated with the `calloc' call, it should be released with the `free' call
    when it is no longer in use. */
-void *tccalloc(size_t nmemb, size_t size);
+EJDB_EXPORT void *tccalloc(size_t nmemb, size_t size);
 
 
 /* Re-allocate a region on memory.
@@ -80,7 +82,7 @@ void *tccalloc(size_t nmemb, size_t size);
    This function handles failure of memory allocation implicitly.  Because the region of the
    return value is allocated with the `realloc' call, it should be released with the `free' call
    when it is no longer in use. */
-void *tcrealloc(void *ptr, size_t size);
+EJDB_EXPORT void *tcrealloc(void *ptr, size_t size);
 
 
 /* Duplicate a region on memory.
@@ -91,7 +93,7 @@ void *tcrealloc(void *ptr, size_t size);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcmemdup(const void *ptr, size_t size);
+EJDB_EXPORT void *tcmemdup(const void *ptr, size_t size);
 
 
 /* Duplicate a string on memory.
@@ -99,14 +101,14 @@ void *tcmemdup(const void *ptr, size_t size);
    The return value is the allocated string equivalent to the specified string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcstrdup(const void *str);
+EJDB_EXPORT char *tcstrdup(const void *str);
 
 
 /* Free a region on memory.
    `ptr' specifies the pointer to the region.  If it is `NULL', this function has no effect.
    Although this function is just a wrapper of `free' call, this is useful in applications using
    another package of the `malloc' series. */
-void tcfree(void *ptr);
+EJDB_EXPORT void tcfree(void *ptr);
 
 
 
@@ -170,44 +172,44 @@ typedef struct {                         /* type of structure for an extensible
 
 /* Create an extensible string object.
    The return value is the new extensible string object. */
-TCXSTR *tcxstrnew(void);
+EJDB_EXPORT TCXSTR *tcxstrnew(void);
 
 
 /* Create an extensible string object from a character string.
    `str' specifies the string of the initial content.
    The return value is the new extensible string object containing the specified string. */
-TCXSTR *tcxstrnew2(const char *str);
+EJDB_EXPORT TCXSTR *tcxstrnew2(const char *str);
 
 
 /* Create an extensible string object with the initial allocation size.
    `asiz' specifies the initial allocation size.
    The return value is the new extensible string object. */
-TCXSTR *tcxstrnew3(int asiz);
+EJDB_EXPORT TCXSTR *tcxstrnew3(int asiz);
 
 
 /* Copy an extensible string object.
    `xstr' specifies the extensible string object.
    The return value is the new extensible string object equivalent to the specified object. */
-TCXSTR *tcxstrdup(const TCXSTR *xstr);
+EJDB_EXPORT TCXSTR *tcxstrdup(const TCXSTR *xstr);
 
 
 /* Delete an extensible string object.
    `xstr' specifies the extensible string object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tcxstrdel(TCXSTR *xstr);
+EJDB_EXPORT void tcxstrdel(TCXSTR *xstr);
 
 
 /* Concatenate a region to the end of an extensible string object.
    `xstr' specifies the extensible string object.
    `ptr' specifies the pointer to the region to be appended.
    `size' specifies the size of the region. */
-void tcxstrcat(TCXSTR *xstr, const void *ptr, int size);
+EJDB_EXPORT void tcxstrcat(TCXSTR *xstr, const void *ptr, int size);
 
 
 /* Concatenate a character string to the end of an extensible string object.
    `xstr' specifies the extensible string object.
    `str' specifies the string to be appended. */
-void tcxstrcat2(TCXSTR *xstr, const char *str);
+EJDB_EXPORT void tcxstrcat2(TCXSTR *xstr, const char *str);
 
 
 /* Get the pointer of the region of an extensible string object.
@@ -215,19 +217,19 @@ void tcxstrcat2(TCXSTR *xstr, const char *str);
    The return value is the pointer of the region of the object.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-const void *tcxstrptr(const TCXSTR *xstr);
+EJDB_EXPORT const void *tcxstrptr(const TCXSTR *xstr);
 
 
 /* Get the size of the region of an extensible string object.
    `xstr' specifies the extensible string object.
    The return value is the size of the region of the object. */
-int tcxstrsize(const TCXSTR *xstr);
+EJDB_EXPORT int tcxstrsize(const TCXSTR *xstr);
 
 
 /* Clear an extensible string object.
    `xstr' specifies the extensible string object.
    The internal buffer of the object is cleared and the size is set zero. */
-void tcxstrclear(TCXSTR *xstr);
+EJDB_EXPORT void tcxstrclear(TCXSTR *xstr);
 
 
 /* Perform formatted output into an extensible string object.
@@ -238,7 +240,7 @@ void tcxstrclear(TCXSTR *xstr);
    with `s' but escapes meta characters of URL.  `b' converts an integer to the string as binary
    numbers.  The other conversion character work as with each original.
    The other arguments are used according to the format string. */
-void tcxstrprintf(TCXSTR *xstr, const char *format, ...);
+EJDB_EXPORT void tcxstrprintf(TCXSTR *xstr, const char *format, ...);
 
 
 /* Allocate a formatted string on memory.
@@ -251,7 +253,7 @@ void tcxstrprintf(TCXSTR *xstr, const char *format, ...);
    The return value is the pointer to the region of the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcsprintf(const char *format, ...);
+EJDB_EXPORT char *tcsprintf(const char *format, ...);
 
 
 
@@ -268,7 +270,7 @@ char *tcsprintf(const char *format, ...);
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use.  Because the region of the original object is deleted, it should not be
    deleted again. */
-void *tcxstrtomalloc(TCXSTR *xstr);
+EJDB_EXPORT void *tcxstrtomalloc(TCXSTR *xstr);
 
 
 /* Create an extensible string object from an allocated region.
@@ -276,7 +278,7 @@ void *tcxstrtomalloc(TCXSTR *xstr);
    `size' specifies the size of the region.
    The return value is the new extensible string object wrapping the specified region.
    Note that the specified region is released when the object is deleted. */
-TCXSTR *tcxstrfrommalloc(void *ptr, int size);
+EJDB_EXPORT TCXSTR *tcxstrfrommalloc(void *ptr, int size);
 
 
 
@@ -300,38 +302,38 @@ typedef struct {                         /* type of structure for an array list
 
 /* Create a list object.
    The return value is the new list object. */
-TCLIST *tclistnew(void);
+EJDB_EXPORT TCLIST *tclistnew(void);
 
 
 /* Create a list object with expecting the number of elements.
    `anum' specifies the number of elements expected to be stored in the list.
    The return value is the new list object. */
-TCLIST *tclistnew2(int anum);
+EJDB_EXPORT TCLIST *tclistnew2(int anum);
 
 
 /* Create a list object with initial string elements.
    `str' specifies the string of the first element.
    The other arguments are other elements.  They should be trailed by a `NULL' argument.
    The return value is the new list object. */
-TCLIST *tclistnew3(const char *str, ...);
+EJDB_EXPORT TCLIST *tclistnew3(const char *str, ...);
 
 
 /* Copy a list object.
    `list' specifies the list object.
    The return value is the new list object equivalent to the specified object. */
-TCLIST *tclistdup(const TCLIST *list);
+EJDB_EXPORT TCLIST *tclistdup(const TCLIST *list);
 
 
 /* Delete a list object.
    `list' specifies the list object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tclistdel(TCLIST *list);
+EJDB_EXPORT void tclistdel(TCLIST *list);
 
 
 /* Get the number of elements of a list object.
    `list' specifies the list object.
    The return value is the number of elements of the list. */
-int tclistnum(const TCLIST *list);
+EJDB_EXPORT int tclistnum(const TCLIST *list);
 
 
 /* Get the pointer to the region of an element of a list object.
@@ -343,7 +345,7 @@ int tclistnum(const TCLIST *list);
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string.  If `index' is equal to or more than
    the number of elements, the return value is `NULL'. */
-const void *tclistval(const TCLIST *list, int index, int *sp);
+EJDB_EXPORT const void *tclistval(const TCLIST *list, int index, int *sp);
 
 
 /* Get the string of an element of a list object.
@@ -351,20 +353,20 @@ const void *tclistval(const TCLIST *list, int index, int *sp);
    `index' specifies the index of the element.
    The return value is the string of the value.
    If `index' is equal to or more than the number of elements, the return value is `NULL'. */
-const char *tclistval2(const TCLIST *list, int index);
+EJDB_EXPORT const char *tclistval2(const TCLIST *list, int index);
 
 
 /* Add an element at the end of a list object.
    `list' specifies the list object.
    `ptr' specifies the pointer to the region of the new element.
    `size' specifies the size of the region. */
-void tclistpush(TCLIST *list, const void *ptr, int size);
+EJDB_EXPORT void tclistpush(TCLIST *list, const void *ptr, int size);
 
 
 /* Add a string element at the end of a list object.
    `list' specifies the list object.
    `str' specifies the string of the new element. */
-void tclistpush2(TCLIST *list, const char *str);
+EJDB_EXPORT void tclistpush2(TCLIST *list, const char *str);
 
 
 /* Remove an element of the end of a list object.
@@ -376,7 +378,7 @@ void tclistpush2(TCLIST *list, const char *str);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use.  If the list is empty, the return value is `NULL'. */
-void *tclistpop(TCLIST *list, int *sp);
+EJDB_EXPORT void *tclistpop(TCLIST *list, int *sp);
 
 
 /* Remove a string element of the end of a list object.
@@ -385,20 +387,20 @@ void *tclistpop(TCLIST *list, int *sp);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  If the list is empty, the return
    value is `NULL'. */
-char *tclistpop2(TCLIST *list);
+EJDB_EXPORT char *tclistpop2(TCLIST *list);
 
 
 /* Add an element at the top of a list object.
    `list' specifies the list object.
    `ptr' specifies the pointer to the region of the new element.
    `size' specifies the size of the region. */
-void tclistunshift(TCLIST *list, const void *ptr, int size);
+EJDB_EXPORT void tclistunshift(TCLIST *list, const void *ptr, int size);
 
 
 /* Add a string element at the top of a list object.
    `list' specifies the list object.
    `str' specifies the string of the new element. */
-void tclistunshift2(TCLIST *list, const char *str);
+EJDB_EXPORT void tclistunshift2(TCLIST *list, const char *str);
 
 
 /* Remove an element of the top of a list object.
@@ -410,7 +412,7 @@ void tclistunshift2(TCLIST *list, const char *str);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use.  If the list is empty, the return value is `NULL'. */
-void *tclistshift(TCLIST *list, int *sp);
+EJDB_EXPORT void *tclistshift(TCLIST *list, int *sp);
 
 
 /* Remove a string element of the top of a list object.
@@ -419,7 +421,7 @@ void *tclistshift(TCLIST *list, int *sp);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  If the list is empty, the return
    value is `NULL'. */
-char *tclistshift2(TCLIST *list);
+EJDB_EXPORT char *tclistshift2(TCLIST *list);
 
 
 /* Add an element at the specified location of a list object.
@@ -428,7 +430,7 @@ char *tclistshift2(TCLIST *list);
    `ptr' specifies the pointer to the region of the new element.
    `size' specifies the size of the region.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistinsert(TCLIST *list, int index, const void *ptr, int size);
+EJDB_EXPORT void tclistinsert(TCLIST *list, int index, const void *ptr, int size);
 
 
 /* Add a string element at the specified location of a list object.
@@ -436,7 +438,7 @@ void tclistinsert(TCLIST *list, int index, const void *ptr, int size);
    `index' specifies the index of the new element.
    `str' specifies the string of the new element.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistinsert2(TCLIST *list, int index, const char *str);
+EJDB_EXPORT void tclistinsert2(TCLIST *list, int index, const char *str);
 
 
 /* Remove an element at the specified location of a list object.
@@ -450,7 +452,7 @@ void tclistinsert2(TCLIST *list, int index, const char *str);
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use.  If `index' is equal to or more than the number of elements, no element
    is removed and the return value is `NULL'. */
-void *tclistremove(TCLIST *list, int index, int *sp);
+EJDB_EXPORT void *tclistremove(TCLIST *list, int index, int *sp);
 
 
 /* Remove a string element at the specified location of a list object.
@@ -460,7 +462,7 @@ void *tclistremove(TCLIST *list, int index, int *sp);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  If `index' is equal to or more
    than the number of elements, no element is removed and the return value is `NULL'. */
-char *tclistremove2(TCLIST *list, int index);
+EJDB_EXPORT char *tclistremove2(TCLIST *list, int index);
 
 
 /* Overwrite an element at the specified location of a list object.
@@ -469,7 +471,7 @@ char *tclistremove2(TCLIST *list, int index);
    `ptr' specifies the pointer to the region of the new content.
    `size' specifies the size of the new content.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistover(TCLIST *list, int index, const void *ptr, int size);
+EJDB_EXPORT void tclistover(TCLIST *list, int index, const void *ptr, int size);
 
 
 /* Overwrite a string element at the specified location of a list object.
@@ -477,12 +479,12 @@ void tclistover(TCLIST *list, int index, const void *ptr, int size);
    `index' specifies the index of the element to be overwritten.
    `str' specifies the string of the new content.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistover2(TCLIST *list, int index, const char *str);
+EJDB_EXPORT void tclistover2(TCLIST *list, int index, const char *str);
 
 
 /* Sort elements of a list object in lexical order.
    `list' specifies the list object. */
-void tclistsort(TCLIST *list);
+EJDB_EXPORT void tclistsort(TCLIST *list);
 
 
 /* Search a list object for an element using liner search.
@@ -492,7 +494,7 @@ void tclistsort(TCLIST *list);
    The return value is the index of a corresponding element or -1 if there is no corresponding
    element.
    If two or more elements correspond, the former returns. */
-int tclistlsearch(const TCLIST *list, const void *ptr, int size);
+EJDB_EXPORT int tclistlsearch(const TCLIST *list, const void *ptr, int size);
 
 
 /* Search a list object for an element using binary search.
@@ -502,13 +504,13 @@ int tclistlsearch(const TCLIST *list, const void *ptr, int size);
    The return value is the index of a corresponding element or -1 if there is no corresponding
    element.
    If two or more elements correspond, which returns is not defined. */
-int tclistbsearch(const TCLIST *list, const void *ptr, int size);
+EJDB_EXPORT int tclistbsearch(const TCLIST *list, const void *ptr, int size);
 
 
 /* Clear a list object.
    `list' specifies the list object.
    All elements are removed. */
-void tclistclear(TCLIST *list);
+EJDB_EXPORT void tclistclear(TCLIST *list);
 
 
 /* Serialize a list object into a byte array.
@@ -518,7 +520,7 @@ void tclistclear(TCLIST *list);
    The return value is the pointer to the region of the result serial region.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-void *tclistdump(const TCLIST *list, int *sp);
+EJDB_EXPORT void *tclistdump(const TCLIST *list, int *sp);
 
 
 /* Create a list object from a serialized byte array.
@@ -527,7 +529,7 @@ void *tclistdump(const TCLIST *list, int *sp);
    The return value is a new list object.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tclistload(const void *ptr, int size);
+EJDB_EXPORT TCLIST *tclistload(const void *ptr, int size);
 
 
 
@@ -541,12 +543,12 @@ TCLIST *tclistload(const void *ptr, int size);
    `ptr' specifies the pointer to the region allocated with `malloc' call.
    `size' specifies the size of the region.
    Note that the specified region is released when the object is deleted. */
-void tclistpushmalloc(TCLIST *list, void *ptr, int size);
+EJDB_EXPORT void tclistpushmalloc(TCLIST *list, void *ptr, int size);
 
 
 /* Sort elements of a list object in case-insensitive lexical order.
    `list' specifies the list object. */
-void tclistsortci(TCLIST *list);
+EJDB_EXPORT void tclistsortci(TCLIST *list);
 
 
 /* Sort elements of a list object by an arbitrary comparison function.
@@ -554,12 +556,12 @@ void tclistsortci(TCLIST *list);
    `cmp' specifies the pointer to the comparison function.  The structure TCLISTDATUM has the
    member "ptr" which is the pointer to the region of the element, and the member "size" which is
    the size of the region. */
-void tclistsortex(TCLIST *list, int (*cmp)(const TCLISTDATUM *, const TCLISTDATUM *));
+EJDB_EXPORT void tclistsortex(TCLIST *list, int (*cmp)(const TCLISTDATUM *, const TCLISTDATUM *));
 
 
 /* Invert elements of a list object.
    `list' specifies the list object. */
-void tclistinvert(TCLIST *list);
+EJDB_EXPORT void tclistinvert(TCLIST *list);
 
 
 /* Perform formatted output into a list object.
@@ -570,7 +572,7 @@ void tclistinvert(TCLIST *list);
    with `s' but escapes meta characters of URL.  `b' converts an integer to the string as binary
    numbers.  The other conversion character work as with each original.
    The other arguments are used according to the format string. */
-void tclistprintf(TCLIST *list, const char *format, ...);
+EJDB_EXPORT void tclistprintf(TCLIST *list, const char *format, ...);
 
 
 
@@ -603,13 +605,13 @@ typedef struct {                         /* type of structure for a map */
 
 /* Create a map object.
    The return value is the new map object. */
-TCMAP *tcmapnew(void);
+EJDB_EXPORT TCMAP *tcmapnew(void);
 
 
 /* Create a map object with specifying the number of the buckets.
    `bnum' specifies the number of the buckets.
    The return value is the new map object. */
-TCMAP *tcmapnew2(uint32_t bnum);
+EJDB_EXPORT TCMAP *tcmapnew2(uint32_t bnum);
 
 
 /* Create a map object with initial string elements.
@@ -617,19 +619,19 @@ TCMAP *tcmapnew2(uint32_t bnum);
    The other arguments are other elements.  They should be trailed by a `NULL' argument.
    The return value is the new map object.
    The key and the value of each record are situated one after the other. */
-TCMAP *tcmapnew3(const char *str, ...);
+EJDB_EXPORT TCMAP *tcmapnew3(const char *str, ...);
 
 
 /* Copy a map object.
    `map' specifies the map object.
    The return value is the new map object equivalent to the specified object. */
-TCMAP *tcmapdup(const TCMAP *map);
+EJDB_EXPORT TCMAP *tcmapdup(const TCMAP *map);
 
 
 /* Delete a map object.
    `map' specifies the map object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tcmapdel(TCMAP *map);
+EJDB_EXPORT void tcmapdel(TCMAP *map);
 
 
 /* Store a record into a map object.
@@ -639,7 +641,7 @@ void tcmapdel(TCMAP *map);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the map, it is overwritten. */
-void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a map object.
@@ -647,7 +649,7 @@ void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If a record with the same key exists in the map, it is overwritten. */
-void tcmapput2(TCMAP *map, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcmapput2(TCMAP *map, const char *kstr, const char *vstr);
 
 
 /* Store a new record into a map object.
@@ -658,7 +660,7 @@ void tcmapput2(TCMAP *map, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the map, this function has no effect. */
-bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into a map object.
@@ -667,7 +669,7 @@ bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the map, this function has no effect. */
-bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the value of the existing record in a map object.
@@ -677,7 +679,7 @@ bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string value at the end of the value of the existing record in a map object.
@@ -685,7 +687,7 @@ void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int v
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If there is no corresponding record, a new record is created. */
-void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr);
 
 
 /* Remove a record of a map object.
@@ -694,7 +696,7 @@ void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmapout(TCMAP *map, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcmapout(TCMAP *map, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of a map object.
@@ -702,7 +704,7 @@ bool tcmapout(TCMAP *map, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmapout2(TCMAP *map, const char *kstr);
+EJDB_EXPORT bool tcmapout2(TCMAP *map, const char *kstr);
 
 
 /* Retrieve a record in a map object.
@@ -715,7 +717,7 @@ bool tcmapout2(TCMAP *map, const char *kstr);
    corresponding record.  `NULL' is returned when no record corresponds.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in a map object.
@@ -723,7 +725,7 @@ const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp);
    `kstr' specifies the string of the key.
    If successful, the return value is the string of the value of the corresponding record.
    `NULL' is returned when no record corresponds. */
-const char *tcmapget2(const TCMAP *map, const char *kstr);
+EJDB_EXPORT const char *tcmapget2(const TCMAP *map, const char *kstr);
 
 
 /* Move a record to the edge of a map object.
@@ -733,7 +735,7 @@ const char *tcmapget2(const TCMAP *map, const char *kstr);
    `head' specifies the destination which is the head if it is true or the tail if else.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head);
+EJDB_EXPORT bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head);
 
 
 /* Move a string record to the edge of a map object.
@@ -742,13 +744,13 @@ bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head);
    `head' specifies the destination which is the head if it is true or the tail if else.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmapmove2(TCMAP *map, const char *kstr, bool head);
+EJDB_EXPORT bool tcmapmove2(TCMAP *map, const char *kstr, bool head);
 
 
 /* Initialize the iterator of a map object.
    `map' specifies the map object.
    The iterator is used in order to access the key of every record stored in the map object. */
-void tcmapiterinit(TCMAP *map);
+EJDB_EXPORT void tcmapiterinit(TCMAP *map);
 
 
 /* Get the next key of the iterator of a map object.
@@ -760,7 +762,7 @@ void tcmapiterinit(TCMAP *map);
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string.
    The order of iteration is assured to be the same as the stored order. */
-const void *tcmapiternext(TCMAP *map, int *sp);
+EJDB_EXPORT const void *tcmapiternext(TCMAP *map, int *sp);
 
 
 /* Get the next key string of the iterator of a map object.
@@ -768,19 +770,19 @@ const void *tcmapiternext(TCMAP *map, int *sp);
    If successful, the return value is the pointer to the region of the next key, else, it is
    `NULL'.  `NULL' is returned when no record can be fetched from the iterator.
    The order of iteration is assured to be the same as the stored order. */
-const char *tcmapiternext2(TCMAP *map);
+EJDB_EXPORT const char *tcmapiternext2(TCMAP *map);
 
 
 /* Get the number of records stored in a map object.
    `map' specifies the map object.
    The return value is the number of the records stored in the map object. */
-uint64_t tcmaprnum(const TCMAP *map);
+EJDB_EXPORT uint64_t tcmaprnum(const TCMAP *map);
 
 
 /* Get the total size of memory used in a map object.
    `map' specifies the map object.
    The return value is the total size of memory used in a map object. */
-uint64_t tcmapmsiz(const TCMAP *map);
+EJDB_EXPORT uint64_t tcmapmsiz(const TCMAP *map);
 
 
 /* Create a list object containing all keys in a map object.
@@ -788,7 +790,7 @@ uint64_t tcmapmsiz(const TCMAP *map);
    The return value is the new list object containing all keys in the map object.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcmapkeys(const TCMAP *map);
+EJDB_EXPORT TCLIST *tcmapkeys(const TCMAP *map);
 
 
 /* Create a list object containing all values in a map object.
@@ -796,7 +798,7 @@ TCLIST *tcmapkeys(const TCMAP *map);
    The return value is the new list object containing all values in the map object.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcmapvals(const TCMAP *map);
+EJDB_EXPORT TCLIST *tcmapvals(const TCMAP *map);
 
 
 /* Add an integer to a record in a map object.
@@ -807,7 +809,7 @@ TCLIST *tcmapvals(const TCMAP *map);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tcmapaddint(TCMAP *map, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tcmapaddint(TCMAP *map, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in a map object.
@@ -818,19 +820,19 @@ int tcmapaddint(TCMAP *map, const void *kbuf, int ksiz, int num);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tcmapadddouble(TCMAP *map, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tcmapadddouble(TCMAP *map, const void *kbuf, int ksiz, double num);
 
 
 /* Clear a map object.
    `map' specifies the map object.
    All records are removed. */
-void tcmapclear(TCMAP *map);
+EJDB_EXPORT void tcmapclear(TCMAP *map);
 
 
 /* Remove front records of a map object.
    `map' specifies the map object.
    `num' specifies the number of records to be removed. */
-void tcmapcutfront(TCMAP *map, int num);
+EJDB_EXPORT void tcmapcutfront(TCMAP *map, int num);
 
 
 /* Serialize a map object into a byte array.
@@ -840,7 +842,7 @@ void tcmapcutfront(TCMAP *map, int num);
    The return value is the pointer to the region of the result serial region.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-void *tcmapdump(const TCMAP *map, int *sp);
+EJDB_EXPORT void *tcmapdump(const TCMAP *map, int *sp);
 
 
 /* Create a map object from a serialized byte array.
@@ -849,7 +851,7 @@ void *tcmapdump(const TCMAP *map, int *sp);
    The return value is a new map object.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcmapload(const void *ptr, int size);
+EJDB_EXPORT TCMAP *tcmapload(const void *ptr, int size);
 
 
 
@@ -866,7 +868,7 @@ TCMAP *tcmapload(const void *ptr, int size);
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the map, it is overwritten.  The record is moved to
    the tail. */
-void tcmapput3(TCMAP *map, const void *kbuf, int ksiz, const char *vbuf, int vsiz);
+EJDB_EXPORT void tcmapput3(TCMAP *map, const void *kbuf, int ksiz, const char *vbuf, int vsiz);
 
 
 /* Store a record of the value of two regions into a map object.
@@ -878,7 +880,7 @@ void tcmapput3(TCMAP *map, const void *kbuf, int ksiz, const char *vbuf, int vsi
    `lvbuf' specifies the pointer to the latter region of the value.
    `lvsiz' specifies the size of the latter region of the value.
    If a record with the same key exists in the map, it is overwritten. */
-void tcmapput4(TCMAP *map, const void *kbuf, int ksiz,
+EJDB_EXPORT void tcmapput4(TCMAP *map, const void *kbuf, int ksiz,
                const void *fvbuf, int fvsiz, const void *lvbuf, int lvsiz);
 
 
@@ -889,7 +891,7 @@ void tcmapput4(TCMAP *map, const void *kbuf, int ksiz,
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tcmapputcat3(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmapputcat3(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a record into a map object with a duplication handler.
@@ -909,7 +911,7 @@ void tcmapputcat3(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int
    `op' specifies an arbitrary pointer to be given as a parameter of the callback function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tcmapputproc(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tcmapputproc(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -925,7 +927,7 @@ bool tcmapputproc(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int
    the return value can be treated as a character string.  The internal region of the returned
    record is moved to the tail so that the record will survive for a time under LRU cache
    algorithm removing records from the head. */
-const void *tcmapget3(TCMAP *map, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT const void *tcmapget3(TCMAP *map, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in a map object with specifying the default value string.
@@ -934,7 +936,7 @@ const void *tcmapget3(TCMAP *map, const void *kbuf, int ksiz, int *sp);
    `dstr' specifies the string of the default value.
    The return value is the string of the value of the corresponding record or the default value
    string. */
-const char *tcmapget4(TCMAP *map, const char *kstr, const char *dstr);
+EJDB_EXPORT const char *tcmapget4(TCMAP *map, const char *kstr, const char *dstr);
 
 
 /* Initialize the iterator of a map object at the record corresponding a key.
@@ -942,14 +944,14 @@ const char *tcmapget4(TCMAP *map, const char *kstr, const char *dstr);
    `kbuf' specifies the pointer to the region of the key.
    `ksiz' specifies the size of the region of the key.
    If there is no record corresponding the condition, the iterator is not modified. */
-void tcmapiterinit2(TCMAP *map, const void *kbuf, int ksiz);
+EJDB_EXPORT void tcmapiterinit2(TCMAP *map, const void *kbuf, int ksiz);
 
 
 /* Initialize the iterator of a map object at the record corresponding a key string.
    `map' specifies the map object.
    `kstr' specifies the string of the key.
    If there is no record corresponding the condition, the iterator is not modified. */
-void tcmapiterinit3(TCMAP *map, const char *kstr);
+EJDB_EXPORT void tcmapiterinit3(TCMAP *map, const char *kstr);
 
 
 /* Get the value bound to the key fetched from the iterator of a map object.
@@ -959,13 +961,13 @@ void tcmapiterinit3(TCMAP *map, const char *kstr);
    The return value is the pointer to the region of the value of the corresponding record.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-const void *tcmapiterval(const void *kbuf, int *sp);
+EJDB_EXPORT const void *tcmapiterval(const void *kbuf, int *sp);
 
 
 /* Get the value string bound to the key fetched from the iterator of a map object.
    `kstr' specifies the string of the iteration key.
    The return value is the pointer to the region of the value of the corresponding record. */
-const char *tcmapiterval2(const char *kstr);
+EJDB_EXPORT const char *tcmapiterval2(const char *kstr);
 
 
 /* Create an array of strings of all keys in a map object.
@@ -976,7 +978,7 @@ const char *tcmapiterval2(const char *kstr);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use.  Note that elements of the array
    point to the inner objects, whose life duration is synchronous with the map object. */
-const char **tcmapkeys2(const TCMAP *map, int *np);
+EJDB_EXPORT const char **tcmapkeys2(const TCMAP *map, int *np);
 
 
 /* Create an array of strings of all values in a map object.
@@ -987,7 +989,7 @@ const char **tcmapkeys2(const TCMAP *map, int *np);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use.  Note that elements of the array
    point to the inner objects, whose life duration is synchronous with the map object. */
-const char **tcmapvals2(const TCMAP *map, int *np);
+EJDB_EXPORT const char **tcmapvals2(const TCMAP *map, int *np);
 
 
 /* Extract a map record from a serialized byte array.
@@ -1001,7 +1003,7 @@ const char **tcmapvals2(const TCMAP *map, int *np);
    corresponding record.  `NULL' is returned when no record corresponds.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-void *tcmaploadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcmaploadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp);
 
 
 /* Extract a map record from a serialized byte array into extensible string object.
@@ -1012,7 +1014,7 @@ void *tcmaploadone(const void *ptr, int size, const void *kbuf, int ksiz, int *s
    `xstr' specifies extensible string object data will be placed into.
    If successful, the return value is >= 0
    corresponding record.  0 is returned when no record corresponds.*/
-int tcmaploadoneintoxstr(const void *ptr, int size, const void *kbuf, int ksiz, TCXSTR *xstr);
+EJDB_EXPORT int tcmaploadoneintoxstr(const void *ptr, int size, const void *kbuf, int ksiz, TCXSTR *xstr);
 
 
 /* Perform formatted output into a map object.
@@ -1024,7 +1026,7 @@ int tcmaploadoneintoxstr(const void *ptr, int size, const void *kbuf, int ksiz,
    with `s' but escapes meta characters of URL.  `b' converts an integer to the string as binary
    numbers.  The other conversion character work as with each original.
    The other arguments are used according to the format string. */
-void tcmapprintf(TCMAP *map, const char *kstr, const char *format, ...);
+EJDB_EXPORT void tcmapprintf(TCMAP *map, const char *kstr, const char *format, ...);
 
 
 
@@ -1052,7 +1054,7 @@ typedef struct {                         /* type of structure for a tree */
 
 /* Create a tree object.
    The return value is the new tree object. */
-TCTREE *tctreenew(void);
+EJDB_EXPORT TCTREE *tctreenew(void);
 
 
 /* Create a tree object with specifying the custom comparison function.
@@ -1067,19 +1069,19 @@ TCTREE *tctreenew(void);
    The return value is the new tree object.
    The default comparison function compares keys of two records by lexical order.  The functions
    `tccmplexical' (dafault), `tccmpdecimal', `tccmpint32', and `tccmpint64' are built-in. */
-TCTREE *tctreenew2(TCCMP cmp, void *cmpop);
+EJDB_EXPORT TCTREE *tctreenew2(TCCMP cmp, void *cmpop);
 
 
 /* Copy a tree object.
    `tree' specifies the tree object.
    The return value is the new tree object equivalent to the specified object. */
-TCTREE *tctreedup(const TCTREE *tree);
+EJDB_EXPORT TCTREE *tctreedup(const TCTREE *tree);
 
 
 /* Delete a tree object.
    `tree' specifies the tree object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tctreedel(TCTREE *tree);
+EJDB_EXPORT void tctreedel(TCTREE *tree);
 
 
 /* Store a record into a tree object.
@@ -1089,7 +1091,7 @@ void tctreedel(TCTREE *tree);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the tree, it is overwritten. */
-void tctreeput(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tctreeput(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into a tree object.
@@ -1097,7 +1099,7 @@ void tctreeput(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int v
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If a record with the same key exists in the tree, it is overwritten. */
-void tctreeput2(TCTREE *tree, const char *kstr, const char *vstr);
+EJDB_EXPORT void tctreeput2(TCTREE *tree, const char *kstr, const char *vstr);
 
 
 /* Store a new record into a tree object.
@@ -1108,7 +1110,7 @@ void tctreeput2(TCTREE *tree, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the tree, this function has no effect. */
-bool tctreeputkeep(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tctreeputkeep(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into a tree object.
@@ -1117,7 +1119,7 @@ bool tctreeputkeep(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, i
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the tree, this function has no effect. */
-bool tctreeputkeep2(TCTREE *tree, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tctreeputkeep2(TCTREE *tree, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the value of the existing record in a tree object.
@@ -1127,7 +1129,7 @@ bool tctreeputkeep2(TCTREE *tree, const char *kstr, const char *vstr);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tctreeputcat(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tctreeputcat(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string value at the end of the value of the existing record in a tree object.
@@ -1135,7 +1137,7 @@ void tctreeputcat(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, in
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If there is no corresponding record, a new record is created. */
-void tctreeputcat2(TCTREE *tree, const char *kstr, const char *vstr);
+EJDB_EXPORT void tctreeputcat2(TCTREE *tree, const char *kstr, const char *vstr);
 
 
 /* Store a record into a tree object with a duplication handler.
@@ -1155,7 +1157,7 @@ void tctreeputcat2(TCTREE *tree, const char *kstr, const char *vstr);
    `op' specifies an arbitrary pointer to be given as a parameter of the callback function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tctreeputproc(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tctreeputproc(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                    TCPDPROC proc, void *op);
 
 
@@ -1165,7 +1167,7 @@ bool tctreeputproc(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, i
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tctreeout(TCTREE *tree, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tctreeout(TCTREE *tree, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of a tree object.
@@ -1173,7 +1175,7 @@ bool tctreeout(TCTREE *tree, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tctreeout2(TCTREE *tree, const char *kstr);
+EJDB_EXPORT bool tctreeout2(TCTREE *tree, const char *kstr);
 
 
 /* Retrieve a record in a tree object.
@@ -1186,7 +1188,7 @@ bool tctreeout2(TCTREE *tree, const char *kstr);
    corresponding record.  `NULL' is returned when no record corresponds.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-const void *tctreeget(TCTREE *tree, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT const void *tctreeget(TCTREE *tree, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in a tree object.
@@ -1194,13 +1196,13 @@ const void *tctreeget(TCTREE *tree, const void *kbuf, int ksiz, int *sp);
    `kstr' specifies the string of the key.
    If successful, the return value is the string of the value of the corresponding record.
    `NULL' is returned when no record corresponds. */
-const char *tctreeget2(TCTREE *tree, const char *kstr);
+EJDB_EXPORT const char *tctreeget2(TCTREE *tree, const char *kstr);
 
 
 /* Initialize the iterator of a tree object.
    `tree' specifies the tree object.
    The iterator is used in order to access the key of every record stored in the tree object. */
-void tctreeiterinit(TCTREE *tree);
+EJDB_EXPORT void tctreeiterinit(TCTREE *tree);
 
 
 /* Get the next key of the iterator of a tree object.
@@ -1212,7 +1214,7 @@ void tctreeiterinit(TCTREE *tree);
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string.
    The order of iteration is assured to be ascending of the keys. */
-const void *tctreeiternext(TCTREE *tree, int *sp);
+EJDB_EXPORT const void *tctreeiternext(TCTREE *tree, int *sp);
 
 
 /* Get the next key string of the iterator of a tree object.
@@ -1220,19 +1222,19 @@ const void *tctreeiternext(TCTREE *tree, int *sp);
    If successful, the return value is the pointer to the region of the next key, else, it is
    `NULL'.  `NULL' is returned when no record can be fetched from the iterator.
    The order of iteration is assured to be ascending of the keys. */
-const char *tctreeiternext2(TCTREE *tree);
+EJDB_EXPORT const char *tctreeiternext2(TCTREE *tree);
 
 
 /* Get the number of records stored in a tree object.
    `tree' specifies the tree object.
    The return value is the number of the records stored in the tree object. */
-uint64_t tctreernum(const TCTREE *tree);
+EJDB_EXPORT uint64_t tctreernum(const TCTREE *tree);
 
 
 /* Get the total size of memory used in a tree object.
    `tree' specifies the tree object.
    The return value is the total size of memory used in a tree object. */
-uint64_t tctreemsiz(const TCTREE *tree);
+EJDB_EXPORT uint64_t tctreemsiz(const TCTREE *tree);
 
 
 /* Create a list object containing all keys in a tree object.
@@ -1240,7 +1242,7 @@ uint64_t tctreemsiz(const TCTREE *tree);
    The return value is the new list object containing all keys in the tree object.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tctreekeys(const TCTREE *tree);
+EJDB_EXPORT TCLIST *tctreekeys(const TCTREE *tree);
 
 
 /* Create a list object containing all values in a tree object.
@@ -1248,7 +1250,7 @@ TCLIST *tctreekeys(const TCTREE *tree);
    The return value is the new list object containing all values in the tree object.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tctreevals(const TCTREE *tree);
+EJDB_EXPORT TCLIST *tctreevals(const TCTREE *tree);
 
 
 /* Add an integer to a record in a tree object.
@@ -1259,7 +1261,7 @@ TCLIST *tctreevals(const TCTREE *tree);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tctreeaddint(TCTREE *tree, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tctreeaddint(TCTREE *tree, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in a tree object.
@@ -1270,19 +1272,19 @@ int tctreeaddint(TCTREE *tree, const void *kbuf, int ksiz, int num);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tctreeadddouble(TCTREE *tree, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tctreeadddouble(TCTREE *tree, const void *kbuf, int ksiz, double num);
 
 
 /* Clear a tree object.
    `tree' specifies the tree object.
    All records are removed. */
-void tctreeclear(TCTREE *tree);
+EJDB_EXPORT void tctreeclear(TCTREE *tree);
 
 
 /* Remove fringe records of a tree object.
    `tree' specifies the tree object.
    `num' specifies the number of records to be removed. */
-void tctreecutfringe(TCTREE *tree, int num);
+EJDB_EXPORT void tctreecutfringe(TCTREE *tree, int num);
 
 
 /* Serialize a tree object into a byte array.
@@ -1292,7 +1294,7 @@ void tctreecutfringe(TCTREE *tree, int num);
    The return value is the pointer to the region of the result serial region.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-void *tctreedump(const TCTREE *tree, int *sp);
+EJDB_EXPORT void *tctreedump(const TCTREE *tree, int *sp);
 
 
 /* Create a tree object from a serialized byte array.
@@ -1304,7 +1306,7 @@ void *tctreedump(const TCTREE *tree, int *sp);
    The return value is a new tree object.
    Because the object of the return value is created with the function `tctreenew', it should be
    deleted with the function `tctreedel' when it is no longer in use. */
-TCTREE *tctreeload(const void *ptr, int size, TCCMP cmp, void *cmpop);
+EJDB_EXPORT TCTREE *tctreeload(const void *ptr, int size, TCCMP cmp, void *cmpop);
 
 
 
@@ -1321,7 +1323,7 @@ TCTREE *tctreeload(const void *ptr, int size, TCCMP cmp, void *cmpop);
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the tree, it is overwritten.  The structure of the
    tree is not modifed by this function. */
-void tctreeput3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tctreeput3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new record into a tree object without balancing nodes.
@@ -1333,7 +1335,7 @@ void tctreeput3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the tree, this function has no effect.  The structure
    of the tree is not modifed by this function. */
-bool tctreeputkeep3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tctreeputkeep3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a value at the existing record in a tree object without balancing nodes.
@@ -1344,7 +1346,7 @@ bool tctreeputkeep3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf,
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created.  The structure of the tree is
    not modifed by this function. */
-void tctreeputcat3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tctreeputcat3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Retrieve a record in a tree object without balancing nodes.
@@ -1358,7 +1360,7 @@ void tctreeputcat3(TCTREE *tree, const void *kbuf, int ksiz, const void *vbuf, i
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string.  The structure of the tree is not
    modifed by this function. */
-const void *tctreeget3(const TCTREE *tree, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT const void *tctreeget3(const TCTREE *tree, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in a tree object with specifying the default value string.
@@ -1367,7 +1369,7 @@ const void *tctreeget3(const TCTREE *tree, const void *kbuf, int ksiz, int *sp);
    `dstr' specifies the string of the default value.
    The return value is the string of the value of the corresponding record or the default value
    string. */
-const char *tctreeget4(TCTREE *tree, const char *kstr, const char *dstr);
+EJDB_EXPORT const char *tctreeget4(TCTREE *tree, const char *kstr, const char *dstr);
 
 
 /* Initialize the iterator of a tree object in front of records corresponding a key.
@@ -1376,7 +1378,7 @@ const char *tctreeget4(TCTREE *tree, const char *kstr, const char *dstr);
    `ksiz' specifies the size of the region of the key.
    The iterator is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-void tctreeiterinit2(TCTREE *tree, const void *kbuf, int ksiz);
+EJDB_EXPORT void tctreeiterinit2(TCTREE *tree, const void *kbuf, int ksiz);
 
 
 /* Initialize the iterator of a tree object in front of records corresponding a key string.
@@ -1384,7 +1386,7 @@ void tctreeiterinit2(TCTREE *tree, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    The iterator is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-void tctreeiterinit3(TCTREE *tree, const char *kstr);
+EJDB_EXPORT void tctreeiterinit3(TCTREE *tree, const char *kstr);
 
 
 /* Get the value bound to the key fetched from the iterator of a tree object.
@@ -1394,13 +1396,13 @@ void tctreeiterinit3(TCTREE *tree, const char *kstr);
    The return value is the pointer to the region of the value of the corresponding record.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-const void *tctreeiterval(const void *kbuf, int *sp);
+EJDB_EXPORT const void *tctreeiterval(const void *kbuf, int *sp);
 
 
 /* Get the value string bound to the key fetched from the iterator of a tree object.
    `kstr' specifies the string of the iteration key.
    The return value is the pointer to the region of the value of the corresponding record. */
-const char *tctreeiterval2(const char *kstr);
+EJDB_EXPORT const char *tctreeiterval2(const char *kstr);
 
 
 /* Create an array of strings of all keys in a tree object.
@@ -1411,7 +1413,7 @@ const char *tctreeiterval2(const char *kstr);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use.  Note that elements of the array
    point to the inner objects, whose life duration is synchronous with the tree object. */
-const char **tctreekeys2(const TCTREE *tree, int *np);
+EJDB_EXPORT const char **tctreekeys2(const TCTREE *tree, int *np);
 
 
 /* Create an array of strings of all values in a tree object.
@@ -1422,7 +1424,7 @@ const char **tctreekeys2(const TCTREE *tree, int *np);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use.  Note that elements of the array
    point to the inner objects, whose life duration is synchronous with the tree object. */
-const char **tctreevals2(const TCTREE *tree, int *np);
+EJDB_EXPORT const char **tctreevals2(const TCTREE *tree, int *np);
 
 
 /* Extract a tree record from a serialized byte array.
@@ -1436,7 +1438,7 @@ const char **tctreevals2(const TCTREE *tree, int *np);
    corresponding record.  `NULL' is returned when no record corresponds.
    Because an additional zero code is appended at the end of the region of the return value,
    the return value can be treated as a character string. */
-void *tctreeloadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tctreeloadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp);
 
 
 /* Perform formatted output into a tree object.
@@ -1448,7 +1450,7 @@ void *tctreeloadone(const void *ptr, int size, const void *kbuf, int ksiz, int *
    with `s' but escapes meta characters of URL.  `b' converts an integer to the string as binary
    numbers.  The other conversion character work as with each original.
    The other arguments are used according to the format string. */
-void tctreeprintf(TCTREE *tree, const char *kstr, const char *format, ...);
+EJDB_EXPORT void tctreeprintf(TCTREE *tree, const char *kstr, const char *format, ...);
 
 
 
@@ -1468,19 +1470,19 @@ typedef struct {                         /* type of structure for a on-memory ha
 /* Create an on-memory hash database object.
    The return value is the new on-memory hash database object.
    The object can be shared by plural threads because of the internal mutex. */
-TCMDB *tcmdbnew(void);
+EJDB_EXPORT TCMDB *tcmdbnew(void);
 
 
 /* Create an on-memory hash database object with specifying the number of the buckets.
    `bnum' specifies the number of the buckets.
    The return value is the new on-memory hash database object.
    The object can be shared by plural threads because of the internal mutex. */
-TCMDB *tcmdbnew2(uint32_t bnum);
+EJDB_EXPORT TCMDB *tcmdbnew2(uint32_t bnum);
 
 
 /* Delete an on-memory hash database object.
    `mdb' specifies the on-memory hash database object. */
-void tcmdbdel(TCMDB *mdb);
+EJDB_EXPORT void tcmdbdel(TCMDB *mdb);
 
 
 /* Store a record into an on-memory hash database object.
@@ -1490,7 +1492,7 @@ void tcmdbdel(TCMDB *mdb);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into an on-memory hash database object.
@@ -1498,7 +1500,7 @@ void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput2(TCMDB *mdb, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcmdbput2(TCMDB *mdb, const char *kstr, const char *vstr);
 
 
 /* Store a new record into an on-memory hash database object.
@@ -1509,7 +1511,7 @@ void tcmdbput2(TCMDB *mdb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcmdbputkeep(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcmdbputkeep(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into an on-memory hash database object.
@@ -1518,7 +1520,7 @@ bool tcmdbputkeep(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcmdbputkeep2(TCMDB *mdb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcmdbputkeep2(TCMDB *mdb, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the existing record in an on-memory hash database.
@@ -1528,7 +1530,7 @@ bool tcmdbputkeep2(TCMDB *mdb, const char *kstr, const char *vstr);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tcmdbputcat(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmdbputcat(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string at the end of the existing record in an on-memory hash database.
@@ -1536,7 +1538,7 @@ void tcmdbputcat(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int v
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If there is no corresponding record, a new record is created. */
-void tcmdbputcat2(TCMDB *mdb, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcmdbputcat2(TCMDB *mdb, const char *kstr, const char *vstr);
 
 
 /* Remove a record of an on-memory hash database object.
@@ -1545,7 +1547,7 @@ void tcmdbputcat2(TCMDB *mdb, const char *kstr, const char *vstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmdbout(TCMDB *mdb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcmdbout(TCMDB *mdb, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of an on-memory hash database object.
@@ -1553,7 +1555,7 @@ bool tcmdbout(TCMDB *mdb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcmdbout2(TCMDB *mdb, const char *kstr);
+EJDB_EXPORT bool tcmdbout2(TCMDB *mdb, const char *kstr);
 
 
 /* Retrieve a record in an on-memory hash database object.
@@ -1568,7 +1570,7 @@ bool tcmdbout2(TCMDB *mdb, const char *kstr);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in an on-memory hash database object.
@@ -1578,7 +1580,7 @@ void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
    `NULL' is returned when no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcmdbget2(TCMDB *mdb, const char *kstr);
+EJDB_EXPORT char *tcmdbget2(TCMDB *mdb, const char *kstr);
 
 
 /* Get the size of the value of a record in an on-memory hash database object.
@@ -1587,7 +1589,7 @@ char *tcmdbget2(TCMDB *mdb, const char *kstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcmdbvsiz(TCMDB *mdb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tcmdbvsiz(TCMDB *mdb, const void *kbuf, int ksiz);
 
 
 /* Get the size of the value of a string record in an on-memory hash database object.
@@ -1595,14 +1597,14 @@ int tcmdbvsiz(TCMDB *mdb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcmdbvsiz2(TCMDB *mdb, const char *kstr);
+EJDB_EXPORT int tcmdbvsiz2(TCMDB *mdb, const char *kstr);
 
 
 /* Initialize the iterator of an on-memory hash database object.
    `mdb' specifies the on-memory hash database object.
    The iterator is used in order to access the key of every record stored in the on-memory
    database. */
-void tcmdbiterinit(TCMDB *mdb);
+EJDB_EXPORT void tcmdbiterinit(TCMDB *mdb);
 
 
 /* Get the next key of the iterator of an on-memory hash database object.
@@ -1616,7 +1618,7 @@ void tcmdbiterinit(TCMDB *mdb);
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use.  The order of iteration is assured to be the same as the stored
    order. */
-void *tcmdbiternext(TCMDB *mdb, int *sp);
+EJDB_EXPORT void *tcmdbiternext(TCMDB *mdb, int *sp);
 
 
 /* Get the next key string of the iterator of an on-memory hash database object.
@@ -1626,7 +1628,7 @@ void *tcmdbiternext(TCMDB *mdb, int *sp);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  The order of iteration is assured
    to be the same as the stored order. */
-char *tcmdbiternext2(TCMDB *mdb);
+EJDB_EXPORT char *tcmdbiternext2(TCMDB *mdb);
 
 
 /* Get forward matching keys in an on-memory hash database object.
@@ -1640,7 +1642,7 @@ char *tcmdbiternext2(TCMDB *mdb);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tcmdbfwmkeys(TCMDB *mdb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tcmdbfwmkeys(TCMDB *mdb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string keys in an on-memory hash database object.
@@ -1653,19 +1655,19 @@ TCLIST *tcmdbfwmkeys(TCMDB *mdb, const void *pbuf, int psiz, int max);
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use.  Note that this function
    may be very slow because every key in the database is scanned. */
-TCLIST *tcmdbfwmkeys2(TCMDB *mdb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tcmdbfwmkeys2(TCMDB *mdb, const char *pstr, int max);
 
 
 /* Get the number of records stored in an on-memory hash database object.
    `mdb' specifies the on-memory hash database object.
    The return value is the number of the records stored in the database. */
-uint64_t tcmdbrnum(TCMDB *mdb);
+EJDB_EXPORT uint64_t tcmdbrnum(TCMDB *mdb);
 
 
 /* Get the total size of memory used in an on-memory hash database object.
    `mdb' specifies the on-memory hash database object.
    The return value is the total size of memory used in the database. */
-uint64_t tcmdbmsiz(TCMDB *mdb);
+EJDB_EXPORT uint64_t tcmdbmsiz(TCMDB *mdb);
 
 
 /* Add an integer to a record in an on-memory hash database object.
@@ -1676,7 +1678,7 @@ uint64_t tcmdbmsiz(TCMDB *mdb);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tcmdbaddint(TCMDB *mdb, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tcmdbaddint(TCMDB *mdb, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in an on-memory hash database object.
@@ -1687,19 +1689,19 @@ int tcmdbaddint(TCMDB *mdb, const void *kbuf, int ksiz, int num);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tcmdbadddouble(TCMDB *mdb, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tcmdbadddouble(TCMDB *mdb, const void *kbuf, int ksiz, double num);
 
 
 /* Clear an on-memory hash database object.
    `mdb' specifies the on-memory hash database object.
    All records are removed. */
-void tcmdbvanish(TCMDB *mdb);
+EJDB_EXPORT void tcmdbvanish(TCMDB *mdb);
 
 
 /* Remove front records of an on-memory hash database object.
    `mdb' specifies the on-memory hash database object.
    `num' specifies the number of records to be removed. */
-void tcmdbcutfront(TCMDB *mdb, int num);
+EJDB_EXPORT void tcmdbcutfront(TCMDB *mdb, int num);
 
 
 
@@ -1716,7 +1718,7 @@ void tcmdbcutfront(TCMDB *mdb, int num);
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the map, it is overwritten.  The record is moved to
    the tail. */
-void tcmdbput3(TCMDB *mdb, const void *kbuf, int ksiz, const char *vbuf, int vsiz);
+EJDB_EXPORT void tcmdbput3(TCMDB *mdb, const void *kbuf, int ksiz, const char *vbuf, int vsiz);
 
 
 /* Store a record of the value of two regions into an on-memory hash database object.
@@ -1728,7 +1730,7 @@ void tcmdbput3(TCMDB *mdb, const void *kbuf, int ksiz, const char *vbuf, int vsi
    `lvbuf' specifies the pointer to the latter region of the value.
    `lvsiz' specifies the size of the latter region of the value.
    If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput4(TCMDB *mdb, const void *kbuf, int ksiz,
+EJDB_EXPORT void tcmdbput4(TCMDB *mdb, const void *kbuf, int ksiz,
                const void *fvbuf, int fvsiz, const void *lvbuf, int lvsiz);
 
 
@@ -1739,7 +1741,7 @@ void tcmdbput4(TCMDB *mdb, const void *kbuf, int ksiz,
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tcmdbputcat3(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcmdbputcat3(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a record into a on-memory hash database object with a duplication handler.
@@ -1759,7 +1761,7 @@ void tcmdbputcat3(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int
    `op' specifies an arbitrary pointer to be given as a parameter of the callback function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tcmdbputproc(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tcmdbputproc(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -1776,7 +1778,7 @@ bool tcmdbputproc(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int
    is allocated with the `malloc' call, it should be released with the `free' call when it is no
    longer in use.  The internal region of the returned record is moved to the tail so that the
    record will survive for a time under LRU cache algorithm removing records from the head. */
-void *tcmdbget3(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcmdbget3(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Initialize the iterator of an on-memory map database object in front of a key.
@@ -1784,14 +1786,14 @@ void *tcmdbget3(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
    `kbuf' specifies the pointer to the region of the key.
    `ksiz' specifies the size of the region of the key.
    If there is no record corresponding the condition, the iterator is not modified. */
-void tcmdbiterinit2(TCMDB *mdb, const void *kbuf, int ksiz);
+EJDB_EXPORT void tcmdbiterinit2(TCMDB *mdb, const void *kbuf, int ksiz);
 
 
 /* Initialize the iterator of an on-memory map database object in front of a key string.
    `mdb' specifies the on-memory map database object.
    `kstr' specifies the string of the key.
    If there is no record corresponding the condition, the iterator is not modified. */
-void tcmdbiterinit3(TCMDB *mdb, const char *kstr);
+EJDB_EXPORT void tcmdbiterinit3(TCMDB *mdb, const char *kstr);
 
 
 /* Process each record atomically of an on-memory hash database object.
@@ -1803,7 +1805,7 @@ void tcmdbiterinit3(TCMDB *mdb, const char *kstr);
    or false to stop iteration.
    `op' specifies an arbitrary pointer to be given as a parameter of the iterator function.  If
    it is not needed, `NULL' can be specified. */
-void tcmdbforeach(TCMDB *mdb, TCITER iter, void *op);
+EJDB_EXPORT void tcmdbforeach(TCMDB *mdb, TCITER iter, void *op);
 
 
 
@@ -1821,7 +1823,7 @@ typedef struct {                         /* type of structure for a on-memory tr
 /* Create an on-memory tree database object.
    The return value is the new on-memory tree database object.
    The object can be shared by plural threads because of the internal mutex. */
-TCNDB *tcndbnew(void);
+EJDB_EXPORT TCNDB *tcndbnew(void);
 
 
 /* Create an on-memory tree database object with specifying the custom comparison function.
@@ -1832,12 +1834,12 @@ TCNDB *tcndbnew(void);
    The default comparison function compares keys of two records by lexical order.  The functions
    `tccmplexical' (dafault), `tccmpdecimal', `tccmpint32', and `tccmpint64' are built-in.  The
    object can be shared by plural threads because of the internal mutex. */
-TCNDB *tcndbnew2(TCCMP cmp, void *cmpop);
+EJDB_EXPORT TCNDB *tcndbnew2(TCCMP cmp, void *cmpop);
 
 
 /* Delete an on-memory tree database object.
    `ndb' specifies the on-memory tree database object. */
-void tcndbdel(TCNDB *ndb);
+EJDB_EXPORT void tcndbdel(TCNDB *ndb);
 
 
 /* Store a record into an on-memory tree database object.
@@ -1847,7 +1849,7 @@ void tcndbdel(TCNDB *ndb);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the database, it is overwritten. */
-void tcndbput(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcndbput(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a string record into an on-memory tree database object.
@@ -1855,7 +1857,7 @@ void tcndbput(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If a record with the same key exists in the database, it is overwritten. */
-void tcndbput2(TCNDB *ndb, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcndbput2(TCNDB *ndb, const char *kstr, const char *vstr);
 
 
 /* Store a new record into an on-memory tree database object.
@@ -1866,7 +1868,7 @@ void tcndbput2(TCNDB *ndb, const char *kstr, const char *vstr);
    `vsiz' specifies the size of the region of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcndbputkeep(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcndbputkeep(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new string record into an on-memory tree database object.
@@ -1875,7 +1877,7 @@ bool tcndbputkeep(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int
    `vstr' specifies the string of the value.
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect. */
-bool tcndbputkeep2(TCNDB *ndb, const char *kstr, const char *vstr);
+EJDB_EXPORT bool tcndbputkeep2(TCNDB *ndb, const char *kstr, const char *vstr);
 
 
 /* Concatenate a value at the end of the existing record in an on-memory tree database.
@@ -1885,7 +1887,7 @@ bool tcndbputkeep2(TCNDB *ndb, const char *kstr, const char *vstr);
    `vbuf' specifies the pointer to the region of the value.
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created. */
-void tcndbputcat(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcndbputcat(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a string at the end of the existing record in an on-memory tree database.
@@ -1893,7 +1895,7 @@ void tcndbputcat(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int v
    `kstr' specifies the string of the key.
    `vstr' specifies the string of the value.
    If there is no corresponding record, a new record is created. */
-void tcndbputcat2(TCNDB *ndb, const char *kstr, const char *vstr);
+EJDB_EXPORT void tcndbputcat2(TCNDB *ndb, const char *kstr, const char *vstr);
 
 
 /* Remove a record of an on-memory tree database object.
@@ -1902,7 +1904,7 @@ void tcndbputcat2(TCNDB *ndb, const char *kstr, const char *vstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcndbout(TCNDB *ndb, const void *kbuf, int ksiz);
+EJDB_EXPORT bool tcndbout(TCNDB *ndb, const void *kbuf, int ksiz);
 
 
 /* Remove a string record of an on-memory tree database object.
@@ -1910,7 +1912,7 @@ bool tcndbout(TCNDB *ndb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is true.  False is returned when no record corresponds to
    the specified key. */
-bool tcndbout2(TCNDB *ndb, const char *kstr);
+EJDB_EXPORT bool tcndbout2(TCNDB *ndb, const char *kstr);
 
 
 /* Retrieve a record in an on-memory tree database object.
@@ -1925,7 +1927,7 @@ bool tcndbout2(TCNDB *ndb, const char *kstr);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-void *tcndbget(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcndbget(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Retrieve a string record in an on-memory tree database object.
@@ -1935,7 +1937,7 @@ void *tcndbget(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
    `NULL' is returned when no record corresponds.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcndbget2(TCNDB *ndb, const char *kstr);
+EJDB_EXPORT char *tcndbget2(TCNDB *ndb, const char *kstr);
 
 
 /* Get the size of the value of a record in an on-memory tree database object.
@@ -1944,7 +1946,7 @@ char *tcndbget2(TCNDB *ndb, const char *kstr);
    `ksiz' specifies the size of the region of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcndbvsiz(TCNDB *ndb, const void *kbuf, int ksiz);
+EJDB_EXPORT int tcndbvsiz(TCNDB *ndb, const void *kbuf, int ksiz);
 
 
 /* Get the size of the value of a string record in an on-memory tree database object.
@@ -1952,14 +1954,14 @@ int tcndbvsiz(TCNDB *ndb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    If successful, the return value is the size of the value of the corresponding record, else,
    it is -1. */
-int tcndbvsiz2(TCNDB *ndb, const char *kstr);
+EJDB_EXPORT int tcndbvsiz2(TCNDB *ndb, const char *kstr);
 
 
 /* Initialize the iterator of an on-memory tree database object.
    `ndb' specifies the on-memory tree database object.
    The iterator is used in order to access the key of every record stored in the on-memory
    database. */
-void tcndbiterinit(TCNDB *ndb);
+EJDB_EXPORT void tcndbiterinit(TCNDB *ndb);
 
 
 /* Get the next key of the iterator of an on-memory tree database object.
@@ -1973,7 +1975,7 @@ void tcndbiterinit(TCNDB *ndb);
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use.  The order of iteration is assured to be the same as the stored
    order. */
-void *tcndbiternext(TCNDB *ndb, int *sp);
+EJDB_EXPORT void *tcndbiternext(TCNDB *ndb, int *sp);
 
 
 /* Get the next key string of the iterator of an on-memory tree database object.
@@ -1983,7 +1985,7 @@ void *tcndbiternext(TCNDB *ndb, int *sp);
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use.  The order of iteration is assured
    to be the same as the stored order. */
-char *tcndbiternext2(TCNDB *ndb);
+EJDB_EXPORT char *tcndbiternext2(TCNDB *ndb);
 
 
 /* Get forward matching keys in an on-memory tree database object.
@@ -1996,7 +1998,7 @@ char *tcndbiternext2(TCNDB *ndb);
    It returns an empty list even if no key corresponds.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcndbfwmkeys(TCNDB *ndb, const void *pbuf, int psiz, int max);
+EJDB_EXPORT TCLIST *tcndbfwmkeys(TCNDB *ndb, const void *pbuf, int psiz, int max);
 
 
 /* Get forward matching string keys in an on-memory tree database object.
@@ -2008,19 +2010,19 @@ TCLIST *tcndbfwmkeys(TCNDB *ndb, const void *pbuf, int psiz, int max);
    It returns an empty list even if no key corresponds.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcndbfwmkeys2(TCNDB *ndb, const char *pstr, int max);
+EJDB_EXPORT TCLIST *tcndbfwmkeys2(TCNDB *ndb, const char *pstr, int max);
 
 
 /* Get the number of records stored in an on-memory tree database object.
    `ndb' specifies the on-memory tree database object.
    The return value is the number of the records stored in the database. */
-uint64_t tcndbrnum(TCNDB *ndb);
+EJDB_EXPORT uint64_t tcndbrnum(TCNDB *ndb);
 
 
 /* Get the total size of memory used in an on-memory tree database object.
    `ndb' specifies the on-memory tree database object.
    The return value is the total size of memory used in the database. */
-uint64_t tcndbmsiz(TCNDB *ndb);
+EJDB_EXPORT uint64_t tcndbmsiz(TCNDB *ndb);
 
 
 /* Add an integer to a record in an on-memory tree database object.
@@ -2031,7 +2033,7 @@ uint64_t tcndbmsiz(TCNDB *ndb);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as an integer and is added to.  If no
    record corresponds, a new record of the additional value is stored. */
-int tcndbaddint(TCNDB *ndb, const void *kbuf, int ksiz, int num);
+EJDB_EXPORT int tcndbaddint(TCNDB *ndb, const void *kbuf, int ksiz, int num);
 
 
 /* Add a real number to a record in an on-memory tree database object.
@@ -2042,19 +2044,19 @@ int tcndbaddint(TCNDB *ndb, const void *kbuf, int ksiz, int num);
    The return value is the summation value.
    If the corresponding record exists, the value is treated as a real number and is added to.  If
    no record corresponds, a new record of the additional value is stored. */
-double tcndbadddouble(TCNDB *ndb, const void *kbuf, int ksiz, double num);
+EJDB_EXPORT double tcndbadddouble(TCNDB *ndb, const void *kbuf, int ksiz, double num);
 
 
 /* Clear an on-memory tree database object.
    `ndb' specifies the on-memory tree database object.
    All records are removed. */
-void tcndbvanish(TCNDB *ndb);
+EJDB_EXPORT void tcndbvanish(TCNDB *ndb);
 
 
 /* Remove fringe records of an on-memory tree database object.
    `ndb' specifies the on-memory tree database object.
    `num' specifies the number of records to be removed. */
-void tcndbcutfringe(TCNDB *ndb, int num);
+EJDB_EXPORT void tcndbcutfringe(TCNDB *ndb, int num);
 
 
 
@@ -2071,7 +2073,7 @@ void tcndbcutfringe(TCNDB *ndb, int num);
    `vsiz' specifies the size of the region of the value.
    If a record with the same key exists in the database, it is overwritten.  The structure of the
    tree is not modifed by this function. */
-void tcndbput3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcndbput3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a new record into a on-memory tree database object without balancing nodes.
@@ -2083,7 +2085,7 @@ void tcndbput3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsi
    If successful, the return value is true, else, it is false.
    If a record with the same key exists in the database, this function has no effect.  The
    structure of the tree is not modifed by this function. */
-bool tcndbputkeep3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT bool tcndbputkeep3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Concatenate a value in a on-memory tree database without balancing nodes.
@@ -2094,7 +2096,7 @@ bool tcndbputkeep3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int
    `vsiz' specifies the size of the region of the value.
    If there is no corresponding record, a new record is created.  The structure of the tree is
    not modifed by this function. */
-void tcndbputcat3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
+EJDB_EXPORT void tcndbputcat3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
 
 
 /* Store a record into a on-memory tree database object with a duplication handler.
@@ -2114,7 +2116,7 @@ void tcndbputcat3(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int
    `op' specifies an arbitrary pointer to be given as a parameter of the callback function.  If
    it is not needed, `NULL' can be specified.
    If successful, the return value is true, else, it is false. */
-bool tcndbputproc(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+EJDB_EXPORT bool tcndbputproc(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
                   TCPDPROC proc, void *op);
 
 
@@ -2130,7 +2132,7 @@ bool tcndbputproc(TCNDB *ndb, const void *kbuf, int ksiz, const void *vbuf, int
    the return value can be treated as a character string.  Because the region of the return value
    is allocated with the `malloc' call, it should be released with the `free' call when it is no
    longer in use.  The structure of the tree is not modifed by this function. */
-void *tcndbget3(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
+EJDB_EXPORT void *tcndbget3(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
 
 
 /* Initialize the iterator of an on-memory tree database object in front of a key.
@@ -2139,7 +2141,7 @@ void *tcndbget3(TCNDB *ndb, const void *kbuf, int ksiz, int *sp);
    `ksiz' specifies the size of the region of the key.
    The iterator is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-void tcndbiterinit2(TCNDB *ndb, const void *kbuf, int ksiz);
+EJDB_EXPORT void tcndbiterinit2(TCNDB *ndb, const void *kbuf, int ksiz);
 
 
 /* Initialize the iterator of an on-memory tree database object in front of a key string.
@@ -2147,7 +2149,7 @@ void tcndbiterinit2(TCNDB *ndb, const void *kbuf, int ksiz);
    `kstr' specifies the string of the key.
    The iterator is set to the first record corresponding the key or the next substitute if
    completely matching record does not exist. */
-void tcndbiterinit3(TCNDB *ndb, const char *kstr);
+EJDB_EXPORT void tcndbiterinit3(TCNDB *ndb, const char *kstr);
 
 
 /* Process each record atomically of an on-memory tree database object.
@@ -2159,7 +2161,7 @@ void tcndbiterinit3(TCNDB *ndb, const char *kstr);
    or false to stop iteration.
    `op' specifies an arbitrary pointer to be given as a parameter of the iterator function.  If
    it is not needed, `NULL' can be specified. */
-void tcndbforeach(TCNDB *ndb, TCITER iter, void *op);
+EJDB_EXPORT void tcndbforeach(TCNDB *ndb, TCITER iter, void *op);
 
 
 
@@ -2183,13 +2185,13 @@ typedef struct {                         /* type of structure for a memory pool
 
 /* Create a memory pool object.
    The return value is the new memory pool object. */
-TCMPOOL *tcmpoolnew(void);
+EJDB_EXPORT TCMPOOL *tcmpoolnew(void);
 
 
 /* Delete a memory pool object.
    `mpool' specifies the memory pool object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tcmpooldel(TCMPOOL *mpool);
+EJDB_EXPORT void tcmpooldel(TCMPOOL *mpool);
 
 
 /* Relegate an arbitrary object to a memory pool object.
@@ -2200,7 +2202,7 @@ void tcmpooldel(TCMPOOL *mpool);
    The return value is the pointer to the given object.
    This function assures that the specified object is deleted when the memory pool object is
    deleted. */
-void *tcmpoolpush(TCMPOOL *mpool, void *ptr, void (*del)(void *));
+EJDB_EXPORT void *tcmpoolpush(TCMPOOL *mpool, void *ptr, void (*del)(void *));
 
 
 /* Relegate an allocated region to a memory pool object.
@@ -2210,7 +2212,7 @@ void *tcmpoolpush(TCMPOOL *mpool, void *ptr, void (*del)(void *));
    The return value is the pointer to the given object.
    This function assures that the specified region is released when the memory pool object is
    deleted. */
-void *tcmpoolpushptr(TCMPOOL *mpool, void *ptr);
+EJDB_EXPORT void *tcmpoolpushptr(TCMPOOL *mpool, void *ptr);
 
 
 /* Relegate an extensible string object to a memory pool object.
@@ -2219,7 +2221,7 @@ void *tcmpoolpushptr(TCMPOOL *mpool, void *ptr);
    The return value is the pointer to the given object.
    This function assures that the specified object is deleted when the memory pool object is
    deleted. */
-TCXSTR *tcmpoolpushxstr(TCMPOOL *mpool, TCXSTR *xstr);
+EJDB_EXPORT TCXSTR *tcmpoolpushxstr(TCMPOOL *mpool, TCXSTR *xstr);
 
 
 /* Relegate a list object to a memory pool object.
@@ -2228,7 +2230,7 @@ TCXSTR *tcmpoolpushxstr(TCMPOOL *mpool, TCXSTR *xstr);
    The return value is the pointer to the given object.
    This function assures that the specified object is deleted when the memory pool object is
    deleted. */
-TCLIST *tcmpoolpushlist(TCMPOOL *mpool, TCLIST *list);
+EJDB_EXPORT TCLIST *tcmpoolpushlist(TCMPOOL *mpool, TCLIST *list);
 
 
 /* Relegate a map object to a memory pool object.
@@ -2237,7 +2239,7 @@ TCLIST *tcmpoolpushlist(TCMPOOL *mpool, TCLIST *list);
    The return value is the pointer to the given object.
    This function assures that the specified object is deleted when the memory pool object is
    deleted. */
-TCMAP *tcmpoolpushmap(TCMPOOL *mpool, TCMAP *map);
+EJDB_EXPORT TCMAP *tcmpoolpushmap(TCMPOOL *mpool, TCMAP *map);
 
 
 /* Relegate a tree object to a memory pool object.
@@ -2246,52 +2248,52 @@ TCMAP *tcmpoolpushmap(TCMPOOL *mpool, TCMAP *map);
    The return value is the pointer to the given object.
    This function assures that the specified object is deleted when the memory pool object is
    deleted. */
-TCTREE *tcmpoolpushtree(TCMPOOL *mpool, TCTREE *tree);
+EJDB_EXPORT TCTREE *tcmpoolpushtree(TCMPOOL *mpool, TCTREE *tree);
 
 
 /* Allocate a region relegated to a memory pool object.
    `mpool' specifies the memory pool object.
    The return value is the pointer to the allocated region under the memory pool. */
-void *tcmpoolmalloc(TCMPOOL *mpool, size_t size);
+EJDB_EXPORT void *tcmpoolmalloc(TCMPOOL *mpool, size_t size);
 
 
 /* Create an extensible string object relegated to a memory pool object.
    The return value is the new extensible string object under the memory pool. */
-TCXSTR *tcmpoolxstrnew(TCMPOOL *mpool);
+EJDB_EXPORT TCXSTR *tcmpoolxstrnew(TCMPOOL *mpool);
 
 
 /* Create a list object relegated to a memory pool object.
    The return value is the new list object under the memory pool. */
-TCLIST *tcmpoollistnew(TCMPOOL *mpool);
+EJDB_EXPORT TCLIST *tcmpoollistnew(TCMPOOL *mpool);
 
 
 /* Create a map object relegated to a memory pool object.
    The return value is the new map object under the memory pool. */
-TCMAP *tcmpoolmapnew(TCMPOOL *mpool);
+EJDB_EXPORT TCMAP *tcmpoolmapnew(TCMPOOL *mpool);
 
 
 /* Create a tree object relegated to a memory pool object.
    The return value is the new tree object under the memory pool. */
-TCTREE *tcmpooltreenew(TCMPOOL *mpool);
+EJDB_EXPORT TCTREE *tcmpooltreenew(TCMPOOL *mpool);
 
 
 /* Remove the most recently installed cleanup handler of a memory pool object.
    `mpool' specifies the memory pool object.
    `exe' specifies whether to execute the destructor of the removed handler. */
-void tcmpoolpop(TCMPOOL *mpool, bool exe);
+EJDB_EXPORT void tcmpoolpop(TCMPOOL *mpool, bool exe);
 
 
 /* Remove all cleanup handler of a memory pool object.
    `mpool' specifies the memory pool object.
    `exe' specifies whether to execute the destructors of the removed handlers. */
-void tcmpoolclear(TCMPOOL *mpool, bool exe);
+EJDB_EXPORT void tcmpoolclear(TCMPOOL *mpool, bool exe);
 
 
 /* Get the global memory pool object.
    The return value is the global memory pool object.
    The global memory pool object is a singleton and assured to be deleted when the porcess is
    terminating normally. */
-TCMPOOL *tcmpoolglobal(void);
+EJDB_EXPORT TCMPOOL *tcmpoolglobal(void);
 
 
 
@@ -2304,28 +2306,28 @@ TCMPOOL *tcmpoolglobal(void);
    `a' specifies an integer.
    `b' specifies the other integer.
    The return value is the larger value of the two. */
-long tclmax(long a, long b);
+EJDB_EXPORT long tclmax(long a, long b);
 
 
 /* Get the lesser value of two integers.
    `a' specifies an integer.
    `b' specifies the other integer.
    The return value is the lesser value of the two. */
-long tclmin(long a, long b);
+EJDB_EXPORT long tclmin(long a, long b);
 
 
 /* Get a random number as long integer based on uniform distribution.
    The return value is the random number between 0 and `ULONG_MAX'.
    This function uses the random number source device and generates a real random number if
    possible. */
-unsigned long tclrand(void);
+EJDB_EXPORT unsigned long tclrand(void);
 
 
 /* Get a random number as double decimal based on uniform distribution.
    The return value is the random number equal to or greater than 0, and less than 1.0.
    This function uses the random number source device and generates a real random number if
    possible. */
-double tcdrand(void);
+EJDB_EXPORT double tcdrand(void);
 
 
 /* Get a random number as double decimal based on normal distribution.
@@ -2334,7 +2336,7 @@ double tcdrand(void);
    The return value is the random number.
    This function uses the random number source device and generates a real random number if
    possible. */
-double tcdrandnd(double avg, double sd);
+EJDB_EXPORT double tcdrandnd(double avg, double sd);
 
 
 /* Compare two strings with case insensitive evaluation.
@@ -2342,35 +2344,35 @@ double tcdrandnd(double avg, double sd);
    `bstr' specifies of the other string.
    The return value is positive if the former is big, negative if the latter is big, 0 if both
    are equivalent. */
-int tcstricmp(const char *astr, const char *bstr);
+EJDB_EXPORT int tcstricmp(const char *astr, const char *bstr);
 
 
 /* Check whether a string begins with a key.
    `str' specifies the target string.
    `key' specifies the forward matching key string.
    The return value is true if the target string begins with the key, else, it is false. */
-bool tcstrfwm(const char *str, const char *key);
+EJDB_EXPORT bool tcstrfwm(const char *str, const char *key);
 
 
 /* Check whether a string begins with a key with case insensitive evaluation.
    `str' specifies the target string.
    `key' specifies the forward matching key string.
    The return value is true if the target string begins with the key, else, it is false. */
-bool tcstrifwm(const char *str, const char *key);
+EJDB_EXPORT bool tcstrifwm(const char *str, const char *key);
 
 
 /* Check whether a string ends with a key.
    `str' specifies the target string.
    `key' specifies the backward matching key string.
    The return value is true if the target string ends with the key, else, it is false. */
-bool tcstrbwm(const char *str, const char *key);
+EJDB_EXPORT bool tcstrbwm(const char *str, const char *key);
 
 
 /* Check whether a string ends with a key with case insensitive evaluation.
    `str' specifies the target string.
    `key' specifies the backward matching key string.
    The return value is true if the target string ends with the key, else, it is false. */
-bool tcstribwm(const char *str, const char *key);
+EJDB_EXPORT bool tcstribwm(const char *str, const char *key);
 
 
 /* Calculate the edit distance of two strings.
@@ -2378,7 +2380,7 @@ bool tcstribwm(const char *str, const char *key);
    `bstr' specifies of the other string.
    The return value is the edit distance which is known as the Levenshtein distance.  The cost is
    calculated by byte. */
-int tcstrdist(const char *astr, const char *bstr);
+EJDB_EXPORT int tcstrdist(const char *astr, const char *bstr);
 
 
 /* Calculate the edit distance of two UTF-8 strings.
@@ -2386,31 +2388,31 @@ int tcstrdist(const char *astr, const char *bstr);
    `bstr' specifies of the other string.
    The return value is the edit distance which is known as the Levenshtein distance.  The cost is
    calculated by Unicode character. */
-int tcstrdistutf(const char *astr, const char *bstr);
+EJDB_EXPORT int tcstrdistutf(const char *astr, const char *bstr);
 
 
 /* Convert the letters of a string into upper case.
    `str' specifies the string to be converted.
    The return value is the string itself. */
-char *tcstrtoupper(char *str);
+EJDB_EXPORT char *tcstrtoupper(char *str);
 
 
 /* Convert the letters of a string into lower case.
    `str' specifies the string to be converted.
    The return value is the string itself. */
-char *tcstrtolower(char *str);
+EJDB_EXPORT char *tcstrtolower(char *str);
 
 
 /* Cut space characters at head or tail of a string.
    `str' specifies the string to be converted.
    The return value is the string itself. */
-char *tcstrtrim(char *str);
+EJDB_EXPORT char *tcstrtrim(char *str);
 
 
 /* Squeeze space characters in a string and trim it.
    `str' specifies the string to be converted.
    The return value is the string itself. */
-char *tcstrsqzspc(char *str);
+EJDB_EXPORT char *tcstrsqzspc(char *str);
 
 
 /* Substitute characters in a string.
@@ -2419,20 +2421,20 @@ char *tcstrsqzspc(char *str);
    `sstr' specifies the string containing characters to be substituted.
    If the substitute string is shorter then the replacement string, corresponding characters are
    removed. */
-char *tcstrsubchr(char *str, const char *rstr, const char *sstr);
+EJDB_EXPORT char *tcstrsubchr(char *str, const char *rstr, const char *sstr);
 
 
 /* Count the number of characters in a string of UTF-8.
    `str' specifies the string of UTF-8.
    The return value is the number of characters in the string. */
-int tcstrcntutf(const char *str);
+EJDB_EXPORT int tcstrcntutf(const char *str);
 
 
 /* Cut a string of UTF-8 at the specified number of characters.
    `str' specifies the string of UTF-8.
    `num' specifies the number of characters to be kept.
    The return value is the string itself. */
-char *tcstrcututf(char *str, int num);
+EJDB_EXPORT char *tcstrcututf(char *str, int num);
 
 
 /* Convert a UTF-8 string into a UCS-2 array.
@@ -2441,7 +2443,7 @@ char *tcstrcututf(char *str, int num);
    size of the buffer should be sufficient.
    `np' specifies the pointer to a variable into which the number of elements of the result array
    is assigned. */
-void tcstrutftoucs(const char *str, uint16_t *ary, int *np);
+EJDB_EXPORT void tcstrutftoucs(const char *str, uint16_t *ary, int *np);
 
 
 /* Convert a UCS-2 array into a UTF-8 string.
@@ -2450,7 +2452,7 @@ void tcstrutftoucs(const char *str, uint16_t *ary, int *np);
    `str' specifies the pointer to the region into which the result UTF-8 string is written.  The
    size of the buffer should be sufficient.
    The return value is the length of the result string. */
-int tcstrucstoutf(const uint16_t *ary, int num, char *str);
+EJDB_EXPORT int tcstrucstoutf(const uint16_t *ary, int num, char *str);
 
 
 /* Create a list object by splitting a string.
@@ -2460,7 +2462,7 @@ int tcstrucstoutf(const uint16_t *ary, int num, char *str);
    If two delimiters are successive, it is assumed that an empty element is between the two.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcstrsplit(const char *str, const char *delims);
+EJDB_EXPORT TCLIST *tcstrsplit(const char *str, const char *delims);
 
 
 /* Create a string by joining all elements of a list object.
@@ -2469,7 +2471,7 @@ TCLIST *tcstrsplit(const char *str, const char *delims);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcstrjoin(const TCLIST *list, char delim);
+EJDB_EXPORT char *tcstrjoin(const TCLIST *list, char delim);
 
 
 /* Convert a string to an integer.
@@ -2477,7 +2479,7 @@ char *tcstrjoin(const TCLIST *list, char delim);
    The return value is the integer.  If the string does not contain numeric expression, 0 is
    returned.
    This function is equivalent to `atoll' except that it does not depend on the locale. */
-int64_t tcatoi(const char *str);
+EJDB_EXPORT int64_t tcatoi(const char *str);
 
 
 /* Convert a string with a metric prefix to an integer.
@@ -2486,7 +2488,7 @@ int64_t tcatoi(const char *str);
    The return value is the integer.  If the string does not contain numeric expression, 0 is
    returned.  If the integer overflows the domain, `INT64_MAX' or `INT64_MIN' is returned
    according to the sign. */
-int64_t tcatoix(const char *str);
+EJDB_EXPORT int64_t tcatoix(const char *str);
 
 
 /* Convert a string to a real number.
@@ -2494,7 +2496,7 @@ int64_t tcatoix(const char *str);
    The return value is the real number.  If the string does not contain numeric expression, 0.0
    is returned.
    This function is equivalent to `atof' except that it does not depend on the locale. */
-double tcatof(const char *str);
+EJDB_EXPORT double tcatof(const char *str);
 
 
 /**
@@ -2510,7 +2512,7 @@ double tcatof(const char *str);
  * @param precision Number of signs after dot.
  * @return
  */
-int tcftoa(long double f, char *buf, int max, int precision);
+EJDB_EXPORT int tcftoa(long double f, char *buf, int max, int precision);
 
 
 /* Check whether a string matches a regular expression.
@@ -2518,7 +2520,7 @@ int tcftoa(long double f, char *buf, int max, int precision);
    `regex' specifies the regular expression string.  If it begins with `*', the trailing
    substring is used as a case-insensitive regular expression.
    The return value is true if matching is success, else, it is false. */
-bool tcregexmatch(const char *str, const char *regex);
+EJDB_EXPORT bool tcregexmatch(const char *str, const char *regex);
 
 
 /* Replace each substring matching a regular expression string.
@@ -2533,7 +2535,7 @@ bool tcregexmatch(const char *str, const char *regex);
    of the original string is returned.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcregexreplace(const char *str, const char *regex, const char *alt);
+EJDB_EXPORT char *tcregexreplace(const char *str, const char *regex, const char *alt);
 
 
 /* Get the MD5 hash value of a serial object.
@@ -2541,7 +2543,7 @@ char *tcregexreplace(const char *str, const char *regex, const char *alt);
    `size' specifies the size of the region.
    `buf' specifies the pointer to the region into which the result string is written.  The size
    of the buffer should be equal to or more than 48 bytes. */
-void tcmd5hash(const void *ptr, int size, char *buf);
+EJDB_EXPORT void tcmd5hash(const void *ptr, int size, char *buf);
 
 
 /* Cipher or decipher a serial object with the Arcfour stream cipher.
@@ -2551,16 +2553,16 @@ void tcmd5hash(const void *ptr, int size, char *buf);
    `ksiz' specifies the size of the region of the cipher key.
    `obuf' specifies the pointer to the region into which the result data is written.  The size
    of the buffer should be equal to or more than the input region. */
-void tcarccipher(const void *ptr, int size, const void *kbuf, int ksiz, void *obuf);
+EJDB_EXPORT void tcarccipher(const void *ptr, int size, const void *kbuf, int ksiz, void *obuf);
 
 
 /* Get the time of day in seconds.
    The return value is the time of day in seconds.  The accuracy is in microseconds. */
-double tctime(void);
+EJDB_EXPORT double tctime(void);
 
 
 /* Get time in milleconds since Epoch. */
-unsigned long tcmstime(void);
+EJDB_EXPORT unsigned long tcmstime(void);
 
 
 /* Get the Gregorian calendar of a time.
@@ -2580,7 +2582,7 @@ unsigned long tcmstime(void);
    it is not used.
    `secp' specifies the pointer to a variable to which the seconds is assigned.  If it is `NULL',
    it is not used. */
-void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
+EJDB_EXPORT void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
                 int *hourp, int *minp, int *secp);
 
 
@@ -2592,7 +2594,7 @@ void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
    `buf' specifies the pointer to the region into which the result string is written.  The size
    of the buffer should be equal to or more than 48 bytes.
    W3CDTF represents a date as "YYYY-MM-DDThh:mm:ddTZD". */
-void tcdatestrwww(int64_t t, int jl, char *buf);
+EJDB_EXPORT void tcdatestrwww(int64_t t, int jl, char *buf);
 
 
 /* Format a date as a string in RFC 1123 format.
@@ -2603,7 +2605,7 @@ void tcdatestrwww(int64_t t, int jl, char *buf);
    `buf' specifies the pointer to the region into which the result string is written.  The size
    of the buffer should be equal to or more than 48 bytes.
    RFC 1123 format represents a date as "Wdy, DD-Mon-YYYY hh:mm:dd TZD". */
-void tcdatestrhttp(int64_t t, int jl, char *buf);
+EJDB_EXPORT void tcdatestrhttp(int64_t t, int jl, char *buf);
 
 
 /* Get the time value of a date string.
@@ -2611,12 +2613,12 @@ void tcdatestrhttp(int64_t t, int jl, char *buf);
    can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in
    days.
    The return value is the time value of the date or `INT64_MIN' if the format is invalid. */
-int64_t tcstrmktime(const char *str);
+EJDB_EXPORT int64_t tcstrmktime(const char *str);
 
 
 /* Get the jet lag of the local time.
    The return value is the jet lag of the local time in seconds. */
-int tcjetlag(void);
+EJDB_EXPORT int tcjetlag(void);
 
 
 /* Get the day of week of a date.
@@ -2624,7 +2626,7 @@ int tcjetlag(void);
    `mon' specifies the month of the date.
    `day' specifies the day of the date.
    The return value is the day of week of the date.  0 means Sunday and 6 means Saturday. */
-int tcdayofweek(int year, int mon, int day);
+EJDB_EXPORT int tcdayofweek(int year, int mon, int day);
 
 
 
@@ -2662,21 +2664,21 @@ typedef struct {                         /* type of structure for a consistent h
 /* Check whether a string is numeric completely or not.
    `str' specifies the string to be checked.
    The return value is true if the string is numeric, else, it is false. */
-bool tcstrisnum(const char *str);
-bool tcstrisintnum(const char *str, int len);
+EJDB_EXPORT bool tcstrisnum(const char *str);
+EJDB_EXPORT bool tcstrisintnum(const char *str, int len);
 
 
 /* Convert a hexadecimal string to an integer.
    `str' specifies the string.
    The return value is the integer.  If the string does not contain numeric expression, 0 is
    returned. */
-int64_t tcatoih(const char *str);
+EJDB_EXPORT int64_t tcatoih(const char *str);
 
 
 /* Skip space characters at head of a string.
    `str' specifies the string.
    The return value is the pointer to the first non-space character. */
-const char *tcstrskipspc(const char *str);
+EJDB_EXPORT const char *tcstrskipspc(const char *str);
 
 
 /* Normalize a UTF-8 string.
@@ -2687,7 +2689,7 @@ const char *tcstrskipspc(const char *str);
    alphabetical characters with accent marks are normalized without accent marks, `TCUNWIDTH'
    specifies that full-width characters are normalized into half-width characters.
    The return value is the string itself. */
-char *tcstrutfnorm(char *str, int opts);
+EJDB_EXPORT char *tcstrutfnorm(char *str, int opts);
 
 
 /* Normalize a UCS-2 array.
@@ -2699,7 +2701,7 @@ char *tcstrutfnorm(char *str, int opts);
    alphabetical characters with accent marks are normalized without accent marks, `TCUNWIDTH'
    specifies that full-width characters are normalized into half-width characters.
    The return value is the number of elements of the result array. */
-int tcstrucsnorm(uint16_t *ary, int num, int opts);
+EJDB_EXPORT int tcstrucsnorm(uint16_t *ary, int num, int opts);
 
 
 /* Generate a keyword-in-context string from a text and keywords.
@@ -2714,7 +2716,7 @@ int tcstrucsnorm(uint16_t *ary, int num, int opts);
    The return value is the list object whose elements are strings around keywords.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcstrkwic(const char *str, const TCLIST *words, int width, int opts);
+EJDB_EXPORT TCLIST *tcstrkwic(const char *str, const TCLIST *words, int width, int opts);
 
 
 /* Tokenize a text separating by white space characters.
@@ -2722,7 +2724,7 @@ TCLIST *tcstrkwic(const char *str, const TCLIST *words, int width, int opts);
    The return value is the list object whose elements are extracted tokens.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcstrtokenize(const char *str);
+EJDB_EXPORT TCLIST *tcstrtokenize(const char *str);
 
 
 /* Create a list object by splitting a region by zero code.
@@ -2732,7 +2734,7 @@ TCLIST *tcstrtokenize(const char *str);
    If two delimiters are successive, it is assumed that an empty element is between the two.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcstrsplit2(const void *ptr, int size);
+EJDB_EXPORT TCLIST *tcstrsplit2(const void *ptr, int size);
 
 
 /* Create a map object by splitting a string.
@@ -2742,7 +2744,7 @@ TCLIST *tcstrsplit2(const void *ptr, int size);
    The return value is a map object of the split records.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcstrsplit3(const char *str, const char *delims);
+EJDB_EXPORT TCMAP *tcstrsplit3(const char *str, const char *delims);
 
 
 /* Create a map object by splitting a region by zero code.
@@ -2752,7 +2754,7 @@ TCMAP *tcstrsplit3(const char *str, const char *delims);
    The return value is a map object of the split records.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcstrsplit4(const void *ptr, int size);
+EJDB_EXPORT TCMAP *tcstrsplit4(const void *ptr, int size);
 
 
 /* Create a region separated by zero code by joining all elements of a list object.
@@ -2762,7 +2764,7 @@ TCMAP *tcstrsplit4(const void *ptr, int size);
    value is assigned.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-void *tcstrjoin2(const TCLIST *list, int *sp);
+EJDB_EXPORT void *tcstrjoin2(const TCLIST *list, int *sp);
 
 
 /* Create a string by joining all records of a map object.
@@ -2772,7 +2774,7 @@ void *tcstrjoin2(const TCLIST *list, int *sp);
    one after the other.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcstrjoin3(const TCMAP *map, char delim);
+EJDB_EXPORT char *tcstrjoin3(const TCMAP *map, char delim);
 
 
 /* Create a region separated by zero code by joining all records of a map object.
@@ -2783,7 +2785,7 @@ char *tcstrjoin3(const TCMAP *map, char delim);
    value is assigned.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-void *tcstrjoin4(const TCMAP *map, int *sp);
+EJDB_EXPORT void *tcstrjoin4(const TCMAP *map, int *sp);
 
 
 /* Sort top records of an array.
@@ -2794,14 +2796,14 @@ void *tcstrjoin4(const TCMAP *map, int *sp);
    `compar' specifies the pointer to comparing function.  The two arguments specify the pointers
    of elements.  The comparing function should returns positive if the former is big, negative
    if the latter is big, 0 if both are equal. */
-void tctopsort(void *base, size_t nmemb, size_t size, size_t top,
+EJDB_EXPORT void tctopsort(void *base, size_t nmemb, size_t size, size_t top,
                int(*compar)(const void *, const void *));
 
 
 /* Suspend execution of the current thread.
    `sec' specifies the interval of the suspension in seconds.
    If successful, the return value is true, else, it is false. */
-bool tcsleep(double sec);
+EJDB_EXPORT bool tcsleep(double sec);
 
 
 /* Get the current system information.
@@ -2813,7 +2815,7 @@ bool tcsleep(double sec);
    memory.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcsysinfo(void);
+EJDB_EXPORT TCMAP *tcsysinfo(void);
 
 
 /* Create a consistent hashing object.
@@ -2822,12 +2824,12 @@ TCMAP *tcsysinfo(void);
    The return value is the new consistent hashing object.
    Consistent hashing is useful because the addition or removal of one node does not
    significantly change the mapping of keys to nodes. */
-TCCHIDX *tcchidxnew(int range);
+EJDB_EXPORT TCCHIDX *tcchidxnew(int range);
 
 
 /* Delete a consistent hashing object.
    `chidx' specifies the consistent hashing object. */
-void tcchidxdel(TCCHIDX *chidx);
+EJDB_EXPORT void tcchidxdel(TCCHIDX *chidx);
 
 
 /* Get the consistent hashing value of a record.
@@ -2835,7 +2837,7 @@ void tcchidxdel(TCCHIDX *chidx);
    `ptr' specifies the pointer to the region of the record.
    `size' specifies the size of the region.
    The return value is the hash value of the record. */
-int tcchidxhash(TCCHIDX *chidx, const void *ptr, int size);
+EJDB_EXPORT int tcchidxhash(TCCHIDX *chidx, const void *ptr, int size);
 
 
 
@@ -2850,7 +2852,7 @@ int tcchidxhash(TCCHIDX *chidx, const void *ptr, int size);
    invalid.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcrealpath(const char *path);
+EJDB_EXPORT char *tcrealpath(const char *path);
 
 
 /* Get the status information of a file.
@@ -2862,7 +2864,7 @@ char *tcrealpath(const char *path);
    `ntimep' specifies the pointer to a variable into which the size of the file is assigned.  If
    it is `NULL', it is ignored.
    If successful, the return value is true, else, it is false. */
-bool tcstatfile(const char *path, bool *isdirp, int64_t *sizep, int64_t *mtimep);
+EJDB_EXPORT bool tcstatfile(const char *path, bool *isdirp, int64_t *sizep, int64_t *mtimep);
 
 
 /* Read whole data of a file.
@@ -2877,7 +2879,7 @@ bool tcstatfile(const char *path, bool *isdirp, int64_t *sizep, int64_t *mtimep)
    return value can be treated as a character string.  Because the region of the return value is
    allocated with the `malloc' call, it should be released with the `free' call when when is no
    longer in use.  */
-void *tcreadfile(const char *path, int limit, int *sp);
+EJDB_EXPORT void *tcreadfile(const char *path, int limit, int *sp);
 
 
 /* Read every line of a file.
@@ -2886,7 +2888,7 @@ void *tcreadfile(const char *path, int limit, int *sp);
    Line separators are cut out.  Because the object of the return value is created with the
    function `tclistnew', it should be deleted with the function `tclistdel' when it is no longer
    in use. */
-TCLIST *tcreadfilelines(const char *path);
+EJDB_EXPORT TCLIST *tcreadfilelines(const char *path);
 
 
 /* Write data into a file.
@@ -2894,7 +2896,7 @@ TCLIST *tcreadfilelines(const char *path);
    `ptr' specifies the pointer to the data region.
    `size' specifies the size of the region.
    If successful, the return value is true, else, it is false. */
-bool tcwritefile(const char *path, const void *ptr, int size);
+EJDB_EXPORT bool tcwritefile(const char *path, const void *ptr, int size);
 
 
 /* Copy a file.
@@ -2902,7 +2904,7 @@ bool tcwritefile(const char *path, const void *ptr, int size);
    `dest' specifies the path of the destination file.
    The return value is true if successful, else, it is false.
    If the destination file exists, it is overwritten. */
-bool tccopyfile(const char *src, const char *dest);
+EJDB_EXPORT bool tccopyfile(const char *src, const char *dest);
 
 
 /* Read names of files in a directory.
@@ -2911,7 +2913,7 @@ bool tccopyfile(const char *src, const char *dest);
    Links to the directory itself and to the parent directory are ignored.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcreaddir(const char *path);
+EJDB_EXPORT TCLIST *tcreaddir(const char *path);
 
 
 /* Expand a pattern into a list of matched paths.
@@ -2920,22 +2922,34 @@ TCLIST *tcreaddir(const char *path);
    returned.
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcglobpat(const char *pattern);
+EJDB_EXPORT TCLIST *tcglobpat(const char *pattern);
 
 
 /* Remove a file or a directory and its sub ones recursively.
    `path' specifies the path of the link.
    If successful, the return value is true, else, it is false.  False is returned when the link
    does not exist or the permission is denied. */
-bool tcremovelink(const char *path);
+EJDB_EXPORT bool tcremovelink(const char *path);
 
 
+enum {
+    TCFSTART = 0,                       /* file start */
+    TCFCUR = 1,                         /* file current pos */
+    TCFEND = 2                          /* file end */
+};
+
+/* File seek implementation */
+EJDB_EXPORT bool tcfseek(HANDLE fd, off_t off, int whence);
+
+
+EJDB_EXPORT bool tcftruncate(HANDLE fd, off_t length);
+
 /* Write data into a file.
    `fd' specifies the file descriptor.
    `buf' specifies the buffer to be written.
    `size' specifies the size of the buffer.
    The return value is true if successful, else, it is false. */
-bool tcwrite(int fd, const void *buf, size_t size);
+EJDB_EXPORT bool tcwrite(HANDLE fd, const void *buf, size_t size);
 
 
 /* Read data from a file.
@@ -2943,7 +2957,7 @@ bool tcwrite(int fd, const void *buf, size_t size);
    `buf' specifies the buffer to store into.
    `size' specifies the size of the buffer.
    The return value is true if successful, else, it is false. */
-bool tcread(int fd, void *buf, size_t size);
+EJDB_EXPORT bool tcread(HANDLE fd, void *buf, size_t size);
 
 
 /* Lock a file.
@@ -2951,13 +2965,13 @@ bool tcread(int fd, void *buf, size_t size);
    `ex' specifies whether an exclusive lock or a shared lock is performed.
    `nb' specifies whether to request with non-blocking.
    The return value is true if successful, else, it is false. */
-bool tclock(int fd, bool ex, bool nb);
+EJDB_EXPORT bool tclock(HANDLE fd, bool ex, bool nb);
 
 
 /* Unlock a file.
    `fd' specifies the file descriptor.
    The return value is true if successful, else, it is false. */
-bool tcunlock(int fd);
+EJDB_EXPORT bool tcunlock(HANDLE fd);
 
 
 /* Execute a shell command.
@@ -2965,7 +2979,7 @@ bool tcunlock(int fd);
    `anum' specifies the number of elements of the array.
    The return value is the exit code of the command or `INT_MAX' on failure.
    The command name and the arguments are quoted and meta characters are escaped. */
-int tcsystem(const char **args, int anum);
+EJDB_EXPORT int tcsystem(const char **args, int anum);
 
 
 
@@ -2980,7 +2994,7 @@ int tcsystem(const char **args, int anum);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcurlencode(const char *ptr, int size);
+EJDB_EXPORT char *tcurlencode(const char *ptr, int size);
 
 
 /* Decode a string encoded with URL encoding.
@@ -2992,7 +3006,7 @@ char *tcurlencode(const char *ptr, int size);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tcurldecode(const char *str, int *sp);
+EJDB_EXPORT char *tcurldecode(const char *str, int *sp);
 
 
 /* Break up a URL into elements.
@@ -3006,7 +3020,7 @@ char *tcurldecode(const char *str, int *sp);
    Supported schema are HTTP, HTTPS, FTP, and FILE.  Absolute URL and relative URL are supported.
    Because the object of the return value is created with the function `tcmapnew', it should be
    deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcurlbreak(const char *str);
+EJDB_EXPORT TCMAP *tcurlbreak(const char *str);
 
 
 /* Resolve a relative URL with an absolute URL.
@@ -3016,7 +3030,7 @@ TCMAP *tcurlbreak(const char *str);
    location from the base location is returned.  Else, a copy of the target URL is returned.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcurlresolve(const char *base, const char *target);
+EJDB_EXPORT char *tcurlresolve(const char *base, const char *target);
 
 
 /* Encode a serial object with Base64 encoding.
@@ -3025,7 +3039,7 @@ char *tcurlresolve(const char *base, const char *target);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcbaseencode(const char *ptr, int size);
+EJDB_EXPORT char *tcbaseencode(const char *ptr, int size);
 
 
 /* Decode a string encoded with Base64 encoding.
@@ -3037,7 +3051,7 @@ char *tcbaseencode(const char *ptr, int size);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tcbasedecode(const char *str, int *sp);
+EJDB_EXPORT char *tcbasedecode(const char *str, int *sp);
 
 
 /* Encode a serial object with Quoted-printable encoding.
@@ -3046,7 +3060,7 @@ char *tcbasedecode(const char *str, int *sp);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcquoteencode(const char *ptr, int size);
+EJDB_EXPORT char *tcquoteencode(const char *ptr, int size);
 
 
 /* Decode a string encoded with Quoted-printable encoding.
@@ -3058,7 +3072,7 @@ char *tcquoteencode(const char *ptr, int size);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tcquotedecode(const char *str, int *sp);
+EJDB_EXPORT char *tcquotedecode(const char *str, int *sp);
 
 
 /* Encode a string with MIME encoding.
@@ -3068,7 +3082,7 @@ char *tcquotedecode(const char *str, int *sp);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcmimeencode(const char *str, const char *encname, bool base);
+EJDB_EXPORT char *tcmimeencode(const char *str, const char *encname, bool base);
 
 
 /* Decode a string encoded with MIME encoding.
@@ -3078,7 +3092,7 @@ char *tcmimeencode(const char *str, const char *encname, bool base);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcmimedecode(const char *str, char *enp);
+EJDB_EXPORT char *tcmimedecode(const char *str, char *enp);
 
 
 /* Split a string of MIME into headers and the body.
@@ -3096,7 +3110,7 @@ char *tcmimedecode(const char *str, char *enp);
    defined, the key "FILENAME" indicates the name.  If the attribute name is defined, the key
    "NAME" indicates the name.  Because the region of the return value is allocated with the
    `malloc' call, it should be released with the `free' call when it is no longer in use. */
-char *tcmimebreak(const char *ptr, int size, TCMAP *headers, int *sp);
+EJDB_EXPORT char *tcmimebreak(const char *ptr, int size, TCMAP *headers, int *sp);
 
 
 /* Split multipart data of MIME into its parts.
@@ -3106,7 +3120,7 @@ char *tcmimebreak(const char *ptr, int size, TCMAP *headers, int *sp);
    The return value is a list object.  Each element of the list is the data of a part.
    Because the object of the return value is created with the function `tclistnew', it should be
    deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcmimeparts(const char *ptr, int size, const char *boundary);
+EJDB_EXPORT TCLIST *tcmimeparts(const char *ptr, int size, const char *boundary);
 
 
 /* Encode a serial object with hexadecimal encoding.
@@ -3115,7 +3129,7 @@ TCLIST *tcmimeparts(const char *ptr, int size, const char *boundary);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tchexencode(const char *ptr, int size);
+EJDB_EXPORT char *tchexencode(const char *ptr, int size);
 
 
 /* Decode a string encoded with hexadecimal encoding.
@@ -3127,7 +3141,7 @@ char *tchexencode(const char *ptr, int size);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when
    it is no longer in use. */
-char *tchexdecode(const char *str, int *sp);
+EJDB_EXPORT char *tchexdecode(const char *str, int *sp);
 
 
 /* Compress a serial object with Packbits encoding.
@@ -3138,7 +3152,7 @@ char *tchexdecode(const char *str, int *sp);
    If successful, the return value is the pointer to the result object, else, it is `NULL'.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcpackencode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcpackencode(const char *ptr, int size, int *sp);
 
 
 /* Decompress a serial object compressed with Packbits encoding.
@@ -3151,7 +3165,7 @@ char *tcpackencode(const char *ptr, int size, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcpackdecode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcpackdecode(const char *ptr, int size, int *sp);
 
 
 /* Compress a serial object with TCBS encoding.
@@ -3162,7 +3176,7 @@ char *tcpackdecode(const char *ptr, int size, int *sp);
    If successful, the return value is the pointer to the result object, else, it is `NULL'.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcbsencode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcbsencode(const char *ptr, int size, int *sp);
 
 
 /* Decompress a serial object compressed with TCBS encoding.
@@ -3175,7 +3189,7 @@ char *tcbsencode(const char *ptr, int size, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcbsdecode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcbsdecode(const char *ptr, int size, int *sp);
 
 
 /* Compress a serial object with Deflate encoding.
@@ -3186,7 +3200,7 @@ char *tcbsdecode(const char *ptr, int size, int *sp);
    If successful, the return value is the pointer to the result object, else, it is `NULL'.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcdeflate(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcdeflate(const char *ptr, int size, int *sp);
 
 
 /* Decompress a serial object compressed with Deflate encoding.
@@ -3199,7 +3213,7 @@ char *tcdeflate(const char *ptr, int size, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcinflate(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcinflate(const char *ptr, int size, int *sp);
 
 
 /* Compress a serial object with GZIP encoding.
@@ -3210,7 +3224,7 @@ char *tcinflate(const char *ptr, int size, int *sp);
    If successful, the return value is the pointer to the result object, else, it is `NULL'.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcgzipencode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcgzipencode(const char *ptr, int size, int *sp);
 
 
 /* Decompress a serial object compressed with GZIP encoding.
@@ -3223,14 +3237,14 @@ char *tcgzipencode(const char *ptr, int size, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcgzipdecode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcgzipdecode(const char *ptr, int size, int *sp);
 
 
 /* Get the CRC32 checksum of a serial object.
    `ptr' specifies the pointer to the region.
    `size' specifies the size of the region.
    The return value is the CRC32 checksum of the object. */
-unsigned int tcgetcrc(const char *ptr, int size);
+EJDB_EXPORT unsigned int tcgetcrc(const char *ptr, int size);
 
 
 /* Compress a serial object with BZIP2 encoding.
@@ -3241,7 +3255,7 @@ unsigned int tcgetcrc(const char *ptr, int size);
    If successful, the return value is the pointer to the result object, else, it is `NULL'.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcbzipencode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcbzipencode(const char *ptr, int size, int *sp);
 
 
 /* Decompress a serial object compressed with BZIP2 encoding.
@@ -3254,7 +3268,7 @@ char *tcbzipencode(const char *ptr, int size, int *sp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcbzipdecode(const char *ptr, int size, int *sp);
+EJDB_EXPORT char *tcbzipdecode(const char *ptr, int size, int *sp);
 
 
 /* Encode an array of nonnegative integers with BER encoding.
@@ -3265,7 +3279,7 @@ char *tcbzipdecode(const char *ptr, int size, int *sp);
    The return value is the pointer to the region of the result.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcberencode(const unsigned int *ary, int anum, int *sp);
+EJDB_EXPORT char *tcberencode(const unsigned int *ary, int anum, int *sp);
 
 
 /* Decode a serial object encoded with BER encoding.
@@ -3276,7 +3290,7 @@ char *tcberencode(const unsigned int *ary, int anum, int *sp);
    The return value is the pointer to the array of the result.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-unsigned int *tcberdecode(const char *ptr, int size, int *np);
+EJDB_EXPORT unsigned int *tcberdecode(const char *ptr, int size, int *np);
 
 
 /* Escape meta characters in a string with the entity references of XML.
@@ -3285,7 +3299,7 @@ unsigned int *tcberdecode(const char *ptr, int size, int *np);
    This function escapes only `&', `<', `>', and `"'.  Because the region of the return value
    is allocated with the `malloc' call, it should be released with the `free' call when it is no
    longer in use. */
-char *tcxmlescape(const char *str);
+EJDB_EXPORT char *tcxmlescape(const char *str);
 
 
 /* Unescape entity references in a string of XML.
@@ -3294,7 +3308,7 @@ char *tcxmlescape(const char *str);
    This function restores only `&amp;', `&lt;', `&gt;', and `&quot;'.  Because the region of the
    return value is allocated with the `malloc' call, it should be released with the `free' call
    when it is no longer in use. */
-char *tcxmlunescape(const char *str);
+EJDB_EXPORT char *tcxmlunescape(const char *str);
 
 
 
@@ -3308,13 +3322,13 @@ char *tcxmlunescape(const char *str);
    The return value is the result string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tcwwwformencode(const TCMAP *params);
+EJDB_EXPORT char *tcwwwformencode(const TCMAP *params);
 
 
 /* Decode a query string in the x-www-form-urlencoded format.
    `str' specifies the query string.
    `params' specifies a map object into which the result parameters are stored. */
-void tcwwwformdecode(const char *str, TCMAP *params);
+EJDB_EXPORT void tcwwwformdecode(const char *str, TCMAP *params);
 
 
 /* Decode a data region in the x-www-form-urlencoded or multipart-form-data format.
@@ -3323,7 +3337,7 @@ void tcwwwformdecode(const char *str, TCMAP *params);
    `type' specifies the value of the content-type header.  If it is `NULL', the type is specified
    as x-www-form-urlencoded.
    `params' specifies a map object into which the result parameters are stored. */
-void tcwwwformdecode2(const void *ptr, int size, const char *type, TCMAP *params);
+EJDB_EXPORT void tcwwwformdecode2(const void *ptr, int size, const char *type, TCMAP *params);
 
 
 /* Split an XML string into tags and text sections.
@@ -3332,7 +3346,7 @@ void tcwwwformdecode2(const void *ptr, int size, const char *type, TCMAP *params
    Because the object of the return value is created with the function `tclistnew', it should
    be deleted with the function `tclistdel' when it is no longer in use.  Because this function
    does not check validation, it can handle also HTML and SGML. */
-TCLIST *tcxmlbreak(const char *str);
+EJDB_EXPORT TCLIST *tcxmlbreak(const char *str);
 
 
 /* Get the map of attributes of an XML tag.
@@ -3341,7 +3355,7 @@ TCLIST *tcxmlbreak(const char *str);
    unescaped.  You can get the name of the tag with the key of an empty string.
    Because the object of the return value is created with the function `tcmapnew', it should
    be deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcxmlattrs(const char *str);
+EJDB_EXPORT TCMAP *tcxmlattrs(const char *str);
 
 
 /* Escape meta characters in a string with backslash escaping of the C language.
@@ -3349,7 +3363,7 @@ TCMAP *tcxmlattrs(const char *str);
    The return value is the pointer to the escaped string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tccstrescape(const char *str);
+EJDB_EXPORT char *tccstrescape(const char *str);
 
 
 /* Unescape a string escaped by backslash escaping of the C language.
@@ -3357,7 +3371,7 @@ char *tccstrescape(const char *str);
    The return value is the unescaped string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tccstrunescape(const char *str);
+EJDB_EXPORT char *tccstrunescape(const char *str);
 
 
 /* Escape meta characters in a string with backslash escaping of JSON.
@@ -3365,7 +3379,7 @@ char *tccstrunescape(const char *str);
    The return value is the pointer to the escaped string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcjsonescape(const char *str);
+EJDB_EXPORT char *tcjsonescape(const char *str);
 
 
 /* Unescape a string escaped by backslash escaping of JSON.
@@ -3373,7 +3387,7 @@ char *tcjsonescape(const char *str);
    The return value is the unescaped string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call if when is no longer in use. */
-char *tcjsonunescape(const char *str);
+EJDB_EXPORT char *tcjsonunescape(const char *str);
 
 
 
@@ -3392,19 +3406,19 @@ typedef struct {                         /* type of structure for a template */
 
 /* Create a template object.
    The return value is the new template object. */
-TCTMPL *tctmplnew(void);
+EJDB_EXPORT TCTMPL *tctmplnew(void);
 
 
 /* Delete a template object.
    `tmpl' specifies the template object. */
-void tctmpldel(TCTMPL *tmpl);
+EJDB_EXPORT void tctmpldel(TCTMPL *tmpl);
 
 
 /* Set the separator strings of a template object.
    `tmpl' specifies the template object.
    `begsep' specifies the beginning separator string.  By default, it is "[%".
    `endsep' specifies the ending separator string.  By default, it is "%]". */
-void tctmplsetsep(TCTMPL *tmpl, const char *begsep, const char *endsep);
+EJDB_EXPORT void tctmplsetsep(TCTMPL *tmpl, const char *begsep, const char *endsep);
 
 
 /* Load a template string into a template object.
@@ -3435,14 +3449,14 @@ void tctmplsetsep(TCTMPL *tmpl, const char *begsep, const char *endsep);
    element.  The session variable setting directive needs the parameters for the variable name
    and its value.  The configuration directive needs the parameters for the variable name and
    its value. */
-void tctmplload(TCTMPL *tmpl, const char *str);
+EJDB_EXPORT void tctmplload(TCTMPL *tmpl, const char *str);
 
 
 /* Load a template string from a file into a template object.
    `tmpl' specifies the template object.
    `path' specifies the input file.
    If successful, the return value is true, else, it is false. */
-bool tctmplload2(TCTMPL *tmpl, const char *path);
+EJDB_EXPORT bool tctmplload2(TCTMPL *tmpl, const char *path);
 
 
 /* Serialize the template string of a template object.
@@ -3451,7 +3465,7 @@ bool tctmplload2(TCTMPL *tmpl, const char *path);
    The return value is the dumped template string.
    Because the region of the return value is allocated with the `malloc' call, it should be
    released with the `free' call when it is no longer in use. */
-char *tctmpldump(TCTMPL *tmpl, const TCMAP *vars);
+EJDB_EXPORT char *tctmpldump(TCTMPL *tmpl, const TCMAP *vars);
 
 
 /* Get the value of a configuration variable of a template object.
@@ -3459,33 +3473,33 @@ char *tctmpldump(TCTMPL *tmpl, const TCMAP *vars);
    `name' specifies the name of the configuration variable.
    The return value is the string value of the configuration variable or `NULL' if it is not
    defined. */
-const char *tctmplconf(TCTMPL *tmpl, const char *name);
+EJDB_EXPORT const char *tctmplconf(TCTMPL *tmpl, const char *name);
 
 
 /* Store a list object into a list object with the type information.
    `list' specifies the container list object.
    `obj' specifies the list object to be stored. */
-void tclistpushlist(TCLIST *list, const TCLIST *obj);
+EJDB_EXPORT void tclistpushlist(TCLIST *list, const TCLIST *obj);
 
 
 /* Store a map object into a list object with the type information.
    `list' specifies the container list object.
    `obj' specifies the map object to be stored. */
-void tclistpushmap(TCLIST *list, const TCMAP *obj);
+EJDB_EXPORT void tclistpushmap(TCLIST *list, const TCMAP *obj);
 
 
 /* Store a list object into a map object with the type information.
    `map' specifies the container map object.
    `kstr' specifies the string of the key.
    `obj' specifies the list object to be stored. */
-void tcmapputlist(TCMAP *map, const char *kstr, const TCLIST *obj);
+EJDB_EXPORT void tcmapputlist(TCMAP *map, const char *kstr, const TCLIST *obj);
 
 
 /* Store a map object into a map object with the type information.
    `map' specifies the container map object.
    `kstr' specifies the string of the key.
    `obj' specifies the map object to be stored. */
-void tcmapputmap(TCMAP *map, const char *kstr, const TCMAP *obj);
+EJDB_EXPORT void tcmapputmap(TCMAP *map, const char *kstr, const TCMAP *obj);
 
 
 
@@ -3504,31 +3518,31 @@ typedef struct {                         /* type of structure for a pointer list
 
 /* Create a pointer list object.
    The return value is the new pointer list object. */
-TCPTRLIST *tcptrlistnew(void);
+EJDB_EXPORT TCPTRLIST *tcptrlistnew(void);
 
 
 /* Create a pointer list object with expecting the number of elements.
    `anum' specifies the number of elements expected to be stored in the list.
    The return value is the new pointer list object. */
-TCPTRLIST *tcptrlistnew2(int anum);
+EJDB_EXPORT TCPTRLIST *tcptrlistnew2(int anum);
 
 
 /* Copy a pointer list object.
    `ptrlist' specifies the pointer list object.
    The return value is the new pointer list object equivalent to the specified object. */
-TCPTRLIST *tcptrlistdup(const TCPTRLIST *ptrlist);
+EJDB_EXPORT TCPTRLIST *tcptrlistdup(const TCPTRLIST *ptrlist);
 
 
 /* Delete a pointer list object.
    `ptrlist' specifies the pointer list object.
    Note that the deleted object and its derivatives can not be used anymore. */
-void tcptrlistdel(TCPTRLIST *ptrlist);
+EJDB_EXPORT void tcptrlistdel(TCPTRLIST *ptrlist);
 
 
 /* Get the number of elements of a pointer list object.
    `ptrlist' specifies the pointer list object.
    The return value is the number of elements of the list. */
-int tcptrlistnum(const TCPTRLIST *ptrlist);
+EJDB_EXPORT int tcptrlistnum(const TCPTRLIST *ptrlist);
 
 
 /* Get the pointer to the region of an element of a pointer list object.
@@ -3536,33 +3550,33 @@ int tcptrlistnum(const TCPTRLIST *ptrlist);
    `index' specifies the index of the element.
    The return value is the pointer to the region of the value.
    If `index' is equal to or more than the number of elements, the return value is `NULL'. */
-void *tcptrlistval(const TCPTRLIST *ptrlist, int index);
+EJDB_EXPORT void *tcptrlistval(const TCPTRLIST *ptrlist, int index);
 
 
 /* Add an element at the end of a pointer list object.
    `ptrlist' specifies the pointer list object.
    `ptr' specifies the pointer to the region of the new element. */
-void tcptrlistpush(TCPTRLIST *ptrlist, void *ptr);
+EJDB_EXPORT void tcptrlistpush(TCPTRLIST *ptrlist, void *ptr);
 
 
 /* Remove an element of the end of a pointer list object.
    `ptrlist' specifies the pointer list object.
    The return value is the pointer to the region of the removed element.
    If the list is empty, the return value is `NULL'. */
-void *tcptrlistpop(TCPTRLIST *ptrlist);
+EJDB_EXPORT void *tcptrlistpop(TCPTRLIST *ptrlist);
 
 
 /* Add an element at the top of a pointer list object.
    `ptrlist' specifies the pointer list object.
    `ptr' specifies the pointer to the region of the new element. */
-void tcptrlistunshift(TCPTRLIST *ptrlist, void *ptr);
+EJDB_EXPORT void tcptrlistunshift(TCPTRLIST *ptrlist, void *ptr);
 
 
 /* Remove an element of the top of a pointer list object.
    `ptrlist' specifies the pointer list object.
    The return value is the pointer to the region of the removed element.
    If the list is empty, the return value is `NULL'. */
-void *tcptrlistshift(TCPTRLIST *ptrlist);
+EJDB_EXPORT void *tcptrlistshift(TCPTRLIST *ptrlist);
 
 
 /* Add an element at the specified location of a pointer list object.
@@ -3570,7 +3584,7 @@ void *tcptrlistshift(TCPTRLIST *ptrlist);
    `index' specifies the index of the new element.
    `ptr' specifies the pointer to the region of the new element.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tcptrlistinsert(TCPTRLIST *ptrlist, int index, void *ptr);
+EJDB_EXPORT void tcptrlistinsert(TCPTRLIST *ptrlist, int index, void *ptr);
 
 
 /* Remove an element at the specified location of a pointer list object.
@@ -3579,7 +3593,7 @@ void tcptrlistinsert(TCPTRLIST *ptrlist, int index, void *ptr);
    The return value is the pointer to the region of the removed element.
    If `index' is equal to or more than the number of elements, no element is removed and the
    return value is `NULL'. */
-void *tcptrlistremove(TCPTRLIST *ptrlist, int index);
+EJDB_EXPORT void *tcptrlistremove(TCPTRLIST *ptrlist, int index);
 
 
 /* Overwrite an element at the specified location of a pointer list object.
@@ -3587,13 +3601,13 @@ void *tcptrlistremove(TCPTRLIST *ptrlist, int index);
    `index' specifies the index of the element to be overwritten.
    `ptr' specifies the pointer to the region of the new content.
    If `index' is equal to or more than the number of elements, this function has no effect. */
-void tcptrlistover(TCPTRLIST *ptrlist, int index, void *ptr);
+EJDB_EXPORT void tcptrlistover(TCPTRLIST *ptrlist, int index, void *ptr);
 
 
 /* Clear a pointer list object.
    `ptrlist' specifies the pointer list object.
    All elements are removed. */
-void tcptrlistclear(TCPTRLIST *ptrlist);
+EJDB_EXPORT void tcptrlistclear(TCPTRLIST *ptrlist);
 
 
 
@@ -3747,6 +3761,7 @@ enum {                                   /* enumeration for error codes */
   TCERMDIR,                              /* rmdir error */
   TCEKEEP,                               /* existing record */
   TCENOREC,                              /* no record found */
+  TCETR,                                 /* illegal transaction state */
   TCEMISC = 9999                         /* miscellaneous error */
 };
 
@@ -3758,16 +3773,22 @@ enum {                                   /* enumeration for database type */
 };
 
 
+/* Converts last errno value on file operation
+ * to matching TC error code or use default `tcerrdef`
+ * if no errno was set.
+ */
+EJDB_EXPORT int tcfilerrno2tcerr(int tcerrdef);
+
 /* Get the message string corresponding to an error code.
    `ecode' specifies the error code.
    The return value is the message string of the error code. */
-const char *tcerrmsg(int ecode);
+EJDB_EXPORT const char *tcerrmsg(int ecode);
 
 
 /* Show error message on the standard error output and exit.
    `message' specifies an error message.
    This function does not return. */
-void *tcmyfatal(const char *message);
+EJDB_EXPORT void *tcmyfatal(const char *message);
 
 
 /* Allocate a large nullified region.
@@ -3775,39 +3796,39 @@ void *tcmyfatal(const char *message);
    The return value is the pointer to the allocated nullified region.
    This function handles failure of memory allocation implicitly.  The region of the return value
    should be released with the function `tczerounmap' when it is no longer in use. */
-void *tczeromap(uint64_t size);
+EJDB_EXPORT void *tczeromap(uint64_t size);
 
 
 /* Free a large nullfied region.
    `ptr' specifies the pointer to the region. */
-void tczerounmap(void *ptr);
+EJDB_EXPORT void tczerounmap(void *ptr);
 
 
 /* Lock the global mutex object.
    If successful, the return value is true, else, it is false. */
-bool tcglobalmutexlock(void);
+EJDB_EXPORT bool tcglobalmutexlock(void);
 
 
 /* Lock the global mutex object by shared locking.
    If successful, the return value is true, else, it is false. */
-bool tcglobalmutexlockshared(void);
+EJDB_EXPORT bool tcglobalmutexlockshared(void);
 
 
 /* Unlock the global mutex object.
    If successful, the return value is true, else, it is false. */
-bool tcglobalmutexunlock(void);
+EJDB_EXPORT bool tcglobalmutexunlock(void);
 
 
 /* Lock the absolute path of a file.
    `path' specifies the path of the file.
    If successful, the return value is true, else, it is false. */
-bool tcpathlock(const char *path);
+EJDB_EXPORT bool tcpathlock(const char *path);
 
 
 /* Unock the absolute path of a file.
    `path' specifies the path of the file.
    If successful, the return value is true, else, it is false. */
-bool tcpathunlock(const char *path);
+EJDB_EXPORT bool tcpathunlock(const char *path);
 
 
 /* Convert an integer to the string as binary numbers.
@@ -3817,7 +3838,7 @@ bool tcpathunlock(const char *path);
    `col' specifies the number of columns.  If it is not more than 0, it depends on the integer.
    `fc' specifies the filling character.
    The return value is the length of the result string. */
-int tcnumtostrbin(uint64_t num, char *buf, int col, int fc);
+EJDB_EXPORT int tcnumtostrbin(uint64_t num, char *buf, int col, int fc);
 
 
 /* Compare two keys by lexical order.
@@ -3828,7 +3849,7 @@ int tcnumtostrbin(uint64_t num, char *buf, int col, int fc);
    `op' is ignored.
    The return value is positive if the former is big, negative if the latter is big, 0 if both
    are equivalent. */
-int tccmplexical(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
+EJDB_EXPORT int tccmplexical(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
 
 
 /* Compare two keys as decimal strings of real numbers.
@@ -3839,7 +3860,7 @@ int tccmplexical(const char *aptr, int asiz, const char *bptr, int bsiz, void *o
    `op' is ignored.
    The return value is positive if the former is big, negative if the latter is big, 0 if both
    are equivalent. */
-int tccmpdecimal(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
+EJDB_EXPORT int tccmpdecimal(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
 
 
 /* Compare two keys as 32-bit integers in the native byte order.
@@ -3850,7 +3871,7 @@ int tccmpdecimal(const char *aptr, int asiz, const char *bptr, int bsiz, void *o
    `op' is ignored.
    The return value is positive if the former is big, negative if the latter is big, 0 if both
    are equivalent. */
-int tccmpint32(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
+EJDB_EXPORT int tccmpint32(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
 
 
 /* Compare two keys as 64-bit integers in the native byte order.
@@ -3861,7 +3882,7 @@ int tccmpint32(const char *aptr, int asiz, const char *bptr, int bsiz, void *op)
    `op' is ignored.
    The return value is positive if the former is big, negative if the latter is big, 0 if both
    are equivalent. */
-int tccmpint64(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
+EJDB_EXPORT int tccmpint64(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
 
 
 /* Encode a serial object with BWT encoding.
@@ -3874,7 +3895,7 @@ int tccmpint64(const char *aptr, int asiz, const char *bptr, int bsiz, void *op)
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcbwtencode(const char *ptr, int size, int *idxp);
+EJDB_EXPORT char *tcbwtencode(const char *ptr, int size, int *idxp);
 
 
 /* Decode a serial object encoded with BWT encoding.
@@ -3886,26 +3907,30 @@ char *tcbwtencode(const char *ptr, int size, int *idxp);
    the return value can be treated as a character string.  Because the region of the return
    value is allocated with the `malloc' call, it should be released with the `free' call when it
    is no longer in use. */
-char *tcbwtdecode(const char *ptr, int size, int idx);
+EJDB_EXPORT char *tcbwtdecode(const char *ptr, int size, int idx);
 
 
 /* Get the binary logarithm of an integer.
    `num' specifies an integer.
    The return value is the binary logarithm. */
-long tclog2l(long num);
+EJDB_EXPORT long tclog2l(long num);
 
 
 /* Get the binary logarithm of a real number.
    `num' specifies a real number.
    The return value is the binary logarithm. */
-double tclog2d(double num);
+EJDB_EXPORT double tclog2d(double num);
 
 
 /* Get the aligned offset of a file offset.
    `off' specifies the file offset.
    The return value is the aligned offset. */
-uint64_t tcpagealign(uint64_t off);
+EJDB_EXPORT uint64_t tcpagealign(uint64_t off);
 
+/**
+ * Get page size
+ */
+EJDB_EXPORT off_t tcpagsize(void);
 
 /**
  * Convert string into case insensitive normalized format.
@@ -3915,8 +3940,8 @@ uint64_t tcpagealign(uint64_t off);
  * @return In case of success the length of the resulting UTF-8 string is
  *  returned, otherwise a negative value.
  */
-int tcicaseformat(const char *str, int strl, void *placeholder, int placeholdersz, char **dstptr);
-int tcutf8map(const uint8_t *str, int strl, void *placeholder, int placeholdersz, uint8_t **dstptr, int options);
+EJDB_EXPORT int tcicaseformat(const char *str, int strl, void *placeholder, int placeholdersz, char **dstptr);
+EJDB_EXPORT int tcutf8map(const uint8_t *str, int strl, void *placeholder, int placeholdersz, uint8_t **dstptr, int options);
 
 
 /* Print debug information with a formatted string as with `printf'. */
diff --git a/tcejdb/win32/platform.c b/tcejdb/win32/platform.c
new file mode 100644 (file)
index 0000000..d19e6c1
--- /dev/null
@@ -0,0 +1,169 @@
+#include "platform.h"
+#include "../tcutil.h"
+#include "../myconf.h"
+
+struct tm *gmtime_r(const time_t *timep, struct tm *result) {
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_lock(&mutex);
+    struct tm *cas = gmtime(timep);
+    pthread_mutex_unlock(&mutex);
+    if (result == NULL) {
+        return NULL; /* was:cas */
+    }
+    memcpy(result, cas, sizeof (struct tm));
+    return result;
+}
+
+struct tm *localtime_r(const time_t *timep, struct tm *result) {
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_lock(&mutex);
+    struct tm *cas = localtime(timep);
+    pthread_mutex_unlock(&mutex);
+    if (result == NULL) {
+        return NULL;
+    }
+    memcpy(result, cas, sizeof (struct tm));
+    return result;
+}
+
+static int file_attr_to_st_mode(DWORD attr) {
+    int fMode = S_IREAD;
+    if (attr & FILE_ATTRIBUTE_DIRECTORY)
+        fMode |= S_IFDIR;
+    else
+        fMode |= S_IFREG;
+    if (!(attr & FILE_ATTRIBUTE_READONLY))
+        fMode |= S_IWRITE;
+    return fMode;
+}
+
+static long long filetime_to_hnsec(const FILETIME *ft) {
+    long long winTime = ((long long) ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+    /* Windows to Unix Epoch conversion */
+    return winTime - 116444736000000000LL;
+}
+
+static time_t filetime_to_time_t(const FILETIME *ft) {
+    return (time_t) (filetime_to_hnsec(ft) / 10000000);
+}
+
+int win_fstat(HANDLE fh, struct stat *buf) {
+    BY_HANDLE_FILE_INFORMATION fdata;
+    if (fh == INVALID_HANDLE_VALUE) {
+        errno = EBADF;
+        return -1;
+    }
+    if (GetFileType(fh) != FILE_TYPE_DISK) {
+        errno = ENODEV;
+        return -1;
+    }
+    if (GetFileInformationByHandle(fh, &fdata)) {
+        buf->st_ino = 0;
+        buf->st_gid = 0;
+        buf->st_uid = 0;
+        buf->st_nlink = 1;
+        buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
+        buf->st_size = (off_t) ((((int64_t) fdata.nFileSizeHigh) << 32) | fdata.nFileSizeLow);
+        buf->st_dev = buf->st_rdev = 0; /* not used by Git */
+        buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+        buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+        buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+        return 0;
+    }
+    errno = EBADF;
+    return -1;
+}
+
+ssize_t win_pwrite(HANDLE fd, const void *buf, size_t count, off_t off) {
+    DWORD written;
+    OVERLAPPED offset;
+    memset(&offset, 0, sizeof (OVERLAPPED));
+    ULARGE_INTEGER bigint;
+    bigint.QuadPart = off;
+    offset.Offset = bigint.LowPart;
+    offset.OffsetHigh = bigint.HighPart;
+    if (!WriteFile(fd, buf, count, &written, &offset)) {
+        return -1;
+    }
+    return written;
+}
+
+ssize_t win_pread(HANDLE fd, void *buf, size_t size, off_t off) {
+    DWORD bread;
+    OVERLAPPED offset;
+    memset(&offset, 0, sizeof (OVERLAPPED));
+    ULARGE_INTEGER bigint;
+    bigint.QuadPart = off;
+    offset.Offset = bigint.LowPart;
+    offset.OffsetHigh = bigint.HighPart;
+    if (!ReadFile(fd, buf, size, &bread, &offset)) {
+        return -1;
+    }
+    return bread;
+}
+
+void globfree(glob_t *_pglob) {
+    size_t i;
+    if (!_pglob->gl_pathv)
+        return;
+    for (i = 0; i < _pglob->gl_pathc; i++)
+        if (_pglob->gl_pathv[i])
+            free(_pglob->gl_pathv[i]);
+    free(_pglob->gl_pathv);
+    _pglob->gl_offs = _pglob->gl_pathc = 0;
+    _pglob->gl_pathv = NULL;
+}
+
+int glob(const char *pattern, int flags,
+        int (*errfunc) (const char *epath, int eerrno),
+        glob_t *pglob) {
+    WIN32_FIND_DATAA stat;
+    char *directory = NULL;
+    int dirlen = 0;
+    /* init pglob */
+    pglob->gl_pathc = 0;
+    pglob->gl_offs = 10;
+    if ((pglob->gl_pathv = calloc(10, sizeof (char *))) == NULL)
+        return GLOB_NOSPACE;
+    char *separator = strrchr(pattern, '/');
+
+    if (separator != NULL) {
+        directory = tccalloc(1, separator - pattern + 2);
+        strncpy(directory, pattern, separator - pattern + 1);
+        dirlen = strlen(directory);
+    }
+    HANDLE h = FindFirstFileA(pattern, &stat);
+    if (h == INVALID_HANDLE_VALUE) {
+        globfree(pglob);
+        if (directory != NULL)
+            TCFREE(directory);
+        return GLOB_ABORTED;
+    }
+    do {
+        /* add new path to list */
+        char *entry = tccalloc(1, strlen(stat.cFileName) + dirlen + 1);
+        if (directory != NULL) {
+            strcpy(entry, directory);
+        }
+        strcat(entry, stat.cFileName);
+        pglob->gl_pathv[pglob->gl_pathc++] = entry;
+        if (pglob->gl_pathc == pglob->gl_offs) {
+            /* increase array size */
+            void *tmp = realloc(pglob->gl_pathv, sizeof (char *)*(pglob->gl_offs + 10));
+            if (tmp == NULL) {
+                globfree(pglob);
+                if (directory != NULL)
+                    TCFREE(directory);
+                return GLOB_NOSPACE;
+            }
+            pglob->gl_offs += 10;
+            pglob->gl_pathv = tmp;
+        }
+    } while (FindNextFileA(h, &stat));
+    FindClose(h);
+    if (directory != NULL)
+        TCFREE(directory);
+    return 0;
+}
+
+
diff --git a/tcejdb/win32/platform.h b/tcejdb/win32/platform.h
new file mode 100644 (file)
index 0000000..a6304e9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * File:   platform.h
+ * Author: adam
+ *
+ * Created on March 31, 2013, 9:34 PM
+ */
+
+#ifndef PLATFORM_H
+#define        PLATFORM_H
+
+#include "../basedefs.h"
+#include <stddef.h>
+#include <time.h>
+#include <direct.h>
+#include <sys/stat.h>
+
+typedef struct {
+    size_t gl_pathc; /* Count of paths matched so far  */
+    char **gl_pathv; /* List of matched pathnames.  */
+    size_t gl_offs; /* Slots to reserve in gl_pathv.  */
+} glob_t;
+
+#define GLOB_ERR 1
+#define GLOB_MARK 0
+#define GLOB_NOSORT 2
+#define GLOB_DOOFFS 0
+#define GLOB_NOCHECK 0
+#define GLOB_APPEND 0
+#define GLOB_NOESCAPE 0
+#define GLOB_PERIOD 0
+#define GLOB_ALTDIRFUNC 0
+#define GLOB_BRACE 0
+#define GLOB_NOMAGIC 0
+#define GLOB_TILDE 0
+#define GLOB_TILDE_CHECK 0
+#define GLOB_ONLYDIR 4
+
+#define GLOB_NOSPACE -1
+#define GLOB_ABORTED -2
+#define GLOB_NOMATCH -3
+
+int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob);
+void globfree(glob_t *pglob);
+struct tm *gmtime_r(const time_t *timep, struct tm *result);
+struct tm *localtime_r(const time_t *timep, struct tm *result);
+int win_fstat(HANDLE fh, struct stat *buf);
+ssize_t win_pwrite(HANDLE fd, const void *buf, size_t count, off_t offset);
+ssize_t win_pread(HANDLE fd, void *buf, size_t size, off_t off);
+
+#define mkdir(a, b) _mkdir(a)
+#define fstat win_fstat
+#define lstat stat
+#define sysconf_SC_CLK_TCK 64
+#define fsync(a) !FlushFileBuffers(a)
+#define pwrite win_pwrite
+#define pread win_pread
+
+
+#ifndef WIFEXITED
+#define WIFEXITED(S) 1
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(S) (S)
+#endif
+
+#endif /* PLATFORM_H */
+