| 1 | /* |
| 2 | * sdbm - ndbm work-alike hashed database library |
| 3 | * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978). |
| 4 | * author: oz@nexus.yorku.ca |
| 5 | * status: public domain. |
| 6 | */ |
| 7 | #define DBLKSIZ 4096 |
| 8 | #define PBLKSIZ 1024 |
| 9 | #define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */ |
| 10 | #define SPLTMAX 10 /* maximum allowed splits */ |
| 11 | /* for a single insertion */ |
| 12 | #ifdef VMS |
| 13 | #define DIRFEXT ".sdbm_dir" |
| 14 | #else |
| 15 | #define DIRFEXT ".dir" |
| 16 | #endif |
| 17 | #define PAGFEXT ".pag" |
| 18 | |
| 19 | typedef struct { |
| 20 | int dirf; /* directory file descriptor */ |
| 21 | int pagf; /* page file descriptor */ |
| 22 | int flags; /* status/error flags, see below */ |
| 23 | long maxbno; /* size of dirfile in bits */ |
| 24 | long curbit; /* current bit number */ |
| 25 | long hmask; /* current hash mask */ |
| 26 | long blkptr; /* current block for nextkey */ |
| 27 | int keyptr; /* current key for nextkey */ |
| 28 | long blkno; /* current page to read/write */ |
| 29 | long pagbno; /* current page in pagbuf */ |
| 30 | char pagbuf[PBLKSIZ]; /* page file block buffer */ |
| 31 | long dirbno; /* current block in dirbuf */ |
| 32 | char dirbuf[DBLKSIZ]; /* directory file block buffer */ |
| 33 | } DBM; |
| 34 | |
| 35 | #define DBM_RDONLY 0x1 /* data base open read-only */ |
| 36 | #define DBM_IOERR 0x2 /* data base I/O error */ |
| 37 | |
| 38 | /* |
| 39 | * utility macros |
| 40 | */ |
| 41 | #define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY) |
| 42 | #define sdbm_error(db) ((db)->flags & DBM_IOERR) |
| 43 | |
| 44 | #define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */ |
| 45 | |
| 46 | #define sdbm_dirfno(db) ((db)->dirf) |
| 47 | #define sdbm_pagfno(db) ((db)->pagf) |
| 48 | |
| 49 | typedef struct { |
| 50 | const char *dptr; |
| 51 | int dsize; |
| 52 | } datum; |
| 53 | |
| 54 | extern const datum nullitem |
| 55 | #ifdef DOINIT |
| 56 | = {0, 0} |
| 57 | #endif |
| 58 | ; |
| 59 | |
| 60 | #if defined(__STDC__) || defined(__cplusplus) || defined(CAN_PROTOTYPE) |
| 61 | #define proto(p) p |
| 62 | #else |
| 63 | #define proto(p) () |
| 64 | #endif |
| 65 | |
| 66 | /* |
| 67 | * flags to sdbm_store |
| 68 | */ |
| 69 | #define DBM_INSERT 0 |
| 70 | #define DBM_REPLACE 1 |
| 71 | |
| 72 | /* |
| 73 | * ndbm interface |
| 74 | */ |
| 75 | extern DBM *sdbm_open proto((char *, int, int)); |
| 76 | extern void sdbm_close proto((DBM *)); |
| 77 | extern datum sdbm_fetch proto((DBM *, datum)); |
| 78 | extern int sdbm_delete proto((DBM *, datum)); |
| 79 | extern int sdbm_store proto((DBM *, datum, datum, int)); |
| 80 | extern datum sdbm_firstkey proto((DBM *)); |
| 81 | extern datum sdbm_nextkey proto((DBM *)); |
| 82 | extern int sdbm_exists proto((DBM *, datum)); |
| 83 | |
| 84 | /* |
| 85 | * other |
| 86 | */ |
| 87 | extern DBM *sdbm_prep proto((char *, char *, int, int)); |
| 88 | extern long sdbm_hash proto((const char *, int)); |
| 89 | |
| 90 | #ifndef SDBM_ONLY |
| 91 | #define dbm_open sdbm_open |
| 92 | #define dbm_close sdbm_close |
| 93 | #define dbm_fetch sdbm_fetch |
| 94 | #define dbm_store sdbm_store |
| 95 | #define dbm_delete sdbm_delete |
| 96 | #define dbm_firstkey sdbm_firstkey |
| 97 | #define dbm_nextkey sdbm_nextkey |
| 98 | #define dbm_error sdbm_error |
| 99 | #define dbm_clearerr sdbm_clearerr |
| 100 | #endif |
| 101 | |
| 102 | /* Most of the following is stolen from perl.h. We don't include |
| 103 | perl.h here because we just want the portability parts of perl.h, |
| 104 | not everything else. |
| 105 | */ |
| 106 | #ifndef H_PERL /* Include guard */ |
| 107 | #include "embed.h" /* Follow all the global renamings. */ |
| 108 | |
| 109 | /* |
| 110 | * The following contortions are brought to you on behalf of all the |
| 111 | * standards, semi-standards, de facto standards, not-so-de-facto standards |
| 112 | * of the world, as well as all the other botches anyone ever thought of. |
| 113 | * The basic theory is that if we work hard enough here, the rest of the |
| 114 | * code can be a lot prettier. Well, so much for theory. Sorry, Henry... |
| 115 | */ |
| 116 | |
| 117 | #include <errno.h> |
| 118 | #ifdef HAS_SOCKET |
| 119 | # ifdef I_NET_ERRNO |
| 120 | # include <net/errno.h> |
| 121 | # endif |
| 122 | #endif |
| 123 | |
| 124 | #if defined(__STDC__) || defined(_AIX) || defined(__stdc__) || defined(__cplusplus) |
| 125 | # define STANDARD_C 1 |
| 126 | #endif |
| 127 | |
| 128 | #include <stdio.h> |
| 129 | #include <ctype.h> |
| 130 | #include <setjmp.h> |
| 131 | |
| 132 | #if defined(I_UNISTD) |
| 133 | #include <unistd.h> |
| 134 | #endif |
| 135 | |
| 136 | #ifdef VMS |
| 137 | # include <file.h> |
| 138 | # include <unixio.h> |
| 139 | #endif |
| 140 | |
| 141 | #ifdef I_SYS_PARAM |
| 142 | # if !defined(MSDOS) && !defined(WIN32) && !defined(VMS) |
| 143 | # ifdef PARAM_NEEDS_TYPES |
| 144 | # include <sys/types.h> |
| 145 | # endif |
| 146 | # include <sys/param.h> |
| 147 | # endif |
| 148 | #endif |
| 149 | |
| 150 | #ifndef _TYPES_ /* If types.h defines this it's easy. */ |
| 151 | # ifndef major /* Does everyone's types.h define this? */ |
| 152 | # include <sys/types.h> |
| 153 | # endif |
| 154 | #endif |
| 155 | |
| 156 | #include <sys/stat.h> |
| 157 | |
| 158 | #ifndef SEEK_SET |
| 159 | # ifdef L_SET |
| 160 | # define SEEK_SET L_SET |
| 161 | # else |
| 162 | # define SEEK_SET 0 /* Wild guess. */ |
| 163 | # endif |
| 164 | #endif |
| 165 | |
| 166 | /* Use all the "standard" definitions? */ |
| 167 | #if defined(STANDARD_C) && defined(I_STDLIB) |
| 168 | # include <stdlib.h> |
| 169 | #endif /* STANDARD_C */ |
| 170 | |
| 171 | #define MEM_SIZE Size_t |
| 172 | |
| 173 | /* This comes after <stdlib.h> so we don't try to change the standard |
| 174 | * library prototypes; we'll use our own instead. */ |
| 175 | |
| 176 | #if defined(MYMALLOC) && !defined(PERL_POLLUTE_MALLOC) |
| 177 | # define malloc Perl_malloc |
| 178 | # define calloc Perl_calloc |
| 179 | # define realloc Perl_realloc |
| 180 | # define free Perl_mfree |
| 181 | |
| 182 | #ifdef __cplusplus |
| 183 | extern "C" { |
| 184 | #endif |
| 185 | |
| 186 | Malloc_t Perl_malloc proto((MEM_SIZE nbytes)); |
| 187 | Malloc_t Perl_calloc proto((MEM_SIZE elements, MEM_SIZE size)); |
| 188 | Malloc_t Perl_realloc proto((Malloc_t where, MEM_SIZE nbytes)); |
| 189 | Free_t Perl_mfree proto((Malloc_t where)); |
| 190 | |
| 191 | #ifdef __cplusplus |
| 192 | } |
| 193 | #endif |
| 194 | |
| 195 | #endif /* MYMALLOC */ |
| 196 | |
| 197 | #ifdef I_STRING |
| 198 | # ifndef __ultrix__ |
| 199 | # include <string.h> |
| 200 | # endif |
| 201 | #else |
| 202 | # include <strings.h> |
| 203 | #endif |
| 204 | |
| 205 | #ifdef I_MEMORY |
| 206 | #include <memory.h> |
| 207 | #endif |
| 208 | |
| 209 | #ifdef __cplusplus |
| 210 | #define HAS_MEMCPY |
| 211 | #endif |
| 212 | |
| 213 | #ifdef HAS_MEMCPY |
| 214 | # if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY) |
| 215 | # ifndef memcpy |
| 216 | extern char * memcpy proto((char*, char*, int)); |
| 217 | # endif |
| 218 | # endif |
| 219 | #else |
| 220 | # ifndef memcpy |
| 221 | # ifdef HAS_BCOPY |
| 222 | # define memcpy(d,s,l) bcopy(s,d,l) |
| 223 | # else |
| 224 | # define memcpy(d,s,l) my_bcopy(s,d,l) |
| 225 | # endif |
| 226 | # endif |
| 227 | #endif /* HAS_MEMCPY */ |
| 228 | |
| 229 | #ifdef HAS_MEMSET |
| 230 | # if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY) |
| 231 | # ifndef memset |
| 232 | extern char *memset proto((char*, int, int)); |
| 233 | # endif |
| 234 | # endif |
| 235 | # define memzero(d,l) memset(d,0,l) |
| 236 | #else |
| 237 | # ifndef memzero |
| 238 | # ifdef HAS_BZERO |
| 239 | # define memzero(d,l) bzero(d,l) |
| 240 | # else |
| 241 | # define memzero(d,l) my_bzero(d,l) |
| 242 | # endif |
| 243 | # endif |
| 244 | #endif /* HAS_MEMSET */ |
| 245 | |
| 246 | #if defined(mips) && defined(ultrix) && !defined(__STDC__) |
| 247 | # undef HAS_MEMCMP |
| 248 | #endif |
| 249 | |
| 250 | #if defined(HAS_MEMCMP) && defined(HAS_SANE_MEMCMP) |
| 251 | # if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY) |
| 252 | # ifndef memcmp |
| 253 | extern int memcmp proto((char*, char*, int)); |
| 254 | # endif |
| 255 | # endif |
| 256 | # ifdef BUGGY_MSC |
| 257 | # pragma function(memcmp) |
| 258 | # endif |
| 259 | #else |
| 260 | # ifndef memcmp |
| 261 | /* maybe we should have included the full embedding header... */ |
| 262 | # define memcmp Perl_my_memcmp |
| 263 | #ifndef __cplusplus |
| 264 | extern int memcmp proto((char*, char*, int)); |
| 265 | #endif |
| 266 | # endif |
| 267 | #endif /* HAS_MEMCMP */ |
| 268 | |
| 269 | #ifndef HAS_BCMP |
| 270 | # ifndef bcmp |
| 271 | # define bcmp(s1,s2,l) memcmp(s1,s2,l) |
| 272 | # endif |
| 273 | #endif /* !HAS_BCMP */ |
| 274 | |
| 275 | #ifdef HAS_MEMCMP |
| 276 | # define memNE(s1,s2,l) (memcmp(s1,s2,l)) |
| 277 | # define memEQ(s1,s2,l) (!memcmp(s1,s2,l)) |
| 278 | #else |
| 279 | # define memNE(s1,s2,l) (bcmp(s1,s2,l)) |
| 280 | # define memEQ(s1,s2,l) (!bcmp(s1,s2,l)) |
| 281 | #endif |
| 282 | |
| 283 | #ifdef I_NETINET_IN |
| 284 | # ifdef VMS |
| 285 | # include <in.h> |
| 286 | # else |
| 287 | # include <netinet/in.h> |
| 288 | # endif |
| 289 | #endif |
| 290 | |
| 291 | #endif /* Include guard */ |
| 292 | |