comparison src/database.c @ 428:3ecd8885ac67 r21-2-22

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