X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FDB_File%2FDB_File.xs;h=ed3a7fa3e044f780dbf1e74f53123b73ec7525ba;hb=3e3318e754fa4289ad1c682811dbe6a31cd59e26;hp=b6da38609d600212d2763f442d4f4d2b0d268b72;hpb=6c5989e9d8ff294ed369afe5749cd5b1711c88c5;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs index b6da386..ed3a7fa 100644 --- a/ext/DB_File/DB_File.xs +++ b/ext/DB_File/DB_File.xs @@ -2,13 +2,13 @@ DB_File.xs -- Perl 5 interface to Berkeley DB - written by Paul Marquess (pmarquess@bfsec.bt.co.uk) - last modified 2nd Feb 1998 - version 1.58 + written by Paul Marquess + last modified 6th June 1999 + version 1.67 All comments/suggestions/problems are welcome - Copyright (c) 1995, 1996, 1997, 1998 Paul Marquess. All rights reserved. + Copyright (c) 1995-9 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -54,6 +54,21 @@ 1.58 - Fixed a problem with the use of sv_setpvn. When the size is specified as 0, it does a strlen on the data. This was ok for DB 1.x, but isn't for DB 2.x. + 1.59 - No change to DB_File.xs + 1.60 - Some code tidy up + 1.61 - added flagSet macro for DB 2.5.x + fixed typo in O_RDONLY test. + 1.62 - No change to DB_File.xs + 1.63 - Fix to alllow DB 2.6.x to build. + 1.64 - Tidied up the 1.x to 2.x flags mapping code. + Added a patch from Mark Kettenis + to fix a flag mapping problem with O_RDONLY on the Hurd + 1.65 - Fixed a bug in the PUSH logic. + Added BOOT check that using 2.3.4 or greater + 1.66 - Added DBM filter code + 1.67 - Backed off the use of newSVpvn. + Fixed DBM Filter code for Perl 5.004. + Fixed a small memory leak in the filter code. @@ -63,6 +78,25 @@ #include "perl.h" #include "XSUB.h" +#ifndef PERL_VERSION +#include "patchlevel.h" +#define PERL_REVISION 5 +#define PERL_VERSION PATCHLEVEL +#define PERL_SUBVERSION SUBVERSION +#endif + +#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 )) + +# define PL_sv_undef sv_undef +# define PL_na na + +#endif + +/* DEFSV appears first in 5.004_56 */ +#ifndef DEFSV +#define DEFSV GvSV(defgv) +#endif + /* Being the Berkeley DB we prefer the (which will be * shortly #included by the ) __attribute__ to the possibly * already defined __attribute__, for example by GNUC or by Perl. */ @@ -80,6 +114,7 @@ #include /* #define TRACE */ +#define DBM_FILTERING @@ -151,6 +186,12 @@ typedef db_recno_t recno_t; #define DBT_flags(x) x.flags = 0 #define DB_flags(x, v) x |= v +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5 +#define flagSet(flags, bitmask) ((flags) & (bitmask)) +#else +#define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask)) +#endif + #else /* db version 1.x */ typedef union INFO { @@ -203,6 +244,7 @@ typedef union INFO { #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag) #define DBT_flags(x) #define DB_flags(x, v) +#define flagSet(flags, bitmask) ((flags) & (bitmask)) #endif /* db version 1 */ @@ -214,10 +256,11 @@ typedef union INFO { #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags) #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) + #ifdef DB_VERSION_MAJOR #define db_DESTROY(db) ((db->dbp)->close)(db->dbp, 0) #define db_close(db) ((db->dbp)->close)(db->dbp, 0) -#define db_del(db, key, flags) ((flags & R_CURSOR) \ +#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \ ? ((db->cursor)->c_del)(db->cursor, 0) \ : ((db->dbp)->del)(db->dbp, NULL, &key, flags) ) @@ -230,6 +273,7 @@ typedef union INFO { #endif + #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags) typedef struct { @@ -243,28 +287,64 @@ typedef struct { #ifdef DB_VERSION_MAJOR DBC * cursor ; #endif +#ifdef DBM_FILTERING + SV * filter_fetch_key ; + SV * filter_store_key ; + SV * filter_fetch_value ; + SV * filter_store_value ; + int filtering ; +#endif /* DBM_FILTERING */ + } DB_File_type; typedef DB_File_type * DB_File ; typedef DBT DBTKEY ; +#ifdef DBM_FILTERING + +#define ckFilter(arg,type,name) \ + if (db->type) { \ + SV * save_defsv ; \ + /* printf("filtering %s\n", name) ;*/ \ + if (db->filtering) \ + croak("recursion detected in %s", name) ; \ + db->filtering = TRUE ; \ + save_defsv = newSVsv(DEFSV) ; \ + sv_setsv(DEFSV, arg) ; \ + PUSHMARK(sp) ; \ + (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \ + sv_setsv(arg, DEFSV) ; \ + sv_setsv(DEFSV, save_defsv) ; \ + SvREFCNT_dec(save_defsv) ; \ + db->filtering = FALSE ; \ + /*printf("end of filtering %s\n", name) ;*/ \ + } + +#else + +#define ckFilter(arg,type, name) + +#endif /* DBM_FILTERING */ + #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s) -#define OutputValue(arg, name) \ - { if (RETVAL == 0) { \ - my_sv_setpvn(arg, name.data, name.size) ; \ - } \ +#define OutputValue(arg, name) \ + { if (RETVAL == 0) { \ + my_sv_setpvn(arg, name.data, name.size) ; \ + ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \ + } \ } -#define OutputKey(arg, name) \ - { if (RETVAL == 0) \ - { \ - if (db->type != DB_RECNO) { \ - my_sv_setpvn(arg, name.data, name.size); \ - } \ - else \ - sv_setiv(arg, (I32)*(I32*)name.data - 1); \ - } \ +#define OutputKey(arg, name) \ + { if (RETVAL == 0) \ + { \ + if (db->type != DB_RECNO) { \ + my_sv_setpvn(arg, name.data, name.size); \ + } \ + else \ + sv_setiv(arg, (I32)*(I32*)name.data - 1); \ + ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \ + } \ } @@ -277,21 +357,21 @@ static DBTKEY empty ; #ifdef DB_VERSION_MAJOR static int -db_put(db, key, value, flags) -DB_File db ; -DBTKEY key ; -DBT value ; -u_int flags ; - +db_put(DB_File db, DBTKEY key, DBT value, u_int flags) { int status ; - if (flags & R_CURSOR) { + if (flagSet(flags, R_CURSOR)) { status = ((db->cursor)->c_del)(db->cursor, 0); if (status != 0) return status ; +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5 flags &= ~R_CURSOR ; +#else + flags &= ~DB_OPFLAGS_MASK ; +#endif + } return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ; @@ -301,7 +381,7 @@ u_int flags ; #endif /* DB_VERSION_MAJOR */ static void -GetVersionInfo() +GetVersionInfo(pTHX) { SV * ver_sv = perl_get_sv("DB_File::db_version", TRUE) ; #ifdef DB_VERSION_MAJOR @@ -309,12 +389,12 @@ GetVersionInfo() (void)db_version(&Major, &Minor, &Patch) ; - /* check that libdb is recent enough */ - if (Major == 2 && Minor == 0 && Patch < 5) - croak("DB_File needs Berkeley DB 2.0.5 or greater, you have %d.%d.%d\n", + /* check that libdb is recent enough -- we need 2.3.4 or greater */ + if (Major == 2 && (Minor < 3 || (Minor == 3 && Patch < 4))) + croak("DB_File needs Berkeley DB 2.3.4 or greater, you have %d.%d.%d\n", Major, Minor, Patch) ; -#if PATCHLEVEL > 3 +#if PERL_VERSION > 3 sv_setpvf(ver_sv, "%d.%d", Major, Minor) ; #else { @@ -332,10 +412,9 @@ GetVersionInfo() static int -btree_compare(key1, key2) -const DBT * key1 ; -const DBT * key2 ; +btree_compare(const DBT *key1, const DBT *key2) { + dTHX; dSP ; void * data1, * data2 ; int retval ; @@ -356,8 +435,8 @@ const DBT * key2 ; ENTER ; SAVETMPS; - PUSHMARK(sp) ; - EXTEND(sp,2) ; + PUSHMARK(SP) ; + EXTEND(SP,2) ; PUSHs(sv_2mortal(newSVpv(data1,key1->size))); PUSHs(sv_2mortal(newSVpv(data2,key2->size))); PUTBACK ; @@ -379,10 +458,9 @@ const DBT * key2 ; } static DB_Prefix_t -btree_prefix(key1, key2) -const DBT * key1 ; -const DBT * key2 ; +btree_prefix(const DBT *key1, const DBT *key2) { + dTHX; dSP ; void * data1, * data2 ; int retval ; @@ -403,8 +481,8 @@ const DBT * key2 ; ENTER ; SAVETMPS; - PUSHMARK(sp) ; - EXTEND(sp,2) ; + PUSHMARK(SP) ; + EXTEND(SP,2) ; PUSHs(sv_2mortal(newSVpv(data1,key1->size))); PUSHs(sv_2mortal(newSVpv(data2,key2->size))); PUTBACK ; @@ -426,10 +504,9 @@ const DBT * key2 ; } static DB_Hash_t -hash_cb(data, size) -const void * data ; -size_t size ; +hash_cb(const void *data, size_t size) { + dTHX; dSP ; int retval ; int count ; @@ -441,7 +518,7 @@ size_t size ; ENTER ; SAVETMPS; - PUSHMARK(sp) ; + PUSHMARK(SP) ; XPUSHs(sv_2mortal(newSVpv((char*)data,size))); PUTBACK ; @@ -466,8 +543,7 @@ size_t size ; #ifdef TRACE static void -PrintHash(hash) -INFO * hash ; +PrintHash(INFO *hash) { printf ("HASH Info\n") ; printf (" hash = %s\n", @@ -481,8 +557,7 @@ INFO * hash ; } static void -PrintRecno(recno) -INFO * recno ; +PrintRecno(INFO *recno) { printf ("RECNO Info\n") ; printf (" flags = %d\n", recno->db_RE_flags) ; @@ -495,8 +570,7 @@ INFO * recno ; } static void -PrintBtree(btree) -INFO * btree ; +PrintBtree(INFO *btree) { printf ("BTREE Info\n") ; printf (" compare = %s\n", @@ -523,8 +597,7 @@ INFO * btree ; static I32 -GetArrayLength(db) -DB_File db ; +GetArrayLength(pTHX_ DB_File db) { DBT key ; DBT value ; @@ -533,14 +606,6 @@ DB_File db ; DBT_flags(key) ; DBT_flags(value) ; RETVAL = do_SEQ(db, key, value, R_LAST) ; - if (RETVAL < 0 && errno == EBADF) - { - recno_t oops = -1; - key.data = &oops; - key.size = sizeof(oops); - db_get(db, key, value, 0); - RETVAL = do_SEQ(db, key, value, R_LAST) ; - } if (RETVAL == 0) RETVAL = *(I32 *)key.data ; else /* No key means empty file */ @@ -550,13 +615,11 @@ DB_File db ; } static recno_t -GetRecnoKey(db, value) -DB_File db ; -I32 value ; +GetRecnoKey(pTHX_ DB_File db, I32 value) { if (value < 0) { /* Get the length of the array */ - I32 length = GetArrayLength(db) ; + I32 length = GetArrayLength(aTHX_ db) ; /* check for attempt to write before start of array */ if (length + value + 1 <= 0) @@ -571,23 +634,24 @@ I32 value ; } static DB_File -ParseOpenInfo(isHASH, name, flags, mode, sv) -int isHASH ; -char * name ; -int flags ; -int mode ; -SV * sv ; +ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv) { SV ** svp; HV * action ; DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ; void * openinfo = NULL ; INFO * info = &RETVAL->info ; + STRLEN n_a; /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */ Zero(RETVAL, 1, DB_File_type) ; /* Default to HASH */ +#ifdef DBM_FILTERING + RETVAL->filtering = 0 ; + RETVAL->filter_fetch_key = RETVAL->filter_store_key = + RETVAL->filter_fetch_value = RETVAL->filter_store_value = +#endif /* DBM_FILTERING */ RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ; RETVAL->type = DB_HASH ; @@ -724,11 +788,11 @@ SV * sv ; #endif svp = hv_fetch(action, "bfname", 6, FALSE); if (svp && SvOK(*svp)) { - char * ptr = SvPV(*svp,na) ; + char * ptr = SvPV(*svp,n_a) ; #ifdef DB_VERSION_MAJOR - name = (char*) na ? ptr : NULL ; + name = (char*) n_a ? ptr : NULL ; #else - info->db_RE_bfname = (char*) (na ? ptr : NULL) ; + info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ; #endif } else @@ -744,7 +808,7 @@ SV * sv ; { int value ; if (SvPOK(*svp)) - value = (int)*SvPV(*svp, na) ; + value = (int)*SvPV(*svp, n_a) ; else value = SvIV(*svp) ; @@ -762,7 +826,7 @@ SV * sv ; if (svp && SvOK(*svp)) { if (SvPOK(*svp)) - info->db_RE_bval = (u_char)*SvPV(*svp, na) ; + info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ; else info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ; DB_flags(info->flags, DB_DELIMITER) ; @@ -806,26 +870,26 @@ SV * sv ; if ((flags & O_CREAT) == O_CREAT) Flags |= DB_CREATE ; -#ifdef O_NONBLOCK - if ((flags & O_NONBLOCK) == O_NONBLOCK) - Flags |= DB_EXCL ; -#endif - #if O_RDONLY == 0 if (flags == O_RDONLY) #else - if (flags & O_RDONLY) == O_RDONLY) + if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR) #endif Flags |= DB_RDONLY ; -#ifdef O_NONBLOCK +#ifdef O_TRUNC if ((flags & O_TRUNC) == O_TRUNC) Flags |= DB_TRUNCATE ; #endif status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ; if (status == 0) +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ; +#else + status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor, + 0) ; +#endif if (status) RETVAL->dbp = NULL ; @@ -839,18 +903,8 @@ SV * sv ; } -static int -not_here(s) -char *s; -{ - croak("DB_File::%s not implemented on this architecture", s); - return -1; -} - static double -constant(name, arg) -char *name; -int arg; +constant(char *name, int arg) { errno = 0; switch (*name) { @@ -1083,7 +1137,7 @@ MODULE = DB_File PACKAGE = DB_File PREFIX = db_ BOOT: { - GetVersionInfo() ; + GetVersionInfo(aTHX) ; empty.data = &zero ; empty.size = sizeof(recno_t) ; @@ -1106,14 +1160,15 @@ db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_H { char * name = (char *) NULL ; SV * sv = (SV *) NULL ; + STRLEN n_a; if (items >= 3 && SvOK(ST(2))) - name = (char*) SvPV(ST(2), na) ; + name = (char*) SvPV(ST(2), n_a) ; if (items == 6) sv = ST(5) ; - RETVAL = ParseOpenInfo(isHASH, name, flags, mode, sv) ; + RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ; if (RETVAL->dbp == NULL) RETVAL = NULL ; } @@ -1132,6 +1187,16 @@ db_DESTROY(db) SvREFCNT_dec(db->compare) ; if (db->prefix) SvREFCNT_dec(db->prefix) ; +#ifdef DBM_FILTERING + if (db->filter_fetch_key) + SvREFCNT_dec(db->filter_fetch_key) ; + if (db->filter_store_key) + SvREFCNT_dec(db->filter_store_key) ; + if (db->filter_fetch_value) + SvREFCNT_dec(db->filter_fetch_value) ; + if (db->filter_store_value) + SvREFCNT_dec(db->filter_store_value) ; +#endif /* DBM_FILTERING */ Safefree(db) ; #ifdef DB_VERSION_MAJOR if (RETVAL > 0) @@ -1177,8 +1242,7 @@ db_FETCH(db, key, flags=0) /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */ RETVAL = db_get(db, key, value, flags) ; ST(0) = sv_newmortal(); - if (RETVAL == 0) - my_sv_setpvn(ST(0), value.data, value.size); + OutputValue(ST(0), value) } int @@ -1198,20 +1262,13 @@ db_FIRSTKEY(db) { DBTKEY key ; DBT value ; - DB * Db = db->dbp ; DBT_flags(key) ; DBT_flags(value) ; CurrentDB = db ; RETVAL = do_SEQ(db, key, value, R_FIRST) ; ST(0) = sv_newmortal(); - if (RETVAL == 0) - { - if (db->type != DB_RECNO) - my_sv_setpvn(ST(0), key.data, key.size); - else - sv_setiv(ST(0), (I32)*(I32*)key.data - 1); - } + OutputKey(ST(0), key) ; } int @@ -1221,19 +1278,12 @@ db_NEXTKEY(db, key) CODE: { DBT value ; - DB * Db = db->dbp ; DBT_flags(value) ; CurrentDB = db ; RETVAL = do_SEQ(db, key, value, R_NEXT) ; ST(0) = sv_newmortal(); - if (RETVAL == 0) - { - if (db->type != DB_RECNO) - my_sv_setpvn(ST(0), key.data, key.size); - else - sv_setiv(ST(0), (I32)*(I32*)key.data - 1); - } + OutputKey(ST(0), key) ; } # @@ -1251,6 +1301,7 @@ unshift(db, ...) int i ; int One ; DB * Db = db->dbp ; + STRLEN n_a; DBT_flags(key) ; DBT_flags(value) ; @@ -1264,8 +1315,8 @@ unshift(db, ...) #endif for (i = items-1 ; i > 0 ; --i) { - value.data = SvPV(ST(i), na) ; - value.size = na ; + value.data = SvPV(ST(i), n_a) ; + value.size = n_a ; One = 1 ; key.data = &One ; key.size = sizeof(int) ; @@ -1289,7 +1340,6 @@ pop(db) { DBTKEY key ; DBT value ; - DB * Db = db->dbp ; DBT_flags(key) ; DBT_flags(value) ; @@ -1302,10 +1352,10 @@ pop(db) if (RETVAL == 0) { /* the call to del will trash value, so take a copy now */ - my_sv_setpvn(ST(0), value.data, value.size); + OutputValue(ST(0), value) ; RETVAL = db_del(db, key, R_CURSOR) ; if (RETVAL != 0) - sv_setsv(ST(0), &sv_undef); + sv_setsv(ST(0), &PL_sv_undef); } } @@ -1317,7 +1367,6 @@ shift(db) { DBT value ; DBTKEY key ; - DB * Db = db->dbp ; DBT_flags(key) ; DBT_flags(value) ; @@ -1329,10 +1378,10 @@ shift(db) if (RETVAL == 0) { /* the call to del will trash value, so take a copy now */ - my_sv_setpvn(ST(0), value.data, value.size); + OutputValue(ST(0), value) ; RETVAL = db_del(db, key, R_CURSOR) ; if (RETVAL != 0) - sv_setsv (ST(0), &sv_undef) ; + sv_setsv (ST(0), &PL_sv_undef) ; } } @@ -1344,42 +1393,43 @@ push(db, ...) CODE: { DBTKEY key ; - DBTKEY * keyptr = &key ; DBT value ; DB * Db = db->dbp ; int i ; + STRLEN n_a; DBT_flags(key) ; DBT_flags(value) ; CurrentDB = db ; - /* Set the Cursor to the Last element */ - RETVAL = do_SEQ(db, key, value, R_LAST) ; - if (RETVAL >= 0) - { - if (RETVAL == 1) - keyptr = &empty ; #ifdef DB_VERSION_MAJOR + RETVAL = 0 ; + key = empty ; for (i = 1 ; i < items ; ++i) { - - ++ (* (int*)key.data) ; - value.data = SvPV(ST(i), na) ; - value.size = na ; - RETVAL = (Db->put)(Db, NULL, &key, &value, 0) ; + value.data = SvPV(ST(i), n_a) ; + value.size = n_a ; + RETVAL = (Db->put)(Db, NULL, &key, &value, DB_APPEND) ; if (RETVAL != 0) break; } -#else +#else + + /* Set the Cursor to the Last element */ + RETVAL = do_SEQ(db, key, value, R_LAST) ; + if (RETVAL >= 0) + { + if (RETVAL == 1) + key = empty ; for (i = items - 1 ; i > 0 ; --i) { - value.data = SvPV(ST(i), na) ; - value.size = na ; - RETVAL = (Db->put)(Db, keyptr, &value, R_IAFTER) ; + value.data = SvPV(ST(i), n_a) ; + value.size = n_a ; + RETVAL = (Db->put)(Db, &key, &value, R_IAFTER) ; if (RETVAL != 0) break; } -#endif } +#endif } OUTPUT: RETVAL @@ -1391,7 +1441,7 @@ length(db) ALIAS: FETCHSIZE = 1 CODE: CurrentDB = db ; - RETVAL = GetArrayLength(db) ; + RETVAL = GetArrayLength(aTHX_ db) ; OUTPUT: RETVAL @@ -1455,7 +1505,7 @@ db_put(db, key, value, flags=0) #endif OUTPUT: RETVAL - key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key); + key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key); int db_fd(db) @@ -1514,3 +1564,56 @@ db_seq(db, key, value, flags) key value +#ifdef DBM_FILTERING + +#define setFilter(type) \ + { \ + if (db->type) \ + RETVAL = sv_mortalcopy(db->type) ; \ + ST(0) = RETVAL ; \ + if (db->type && (code == &PL_sv_undef)) { \ + SvREFCNT_dec(db->type) ; \ + db->type = NULL ; \ + } \ + else if (code) { \ + if (db->type) \ + sv_setsv(db->type, code) ; \ + else \ + db->type = newSVsv(code) ; \ + } \ + } + + +SV * +filter_fetch_key(db, code) + DB_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + setFilter(filter_fetch_key) ; + +SV * +filter_store_key(db, code) + DB_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + setFilter(filter_store_key) ; + +SV * +filter_fetch_value(db, code) + DB_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + setFilter(filter_fetch_value) ; + +SV * +filter_store_value(db, code) + DB_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + setFilter(filter_store_value) ; + +#endif /* DBM_FILTERING */