/* This file is part of the Q programming system. The Q programming system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The Q programming system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if defined (HAVE_CONFIG_H) # include "config.h" #endif /* system headers */ #include #include /* check for standard C headers */ #if STDC_HEADERS # include # include #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef WIN32 #define __GDBM_IMPORT__ 1 #endif #include #include #ifdef DMALLOC #include #endif MODULE(gdbm) #ifndef HAVE_STRDUP static char *strdup(char *s) { char *t; return ((t=malloc(strlen(s)+1))?strcpy(t, s):NULL); } #endif /* ByteStr data structure, see clib.c */ typedef struct bstr { long size; unsigned char *v; } bstr_t; FUNCTION(gdbm,gdbm_vars,argc,argv) { if (argc != 0) return __FAIL; return mktuplel (9, mkint(GDBM_READER), mkint(GDBM_WRITER), mkint(GDBM_WRCREAT), mkint(GDBM_NEWDB), mkint(GDBM_FAST), mkint(GDBM_SYNC), mkint(GDBM_NOLOCK), mkint(GDBM_INSERT), mkint(GDBM_REPLACE)); } DESTRUCTOR(gdbm,GdbmFile,ptr) { GDBM_FILE *dbf = (GDBM_FILE*)ptr; if (*dbf) gdbm_close(*dbf); free(dbf); } FUNCTION(gdbm,gdbm_version,argc,argv) { if (argc == 0) return mkstr(strdup(gdbm_version)); else return __FAIL; } FUNCTION(gdbm,gdbm_errno,argc,argv) { if (argc == 0) return mkint(gdbm_errno); else return __FAIL; } FUNCTION(gdbm,gdbm_seterrno,argc,argv) { long n; if (argc == 1 && isint(argv[0], &n)) { gdbm_errno = (int)n; return mkvoid; } else return __FAIL; } FUNCTION(gdbm,gdbm_strerror,argc,argv) { long n; char *s; if (argc == 1 && isint(argv[0], &n) && (s = gdbm_strerror((int)n))) return mkstr(strdup(s)); else return __FAIL; } FUNCTION(gdbm,gdbm_open,argc,argv) { char *name; long block_size, flags, mode; if (argc == 4 && isstr(argv[0], &name) && isint(argv[1], &block_size) && isint(argv[2], &flags) && isint(argv[3], &mode)) { GDBM_FILE *dbf; if (!(dbf = malloc(sizeof(GDBM_FILE)))) return __ERROR; else if ((*dbf = gdbm_open(name, (int)block_size, (int)flags, (int)mode, NULL))) return mkobj(type(GdbmFile), dbf); else { free(dbf); return __FAIL; } } else return __FAIL; } FUNCTION(gdbm,gdbm_close,argc,argv) { GDBM_FILE *dbf; if (argc == 1 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf) { gdbm_close(*dbf); *dbf = NULL; return mkvoid; } else return __FAIL; } FUNCTION(gdbm,gdbm_fdesc,argc,argv) { GDBM_FILE *dbf; if (argc == 1 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf) return mkint(gdbm_fdesc(*dbf)); else return __FAIL; } static char dummy_data[1]; #define gdbm_data(v) ((v)?((char*)v):dummy_data) FUNCTION(gdbm,gdbm_store,argc,argv) { GDBM_FILE *dbf; bstr_t *mk, *md; long flag; if (argc == 4 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && isobj(argv[1], type(ByteStr), (void**)&mk) && isobj(argv[2], type(ByteStr), (void**)&md) && isint(argv[3], &flag)) { datum key, data; key.dsize = (int)mk->size; key.dptr = gdbm_data(mk->v); data.dsize = (int)md->size; data.dptr = gdbm_data(md->v); if (!gdbm_store(*dbf, key, data, (int)flag)) return mkvoid; else return __FAIL; } else return __FAIL; } FUNCTION(gdbm,gdbm_delete,argc,argv) { GDBM_FILE *dbf; bstr_t *m; if (argc == 2 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && isobj(argv[1], type(ByteStr), (void**)&m)) { datum key; key.dsize = (int)m->size; key.dptr = gdbm_data(m->v); if (!gdbm_delete(*dbf, key)) return mkvoid; else return __FAIL; } else return __FAIL; } FUNCTION(gdbm,gdbm_fetch,argc,argv) { GDBM_FILE *dbf; bstr_t *m; if (argc == 2 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && isobj(argv[1], type(ByteStr), (void**)&m)) { datum key, data; key.dsize = (int)m->size; key.dptr = gdbm_data(m->v); data = gdbm_fetch(*dbf, key); if (data.dptr) { if (!(m = malloc(sizeof(bstr_t)))) { free(data.dptr); return __ERROR; } m->size = (long)data.dsize; if (data.dsize > 0) m->v = (unsigned char*)data.dptr; else { free(data.dptr); m->v = NULL; } return mkobj(type(ByteStr), m); } else return __FAIL; } else return __FAIL; } FUNCTION(gdbm,gdbm_exists,argc,argv) { GDBM_FILE *dbf; bstr_t *m; if (argc == 2 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && isobj(argv[1], type(ByteStr), (void**)&m)) { datum key; key.dsize = (int)m->size; key.dptr = gdbm_data(m->v); if (gdbm_exists(*dbf, key)) return mktrue; else return mkfalse; } else return __FAIL; } FUNCTION(gdbm,gdbm_firstkey,argc,argv) { GDBM_FILE *dbf; bstr_t *m; if (argc == 1 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf) { datum key; key = gdbm_firstkey(*dbf); if (key.dptr) { if (!(m = malloc(sizeof(bstr_t)))) { free(key.dptr); return __ERROR; } m->size = (long)key.dsize; if (key.dsize > 0) m->v = (unsigned char*)key.dptr; else { free(key.dptr); m->v = NULL; } return mkobj(type(ByteStr), m); } else return __FAIL; } else return __FAIL; } FUNCTION(gdbm,gdbm_nextkey,argc,argv) { GDBM_FILE *dbf; bstr_t *m; if (argc == 2 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && isobj(argv[1], type(ByteStr), (void**)&m)) { datum key; key.dsize = (int)m->size; key.dptr = gdbm_data(m->v); key = gdbm_nextkey(*dbf, key); if (key.dptr) { if (!(m = malloc(sizeof(bstr_t)))) { free(key.dptr); return __ERROR; } m->size = (long)key.dsize; if (key.dsize > 0) m->v = (unsigned char*)key.dptr; else { free(key.dptr); m->v = NULL; } return mkobj(type(ByteStr), m); } else return __FAIL; } else return __FAIL; } FUNCTION(gdbm,gdbm_sync,argc,argv) { GDBM_FILE *dbf; if (argc == 1 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf) { gdbm_sync(*dbf); return mkvoid; } else return __FAIL; } FUNCTION(gdbm,gdbm_reorganize,argc,argv) { GDBM_FILE *dbf; if (argc == 1 && isobj(argv[0], type(GdbmFile), (void**)&dbf) && *dbf && !gdbm_reorganize(*dbf)) return mkvoid; else return __FAIL; }