DB_File.xs
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:46k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* 
  2.  DB_File.xs -- Perl 5 interface to Berkeley DB 
  3.  written by Paul Marquess <Paul.Marquess@btinternet.com>
  4.  last modified 15th January 2001
  5.  version 1.76
  6.  All comments/suggestions/problems are welcome
  7.      Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
  8.      This program is free software; you can redistribute it and/or
  9.      modify it under the same terms as Perl itself.
  10.  Changes:
  11. 0.1 -  Initial Release
  12. 0.2 -  No longer bombs out if dbopen returns an error.
  13. 0.3 -  Added some support for multiple btree compares
  14. 1.0 -  Complete support for multiple callbacks added.
  15.        Fixed a problem with pushing a value onto an empty list.
  16. 1.01 -  Fixed a SunOS core dump problem.
  17. The return value from TIEHASH wasn't set to NULL when
  18. dbopen returned an error.
  19. 1.02 -  Use ALIAS to define TIEARRAY.
  20. Removed some redundant commented code.
  21. Merged OS2 code into the main distribution.
  22. Allow negative subscripts with RECNO interface.
  23. Changed the default flags to O_CREAT|O_RDWR
  24. 1.03 -  Added EXISTS
  25. 1.04 -  fixed a couple of bugs in hash_cb. Patches supplied by
  26. Dave Hammen, hammen@gothamcity.jsc.nasa.gov
  27. 1.05 -  Added logic to allow prefix & hash types to be specified via
  28. Makefile.PL
  29. 1.06 -  Minor namespace cleanup: Localized PrintBtree.
  30. 1.07 -  Fixed bug with RECNO, where bval wasn't defaulting to "n". 
  31. 1.08 -  No change to DB_File.xs
  32. 1.09 -  Default mode for dbopen changed to 0666
  33. 1.10 -  Fixed fd method so that it still returns -1 for
  34. in-memory files when db 1.86 is used.
  35. 1.11 -  No change to DB_File.xs
  36. 1.12 -  No change to DB_File.xs
  37. 1.13 -  Tidied up a few casts.     
  38. 1.14 - Made it illegal to tie an associative array to a RECNO
  39. database and an ordinary array to a HASH or BTREE database.
  40. 1.50 -  Make work with both DB 1.x or DB 2.x
  41. 1.51 -  Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
  42. 1.52 -  Patch from Gisle Aas <gisle@aas.no> to suppress "use of 
  43. undefined value" warning with db_get and db_seq.
  44. 1.53 -  Added DB_RENUMBER to flags for recno.
  45. 1.54 -  Fixed bug in the fd method
  46.         1.55 -  Fix for AIX from Jarkko Hietaniemi
  47.         1.56 -  No change to DB_File.xs
  48.         1.57 -  added the #undef op to allow building with Threads support.
  49. 1.58 -  Fixed a problem with the use of sv_setpvn. When the
  50. size is specified as 0, it does a strlen on the data.
  51. This was ok for DB 1.x, but isn't for DB 2.x.
  52.         1.59 -  No change to DB_File.xs
  53.         1.60 -  Some code tidy up
  54.         1.61 -  added flagSet macro for DB 2.5.x
  55. fixed typo in O_RDONLY test.
  56.         1.62 -  No change to DB_File.xs
  57.         1.63 -  Fix to alllow DB 2.6.x to build.
  58.         1.64 -  Tidied up the 1.x to 2.x flags mapping code.
  59. Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
  60. to fix a flag mapping problem with O_RDONLY on the Hurd
  61.         1.65 -  Fixed a bug in the PUSH logic.
  62. Added BOOT check that using 2.3.4 or greater
  63.         1.66 -  Added DBM filter code
  64.         1.67 -  Backed off the use of newSVpvn.
  65. Fixed DBM Filter code for Perl 5.004.
  66. Fixed a small memory leak in the filter code.
  67.         1.68 -  fixed backward compatability bug with R_IAFTER & R_IBEFORE
  68. merged in the 5.005_58 changes
  69.         1.69 -  fixed a bug in push -- DB_APPEND wasn't working properly.
  70. Fixed the R_SETCURSOR bug introduced in 1.68
  71. Added a new Perl variable $DB_File::db_ver 
  72.         1.70 -  Initialise $DB_File::db_ver and $DB_File::db_version with 
  73. GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
  74. Added a BOOT check to test for equivalent versions of db.h &
  75. libdb.a/so.
  76.         1.71 -  Support for Berkeley DB version 3.
  77. Support for Berkeley DB 2/3's backward compatability mode.
  78. Rewrote push
  79.         1.72 -  No change to DB_File.xs
  80.         1.73 -  No change to DB_File.xs
  81.         1.74 -  A call to open needed parenthesised to stop it clashing
  82.                 with a win32 macro.
  83. Added Perl core patches 7703 & 7801.
  84.         1.75 -  Fixed Perl core patch 7703.
  85. Added suppport to allow DB_File to be built with 
  86. Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
  87. needed to be changed.
  88.         1.76 -  No change to DB_File.xs
  89. */
  90. #include "EXTERN.h"  
  91. #include "perl.h"
  92. #include "XSUB.h"
  93. #ifndef PERL_VERSION
  94. #    include "patchlevel.h"
  95. #    define PERL_REVISION 5
  96. #    define PERL_VERSION PATCHLEVEL
  97. #    define PERL_SUBVERSION SUBVERSION
  98. #endif
  99. #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
  100. #    define PL_sv_undef sv_undef
  101. #    define PL_na na
  102. #endif
  103. /* DEFSV appears first in 5.004_56 */
  104. #ifndef DEFSV
  105. #    define DEFSV GvSV(defgv)
  106. #endif
  107. /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
  108.  * shortly #included by the <db.h>) __attribute__ to the possibly
  109.  * already defined __attribute__, for example by GNUC or by Perl. */
  110. #undef __attribute__
  111. /* If Perl has been compiled with Threads support,the symbol op will
  112.    be defined here. This clashes with a field name in db.h, so get rid of it.
  113.  */
  114. #ifdef op
  115. #    undef op
  116. #endif
  117. #ifdef COMPAT185
  118. #    include <db_185.h>
  119. #else
  120. #    include <db.h>
  121. #endif
  122. #ifdef CAN_PROTOTYPE
  123. extern void __getBerkeleyDBInfo(void);
  124. #endif
  125. #ifndef pTHX
  126. #    define pTHX
  127. #    define pTHX_
  128. #    define aTHX
  129. #    define aTHX_
  130. #endif
  131. #ifndef newSVpvn
  132. #    define newSVpvn(a,b) newSVpv(a,b)
  133. #endif
  134. #include <fcntl.h> 
  135. /* #define TRACE */
  136. #define DBM_FILTERING
  137. #ifdef TRACE
  138. #    define Trace(x)        printf x
  139. #else
  140. #    define Trace(x)
  141. #endif
  142. #define DBT_clear(x) Zero(&x, 1, DBT) ;
  143. #ifdef DB_VERSION_MAJOR
  144. #if DB_VERSION_MAJOR == 2
  145. #    define BERKELEY_DB_1_OR_2
  146. #endif
  147. #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
  148. #    define AT_LEAST_DB_3_2
  149. #endif
  150. /* map version 2 features & constants onto their version 1 equivalent */
  151. #ifdef DB_Prefix_t
  152. #    undef DB_Prefix_t
  153. #endif
  154. #define DB_Prefix_t size_t
  155. #ifdef DB_Hash_t
  156. #    undef DB_Hash_t
  157. #endif
  158. #define DB_Hash_t u_int32_t
  159. /* DBTYPE stays the same */
  160. /* HASHINFO, RECNOINFO and BTREEINFO  map to DB_INFO */
  161. #if DB_VERSION_MAJOR == 2
  162.     typedef DB_INFO INFO ;
  163. #else /* DB_VERSION_MAJOR > 2 */
  164. #    define DB_FIXEDLEN (0x8000)
  165. #endif /* DB_VERSION_MAJOR == 2 */
  166. /* version 2 has db_recno_t in place of recno_t */
  167. typedef db_recno_t recno_t;
  168. #define R_CURSOR        DB_SET_RANGE
  169. #define R_FIRST         DB_FIRST
  170. #define R_IAFTER        DB_AFTER
  171. #define R_IBEFORE       DB_BEFORE
  172. #define R_LAST          DB_LAST
  173. #define R_NEXT          DB_NEXT
  174. #define R_NOOVERWRITE   DB_NOOVERWRITE
  175. #define R_PREV          DB_PREV
  176. #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
  177. #  define R_SETCURSOR 0x800000
  178. #else
  179. #  define R_SETCURSOR (-100)
  180. #endif
  181. #define R_RECNOSYNC     0
  182. #define R_FIXEDLEN DB_FIXEDLEN
  183. #define R_DUP DB_DUP
  184. #define db_HA_hash  h_hash
  185. #define db_HA_ffactor h_ffactor
  186. #define db_HA_nelem h_nelem
  187. #define db_HA_bsize db_pagesize
  188. #define db_HA_cachesize db_cachesize
  189. #define db_HA_lorder db_lorder
  190. #define db_BT_compare bt_compare
  191. #define db_BT_prefix bt_prefix
  192. #define db_BT_flags flags
  193. #define db_BT_psize db_pagesize
  194. #define db_BT_cachesize db_cachesize
  195. #define db_BT_lorder db_lorder
  196. #define db_BT_maxkeypage
  197. #define db_BT_minkeypage
  198. #define db_RE_reclen re_len
  199. #define db_RE_flags flags
  200. #define db_RE_bval re_pad
  201. #define db_RE_bfname re_source
  202. #define db_RE_psize db_pagesize
  203. #define db_RE_cachesize db_cachesize
  204. #define db_RE_lorder db_lorder
  205. #define TXN NULL,
  206. #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
  207. #define DBT_flags(x) x.flags = 0
  208. #define DB_flags(x, v) x |= v 
  209. #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
  210. #    define flagSet(flags, bitmask) ((flags) & (bitmask))
  211. #else
  212. #    define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
  213. #endif
  214. #else /* db version 1.x */
  215. #define BERKELEY_DB_1
  216. #define BERKELEY_DB_1_OR_2
  217. typedef union INFO {
  218.         HASHINFO  hash ;
  219.         RECNOINFO  recno ;
  220.         BTREEINFO  btree ;
  221.       } INFO ;
  222. #ifdef mDB_Prefix_t 
  223. #  ifdef DB_Prefix_t
  224. #    undef DB_Prefix_t
  225. #  endif
  226. #  define DB_Prefix_t mDB_Prefix_t 
  227. #endif
  228. #ifdef mDB_Hash_t
  229. #  ifdef DB_Hash_t
  230. #    undef DB_Hash_t
  231. #  endif
  232. #  define DB_Hash_t mDB_Hash_t
  233. #endif
  234. #define db_HA_hash  hash.hash
  235. #define db_HA_ffactor hash.ffactor
  236. #define db_HA_nelem hash.nelem
  237. #define db_HA_bsize hash.bsize
  238. #define db_HA_cachesize hash.cachesize
  239. #define db_HA_lorder hash.lorder
  240. #define db_BT_compare btree.compare
  241. #define db_BT_prefix btree.prefix
  242. #define db_BT_flags btree.flags
  243. #define db_BT_psize btree.psize
  244. #define db_BT_cachesize btree.cachesize
  245. #define db_BT_lorder btree.lorder
  246. #define db_BT_maxkeypage btree.maxkeypage
  247. #define db_BT_minkeypage btree.minkeypage
  248. #define db_RE_reclen recno.reclen
  249. #define db_RE_flags recno.flags
  250. #define db_RE_bval recno.bval
  251. #define db_RE_bfname recno.bfname
  252. #define db_RE_psize recno.psize
  253. #define db_RE_cachesize recno.cachesize
  254. #define db_RE_lorder recno.lorder
  255. #define TXN
  256. #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
  257. #define DBT_flags(x)
  258. #define DB_flags(x, v)
  259. #define flagSet(flags, bitmask)        ((flags) & (bitmask))
  260. #endif /* db version 1 */
  261. #define db_DELETE(db, key, flags)       ((db->dbp)->del)(db->dbp, TXN &key, flags)
  262. #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
  263. #define db_FETCH(db, key, flags)        ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
  264. #define db_sync(db, flags)              ((db->dbp)->sync)(db->dbp, flags)
  265. #define db_get(db, key, value, flags)   ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
  266. #ifdef DB_VERSION_MAJOR
  267. #define db_DESTROY(db)                  ( db->cursor->c_close(db->cursor),
  268.   (db->dbp->close)(db->dbp, 0) )
  269. #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
  270. #define db_del(db, key, flags)          (flagSet(flags, R_CURSOR) 
  271. ? ((db->cursor)->c_del)(db->cursor, 0)
  272. : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
  273. #else /* ! DB_VERSION_MAJOR */
  274. #define db_DESTROY(db)                  ((db->dbp)->close)(db->dbp)
  275. #define db_close(db) ((db->dbp)->close)(db->dbp)
  276. #define db_del(db, key, flags)          ((db->dbp)->del)(db->dbp, &key, flags)
  277. #define db_put(db, key, value, flags)   ((db->dbp)->put)(db->dbp, &key, &value, flags)
  278. #endif /* ! DB_VERSION_MAJOR */
  279. #define db_seq(db, key, value, flags)   do_SEQ(db, key, value, flags)
  280. typedef struct {
  281. DBTYPE type ;
  282. DB *  dbp ;
  283. SV * compare ;
  284. SV * prefix ;
  285. SV * hash ;
  286. int in_memory ;
  287. #ifdef BERKELEY_DB_1_OR_2
  288. INFO  info ;
  289. #endif
  290. #ifdef DB_VERSION_MAJOR
  291. DBC * cursor ;
  292. #endif
  293. #ifdef DBM_FILTERING
  294. SV *    filter_fetch_key ;
  295. SV *    filter_store_key ;
  296. SV *    filter_fetch_value ;
  297. SV *    filter_store_value ;
  298. int     filtering ;
  299. #endif /* DBM_FILTERING */
  300. } DB_File_type;
  301. typedef DB_File_type * DB_File ;
  302. typedef DBT DBTKEY ;
  303. #ifdef DBM_FILTERING
  304. #define ckFilter(arg,type,name)
  305. if (db->type) {
  306.     SV * save_defsv ;
  307.             /* printf("filtering %sn", name) ;*/
  308.     if (db->filtering)
  309.         croak("recursion detected in %s", name) ;
  310.     db->filtering = TRUE ;
  311.     save_defsv = newSVsv(DEFSV) ;
  312.     sv_setsv(DEFSV, arg) ;
  313.     PUSHMARK(sp) ;
  314.     (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); 
  315.     sv_setsv(arg, DEFSV) ;
  316.     sv_setsv(DEFSV, save_defsv) ;
  317.     SvREFCNT_dec(save_defsv) ;
  318.     db->filtering = FALSE ;
  319.     /*printf("end of filtering %sn", name) ;*/
  320. }
  321. #else
  322. #define ckFilter(arg,type, name)
  323. #endif /* DBM_FILTERING */
  324. #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
  325. #define OutputValue(arg, name)  
  326. { if (RETVAL == 0) {
  327.       my_sv_setpvn(arg, name.data, name.size) ;
  328.       ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; 
  329.   }
  330. }
  331. #define OutputKey(arg, name)  
  332. { if (RETVAL == 0) 
  333.   { 
  334. if (db->type != DB_RECNO) {
  335.     my_sv_setpvn(arg, name.data, name.size); 
  336. }
  337. else 
  338.     sv_setiv(arg, (I32)*(I32*)name.data - 1); 
  339.       ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; 
  340.   } 
  341. }
  342. /* Internal Global Data */
  343. static recno_t Value ; 
  344. static recno_t zero = 0 ;
  345. static DB_File CurrentDB ;
  346. static DBTKEY empty ;
  347. #ifdef DB_VERSION_MAJOR
  348. static int
  349. #ifdef CAN_PROTOTYPE
  350. db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
  351. #else
  352. db_put(db, key, value, flags)
  353. DB_File db ;
  354. DBTKEY key ;
  355. DBT value ;
  356. u_int flags ;
  357. #endif
  358. {
  359.     int status ;
  360.     if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
  361.         DBC * temp_cursor ;
  362. DBT l_key, l_value;
  363.         
  364. #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
  365.         if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
  366. #else
  367.         if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
  368. #endif
  369.     return (-1) ;
  370. memset(&l_key, 0, sizeof(l_key));
  371. l_key.data = key.data;
  372. l_key.size = key.size;
  373. memset(&l_value, 0, sizeof(l_value));
  374. l_value.data = value.data;
  375. l_value.size = value.size;
  376. if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
  377.     (void)temp_cursor->c_close(temp_cursor);
  378.     return (-1);
  379. }
  380. status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
  381. (void)temp_cursor->c_close(temp_cursor);
  382.     
  383.         return (status) ;
  384.     }
  385.     
  386.     
  387.     if (flagSet(flags, R_CURSOR)) {
  388. return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
  389.     }
  390.     if (flagSet(flags, R_SETCURSOR)) {
  391. if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
  392. return -1 ;
  393.         return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
  394.     
  395.     }
  396.     return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
  397. }
  398. #endif /* DB_VERSION_MAJOR */
  399. static int
  400. #ifdef AT_LEAST_DB_3_2
  401. #ifdef CAN_PROTOTYPE
  402. btree_compare(DB * db, const DBT *key1, const DBT *key2)
  403. #else
  404. btree_compare(db, key1, key2)
  405. DB * db ;
  406. const DBT * key1 ;
  407. const DBT * key2 ;
  408. #endif /* CAN_PROTOTYPE */
  409. #else /* Berkeley DB < 3.2 */
  410. #ifdef CAN_PROTOTYPE
  411. btree_compare(const DBT *key1, const DBT *key2)
  412. #else
  413. btree_compare(key1, key2)
  414. const DBT * key1 ;
  415. const DBT * key2 ;
  416. #endif
  417. #endif
  418. {
  419. #ifdef dTHX
  420.     dTHX;
  421. #endif    
  422.     dSP ;
  423.     void * data1, * data2 ;
  424.     int retval ;
  425.     int count ;
  426.     
  427.     data1 = key1->data ;
  428.     data2 = key2->data ;
  429. #ifndef newSVpvn
  430.     /* As newSVpv will assume that the data pointer is a null terminated C 
  431.        string if the size parameter is 0, make sure that data points to an 
  432.        empty string if the length is 0
  433.     */
  434.     if (key1->size == 0)
  435.         data1 = "" ; 
  436.     if (key2->size == 0)
  437.         data2 = "" ;
  438. #endif
  439.     ENTER ;
  440.     SAVETMPS;
  441.     PUSHMARK(SP) ;
  442.     EXTEND(SP,2) ;
  443.     PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
  444.     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
  445.     PUTBACK ;
  446.     count = perl_call_sv(CurrentDB->compare, G_SCALAR); 
  447.     SPAGAIN ;
  448.     if (count != 1)
  449.         croak ("DB_File btree_compare: expected 1 return value from compare sub, got %dn", count) ;
  450.     retval = POPi ;
  451.     PUTBACK ;
  452.     FREETMPS ;
  453.     LEAVE ;
  454.     return (retval) ;
  455. }
  456. static DB_Prefix_t
  457. #ifdef AT_LEAST_DB_3_2
  458. #ifdef CAN_PROTOTYPE
  459. btree_prefix(DB * db, const DBT *key1, const DBT *key2)
  460. #else
  461. btree_prefix(db, key1, key2)
  462. Db * db ;
  463. const DBT * key1 ;
  464. const DBT * key2 ;
  465. #endif
  466. #else /* Berkeley DB < 3.2 */
  467. #ifdef CAN_PROTOTYPE
  468. btree_prefix(const DBT *key1, const DBT *key2)
  469. #else
  470. btree_prefix(key1, key2)
  471. const DBT * key1 ;
  472. const DBT * key2 ;
  473. #endif
  474. #endif
  475. {
  476. #ifdef dTHX
  477.     dTHX;
  478. #endif    
  479.     dSP ;
  480.     void * data1, * data2 ;
  481.     int retval ;
  482.     int count ;
  483.     
  484.     data1 = key1->data ;
  485.     data2 = key2->data ;
  486. #ifndef newSVpvn
  487.     /* As newSVpv will assume that the data pointer is a null terminated C 
  488.        string if the size parameter is 0, make sure that data points to an 
  489.        empty string if the length is 0
  490.     */
  491.     if (key1->size == 0)
  492.         data1 = "" ;
  493.     if (key2->size == 0)
  494.         data2 = "" ;
  495. #endif
  496.     ENTER ;
  497.     SAVETMPS;
  498.     PUSHMARK(SP) ;
  499.     EXTEND(SP,2) ;
  500.     PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
  501.     PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
  502.     PUTBACK ;
  503.     count = perl_call_sv(CurrentDB->prefix, G_SCALAR); 
  504.     SPAGAIN ;
  505.     if (count != 1)
  506.         croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %dn", count) ;
  507.  
  508.     retval = POPi ;
  509.  
  510.     PUTBACK ;
  511.     FREETMPS ;
  512.     LEAVE ;
  513.     return (retval) ;
  514. }
  515. #ifdef BERKELEY_DB_1
  516. #    define HASH_CB_SIZE_TYPE size_t
  517. #else
  518. #    define HASH_CB_SIZE_TYPE u_int32_t
  519. #endif
  520. static DB_Hash_t
  521. #ifdef AT_LEAST_DB_3_2
  522. #ifdef CAN_PROTOTYPE
  523. hash_cb(DB * db, const void *data, u_int32_t size)
  524. #else
  525. hash_cb(db, data, size)
  526. DB * db ;
  527. const void * data ;
  528. HASH_CB_SIZE_TYPE size ;
  529. #endif
  530. #else /* Berkeley DB < 3.2 */
  531. #ifdef CAN_PROTOTYPE
  532. hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
  533. #else
  534. hash_cb(data, size)
  535. const void * data ;
  536. HASH_CB_SIZE_TYPE size ;
  537. #endif
  538. #endif
  539. {
  540. #ifdef dTHX
  541.     dTHX;
  542. #endif    
  543.     dSP ;
  544.     int retval ;
  545.     int count ;
  546. #ifndef newSVpvn
  547.     if (size == 0)
  548.         data = "" ;
  549. #endif
  550.      /* DGH - Next two lines added to fix corrupted stack problem */
  551.     ENTER ;
  552.     SAVETMPS;
  553.     PUSHMARK(SP) ;
  554.     XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
  555.     PUTBACK ;
  556.     count = perl_call_sv(CurrentDB->hash, G_SCALAR); 
  557.     SPAGAIN ;
  558.     if (count != 1)
  559.         croak ("DB_File hash_cb: expected 1 return value from hash sub, got %dn", count) ;
  560.     retval = POPi ;
  561.     PUTBACK ;
  562.     FREETMPS ;
  563.     LEAVE ;
  564.     return (retval) ;
  565. }
  566. #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
  567. static void
  568. #ifdef CAN_PROTOTYPE
  569. PrintHash(INFO *hash)
  570. #else
  571. PrintHash(hash)
  572. INFO * hash ;
  573. #endif
  574. {
  575.     printf ("HASH Infon") ;
  576.     printf ("  hash      = %sn", 
  577. (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
  578.     printf ("  bsize     = %dn", hash->db_HA_bsize) ;
  579.     printf ("  ffactor   = %dn", hash->db_HA_ffactor) ;
  580.     printf ("  nelem     = %dn", hash->db_HA_nelem) ;
  581.     printf ("  cachesize = %dn", hash->db_HA_cachesize) ;
  582.     printf ("  lorder    = %dn", hash->db_HA_lorder) ;
  583. }
  584. static void
  585. #ifdef CAN_PROTOTYPE
  586. PrintRecno(INFO *recno)
  587. #else
  588. PrintRecno(recno)
  589. INFO * recno ;
  590. #endif
  591. {
  592.     printf ("RECNO Infon") ;
  593.     printf ("  flags     = %dn", recno->db_RE_flags) ;
  594.     printf ("  cachesize = %dn", recno->db_RE_cachesize) ;
  595.     printf ("  psize     = %dn", recno->db_RE_psize) ;
  596.     printf ("  lorder    = %dn", recno->db_RE_lorder) ;
  597.     printf ("  reclen    = %uln", (unsigned long)recno->db_RE_reclen) ;
  598.     printf ("  bval      = %d 0x%xn", recno->db_RE_bval, recno->db_RE_bval) ;
  599.     printf ("  bfname    = %d [%s]n", recno->db_RE_bfname, recno->db_RE_bfname) ;
  600. }
  601. static void
  602. #ifdef CAN_PROTOTYPE
  603. PrintBtree(INFO *btree)
  604. #else
  605. PrintBtree(btree)
  606. INFO * btree ;
  607. #endif
  608. {
  609.     printf ("BTREE Infon") ;
  610.     printf ("  compare    = %sn", 
  611. (btree->db_BT_compare ? "redefined" : "default")) ;
  612.     printf ("  prefix     = %sn", 
  613. (btree->db_BT_prefix ? "redefined" : "default")) ;
  614.     printf ("  flags      = %dn", btree->db_BT_flags) ;
  615.     printf ("  cachesize  = %dn", btree->db_BT_cachesize) ;
  616.     printf ("  psize      = %dn", btree->db_BT_psize) ;
  617. #ifndef DB_VERSION_MAJOR
  618.     printf ("  maxkeypage = %dn", btree->db_BT_maxkeypage) ;
  619.     printf ("  minkeypage = %dn", btree->db_BT_minkeypage) ;
  620. #endif
  621.     printf ("  lorder     = %dn", btree->db_BT_lorder) ;
  622. }
  623. #else
  624. #define PrintRecno(recno)
  625. #define PrintHash(hash)
  626. #define PrintBtree(btree)
  627. #endif /* TRACE */
  628. static I32
  629. #ifdef CAN_PROTOTYPE
  630. GetArrayLength(pTHX_ DB_File db)
  631. #else
  632. GetArrayLength(db)
  633. DB_File db ;
  634. #endif
  635. {
  636.     DBT key ;
  637.     DBT value ;
  638.     int RETVAL ;
  639.     DBT_clear(key) ;
  640.     DBT_clear(value) ;
  641.     RETVAL = do_SEQ(db, key, value, R_LAST) ;
  642.     if (RETVAL == 0)
  643.         RETVAL = *(I32 *)key.data ;
  644.     else /* No key means empty file */
  645.         RETVAL = 0 ;
  646.     return ((I32)RETVAL) ;
  647. }
  648. static recno_t
  649. #ifdef CAN_PROTOTYPE
  650. GetRecnoKey(pTHX_ DB_File db, I32 value)
  651. #else
  652. GetRecnoKey(db, value)
  653. DB_File  db ;
  654. I32      value ;
  655. #endif
  656. {
  657.     if (value < 0) {
  658. /* Get the length of the array */
  659. I32 length = GetArrayLength(aTHX_ db) ;
  660. /* check for attempt to write before start of array */
  661. if (length + value + 1 <= 0)
  662.     croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
  663. value = length + value + 1 ;
  664.     }
  665.     else
  666.         ++ value ;
  667.     return value ;
  668. }
  669. static DB_File
  670. #ifdef CAN_PROTOTYPE
  671. ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
  672. #else
  673. ParseOpenInfo(isHASH, name, flags, mode, sv)
  674. int    isHASH ;
  675. char * name ;
  676. int    flags ;
  677. int    mode ;
  678. SV *   sv ;
  679. #endif
  680. {
  681. #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1  or 2 */
  682.     SV ** svp;
  683.     HV * action ;
  684.     DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
  685.     void * openinfo = NULL ;
  686.     INFO * info  = &RETVAL->info ;
  687.     STRLEN n_a;
  688. /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]n", name, flags, mode) ;  */
  689.     Zero(RETVAL, 1, DB_File_type) ;
  690.     /* Default to HASH */
  691. #ifdef DBM_FILTERING
  692.     RETVAL->filtering = 0 ;
  693.     RETVAL->filter_fetch_key = RETVAL->filter_store_key = 
  694.     RETVAL->filter_fetch_value = RETVAL->filter_store_value =
  695. #endif /* DBM_FILTERING */
  696.     RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
  697.     RETVAL->type = DB_HASH ;
  698.      /* DGH - Next line added to avoid SEGV on existing hash DB */
  699.     CurrentDB = RETVAL; 
  700.     /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
  701.     RETVAL->in_memory = (name == NULL) ;
  702.     if (sv)
  703.     {
  704.         if (! SvROK(sv) )
  705.             croak ("type parameter is not a reference") ;
  706.         svp  = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
  707.         if (svp && SvOK(*svp))
  708.             action  = (HV*) SvRV(*svp) ;
  709. else
  710.     croak("internal error") ;
  711.         if (sv_isa(sv, "DB_File::HASHINFO"))
  712.         {
  713.     if (!isHASH)
  714.         croak("DB_File can only tie an associative array to a DB_HASH database") ;
  715.             RETVAL->type = DB_HASH ;
  716.             openinfo = (void*)info ;
  717.   
  718.             svp = hv_fetch(action, "hash", 4, FALSE); 
  719.             if (svp && SvOK(*svp))
  720.             {
  721.                 info->db_HA_hash = hash_cb ;
  722. RETVAL->hash = newSVsv(*svp) ;
  723.             }
  724.             else
  725.         info->db_HA_hash = NULL ;
  726.            svp = hv_fetch(action, "ffactor", 7, FALSE);
  727.            info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
  728.          
  729.            svp = hv_fetch(action, "nelem", 5, FALSE);
  730.            info->db_HA_nelem = svp ? SvIV(*svp) : 0;
  731.          
  732.            svp = hv_fetch(action, "bsize", 5, FALSE);
  733.            info->db_HA_bsize = svp ? SvIV(*svp) : 0;
  734.            
  735.            svp = hv_fetch(action, "cachesize", 9, FALSE);
  736.            info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
  737.          
  738.            svp = hv_fetch(action, "lorder", 6, FALSE);
  739.            info->db_HA_lorder = svp ? SvIV(*svp) : 0;
  740.            PrintHash(info) ; 
  741.         }
  742.         else if (sv_isa(sv, "DB_File::BTREEINFO"))
  743.         {
  744.     if (!isHASH)
  745.         croak("DB_File can only tie an associative array to a DB_BTREE database");
  746.             RETVAL->type = DB_BTREE ;
  747.             openinfo = (void*)info ;
  748.    
  749.             svp = hv_fetch(action, "compare", 7, FALSE);
  750.             if (svp && SvOK(*svp))
  751.             {
  752.                 info->db_BT_compare = btree_compare ;
  753. RETVAL->compare = newSVsv(*svp) ;
  754.             }
  755.             else
  756.                 info->db_BT_compare = NULL ;
  757.             svp = hv_fetch(action, "prefix", 6, FALSE);
  758.             if (svp && SvOK(*svp))
  759.             {
  760.                 info->db_BT_prefix = btree_prefix ;
  761. RETVAL->prefix = newSVsv(*svp) ;
  762.             }
  763.             else
  764.                 info->db_BT_prefix = NULL ;
  765.             svp = hv_fetch(action, "flags", 5, FALSE);
  766.             info->db_BT_flags = svp ? SvIV(*svp) : 0;
  767.    
  768.             svp = hv_fetch(action, "cachesize", 9, FALSE);
  769.             info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
  770.          
  771. #ifndef DB_VERSION_MAJOR
  772.             svp = hv_fetch(action, "minkeypage", 10, FALSE);
  773.             info->btree.minkeypage = svp ? SvIV(*svp) : 0;
  774.         
  775.             svp = hv_fetch(action, "maxkeypage", 10, FALSE);
  776.             info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
  777. #endif
  778.             svp = hv_fetch(action, "psize", 5, FALSE);
  779.             info->db_BT_psize = svp ? SvIV(*svp) : 0;
  780.          
  781.             svp = hv_fetch(action, "lorder", 6, FALSE);
  782.             info->db_BT_lorder = svp ? SvIV(*svp) : 0;
  783.             PrintBtree(info) ;
  784.          
  785.         }
  786.         else if (sv_isa(sv, "DB_File::RECNOINFO"))
  787.         {
  788.     if (isHASH)
  789.         croak("DB_File can only tie an array to a DB_RECNO database");
  790.             RETVAL->type = DB_RECNO ;
  791.             openinfo = (void *)info ;
  792.     info->db_RE_flags = 0 ;
  793.             svp = hv_fetch(action, "flags", 5, FALSE);
  794.             info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
  795.          
  796.             svp = hv_fetch(action, "reclen", 6, FALSE);
  797.             info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
  798.          
  799.             svp = hv_fetch(action, "cachesize", 9, FALSE);
  800.             info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
  801.          
  802.             svp = hv_fetch(action, "psize", 5, FALSE);
  803.             info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
  804.          
  805.             svp = hv_fetch(action, "lorder", 6, FALSE);
  806.             info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
  807. #ifdef DB_VERSION_MAJOR
  808.     info->re_source = name ;
  809.     name = NULL ;
  810. #endif
  811.             svp = hv_fetch(action, "bfname", 6, FALSE); 
  812.             if (svp && SvOK(*svp)) {
  813. char * ptr = SvPV(*svp,n_a) ;
  814. #ifdef DB_VERSION_MAJOR
  815. name = (char*) n_a ? ptr : NULL ;
  816. #else
  817.                 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
  818. #endif
  819.     }
  820.     else
  821. #ifdef DB_VERSION_MAJOR
  822. name = NULL ;
  823. #else
  824.                 info->db_RE_bfname = NULL ;
  825. #endif
  826.          
  827.     svp = hv_fetch(action, "bval", 4, FALSE);
  828. #ifdef DB_VERSION_MAJOR
  829.             if (svp && SvOK(*svp))
  830.             {
  831. int value ;
  832.                 if (SvPOK(*svp))
  833.     value = (int)*SvPV(*svp, n_a) ;
  834. else
  835.     value = SvIV(*svp) ;
  836. if (info->flags & DB_FIXEDLEN) {
  837.     info->re_pad = value ;
  838.     info->flags |= DB_PAD ;
  839. }
  840. else {
  841.     info->re_delim = value ;
  842.     info->flags |= DB_DELIMITER ;
  843. }
  844.             }
  845. #else
  846.             if (svp && SvOK(*svp))
  847.             {
  848.                 if (SvPOK(*svp))
  849.     info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
  850. else
  851.     info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
  852. DB_flags(info->flags, DB_DELIMITER) ;
  853.             }
  854.             else
  855.       {
  856. if (info->db_RE_flags & R_FIXEDLEN)
  857.                     info->db_RE_bval = (u_char) ' ' ;
  858. else
  859.                     info->db_RE_bval = (u_char) 'n' ;
  860. DB_flags(info->flags, DB_DELIMITER) ;
  861.     }
  862. #endif
  863. #ifdef DB_RENUMBER
  864.     info->flags |= DB_RENUMBER ;
  865. #endif
  866.          
  867.             PrintRecno(info) ;
  868.         }
  869.         else
  870.             croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
  871.     }
  872.     /* OS2 Specific Code */
  873. #ifdef OS2
  874. #ifdef __EMX__
  875.     flags |= O_BINARY;
  876. #endif /* __EMX__ */
  877. #endif /* OS2 */
  878. #ifdef DB_VERSION_MAJOR
  879.     {
  880.         int   Flags = 0 ;
  881.         int status ;
  882.         /* Map 1.x flags to 2.x flags */
  883.         if ((flags & O_CREAT) == O_CREAT)
  884.             Flags |= DB_CREATE ;
  885. #if O_RDONLY == 0
  886.         if (flags == O_RDONLY)
  887. #else
  888.         if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
  889. #endif
  890.             Flags |= DB_RDONLY ;
  891. #ifdef O_TRUNC
  892.         if ((flags & O_TRUNC) == O_TRUNC)
  893.             Flags |= DB_TRUNCATE ;
  894. #endif
  895.         status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ; 
  896.         if (status == 0)
  897. #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
  898.             status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
  899. #else
  900.             status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
  901. 0) ;
  902. #endif
  903.         if (status)
  904.     RETVAL->dbp = NULL ;
  905.     }
  906. #else
  907. #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
  908.     RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ; 
  909. #else    
  910.     RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ; 
  911. #endif /* DB_LIBRARY_COMPATIBILITY_API */
  912. #endif
  913.     return (RETVAL) ;
  914. #else /* Berkeley DB Version > 2 */
  915.     SV ** svp;
  916.     HV * action ;
  917.     DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
  918.     DB * dbp ;
  919.     STRLEN n_a;
  920.     int status ;
  921. /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]n", name, flags, mode) ;  */
  922.     Zero(RETVAL, 1, DB_File_type) ;
  923.     /* Default to HASH */
  924. #ifdef DBM_FILTERING
  925.     RETVAL->filtering = 0 ;
  926.     RETVAL->filter_fetch_key = RETVAL->filter_store_key = 
  927.     RETVAL->filter_fetch_value = RETVAL->filter_store_value =
  928. #endif /* DBM_FILTERING */
  929.     RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
  930.     RETVAL->type = DB_HASH ;
  931.      /* DGH - Next line added to avoid SEGV on existing hash DB */
  932.     CurrentDB = RETVAL; 
  933.     /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
  934.     RETVAL->in_memory = (name == NULL) ;
  935.     status = db_create(&RETVAL->dbp, NULL,0) ;
  936.     /* printf("db_create returned %d %sn", status, db_strerror(status)) ; */
  937.     if (status) {
  938. RETVAL->dbp = NULL ;
  939.         return (RETVAL) ;
  940.     }
  941.     dbp = RETVAL->dbp ;
  942.     if (sv)
  943.     {
  944.         if (! SvROK(sv) )
  945.             croak ("type parameter is not a reference") ;
  946.         svp  = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
  947.         if (svp && SvOK(*svp))
  948.             action  = (HV*) SvRV(*svp) ;
  949. else
  950.     croak("internal error") ;
  951.         if (sv_isa(sv, "DB_File::HASHINFO"))
  952.         {
  953.     if (!isHASH)
  954.         croak("DB_File can only tie an associative array to a DB_HASH database") ;
  955.             RETVAL->type = DB_HASH ;
  956.   
  957.             svp = hv_fetch(action, "hash", 4, FALSE); 
  958.             if (svp && SvOK(*svp))
  959.             {
  960. (void)dbp->set_h_hash(dbp, hash_cb) ;
  961. RETVAL->hash = newSVsv(*svp) ;
  962.             }
  963.            svp = hv_fetch(action, "ffactor", 7, FALSE);
  964.    if (svp)
  965.        (void)dbp->set_h_ffactor(dbp, SvIV(*svp)) ;
  966.          
  967.            svp = hv_fetch(action, "nelem", 5, FALSE);
  968.    if (svp)
  969.                (void)dbp->set_h_nelem(dbp, SvIV(*svp)) ;
  970.          
  971.            svp = hv_fetch(action, "bsize", 5, FALSE);
  972.    if (svp)
  973.                (void)dbp->set_pagesize(dbp, SvIV(*svp));
  974.            
  975.            svp = hv_fetch(action, "cachesize", 9, FALSE);
  976.    if (svp)
  977.                (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
  978.          
  979.            svp = hv_fetch(action, "lorder", 6, FALSE);
  980.    if (svp)
  981.                (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
  982.            PrintHash(info) ; 
  983.         }
  984.         else if (sv_isa(sv, "DB_File::BTREEINFO"))
  985.         {
  986.     if (!isHASH)
  987.         croak("DB_File can only tie an associative array to a DB_BTREE database");
  988.             RETVAL->type = DB_BTREE ;
  989.    
  990.             svp = hv_fetch(action, "compare", 7, FALSE);
  991.             if (svp && SvOK(*svp))
  992.             {
  993.                 (void)dbp->set_bt_compare(dbp, btree_compare) ;
  994. RETVAL->compare = newSVsv(*svp) ;
  995.             }
  996.             svp = hv_fetch(action, "prefix", 6, FALSE);
  997.             if (svp && SvOK(*svp))
  998.             {
  999.                 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
  1000. RETVAL->prefix = newSVsv(*svp) ;
  1001.             }
  1002.            svp = hv_fetch(action, "flags", 5, FALSE);
  1003.    if (svp)
  1004.        (void)dbp->set_flags(dbp, SvIV(*svp)) ;
  1005.    
  1006.            svp = hv_fetch(action, "cachesize", 9, FALSE);
  1007.    if (svp)
  1008.                (void)dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
  1009.          
  1010.            svp = hv_fetch(action, "psize", 5, FALSE);
  1011.    if (svp)
  1012.                (void)dbp->set_pagesize(dbp, SvIV(*svp)) ;
  1013.          
  1014.            svp = hv_fetch(action, "lorder", 6, FALSE);
  1015.    if (svp)
  1016.                (void)dbp->set_lorder(dbp, SvIV(*svp)) ;
  1017.             PrintBtree(info) ;
  1018.          
  1019.         }
  1020.         else if (sv_isa(sv, "DB_File::RECNOINFO"))
  1021.         {
  1022.     int fixed = FALSE ;
  1023.     if (isHASH)
  1024.         croak("DB_File can only tie an array to a DB_RECNO database");
  1025.             RETVAL->type = DB_RECNO ;
  1026.            svp = hv_fetch(action, "flags", 5, FALSE);
  1027.    if (svp) {
  1028. int flags = SvIV(*svp) ;
  1029. /* remove FIXDLEN, if present */
  1030. if (flags & DB_FIXEDLEN) {
  1031.     fixed = TRUE ;
  1032.     flags &= ~DB_FIXEDLEN ;
  1033.     }
  1034.    }
  1035.            svp = hv_fetch(action, "cachesize", 9, FALSE);
  1036.    if (svp) {
  1037.                status = dbp->set_cachesize(dbp, 0, SvIV(*svp), 0) ;
  1038.    }
  1039.          
  1040.            svp = hv_fetch(action, "psize", 5, FALSE);
  1041.    if (svp) {
  1042.                status = dbp->set_pagesize(dbp, SvIV(*svp)) ;
  1043.     }
  1044.          
  1045.            svp = hv_fetch(action, "lorder", 6, FALSE);
  1046.    if (svp) {
  1047.                status = dbp->set_lorder(dbp, SvIV(*svp)) ;
  1048.    }
  1049.     svp = hv_fetch(action, "bval", 4, FALSE);
  1050.             if (svp && SvOK(*svp))
  1051.             {
  1052. int value ;
  1053.                 if (SvPOK(*svp))
  1054.     value = (int)*SvPV(*svp, n_a) ;
  1055. else
  1056.     value = SvIV(*svp) ;
  1057. if (fixed) {
  1058.     status = dbp->set_re_pad(dbp, value) ;
  1059. }
  1060. else {
  1061.     status = dbp->set_re_delim(dbp, value) ;
  1062. }
  1063.             }
  1064.    if (fixed) {
  1065.                svp = hv_fetch(action, "reclen", 6, FALSE);
  1066.        if (svp) {
  1067.    u_int32_t len =  (u_int32_t)SvIV(*svp) ;
  1068.                    status = dbp->set_re_len(dbp, len) ;
  1069.        }    
  1070.    }
  1071.          
  1072.     if (name != NULL) {
  1073.         status = dbp->set_re_source(dbp, name) ;
  1074.         name = NULL ;
  1075.     }
  1076.             svp = hv_fetch(action, "bfname", 6, FALSE); 
  1077.             if (svp && SvOK(*svp)) {
  1078. char * ptr = SvPV(*svp,n_a) ;
  1079. name = (char*) n_a ? ptr : NULL ;
  1080.     }
  1081.     else
  1082. name = NULL ;
  1083.          
  1084.     status = dbp->set_flags(dbp, DB_RENUMBER) ;
  1085.          
  1086. if (flags){
  1087.             (void)dbp->set_flags(dbp, flags) ;
  1088. }
  1089.             PrintRecno(info) ;
  1090.         }
  1091.         else
  1092.             croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
  1093.     }
  1094.     {
  1095.         int   Flags = 0 ;
  1096.         int status ;
  1097.         /* Map 1.x flags to 3.x flags */
  1098.         if ((flags & O_CREAT) == O_CREAT)
  1099.             Flags |= DB_CREATE ;
  1100. #if O_RDONLY == 0
  1101.         if (flags == O_RDONLY)
  1102. #else
  1103.         if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
  1104. #endif
  1105.             Flags |= DB_RDONLY ;
  1106. #ifdef O_TRUNC
  1107.         if ((flags & O_TRUNC) == O_TRUNC)
  1108.             Flags |= DB_TRUNCATE ;
  1109. #endif
  1110.         status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type, 
  1111.      Flags, mode) ; 
  1112. /* printf("open returned %d %sn", status, db_strerror(status)) ; */
  1113.         if (status == 0)
  1114.             status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
  1115. 0) ;
  1116. /* printf("cursor returned %d %sn", status, db_strerror(status)) ; */
  1117.         if (status)
  1118.     RETVAL->dbp = NULL ;
  1119.     }
  1120.     return (RETVAL) ;
  1121. #endif /* Berkeley DB Version > 2 */
  1122. } /* ParseOpenInfo */
  1123. static double 
  1124. #ifdef CAN_PROTOTYPE
  1125. constant(char *name, int arg)
  1126. #else
  1127. constant(name, arg)
  1128. char *name;
  1129. int arg;
  1130. #endif
  1131. {
  1132.     errno = 0;
  1133.     switch (*name) {
  1134.     case 'A':
  1135. break;
  1136.     case 'B':
  1137. if (strEQ(name, "BTREEMAGIC"))
  1138. #ifdef BTREEMAGIC
  1139.     return BTREEMAGIC;
  1140. #else
  1141.     goto not_there;
  1142. #endif
  1143. if (strEQ(name, "BTREEVERSION"))
  1144. #ifdef BTREEVERSION
  1145.     return BTREEVERSION;
  1146. #else
  1147.     goto not_there;
  1148. #endif
  1149. break;
  1150.     case 'C':
  1151. break;
  1152.     case 'D':
  1153. if (strEQ(name, "DB_LOCK"))
  1154. #ifdef DB_LOCK
  1155.     return DB_LOCK;
  1156. #else
  1157.     goto not_there;
  1158. #endif
  1159. if (strEQ(name, "DB_SHMEM"))
  1160. #ifdef DB_SHMEM
  1161.     return DB_SHMEM;
  1162. #else
  1163.     goto not_there;
  1164. #endif
  1165. if (strEQ(name, "DB_TXN"))
  1166. #ifdef DB_TXN
  1167.     return (U32)DB_TXN;
  1168. #else
  1169.     goto not_there;
  1170. #endif
  1171. break;
  1172.     case 'E':
  1173. break;
  1174.     case 'F':
  1175. break;
  1176.     case 'G':
  1177. break;
  1178.     case 'H':
  1179. if (strEQ(name, "HASHMAGIC"))
  1180. #ifdef HASHMAGIC
  1181.     return HASHMAGIC;
  1182. #else
  1183.     goto not_there;
  1184. #endif
  1185. if (strEQ(name, "HASHVERSION"))
  1186. #ifdef HASHVERSION
  1187.     return HASHVERSION;
  1188. #else
  1189.     goto not_there;
  1190. #endif
  1191. break;
  1192.     case 'I':
  1193. break;
  1194.     case 'J':
  1195. break;
  1196.     case 'K':
  1197. break;
  1198.     case 'L':
  1199. break;
  1200.     case 'M':
  1201. if (strEQ(name, "MAX_PAGE_NUMBER"))
  1202. #ifdef MAX_PAGE_NUMBER
  1203.     return (U32)MAX_PAGE_NUMBER;
  1204. #else
  1205.     goto not_there;
  1206. #endif
  1207. if (strEQ(name, "MAX_PAGE_OFFSET"))
  1208. #ifdef MAX_PAGE_OFFSET
  1209.     return MAX_PAGE_OFFSET;
  1210. #else
  1211.     goto not_there;
  1212. #endif
  1213. if (strEQ(name, "MAX_REC_NUMBER"))
  1214. #ifdef MAX_REC_NUMBER
  1215.     return (U32)MAX_REC_NUMBER;
  1216. #else
  1217.     goto not_there;
  1218. #endif
  1219. break;
  1220.     case 'N':
  1221. break;
  1222.     case 'O':
  1223. break;
  1224.     case 'P':
  1225. break;
  1226.     case 'Q':
  1227. break;
  1228.     case 'R':
  1229. if (strEQ(name, "RET_ERROR"))
  1230. #ifdef RET_ERROR
  1231.     return RET_ERROR;
  1232. #else
  1233.     goto not_there;
  1234. #endif
  1235. if (strEQ(name, "RET_SPECIAL"))
  1236. #ifdef RET_SPECIAL
  1237.     return RET_SPECIAL;
  1238. #else
  1239.     goto not_there;
  1240. #endif
  1241. if (strEQ(name, "RET_SUCCESS"))
  1242. #ifdef RET_SUCCESS
  1243.     return RET_SUCCESS;
  1244. #else
  1245.     goto not_there;
  1246. #endif
  1247. if (strEQ(name, "R_CURSOR"))
  1248. #ifdef R_CURSOR
  1249.     return R_CURSOR;
  1250. #else
  1251.     goto not_there;
  1252. #endif
  1253. if (strEQ(name, "R_DUP"))
  1254. #ifdef R_DUP
  1255.     return R_DUP;
  1256. #else
  1257.     goto not_there;
  1258. #endif
  1259. if (strEQ(name, "R_FIRST"))
  1260. #ifdef R_FIRST
  1261.     return R_FIRST;
  1262. #else
  1263.     goto not_there;
  1264. #endif
  1265. if (strEQ(name, "R_FIXEDLEN"))
  1266. #ifdef R_FIXEDLEN
  1267.     return R_FIXEDLEN;
  1268. #else
  1269.     goto not_there;
  1270. #endif
  1271. if (strEQ(name, "R_IAFTER"))
  1272. #ifdef R_IAFTER
  1273.     return R_IAFTER;
  1274. #else
  1275.     goto not_there;
  1276. #endif
  1277. if (strEQ(name, "R_IBEFORE"))
  1278. #ifdef R_IBEFORE
  1279.     return R_IBEFORE;
  1280. #else
  1281.     goto not_there;
  1282. #endif
  1283. if (strEQ(name, "R_LAST"))
  1284. #ifdef R_LAST
  1285.     return R_LAST;
  1286. #else
  1287.     goto not_there;
  1288. #endif
  1289. if (strEQ(name, "R_NEXT"))
  1290. #ifdef R_NEXT
  1291.     return R_NEXT;
  1292. #else
  1293.     goto not_there;
  1294. #endif
  1295. if (strEQ(name, "R_NOKEY"))
  1296. #ifdef R_NOKEY
  1297.     return R_NOKEY;
  1298. #else
  1299.     goto not_there;
  1300. #endif
  1301. if (strEQ(name, "R_NOOVERWRITE"))
  1302. #ifdef R_NOOVERWRITE
  1303.     return R_NOOVERWRITE;
  1304. #else
  1305.     goto not_there;
  1306. #endif
  1307. if (strEQ(name, "R_PREV"))
  1308. #ifdef R_PREV
  1309.     return R_PREV;
  1310. #else
  1311.     goto not_there;
  1312. #endif
  1313. if (strEQ(name, "R_RECNOSYNC"))
  1314. #ifdef R_RECNOSYNC
  1315.     return R_RECNOSYNC;
  1316. #else
  1317.     goto not_there;
  1318. #endif
  1319. if (strEQ(name, "R_SETCURSOR"))
  1320. #ifdef R_SETCURSOR
  1321.     return R_SETCURSOR;
  1322. #else
  1323.     goto not_there;
  1324. #endif
  1325. if (strEQ(name, "R_SNAPSHOT"))
  1326. #ifdef R_SNAPSHOT
  1327.     return R_SNAPSHOT;
  1328. #else
  1329.     goto not_there;
  1330. #endif
  1331. break;
  1332.     case 'S':
  1333. break;
  1334.     case 'T':
  1335. break;
  1336.     case 'U':
  1337. break;
  1338.     case 'V':
  1339. break;
  1340.     case 'W':
  1341. break;
  1342.     case 'X':
  1343. break;
  1344.     case 'Y':
  1345. break;
  1346.     case 'Z':
  1347. break;
  1348.     case '_':
  1349. break;
  1350.     }
  1351.     errno = EINVAL;
  1352.     return 0;
  1353. not_there:
  1354.     errno = ENOENT;
  1355.     return 0;
  1356. }
  1357. MODULE = DB_File PACKAGE = DB_File PREFIX = db_
  1358. BOOT:
  1359.   {
  1360.     __getBerkeleyDBInfo() ;
  1361.  
  1362.     DBT_clear(empty) ; 
  1363.     empty.data = &zero ;
  1364.     empty.size =  sizeof(recno_t) ;
  1365.   }
  1366. double
  1367. constant(name,arg)
  1368. char * name
  1369. int arg
  1370. DB_File
  1371. db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
  1372. int isHASH
  1373. char * dbtype
  1374. int flags
  1375. int mode
  1376. CODE:
  1377. {
  1378.     char * name = (char *) NULL ; 
  1379.     SV * sv = (SV *) NULL ; 
  1380.     STRLEN n_a;
  1381.     if (items >= 3 && SvOK(ST(2))) 
  1382.         name = (char*) SvPV(ST(2), n_a) ; 
  1383.             if (items == 6)
  1384.         sv = ST(5) ;
  1385.     RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
  1386.     if (RETVAL->dbp == NULL)
  1387.         RETVAL = NULL ;
  1388. }
  1389. OUTPUT:
  1390.     RETVAL
  1391. int
  1392. db_DESTROY(db)
  1393. DB_File db
  1394. INIT:
  1395.   CurrentDB = db ;
  1396. CLEANUP:
  1397.   if (db->hash)
  1398.     SvREFCNT_dec(db->hash) ;
  1399.   if (db->compare)
  1400.     SvREFCNT_dec(db->compare) ;
  1401.   if (db->prefix)
  1402.     SvREFCNT_dec(db->prefix) ;
  1403. #ifdef DBM_FILTERING
  1404.   if (db->filter_fetch_key)
  1405.     SvREFCNT_dec(db->filter_fetch_key) ;
  1406.   if (db->filter_store_key)
  1407.     SvREFCNT_dec(db->filter_store_key) ;
  1408.   if (db->filter_fetch_value)
  1409.     SvREFCNT_dec(db->filter_fetch_value) ;
  1410.   if (db->filter_store_value)
  1411.     SvREFCNT_dec(db->filter_store_value) ;
  1412. #endif /* DBM_FILTERING */
  1413.   safefree(db) ;
  1414. #ifdef DB_VERSION_MAJOR
  1415.   if (RETVAL > 0)
  1416.     RETVAL = -1 ;
  1417. #endif
  1418. int
  1419. db_DELETE(db, key, flags=0)
  1420. DB_File db
  1421. DBTKEY key
  1422. u_int flags
  1423. INIT:
  1424.   CurrentDB = db ;
  1425. int
  1426. db_EXISTS(db, key)
  1427. DB_File db
  1428. DBTKEY key
  1429. CODE:
  1430. {
  1431.           DBT value ;
  1432.   DBT_clear(value) ; 
  1433.   CurrentDB = db ;
  1434.   RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
  1435. }
  1436. OUTPUT:
  1437.   RETVAL
  1438. int
  1439. db_FETCH(db, key, flags=0)
  1440. DB_File db
  1441. DBTKEY key
  1442. u_int flags
  1443. CODE:
  1444. {
  1445.             DBT value ;
  1446.     DBT_clear(value) ; 
  1447.     CurrentDB = db ;
  1448.     /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
  1449.     RETVAL = db_get(db, key, value, flags) ;
  1450.     ST(0) = sv_newmortal();
  1451.     OutputValue(ST(0), value)
  1452. }
  1453. int
  1454. db_STORE(db, key, value, flags=0)
  1455. DB_File db
  1456. DBTKEY key
  1457. DBT value
  1458. u_int flags
  1459. INIT:
  1460.   CurrentDB = db ;
  1461. int
  1462. db_FIRSTKEY(db)
  1463. DB_File db
  1464. CODE:
  1465. {
  1466.     DBTKEY key ;
  1467.     DBT value ;
  1468.     DBT_clear(key) ; 
  1469.     DBT_clear(value) ; 
  1470.     CurrentDB = db ;
  1471.     RETVAL = do_SEQ(db, key, value, R_FIRST) ;
  1472.     ST(0) = sv_newmortal();
  1473.     OutputKey(ST(0), key) ;
  1474. }
  1475. int
  1476. db_NEXTKEY(db, key)
  1477. DB_File db
  1478. DBTKEY key
  1479. CODE:
  1480. {
  1481.     DBT value ;
  1482.     DBT_clear(value) ; 
  1483.     CurrentDB = db ;
  1484.     RETVAL = do_SEQ(db, key, value, R_NEXT) ;
  1485.     ST(0) = sv_newmortal();
  1486.     OutputKey(ST(0), key) ;
  1487. }
  1488. #
  1489. # These would be nice for RECNO
  1490. #
  1491. int
  1492. unshift(db, ...)
  1493. DB_File db
  1494. ALIAS: UNSHIFT = 1
  1495. CODE:
  1496. {
  1497.     DBTKEY key ;
  1498.     DBT value ;
  1499.     int i ;
  1500.     int One ;
  1501.     DB * Db = db->dbp ;
  1502.     STRLEN n_a;
  1503.     DBT_clear(key) ; 
  1504.     DBT_clear(value) ; 
  1505.     CurrentDB = db ;
  1506. #ifdef DB_VERSION_MAJOR
  1507.     /* get the first value */
  1508.     RETVAL = do_SEQ(db, key, value, DB_FIRST) ;  
  1509.     RETVAL = 0 ;
  1510. #else
  1511.     RETVAL = -1 ;
  1512. #endif
  1513.     for (i = items-1 ; i > 0 ; --i)
  1514.     {
  1515.         value.data = SvPV(ST(i), n_a) ;
  1516.         value.size = n_a ;
  1517.         One = 1 ;
  1518.         key.data = &One ;
  1519.         key.size = sizeof(int) ;
  1520. #ifdef DB_VERSION_MAJOR
  1521.             RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
  1522. #else
  1523.         RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
  1524. #endif
  1525.         if (RETVAL != 0)
  1526.             break;
  1527.     }
  1528. }
  1529. OUTPUT:
  1530.     RETVAL
  1531. I32
  1532. pop(db)
  1533. DB_File db
  1534. ALIAS: POP = 1
  1535. CODE:
  1536. {
  1537.     DBTKEY key ;
  1538.     DBT value ;
  1539.     DBT_clear(key) ; 
  1540.     DBT_clear(value) ; 
  1541.     CurrentDB = db ;
  1542.     /* First get the final value */
  1543.     RETVAL = do_SEQ(db, key, value, R_LAST) ;  
  1544.     ST(0) = sv_newmortal();
  1545.     /* Now delete it */
  1546.     if (RETVAL == 0)
  1547.     {
  1548. /* the call to del will trash value, so take a copy now */
  1549. OutputValue(ST(0), value) ;
  1550.         RETVAL = db_del(db, key, R_CURSOR) ;
  1551.         if (RETVAL != 0) 
  1552.             sv_setsv(ST(0), &PL_sv_undef); 
  1553.     }
  1554. }
  1555. I32
  1556. shift(db)
  1557. DB_File db
  1558. ALIAS: SHIFT = 1
  1559. CODE:
  1560. {
  1561.     DBT value ;
  1562.     DBTKEY key ;
  1563.     DBT_clear(key) ; 
  1564.     DBT_clear(value) ; 
  1565.     CurrentDB = db ;
  1566.     /* get the first value */
  1567.     RETVAL = do_SEQ(db, key, value, R_FIRST) ;  
  1568.     ST(0) = sv_newmortal();
  1569.     /* Now delete it */
  1570.     if (RETVAL == 0)
  1571.     {
  1572. /* the call to del will trash value, so take a copy now */
  1573. OutputValue(ST(0), value) ;
  1574.         RETVAL = db_del(db, key, R_CURSOR) ;
  1575.         if (RETVAL != 0)
  1576.             sv_setsv (ST(0), &PL_sv_undef) ;
  1577.     }
  1578. }
  1579. I32
  1580. push(db, ...)
  1581. DB_File db
  1582. ALIAS: PUSH = 1
  1583. CODE:
  1584. {
  1585.     DBTKEY key ;
  1586.     DBT value ;
  1587.     DB * Db = db->dbp ;
  1588.     int i ;
  1589.     STRLEN n_a;
  1590.     int keyval ;
  1591.     DBT_flags(key) ; 
  1592.     DBT_flags(value) ; 
  1593.     CurrentDB = db ;
  1594.     /* Set the Cursor to the Last element */
  1595.     RETVAL = do_SEQ(db, key, value, R_LAST) ;
  1596. #ifndef DB_VERSION_MAJOR          
  1597.     if (RETVAL >= 0)
  1598. #endif     
  1599.     {
  1600.      if (RETVAL == 0)
  1601.     keyval = *(int*)key.data ;
  1602. else
  1603.     keyval = 0 ;
  1604.         for (i = 1 ; i < items ; ++i)
  1605.         {
  1606.             value.data = SvPV(ST(i), n_a) ;
  1607.             value.size = n_a ;
  1608.     ++ keyval ;
  1609.             key.data = &keyval ;
  1610.             key.size = sizeof(int) ;
  1611.     RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
  1612.             if (RETVAL != 0)
  1613.                 break;
  1614.         }
  1615.     }
  1616. }
  1617. OUTPUT:
  1618.     RETVAL
  1619. I32
  1620. length(db)
  1621. DB_File db
  1622. ALIAS: FETCHSIZE = 1
  1623. CODE:
  1624.     CurrentDB = db ;
  1625.     RETVAL = GetArrayLength(aTHX_ db) ;
  1626. OUTPUT:
  1627.     RETVAL
  1628. #
  1629. # Now provide an interface to the rest of the DB functionality
  1630. #
  1631. int
  1632. db_del(db, key, flags=0)
  1633. DB_File db
  1634. DBTKEY key
  1635. u_int flags
  1636. CODE:
  1637.   CurrentDB = db ;
  1638.   RETVAL = db_del(db, key, flags) ;
  1639. #ifdef DB_VERSION_MAJOR
  1640.   if (RETVAL > 0)
  1641.     RETVAL = -1 ;
  1642.   else if (RETVAL == DB_NOTFOUND)
  1643.     RETVAL = 1 ;
  1644. #endif
  1645. OUTPUT:
  1646.   RETVAL
  1647. int
  1648. db_get(db, key, value, flags=0)
  1649. DB_File db
  1650. DBTKEY key
  1651. DBT value = NO_INIT
  1652. u_int flags
  1653. CODE:
  1654.   CurrentDB = db ;
  1655.   DBT_clear(value) ; 
  1656.   RETVAL = db_get(db, key, value, flags) ;
  1657. #ifdef DB_VERSION_MAJOR
  1658.   if (RETVAL > 0)
  1659.     RETVAL = -1 ;
  1660.   else if (RETVAL == DB_NOTFOUND)
  1661.     RETVAL = 1 ;
  1662. #endif
  1663. OUTPUT:
  1664.   RETVAL
  1665.   value
  1666. int
  1667. db_put(db, key, value, flags=0)
  1668. DB_File db
  1669. DBTKEY key
  1670. DBT value
  1671. u_int flags
  1672. CODE:
  1673.   CurrentDB = db ;
  1674.   RETVAL = db_put(db, key, value, flags) ;
  1675. #ifdef DB_VERSION_MAJOR
  1676.   if (RETVAL > 0)
  1677.     RETVAL = -1 ;
  1678.   else if (RETVAL == DB_KEYEXIST)
  1679.     RETVAL = 1 ;
  1680. #endif
  1681. OUTPUT:
  1682.   RETVAL
  1683.   key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
  1684. int
  1685. db_fd(db)
  1686. DB_File db
  1687. int status = 0 ;
  1688. CODE:
  1689.   CurrentDB = db ;
  1690. #ifdef DB_VERSION_MAJOR
  1691.   RETVAL = -1 ;
  1692.   status = (db->in_memory
  1693. ? -1 
  1694. : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
  1695.   if (status != 0)
  1696.     RETVAL = -1 ;
  1697. #else
  1698.   RETVAL = (db->in_memory
  1699. ? -1 
  1700. : ((db->dbp)->fd)(db->dbp) ) ;
  1701. #endif
  1702. OUTPUT:
  1703.   RETVAL
  1704. int
  1705. db_sync(db, flags=0)
  1706. DB_File db
  1707. u_int flags
  1708. CODE:
  1709.   CurrentDB = db ;
  1710.   RETVAL = db_sync(db, flags) ;
  1711. #ifdef DB_VERSION_MAJOR
  1712.   if (RETVAL > 0)
  1713.     RETVAL = -1 ;
  1714. #endif
  1715. OUTPUT:
  1716.   RETVAL
  1717. int
  1718. db_seq(db, key, value, flags)
  1719. DB_File db
  1720. DBTKEY key 
  1721. DBT value = NO_INIT
  1722. u_int flags
  1723. CODE:
  1724.   CurrentDB = db ;
  1725.   DBT_clear(value) ; 
  1726.   RETVAL = db_seq(db, key, value, flags);
  1727. #ifdef DB_VERSION_MAJOR
  1728.   if (RETVAL > 0)
  1729.     RETVAL = -1 ;
  1730.   else if (RETVAL == DB_NOTFOUND)
  1731.     RETVAL = 1 ;
  1732. #endif
  1733. OUTPUT:
  1734.   RETVAL
  1735.   key
  1736.   value
  1737. #ifdef DBM_FILTERING
  1738. #define setFilter(type)
  1739. {
  1740.     if (db->type)
  1741.         RETVAL = sv_mortalcopy(db->type) ;
  1742.     ST(0) = RETVAL ;
  1743.     if (db->type && (code == &PL_sv_undef)) {
  1744.                 SvREFCNT_dec(db->type) ;
  1745.         db->type = NULL ;
  1746.     }
  1747.     else if (code) {
  1748.         if (db->type)
  1749.             sv_setsv(db->type, code) ;
  1750.         else
  1751.             db->type = newSVsv(code) ;
  1752.     }     
  1753. }
  1754. SV *
  1755. filter_fetch_key(db, code)
  1756. DB_File db
  1757. SV * code
  1758. SV * RETVAL = &PL_sv_undef ;
  1759. CODE:
  1760.     setFilter(filter_fetch_key) ;
  1761. SV *
  1762. filter_store_key(db, code)
  1763. DB_File db
  1764. SV * code
  1765. SV * RETVAL = &PL_sv_undef ;
  1766. CODE:
  1767.     setFilter(filter_store_key) ;
  1768. SV *
  1769. filter_fetch_value(db, code)
  1770. DB_File db
  1771. SV * code
  1772. SV * RETVAL = &PL_sv_undef ;
  1773. CODE:
  1774.     setFilter(filter_fetch_value) ;
  1775. SV *
  1776. filter_store_value(db, code)
  1777. DB_File db
  1778. SV * code
  1779. SV * RETVAL = &PL_sv_undef ;
  1780. CODE:
  1781.     setFilter(filter_store_value) ;
  1782. #endif /* DBM_FILTERING */