home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / libtex / search.c < prev    next >
C/C++ Source or Header  |  1990-07-10  |  5KB  |  181 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/search.c,v 3.1 89/08/22 21:58:14 chris Exp $";
  10. #endif
  11.  
  12. /*
  13.  * Key search routines (for a 32 bit key)
  14.  *
  15.  * SCreate initializes the search control area.
  16.  *
  17.  * SSearch returns the address of the data area (if found or created)
  18.  * or a null pointer (if not).  The last argument controls the disposition
  19.  * in various cases, and is a ``value-result'' parameter.
  20.  *
  21.  * SEnumerate calls the given function on each data object within the
  22.  * search table.  Note that no ordering is specified (though currently
  23.  * it runs in increasing-key-value sequence).
  24.  */
  25.  
  26. #include "types.h"
  27. #include "search.h"
  28.  
  29. #if vax || mc68000 || ns32000 || pyr
  30. #define    HARD_ALIGNMENT    4
  31. #else
  32. #define    HARD_ALIGNMENT    16    /* should suffice for most everyone */
  33. #endif
  34.  
  35. static int DOffset;        /* part of alignment code */
  36.  
  37. char    *malloc(), *realloc();
  38.  
  39. struct search *
  40. SCreate(dsize)
  41.     register unsigned int dsize;
  42. {
  43.     register struct search *s;
  44.  
  45.     if ((s = (struct search *) malloc(sizeof *s)) == 0)
  46.         return (0);
  47.  
  48.     if (DOffset == 0) {
  49. #ifndef HARD_ALIGNMENT
  50.         DOffset = sizeof(i32);
  51. #else
  52.         DOffset = (sizeof(i32) + HARD_ALIGNMENT - 1) &
  53.             ~(HARD_ALIGNMENT - 1);
  54. #endif
  55.     }
  56.     dsize += DOffset;    /* tack on space for keys */
  57.  
  58. #ifdef HARD_ALIGNMENT
  59.     /*
  60.      * For machines with strict alignment constraints, it may be
  61.      * necessary to align the data at a multiple of some positive power
  62.      * of two.  In general, it would suffice to make dsize a power of
  63.      * two, but this could be very space-wasteful, so instead we align it
  64.      * to HARD_ALIGNMENT.  64 bit machines might ``#define HARD_ALIGNMENT
  65.      * 8'', for example.  N.B.:  we assume that HARD_ALIGNMENT is a power
  66.      * of two.
  67.      */
  68.  
  69.     dsize = (dsize + HARD_ALIGNMENT - 1) & ~(HARD_ALIGNMENT - 1);
  70. #endif
  71.  
  72.     s->s_dsize = dsize;    /* save data object size */
  73.     s->s_space = 10;    /* initially, room for 10 objects */
  74.     s->s_n = 0;        /* and none in the table */
  75.     if ((s->s_data = malloc(s->s_space * dsize)) == 0) {
  76.         free((char *)s);
  77.         return (0);
  78.     }
  79.     return (s);
  80. }
  81.  
  82. /*
  83.  * We actually use a binary search right now - this may change.
  84.  */
  85. char *
  86. SSearch(s, key, disp)
  87.     register struct search *s;
  88.     register i32 key;
  89.     int *disp;
  90. {
  91.     register char *keyaddr;
  92.     int itemstomove;
  93.  
  94.     *disp &= S_CREATE | S_EXCL;    /* clear return codes */
  95.     if (s->s_n) {        /* look for the key */
  96.         register int h, l, m;
  97.  
  98.         h = s->s_n - 1;
  99.         l = 0;
  100.         while (l <= h) {
  101.             m = (l + h) >> 1;
  102.             keyaddr = s->s_data + m * s->s_dsize;
  103.             if (*(i32 *) keyaddr > key)
  104.                 h = m - 1;
  105.             else if (*(i32 *) keyaddr < key)
  106.                 l = m + 1;
  107.             else {    /* found it, now what? */
  108.                 if (*disp & S_EXCL) {
  109.                     *disp |= S_COLL;
  110.                     return (0);    /* collision */
  111.                 }
  112.                 *disp |= S_FOUND;
  113.                 return (keyaddr + DOffset);
  114.             }
  115.         }
  116.         keyaddr = s->s_data + l * s->s_dsize;
  117.     } else
  118.         keyaddr = s->s_data;
  119.  
  120.     /* keyaddr is now where the key should have been found, if anywhere */
  121.     if ((*disp & S_CREATE) == 0)
  122.         return (0);    /* not found */
  123.  
  124.     /* avoid using realloc so as to retain old data if out of memory */
  125.     if (s->s_space <= 0) {    /* must expand; double it */
  126.         register char *new;
  127.  
  128.         if ((new = malloc((s->s_n << 1) * s->s_dsize)) == 0) {
  129.             *disp |= S_ERROR;    /* no space */
  130.             return (0);
  131.         }
  132.         keyaddr = (keyaddr - s->s_data) + new;    /* relocate */
  133.         bcopy(s->s_data, new, s->s_n * s->s_dsize);
  134.         free(s->s_data);
  135.         s->s_data = new;
  136.         s->s_space = s->s_n;
  137.     }
  138.     /* now move any keyed data that is beyond keyaddr down */
  139.     itemstomove = s->s_n - (keyaddr - s->s_data) / s->s_dsize;
  140.     if (itemstomove) {
  141. #ifndef BLOCK_COPY
  142.         register char *from, *to;
  143.  
  144.         from = s->s_data + s->s_n * s->s_dsize;
  145.         to = from + s->s_dsize;
  146.         while (from > keyaddr)
  147.             *--to = *--from;
  148. #else
  149.         BLOCK_COPY(keyaddr, keyaddr + s->s_dsize,
  150.             itemstomove * s->s_dsize);
  151. #endif
  152.     }
  153.     *disp |= S_NEW;
  154.     s->s_n++;
  155.     s->s_space--;
  156.     *(i32 *) keyaddr = key;
  157.     keyaddr += DOffset;    /* now actually dataaddr */
  158.     /* the bzero is just a frill... */
  159.     bzero(keyaddr, s->s_dsize - DOffset);
  160.     return (keyaddr);
  161. }
  162.  
  163. /*
  164.  * Call function `f' for each element in the search table `s'.
  165.  */
  166. void
  167. SEnumerate(s, f)
  168.     register struct search *s;
  169.     register void (*f)();
  170. {
  171.     register int n;
  172.     register char *p;
  173.  
  174.     n = s->s_n;
  175.     p = s->s_data;
  176.     while (--n >= 0) {
  177.         (*f)(p + DOffset, *(i32 *)p);
  178.         p += s->s_dsize;
  179.     }
  180. }
  181.