[comp.sources.misc] v16i003: mbase - C database engine, Part02/03

kent@sparky.IMD.Sterling.COM (Kent Landfield) (01/03/91)

Submitted-by: rpj@pygmy.rice.edu (Richard Parvin Jernigan)
Posting-number: Volume 16, Issue 3
Archive-name: mbase/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  build.c mbase.c sample.c
# Wrapped by rpj@pygmy on Mon Dec 17 19:54:41 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'build.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'build.c'\"
else
echo shar: Extracting \"'build.c'\" \(10221 characters\)
sed "s/^X//" >'build.c' <<'END_OF_FILE'
X#include "stdinc.h"
X
X#define cr(x) ((x) == 0) ? "\n\n" : "\n"
X
Xstatic char *justword[] = { "L-just", "R-just" };
X
Xchar *word (fle)
Xint         fle;
X{
X   int         i;
X   char        a[2];
X   static char buffer [81];
X
X   i = 0;
X
X   while (read (fle, a, 1) == 1)
X    {
X      if (a[0] == ' ' || a[0] == '\n')
X       { if (i != 0)
X            break;
X       }
X      else
X         buffer[i++] = a[0];
X    };
X
X   buffer [i] = 0;
X
X   return buffer;
X}
X
Xchar *repeat (ch, nm)
Xint           ch, nm;
X{
X   char  buf [MAX_RPT];
X
X   buf[(nm = (nm < 0) ? 0 : nm)] = 0;
X
X   for (nm--; nm >= 0; nm--)  buf[nm] = ch;
X
X   return buf;
X}
X
Xpattern (whole,  match, skip)
Xchar    *whole, *match;
Xint                     skip;
X{
X   int  i, j, m, w;
X
X   m = strlen (match);  w = strlen (whole);
X
X   for (i = 0; i <= w-m; i++)
X    {
X      for (j = 0; match [j] != 0 && whole[i+j] == match[j]; j++)
X       ;
X
X      if (match[j] == 0)  if (skip-- == 0)  return i;
X    };
X
X   return -1;
X}
X
X/*  Encode and Eval perform base 10 to base 255 conversion, with a bottom
X    value of 1 (As opposed to 0) for the base-255 numbers.  Perfect for
X    encoding BIG numbers (See chart) and storing them in 5 bytes on disk, eh?
X
X    # of characters used______________Maximum integer representable
X    1                                          254
X    2                                        65024
X    3                                     16581374
X    4                                   4228250624
X    5                                 107820390900.... etc.                  */
X
Xlong _eval (st, x)
Xchar       *st;
Xint             x;
X{
X   long int  j;
X   long int  n;
X   int       a;
X
X   j = 0;  n = 1;
X
X   while (x > 0) { a = st[--x];  a = fix (a);  j += n * (a - 1);  n *= 255; };
X
X   return j;
X}
X
Xchar *_encode (num, len)
Xlong int       num;
Xint                 len;
X{
X   register int  i;
X            int  a;
X   static   char buf[10];
X
X   len = (len < 9) ? len : 9;
X
X   for (i = len-1; i >= 0; i--)
X    { a = num % 255;
X
X      num = (num - a) / 255;
X
X      buf[i] = a + 1;
X    };
X
X   buf[len] = 0;
X
X   return buf;
X}
X
Xmain  (argc, argv)
Xint    argc;
Xchar **argv;
X{
X   char   flds[384], lens[384], idxs[20][50];
X   char   rel[80],   temp[80],  tmp2[80];
X   int    stage,     column,    num_i,         num_f,    R;
X   int    n,     i,  fle,       st,    dups,   s,        r_len,   isright;
X
X   if (argc != 2)
X    { printf ("%s: Format = '%s%s%s schema.s'\n", argv[0], BOLD, argv[0], NORM);
X      exit   (1);
X    };
X
X   n = strlen (argv[1]);
X   if (argv[1][n-1] != 's' || argv[1][n-2] != '.')  strcat (argv[1], ".s");
X
X   sprintf (flds, "|");  sprintf (rel, "%s", argv[1]);  sprintf (lens, "");
X
X   for (i = strlen(argv[1])-1; i > -1 && argv[1][i] != ':'
X                                      && argv[1][i] != '/'; i--);
X
X   r_len = rel[i+1] = 0;
X
X   if ((fle = open (argv[1], O_RDONLY)) == -1)
X    { fprintf (stderr, "\nCannot open %s%s%s.\n", BOLD, argv[1], NORM);
X      exit    (1);
X    };
X
X   skip (fle, "relation");
X
X   sprintf (temp, "%s", word (fle));
X
X   if (strlen (temp) == 0)
X    { fprintf (stderr, "\nFile %s%s%s holds no schema definition.\n",
X                       BOLD, argv[1], NORM);
X      exit    (1);
X    };
X
X   printf ("%s", CLS);
X   printf ("Building relation %s%s%s", BOLD, temp, NORM);
X
X   if (rel[0] != 0)
X      printf (" under directory %s%s%s\n\n", BOLD, rel, NORM);
X   else
X      printf (" under current directory\n\n");
X
X   sprintf (rel, "%s%s.rel", rel, temp);
X
X   num_f  = num_i = 0;
X   column = stage = 1;
X
X   printf ("%s%-60.60s%s\n", UNDR, "Fields", NORM);
X
X   do
X    { sprintf (temp, "%s", word (fle));
X
X      if (strcmp (temp, "field") == 0)
X       { if (stage == 2)
X          { fprintf (stderr, "%sField %s%s%s declared after indicies.\n",
X                     cr (column), BOLD, word (fle), NORM);
X            exit    (1);
X          };
X
X         sprintf (temp, "%s", word (fle));
X
X         if (temp [strlen(temp)-1] == '|')  temp[strlen(temp)-1] = 0;
X
X         sprintf (tmp2, "|%s|", temp);
X
X         if (pattern (flds, tmp2, 0) != -1)
X          { fprintf (stderr, "%sField %s%s%s declared twice.\n",
X                     cr (column), BOLD, temp, NORM);
X            exit    (1);
X          };
X
X         strcat  (flds, temp);  strcat  (flds, "|");
X
X         skip    (fle, "length");
X
X         sprintf (tmp2, "%03s", word (fle));
X
X         strcat  (lens, tmp2);
X
X         if ((isright = skip (fle, "right")) == 1)
X            strcat (lens, "r|");
X         else
X          { strcat (lens, "l|");
X            skip   (fle,  "left");
X          };
X
X         r_len += atoi (tmp2) + 1;
X
X         sprintf (temp, "%s [%d] %s", temp, atoi (tmp2), justword[isright]);
X
X         if ((column = 1-column) == 0)
X            printf ("%s%-30.30s%s", SUBD, temp, NORM);
X         else
X            printf ("%s%s%s\n",     SUBD, temp, NORM);
X
X         num_f ++;
X
X         if (skip (fle, ";") == 1)
X          { do     sprintf (temp, "%s", word (fle));
X            until (strcmp (temp, ";") == 0 || temp[0] == 0);
X
X            if (temp[0] == 0)
X             { printf ("%s", cr (column));
X               endoffile (num_f, num_i);
X               stage = 3;
X             };
X          };
X       }
X      else
X         if (strcmp (temp, "index") == 0)
X          {
X            if (stage == 1)
X             { if (column == 0)  printf ("\n");
X
X               if (num_f == 0)
X                { fprintf (stderr, "\nNo fields declared before indicies.\n");
X                  exit    (1);
X                };
X
X               printf ("\n%s%-60.60s%s\n", UNDR, "Indicies", NORM);
X
X               stage  = 2;
X               column = 1;
X             };
X
X            skip (fle, "on");
X
X            sprintf (temp, "%s", word (fle));
X
X            if (temp[strlen(temp)-1] == '|')  temp[strlen(temp)-1] = 0;
X
X            printf  ("%s%s%s%s", SUBD, temp, NORM,
X                                       repeat ('.', 36-strlen (temp)));
X            dups = 0;
X
X            if (skip (fle, "with") == 1)
X             { if (skip (fle, "duplicates") == 0)
X                { fprintf (stderr, "?\n\nIncorrect syntax\n");
X                  exit    (1);
X                }
X               else
X                { printf  ("Duplicates allowed\n");
X                  dups = 1;
X                };
X             }
X            else
X               printf ("Duplicates not allowed\n");
X
X            strcat  (temp, "|");  sprintf (tmp2, "%s", "");
X
X            s = idxs[num_i][0] = 0;
X
X            while (temp[s] != 0)
X             { for (i = s, tmp2[0] = '|'; temp[i] != '|'; i++)
X                  tmp2 [i-s+1] = temp [i];
X
X               tmp2[i-s+1] = '|';  tmp2[i-s+2] = 0; s = i+1;
X
X               if ((i = pattern (flds, tmp2, 0)) == -1)
X                {
X                  sprintf (temp, "%s", &tmp2[1]);  temp[strlen(temp)-1] = 0;
X
X                  fprintf (stderr, "\nField %s%s%s undefined\n", BOLD,
X                           temp, NORM);
X                  exit    (1);
X                };
X
X               for (st = 0, i++; i >= 0; i--)  if (flds[i] == '|')  st++;
X
X               sprintf (tmp2, "%03d|", st);
X               strcat  (idxs[num_i], tmp2);
X             };
X
X            if (dups == 1)  strcat (idxs[num_i], "d");
X
X            num_i ++;
X
X            if (skip (fle, ";") == 1)
X             { do     sprintf (temp, "%s", word (fle));
X               until (strcmp (temp, ";") == 0 || temp[0] == 0);
X
X               if (temp[0] == 0)
X                { printf ("%s", cr (column));
X                  endoffile (num_f, num_i);
X                  stage = 3;
X                };
X             };
X          }
X         else
X            if (strcmp (temp, "end") == 0 || temp[0] == 0)
X             { printf ("%s", cr (column));
X               endoffile (num_f, num_i);
X               stage = 3;
X             }
X            else
X             { fprintf (stderr, "%sIdentifier %s%s%s not recognized.\n",
X                                cr (column), BOLD, temp, NORM);
X               exit    (1);
X             };
X
X    } while (stage != 3);
X
X   R = open (rel, O_RDWR);
X
X   if (R != -1)
X    { if (read (R, temp, 1) != -1)
X         if (temp[0] != 1)
X          { fprintf (stderr, "\n%s%s%32.32s%-28.28s%s\n", SUBD, INVR,
X                             "*** ERR", "OR ***", NORM);
X            fprintf (stderr, "\n   This relation is busy.  It cannot be");
X            fprintf (stderr, " built during use.\n\n");
X
X            close (R);  exit (1);
X          };
X
X      printf ("%s%s%32.32s%-28.28s%s\n", SUBD, INVR, "** WARN", "ING **", NORM);
X      printf ("\n   The file about to be created already exists under the\n");
X      printf ("         target directory!  This data will be lost!\n\n");
X
X      close (R);
X    };
X
X   printf ("Continue with the creation of the relation [Y/n] ? ");
X
X   i = getchar ();
X
X   printf ("\n");
X
X   if (i == 'n' || i == 'N' || i == 'q' || i == 'Q')  exit (0);
X
X   remove (rel);
X
X   if ((R = open (rel, O_RDWR | O_CREAT)) == -1)
X    { fprintf (stderr, "\n\nCannot open relation -- Aborted\n");
X      exit    (-1);
X    };
X
X#ifdef UNIX
X   sprintf (temp, "chmod 755 %s", rel);
X   system  (temp);
X#endif
X
X   write (R, _encode (0,     1), 1);
X   write (R, _encode (num_i, 1), 1);
X   write (R, _encode (r_len, 2), 2);
X
X   for (i = 0; i < num_i; i++)  write (R, _encode (0, 4), 4);
X
X   write (R, ".\001\001\001\001.\n", 7);
X
X   write (R, lens, strlen(lens));    write (R, "\n", 1);
X
X   for (i = 0; i < num_i; i++)
X    { write (R, idxs[i], strlen (idxs[i]));  write (R, "\n", 1);
X    };
X
X   close (R);
X
X   printf ("Relation created -- zero entries.\n");
X}
X
Xskip (f, s)  /* 0 means didn't skip the word, 1 means we did. */
Xint   f;
Xchar    *s;
X{
X   int   i;
X   char  a[2];
X
X   i = 0;
X
X   while (s[i] != 0)
X    {
X      if (read (f, a, 1) != 1)  return -1;
X
X      if (i != 0 || (i == 0 && a[0] != ' ' && a[0] != '\n'))
X       { if (s[i] != a[0])
X          { lseek (f, -1, 1);
X            break;
X          }
X         else
X            i++;
X       };
X    }
X
X   if (s[i] == 0)  return 1;
X
X   return 0;
X}
X
Xendoffile (num_f, num_i)
Xint            num_f, num_i;
X{
X   if (num_f == 0)
X    { fprintf (stderr, "No fields declared before end reached\n");
X      exit    (1);
X    };
X   if (num_i == 0)
X    { fprintf (stderr, "No indicies declared before end reached\n");
X      exit    (1);
X    };
X}
X
END_OF_FILE
if test 10221 -ne `wc -c <'build.c'`; then
    echo shar: \"'build.c'\" unpacked with wrong size!
