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.