This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Clean up a few core dumps when layers are used in unexpected ways.
[perl5.git] / ext / NDBM_File / NDBM_File.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 /* If using the DB3 emulation, ENTER is defined both
5  * by DB3 and Perl.  We drop the Perl definition now.
6  * See also INSTALL section on DB3.
7  * -- Stanislav Brabec <utx@penguin.cz> */
8 #undef ENTER
9 #include <ndbm.h>
10
11 typedef struct {
12         DBM *   dbp ;
13         SV *    filter_fetch_key ;
14         SV *    filter_store_key ;
15         SV *    filter_fetch_value ;
16         SV *    filter_store_value ;
17         int     filtering ;
18         } NDBM_File_type;
19
20 typedef NDBM_File_type * NDBM_File ;
21 typedef datum datum_key ;
22 typedef datum datum_value ;
23
24 #define ckFilter(arg,type,name)                                 \
25         if (db->type) {                                         \
26             SV * save_defsv ;                                   \
27             /* printf("filtering %s\n", name) ;*/               \
28             if (db->filtering)                                  \
29                 croak("recursion detected in %s", name) ;       \
30             db->filtering = TRUE ;                              \
31             save_defsv = newSVsv(DEFSV) ;                       \
32             sv_setsv(DEFSV, arg) ;                              \
33             PUSHMARK(sp) ;                                      \
34             (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS);  \
35             sv_setsv(arg, DEFSV) ;                              \
36             sv_setsv(DEFSV, save_defsv) ;                       \
37             SvREFCNT_dec(save_defsv) ;                          \
38             db->filtering = FALSE ;                             \
39             /*printf("end of filtering %s\n", name) ;*/         \
40         }
41
42
43 MODULE = NDBM_File      PACKAGE = NDBM_File     PREFIX = ndbm_
44
45 NDBM_File
46 ndbm_TIEHASH(dbtype, filename, flags, mode)
47         char *          dbtype
48         char *          filename
49         int             flags
50         int             mode
51         CODE:
52         {
53             DBM *       dbp ;
54
55             RETVAL = NULL ;
56             if (dbp =  dbm_open(filename, flags, mode)) {
57                 RETVAL = (NDBM_File)safemalloc(sizeof(NDBM_File_type)) ;
58                 Zero(RETVAL, 1, NDBM_File_type) ;
59                 RETVAL->dbp = dbp ;
60             }
61             
62         }
63         OUTPUT:
64           RETVAL
65
66 void
67 ndbm_DESTROY(db)
68         NDBM_File       db
69         CODE:
70         dbm_close(db->dbp);
71         safefree(db);
72
73 #define ndbm_FETCH(db,key)                      dbm_fetch(db->dbp,key)
74 datum_value
75 ndbm_FETCH(db, key)
76         NDBM_File       db
77         datum_key       key
78
79 #define ndbm_STORE(db,key,value,flags)          dbm_store(db->dbp,key,value,flags)
80 int
81 ndbm_STORE(db, key, value, flags = DBM_REPLACE)
82         NDBM_File       db
83         datum_key       key
84         datum_value     value
85         int             flags
86     CLEANUP:
87         if (RETVAL) {
88             if (RETVAL < 0 && errno == EPERM)
89                 croak("No write permission to ndbm file");
90             croak("ndbm store returned %d, errno %d, key \"%s\"",
91                         RETVAL,errno,key.dptr);
92             dbm_clearerr(db->dbp);
93         }
94
95 #define ndbm_DELETE(db,key)                     dbm_delete(db->dbp,key)
96 int
97 ndbm_DELETE(db, key)
98         NDBM_File       db
99         datum_key       key
100
101 #define ndbm_FIRSTKEY(db)                       dbm_firstkey(db->dbp)
102 datum_key
103 ndbm_FIRSTKEY(db)
104         NDBM_File       db
105
106 #define ndbm_NEXTKEY(db,key)                    dbm_nextkey(db->dbp)
107 datum_key
108 ndbm_NEXTKEY(db, key)
109         NDBM_File       db
110         datum_key       key
111
112 #define ndbm_error(db)                          dbm_error(db->dbp)
113 int
114 ndbm_error(db)
115         NDBM_File       db
116
117 #define ndbm_clearerr(db)                       dbm_clearerr(db->dbp)
118 void
119 ndbm_clearerr(db)
120         NDBM_File       db
121
122
123 #define setFilter(type)                                 \
124         {                                               \
125             if (db->type)                               \
126                 RETVAL = sv_mortalcopy(db->type) ;      \
127             ST(0) = RETVAL ;                            \
128             if (db->type && (code == &PL_sv_undef)) {   \
129                 SvREFCNT_dec(db->type) ;                \
130                 db->type = NULL ;                       \
131             }                                           \
132             else if (code) {                            \
133                 if (db->type)                           \
134                     sv_setsv(db->type, code) ;          \
135                 else                                    \
136                     db->type = newSVsv(code) ;          \
137             }                                           \
138         }
139
140
141
142 SV *
143 filter_fetch_key(db, code)
144         NDBM_File       db
145         SV *            code
146         SV *            RETVAL = &PL_sv_undef ;
147         CODE:
148             setFilter(filter_fetch_key) ;
149
150 SV *
151 filter_store_key(db, code)
152         NDBM_File       db
153         SV *            code
154         SV *            RETVAL =  &PL_sv_undef ;
155         CODE:
156             setFilter(filter_store_key) ;
157
158 SV *
159 filter_fetch_value(db, code)
160         NDBM_File       db
161         SV *            code
162         SV *            RETVAL =  &PL_sv_undef ;
163         CODE:
164             setFilter(filter_fetch_value) ;
165
166 SV *
167 filter_store_value(db, code)
168         NDBM_File       db
169         SV *            code
170         SV *            RETVAL =  &PL_sv_undef ;
171         CODE:
172             setFilter(filter_store_value) ;
173