source: git/Singular/ndbm.cc @ 9bffb9c

spielwiese
Last change on this file since 9bffb9c was 9bffb9c, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: SOLARIS/gcc 2.95.2 changes git-svn-id: file:///usr/local/Singular/svn/trunk@4752 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.4 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4
5//**************************************************************************/
6//
7// $Id: ndbm.cc,v 1.13 2000-11-21 15:35:45 Singular Exp $
8//
9//**************************************************************************/
10// 'ndbm.cc' containes all low-level functions to manipulate dbm-files
11// for the original Copyright of this file and 'ndbm.h' see below .
12//
13// some minor change where needed to compile and run under MacOS/MPW
14//
15//**************************************************************************/
16
17#include <strings.h>
18#include "mod2.h"
19#ifdef HAVE_DBM
20/*
21 * Copyright (c) 1983 Regents of the University of California.
22 * All rights reserved.  The Berkeley software License Agreement
23 * specifies the terms and conditions for redistribution.
24 */
25
26#if defined(LIBC_SCCS) && !defined(lint)
27static char sccsid[] = "@(#)ndbm.c        5.3 (Berkeley) 3/9/86";
28#endif LIBC_SCCS and not lint
29
30//**************************************************************************/
31
32#include <stdio.h>
33#ifdef __MWERKS__
34#   define bcopy(a,b,c) memmove(b,a,c)
35#   define EPERM 1
36#   define ENOMEM 23
37#   define ENOSPC 28
38#   define L_SET SEEK_SET
39#ifdef macintosh
40#   include <stdlib.h>
41#   include <errno.h>
42#   include "fcntl.h"
43#   include <string.h>
44#   include <stat.h>
45//#   include <stat.h>
46#else
47#   include <unix.h>
48#   include <ThreadLocalData.h>
49#endif
50#else
51#   include <sys/types.h>
52#   include <sys/stat.h>
53#   include <sys/file.h>
54#   include <errno.h>
55#   include <stdlib.h>
56#   include <string.h>
57#   include <unistd.h>
58#   include <fcntl.h>
59#endif
60#ifndef HAVE_BCOPY
61#   define bcopy(a,b,c) memmove(b,a,c)
62#endif /* not HAVE_BCOPY */
63#include "ndbm.h"
64
65#define BYTESIZ 8
66#undef setbit
67
68static  void dbm_access(register DBM *db, long hash);
69static  int getbit(register DBM *db);
70static  void setbit(register DBM *db);
71static  datum makdatum(char buf[PBLKSIZ], int n);
72static  int finddatum(char buf[PBLKSIZ], datum item);
73static  long hashinc(register DBM *db, long hash);
74static  long dcalchash(datum item);
75static  int delitem(char buf[PBLKSIZ], int n);
76static  int additem(char buf[PBLKSIZ], datum item, datum item1);
77#if defined(__MWERKS__) && ! defined(macintosh)
78#define errno (_GetThreadLocalData()->errno)
79#else
80extern  int errno;
81#endif
82
83DBM *
84dbm_open(char *file, int flags, int mode)
85{
86  struct stat statb;
87  register DBM *db;
88
89  if ((db = (DBM *)malloc(sizeof *db)) == 0) {
90    errno = ENOMEM;
91    return ((DBM *)0);
92  }
93#ifdef macintosh
94  // It seems that the compile has some problems to commit the flags properly
95  // O_RDWR | O_CREAT = 0x102 change to 0x200. We don't know why.
96  // setting flags to O_RDWR | O_CREAT solved our problem. :-(
97  flags = O_RDWR | O_CREAT;
98#endif /* macintosh */
99#ifdef MSDOS
100  // default mode of open is ascii, we need binary mode.
101  flags |= O_BINARY;
102#endif
103  db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;
104  if ((flags & 03) == O_WRONLY)
105    flags = (flags & ~03) | O_RDWR;
106  strcpy(db->dbm_pagbuf, file);
107  strcat(db->dbm_pagbuf, ".pag");
108#ifdef __MWERKS__
109  db->dbm_pagf = open(db->dbm_pagbuf, flags);
110#else /* not __MWERKS__ */
111  db->dbm_pagf = open(db->dbm_pagbuf, flags, mode);
112#endif /* __MWERKS__ */
113  if (db->dbm_pagf < 0)
114    goto bad;
115  strcpy(db->dbm_pagbuf, file);
116  strcat(db->dbm_pagbuf, ".dir");
117#ifdef __MWERKS__
118  db->dbm_dirf = open(db->dbm_pagbuf, flags);
119#else /* not __MWERKS__ */
120  db->dbm_dirf = open(db->dbm_pagbuf, flags, mode);
121#endif /* __MWERKS__ */
122  if (db->dbm_dirf < 0)
123    goto bad1;
124  fstat(db->dbm_dirf, &statb);
125  db->dbm_maxbno = statb.st_size*BYTESIZ-1;
126  db->dbm_pagbno = db->dbm_dirbno = -1;
127  return (db);
128bad1:
129  (void) close(db->dbm_pagf);
130bad:
131  free((char *)db);
132  return ((DBM *)0);
133}
134
135void
136dbm_close(DBM *db)
137{
138  (void) close(db->dbm_dirf);
139  (void) close(db->dbm_pagf);
140  free((char *)db);
141}
142
143long
144dbm_forder(register DBM *db, datum key)
145{
146  long hash;
147
148  hash = dcalchash(key);
149  for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
150    db->dbm_blkno = hash & db->dbm_hmask;
151    db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
152    if (getbit(db) == 0)
153      break;
154  }
155  return (db->dbm_blkno);
156}
157
158datum
159dbm_fetch(register DBM *db, datum key)
160{
161  register int i;
162  datum item;
163
164  if (dbm_error(db))
165    goto err;
166  dbm_access(db, dcalchash(key));
167  if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
168    item = makdatum(db->dbm_pagbuf, i+1);
169    if (item.dptr != NULL)
170      return (item);
171  }
172err:
173  item.dptr = NULL;
174  item.dsize = 0;
175  return (item);
176}
177
178int dbm_delete(register DBM *db, datum key)
179{
180  register int i;
181  datum item;
182
183  if (dbm_error(db))
184    return (-1);
185  if (dbm_rdonly(db)) {
186    errno = EPERM;
187    return (-1);
188  }
189  dbm_access(db, dcalchash(key));
190  if ((i = finddatum(db->dbm_pagbuf, key)) < 0)
191    return (-1);
192  if (!delitem(db->dbm_pagbuf, i))
193    goto err;
194  db->dbm_pagbno = db->dbm_blkno;
195  (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
196  if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
197  err:
198    db->dbm_flags |= _DBM_IOERR;
199    return (-1);
200  }
201  return (0);
202}
203
204int dbm_store(register DBM *db, datum key, datum dat, int replace)
205{
206  register int i;
207  int ret;
208  datum item, item1;
209  char ovfbuf[PBLKSIZ];
210
211  if (dbm_error(db))
212    return (-1);
213  if (dbm_rdonly(db)) {
214    errno = EPERM;
215    return (-1);
216  }
217loop:
218  dbm_access(db, dcalchash(key));
219  if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
220    if (!replace)
221      return (1);
222    if (!delitem(db->dbm_pagbuf, i)) {
223      db->dbm_flags |= _DBM_IOERR;
224      return (-1);
225    }
226  }
227  if (!additem(db->dbm_pagbuf, key, dat))
228    goto split;
229  db->dbm_pagbno = db->dbm_blkno;
230  (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
231  if ( (ret=write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ)) != PBLKSIZ) {
232    db->dbm_flags |= _DBM_IOERR;
233    return (-1);
234  }
235  return (0);
236
237split:
238  if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) {
239    db->dbm_flags |= _DBM_IOERR;
240    errno = ENOSPC;
241    return (-1);
242  }
243  memset(ovfbuf, 0, PBLKSIZ);
244  for (i=0;;) {
245    item = makdatum(db->dbm_pagbuf, i);
246    if (item.dptr == NULL)
247      break;
248    if (dcalchash(item) & (db->dbm_hmask+1)) {
249      item1 = makdatum(db->dbm_pagbuf, i+1);
250      if (item1.dptr == NULL) {
251        fprintf(stderr, "ndbm: split not paired\n");
252        db->dbm_flags |= _DBM_IOERR;
253        break;
254      }
255      if (!additem(ovfbuf, item, item1) ||
256          !delitem(db->dbm_pagbuf, i)) {
257        db->dbm_flags |= _DBM_IOERR;
258        return (-1);
259      }
260      continue;
261    }
262    i += 2;
263  }
264  db->dbm_pagbno = db->dbm_blkno;
265  (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
266  if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
267    db->dbm_flags |= _DBM_IOERR;
268    return (-1);
269  }
270  (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, L_SET);
271  if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) {
272    db->dbm_flags |= _DBM_IOERR;
273    return (-1);
274  }
275  setbit(db);
276  goto loop;
277}
278
279datum
280dbm_firstkey(DBM *db)
281{
282
283  db->dbm_blkptr = 0L;
284  db->dbm_keyptr = 0;
285  return (dbm_nextkey(db));
286}
287
288datum
289dbm_nextkey(register DBM *db)
290{
291  struct stat statb;
292  datum item;
293
294  if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0)
295                goto err;
296  statb.st_size /= PBLKSIZ;
297  for (;;) {
298    if (db->dbm_blkptr != db->dbm_pagbno) {
299      db->dbm_pagbno = db->dbm_blkptr;
300      (void) lseek(db->dbm_pagf, db->dbm_blkptr*PBLKSIZ, L_SET);
301      if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
302        memset(db->dbm_pagbuf, 0, PBLKSIZ);
303#ifdef DEBUG
304      else if (chkblk(db->dbm_pagbuf) < 0)
305        db->dbm_flags |= _DBM_IOERR;
306#endif
307    }
308    if (((short *)db->dbm_pagbuf)[0] != 0) {
309      item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);
310      if (item.dptr != NULL) {
311        db->dbm_keyptr += 2;
312        return (item);
313      }
314      db->dbm_keyptr = 0;
315    }
316    if (++db->dbm_blkptr >= statb.st_size)
317      break;
318  }
319err:
320  item.dptr = NULL;
321  item.dsize = 0;
322  return (item);
323}
324
325static void
326dbm_access(register DBM *db, long hash)
327{
328  for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
329    db->dbm_blkno = hash & db->dbm_hmask;
330    db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
331    if (getbit(db) == 0)
332      break;
333  }
334  if (db->dbm_blkno != db->dbm_pagbno) {
335    db->dbm_pagbno = db->dbm_blkno;
336    (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
337    if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
338      memset(db->dbm_pagbuf, 0, PBLKSIZ);
339#ifdef DEBUG
340    else if (chkblk(db->dbm_pagbuf) < 0)
341      db->dbm_flags |= _DBM_IOERR;
342#endif
343  }
344}
345
346static
347int getbit(register DBM *db)
348{
349  long bn;
350  register int b, i, n;
351
352
353  if (db->dbm_bitno > db->dbm_maxbno)
354    return (0);
355  n = db->dbm_bitno % BYTESIZ;
356  bn = db->dbm_bitno / BYTESIZ;
357  i = bn % DBLKSIZ;
358  b = bn / DBLKSIZ;
359  if (b != db->dbm_dirbno) {
360    db->dbm_dirbno = b;
361    (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
362    if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
363      memset(db->dbm_dirbuf, 0, DBLKSIZ);
364  }
365  return (db->dbm_dirbuf[i] & (1<<n));
366}
367
368static void
369setbit(register DBM *db)
370{
371  long bn;
372  register int i, n, b;
373
374  if (db->dbm_bitno > db->dbm_maxbno)
375    db->dbm_maxbno = db->dbm_bitno;
376  n = db->dbm_bitno % BYTESIZ;
377  bn = db->dbm_bitno / BYTESIZ;
378  i = bn % DBLKSIZ;
379  b = bn / DBLKSIZ;
380  if (b != db->dbm_dirbno) {
381    db->dbm_dirbno = b;
382    (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
383    if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
384      memset(db->dbm_dirbuf, 0, DBLKSIZ);
385  }
386  db->dbm_dirbuf[i] |= 1<<n;
387  db->dbm_dirbno = b;
388  (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
389  if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
390    db->dbm_flags |= _DBM_IOERR;
391}
392
393static datum
394makdatum(char buf[PBLKSIZ], int n)
395{
396  register short *sp;
397  register int t;
398  datum item;
399
400  sp = (short *)buf;
401  if ((unsigned)n >= (unsigned)sp[0])
402  {
403    item.dptr = NULL;
404    item.dsize = 0;
405    return (item);
406  }
407  t = PBLKSIZ;
408  if (n > 0)
409    t = sp[n];
410  item.dptr = buf+sp[n+1];
411  item.dsize = t - sp[n+1];
412  return (item);
413}
414
415static
416int finddatum(char buf[PBLKSIZ], datum item)
417{
418  register short *sp;
419  register int i, n, j;
420
421  sp = (short *)buf;
422  n = PBLKSIZ;
423  for (i=0, j=sp[0]; i<j; i+=2, n = sp[i]) {
424    n -= sp[i+1];
425    if (n != item.dsize)
426      continue;
427    if (n == 0 || memcmp(&buf[sp[i+1]], item.dptr, n) == 0)
428      return (i);
429  }
430  return (-1);
431}
432
433static  int hitab[16]
434/* ken's
435{
436        055,043,036,054,063,014,004,005,
437        010,064,077,000,035,027,025,071,
438};
439*/
440 = {    61, 57, 53, 49, 45, 41, 37, 33,
441        29, 25, 21, 17, 13,  9,  5,  1,
442};
443static  long hltab[64]
444 = {
445        06100151277L,06106161736L,06452611562L,05001724107L,
446        02614772546L,04120731531L,04665262210L,07347467531L,
447        06735253126L,06042345173L,03072226605L,01464164730L,
448        03247435524L,07652510057L,01546775256L,05714532133L,
449        06173260402L,07517101630L,02431460343L,01743245566L,
450        00261675137L,02433103631L,03421772437L,04447707466L,
451        04435620103L,03757017115L,03641531772L,06767633246L,
452        02673230344L,00260612216L,04133454451L,00615531516L,
453        06137717526L,02574116560L,02304023373L,07061702261L,
454        05153031405L,05322056705L,07401116734L,06552375715L,
455        06165233473L,05311063631L,01212221723L,01052267235L,
456        06000615237L,01075222665L,06330216006L,04402355630L,
457        01451177262L,02000133436L,06025467062L,07121076461L,
458        03123433522L,01010635225L,01716177066L,05161746527L,
459        01736635071L,06243505026L,03637211610L,01756474365L,
460        04723077174L,03642763134L,05750130273L,03655541561L,
461};
462
463static long
464hashinc(register DBM *db, long hash)
465{
466  long bit;
467
468  hash &= db->dbm_hmask;
469  bit = db->dbm_hmask+1;
470  for (;;) {
471    bit >>= 1;
472    if (bit == 0)
473      return (0L);
474    if ((hash & bit) == 0)
475      return (hash | bit);
476    hash &= ~bit;
477  }
478}
479
480static long
481dcalchash(datum item)
482{
483  register int s, c, j;
484  register char *cp;
485  register long hashl;
486  register int hashi;
487
488  hashl = 0;
489  hashi = 0;
490  for (cp = item.dptr, s=item.dsize; --s >= 0; ) {
491    c = *cp++;
492    for (j=0; j<BYTESIZ; j+=4) {
493      hashi += hitab[c&017];
494      hashl += hltab[hashi&63];
495      c >>= 4;
496    }
497  }
498  return (hashl);
499}
500
501/*
502 * Delete pairs of items (n & n+1).
503 */
504static
505int delitem(char buf[PBLKSIZ], int n)
506{
507  register short *sp, *sp1;
508  register int i1, i2;
509
510  sp = (short *)buf;
511  i2 = sp[0];
512  if ((unsigned)n >= (unsigned)i2 || (n & 1))
513    return (0);
514  if (n == i2-2)
515  {
516    sp[0] -= 2;
517    return (1);
518  }
519  i1 = PBLKSIZ;
520  if (n > 0)
521    i1 = sp[n];
522  i1 -= sp[n+2];
523  if (i1 > 0) {
524    i2 = sp[i2];
525    bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2);
526  }
527  sp[0] -= 2;
528  for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++)
529    sp[0] = sp[2] + i1;
530  return (1);
531}
532
533/*
534 * Add pairs of items (item & item1).
535 */
536static
537int additem(char buf[PBLKSIZ], datum item, datum item1)
538{
539  register short *sp;
540  register int i1, i2, tmp;
541
542  sp = (short *)buf;
543  i1 = PBLKSIZ;
544  i2 = sp[0];
545  if (i2 > 0)
546    i1 = sp[i2];
547  i1 -= item.dsize + item1.dsize;
548  tmp = (i2+3) * sizeof(short);
549  if (i1 <= tmp) return (0);
550  sp[0] += 2;
551  sp[++i2] = i1 + item1.dsize;
552  bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize);
553  sp[++i2] = i1;
554  bcopy(item1.dptr, &buf[i1], item1.dsize);
555  return (1);
556}
557
558#ifdef DEBUG
559static
560chkblk(char buf[PBLKSIZ])
561{
562  register short *sp;
563  register t, i;
564
565  sp = (short *)buf;
566  t = PBLKSIZ;
567  for (i=0; i<sp[0]; i++) {
568    if (sp[i+1] > t)
569      return (-1);
570    t = sp[i+1];
571  }
572  if (t < (sp[0]+1)*sizeof(short))
573    return (-1);
574  return (0);
575}
576#endif
577
578#endif /* HAVE_DBM */
Note: See TracBrowser for help on using the repository browser.