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