home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / ddb / part01 < prev    next >
Encoding:
Text File  |  1993-11-02  |  48.9 KB  |  2,265 lines

  1. Newsgroups: comp.sources.misc
  2. From: pefv700@hermes.chpc.utexas.edu (Christopher Phillips)
  3. Subject: v40i082:  ddb - dynamic memory database library, Part01/01
  4. Message-ID: <1993Nov2.233314.7646@sparky.sterling.com>
  5. X-Md4-Signature: 28e0a59e351dba847e67961601e2229b
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Reply-To: pefv700@utpe.pe.utexas.edu
  8. Organization: Sterling Software
  9. Date: Tue, 2 Nov 1993 23:33:14 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: pefv700@hermes.chpc.utexas.edu (Christopher Phillips)
  13. Posting-number: Volume 40, Issue 82
  14. Archive-name: ddb/part01
  15. Environment: ANSI-C
  16.  
  17. ddb is a library of database routines that are kept in dynamic memory
  18. and are designed to be simple to use and flexible.  Its functions are
  19. loosely modeled after normal UNIX I/O functions.  Currently, there is
  20. support for binary trees, bit vectors, hash tables, linked lists,
  21. queues, and stacks.
  22.  
  23. Chris
  24. ---
  25. #! /bin/sh
  26. # This is a shell archive.  Remove anything before this line, then unpack
  27. # it by saving it into a file and typing "sh file".  To overwrite existing
  28. # files, type "sh file -c".  You can also feed this as standard input via
  29. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  30. # will see the following message at the end:
  31. #        "End of shell archive."
  32. # Contents:  ddb ddb/Makefile ddb/README ddb/binary.c ddb/bit.c
  33. #   ddb/ddb.3 ddb/ddb.h ddb/hash.c ddb/list.c ddb/new.c
  34. #   ddb/patchlevel.h ddb/queue.c ddb/stack.c
  35. # Wrapped by pefv700@hermes on Mon Nov  1 23:59:58 1993
  36. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  37. if test ! -d 'ddb' ; then
  38.     echo shar: Creating directory \"'ddb'\"
  39.     mkdir 'ddb'
  40. fi
  41. if test -f 'ddb/Makefile' -a "${1}" != "-c" ; then 
  42.   echo shar: Will not clobber existing file \"'ddb/Makefile'\"
  43. else
  44. echo shar: Extracting \"'ddb/Makefile'\" \(232 characters\)
  45. sed "s/^X//" >'ddb/Makefile' <<'END_OF_FILE'
  46. XOPT=-O
  47. XCFLAGS=$(OPT) -I.
  48. XCDBS=hash.c list.c queue.c stack.c binary.c bit.c
  49. XCSRCS=new.c $(CDBS)
  50. XCOBJS=$(CSRCS:.c=.o)
  51. X
  52. Xlibddb.a: $(COBJS)
  53. X    -rm -f $@
  54. X    ar rv $@ $(COBJS)
  55. X    ranlib $@
  56. X
  57. Xclean:
  58. X    rm -f $(COBJS) libddb.a
  59. X
  60. X$(CDBS:.c=.o): ddb.h
  61. END_OF_FILE
  62. if test 232 -ne `wc -c <'ddb/Makefile'`; then
  63.     echo shar: \"'ddb/Makefile'\" unpacked with wrong size!
  64. fi
  65. # end of 'ddb/Makefile'
  66. fi
  67. if test -f 'ddb/README' -a "${1}" != "-c" ; then 
  68.   echo shar: Will not clobber existing file \"'ddb/README'\"
  69. else
  70. echo shar: Extracting \"'ddb/README'\" \(661 characters\)
  71. sed "s/^X//" >'ddb/README' <<'END_OF_FILE'
  72. XDDB - dynamic memory database routines
  73. X
  74. Xddb is a library of database routines that are kept in dynamic memory
  75. Xand are designed to be simple to use and flexible.  Its functions are
  76. Xloosely modeled after normal UNIX I/O functions.  Currently, there is
  77. Xsupport for binary trees, bit vectors, hash tables, linked lists,
  78. Xqueues, and stacks.
  79. X
  80. XTo make the library, just use make.  You may want to use whatever flags
  81. Xyour compiler wants for ANSI C source (or your favorite translator to
  82. XK&R C if you are so disadvantaged).  Then place libddb.a, ddb.h, and
  83. Xddb.3 in appropriate places.
  84. X
  85. X
  86. XChris
  87. X
  88. X-----------------------
  89. XChristopher G. Phillips
  90. Xpefv700@utpe.pe.utexas.edu
  91. END_OF_FILE
  92. if test 661 -ne `wc -c <'ddb/README'`; then
  93.     echo shar: \"'ddb/README'\" unpacked with wrong size!
  94. fi
  95. # end of 'ddb/README'
  96. fi
  97. if test -f 'ddb/binary.c' -a "${1}" != "-c" ; then 
  98.   echo shar: Will not clobber existing file \"'ddb/binary.c'\"
  99. else
  100. echo shar: Extracting \"'ddb/binary.c'\" \(8251 characters\)
  101. sed "s/^X//" >'ddb/binary.c' <<'END_OF_FILE'
  102. X/*
  103. X *                 Author:  Christopher G. Phillips
  104. X *              Copyright (C) 1993 All Rights Reserved
  105. X *
  106. X *                              NOTICE
  107. X *
  108. X * Permission to use, copy, modify, and distribute this software and
  109. X * its documentation for any purpose and without fee is hereby granted
  110. X * provided that the above copyright notice appear in all copies and
  111. X * that both the copyright notice and this permission notice appear in
  112. X * supporting documentation.
  113. X *
  114. X * The author makes no representations about the suitability of this
  115. X * software for any purpose.  This software is provided ``as is''
  116. X * without express or implied warranty.
  117. X */
  118. X
  119. X#define SEQUENTIAL
  120. X
  121. X#include <stdio.h>
  122. X#include <stdlib.h>
  123. X#include <string.h>
  124. X#include <sys/types.h>
  125. X#include <ddb.h>
  126. X
  127. X#define MIN(a,b)    ((a) < (b) ? (a) : (b))
  128. X
  129. Xtypedef struct bent {
  130. X    DATUM        key;
  131. X    DATUM        data;
  132. X    struct bent    *left;
  133. X    struct bent    *right;
  134. X#ifdef SEQUENTIAL
  135. X    struct bent    *parent;
  136. X#endif
  137. X} BELEM;
  138. Xtypedef struct {
  139. X    int    used;
  140. X    BELEM    *root;
  141. X#ifdef SEQUENTIAL
  142. X    BELEM    *lastkey;
  143. X    int    startover;
  144. X#endif
  145. X} BINARY;
  146. X
  147. Xstatic BINARY    *binary = NULL;
  148. Xstatic int    maxbinaries = 0;
  149. X
  150. Xextern void    *ddb_new(const DATUM *, const DATUM *, size_t);
  151. X
  152. Xint
  153. Xddb_memcmp(const DATUM *dp1, const DATUM *dp2)
  154. X{
  155. X    int    c;
  156. X
  157. X    if ((c = memcmp(dp1->addr, dp2->addr, MIN(dp1->size, dp2->size))) == 0)
  158. X        if (dp1->size < dp2->size)
  159. X            return -1;
  160. X        else if (dp1->size > dp2->size)
  161. X            return 1;
  162. X        
  163. X    return c;
  164. X}
  165. X
  166. Xstatic int
  167. Xvalidbd(int bd)
  168. X{
  169. X    return binary && bd < maxbinaries && binary[bd].used;
  170. X}
  171. X
  172. Xstatic int
  173. Xvalidmode(int mode)
  174. X{
  175. X    switch (mode & DDB_MODE_MASK) {
  176. X    case DDB_INSERT:
  177. X    case DDB_REPLACE:
  178. X    case DDB_DUPLICATE:
  179. X        return 1;
  180. X    default:
  181. X        return 0;
  182. X    }
  183. X}
  184. X
  185. Xstatic BELEM *
  186. X#ifdef SEQUENTIAL
  187. Xfind(int bd, const DATUM *key, ddb_cmp_t cmp, BELEM ***prevp, BELEM **parent)
  188. X#else
  189. Xfind(int bd, const DATUM *key, ddb_cmp_t cmp, BELEM ***prevp)
  190. X#endif
  191. X{
  192. X    int    c;
  193. X    BELEM    *bp;
  194. X
  195. X    bp = binary[bd].root;
  196. X    if (prevp) {
  197. X        *prevp = &binary[bd].root;
  198. X#ifdef SEQUENTIAL
  199. X        *parent = NULL;
  200. X#endif
  201. X    }
  202. X
  203. X    while (bp) {
  204. X        if ((c = (*cmp)(key, &bp->key)) == 0)
  205. X            return bp;
  206. X        else if (c < 0) {
  207. X            if (prevp) {
  208. X                *prevp = &bp->left;
  209. X#ifdef SEQUENTIAL
  210. X                *parent = bp;
  211. X#endif
  212. X            }
  213. X            bp = bp->left;
  214. X        } else {
  215. X            if (prevp) {
  216. X                *prevp = &bp->right;
  217. X#ifdef SEQUENTIAL
  218. X                *parent = bp;
  219. X#endif
  220. X            }
  221. X            bp = bp->right;
  222. X        }
  223. X    }
  224. X
  225. X    return NULL;
  226. X}
  227. X
  228. Xstatic void
  229. Xbfree(BELEM *bp)
  230. X{
  231. X    BELEM    *right;
  232. X
  233. X    if (bp) {
  234. X        bfree(bp->left);
  235. X        right = bp->right;
  236. X        free(bp->key.addr);
  237. X        free(bp->data.addr);
  238. X        bfree(right);
  239. X    }
  240. X}
  241. X
  242. Xint
  243. Xddb_bwrite(int bd, const DATUM *key, const DATUM *data, ddb_cmp_t cmp, int mode)
  244. X{
  245. X    BELEM    *bp;
  246. X    BELEM    *bp_new;
  247. X    BELEM    **prev;
  248. X
  249. X    if (!validbd(bd) || !validmode(mode)
  250. X      || (bp_new = ddb_new(key, data, sizeof(*bp_new))) == NULL)
  251. X        return -1;
  252. X    if (!cmp)
  253. X        cmp = ddb_memcmp;
  254. X    bp_new->left = bp_new->right = NULL;
  255. X
  256. X#ifdef SEQUENTIAL
  257. X    if (bp = find(bd, key, cmp, &prev, &bp_new->parent)) {
  258. X#else
  259. X    if (bp = find(bd, key, cmp, &prev)) {
  260. X#endif
  261. X        if (mode & DDB_REPLACE) {
  262. X            free(bp->data.addr);
  263. X            bp->data = bp_new->data;
  264. X            bp_new->data.addr = NULL;
  265. X            bfree(bp_new);
  266. X        } else if (mode & DDB_DUPLICATE) {
  267. X            bp_new->left = bp->left;
  268. X            bp->left = bp_new;
  269. X        } else /* DDB_INSERT */ {
  270. X            bfree(bp_new);
  271. X            return -1;
  272. X        }
  273. X    } else
  274. X        *prev = bp_new;
  275. X
  276. X    return 0;
  277. X}
  278. X
  279. XDATUM *
  280. Xddb_bread(int bd, const DATUM *key, ddb_cmp_t cmp)
  281. X{
  282. X    BELEM    *bp;
  283. X
  284. X    if (!validbd(bd))
  285. X        return NULL;
  286. X    if (!cmp)
  287. X        cmp = ddb_memcmp;
  288. X
  289. X#ifdef SEQUENTIAL
  290. X    if (bp = find(bd, key, cmp, NULL, NULL))
  291. X#else
  292. X    if (bp = find(bd, key, cmp, NULL))
  293. X#endif
  294. X        return &bp->data;
  295. X    else
  296. X        return NULL;
  297. X}
  298. X
  299. Xint
  300. Xddb_bdelete(int bd, const DATUM *key, ddb_cmp_t cmp)
  301. X{
  302. X    BELEM    *bp;
  303. X    BELEM    **prev;
  304. X    BELEM    *q;
  305. X#ifdef SEQUENTIAL
  306. X    BELEM    *parent;
  307. X#endif
  308. X
  309. X    if (!validbd(bd))
  310. X        return NULL;
  311. X    if (!cmp)
  312. X        cmp = ddb_memcmp;
  313. X
  314. X#ifdef SEQUENTIAL
  315. X    if (bp = find(bd, key, cmp, &prev, &parent)) {
  316. X#else
  317. X    if (bp = find(bd, key, cmp, &prev)) {
  318. X#endif
  319. X        free(bp->key.addr);
  320. X        free(bp->data.addr);
  321. X        if (bp->left && bp->right) {
  322. X            BELEM    *qprev;
  323. X
  324. X            for (qprev = bp->right, q = bp->right; q->left;
  325. X              qprev = q, q = q->left)
  326. X                ;
  327. X            bp->key.addr = q->key.addr;
  328. X            bp->key.size = q->key.size;
  329. X            bp->data.addr = q->data.addr;
  330. X            bp->data.size = q->data.size;
  331. X            if (q == bp->right) {
  332. X                bp->right = q->right;
  333. X#ifdef SEQUENTIAL
  334. X                if (q->right)
  335. X                    q->right->parent = bp;
  336. X#endif
  337. X            } else {
  338. X                qprev->left = q->right;
  339. X#ifdef SEQUENTIAL
  340. X                if (q->right)
  341. X                    q->right->parent = qprev;
  342. X#endif
  343. X            }
  344. X            free(q);
  345. X        } else {
  346. X            if (bp->right)
  347. X                q = bp->right;
  348. X            else
  349. X                q = bp->left;
  350. X            *prev = q;
  351. X#ifdef SEQUENTIAL
  352. X            if (q)
  353. X                q->parent = bp->parent;
  354. X#endif
  355. X            free(bp);
  356. X        }
  357. X        return 0;
  358. X    } else
  359. X        return -1;
  360. X}
  361. X
  362. Xstatic void
  363. Xinit(int bd)
  364. X{
  365. X    binary[bd].used = 0;
  366. X    binary[bd].root = NULL;
  367. X#ifdef SEQUENTIAL
  368. X    binary[bd].lastkey = NULL;
  369. X    binary[bd].startover = 0;
  370. X#endif
  371. X}
  372. X
  373. Xint
  374. Xddb_bclose(int bd)
  375. X{
  376. X    if (!validbd(bd))
  377. X        return -1;
  378. X
  379. X    bfree(binary[bd].root);
  380. X    init(bd);
  381. X
  382. X    return 0;
  383. X}
  384. X
  385. X#define ADDBINARIES    1
  386. X
  387. Xint
  388. Xddb_bopen(void)
  389. X{
  390. X    int    i;
  391. X    int    j;
  392. X    BINARY    *btmp;
  393. X
  394. X    for (i = 0; i < maxbinaries && binary[i].used; i++)
  395. X        ;
  396. X    if (i == maxbinaries) {
  397. X        if ((btmp = realloc(binary,
  398. X          (maxbinaries + ADDBINARIES) * sizeof(BINARY))) == NULL)
  399. X            return -1;
  400. X        binary = btmp;
  401. X        for (j = maxbinaries; j < maxbinaries + ADDBINARIES; j++)
  402. X            init(j);
  403. X        maxbinaries += ADDBINARIES;
  404. X    }
  405. X
  406. X    binary[i].used = 1;
  407. X
  408. X    return i;
  409. X}
  410. X
  411. X#ifdef SEQUENTIAL
  412. Xstatic DATUM *
  413. Xgetnext(int bd)
  414. X{
  415. X    BELEM    *bp;
  416. X
  417. X    if (!binary[bd].lastkey) {
  418. X        if (binary[bd].startover) {
  419. X            if (bp = binary[bd].root) {
  420. X                while (bp->left)
  421. X                    bp = bp->left;
  422. X            }
  423. X        } else
  424. X            bp = NULL;
  425. X    } else if (bp = binary[bd].lastkey->right) {
  426. X        while (bp->left)
  427. X            bp = bp->left;
  428. X    } else {
  429. X        bp = binary[bd].lastkey;
  430. X        while (bp->parent && bp == bp->parent->right)
  431. X            bp = bp->parent;
  432. X        if (bp->parent)
  433. X            bp = bp->parent;
  434. X        else
  435. X            bp = NULL;
  436. X    }
  437. X
  438. X    if (bp) {
  439. X        binary[bd].lastkey = bp;
  440. X        return &bp->key;
  441. X    } else
  442. X        return NULL;
  443. X}
  444. X
  445. XDATUM *
  446. Xddb_bfirst(int bd)
  447. X{
  448. X    DATUM    *dp;
  449. X
  450. X    if (!validbd(bd))
  451. X        return NULL;
  452. X    binary[bd].lastkey = NULL;
  453. X    binary[bd].startover = 1;
  454. X    dp = getnext(bd);
  455. X    binary[bd].startover = 0;
  456. X    return dp;
  457. X}
  458. X
  459. XDATUM *
  460. Xddb_bnext(int bd)
  461. X{
  462. X    if (!validbd(bd))
  463. X        return NULL;
  464. X    return getnext(bd);
  465. X}
  466. X#endif
  467. X
  468. Xstatic void
  469. Xrecurse(BELEM *bp, void (*f)(const DATUM *, const DATUM *), int order)
  470. X{
  471. X    if (bp) {
  472. X        if (order != DDB_PREORDER)
  473. X            recurse(bp->left, f, order);
  474. X        if (order == DDB_POSTORDER)
  475. X            recurse(bp->right, f, order);
  476. X        (*f)(&bp->key, &bp->data);
  477. X        if (order == DDB_PREORDER)
  478. X            recurse(bp->left, f, order);
  479. X        if (order != DDB_POSTORDER)
  480. X            recurse(bp->right, f, order);
  481. X    }
  482. X}
  483. X
  484. Xvoid
  485. Xddb_bfunc(int bd, void (*f)(const DATUM *, const DATUM *), int order)
  486. X{
  487. X    if (validbd(bd))
  488. X        recurse(binary[bd].root, f, order);
  489. X}
  490. X
  491. XDATUM *
  492. Xddb_blargestkey(int bd)
  493. X{
  494. X    BELEM    *bp;
  495. X
  496. X    if (!validbd(bd))
  497. X        return NULL;
  498. X
  499. X    if (bp = binary[bd].root) {
  500. X        while (bp->right)
  501. X            bp = bp->right;
  502. X        return &bp->key;
  503. X    } else
  504. X        return NULL;
  505. X}
  506. X
  507. XDATUM *
  508. Xddb_bsmallestkey(int bd)
  509. X{
  510. X    BELEM    *bp;
  511. X
  512. X    if (!validbd(bd))
  513. X        return NULL;
  514. X
  515. X    if (bp = binary[bd].root) {
  516. X        while (bp->left)
  517. X            bp = bp->left;
  518. X        return &bp->key;
  519. X    } else
  520. X        return NULL;
  521. X}
  522. X
  523. X#ifdef DEBUG
  524. Xstatic void
  525. Xdef_print(const DATUM *dp)
  526. X{
  527. X    printf("%*.*s", dp->size, dp->size, dp->addr);
  528. X}
  529. X
  530. Xstatic void
  531. Xughprint(const DATUM *dp)
  532. X{
  533. X    def_print(dp);
  534. X    putchar('\n');
  535. X}
  536. X
  537. Xstatic void
  538. Xbprint(BELEM *bp, void (*kprint)(const DATUM *), void (*dprint)(const DATUM *),
  539. X  int order)
  540. X{
  541. X    if (bp) {
  542. X        if (order != DDB_PREORDER)
  543. X            bprint(bp->left, kprint, dprint, order);
  544. X        if (order == DDB_POSTORDER)
  545. X            bprint(bp->right, kprint, dprint, order);
  546. X        printf("key: ");
  547. X        (*kprint)(&bp->key);
  548. X        printf("\tdata: ");
  549. X        (*dprint)(&bp->data);
  550. X        putchar('\n');
  551. X        if (order == DDB_PREORDER)
  552. X            bprint(bp->left, kprint, dprint, order);
  553. X        if (order != DDB_POSTORDER)
  554. X            bprint(bp->right, kprint, dprint, order);
  555. X    }
  556. X}
  557. X
  558. Xvoid
  559. Xddb_bdump(int bd, void (*kprint)(const DATUM *), void (*dprint)(const DATUM *),
  560. X  int order)
  561. X{
  562. X    if (!kprint)
  563. X        kprint = def_print;
  564. X    if (!dprint)
  565. X        dprint = def_print;
  566. X
  567. X    if (validbd(bd))
  568. X        switch (order) {
  569. X        case DDB_PREORDER:
  570. X            bprint(binary[bd].root, kprint, dprint, order);
  571. X            break;
  572. X        case DDB_INORDER:
  573. X            bprint(binary[bd].root, kprint, dprint, order);
  574. X            break;
  575. X        case DDB_POSTORDER:
  576. X            bprint(binary[bd].root, kprint, dprint, order);
  577. X            break;
  578. X        }
  579. X}
  580. X#endif
  581. END_OF_FILE
  582. if test 8251 -ne `wc -c <'ddb/binary.c'`; then
  583.     echo shar: \"'ddb/binary.c'\" unpacked with wrong size!
  584. fi
  585. # end of 'ddb/binary.c'
  586. fi
  587. if test -f 'ddb/bit.c' -a "${1}" != "-c" ; then 
  588.   echo shar: Will not clobber existing file \"'ddb/bit.c'\"
  589. else
  590. echo shar: Extracting \"'ddb/bit.c'\" \(5839 characters\)
  591. sed "s/^X//" >'ddb/bit.c' <<'END_OF_FILE'
  592. X/*
  593. X *                 Author:  Christopher G. Phillips
  594. X *              Copyright (C) 1993 All Rights Reserved
  595. X *
  596. X *                              NOTICE
  597. X *
  598. X * Permission to use, copy, modify, and distribute this software and
  599. X * its documentation for any purpose and without fee is hereby granted
  600. X * provided that the above copyright notice appear in all copies and
  601. X * that both the copyright notice and this permission notice appear in
  602. X * supporting documentation.
  603. X *
  604. X * The author makes no representations about the suitability of this
  605. X * software for any purpose.  This software is provided ``as is''
  606. X * without express or implied warranty.
  607. X */
  608. X
  609. X#include <stdio.h>
  610. X#include <stdlib.h>
  611. X#include <string.h>
  612. X#include <limits.h>
  613. X#include <sys/types.h>
  614. X#include <ddb.h>
  615. X
  616. X#define MIN(a,b)    ((a) < (b) ? (a) : (b))
  617. X
  618. X#ifndef WORD_BIT
  619. X#define WORD_BIT    (sizeof(int) * CHAR_BIT)
  620. X#endif
  621. X#define setbit(a,b)    ((a)[(b) / WORD_BIT] |= 1 << ((b) % WORD_BIT))
  622. X#define clrbit(a,b)    ((a)[(b) / WORD_BIT] &= ~(1 << ((b) % WORD_BIT)))
  623. X#define isset(a,b)    ((a)[(b) / WORD_BIT] & (1 << ((b) % WORD_BIT)))
  624. X#define isclr(a,b)    (((a)[(b) / WORD_BIT] & (1 << ((b) % WORD_BIT))) == 0)
  625. X
  626. Xtypedef struct {
  627. X    int        used;
  628. X    unsigned long    maxbit;
  629. X    unsigned int    *bits;
  630. X    long        lastbit;
  631. X} BIT;
  632. X
  633. Xstatic BIT    *vector = NULL;
  634. Xstatic int    maxvectors = 0;
  635. X
  636. X#define CHECK_MAXBIT    1
  637. X
  638. Xstatic int
  639. Xvalidbd(int bd, unsigned long bit, int check)
  640. X{
  641. X    return vector && bd < maxvectors && vector[bd].used
  642. X      && (check != CHECK_MAXBIT || bit <= vector[bd].maxbit);
  643. X}
  644. X
  645. Xstatic int
  646. Xvalidmode(int mode)
  647. X{
  648. X    switch (mode & DDB_MODE_MASK) {
  649. X    case DDB_INSERT:
  650. X    case DDB_REPLACE:
  651. X    case DDB_DUPLICATE:
  652. X        return 1;
  653. X    default:
  654. X        return 0;
  655. X    }
  656. X}
  657. X
  658. Xstatic int
  659. Xenlarge(int bd, unsigned long maxbit)
  660. X{
  661. X    unsigned int    *newbits;
  662. X    unsigned long    nints1, nints2;
  663. X    unsigned long    bit;
  664. X
  665. X    if (maxbit > (unsigned long)LONG_MAX)
  666. X        return -1;
  667. X
  668. X    nints1 = vector[bd].maxbit / WORD_BIT + 1;
  669. X    nints2 = maxbit / WORD_BIT + 1;
  670. X    for (bit = vector[bd].maxbit + 1; bit / WORD_BIT + 1 == nints1; bit++)
  671. X        clrbit(vector[bd].bits, bit);
  672. X    if (nints2 > nints1) {
  673. X        if ((newbits = realloc(vector[bd].bits, nints2 * sizeof(int)))
  674. X          == NULL)
  675. X            return -1;
  676. X        (void)memset(newbits + nints1, '\0',
  677. X          (nints2 - nints1) * sizeof(int));
  678. X    }
  679. X    
  680. X    vector[bd].maxbit = maxbit;
  681. X
  682. X    return 0;
  683. X}
  684. X
  685. Xint
  686. Xddb_bitwrite(int bd, unsigned long bit, int mode)
  687. X{
  688. X    if (!validbd(bd, bit, !CHECK_MAXBIT) || !validmode(mode))
  689. X        return -1;
  690. X    if (bit > vector[bd].maxbit && enlarge(bd, bit) == -1)
  691. X        return -1;
  692. X
  693. X    if (!isset(vector[bd].bits, bit))
  694. X        setbit(vector[bd].bits, bit);
  695. X    else if (mode & DDB_INSERT)
  696. X        return -1;
  697. X
  698. X    return 0;
  699. X}
  700. X
  701. Xint
  702. Xddb_bitread(int bd, unsigned long bit)
  703. X{
  704. X    if (!validbd(bd, bit, !CHECK_MAXBIT))
  705. X        return -1;
  706. X
  707. X    if (bit > vector[bd].maxbit)
  708. X        return 0;
  709. X    return isset(vector[bd].bits, bit) != 0;
  710. X}
  711. X
  712. Xint
  713. Xddb_bitdelete(int bd, unsigned long bit)
  714. X{
  715. X    if (!validbd(bd, bit, CHECK_MAXBIT))
  716. X        return -1;
  717. X
  718. X    if (isset(vector[bd].bits, bit)) {
  719. X        clrbit(vector[bd].bits, bit);
  720. X        return 0;
  721. X    } else
  722. X        return -1;
  723. X}
  724. X
  725. Xint
  726. Xddb_bitclose(int bd)
  727. X{
  728. X    if (!validbd(bd, 0, !CHECK_MAXBIT))
  729. X        return -1;
  730. X
  731. X    vector[bd].used = 0;
  732. X    free(vector[bd].bits);
  733. X    vector[bd].bits = NULL;
  734. X
  735. X    return 0;
  736. X}
  737. X
  738. Xint
  739. Xddb_bitset(int bd, int on)
  740. X{
  741. X    if (!validbd(bd, 0, !CHECK_MAXBIT))
  742. X        return -1;
  743. X
  744. X    (void)memset(vector[bd].bits, on ? ~0 : '\0',
  745. X      (vector[bd].maxbit / WORD_BIT + 1) * sizeof(int));
  746. X    return 0;
  747. X}
  748. X
  749. X#define ADDVECTORS    1
  750. X
  751. Xint
  752. Xddb_bitopen(unsigned long maxbit)
  753. X{
  754. X    int        i;
  755. X    int        j;
  756. X    BIT        *vtmp;
  757. X
  758. X    if (maxbit > (unsigned long)LONG_MAX)
  759. X        return -1;
  760. X
  761. X    for (i = 0; i < maxvectors && vector[i].used; i++)
  762. X        ;
  763. X    if (i == maxvectors) {
  764. X        if ((vtmp = realloc(vector,
  765. X          (maxvectors + ADDVECTORS) * sizeof(BIT))) == NULL)
  766. X            return -1;
  767. X        vector = vtmp;
  768. X        for (j = maxvectors; j < maxvectors + ADDVECTORS; j++) {
  769. X            vector[j].used = 0;
  770. X            vector[j].bits = NULL;
  771. X        }
  772. X        maxvectors += ADDVECTORS;
  773. X    } else
  774. X        free(vector[i].bits);
  775. X
  776. X    if ((vector[i].bits = malloc((maxbit / WORD_BIT + 1) * sizeof(int)))
  777. X      == NULL)
  778. X        return -1;
  779. X
  780. X    vector[i].used = 1;
  781. X    vector[i].maxbit = maxbit;
  782. X    (void)ddb_bitset(i, 0);
  783. X
  784. X    return i;
  785. X}
  786. X
  787. Xstatic long
  788. Xfindword(unsigned int *bits, unsigned long first, unsigned long last,
  789. X  unsigned int firstmask)
  790. X{
  791. X    unsigned long    i;
  792. X
  793. X    if (bits[first] & ~firstmask)
  794. X        return (long)first;
  795. X    if (last >= first) {
  796. X        for (i = first + 1; i <= last; i++)
  797. X            if (bits[i])
  798. X                return (long)i;
  799. X    } else {
  800. X        for (i = first - 1; i >= last; i--)
  801. X            if (bits[i])
  802. X                return (long)i;
  803. X    }
  804. X
  805. X    return -1;
  806. X}
  807. X
  808. X#if 0
  809. Xstatic long
  810. Xfindhighset(unsigned int word, unsigned int mask)
  811. X{
  812. X    long    bit;
  813. X
  814. X    word &= ~mask;
  815. X    for (bit = WORD_BIT - 1; (word & (1 << bit)) == 0; bit--)
  816. X        ;
  817. X    return bit;
  818. X}
  819. X#endif
  820. X
  821. Xstatic long
  822. Xfindlowset(unsigned int word, unsigned int mask)
  823. X{
  824. X    long    bit;
  825. X
  826. X    word &= ~mask;
  827. X    for (bit = 0; (word & (1 << bit)) == 0; bit++)
  828. X        ;
  829. X    return bit;
  830. X}
  831. X
  832. Xlong
  833. Xddb_bitfirst(int bd)
  834. X{
  835. X    unsigned long    index;
  836. X
  837. X    if (!validbd(bd, 0, !CHECK_MAXBIT) || (index = findword(vector[bd].bits,
  838. X      0, vector[bd].maxbit / WORD_BIT, 0)) == -1)
  839. X        return -1;
  840. X    else
  841. X        return vector[bd].lastbit = findlowset(vector[bd].bits[index],
  842. X          0) + index * WORD_BIT;
  843. X}
  844. X
  845. X#define wordmask(n)    ((1 << (n + 1)) - 1)
  846. X
  847. Xlong
  848. Xddb_bitnext(int bd)
  849. X{
  850. X    unsigned int    mask;
  851. X    unsigned long    index;
  852. X
  853. X    if (!validbd(bd, 0, !CHECK_MAXBIT))
  854. X        return -1;
  855. X    mask = wordmask(vector[bd].lastbit % WORD_BIT);
  856. X    if ((index = findword(vector[bd].bits, vector[bd].lastbit / WORD_BIT,
  857. X      vector[bd].maxbit / WORD_BIT, mask)) == -1)
  858. X        return -1;
  859. X    else {
  860. X        if (index != vector[bd].lastbit / WORD_BIT)
  861. X            mask = 0;
  862. X        return vector[bd].lastbit = findlowset(vector[bd].bits[index],
  863. X          mask) + index * WORD_BIT;
  864. X    }
  865. X}
  866. X
  867. X#ifdef DEBUG
  868. Xvoid
  869. Xddb_bitdump(int bd)
  870. X{
  871. X    long    result;
  872. X
  873. X    printf("BITS SET:");
  874. X    if ((result = ddb_bitfirst(bd)) >= 0) {
  875. X        printf("\n%ld\n", result);
  876. X        while ((result = ddb_bitnext(bd)) >= 0)
  877. X            printf("%ld\n", result);
  878. X        putchar('\n');
  879. X    } else
  880. X        printf("\tnone\n");
  881. X
  882. X}
  883. X#endif
  884. END_OF_FILE
  885. if test 5839 -ne `wc -c <'ddb/bit.c'`; then
  886.     echo shar: \"'ddb/bit.c'\" unpacked with wrong size!
  887. fi
  888. # end of 'ddb/bit.c'
  889. fi
  890. if test -f 'ddb/ddb.3' -a "${1}" != "-c" ; then 
  891.   echo shar: Will not clobber existing file \"'ddb/ddb.3'\"
  892. else
  893. echo shar: Extracting \"'ddb/ddb.3'\" \(6659 characters\)
  894. sed "s/^X//" >'ddb/ddb.3' <<'END_OF_FILE'
  895. X.\" ddb.3
  896. X.TH DDB 3 "October 31, 1993"
  897. X.SH NAME
  898. Xddb \- dynamic memory database library
  899. X.SH SYNOPSIS
  900. X.LP
  901. X.nf
  902. X.ft B
  903. X#include "ddb.h"
  904. Xtypedef struct {
  905. X    void    *addr;
  906. X    size_t    size;
  907. X} DATUM;
  908. X.sp
  909. Xtypedef int    (*ddb_cmp_t)(const DATUM *key1, const DATUM *key2);
  910. Xtypedef size_t    (*ddb_hash_t)(const char *addr, size_t size, size_t buckets);
  911. X.ft
  912. X.fi
  913. X.LP
  914. X.nf
  915. X.ft B
  916. XBinary Tree Interface
  917. Xint    ddb_bopen(void);
  918. Xint    ddb_bclose(int dbd);
  919. Xint    ddb_bwrite(int dbd, const DATUM *key, const DATUM *data,
  920. X      ddb_cmp_t cmp, int flag);
  921. Xint    ddb_bdelete(int dbd, const DATUM *key, ddb_cmp_t cmp);
  922. XDATUM    *ddb_bread(int dbd, const DATUM *key, ddb_cmp_t cmp);
  923. XDATUM    *ddb_bfirst(int dbd);
  924. XDATUM    *ddb_bnext(int dbd);
  925. Xvoid    ddb_bfunc(int dbd, void (*f)(const DATUM *key, const DATUM *data),
  926. X      int order);
  927. X.ft
  928. X.fi
  929. X.LP
  930. X.nf
  931. X.ft B
  932. XBit Vector Interface
  933. Xint    ddb_bitopen(unsigned long maxbit);
  934. Xint    ddb_bitclose(int dbd);
  935. Xint    ddb_bitwrite(int dbd, unsigned long bit, int flag);
  936. Xint    ddb_bitdelete(int dbd, unsigned long bit);
  937. Xint    ddb_bitread(int dbd, unsigned long bit);
  938. Xlong    ddb_bitfirst(int dbd);
  939. Xlong    ddb_bitnext(int dbd);
  940. Xint    ddb_bitset(int dbd, int on);
  941. X.ft
  942. X.fi
  943. X.LP
  944. X.nf
  945. X.ft B
  946. XHash Table Interface
  947. Xint    ddb_hopen(size_t buckets);
  948. Xint    ddb_hclose(int dbd);
  949. Xint    ddb_hwrite(int dbd, const DATUM *key, const DATUM *data,
  950. X      ddb_cmp_t cmp, int flag, ddb_hash_t hash);
  951. Xint    ddb_hdelete(int dbd, const DATUM *key, ddb_cmp_t cmp,
  952. X      ddb_hash_t hash);
  953. XDATUM    *ddb_hread(int dbd, const DATUM *key, ddb_cmp_t cmp,
  954. X      ddb_hash_t hash);
  955. XDATUM    *ddb_hfirst(int dbd);
  956. XDATUM    *ddb_hnext(int dbd);
  957. X.ft
  958. X.fi
  959. X.LP
  960. X.nf
  961. X.ft B
  962. XLinked List Interface
  963. Xint    ddb_lopen(void);
  964. Xint    ddb_lclose(int dbd);
  965. Xint    ddb_lwrite(int dbd, const DATUM *key, const DATUM *data,
  966. X      ddb_cmp_t cmp, int flag);
  967. Xint    ddb_ldelete(int dbd, const DATUM *key, ddb_cmp_t cmp);
  968. XDATUM    *ddb_lread(int dbd, const DATUM *key, ddb_cmp_t cmp);
  969. XDATUM    *ddb_lfirst(int dbd);
  970. XDATUM    *ddb_lnext(int dbd);
  971. X.ft
  972. X.fi
  973. X.LP
  974. X.nf
  975. X.ft B
  976. XQueue Interface
  977. Xint    ddb_qopen(void);
  978. Xint    ddb_qclose(int dbd);
  979. Xint    ddb_qwrite(int dbd, const DATUM *key);
  980. XDATUM    *ddb_qread(int dbd);
  981. X.ft
  982. X.fi
  983. X.LP
  984. X.nf
  985. X.ft B
  986. XStack Interface
  987. Xint    ddb_sopen(void);
  988. Xint    ddb_sclose(int dbd);
  989. Xint    ddb_swrite(int dbd, const DATUM *key);
  990. XDATUM    *ddb_sread(int dbd);
  991. X.ft
  992. X.fi
  993. X.SH PARAMETERS
  994. X.IP \fIdbd\fP
  995. XSpecifies a small nonnegative database descriptor previously returned
  996. Xby one of the
  997. X.BR open(\|)
  998. Xfunctions.
  999. X.IP \fIkey\fP
  1000. XSpecifies the key.
  1001. X.IP \fIdata\fP
  1002. XSpecifies the data associated with
  1003. X.IR key .
  1004. X.IP \fIcmp\fP
  1005. XSpecifies a function used to compare two keys.
  1006. XThe function
  1007. X.IR cmp
  1008. Xshould return zero if the keys compare equal, less than zero if
  1009. Xthe first key compares less than the second, else greater than zero.
  1010. XIf
  1011. X.IR cmp
  1012. Xis NULL, a default function is used.
  1013. XThis function returns zero if the two keys are identical and of the same size.
  1014. XIf they are identical up to the length of the shorter, the shorter is
  1015. Xassumed to precede the longer.
  1016. XOtherwise, the order is as returned by
  1017. X.BR memcmp (3).
  1018. X.IP \fIflag\fP
  1019. XSpecifies the mode that the
  1020. X.BR write(\|)
  1021. Xfunctions use to add to the databases.
  1022. XMust include only one of the following values:
  1023. X.IP DDB_INSERT
  1024. XInsert the pair only if the key is not currently in the database.
  1025. X.IP DDB_REPLACE
  1026. XAdd the pair to the database.
  1027. XIf the key is already in the database, delete that entry.
  1028. X.IP DDB_DUPLICATE
  1029. XAdd the pair to the database.
  1030. XIf the key is already in the database, do not delete that entry.
  1031. X
  1032. XFor the
  1033. X.BR ddb_lwrite(\|)
  1034. Xfunction, the value
  1035. X.IR DDB_TAIL
  1036. Xcan be inclusively OR'ed into
  1037. X.IR flag
  1038. Xto specify writing at the tail of the list.
  1039. X.IP \fIf\fP
  1040. XSpecifies a function called for each entry in a binary tree database
  1041. Xin the order given by parameter
  1042. X.IR order .
  1043. XThe function takes two arguments: a key in the database and its associated data.
  1044. X.IP \fIorder\fP
  1045. XSpecifies the order that the entries in a binary tree database
  1046. Xare operated on by function
  1047. X.IR f
  1048. Xand must be DDB_PREORDER, DDB_INORDER, or DDB_POSTORDER.
  1049. X.IP \fImaxbit\fP
  1050. XSpecifies the maximum bit which may be used by a bit vector database.
  1051. XThis value is changed as necessary to grow the database although the ultimate
  1052. Xmaximum bit is LONG_MAX.
  1053. XThe minimum bit which may be used is bit 0.
  1054. X.IP \fIon\fP
  1055. XSpecifies whether all valid bits of a bit vector database should be set or
  1056. Xunset.
  1057. XInitially, all bits are cleared.
  1058. XWhenever the database is grown, all new bits are cleared.
  1059. X.IP \fIbuckets\fP
  1060. XSpecifies the number of buckets used for a hash table database.
  1061. X.IP \fIhash\fP
  1062. XSpecifies the hashing function used by the
  1063. X.BR hash(\|)
  1064. Xfunctions.
  1065. XThe function takes three arguments: the address and size of the key
  1066. Xand the number of buckets used in the hash table.
  1067. XIf NULL, a default function is used.
  1068. X.SH DESCRIPTION
  1069. X.LP
  1070. XThis package provides a simple interface to flexible database routines.
  1071. XData structures supported are binary trees, bit vectors, hash tables,
  1072. Xlinked lists, queues, and stacks.
  1073. XAll key\-data pairs are copied into the databases using
  1074. X.BR malloc(3) .
  1075. X.LP
  1076. XTo create a database, the
  1077. X.BR open(\|)
  1078. Xfunctions are used.
  1079. XAdding and deleting are respectively done with the
  1080. X.BR write(\|)
  1081. Xand
  1082. X.BR delete(\|)
  1083. Xfunctions and reading is done with the
  1084. X.BR read(\|)
  1085. Xfunctions.
  1086. X.LP
  1087. XMost database types may have all keys (or bits) in a database examined
  1088. Xby calling the
  1089. X.BR first(\|)
  1090. Xfunction once followed by repeated calls to the
  1091. X.BR next(\|)
  1092. Xfunction.
  1093. XFailure indicates that all keys have been returned.
  1094. XThe keys are returned in unspecified order.
  1095. X.LP
  1096. XDatabases are destroyed (and all associated memory freed) with the
  1097. X.BR close(\|)
  1098. Xfunctions.
  1099. X.SH RETURN VALUES
  1100. XThe
  1101. X.BR open(\|)
  1102. Xfunctions return nonnegative if successful and -1 otherwise.
  1103. XThe
  1104. X.BR close(\|) ,
  1105. X.BR write(\|) ,
  1106. Xand
  1107. X.BR delete(\|)
  1108. Xfunctions return 0 on success and -1 otherwise.
  1109. X.LP
  1110. XThe
  1111. X.BR first(\|)
  1112. Xfunctions indicate failure (-1 for
  1113. X.BR ddb_bitfirst(\|)
  1114. Xand NULL otherwise) if the database is empty.
  1115. X.BR ddb_bitfirst(\|)
  1116. Xreturns nonnegative and the other
  1117. X.BR first(\|)
  1118. Xfunctions return non-NULL to indicate success.
  1119. XThe
  1120. X.BR next(\|)
  1121. Xfunctions denote success and failure identically to the
  1122. X.BR first(\|)
  1123. Xfunctions.
  1124. X.LP
  1125. XFunctions returning type pointer\-to\-DATUM return NULL on failure.
  1126. X.SH NOTES
  1127. XAll of the
  1128. X.BR read(\|)
  1129. Xfunctions except
  1130. X.BR ddb_bitread(\|)
  1131. Xreturn pointers to memory which should be freed when unneeded.
  1132. X.LP
  1133. XAltering a database and then calling a
  1134. X.BR next(\|)
  1135. Xfunction without an intervening
  1136. X.BR first(\|)
  1137. Xcall results in undefined behavior.
  1138. X.LP
  1139. XIf the
  1140. X.IR key
  1141. Xargument to
  1142. X.BR ddb_bread(\|)
  1143. Xis NULL, the head of the list is implied.
  1144. XWriting to a linked list may be at the head or tail of the list.
  1145. X.SH SEE ALSO
  1146. X.BR bsearch (3),
  1147. X.BR hsearch (3),
  1148. X.BR ndbm (3),
  1149. X.BR tsearch (3).
  1150. X.SH AUTHOR
  1151. X.nf
  1152. XChristopher G. Phillips
  1153. Xpefv700@utpe.pe.utexas.edu
  1154. END_OF_FILE
  1155. if test 6659 -ne `wc -c <'ddb/ddb.3'`; then
  1156.     echo shar: \"'ddb/ddb.3'\" unpacked with wrong size!
  1157. fi
  1158. # end of 'ddb/ddb.3'
  1159. fi
  1160. if test -f 'ddb/ddb.h' -a "${1}" != "-c" ; then 
  1161.   echo shar: Will not clobber existing file \"'ddb/ddb.h'\"
  1162. else
  1163. echo shar: Extracting \"'ddb/ddb.h'\" \(3258 characters\)
  1164. sed "s/^X//" >'ddb/ddb.h' <<'END_OF_FILE'
  1165. X/*
  1166. X *                 Author:  Christopher G. Phillips
  1167. X *              Copyright (C) 1993 All Rights Reserved
  1168. X *
  1169. X *                              NOTICE
  1170. X *
  1171. X * Permission to use, copy, modify, and distribute this software and
  1172. X * its documentation for any purpose and without fee is hereby granted
  1173. X * provided that the above copyright notice appear in all copies and
  1174. X * that both the copyright notice and this permission notice appear in
  1175. X * supporting documentation.
  1176. X *
  1177. X * The author makes no representations about the suitability of this
  1178. X * software for any purpose.  This software is provided ``as is''
  1179. X * without express or implied warranty.
  1180. X */
  1181. X
  1182. X#ifndef H_DDB
  1183. X#define H_DDB
  1184. X
  1185. X#include <sys/types.h>
  1186. X
  1187. Xtypedef struct {
  1188. X    void    *addr;
  1189. X    size_t    size;
  1190. X} DATUM;
  1191. X
  1192. Xtypedef int    (*ddb_cmp_t)(const DATUM *, const DATUM *);
  1193. Xtypedef size_t    (*ddb_hash_t)(const char *, size_t, size_t);
  1194. X
  1195. X#define DDB_INSERT    1
  1196. X#define DDB_REPLACE    2
  1197. X#define DDB_DUPLICATE    4
  1198. X#define DDB_MODE_MASK    (DDB_INSERT | DDB_REPLACE | DDB_DUPLICATE)
  1199. X#define DDB_TAIL    8
  1200. X
  1201. X/* Binary tree interface */
  1202. Xextern int    ddb_bopen(void);
  1203. Xextern int    ddb_bclose(int);
  1204. Xextern int    ddb_bwrite(int, const DATUM *, const DATUM *, ddb_cmp_t, int);
  1205. Xextern int    ddb_bdelete(int, const DATUM *, ddb_cmp_t);
  1206. Xextern DATUM    *ddb_bread(int, const DATUM *, ddb_cmp_t);
  1207. X#define DDB_PREORDER    0
  1208. X#define DDB_INORDER    1
  1209. X#define DDB_POSTORDER    2
  1210. Xextern DATUM    *ddb_bfirst(int);
  1211. Xextern DATUM    *ddb_bnext(int);
  1212. Xextern void    ddb_bfunc(int, void (*)(const DATUM *, const DATUM *), int);
  1213. Xextern DATUM    *ddb_blargestkey(int);
  1214. Xextern DATUM    *ddb_bsmallestkey(int);
  1215. X#ifdef DEBUG
  1216. Xextern void    ddb_bdump(int, void (*)(const DATUM *), void (*)(const DATUM *),
  1217. X          int);
  1218. X#endif
  1219. X
  1220. X/* Bit vector interface */
  1221. Xextern int    ddb_bitopen(unsigned long);
  1222. Xextern int    ddb_bitclose(int);
  1223. Xextern int    ddb_bitwrite(int, unsigned long, int);
  1224. Xextern int    ddb_bitdelete(int, unsigned long);
  1225. Xextern int    ddb_bitread(int, unsigned long);
  1226. Xextern long    ddb_bitfirst(int);
  1227. Xextern long    ddb_bitnext(int);
  1228. Xextern long    ddb_bitlargestkey(int);
  1229. Xextern long    ddb_bitsmallestkey(int);
  1230. Xextern int    ddb_bitset(int, int);
  1231. X#ifdef DEBUG
  1232. Xextern void    ddb_bitdump(int);
  1233. X#endif
  1234. X
  1235. X/* Hash table interface */
  1236. Xextern int    ddb_hopen(size_t);
  1237. Xextern int    ddb_hclose(int);
  1238. Xextern int    ddb_hwrite(int, const DATUM *, const DATUM *, ddb_cmp_t, int,
  1239. X          ddb_hash_t);
  1240. Xextern int    ddb_hdelete(int, const DATUM *, ddb_cmp_t, ddb_hash_t);
  1241. Xextern DATUM    *ddb_hread(int, const DATUM *, ddb_cmp_t, ddb_hash_t);
  1242. Xextern DATUM    *ddb_hfirst(int);
  1243. Xextern DATUM    *ddb_hnext(int);
  1244. X#ifdef DEBUG
  1245. Xextern void    ddb_hdump(int, void (*)(const DATUM *),
  1246. X          void (*)(const DATUM *));
  1247. X#endif
  1248. X
  1249. X/* Linked list interface */
  1250. Xextern int    ddb_lopen(void);
  1251. Xextern int    ddb_lclose(int);
  1252. Xextern int    ddb_lwrite(int, const DATUM *, const DATUM *, ddb_cmp_t, int);
  1253. Xextern int    ddb_ldelete(int, const DATUM *, ddb_cmp_t);
  1254. Xextern DATUM    *ddb_lread(int, const DATUM *, ddb_cmp_t);
  1255. Xextern DATUM    *ddb_lfirst(int);
  1256. Xextern DATUM    *ddb_lnext(int);
  1257. X
  1258. X/* Queue interface */
  1259. Xextern int    ddb_qopen(void);
  1260. Xextern int    ddb_qclose(int);
  1261. Xextern int    ddb_qwrite(int, const DATUM *);
  1262. Xextern DATUM    *ddb_qread(int);
  1263. X
  1264. X/* Stack interface */
  1265. Xextern int    ddb_sopen(void);
  1266. Xextern int    ddb_sclose(int);
  1267. Xextern int    ddb_swrite(int, const DATUM *);
  1268. Xextern DATUM    *ddb_sread(int);
  1269. X
  1270. X#endif /* H_DDB */
  1271. END_OF_FILE
  1272. if test 3258 -ne `wc -c <'ddb/ddb.h'`; then
  1273.     echo shar: \"'ddb/ddb.h'\" unpacked with wrong size!
  1274. fi
  1275. # end of 'ddb/ddb.h'
  1276. fi
  1277. if test -f 'ddb/hash.c' -a "${1}" != "-c" ; then 
  1278.   echo shar: Will not clobber existing file \"'ddb/hash.c'\"
  1279. else
  1280. echo shar: Extracting \"'ddb/hash.c'\" \(6175 characters\)
  1281. sed "s/^X//" >'ddb/hash.c' <<'END_OF_FILE'
  1282. X/*
  1283. X *                 Author:  Christopher G. Phillips
  1284. X *              Copyright (C) 1993 All Rights Reserved
  1285. X *
  1286. X *                              NOTICE
  1287. X *
  1288. X * Permission to use, copy, modify, and distribute this software and
  1289. X * its documentation for any purpose and without fee is hereby granted
  1290. X * provided that the above copyright notice appear in all copies and
  1291. X * that both the copyright notice and this permission notice appear in
  1292. X * supporting documentation.
  1293. X *
  1294. X * The author makes no representations about the suitability of this
  1295. X * software for any purpose.  This software is provided ``as is''
  1296. X * without express or implied warranty.
  1297. X */
  1298. X
  1299. X#include <stdio.h>
  1300. X#include <stdlib.h>
  1301. X#include <string.h>
  1302. X#include <sys/types.h>
  1303. X#include <ddb.h>
  1304. X
  1305. Xtypedef struct hashent {
  1306. X    DATUM        key;
  1307. X    DATUM        data;
  1308. X    struct hashent    *next;
  1309. X} HASHENT;
  1310. Xtypedef HASHENT *BUCKET;
  1311. Xtypedef struct {
  1312. X    short    used;
  1313. X    size_t    nbuckets;
  1314. X    BUCKET    *bucket;
  1315. X    size_t    which_bucket;
  1316. X    HASHENT    *lastkey;
  1317. X} HASHTAB;
  1318. X
  1319. X#define NBUCKETS    43
  1320. X
  1321. X#define H_READ        0
  1322. X#define H_DELETE    3
  1323. X
  1324. Xstatic HASHTAB    *hashtable = NULL;
  1325. Xstatic int    maxtables = 0;
  1326. X
  1327. Xextern void    *ddb_new(const DATUM *, const DATUM *, size_t);
  1328. Xextern int    ddb_memcmp(const DATUM *, const DATUM *);
  1329. X
  1330. Xstatic size_t
  1331. Xdef_hash(const char *key, size_t keysize, size_t nbuckets)
  1332. X{
  1333. X    size_t    c;
  1334. X    size_t    i;
  1335. X
  1336. X    for (c = i = 0; i < keysize; i++, key++)
  1337. X        c = *key + 33 * c;
  1338. X    return c % nbuckets;
  1339. X}
  1340. X
  1341. Xstatic int
  1342. Xvalidhd(int hd)
  1343. X{
  1344. X    return hashtable && hd < maxtables && hashtable[hd].used;
  1345. X}
  1346. X
  1347. Xstatic DATUM *
  1348. Xhashop(int hd, int action, const DATUM *key, const DATUM *data, ddb_cmp_t cmp,
  1349. X  ddb_hash_t hash)
  1350. X{
  1351. X    size_t    hashval;
  1352. X    HASHENT    *ptr, *oldptr = NULL;
  1353. X
  1354. X    if (!validhd(hd))
  1355. X        return NULL;
  1356. X
  1357. X    if (hash == NULL)
  1358. X        hash = def_hash;
  1359. X    if (cmp == NULL)
  1360. X        cmp = ddb_memcmp;
  1361. X
  1362. X    hashval = hash(key->addr, key->size, hashtable[hd].nbuckets)
  1363. X      % hashtable[hd].nbuckets;
  1364. X
  1365. X    if (ptr = hashtable[hd].bucket[hashval])
  1366. X        while (ptr && (*cmp)(key, &ptr->key)) {
  1367. X            oldptr = ptr;
  1368. X            ptr = ptr->next;
  1369. X        }
  1370. X
  1371. X    if (action == H_READ)
  1372. X        return ptr ? &ptr->data : NULL;
  1373. X
  1374. X    if (ptr && action == DDB_INSERT)
  1375. X        return NULL;
  1376. X
  1377. X    if (!ptr && action == H_DELETE)
  1378. X        return NULL;
  1379. X
  1380. X    if (ptr && action != DDB_DUPLICATE) {    /* H_DELETE || DDB_REPLACE */
  1381. X        free(ptr->data.addr);
  1382. X        if (action == H_DELETE) {
  1383. X            free(ptr->key.addr);
  1384. X            if (oldptr)
  1385. X                oldptr->next = ptr->next;
  1386. X            else {
  1387. X                oldptr = ptr->next;
  1388. X                hashtable[hd].bucket[hashval] = oldptr;
  1389. X            }
  1390. X            return &oldptr->data;
  1391. X        } else {    /* DDB_REPLACE */
  1392. X            if ((ptr->data.addr = malloc(data->size)) == NULL)
  1393. X                return NULL;
  1394. X            (void)memcpy(ptr->data.addr, data->addr,
  1395. X              (int)data->size);
  1396. X            ptr->data.size = data->size;
  1397. X            return &ptr->data;
  1398. X        }
  1399. X    }
  1400. X
  1401. X    if (ptr && action == DDB_DUPLICATE) {
  1402. X        oldptr = ptr;
  1403. X        if ((ptr = ddb_new(key, data, sizeof(*ptr))) == NULL)
  1404. X            return NULL;
  1405. X        ptr->next = oldptr->next;
  1406. X        oldptr->next = ptr;
  1407. X        return &ptr->data;
  1408. X    }
  1409. X
  1410. X    /* DDB_INSERT || DDB_REPLACE || DDB_DUPLICATE */
  1411. X    if (oldptr)
  1412. X        oldptr = hashtable[hd].bucket[hashval];
  1413. X    if ((ptr = hashtable[hd].bucket[hashval]
  1414. X      = ddb_new(key, data, sizeof(*ptr))) == NULL)
  1415. X        return NULL;
  1416. X    ptr->next = oldptr;
  1417. X    return &ptr->data;
  1418. X}
  1419. X
  1420. Xint
  1421. Xddb_hwrite(int hd, const DATUM *key, const DATUM *data, ddb_cmp_t cmp, int mode,
  1422. X  ddb_hash_t hash)
  1423. X{
  1424. X    if (mode != DDB_INSERT && mode != DDB_REPLACE && mode != DDB_DUPLICATE)
  1425. X        return -1;
  1426. X    else if (hashop(hd, mode, key, data, cmp, hash))
  1427. X        return 0;
  1428. X    else
  1429. X        return -1;
  1430. X}
  1431. X
  1432. XDATUM *
  1433. Xddb_hread(int hd, const DATUM *key, ddb_cmp_t cmp, ddb_hash_t hash)
  1434. X{
  1435. X    return hashop(hd, H_READ, key, NULL, cmp, hash);
  1436. X}
  1437. X
  1438. Xint
  1439. Xddb_hdelete(int hd, const DATUM *key, ddb_cmp_t cmp, ddb_hash_t hash)
  1440. X{
  1441. X    if (hashop(hd, H_DELETE, key, NULL, cmp, hash))
  1442. X        return 0;
  1443. X    else
  1444. X        return -1;
  1445. X}
  1446. X
  1447. Xstatic void
  1448. Xhfree(HASHENT *hp)
  1449. X{
  1450. X    if (hp->next)
  1451. X        hfree(hp->next);
  1452. X    free(hp->data.addr);
  1453. X    free(hp->key.addr);
  1454. X    free(hp);
  1455. X}
  1456. X
  1457. Xint
  1458. Xddb_hclose(int hd)
  1459. X{
  1460. X    int    bucket;
  1461. X
  1462. X    if (!validhd(hd))
  1463. X        return -1;
  1464. X
  1465. X    for (bucket = 0; bucket < hashtable[hd].nbuckets; bucket++)
  1466. X        if (hashtable[hd].bucket[bucket])
  1467. X            hfree(hashtable[hd].bucket[bucket]);
  1468. X
  1469. X    hashtable[hd].used = 0;
  1470. X
  1471. X    return 0;
  1472. X}
  1473. X
  1474. X#define ADDTABLES    1
  1475. X
  1476. Xstatic int
  1477. Xgetbuckets(size_t nbuckets)
  1478. X{
  1479. X    int    i, j;
  1480. X
  1481. X    for (i = maxtables; i < maxtables + ADDTABLES; i++) {
  1482. X        if ((hashtable[i].bucket = malloc(nbuckets * sizeof(BUCKET)))
  1483. X          == NULL) {
  1484. X            for (j = maxtables; j <= i; j++)
  1485. X                free(hashtable[j].bucket);
  1486. X            return -1;
  1487. X        }
  1488. X        for (j = 0; j < nbuckets; j++)
  1489. X            hashtable[i].bucket[j] = NULL;
  1490. X    }
  1491. X    return 0;
  1492. X}
  1493. X
  1494. Xint
  1495. Xddb_hopen(size_t nbuckets)
  1496. X{
  1497. X    int    i;
  1498. X    HASHTAB    *hashtmp;
  1499. X
  1500. X    if (nbuckets == 0)
  1501. X        nbuckets = NBUCKETS;
  1502. X
  1503. X    for (i = 0; i < maxtables && hashtable[i].used; i++)
  1504. X        ;
  1505. X    if (i == maxtables) {
  1506. X        if ((hashtmp = realloc(hashtable,
  1507. X          (maxtables + ADDTABLES) * sizeof(HASHTAB))) == NULL)
  1508. X            return -1;
  1509. X        hashtable = hashtmp;
  1510. X        if (getbuckets(nbuckets) == -1)
  1511. X            return -1;
  1512. X        maxtables += ADDTABLES;
  1513. X    }
  1514. X
  1515. X    hashtable[i].used = 1;
  1516. X    hashtable[i].nbuckets = nbuckets;
  1517. X
  1518. X    return i;
  1519. X}
  1520. X
  1521. XDATUM *
  1522. Xddb_hnext(int hd)
  1523. X{
  1524. X    HASHTAB    *hp;
  1525. X
  1526. X    if (!validhd(hd))
  1527. X        return NULL;
  1528. X
  1529. X    hp = &hashtable[hd];
  1530. X
  1531. X    if (!hp->lastkey)
  1532. X        return NULL;
  1533. X
  1534. X    if (hp->lastkey = hp->lastkey->next)
  1535. X        return &hp->lastkey->key;
  1536. X
  1537. X    for (hp->which_bucket++; hp->which_bucket < hp->nbuckets;
  1538. X      hp->which_bucket++)
  1539. X        if (hp->lastkey = hp->bucket[hp->which_bucket])
  1540. X            return &hp->lastkey->key;
  1541. X
  1542. X    return NULL;
  1543. X}
  1544. X
  1545. XDATUM *
  1546. Xddb_hfirst(int hd)
  1547. X{
  1548. X    HASHTAB    *hp;
  1549. X
  1550. X    if (!validhd(hd))
  1551. X        return NULL;
  1552. X
  1553. X    hp = &hashtable[hd];
  1554. X
  1555. X    for (hp->which_bucket = 0; hp->which_bucket < hp->nbuckets;
  1556. X      hp->which_bucket++)
  1557. X        if (hp->lastkey = hp->bucket[hp->which_bucket])
  1558. X            return &hp->lastkey->key;
  1559. X
  1560. X    return NULL;
  1561. X}
  1562. X
  1563. X#ifdef DEBUG
  1564. Xstatic void
  1565. Xdef_print(const DATUM *dp)
  1566. X{
  1567. X    printf("%*.*s", dp->size, dp->size, dp->addr);
  1568. X}
  1569. X
  1570. Xvoid
  1571. Xddb_hdump(int hd, void (*kprint)(const DATUM *), void (*dprint)(const DATUM *))
  1572. X{
  1573. X    int        index;
  1574. X    HASHENT        *ptr, *oldptr = NULL;
  1575. X
  1576. X    if (!validhd(hd))
  1577. X        return;
  1578. X
  1579. X    if (kprint == NULL)
  1580. X        kprint = def_print;
  1581. X    if (dprint == NULL)
  1582. X        dprint = def_print;
  1583. X
  1584. X    for (index = 0; index < hashtable[hd].nbuckets; index++)
  1585. X        for (ptr = hashtable[hd].bucket[index]; ptr; ptr = ptr->next) {
  1586. X            printf("key: ");
  1587. X            (*kprint)(&ptr->key);
  1588. X            printf("\tdata: ");
  1589. X            (*dprint)(&ptr->data);
  1590. X            putchar('\n');
  1591. X        }
  1592. X}
  1593. X#endif
  1594. END_OF_FILE
  1595. if test 6175 -ne `wc -c <'ddb/hash.c'`; then
  1596.     echo shar: \"'ddb/hash.c'\" unpacked with wrong size!
  1597. fi
  1598. # end of 'ddb/hash.c'
  1599. fi
  1600. if test -f 'ddb/list.c' -a "${1}" != "-c" ; then 
  1601.   echo shar: Will not clobber existing file \"'ddb/list.c'\"
  1602. else
  1603. echo shar: Extracting \"'ddb/list.c'\" \(4347 characters\)
  1604. sed "s/^X//" >'ddb/list.c' <<'END_OF_FILE'
  1605. X/*
  1606. X *                 Author:  Christopher G. Phillips
  1607. X *              Copyright (C) 1993 All Rights Reserved
  1608. X *
  1609. X *                              NOTICE
  1610. X *
  1611. X * Permission to use, copy, modify, and distribute this software and
  1612. X * its documentation for any purpose and without fee is hereby granted
  1613. X * provided that the above copyright notice appear in all copies and
  1614. X * that both the copyright notice and this permission notice appear in
  1615. X * supporting documentation.
  1616. X *
  1617. X * The author makes no representations about the suitability of this
  1618. X * software for any purpose.  This software is provided ``as is''
  1619. X * without express or implied warranty.
  1620. X */
  1621. X
  1622. X#include <stdio.h>
  1623. X#include <stdlib.h>
  1624. X#include <string.h>
  1625. X#include <sys/types.h>
  1626. X#include <ddb.h>
  1627. X
  1628. Xextern void    *ddb_new(const DATUM *, const DATUM *, size_t);
  1629. Xextern int    ddb_memcmp(const DATUM *, const DATUM *);
  1630. X
  1631. Xtypedef struct lent {
  1632. X    DATUM        key;
  1633. X    DATUM        data;
  1634. X    struct lent    *next;
  1635. X} LELEM;
  1636. Xtypedef struct {
  1637. X    int    used;
  1638. X    LELEM    *head;
  1639. X    LELEM    *nextkey;
  1640. X} LIST;
  1641. X
  1642. Xstatic LIST    *list = NULL;
  1643. Xstatic int    maxlists = 0;
  1644. X
  1645. Xstatic int
  1646. Xvalidld(int ld)
  1647. X{
  1648. X    return list && ld < maxlists && list[ld].used;
  1649. X}
  1650. X
  1651. Xstatic int
  1652. Xvalidmode(int mode)
  1653. X{
  1654. X    switch (mode & DDB_MODE_MASK) {
  1655. X    case DDB_INSERT:
  1656. X    case DDB_REPLACE:
  1657. X    case DDB_DUPLICATE:
  1658. X        return 1;
  1659. X    default:
  1660. X        return 0;
  1661. X    }
  1662. X}
  1663. X
  1664. Xstatic LELEM *
  1665. Xfind(int ld, const DATUM *key, ddb_cmp_t cmp, LELEM **prevp)
  1666. X{
  1667. X    LIST    *lp;
  1668. X    LELEM    *le;
  1669. X    LELEM    *le_prev;
  1670. X    LELEM    *result = NULL;
  1671. X
  1672. X    lp = &list[ld];
  1673. X
  1674. X    for (le_prev = NULL, le = lp->head; le; le_prev = le, le = le->next)
  1675. X        if (key && (*cmp)(key, &le->key) == 0) {
  1676. X            result = le;
  1677. X            break;
  1678. X        }
  1679. X
  1680. X    if (prevp)
  1681. X        *prevp = le_prev;
  1682. X    return result;
  1683. X}
  1684. X
  1685. Xint
  1686. Xddb_lwrite(int ld, const DATUM *key, const DATUM *data, ddb_cmp_t cmp, int mode)
  1687. X{
  1688. X    LIST    *lp;
  1689. X    LELEM    *le;
  1690. X    LELEM    *le_prev;
  1691. X    LELEM    *le_new;
  1692. X
  1693. X    if (!validld(ld) || !validmode(mode)
  1694. X      || (le_new = ddb_new(key, data, sizeof(*le_new))) == NULL)
  1695. X        return -1;
  1696. X
  1697. X    if (cmp == NULL)
  1698. X        cmp = ddb_memcmp;
  1699. X
  1700. X    lp = &list[ld];
  1701. X
  1702. X    if (mode & DDB_DUPLICATE) {
  1703. X        if (mode & DDB_TAIL)
  1704. X            (void)find(ld, NULL, cmp, &le_prev);
  1705. X    } else if (le = find(ld, key, cmp, NULL))
  1706. X        if (mode & DDB_INSERT)
  1707. X            return -1;
  1708. X        else /* DDB_REPLACE */ {
  1709. X            free(le->key.addr);
  1710. X            free(le->data.addr);
  1711. X            le->key = le_new->key;
  1712. X            le->data = le_new->data;
  1713. X            free(le_new);
  1714. X            return 0;
  1715. X        }
  1716. X
  1717. X    if (mode & DDB_TAIL) {
  1718. X        le_new->next = NULL;
  1719. X        if (le_prev)
  1720. X            le_prev->next = le_new;
  1721. X        else
  1722. X            lp->head = le_new;
  1723. X    } else {
  1724. X        le_new->next = lp->head;
  1725. X        lp->head = le_new;
  1726. X    }
  1727. X
  1728. X    return 0;
  1729. X}
  1730. X
  1731. XDATUM *
  1732. Xddb_lread(int ld, const DATUM *key, ddb_cmp_t cmp)
  1733. X{
  1734. X    LIST    *lp;
  1735. X    LELEM    *le;
  1736. X
  1737. X    if (!validld(ld))
  1738. X        return NULL;
  1739. X
  1740. X    if (cmp == NULL)
  1741. X        cmp = ddb_memcmp;
  1742. X
  1743. X    lp = &list[ld];
  1744. X
  1745. X    if (key == NULL)
  1746. X        return lp->head ? &lp->head->data : NULL;
  1747. X
  1748. X    if (le = find(ld, key, cmp, NULL))
  1749. X        return &le->data;
  1750. X
  1751. X    return NULL;
  1752. X}
  1753. X
  1754. Xint
  1755. Xddb_ldelete(int ld, const DATUM *key, ddb_cmp_t cmp)
  1756. X{
  1757. X    LIST    *lp;
  1758. X    LELEM    *le;
  1759. X    LELEM    *le_prev;
  1760. X
  1761. X    if (!validld(ld))
  1762. X        return NULL;
  1763. X
  1764. X    if (cmp == NULL)
  1765. X        cmp = ddb_memcmp;
  1766. X
  1767. X    lp = &list[ld];
  1768. X
  1769. X    if (le = find(ld, key, cmp, &le_prev)) {
  1770. X        if (le_prev)
  1771. X            le_prev->next = le->next;
  1772. X        else
  1773. X            lp->head = le->next;
  1774. X        free(le->key.addr);
  1775. X        free(le->data.addr);
  1776. X        free(le);
  1777. X        return 0;
  1778. X    }
  1779. X
  1780. X    return -1;
  1781. X}
  1782. X
  1783. Xstatic void
  1784. Xinit(int ld)
  1785. X{
  1786. X    list[ld].used = 0;
  1787. X    list[ld].head = list[ld].nextkey = NULL;
  1788. X}
  1789. X
  1790. Xint
  1791. Xddb_lclose(int ld)
  1792. X{
  1793. X    LIST    *lp;
  1794. X    LELEM    *le;
  1795. X
  1796. X    if (!validld(ld))
  1797. X        return -1;
  1798. X
  1799. X    lp = &list[ld];
  1800. X
  1801. X    for (le = lp->head; le; le = le->next) {
  1802. X        free(le->key.addr);
  1803. X        free(le->data.addr);
  1804. X        free(le);
  1805. X    }
  1806. X
  1807. X    init(ld);
  1808. X
  1809. X    return 0;
  1810. X}
  1811. X
  1812. X#define ADDLISTS    1
  1813. X
  1814. Xint
  1815. Xddb_lopen(void)
  1816. X{
  1817. X    int    i;
  1818. X    int    j;
  1819. X    LIST    *ltmp;
  1820. X
  1821. X    for (i = 0; i < maxlists && list[i].used; i++)
  1822. X        ;
  1823. X    if (i == maxlists) {
  1824. X        if ((ltmp = realloc(list,
  1825. X          (maxlists + ADDLISTS) * sizeof(LIST))) == NULL)
  1826. X            return -1;
  1827. X        list = ltmp;
  1828. X        for (j = maxlists; j < maxlists + ADDLISTS; j++)
  1829. X            init(j);
  1830. X        maxlists += ADDLISTS;
  1831. X    }
  1832. X
  1833. X    list[i].used = 1;
  1834. X
  1835. X    return i;
  1836. X}
  1837. X
  1838. XDATUM *
  1839. Xddb_lfirst(int ld)
  1840. X{
  1841. X    LIST    *lp;
  1842. X
  1843. X    if (!validld(ld))
  1844. X        return NULL;
  1845. X
  1846. X    lp = &list[ld];
  1847. X
  1848. X    if (lp->head) {
  1849. X        lp->nextkey = lp->head->next;
  1850. X        return &lp->head->key;
  1851. X    } else {
  1852. X        lp->nextkey = NULL;
  1853. X        return NULL;
  1854. X    }
  1855. X}
  1856. X
  1857. XDATUM *
  1858. Xddb_lnext(int ld)
  1859. X{
  1860. X    LIST    *lp;
  1861. X    LELEM    *le;
  1862. X
  1863. X    if (!validld(ld))
  1864. X        return NULL;
  1865. X
  1866. X    lp = &list[ld];
  1867. X
  1868. X    if (le = lp->nextkey) {
  1869. X        lp->nextkey = lp->nextkey->next;
  1870. X        return &le->data;
  1871. X    } else
  1872. X        return NULL;
  1873. X}
  1874. END_OF_FILE
  1875. if test 4347 -ne `wc -c <'ddb/list.c'`; then
  1876.     echo shar: \"'ddb/list.c'\" unpacked with wrong size!
  1877. fi
  1878. # end of 'ddb/list.c'
  1879. fi
  1880. if test -f 'ddb/new.c' -a "${1}" != "-c" ; then 
  1881.   echo shar: Will not clobber existing file \"'ddb/new.c'\"
  1882. else
  1883. echo shar: Extracting \"'ddb/new.c'\" \(1406 characters\)
  1884. sed "s/^X//" >'ddb/new.c' <<'END_OF_FILE'
  1885. X/*
  1886. X *                 Author:  Christopher G. Phillips
  1887. X *              Copyright (C) 1993 All Rights Reserved
  1888. X *
  1889. X *                              NOTICE
  1890. X *
  1891. X * Permission to use, copy, modify, and distribute this software and
  1892. X * its documentation for any purpose and without fee is hereby granted
  1893. X * provided that the above copyright notice appear in all copies and
  1894. X * that both the copyright notice and this permission notice appear in
  1895. X * supporting documentation.
  1896. X *
  1897. X * The author makes no representations about the suitability of this
  1898. X * software for any purpose.  This software is provided ``as is''
  1899. X * without express or implied warranty.
  1900. X */
  1901. X
  1902. X#include <stdio.h>
  1903. X#include <stdlib.h>
  1904. X#include <sys/types.h>
  1905. X#include <string.h>
  1906. X#include <ddb.h>
  1907. X
  1908. Xvoid *
  1909. Xddb_new(const DATUM *key, const DATUM *data, size_t size)
  1910. X{
  1911. X    DATUM    (*ptr)[2];
  1912. X
  1913. X    if ((ptr = malloc(size)) == NULL
  1914. X      || ((*ptr)[0].addr = malloc(key->size)) == NULL
  1915. X      || (data && ((*ptr)[1].addr = malloc(data->size)) == NULL)) {
  1916. X        if (ptr) {
  1917. X            if ((*ptr)[0].addr) {
  1918. X                free((*ptr)[0].addr);
  1919. X                if (data && (*ptr)[1].addr)
  1920. X                    free((*ptr)[1].addr);
  1921. X            }
  1922. X            free(ptr);
  1923. X        }
  1924. X        return NULL;
  1925. X    }
  1926. X
  1927. X    (void)memcpy((*ptr)[0].addr, key->addr, key->size);
  1928. X    (*ptr)[0].size = key->size;
  1929. X    if (data) {
  1930. X        (void)memcpy((*ptr)[1].addr, data->addr, data->size);
  1931. X        (*ptr)[1].size = data->size;
  1932. X    } else {
  1933. X        (*ptr)[1].addr = NULL;
  1934. X        (*ptr)[1].size = 0;
  1935. X    }
  1936. X
  1937. X    return ptr;
  1938. X}
  1939. END_OF_FILE
  1940. if test 1406 -ne `wc -c <'ddb/new.c'`; then
  1941.     echo shar: \"'ddb/new.c'\" unpacked with wrong size!
  1942. fi
  1943. # end of 'ddb/new.c'
  1944. fi
  1945. if test -f 'ddb/patchlevel.h' -a "${1}" != "-c" ; then 
  1946.   echo shar: Will not clobber existing file \"'ddb/patchlevel.h'\"
  1947. else
  1948. echo shar: Extracting \"'ddb/patchlevel.h'\" \(21 characters\)
  1949. sed "s/^X//" >'ddb/patchlevel.h' <<'END_OF_FILE'
  1950. X#define PATCHLEVEL    0
  1951. END_OF_FILE
  1952. if test 21 -ne `wc -c <'ddb/patchlevel.h'`; then
  1953.     echo shar: \"'ddb/patchlevel.h'\" unpacked with wrong size!
  1954. fi
  1955. # end of 'ddb/patchlevel.h'
  1956. fi
  1957. if test -f 'ddb/queue.c' -a "${1}" != "-c" ; then 
  1958.   echo shar: Will not clobber existing file \"'ddb/queue.c'\"
  1959. else
  1960. echo shar: Extracting \"'ddb/queue.c'\" \(2464 characters\)
  1961. sed "s/^X//" >'ddb/queue.c' <<'END_OF_FILE'
  1962. X/*
  1963. X *                 Author:  Christopher G. Phillips
  1964. X *              Copyright (C) 1993 All Rights Reserved
  1965. X *
  1966. X *                              NOTICE
  1967. X *
  1968. X * Permission to use, copy, modify, and distribute this software and
  1969. X * its documentation for any purpose and without fee is hereby granted
  1970. X * provided that the above copyright notice appear in all copies and
  1971. X * that both the copyright notice and this permission notice appear in
  1972. X * supporting documentation.
  1973. X *
  1974. X * The author makes no representations about the suitability of this
  1975. X * software for any purpose.  This software is provided ``as is''
  1976. X * without express or implied warranty.
  1977. X */
  1978. X
  1979. X#include <stdio.h>
  1980. X#include <stdlib.h>
  1981. X#include <sys/types.h>
  1982. X#include <ddb.h>
  1983. X
  1984. Xtypedef struct qent {
  1985. X    DATUM        data;
  1986. X    struct qent    *next;
  1987. X} QELEM;
  1988. Xtypedef struct {
  1989. X    int    used;
  1990. X    QELEM    *head;
  1991. X    QELEM    *tail;
  1992. X} QUEUE;
  1993. X
  1994. Xstatic QUEUE    *queue = NULL;
  1995. Xstatic int    maxqueues = 0;
  1996. X
  1997. Xextern void    *ddb_new(const DATUM *, const DATUM *, size_t);
  1998. X
  1999. Xstatic int
  2000. Xvalidqd(int qd)
  2001. X{
  2002. X    return queue && qd < maxqueues && queue[qd].used;
  2003. X}
  2004. X
  2005. Xint
  2006. Xddb_qwrite(int qd, const DATUM *data)
  2007. X{
  2008. X    QUEUE    *qp;
  2009. X    QELEM    *qe;
  2010. X
  2011. X    if (!validqd(qd) || (qe = ddb_new(data, NULL, sizeof(*qe))) == NULL)
  2012. X        return -1;
  2013. X
  2014. X    qe->next = NULL;
  2015. X    qp = &queue[qd];
  2016. X
  2017. X    if (qp->tail) {
  2018. X        qp->tail->next = qe;
  2019. X        qp->tail = qe;
  2020. X    } else
  2021. X        qp->head = qp->tail = qe;
  2022. X
  2023. X    return 0;
  2024. X}
  2025. X
  2026. XDATUM *
  2027. Xddb_qread(int qd)
  2028. X{
  2029. X    QUEUE    *qp;
  2030. X    QELEM    *qe;
  2031. X    DATUM    *dp;
  2032. X
  2033. X    if (!validqd(qd))
  2034. X        return NULL;
  2035. X
  2036. X    qp = &queue[qd];
  2037. X
  2038. X    if (qe = qp->head) {
  2039. X        qp->head = qp->head->next;
  2040. X        if (qp->tail == qe)
  2041. X            qp->tail = NULL;
  2042. X        if ((dp = malloc(sizeof(*dp))) == NULL)
  2043. X            return NULL;
  2044. X        *dp = qe->data;
  2045. X        free(qe);
  2046. X        return dp;
  2047. X    } else
  2048. X        return NULL;
  2049. X}
  2050. X
  2051. Xint
  2052. Xddb_qclose(int qd)
  2053. X{
  2054. X    QELEM    *qp;
  2055. X    QELEM    *next;
  2056. X
  2057. X    if (!validqd(qd))
  2058. X        return -1;
  2059. X
  2060. X    if (qp = queue[qd].head)
  2061. X        while (1) {
  2062. X            free(qp->data.addr);
  2063. X            next = qp->next;
  2064. X            free(qp);
  2065. X            if (qp == queue[qd].tail)
  2066. X                break;
  2067. X            qp = next;
  2068. X        }
  2069. X
  2070. X    queue[qd].used = 0;
  2071. X    queue[qd].head = queue[qd].tail = NULL;
  2072. X
  2073. X    return 0;
  2074. X}
  2075. X
  2076. X#define ADDQUEUES    1
  2077. X
  2078. Xint
  2079. Xddb_qopen(void)
  2080. X{
  2081. X    int    i;
  2082. X    int    j;
  2083. X    QUEUE    *qtmp;
  2084. X
  2085. X    for (i = 0; i < maxqueues && queue[i].used; i++)
  2086. X        ;
  2087. X    if (i == maxqueues) {
  2088. X        if ((qtmp = realloc(queue,
  2089. X          (maxqueues + ADDQUEUES) * sizeof(QUEUE))) == NULL)
  2090. X            return -1;
  2091. X        queue = qtmp;
  2092. X        for (j = maxqueues; j < maxqueues + ADDQUEUES; j++) {
  2093. X            queue[j].used = 0;
  2094. X            queue[j].head = queue[j].tail = NULL;
  2095. X        }
  2096. X        maxqueues += ADDQUEUES;
  2097. X    }
  2098. X
  2099. X    queue[i].used = 1;
  2100. X
  2101. X    return i;
  2102. X}
  2103. END_OF_FILE
  2104. if test 2464 -ne `wc -c <'ddb/queue.c'`; then
  2105.     echo shar: \"'ddb/queue.c'\" unpacked with wrong size!
  2106. fi
  2107. # end of 'ddb/queue.c'
  2108. fi
  2109. if test -f 'ddb/stack.c' -a "${1}" != "-c" ; then 
  2110.   echo shar: Will not clobber existing file \"'ddb/stack.c'\"
  2111. else
  2112. echo shar: Extracting \"'ddb/stack.c'\" \(2548 characters\)
  2113. sed "s/^X//" >'ddb/stack.c' <<'END_OF_FILE'
  2114. X/*
  2115. X *                 Author:  Christopher G. Phillips
  2116. X *              Copyright (C) 1993 All Rights Reserved
  2117. X *
  2118. X *                              NOTICE
  2119. X *
  2120. X * Permission to use, copy, modify, and distribute this software and
  2121. X * its documentation for any purpose and without fee is hereby granted
  2122. X * provided that the above copyright notice appear in all copies and
  2123. X * that both the copyright notice and this permission notice appear in
  2124. X * supporting documentation.
  2125. X *
  2126. X * The author makes no representations about the suitability of this
  2127. X * software for any purpose.  This software is provided ``as is''
  2128. X * without express or implied warranty.
  2129. X */
  2130. X
  2131. X#include <stdio.h>
  2132. X#include <stdlib.h>
  2133. X#include <sys/types.h>
  2134. X#include <ddb.h>
  2135. X
  2136. Xtypedef struct {
  2137. X    int    used;
  2138. X    DATUM    **stack;
  2139. X    long    top;        /* -1 implies empty */
  2140. X} STACK;
  2141. X
  2142. Xstatic STACK    *stack = NULL;
  2143. Xstatic int    maxstacks = 0;
  2144. X
  2145. Xextern void    *ddb_new(const DATUM *, const DATUM *, size_t);
  2146. X
  2147. Xstatic int
  2148. Xvalidsd(int sd)
  2149. X{
  2150. X    return stack && sd < maxstacks && stack[sd].used;
  2151. X}
  2152. X
  2153. Xint
  2154. Xddb_swrite(int sd, const DATUM *data)
  2155. X{
  2156. X    STACK    *sp;
  2157. X    DATUM    **stmp;
  2158. X    DATUM    *dp;
  2159. X
  2160. X    sp = &stack[sd];
  2161. X    if (!validsd(sd) || (dp = ddb_new(data, NULL, sizeof(*dp))) == NULL
  2162. X      || (stmp = realloc(sp->stack, (sp->top + 2) * sizeof(*sp->stack)))
  2163. X      == NULL)
  2164. X        return -1;
  2165. X
  2166. X    sp->stack = stmp;
  2167. X    sp->stack[++sp->top] = dp;
  2168. X
  2169. X    return 0;
  2170. X}
  2171. X
  2172. XDATUM *
  2173. Xddb_sread(int sd)
  2174. X{
  2175. X    STACK    *sp;
  2176. X
  2177. X    if (!validsd(sd))
  2178. X        return NULL;
  2179. X
  2180. X    sp = &stack[sd];
  2181. X
  2182. X    if (sp->top >= 0)
  2183. X        return sp->stack[sp->top--];
  2184. X    else
  2185. X        return NULL;
  2186. X}
  2187. X
  2188. Xint
  2189. Xddb_sclose(int sd)
  2190. X{
  2191. X    long    i;
  2192. X
  2193. X    if (!validsd(sd))
  2194. X        return -1;
  2195. X
  2196. X    for (i = 0; i <= stack[sd].top; i++) {
  2197. X        free(stack[sd].stack[i]->addr);
  2198. X        free(stack[sd].stack[i]);
  2199. X    }
  2200. X    free(stack[sd].stack);
  2201. X
  2202. X    stack[sd].used = 0;
  2203. X    stack[sd].stack = NULL;
  2204. X
  2205. X    return 0;
  2206. X}
  2207. X
  2208. X#define ADDSTACKS    1
  2209. X
  2210. Xint
  2211. Xddb_sopen(void)
  2212. X{
  2213. X    int    i;
  2214. X    int    j;
  2215. X    STACK    *stmp;
  2216. X
  2217. X    for (i = 0; i < maxstacks && stack[i].used; i++)
  2218. X        ;
  2219. X    if (i == maxstacks) {
  2220. X        if ((stmp = realloc(stack,
  2221. X          (maxstacks + ADDSTACKS) * sizeof(STACK))) == NULL)
  2222. X            return -1;
  2223. X        stack = stmp;
  2224. X        for (j = maxstacks; j < maxstacks + ADDSTACKS; j++) {
  2225. X            stack[j].used = 0;
  2226. X            stack[j].top = -1;
  2227. X            stack[j].stack = NULL;
  2228. X        }
  2229. X        maxstacks += ADDSTACKS;
  2230. X    }
  2231. X
  2232. X    stack[i].used = 1;
  2233. X
  2234. X    return i;
  2235. X}
  2236. X
  2237. X#ifdef DEBUG
  2238. Xvoid
  2239. Xddb_sdump(int sd)
  2240. X{
  2241. X    STACK    *sp;
  2242. X    long    i;
  2243. X
  2244. X    sp = &stack[sd];
  2245. X    if (validsd(sd)) {
  2246. X        if (sp->top < 0)
  2247. X            printf("empty\n");
  2248. X        for (i = sp->top; i >= 0; i--)
  2249. X            printf("%d: %p, %ld (%ld)\n", i, sp->stack[i]->addr,
  2250. X              (long)sp->stack[i]->size,
  2251. X              (long)*(unsigned *)sp->stack[i]->addr);
  2252. X    }
  2253. X}
  2254. X#endif
  2255. END_OF_FILE
  2256. if test 2548 -ne `wc -c <'ddb/stack.c'`; then
  2257.     echo shar: \"'ddb/stack.c'\" unpacked with wrong size!
  2258. fi
  2259. # end of 'ddb/stack.c'
  2260. fi
  2261. echo shar: End of shell archive.
  2262. exit 0
  2263.  
  2264. exit 0 # Just in case...
  2265.