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