fi
chmod +x 'build.c'
# end of 'build.c'
fi
if test -f 'mbase.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mbase.c'\"
else
echo shar: Extracting \"'mbase.c'\" \(29825 characters\)
sed "s/^X//" >'mbase.c' <<'END_OF_FILE'
X/*   ********************************************************************   *
X  ***                                                    unix compatible ***
X *    MetalBase 3.0.....................................................    *
X *                                                                          *
X *    Multi-user simultaneous use of relations (On multi-user hardware)     *
X *    Users may have many relations open at once, even the same one!        *
X *    Unlimited length records (Really!  Just redefine BUF_LEN!)            *
X *    Up to 20 indicies per relation, 5 fields max per composite index      *
X *    Up to 4.2 billion records per relation                                *
X *    Bizzare intermittent bugs, just like the expensive programs           *
X *    And, unless they're weird, your kids will eat it                      *
X *                                                               /\         *
X *    Written starting August 1989, by Huan-Ti               rj /  \        *
X *                                                             /    \       *
X *   "Ye hath mushrooms for $1.99 a pound.  Ye art             \    /       *
X *    truly a Calvinist."                                       \  / tp     *
X *                       -- II Calvin 7:1                        \/         *
X *                                                                          *
X *          713/630-8962 <-----= May 26, 1996 =-----> 615/494-0220          *
X  ***                                                                    ***
X *   ********************************************************************   */
X
X#include "stdinc.h"
X
X#define BUF_LEN 256       /* Record_length + 13*number_of_indicies          */
X#define MAX_REL 5         /* For this user.  DOES NOT CHANGE STDIO'S # !    */
X#define MAX_FLDS 30       /* Fields/rel. If you need more than 30, redefine */
X
X#define OKAY                  0   /* Generic no-problem number.  Thank IBM. */
X#define NOT_ENOUGH_ROOM   -1000   /* Too many files are open at once        */
X#define CANNOT_OPEN_REL   -1001   /* Can't open FILE.REL                    */
X#define RELATION_HUNG     -1002   /* User left during add/del/upd.  See dox */
X#define CANNOT_READ_REL   -1003   /* FILE.REL is protected (Need rw access) */
X#define RELATION_BUSY     -1004   /* 120 users on one relation=max (Hah!)   */
X#define RELATION_LOCKED   -1005   /* Someone has locked the relation        */
X#define LOCK_DENIED       -1006   /* Can't lock with other users.  See dox  */
X#define ILLEGAL_DUPLICATE -1007   /* Record would violate a nodups index    */
X#define CORRUPT_INDEX     -1008   /* Means you're fucked.  Probly not used  */
X#define INVALID_FILE_CODE -1009   /* You've passed an unreal relation numb  */
X#define NOT_OPEN          -1010   /* You've tried to work with a closed rel */
X#define RCD_INVALID       -1011   /* Bad-size or # of flds given to add/upd */
X#define INVALID_COMP      -1012   /* SELECT's record for comparison is bad  */
X#define UNKNOWN_ACTION    -1013   /* You'll probly never get this one.      */
X#define NOT_FOUND         -1014   /* Generic.  Can't find the record U want */
X#define NO_CURRENT_RECORD -1015   /* Must select a record before del/upd    */
X#define INVALID_INDEX     -1016   /* A bad index # has been sent to mb_sel  */
X
X#define CURR                  1   /* Re-read the current record (4 mb_sel)  */
X#define EQUL                  2   /* Get rec that matches exactly (see dox) */
X#define FRST                  3   /* Get the first record, sequentially     */
X#define GTEQ                  4   /* If not exact, get the one right after  */
X#define GTHN                  5   /* Like GTEQ, but won't accept exact one  */
X#define LAST                  6   /* Get the last record, sequentially      */
X#define LTEQ                  7   /* If not exact, get the one right before */
X#define LTHN                  8   /* Like LTEQ, but won't accept exact one  */
X#define NEXT                  9   /* Get the next record, sequentially      */
X#define PREV                 10   /* Get the previous record, sequentially  */
X
X#define CURRENT            CURR   /* These are included to reduce errors    */
X#define EQUAL              EQUL   /* due to stupid humans who insist on     */
X#define FIRST              FRST   /* using long words instead of short ones */
X#define GTHAN              GTHN   /*                                        */
X#define LTHAN              LTHN   /* Gee, I'm considerate.                  */
X#define PREVIOUS           PREV   /*                                        */
X
X#define ZEROES "\001\001\001\001\001\001\001\001\001\001\001\001."
X
X/****************************************************************************/
X/*                                                                          */
X/* A reminder of the single rule that applies to EVERYTHING in this file:   */
X/*                                                                          */
X/* If you don't understand it, DON'T SCREW WITH IT.                         */
X/*                                                                          */
X/* I'd like to emphasize that this rule is _most_important_ in viewing the  */
X/* follow section of definitions.  If you wanna change the internal         */
X/* structure of the relations, and think you can (successfully, that is),   */
X/* go right ahead.  And send me a copy of the "better" MetalBase when you   */
X/* think you're finished... I'd like to see it.  (smiley-face)              */
X/*                                                                          */
X/****************************************************************************/
X
X#define _t_top(f,i)    4 +  4*i
X#define _idxs(f)           13*(_list[f].num_idx)
X#define _num_recs(f)   5 +  4*(_list[f].num_idx)
X
X#define _block(f)      11+(4*_list[f].num_idx)
X#define _base(f,r)     _block(f)+_list[f].relbase+(r-1)*((13*_list[f].num_idx)+\
X                          2+(_list[f].rec_len))
X#define _l_ptr(f,i,r)  _base  (f, r)    + 13*i
X#define _r_ptr(f,i,r)  _l_ptr (f, i, r) +  4
X#define _b_ptr(f,i,r)  _r_ptr (f, i, r) +  4
X#define _rec(f,r)      _base  (f, r)    + (13*_list[f].num_idx) + 1
X
X#define _len(f)        2 + _idxs (f) + _list[f].rec_len
X
Xchar   buffer [BUF_LEN];
X
Xextern int  _Started;
X
Xstruct
X { long  int   pos,      relbase;
X         int   relcode;
X         int   num_idx,  rec_len;
X         char  alpha,    beta,     gamma;
X
X         int   idx_dups  [20];
X         int   idx_just  [MAX_FLDS];
X         int   idx_num   [20][6];
X         int   idx_start [20][6];
X         int   idx_stop  [20][5];
X
X         char  filename  [80];     } _list [MAX_REL];
X
X/****************************************************************************/
X
X#define hash(a,o,g) ((a + o) & g)
X
Xvoid breakkey (n, key)
Xint            n;
Xint               key;
X{
X   _list[n].alpha = (key &  48) >> 4;
X   _list[n].beta  = (key &  63);
X   _list[n].gamma = (key & 192) >> 6;
X}
X
Xvoid _encrypt (temp, n)
Xchar          *temp;
Xint                  n;
X{
X   register int len;
X   char         old;
X
X   for (len = 0, old=_list[n].beta; temp[len] != 0; len++)
X      old = temp[len] = 127 - temp[len] ^ hash (_list[n].alpha, old, _list[n].gamma);
X}
X
Xvoid _decrypt (temp, n)
Xchar          *temp;
Xint                  n;
X{
X   register int len;
X   char         old, oold;
X
X   for (len = 0, old=_list[n].beta; temp[len] != 0; len++, old=oold)
X      temp[len] = (127 - (oold = temp[len])) ^ hash (_list[n].alpha, old, _list[n].gamma);
X}
X
X_diff   (one,  two, use_sp, num)
Xchar    *one, *two;
Xint                 use_sp, num;
X{
X   register int  i;
X   char          lold, rold, l, r;
X   int           x, sp, vl, a, g;
X
X   a           = _list[num].alpha;
X   lold = rold = _list[num].beta;
X   g           = _list[num].gamma;
X
X   x = 0;
X
X   do
X    { vl = 0;  sp = 1-use_sp;
X
X      for (i = x; one[i] != 0 && one[i] != '|'; i++)
X       { if (use_sp == 1 && one[i] != ' ')  sp = 1;
X 
X         if (vl == 0)
X          { l = (127 - (lold = one[i])) ^ hash (a, lold, g);
X            r = (127 - (rold = two[i])) ^ hash (a, rold, g);
X
X            if (l > r)  vl = -1;
X            if (l < r)  vl =  1;
X          };
X
X         if (one[i] == '|')  lold = rold = _list[num].beta;
X       };
X
X      if (sp != 0 && vl != 0)  return vl;
X
X      x = i+1;
X    } while (one[i] != 0);
X
X   return 0;
X}
X
X/****************************************************************************/
X
Xchar *repeat (ch, nm)
Xint           ch, nm;
X{
X   char  buf [MAX_RPT];
X
X   buf[(nm = (nm < 0) ? 0 : nm)] = 0;
X
X   for (nm--; nm >= 0; nm--)  buf[nm] = ch;
X
X   return buf;
X}
X
Xchar *_next_line (file)
Xint               file;
X{
X   register int   i;
X   int            j;
X
X   j = 0;
X
X   do     i = read (file, &buffer[j++], 1);
X   while (i != 0 && buffer[j-1] != '\n' && buffer[j-1] != 0);
X
X   buffer[j-1] = 0;
X
X   return buffer;
X}
X
Xchar *_rcd (file, rec)
Xint         file, rec;
X{
X   static char temp[BUF_LEN];
X
X   lseek (_list[file].relcode, _rec (file, rec), 0);
X
X   read  (_list[file].relcode, temp, _list[file].rec_len);
X
X   temp[_list[file].rec_len] = 0;
X
X   return temp;
X}
X
Xchar *_skey (file,  index,  str)
Xint          file,  index;
Xchar                       *str;
X{
X   register int   j, s, i;
X   static   char  temp[BUF_LEN];
X
X   for (i = s = 0; _list[file].idx_start[index][i] != -1; i++)
X    {
X      for (j = _list[file].idx_start[index][i];
X           j < _list[file].idx_stop [index][i]; j++)  temp[s++] = str[j];
X
X      temp[s++] = '|';
X    };
X
X   temp[s] = 0;
X
X   return temp;
X}
X
Xchar *_key (file, index, rec)
Xint         file, index, rec;
X{
X   static char temp[BUF_LEN];
X
X   strcpy (temp, _skey (file, index, _rcd (file, rec)));
X
X   return temp;
X}
X
Xchar *cut (str, num)
Xchar      *str;
Xint             num;
X{
X   static char buff [MAX_CUT];
X
X   if (num == 0)
X      sprintf (buff, "");
X   else
X      for (buff[num] = 0; num > 0; num--)  buff[num-1] = str[num-1];
X
X   return buff;
X}
X
Xchar *_spc (file, index,  str, enc)
Xint         file, index,       enc;
Xchar                     *str;
X{
X   register int   i, a;
X   int            x, b;
X   static   char  temp[BUF_LEN];
X
X   i = b = temp[0] = 0;
X
X   do
X    { x = (index == -1) ? b : _list[file].idx_num[index][b];
X
X      if ((index == -1) ? (_list[file].idx_just[x] != 0) : (x != -1))
X       { for (a = 0; str[i] != '|' && str[i] != 0; i++, a++);
X
X         if (_list[file].idx_just[x] > 0)
X            sprintf (buffer, "%s%s", repeat (' ', _list[file].idx_just[x]-a),
X                                    cut (&str[i-a], a));
X         else
X            sprintf (buffer, "%s%s", cut (&str[i-a], a),
X                                    repeat (' ', 0-_list[file].idx_just[x]-a));
X
X         if (enc == -1)  _decrypt (buffer, file);
X         if (enc ==  1)  _encrypt (buffer, file);
X
X         strcat (temp, buffer);
X         strcat (temp, "|");
X       };
X
X      i = (str[i] == 0) ? i : i+1;
X      b++;
X    } while ((index == -1) ? (_list[file].idx_just[x] != 0) : (x != -1));
X
X   return temp;
X}
X
Xpattern (whole,  match, skip)
Xchar    *whole, *match;
Xint                     skip;
X{
X   int  i, j, m, w;
X
X   m = strlen (match);  w = strlen (whole);
X
X   for (i = 0; i <= w-m; i++)
X    {
X      for (j = 0; match [j] != 0 && whole[i+j] == match[j]; j++)
X       ;
X
X      if (match[j] == 0)  if (skip-- == 0)  return i;
X    };
X
X   return -1;
X}
X
X/*  Encode and Eval perform base 10 to base 255 conversion, with a bottom
X    value of 1 (As opposed to 0) for the base-255 numbers.  Perfect for
X    encoding BIG numbers (See chart) and storing them in 5 bytes on disk, eh?
X
X    # of characters used______________Maximum integer representable
X    1                                          254
X    2                                        65024
X    3                                     16581374
X    4                                   4228250624
X    5                                 107820390900.... etc.                  */
X
Xlong _eval (st, x)
Xchar       *st;
Xint             x;
X{
X   long int  j;
X   long int  n;
X   int       a;
X
X   j = 0;  n = 1;
X
X   while (x > 0) { a = st[--x];  a = fix (a);  j += n * (a - 1);  n *= 255; };
X
X   return j;
X}
X
Xchar *_encode (num, len)
Xlong int       num;
Xint                 len;
X{
X   register int  i;
X            int  a;
X   static   char buf[10];
X
X   len = (len < 9) ? len : 9;
X
X   for (i = len-1; i >= 0; i--)
X    { a = num % 255;
X
X      num = (num - a) / 255;
X
X      buf[i] = a + 1;
X    };
X
X   buf[len] = 0;
X
X   return buf;
X}
X
Xmb_lck (file)
Xint     file;
X{
X   if (file < 0 || file > MAX_REL)  return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)       return NOT_OPEN;
X
X   lseek (_list[file].relcode, 0L, 0);  read  (_list[file].relcode, buffer, 1);
X
X   if (fix (buffer[0]) == 127)  return OKAY;
X   if (fix (buffer[0]) != 2)    return LOCK_DENIED;
X
X   buffer[0] = 127;
X
X   lseek (_list[file].relcode, 0L, 0);  write (_list[file].relcode, buffer, 1);
X
X   return OKAY;
X}
X
Xmb_unl (file)
Xint     file;
X{
X   if (file < 0 || file > MAX_REL)  return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)       return NOT_OPEN;
X
X   lseek (_list[file].relcode, 0L, 0);  read  (_list[file].relcode, buffer, 1);
X
X   if (buffer[0] != 127)  return OKAY;
X
X   buffer[0] = 2;
X
X   lseek (_list[file].relcode, 0L, 0);  write (_list[file].relcode, buffer, 1);
X
X   return OKAY;
X}
X
Xmb_rst (filename)
Xchar   *filename;
X{
X   int   relcode;
X
X   sprintf (buffer, "%s.rel", filename);
X
X   if ((relcode = open (buffer, O_RDWR)) == -1)
X      return CANNOT_OPEN_REL;
X
X   if (read (relcode, buffer, 4) != 4)
X      return CANNOT_READ_REL;
X
X   sprintf (buffer, "%c", '\001');
X
X   lseek (relcode, 0L, 0);  write (relcode, buffer, 1);
X
X   return OKAY;
X}
X
Xmb_inc (filename, key)
Xchar   *filename, key;
X{
X   char  temp[5];
X   int   i, place, relcode, n;
X
X   place = -1;
X
X   if (_Started == -1)
X    { _Started = 0;
X
X      for (i = 0; i < MAX_REL; i++)  _list[i].pos = -1;
X    };
X
X   for (i = 0; i < MAX_REL; i++)
X      if (_list[i].pos == -1)
X         place = (place == -1) ? i : place;
X
X   if (place == -1)  return NOT_ENOUGH_ROOM;
X
X   sprintf (buffer, "%s.rel", filename);
X
X   if ((relcode = _list[place].relcode = open (buffer, O_RDWR)) == -1)
X      return CANNOT_OPEN_REL;
X
X   if (read (relcode, buffer, 4) != 4)
X      return CANNOT_READ_REL;
X
X   n = fix (buffer[0]);
X
X   if (n == 121 || n == 249)  return RELATION_BUSY;
X   if (n == 127)              return RELATION_LOCKED;
X
X   sprintf (temp, "%c", n+1);
X
X   lseek (relcode, 0L, 0);  write (relcode, temp, 1);
X
X   _list[place].num_idx = _eval (&buffer[1], 1);
X   _list[place].rec_len = _eval (&buffer[2], 2);
X
X   if (_fill_idx (place) == -1)  return CORRUPT_INDEX;
X
X   strcpy (_list[place].filename, filename);
X
X   _list[place].pos = 0;
X
X   breakkey (place, key);
X
X   return place;
X}
X
X_fill_idx (file)
Xint        file;
X{
X   register int  j;
X            int  acc, i, k;
X            char temp[BUF_LEN];
X
X   acc = _list[file].relcode;
X
X   _list[file].relbase = 0 - lseek (acc, _block(file), 0);  _next_line (acc);
X
X   for (i = 0; i < _list[file].num_idx; i++)
X    { strcpy (temp, _next_line (acc));
X
X      for (j = 0; temp[4*j] != 0 && temp[4*j] != 'd'; j++)
X         _list[file].idx_num[i][j] = atoi (cut (&temp[4*j], 3)) - 1;
X
X      _list[file].idx_num[i][j] = -1;
X
X      _list[file].idx_dups[i] = (temp[4*j] == 'd') ? 1 : 0;
X    };
X
X   _list[file].relbase += lseek (acc, 0L, 1);
X
X   lseek (acc, _block(file), 0);
X
X   strcpy (temp, _next_line (acc));
X
X   for (i = 0; i < _list[file].num_idx; i++)
X    {
X      for (k = 0; _list[file].idx_num[i][k] != -1; k++)
X       { _list[file].idx_start[i][k] = 0;
X
X         for (j = 0; j < _list[file].idx_num[i][k]; j++)
X            _list[file].idx_start[i][k] += 1 + atoi (cut (&temp[5*j], 3));
X
X         _list[file].idx_stop[i][k] = _list[file].idx_start[i][k] +
X                                        atoi (cut (&temp[5*j], 3));
X       };
X
X      _list[file].idx_num[i][k] = _list[file].idx_start[i][k] = -1;
X    };
X
X   for (j = 0; temp[5*j] != 0; _list[file].idx_just[j] = ((temp[5*j+3] == 'r')
X           ? atoi (cut (&temp[5*j], 3)) : (0 - atoi (cut(&temp[5*j], 3)))), j++);
X
X   _list[file].idx_just[j] = 0;
X
X   return OKAY;
X}
X
X
Xmb_rmv (file)
Xint     file;
X{
X   int     n;
X
X   if (file < 0 || file > MAX_REL)  return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)       return NOT_OPEN;
X
X   _list[file].pos = -1;
X
X   lseek (_list[file].relcode, 0L, 0);  read  (_list[file].relcode, buffer, 1);
X   n=fix (buffer[0]);  n=((n == 127) ? 1 : n-1);  buffer[0]=((n < 1) ? 1 : n);
X   lseek (_list[file].relcode, 0L, 0);  write (_list[file].relcode, buffer, 1);
X
X   close (_list[file].relcode);
X
X   return OKAY;
X}
X
Xmb_upd (file,  string)
Xint     file;
Xchar          *string;
X{
X   register int   i;
X   long     int   pos;
X   int            acc;
X   char           temp[BUF_LEN];
X
X   strcpy (buffer, _spc (file, -1, string, 1));
X
X   if (file < 0 || file > MAX_REL)              return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)                   return NOT_OPEN;
X   if ((pos = _list[file].pos) == 0)            return NO_CURRENT_RECORD;
X   if (strlen (buffer) != _list[file].rec_len)  return RCD_INVALID;
X
X   if (_set_lck ((acc = _list[file].relcode), 1) != 0)  return RELATION_HUNG;
X
X   for (i = 0; i < _list[file].num_idx; i++)
X    { if (_list[file].idx_dups[i] == 0)
X       { strcpy (temp, _skey (file, i, buffer));
X
X         if (_search (file, i, EQUL, temp, _find_top (file, i)) != 0)
X          { _clr_lck (acc);
X
X            return ILLEGAL_DUPLICATE;
X          };
X       };
X    };
X
X   lseek (acc, _rec (file, pos), 0);  read  (acc, temp,   _list[file].rec_len);
X   lseek (acc, _rec (file, pos), 0);  write (acc, buffer, _list[file].rec_len);
X
X   for (i = 0; i < _list[file].num_idx; i++)
X    { _disconnect (file, i, pos);
X      _drop       (file, i, pos);
X    };
X
X   _clr_lck (acc);
X
X   return OKAY;
X}
X
Xmb_add (file,  string)
Xint     file;
Xchar          *string;
X{
X   register int   i;
X   int            r_o,      acc;
X   char           temp[BUF_LEN], tmp2[5];
X
X   strcpy (buffer, _spc (file, -1, string, 1));
X
X   if (file < 0 || file > MAX_REL)              return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)                   return NOT_OPEN;
X   if (strlen (buffer) != _list[file].rec_len)  return RCD_INVALID;
X
X   if (_set_lck ((acc = _list[file].relcode), 1) != 0)  return RELATION_HUNG;
X
X   for (i = 0; i < _list[file].num_idx; i++)
X    { if (_list[file].idx_dups[i] == 0)
X       { strcpy (temp, _skey (file, i, buffer));
X
X         if (_search (file, i, EQUL, temp, _find_top (file, i)) != 0)
X          { _clr_lck (acc);
X
X            return ILLEGAL_DUPLICATE;
X          };
X       };
X    };
X
X   lseek (acc, _num_recs(file), 0);  read (acc, tmp2, 4);
X
X   r_o = _eval (tmp2, 4) + 1;
X
X   lseek (acc, _base (file, r_o), 0);
X
X   for (i = 0; i < _list[file].num_idx; i++)  write (acc, ZEROES, 13);
X
X   write (acc, "\n",    1);
X   write (acc, buffer, _list[file].rec_len);
X   write (acc, "\n",    1);
X
X   for (i = 0; i < _list[file].num_idx; i++)  _drop (file, i, r_o);
X
X   lseek (acc, _num_recs (file), 0);  write (acc, _encode (r_o, 4), 4);
X
X   _clr_lck (acc);
X
X   return OKAY;
X}
X
Xlong _find_top (file, index)
Xint             file, index;
X{
X   char   temp [5];
X
X   lseek (_list[file].relcode, _t_top (file, index), 0);
X   read  (_list[file].relcode, temp,                 4);
X
X   return (_eval (temp, 4));
X}
X
X_drop (file, index, rec)
Xint    file, index, rec;
X{
X   int    acc, a, off;
X   char   temp  [BUF_LEN];
X   char   temp2 [14];
X
X   acc =     _list[file].relcode;
X   off = a = _find_top (file, index);
X
X   if (a == 0)
X    { lseek (acc, _t_top  (file, index), 0);
X      write (acc, _encode (rec,  4),     4);  }
X   else
X    { strcpy (temp, _key (file, index, rec));
X
X      do
X       { off = a;
X
X         lseek (acc, _l_ptr (file, index, off), 0);  read (acc, temp2, 8);
X
X         if (_diff (_key (file, index, off), temp, 0, file) == -1)
X          { if ((a = _eval (&temp2[0], 4)) == 0)
X               sprintf (temp2, "%-4.4s%-4.4s", _encode (rec, 4), &temp2[4]);
X          }
X         else
X          { if ((a = _eval (&temp2[4], 4)) == 0)
X               sprintf (temp2, "%-4.4s%-4.4s", temp2, _encode (rec, 4));
X          };
X       } while (a != 0);
X
X      lseek (acc, _l_ptr (file, index, off), 0);  write (acc, temp2, 8);
X    };
X
X   sprintf (temp, "%-8.8s%-4.4s", ZEROES, _encode (off, 4));
X
X   lseek (acc, _l_ptr (file, index, rec), 0);  write (acc, temp, 12);
X
X   return;
X}
X
Xmb_sel (file, index, str, action, comp)
Xint     file, index,      action;
Xchar                *str,        *comp;
X{
X   long   off;
X
X   if (file < 0 || file > MAX_REL)                   return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)                        return NOT_OPEN;
X   if (_set_lck (_list[file].relcode, 0) != 0)       return RELATION_HUNG;
X   if (action != CURRENT)
X      if (index < 1 || index > _list[file].num_idx)  return INVALID_INDEX;
X
X   strcpy (buffer, (comp[0] == 0) ? "" : _spc (file, index-1, comp, 1));
X
X   if (_list[file].pos == 0)
X    { if (action == NEXT)  action = FRST;
X      if (action == PREV)  action = LAST;
X    };
X
X   switch (action)
X    { case FRST:
X      case LAST:  off = _get_ends (file, index-1, action);
X                 break;
X      case CURR:  off = _list[file].pos;
X                 break;
X      case NEXT:
X      case PREV:  off = _get_sides (file, index-1, action);
X                 break;
X      case GTEQ:
X      case GTHN:
X      case LTEQ:
X      case LTHN:
X      case EQUL:  off = _search (file, index-1, action, buffer,
X                                                 _find_top (file, index-1));
X                 break;
X      default  :  return UNKNOWN_ACTION;
X    };
X
X   if (off == 0)  return NOT_FOUND;
X   if (off <  0)  return off;
X
X   strcpy (str, _spc (file, -1, _rcd (file, (_list[file].pos = off)), -1));
X
X   return OKAY;
X}
X
X_get_ends (file, index, action)
Xint        file, index, action;
X{
X   long    go, off;
X   int     acc;
X   char    buf[10];
X
X   acc = _list[file].relcode;
X
X   if ((go = off = _find_top (file, index)) == 0)  return NOT_FOUND;
X
X   while (go != 0)
X    { lseek (acc, _l_ptr (file, index, off), 0);  read  (acc, buf, 8);
X
X      off = ((go = _eval (&buf[(action == LAST) ? 4 : 0], 4)) == 0) ? off : go;
X    };
X
X   return off;
X}
X
X_get_sides (file, index, action)
Xint         file, index, action;
X{
X   long  pos;
X   int   acc, same, go, off;
X   char  buf[13];
X
X   acc = _list[file].relcode;
X   pos = _list[file].pos;
X
X   same = (action == NEXT) ? 4 : 0;
X
X   lseek (acc, _l_ptr (file, index, pos), 0);  read (acc, buf, 12);
X
X   if ((go = off = _eval (&buf[same], 4)) == 0)
X    { go = pos;
X
X      for (;;)
X       { if ((off = _eval (&buf[8], 4)) == 0)  return NOT_FOUND;
X
X         lseek (acc, _l_ptr (file, index, off), 0);  read (acc, buf, 12);
X
X         if (go == _eval (&buf[4-same], 4))    return off;
X
X         go = off;
X       };
X    };
X
X   while (go != 0)
X    { lseek (acc, _l_ptr (file, index, off), 0);  read (acc, buf, 8);
X
X      off = ((go = _eval (&buf[4-same], 4)) == 0) ? off : go;
X    };
X
X   return off;
X}
X
X_search (file, index, action, comp, pos)
Xint      file, index, action,       pos;
Xchar                         *comp;
X{
X   long   x;
X   int    flag, r, dir;
X   char   temp[9];
X
X   if (pos == 0)  return 0;
X
X   lseek (_list[file].relcode, _l_ptr (file, index, pos), 0);
X
X   read  (_list[file].relcode, temp, 8);
X
X   flag = ((r = _diff (comp, _key (file, index, pos), 1, file)) == 0) ? 1 : 0;
X
X   if (r == -1)  dir = 4;
X   if (r ==  1)  dir = 0;
X   if (r ==  0)
X    { if (action == GTHN || action == LTEQ)                    dir = 4;
X      if (action == GTEQ || action == LTHN || action == EQUL)  dir = 0;
X    };
X
X   if ((x = _search (file, index, action, comp, _eval (&temp[dir], 4))) != 0)
X      return x;
X
X   if  (action != GTHN && action != LTHN  && flag == 1)  return pos;
X   if ((action == GTEQ || action == GTHN) && dir  == 0)  return pos;
X   if ((action == LTEQ || action == LTHN) && dir  == 4)  return pos;
X
X   return 0;
X}
X
Xmb_del (file, verify)  /* 'verify' is ignored--only used so programs won't */
Xint     file, verify;  /* compile if mb_del is confused with mb_rmv        */
X{
X   long     int  to_die,   last,  pos;
X   int           i,        acc;
X   char          temp[13], sidx[13];
X
X   if (file < 0 || file > MAX_REL)       return INVALID_FILE_CODE;
X   if (_list[file].pos == -1)            return NOT_OPEN;
X
X   lseek ((acc = _list[file].relcode), _num_recs (file), 0);
X   read  (acc, temp, 4);
X
X   if ((to_die = _list[file].pos) <= 0)  return NO_CURRENT_RECORD;
X   if ((last   = _eval (temp, 4)) == 0)  return NO_CURRENT_RECORD;
X   if (_set_lck (acc, 1) != 0)           return RELATION_HUNG;
X
X   for (i = 0; i < _list[file].num_idx; i++)  _disconnect (file, i, to_die);
X
X   if (last != to_die)
X    { lseek (acc, _base (file, last),   0);  read  (acc, buffer, _len (file));
X      lseek (acc, _base (file, to_die), 0);  write (acc, buffer, _len (file));
X
X      strcpy (sidx, _encode (to_die, 4));
X
X      for (i = 0; i < _list[file].num_idx; i++)
X       { if ((pos = _eval (&buffer[13*i+8], 4)) == 0)
X            lseek (acc, _t_top (file, i), 0);
X         else
X          { lseek (acc, _l_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X            if (_eval (temp, 4) == last)  lseek (acc, -4L, 1);
X          };
X         write (acc, sidx, 4);
X
X         if ((pos = _eval (&buffer[13*i],   4)) != 0)
X          { lseek (acc, _b_ptr (file, i, pos), 0);  write (acc, sidx, 4); };
X         if ((pos = _eval (&buffer[13*i+4], 4)) != 0)
X          { lseek (acc, _b_ptr (file, i, pos), 0);  write (acc, sidx, 4); };
X       };
X    };
X
X   strcpy (temp, _encode (last-1, 4));
X
X   lseek  (acc, _num_recs (file), 0);  write (acc, temp, 4);
X
X   _clr_lck (acc);
X
X   _list[file].pos = 0;
X
X   return OKAY;
X}
X
X_move (file, i, self, targ, child, dad, dch, dir, sidx)
Xint    file, i,                         dch, dir;
Xlong            self, targ, child, dad;
Xchar                                             *sidx;
X{
X   long int  pos;
X   int       acc;
X   char      temp[13], ltgt[5];
X
X   acc = _list[file].relcode;
X
X   sprintf (temp, "%-12.12s", sidx);
X
X   if (dch == 1)
X      change (&temp[dir], _encode (child, 4), 4);
X   else
X    { if (child != 0)
X       { lseek (acc, _b_ptr  (file, i, child), 0);
X         write (acc, _encode (dad,  4),        4);
X       };
X
X      if (dad != 0)  lseek (acc, _l_ptr (file, i, dad) + 4 - dir, 0);
X      else           lseek (acc, _t_top (file, i),                0);
X
X      write (acc, _encode (child, 4), 4);
X    };
X
X   lseek (acc, _l_ptr (file, i, targ), 0);  write (acc, temp, 12);
X
X   if ((pos = _eval (&temp[8], 4)) == 0)
X      lseek (acc, _t_top (file, i), 0);
X   else
X    { lseek (acc, _l_ptr (file, i, pos), 0);  read (acc, ltgt, 4);
X
X      if (_eval (ltgt, 4) == self)  lseek (acc, -4L, 1);
X    };
X
X   strcpy (ltgt, _encode (targ, 4));  write (acc, ltgt, 4);
X
X   if ((pos = _eval (&temp[0], 4)) != 0)
X    { lseek (acc, _b_ptr (file, i, pos), 0);  write (acc, ltgt, 4); };
X
X   if ((pos = _eval (&temp[4], 4)) != 0)
X    { lseek (acc, _b_ptr (file, i, pos), 0);  write (acc, ltgt, 4); };
X}
X
X_disconnect (file, i, to_die)
Xint          file, i;
Xlong int              to_die;
X{
X   int           acc;
X   int           level_n,  dch_n,   level_p,  dch_p;
X   long     int  rch,      pos,     targ_n,  targ_p, lch;
X   long     int  dad_n,    dad_p;
X   char          sidx[13], temp[13];
X
X   acc = _list[file].relcode;
X
X   lseek (acc, _l_ptr (file, i, to_die), 0);  read (acc, sidx, 12);
X
X   level_n = level_p = 0;
X
X   for (pos = targ_n = _eval (&sidx[4], 4); pos != 0; level_n++)
X    { lseek (acc, _l_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X      targ_n = pos;  pos = _eval (temp, 4);
X    };
X
X   if (level_n != 0)
X    { lseek (acc, _l_ptr (file, i, targ_n), 0);  read (acc, temp, 12);
X
X      rch   = _eval (&temp[4], 4);
X      dad_n = _eval (&temp[8], 4);
X      dch_n = (level_n == 1) ? 1 : 0;
X
X      for (pos = rch; pos != 0; level_n++)
X       { lseek (acc, _r_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X         pos = _eval (temp, 4);
X       };
X    };
X
X   for (pos = targ_p = _eval (&sidx[0], 4); pos != 0; level_p++)
X    { lseek (acc, _r_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X      targ_p = pos;  pos = _eval (temp, 4);
X    };
X
X   if (level_p != 0)
X    { lseek (acc, _l_ptr (file, i, targ_p), 0);  read (acc, temp, 12);
X
X      lch   = _eval (&temp[0], 4);
X      dad_p = _eval (&temp[8], 4);
X      dch_p = (level_p == 1) ? 1 : 0;
X
X      for (pos = lch; pos != 0; level_p++)
X       { lseek (acc, _l_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X         pos = _eval (temp, 4);
X       };
X    };
X
X   if (level_n == 0 && level_p == 0)
X    { if ((pos = _eval (&sidx[8], 4)) == 0)
X         lseek (acc, _t_top (file, i), 0);
X      else
X       { lseek (acc, _l_ptr (file, i, pos), 0);  read (acc, temp, 4);
X
X         if (_eval (temp, 4) == to_die)  lseek (acc, -4L, 1);
X       };
X
X      write (acc, ZEROES, 4);
X    }
X   else
X    { if (level_n >= level_p)
X         _move (file, i, to_die, targ_n, rch, dad_n, dch_n, 4, sidx);
X      else
X         _move (file, i, to_die, targ_p, lch, dad_p, dch_p, 0, sidx);
X    };
X}
X
X_clr_lck (acc)
Xint       acc;
X{
X   char   t[3];
X   int    n;
X
X   lseek   (acc, 0L, 0);  read  (acc, t, 1);
X   n = fix (t[0]);        n = ((n > 127) ? (n-127) : n);  t[0] = n;
X   lseek   (acc, 0L, 0);  write (acc, t, 1);
X}
X
X_set_lck (acc, set)
Xint       acc, set;
X{
X   char          t[3];
X   int           n;
X   register int  i;
X
X   n = 0;
X
X   do
X    { lseek (acc, 0L, 0);  read (acc, t, 1);
X
X      if (fix (t[0]) > 127)
X       { if (n == 200)           return -1;
X
X         for (i = 0, n++; i < 6000; i++);
X       };
X    } while (fix (t[0]) > 127);
X
X   if (set == 1)
X    { sprintf (t, "%c", fix (t[0]) + 127);
X
X      lseek (acc, 0L, 0);  write (acc, t, 1);
X    };
X
X   return 0;
X}
X
Xchange  (one,  two,  num)
Xchar    *one, *two;
Xint                  num;
X{
X   register int  i;
X
X   for (i = num-1; i >= 0; i--)  one[i] = two[i];
X}
X
END_OF_FILE
if test 29825 -ne `wc -c <'mbase.c'`; then
    echo shar: \"'mbase.c'\" unpacked with wrong size!
fi
chmod +x 'mbase.c'
# end of 'mbase.c'
fi
if test -f 'sample.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sample.c'\"
else
echo shar: Extracting \"'sample.c'\" \(3141 characters\)
sed "s/^X//" >'sample.c' <<'END_OF_FILE'
X#include "stdinc.h"
X#include "mbase.h"
X
X/* INDICIES:
X	1 -- noun
X	2 -- question|goodbad
X	3 -- question               */
X
Xstatic char *records[] =
X { "1|aReallyGoodKWIn1|r", "2|betterKeyWordin2|r",
X   "10|aGoodKWordIn10|r",  "1|aRottenKWordIn1|w",
X   "2|nastyKeyWordin2|w",  "10|aRottenKWordIn10|w",
X   "2|nastyKeyWordin2|w",  "2|aGoodKeyWordIn2|r",
X   "1|aGoodKeyWordIn1|r",  "10|greatOnein10|r",
X   "0"
X };
X
Xint    f;        /* Int into which to place the file # after mb_inc    */
Xchar   str[80];  /* Generic global char * into which to return records */
X
Xstatic int KEY = 128;  /* Encryption key to use on the file */
X
Xmain ()
X{
X   int   i, func;
X   char  temp[80], validkey[80];
X
X   if ((f = mb_inc ("sample", KEY)) < 0)
X    { printf ("Relation could not be opened.\n");
X      exit   (0);
X    };
X   printf ("Relation has been included -- %d.\n\n", f);
X
X   printf ("Relation has been cleaned  -- %d.\n\n", mb_rst ("sample"));
X
X   printf ("Adding records (If they're not there)\n");
X   printf ("   ('!' = already there, '.' = added)\n");
X
X   for (i = 0; records[i][0] != '0'; i++)
X      printf ( (mb_add (f, records[i]) == 0) ? "." : "!" );
X   printf ("\n");
X
X   printf ("Printing all words in the relation:\n");
X
X   for (func = FIRST; mb_sel (f, 1, str, func, "") == 0; func = NEXT)
X      print_record ("<validkey unused>");
X
X   printf ("\nLooking up 'greatOnein10'\n");
X   if (mb_sel (f, 1, str, EQUAL, "greatOnein10") == 0)
X      print_record ("<validkey unused>");
X   else
X      printf ("Couldn't find it.\n");
X
X   printf ("\nPrinting all good words in question 1:\n");
X   strcpy (temp, "1|r|");
X   for (func = EQUAL; ; func = NEXT)
X    { if (mb_sel (f, 2, str, func, temp) != 0)  break;
X      if (func == EQUAL)  strcpy (validkey, mb_key (f, 2, str));
X      else
X         if (strcmp (validkey, mb_key (f, 2, str)) != 0)  break;
X      print_record (validkey);
X    };
X
X   printf ("\nPrinting all bad words in question 2:\n");
X   strcpy (temp, "2|w|");
X   for (func = EQUAL; ; func = NEXT)
X    { if (mb_sel (f, 2, str, func, temp) != 0)  break;
X      if (func == EQUAL)  strcpy (validkey, mb_key (f, 2, str));
X      else
X         if (strcmp (validkey, mb_key (f, 2, str)) != 0)  break;
X      print_record (validkey);
X    };
X
X   printf ("\nPrinting all words in question 10:\n");
X   strcpy (temp, "10|");
X   for (func = EQUAL; ; func = NEXT)
X    { if (mb_sel (f, 3, str, func, temp) != 0)  break;
X      if (func == EQUAL)  strcpy (validkey, mb_key (f, 3, str));
X      else
X         if (strcmp (validkey, mb_key (f, 3, str)) != 0)  break;
X      print_record (validkey);
X    };
X
X   printf ("Relation has been closed -- %d\n", mb_rmv (f));
X}
X
Xprint_record (extra)
Xchar         *extra;
X{
X   printf (" %s [ %s ]\n", str, extra);
X}
X
X/*
X
XLOOK UP A SPECIFIC RECORD:
X   mb_sel (f, idx, str, EQUAL, "comparison|");
X
XUPDATE CURRENT RECORD:
X   sprintf (str, "%s", "<type in your new record value here>");
X   mb_upd (f, str);
X
XDELETE CURRENT RECORD:
X   mb_del (f, 0);       The 0 is so you can't compile if you've confused
X                        mb_del with mb_rmv
X
XRETRIEVE CURRENT RECORD:
X   mb_sel (f, idx, str, CURR, "");
X   print_record ();
X
X*/
X
END_OF_FILE
if test 3141 -ne `wc -c <'sample.c'`; then
    echo shar: \"'sample.c'\" unpacked with wrong size!
fi
chmod +x 'sample.c'
# end of 'sample.c'
fi
echo shar: End of shell archive.
exit 0

-- 
 / (_________ The man with the hammer __________) \  "Lobbest-thou thy Holy
(   ______                               _______   )  Hand-Grenade of Antioch
 ) (       Richid    rpj@owlnet.rice.edu        ) (   towards thy foe..."
'---`                                          '---`      --Monty Python, HG.


exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.