comparison src/database.c @ 272:c5d627a313b1 r21-0b34

Import from CVS: tag r21-0b34
author cvs
date Mon, 13 Aug 2007 10:28:48 +0200
parents 78478c60bfcd
children 54f7aa390f4f
comparison
equal deleted inserted replaced
271:c7b7086b0a39 272:c5d627a313b1
24 /* Substantially rewritten by Martin Buchholz */ 24 /* Substantially rewritten by Martin Buchholz */
25 /* db 2.x support added by Andreas Jaeger */ 25 /* db 2.x support added by Andreas Jaeger */
26 26
27 #include <config.h> 27 #include <config.h>
28 #include "lisp.h" 28 #include "lisp.h"
29 #include "sysfile.h"
29 #include <errno.h> 30 #include <errno.h>
30 31
31 #ifndef HAVE_DATABASE 32 #ifndef HAVE_DATABASE
32 #error database.c being compiled, but HAVE_DATABASE not defined! 33 #error HAVE_DATABASE not defined!!
33 #endif /* HAVE_DATABASE */ 34 #endif
34 35
35 #include "database.h" /* Our include file */ 36 #include "database.h" /* Our include file */
36 37
37 #ifdef HAVE_BERKELEY_DB 38 #ifdef HAVE_BERKELEY_DB
38 /* Work around Berkeley DB's use of int types which are defined 39 /* Work around Berkeley DB's use of int types which are defined
54 #include DB_H_PATH /* Berkeley db's header file */ 55 #include DB_H_PATH /* Berkeley db's header file */
55 #ifndef DB_VERSION_MAJOR 56 #ifndef DB_VERSION_MAJOR
56 # define DB_VERSION_MAJOR 1 57 # define DB_VERSION_MAJOR 1
57 #endif /* DB_VERSION_MAJOR */ 58 #endif /* DB_VERSION_MAJOR */
58 Lisp_Object Qberkeley_db; 59 Lisp_Object Qberkeley_db;
59 Lisp_Object Qhash; 60 Lisp_Object Qhash, Qbtree, Qrecno, Qunknown;
60 Lisp_Object Qbtree;
61 Lisp_Object Qrecno;
62 #endif /* HAVE_BERKELEY_DB */ 61 #endif /* HAVE_BERKELEY_DB */
63 62
64 #ifdef HAVE_DBM 63 #ifdef HAVE_DBM
65 #include <ndbm.h> 64 #include <ndbm.h>
66 Lisp_Object Qdbm; 65 Lisp_Object Qdbm;
68 67
69 Lisp_Object Qdatabasep; 68 Lisp_Object Qdatabasep;
70 69
71 typedef enum { DB_DBM, DB_BERKELEY, DB_IS_UNKNOWN } XEMACS_DB_TYPE; 70 typedef enum { DB_DBM, DB_BERKELEY, DB_IS_UNKNOWN } XEMACS_DB_TYPE;
72 71
73 struct database; 72 struct Lisp_Database;
74 typedef struct database database;
75 73
76 typedef struct 74 typedef struct
77 { 75 {
78 CONST char * (*get_subtype) (struct database *); 76 Lisp_Object (*get_subtype) (struct Lisp_Database *);
79 CONST char * (*get_type) (struct database *); 77 Lisp_Object (*get_type) (struct Lisp_Database *);
80 Lisp_Object (*get) (struct database *, Lisp_Object); 78 Lisp_Object (*get) (struct Lisp_Database *, Lisp_Object);
81 int (*put) (struct database *, Lisp_Object, Lisp_Object, Lisp_Object); 79 int (*put) (struct Lisp_Database *, Lisp_Object, Lisp_Object, Lisp_Object);
82 int (*rem) (struct database *, Lisp_Object); 80 int (*rem) (struct Lisp_Database *, Lisp_Object);
83 void (*map) (struct database *, Lisp_Object); 81 void (*map) (struct Lisp_Database *, Lisp_Object);
84 Lisp_Object (*get_lisp_type) (struct database *); 82 void (*close) (struct Lisp_Database *);
85 void (*close) (struct database *); 83 Lisp_Object (*last_error) (struct Lisp_Database *);
86 Lisp_Object (*last_error) (struct database *);
87 } DB_FUNCS; 84 } DB_FUNCS;
88 85
89 struct database 86 struct Lisp_Database
90 { 87 {
91 struct lcrecord_header header; 88 struct lcrecord_header header;
92 Lisp_Object fname; 89 Lisp_Object fname;
93 XEMACS_DB_TYPE type; 90 XEMACS_DB_TYPE type;
94 int mode; 91 int mode;
105 #ifdef MULE 102 #ifdef MULE
106 Lisp_Object coding_system; 103 Lisp_Object coding_system;
107 #endif 104 #endif
108 }; 105 };
109 106
110 #define XDATABASE(x) XRECORD (x, database, struct database) 107 #define XDATABASE(x) XRECORD (x, database, struct Lisp_Database)
111 #define XSETDATABASE(x, p) XSETRECORD (x, p, database) 108 #define XSETDATABASE(x, p) XSETRECORD (x, p, database)
112 #define DATABASEP(x) RECORDP (x, database) 109 #define DATABASEP(x) RECORDP (x, database)
113 #define GC_DATABASEP(x) GC_RECORDP (x, database) 110 #define GC_DATABASEP(x) GC_RECORDP (x, database)
114 #define CHECK_DATABASE(x) CHECK_RECORD (x, database) 111 #define CHECK_DATABASE(x) CHECK_RECORD (x, database)
115 #define CONCHECK_DATABASE(x) CONCHECK_RECORD (x, database) 112 #define CONCHECK_DATABASE(x) CONCHECK_RECORD (x, database)
116 #define DATABASE_LIVE_P(x) (x->live_p) 113 #define DATABASE_LIVE_P(x) (x->live_p)
117 static Lisp_Object mark_database (Lisp_Object, void (*) (Lisp_Object)); 114
118 static void print_database (Lisp_Object, Lisp_Object, int); 115 #define CHECK_LIVE_DATABASE(db) do { \
119 static void finalize_database (void *, int); 116 CHECK_DATABASE (db); \
117 if (!DATABASE_LIVE_P (XDATABASE(db))) \
118 signal_simple_error ("Attempting to access closed database", db); \
119 } while (0)
120
121
122 static struct Lisp_Database *
123 allocate_database (void)
124 {
125 struct Lisp_Database *db =
126 alloc_lcrecord_type (struct Lisp_Database, lrecord_database);
127
128 db->fname = Qnil;
129 db->live_p = 0;
130 #ifdef HAVE_BERKELEY_DB
131 db->db_handle = NULL;
132 #endif
133 #ifdef HAVE_DBM
134 db->dbm_handle = NULL;
135 #endif
136 db->access_ = 0;
137 db->mode = 0;
138 db->dberrno = 0;
139 db->type = DB_IS_UNKNOWN;
140 #ifdef MULE
141 db->coding_system = Fget_coding_system (Qbinary);
142 #endif
143 return db;
144 }
145
146 static Lisp_Object
147 mark_database (Lisp_Object obj, void (*markobj) (Lisp_Object))
148 {
149 struct Lisp_Database *db = XDATABASE (obj);
150
151 ((markobj) (db->fname));
152 return Qnil;
153 }
154
155 static void
156 print_database (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
157 {
158 char buf[64];
159 struct Lisp_Database *db = XDATABASE (obj);
160
161 if (print_readably)
162 error ("printing unreadable object #<database 0x%x>", db->header.uid);
163
164 write_c_string ("#<database \"", printcharfun);
165 print_internal (db->fname, printcharfun, 0);
166 sprintf (buf, "\" (%s/%s/%s) 0x%x>",
167 (char *) string_data (XSYMBOL (db->funcs->get_type (db))->name),
168 (char *) string_data (XSYMBOL (db->funcs->get_subtype (db))->name),
169 (!DATABASE_LIVE_P (db) ? "closed" :
170 (db->access_ & O_WRONLY) ? "writeonly" :
171 (db->access_ & O_RDWR) ? "readwrite" : "readonly"),
172 db->header.uid);
173 write_c_string (buf, printcharfun);
174 }
175
176 static void
177 finalize_database (void *header, int for_disksave)
178 {
179 struct Lisp_Database *db = (struct Lisp_Database *) header;
180
181 if (for_disksave)
182 {
183 Lisp_Object obj;
184 XSETOBJ (obj, Lisp_Type_Record, (void *) db);
185
186 signal_simple_error
187 ("Can't dump an emacs containing database objects", obj);
188 }
189 db->funcs->close (db);
190 }
191
120 DEFINE_LRECORD_IMPLEMENTATION ("database", database, 192 DEFINE_LRECORD_IMPLEMENTATION ("database", database,
121 mark_database, print_database, 193 mark_database, print_database,
122 finalize_database, 0, 0, 194 finalize_database, 0, 0,
123 struct database); 195 struct Lisp_Database);
124 196
125 #define CHECK_LIVE_DATABASE(db) do { \ 197 DEFUN ("close-database", Fclose_database, 1, 1, 0, /*
126 CHECK_DATABASE(db); \ 198 Close database DATABASE.
127 if (!DATABASE_LIVE_P (XDATABASE(db))) \ 199 */
128 signal_simple_error ("Attempting to access closed database", db); \ 200 (database))
129 } while (0) 201 {
130 202 struct Lisp_Database *db;
131 203 CHECK_LIVE_DATABASE (database);
132 static struct database * 204 db = XDATABASE (database);
133 allocate_database (void) 205 db->funcs->close (db);
134 { 206 db->live_p = 0;
135 struct database *dbase =
136 alloc_lcrecord_type (struct database, lrecord_database);
137
138 dbase->fname = Qnil;
139 dbase->live_p = 0;
140 #ifdef HAVE_BERKELEY_DB
141 dbase->db_handle = NULL;
142 #endif
143 #ifdef HAVE_DBM
144 dbase->dbm_handle = NULL;
145 #endif
146 dbase->access_ = 0;
147 dbase->mode = 0;
148 dbase->dberrno = 0;
149 dbase->type = DB_IS_UNKNOWN;
150 #ifdef MULE
151 dbase->coding_system = Fget_coding_system (Qbinary);
152 #endif
153 return dbase;
154 }
155
156 static Lisp_Object
157 mark_database (Lisp_Object obj, void (*markobj) (Lisp_Object))
158 {
159 struct database *dbase = XDATABASE (obj);
160
161 ((markobj) (dbase->fname));
162 return Qnil; 207 return Qnil;
163 } 208 }
164 209
165 static void 210 DEFUN ("database-type", Fdatabase_type, 1, 1, 0, /*
166 print_database (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 211 Return the type of database DATABASE.
167 { 212 */
168 char buf[64]; 213 (database))
169 struct database *dbase = XDATABASE (obj); 214 {
170 215 CHECK_DATABASE (database);
171 if (print_readably) 216
172 error ("printing unreadable object #<database 0x%x>", dbase->header.uid); 217 return XDATABASE (database)->funcs->get_type (XDATABASE (database));
173 218 }
174 write_c_string ("#<database \"", printcharfun); 219
175 print_internal (dbase->fname, printcharfun, 0); 220 DEFUN ("database-subtype", Fdatabase_subtype, 1, 1, 0, /*
176 sprintf (buf, "\" (%s/%s/%s) 0x%x>", 221 Return the subtype of database DATABASE, if any.
177 dbase->funcs->get_type (dbase), 222 */
178 dbase->funcs->get_subtype (dbase), 223 (database))
179 (!DATABASE_LIVE_P (dbase) ? "closed" : 224 {
180 (dbase->access_ & O_WRONLY) ? "writeonly" : 225 CHECK_DATABASE (database);
181 (dbase->access_ & O_RDWR) ? "readwrite" : "readonly"), 226
182 dbase->header.uid); 227 return XDATABASE (database)->funcs->get_subtype (XDATABASE (database));
183 write_c_string (buf, printcharfun); 228 }
184 } 229
185 230 DEFUN ("database-live-p", Fdatabase_live_p, 1, 1, 0, /*
186 static void 231 Return t if OBJ is an active database.
187 finalize_database (void *header, int for_disksave)
188 {
189 struct database *db = (struct database *) header;
190
191 if (for_disksave)
192 {
193 Lisp_Object obj;
194 XSETOBJ (obj, Lisp_Type_Record, (void *) db);
195
196 signal_simple_error
197 ("Can't dump an emacs containing window system objects", obj);
198 }
199 db->funcs->close (db);
200 }
201
202 DEFUN ("close-database", Fclose_database, 1, 1, 0, /*
203 Close database OBJ.
204 */ 232 */
205 (obj)) 233 (obj))
206 { 234 {
207 CHECK_LIVE_DATABASE (obj); 235 return DATABASEP (obj) && DATABASE_LIVE_P (XDATABASE (obj)) ? Qt : Qnil;
208 XDATABASE (obj)->funcs->close (XDATABASE (obj));
209 XDATABASE (obj)->live_p = 0;
210 return Qnil;
211 }
212
213 DEFUN ("database-type", Fdatabase_type, 1, 1, 0, /*
214 Return the type of database OBJ.
215 */
216 (obj))
217 {
218 CHECK_DATABASE (obj);
219
220 return XDATABASE (obj)->funcs->get_lisp_type (XDATABASE (obj));
221 }
222
223 DEFUN ("database-subtype", Fdatabase_subtype, 1, 1, 0, /*
224 Return the subtype of database OBJ, if any.
225 */
226 (obj))
227 {
228 CHECK_DATABASE (obj);
229
230 return intern (XDATABASE (obj)->funcs->get_subtype (XDATABASE (obj)));
231 }
232
233 DEFUN ("database-live-p", Fdatabase_live_p, 1, 1, 0, /*
234 Return t iff OBJ is an active database, else nil.
235 */
236 (obj))
237 {
238 CHECK_DATABASE (obj);
239
240 return DATABASE_LIVE_P (XDATABASE (obj)) ? Qt : Qnil;
241 } 236 }
242 237
243 DEFUN ("database-file-name", Fdatabase_file_name, 1, 1, 0, /* 238 DEFUN ("database-file-name", Fdatabase_file_name, 1, 1, 0, /*
244 Return the filename associated with the database OBJ. 239 Return the filename associated with the database DATABASE.
245 */ 240 */
246 (obj)) 241 (database))
247 { 242 {
248 CHECK_DATABASE (obj); 243 CHECK_DATABASE (database);
249 244
250 return XDATABASE (obj)->fname; 245 return XDATABASE (database)->fname;
251 } 246 }
252 247
253 DEFUN ("databasep", Fdatabasep, 1, 1, 0, /* 248 DEFUN ("databasep", Fdatabasep, 1, 1, 0, /*
254 Return t iff OBJ is a database, else nil. 249 Return t if OBJ is a database.
255 */ 250 */
256 (obj)) 251 (obj))
257 { 252 {
258 return DATABASEP (obj) ? Qt : Qnil; 253 return DATABASEP (obj) ? Qt : Qnil;
259 } 254 }
260 255
261 #ifdef HAVE_DBM 256 #ifdef HAVE_DBM
262 static void 257 static void
263 dbm_map (struct database *db, Lisp_Object func) 258 dbm_map (struct Lisp_Database *db, Lisp_Object func)
264 { 259 {
265 datum keydatum, valdatum; 260 datum keydatum, valdatum;
266 Lisp_Object key, val; 261 Lisp_Object key, val;
267 262
268 for (keydatum = dbm_firstkey (db->dbm_handle); 263 for (keydatum = dbm_firstkey (db->dbm_handle);
275 call2 (func, key, val); 270 call2 (func, key, val);
276 } 271 }
277 } 272 }
278 273
279 static Lisp_Object 274 static Lisp_Object
280 dbm_get (struct database *db, Lisp_Object key) 275 dbm_get (struct Lisp_Database *db, Lisp_Object key)
281 { 276 {
282 datum keydatum, valdatum; 277 datum keydatum, valdatum;
283 278
284 keydatum.dptr = (char *) XSTRING_DATA (key); 279 keydatum.dptr = (char *) XSTRING_DATA (key);
285 keydatum.dsize = XSTRING_LENGTH (key); 280 keydatum.dsize = XSTRING_LENGTH (key);
289 ? make_string ((unsigned char *) valdatum.dptr, valdatum.dsize) 284 ? make_string ((unsigned char *) valdatum.dptr, valdatum.dsize)
290 : Qnil); 285 : Qnil);
291 } 286 }
292 287
293 static int 288 static int
294 dbm_put (struct database *db, 289 dbm_put (struct Lisp_Database *db,
295 Lisp_Object key, Lisp_Object val, Lisp_Object replace) 290 Lisp_Object key, Lisp_Object val, Lisp_Object replace)
296 { 291 {
297 datum keydatum, valdatum; 292 datum keydatum, valdatum;
298 293
299 valdatum.dptr = (char *) XSTRING_DATA (val); 294 valdatum.dptr = (char *) XSTRING_DATA (val);
304 return !dbm_store (db->dbm_handle, keydatum, valdatum, 299 return !dbm_store (db->dbm_handle, keydatum, valdatum,
305 NILP (replace) ? DBM_INSERT : DBM_REPLACE); 300 NILP (replace) ? DBM_INSERT : DBM_REPLACE);
306 } 301 }
307 302
308 static int 303 static int
309 dbm_remove (struct database *db, Lisp_Object key) 304 dbm_remove (struct Lisp_Database *db, Lisp_Object key)
310 { 305 {
311 datum keydatum; 306 datum keydatum;
312 307
313 keydatum.dptr = (char *) XSTRING_DATA (key); 308 keydatum.dptr = (char *) XSTRING_DATA (key);
314 keydatum.dsize = XSTRING_LENGTH (key); 309 keydatum.dsize = XSTRING_LENGTH (key);
315 310
316 return dbm_delete (db->dbm_handle, keydatum); 311 return dbm_delete (db->dbm_handle, keydatum);
317 } 312 }
318 313
319 static Lisp_Object 314 static Lisp_Object
320 dbm_lisp_type (struct database *db) 315 dbm_type (struct Lisp_Database *db)
321 { 316 {
322 return Qdbm; 317 return Qdbm;
323 } 318 }
324 319
325 static CONST char * 320 static Lisp_Object
326 dbm_type (struct database *db) 321 dbm_subtype (struct Lisp_Database *db)
327 { 322 {
328 return "dbm"; 323 return Qnil;
329 } 324 }
330 325
331 static CONST char * 326 static Lisp_Object
332 dbm_subtype (struct database *db) 327 dbm_lasterr (struct Lisp_Database *db)
333 { 328 {
334 return "nil"; 329 return lisp_strerror (db->dberrno);
335 }
336
337 static Lisp_Object
338 dbm_lasterr (struct database *dbp)
339 {
340 return lisp_strerror (dbp->dberrno);
341 } 330 }
342 331
343 static void 332 static void
344 dbm_closeit (struct database *db) 333 dbm_closeit (struct Lisp_Database *db)
345 { 334 {
346 if (db->dbm_handle) 335 if (db->dbm_handle)
347 { 336 {
348 dbm_close (db->dbm_handle); 337 dbm_close (db->dbm_handle);
349 db->dbm_handle = NULL; 338 db->dbm_handle = NULL;
356 dbm_type, 345 dbm_type,
357 dbm_get, 346 dbm_get,
358 dbm_put, 347 dbm_put,
359 dbm_remove, 348 dbm_remove,
360 dbm_map, 349 dbm_map,
361 dbm_lisp_type,
362 dbm_closeit, 350 dbm_closeit,
363 dbm_lasterr 351 dbm_lasterr
364 }; 352 };
365 #endif /* HAVE_DBM */ 353 #endif /* HAVE_DBM */
366 354
367 #ifdef HAVE_BERKELEY_DB 355 #ifdef HAVE_BERKELEY_DB
368 static Lisp_Object 356 static Lisp_Object
369 berkdb_lisp_type (struct database *db) 357 berkdb_type (struct Lisp_Database *db)
370 { 358 {
371 return Qberkeley_db; 359 return Qberkeley_db;
372 } 360 }
373 361
374 static CONST char * 362 static Lisp_Object
375 berkdb_type (struct database *db) 363 berkdb_subtype (struct Lisp_Database *db)
376 {
377 return "berkeley";
378 }
379
380 static CONST char *
381 berkdb_subtype (struct database *db)
382 { 364 {
383 if (!db->db_handle) 365 if (!db->db_handle)
384 return "nil"; 366 return Qnil;
385 367
386 switch (db->db_handle->type) 368 switch (db->db_handle->type)
387 { 369 {
388 case DB_BTREE: return "btree"; 370 case DB_BTREE: return Qbtree;
389 case DB_HASH: return "hash"; 371 case DB_HASH: return Qhash;
390 case DB_RECNO: return "recno"; 372 case DB_RECNO: return Qrecno;
391 default: return "unknown"; 373 default: return Qunknown;
392 } 374 }
393 } 375 }
394 376
395 static Lisp_Object 377 static Lisp_Object
396 berkdb_lasterr (struct database *dbp) 378 berkdb_lasterr (struct Lisp_Database *db)
397 { 379 {
398 return lisp_strerror (dbp->dberrno); 380 return lisp_strerror (db->dberrno);
399 } 381 }
400 382
401 static Lisp_Object 383 static Lisp_Object
402 berkdb_get (struct database *db, Lisp_Object key) 384 berkdb_get (struct Lisp_Database *db, Lisp_Object key)
403 { 385 {
404 /* #### Needs mule-izing */ 386 /* #### Needs mule-izing */
405 DBT keydatum, valdatum; 387 DBT keydatum, valdatum;
406 int status = 0; 388 int status = 0;
407 389
408 #if DB_VERSION_MAJOR == 2 390 #if DB_VERSION_MAJOR == 2
409 /* Always initialize keydatum, valdatum. */ 391 /* Always initialize keydatum, valdatum. */
410 memset(&keydatum, 0, sizeof(keydatum)); 392 xzero (keydatum);
411 memset(&valdatum, 0, sizeof(valdatum)); 393 xzero (valdatum);
412 #endif /* DV_VERSION_MAJOR = 2 */ 394 #endif /* DV_VERSION_MAJOR = 2 */
413 395
414 keydatum.data = XSTRING_DATA (key); 396 keydatum.data = XSTRING_DATA (key);
415 keydatum.size = XSTRING_LENGTH (key); 397 keydatum.size = XSTRING_LENGTH (key);
416 398
431 413
432 return Qnil; 414 return Qnil;
433 } 415 }
434 416
435 static int 417 static int
436 berkdb_put (struct database *db, 418 berkdb_put (struct Lisp_Database *db,
437 Lisp_Object key, 419 Lisp_Object key,
438 Lisp_Object val, 420 Lisp_Object val,
439 Lisp_Object replace) 421 Lisp_Object replace)
440 { 422 {
441 DBT keydatum, valdatum; 423 DBT keydatum, valdatum;
442 int status = 0; 424 int status = 0;
443 425
444 #if DB_VERSION_MAJOR == 2 426 #if DB_VERSION_MAJOR == 2
445 /* Always initalize keydatum, valdatum. */ 427 /* Always initalize keydatum, valdatum. */
446 memset(&keydatum, 0, sizeof(keydatum)); 428 xzero (keydatum);
447 memset(&valdatum, 0, sizeof(valdatum)); 429 xzero (valdatum);
448 #endif /* DV_VERSION_MAJOR = 2 */ 430 #endif /* DV_VERSION_MAJOR = 2 */
449 431
450 keydatum.data = XSTRING_DATA (key); 432 keydatum.data = XSTRING_DATA (key);
451 keydatum.size = XSTRING_LENGTH (key); 433 keydatum.size = XSTRING_LENGTH (key);
452 valdatum.data = XSTRING_DATA (val); 434 valdatum.data = XSTRING_DATA (val);
463 445
464 return status; 446 return status;
465 } 447 }
466 448
467 static int 449 static int
468 berkdb_remove (struct database *db, Lisp_Object key) 450 berkdb_remove (struct Lisp_Database *db, Lisp_Object key)
469 { 451 {
470 DBT keydatum; 452 DBT keydatum;
471 int status; 453 int status;
472 454
473 #if DB_VERSION_MAJOR == 2 455 #if DB_VERSION_MAJOR == 2
474 /* Always initialize keydatum. */ 456 /* Always initialize keydatum. */
475 memset(&keydatum, 0, sizeof(keydatum)); 457 xzero (keydatum);
476 #endif /* DV_VERSION_MAJOR = 2 */ 458 #endif /* DV_VERSION_MAJOR = 2 */
477 459
478 keydatum.data = XSTRING_DATA (key); 460 keydatum.data = XSTRING_DATA (key);
479 keydatum.size = XSTRING_LENGTH (key); 461 keydatum.size = XSTRING_LENGTH (key);
480 462
495 477
496 return 1; 478 return 1;
497 } 479 }
498 480
499 static void 481 static void
500 berkdb_map (struct database *db, Lisp_Object func) 482 berkdb_map (struct Lisp_Database *db, Lisp_Object func)
501 { 483 {
502 DBT keydatum, valdatum; 484 DBT keydatum, valdatum;
503 Lisp_Object key, val; 485 Lisp_Object key, val;
504 DB *dbp = db->db_handle; 486 DB *dbp = db->db_handle;
505 int status; 487 int status;
515 call2 (func, key, val); 497 call2 (func, key, val);
516 } 498 }
517 #else 499 #else
518 DBC *dbcp; 500 DBC *dbcp;
519 /* Initialize the key/data pair so the flags aren't set. */ 501 /* Initialize the key/data pair so the flags aren't set. */
520 memset(&keydatum, 0, sizeof(keydatum)); 502 xzero (keydatum);
521 memset(&valdatum, 0, sizeof(valdatum)); 503 xzero (valdatum);
522 504
523 status = dbp->cursor (dbp, NULL, &dbcp); 505 status = dbp->cursor (dbp, NULL, &dbcp);
524 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST); 506 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST);
525 status == 0; 507 status == 0;
526 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT)) 508 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT))
533 dbcp->c_close (dbcp); 515 dbcp->c_close (dbcp);
534 #endif /* DB_VERSION_MAJOR */ 516 #endif /* DB_VERSION_MAJOR */
535 } 517 }
536 518
537 static void 519 static void
538 berkdb_close (struct database *db) 520 berkdb_close (struct Lisp_Database *db)
539 { 521 {
540 if (db->db_handle) 522 if (db->db_handle)
541 { 523 {
542 #if DB_VERSION_MAJOR == 1 524 #if DB_VERSION_MAJOR == 1
543 db->db_handle->sync (db->db_handle, 0); 525 db->db_handle->sync (db->db_handle, 0);
556 berkdb_type, 538 berkdb_type,
557 berkdb_get, 539 berkdb_get,
558 berkdb_put, 540 berkdb_put,
559 berkdb_remove, 541 berkdb_remove,
560 berkdb_map, 542 berkdb_map,
561 berkdb_lisp_type,
562 berkdb_close, 543 berkdb_close,
563 berkdb_lasterr 544 berkdb_lasterr
564 }; 545 };
565 #endif /* HAVE_BERKELEY_DB */ 546 #endif /* HAVE_BERKELEY_DB */
566 547
567 DEFUN ("database-last-error", Fdatabase_last_error, 0, 1, 0, /* 548 DEFUN ("database-last-error", Fdatabase_last_error, 0, 1, 0, /*
568 Return the last error associated with database OBJ. 549 Return the last error associated with DATABASE.
569 */ 550 */
570 (obj)) 551 (database))
571 { 552 {
572 if (NILP (obj)) 553 if (NILP (database))
573 return lisp_strerror (errno); 554 return lisp_strerror (errno);
574 555
575 CHECK_DATABASE (obj); 556 CHECK_DATABASE (database);
576 557
577 return XDATABASE (obj)->funcs->last_error (XDATABASE (obj)); 558 return XDATABASE (database)->funcs->last_error (XDATABASE (database));
578 } 559 }
579 560
580 DEFUN ("open-database", Fopen_database, 1, 5, 0, /* 561 DEFUN ("open-database", Fopen_database, 1, 5, 0, /*
581 Open database FILE, using database method TYPE and SUBTYPE, with 562 Return a new database object opened on FILE.
582 access rights ACCESS and permissions MODE. ACCESS can be any 563 Optional arguments TYPE and SUBTYPE specify the database type.
564 Optional argument ACCESS specifies the access rights, which may be any
583 combination of 'r' 'w' and '+', for read, write, and creation flags. 565 combination of 'r' 'w' and '+', for read, write, and creation flags.
566 Optional argument MODE gives the permissions to use when opening FILE,
567 and defaults to 0755.
584 */ 568 */
585 (file, type, subtype, access_, mode)) 569 (file, type, subtype, access_, mode))
586 { 570 {
587 /* This function can GC */ 571 /* This function can GC */
588 Lisp_Object retval = Qnil;
589 int modemask; 572 int modemask;
590 int accessmask = 0; 573 int accessmask = 0;
591 struct database *dbase = NULL; 574 struct Lisp_Database *db = NULL;
592 char *filename; 575 char *filename;
593 struct gcpro gcpro1, gcpro2; 576 struct gcpro gcpro1, gcpro2;
594 577
595 CHECK_STRING (file); 578 CHECK_STRING (file);
596 GCPRO2 (file, access_); 579 GCPRO2 (file, access_);
609 acc = (char *) XSTRING_DATA (access_); 592 acc = (char *) XSTRING_DATA (access_);
610 593
611 if (strchr (acc, '+')) 594 if (strchr (acc, '+'))
612 accessmask |= O_CREAT; 595 accessmask |= O_CREAT;
613 596
614 if (strchr (acc, 'r') && strchr (acc, 'w')) 597 {
615 accessmask |= O_RDWR; 598 char *rp = strchr (acc, 'r');
616 else if (strchr (acc, 'w')) 599 char *wp = strchr (acc, 'w');
617 accessmask |= O_WRONLY; 600 if (rp && wp) accessmask |= O_RDWR;
618 else 601 else if (wp) accessmask |= O_WRONLY;
619 accessmask |= O_RDONLY; 602 else accessmask |= O_RDONLY;
603 }
620 } 604 }
621 605
622 if (NILP (mode)) 606 if (NILP (mode))
623 { 607 {
624 modemask = 0755; /* rwxr-xr-x */ 608 modemask = 0755; /* rwxr-xr-x */
630 } 614 }
631 615
632 #ifdef HAVE_DBM 616 #ifdef HAVE_DBM
633 if (NILP (type) || EQ (type, Qdbm)) 617 if (NILP (type) || EQ (type, Qdbm))
634 { 618 {
635 DBM *dbm = dbm_open (filename, accessmask, modemask); 619 DBM *dbase = dbm_open (filename, accessmask, modemask);
636 if (!dbm) 620 if (!dbase)
637 return Qnil; 621 return Qnil;
638 622
639 dbase = allocate_database (); 623 db = allocate_database ();
640 dbase->dbm_handle = dbm; 624 db->dbm_handle = dbase;
641 dbase->type = DB_DBM; 625 db->type = DB_DBM;
642 dbase->funcs = &ndbm_func_block; 626 db->funcs = &ndbm_func_block;
643 goto db_done; 627 goto db_done;
644 } 628 }
645 #endif /* HAVE_DBM */ 629 #endif /* HAVE_DBM */
646 630
647 #ifdef HAVE_BERKELEY_DB 631 #ifdef HAVE_BERKELEY_DB
648 if (NILP (type) || EQ (type, Qberkeley_db)) 632 if (NILP (type) || EQ (type, Qberkeley_db))
649 { 633 {
650 DBTYPE real_subtype; 634 DBTYPE real_subtype;
651 DB *db; 635 DB *dbase;
652 #if DB_VERSION_MAJOR != 1 636 #if DB_VERSION_MAJOR != 1
653 int status; 637 int status;
654 #endif 638 #endif
655 639
656 if (EQ (subtype, Qhash) || NILP (subtype)) 640 if (EQ (subtype, Qhash) || NILP (subtype))
661 real_subtype = DB_RECNO; 645 real_subtype = DB_RECNO;
662 else 646 else
663 signal_simple_error ("Unsupported subtype", subtype); 647 signal_simple_error ("Unsupported subtype", subtype);
664 648
665 #if DB_VERSION_MAJOR == 1 649 #if DB_VERSION_MAJOR == 1
666 db = dbopen (filename, accessmask, modemask, real_subtype, NULL); 650 dbase = dbopen (filename, accessmask, modemask, real_subtype, NULL);
667 if (!db) 651 if (!dbase)
668 return Qnil; 652 return Qnil;
669 #else 653 #else
670 /* Berkeley DB Version 2 has only the accessmask DB_CREATE and DB_RDONLY, 654 /* Berkeley DB Version 2 has only the accessmask DB_CREATE and DB_RDONLY,
671 other flags shouldn't be set */ 655 other flags shouldn't be set */
672 if (NILP (access_)) 656 if (NILP (access_))
673 { 657 accessmask = DB_CREATE;
674 accessmask = DB_CREATE;
675 }
676 else 658 else
677 { 659 {
678 char *acc; 660 char *acc;
679 CHECK_STRING (access_); 661 CHECK_STRING (access_);
680 acc = (char *) XSTRING_DATA (access_); 662 acc = (char *) XSTRING_DATA (access_);
681 accessmask = 0; 663 accessmask = 0;
682 664
683 if (strchr (acc, '+')) 665 if (strchr (acc, '+'))
684 accessmask |= DB_CREATE; 666 accessmask |= DB_CREATE;
685 667
686 if (strchr (acc, 'r') && !strchr (acc, 'w')) 668 if (strchr (acc, 'r') && !strchr (acc, 'w'))
687 accessmask |= DB_RDONLY; 669 accessmask |= DB_RDONLY;
688 } 670 }
689 status = db_open (filename, real_subtype, accessmask, modemask, NULL , NULL, &db); 671 status = db_open (filename, real_subtype, accessmask,
672 modemask, NULL , NULL, &dbase);
690 if (status) 673 if (status)
691 return Qnil; 674 return Qnil;
692 #endif /* DB_VERSION_MAJOR */ 675 #endif /* DB_VERSION_MAJOR */
693 676
694 dbase = allocate_database (); 677 db = allocate_database ();
695 dbase->db_handle = db; 678 db->db_handle = dbase;
696 dbase->type = DB_BERKELEY; 679 db->type = DB_BERKELEY;
697 dbase->funcs = &berk_func_block; 680 db->funcs = &berk_func_block;
698 goto db_done; 681 goto db_done;
699 } 682 }
700 #endif /* HAVE_BERKELEY_DB */ 683 #endif /* HAVE_BERKELEY_DB */
701 684
702 signal_simple_error ("Unsupported database type", type); 685 signal_simple_error ("Unsupported database type", type);
703 return Qnil; 686 return Qnil;
704 687
705 db_done: 688 db_done:
706 dbase->live_p = 1; 689 db->live_p = 1;
707 dbase->fname = file; 690 db->fname = file;
708 dbase->mode = modemask; 691 db->mode = modemask;
709 dbase->access_ = accessmask; 692 db->access_ = accessmask;
710 XSETDATABASE (retval, dbase); 693
711 694 {
712 return retval; 695 Lisp_Object retval;
696 XSETDATABASE (retval, db);
697 return retval;
698 }
713 } 699 }
714 700
715 DEFUN ("put-database", Fput_database, 3, 4, 0, /* 701 DEFUN ("put-database", Fput_database, 3, 4, 0, /*
716 Store KEY and VAL in DATABASE. If optional fourth arg REPLACE is 702 Store KEY and VALUE in DATABASE.
717 non-nil, replace any existing entry in the database. 703 If optional fourth arg REPLACE is non-nil,
718 */ 704 replace any existing entry in the database.
719 (key, val, dbase, replace)) 705 */
720 { 706 (key, value, database, replace))
721 CHECK_LIVE_DATABASE (dbase); 707 {
708 CHECK_LIVE_DATABASE (database);
722 CHECK_STRING (key); 709 CHECK_STRING (key);
723 CHECK_STRING (val); 710 CHECK_STRING (value);
724
725 { 711 {
726 int status = 712 struct Lisp_Database *db = XDATABASE (database);
727 XDATABASE (dbase)->funcs->put (XDATABASE (dbase), key, val, replace); 713 int status = db->funcs->put (db, key, value, replace);
728 return status ? Qt : Qnil; 714 return status ? Qt : Qnil;
729 } 715 }
730 } 716 }
731 717
732 DEFUN ("remove-database", Fremove_database, 2, 2, 0, /* 718 DEFUN ("remove-database", Fremove_database, 2, 2, 0, /*
733 Remove KEY from DATABASE. 719 Remove KEY from DATABASE.
734 */ 720 */
735 (key, dbase)) 721 (key, database))
736 { 722 {
737 CHECK_LIVE_DATABASE (dbase); 723 CHECK_LIVE_DATABASE (database);
738 CHECK_STRING (key); 724 CHECK_STRING (key);
739 725 {
740 return XDATABASE (dbase)->funcs->rem (XDATABASE (dbase), key) ? Qt : Qnil; 726 struct Lisp_Database *db = XDATABASE (database);
727 int status = db->funcs->rem (db, key);
728 return status ? Qt : Qnil;
729 }
741 } 730 }
742 731
743 DEFUN ("get-database", Fget_database, 2, 3, 0, /* 732 DEFUN ("get-database", Fget_database, 2, 3, 0, /*
744 Find value for KEY in DATABASE. 733 Return value for KEY in DATABASE.
745 If there is no corresponding value, return DEFAULT (defaults to nil). 734 If there is no corresponding value, return DEFAULT (defaults to nil).
746 */ 735 */
747 (key, dbase, default_)) 736 (key, database, default_))
748 { 737 {
749 738 CHECK_LIVE_DATABASE (database);
750 CHECK_LIVE_DATABASE (dbase);
751 CHECK_STRING (key); 739 CHECK_STRING (key);
752
753 { 740 {
754 Lisp_Object retval = 741 struct Lisp_Database *db = XDATABASE (database);
755 XDATABASE (dbase)->funcs->get (XDATABASE (dbase), key); 742 Lisp_Object retval = db->funcs->get (db, key);
756 return NILP (retval) ? default_ : retval; 743 return NILP (retval) ? default_ : retval;
757 } 744 }
758 } 745 }
759 746
760 DEFUN ("map-database", Fmapdatabase, 2, 2, 0, /* 747 DEFUN ("map-database", Fmapdatabase, 2, 2, 0, /*
761 Map FUNCTION over entries in DATABASE, calling it with two args, 748 Map FUNCTION over entries in DATABASE, calling it with two args,
762 each key and value in the database. 749 each key and value in the database.
763 */ 750 */
764 (function, dbase)) 751 (function, database))
765 { 752 {
766 CHECK_LIVE_DATABASE (dbase); 753 CHECK_LIVE_DATABASE (database);
767 754
768 XDATABASE (dbase)->funcs->map (XDATABASE (dbase), function); 755 XDATABASE (database)->funcs->map (XDATABASE (database), function);
769 756
770 return Qnil; 757 return Qnil;
771 } 758 }
772 759
773 void 760 void
774 syms_of_dbm (void) 761 syms_of_database (void)
775 { 762 {
776 defsymbol (&Qdatabasep, "databasep"); 763 defsymbol (&Qdatabasep, "databasep");
777 #ifdef HAVE_DBM 764 #ifdef HAVE_DBM
778 defsymbol (&Qdbm, "dbm"); 765 defsymbol (&Qdbm, "dbm");
779 #endif 766 #endif
780 #ifdef HAVE_BERKELEY_DB 767 #ifdef HAVE_BERKELEY_DB
781 defsymbol (&Qberkeley_db, "berkeley-db"); 768 defsymbol (&Qberkeley_db, "berkeley-db");
782 defsymbol (&Qhash, "hash"); 769 defsymbol (&Qhash, "hash");
783 defsymbol (&Qbtree, "btree"); 770 defsymbol (&Qbtree, "btree");
784 defsymbol (&Qrecno, "recno"); 771 defsymbol (&Qrecno, "recno");
772 defsymbol (&Qunknown, "unknown");
785 #endif 773 #endif
786 774
787 DEFSUBR (Fopen_database); 775 DEFSUBR (Fopen_database);
788 DEFSUBR (Fdatabasep); 776 DEFSUBR (Fdatabasep);
789 DEFSUBR (Fmapdatabase); 777 DEFSUBR (Fmapdatabase);
797 DEFSUBR (Fdatabase_file_name); 785 DEFSUBR (Fdatabase_file_name);
798 DEFSUBR (Fclose_database); 786 DEFSUBR (Fclose_database);
799 } 787 }
800 788
801 void 789 void
802 vars_of_dbm (void) 790 vars_of_database (void)
803 { 791 {
804 #ifdef HAVE_DBM 792 #ifdef HAVE_DBM
805 Fprovide (Qdbm); 793 Fprovide (Qdbm);
806 #endif 794 #endif
807 #ifdef HAVE_BERKELEY_DB 795 #ifdef HAVE_BERKELEY_DB