home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-23 | 55.0 KB | 1,963 lines |
- Newsgroups: comp.sources.misc
- Path: sparky!kent
- From: richid@owlnet.rice.edu (Richard Parvin Jernigan)
- Subject: v33i122: mbase - MetalBase 5.0, Portable database engine, Part04/08
- Message-ID: <1992Nov23.232459.7422@sparky.imd.sterling.com>
- Followup-To: comp.sources.d
- X-Md4-Signature: 87d6cd42d8825598a91064150903ec07
- Sender: kent@sparky.imd.sterling.com (Kent Landfield)
- Organization: Sterling Software
- References: <csm-v33i119=mbase.165613@sparky.IMD.Sterling.COM>
- Date: Mon, 23 Nov 1992 23:24:59 GMT
- Approved: kent@sparky.imd.sterling.com
- Lines: 1948
-
- Submitted-by: richid@owlnet.rice.edu (Richard Parvin Jernigan)
- Posting-number: Volume 33, Issue 122
- Archive-name: mbase/part04
- Environment: AMIGA, MS-DOS, HP-UX, XENIX, UNIX, ULTRIX, SGI, SU, Curses
- Supersedes: mbase: Volume 28, Issue 40-44
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: sample/bench.s src/form.c src/lock.c src/mbase.c
- # src/mbase.h
- # Wrapped by kent@sparky on Mon Nov 23 16:33:13 1992
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 4 (of 8)."'
- if test -f 'sample/bench.s' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sample/bench.s'\"
- else
- echo shar: Extracting \"'sample/bench.s'\" \(67 characters\)
- sed "s/^X//" >'sample/bench.s' <<'END_OF_FILE'
- Xrelation bench
- X
- Xfield num type serial;
- X
- Xindex ix_num on num;
- X
- Xend
- X
- END_OF_FILE
- if test 67 -ne `wc -c <'sample/bench.s'`; then
- echo shar: \"'sample/bench.s'\" unpacked with wrong size!
- fi
- # end of 'sample/bench.s'
- fi
- if test -f 'src/form.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/form.c'\"
- else
- echo shar: Extracting \"'src/form.c'\" \(12334 characters\)
- sed "s/^X//" >'src/form.c' <<'END_OF_FILE'
- X/*
- X * METALBASE 5.0
- X *
- X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
- X * [ t-richj@microsoft.com ]
- X *
- X * Special thanks go to Adrian Corston (adrian@internode.com.au) for his
- X * suggestions and code. While this code is of my penning, the idea and
- X * style of implementation for this are direct ports from his own
- X * excellent work.
- X *
- X */
- X
- X#include "mbase.h"
- X
- X#ifndef MAXnREL
- X#define MAXnREL 20 /* Max # of relations in any given DE form */
- X#endif
- X#ifndef MAXnFLD
- X#define MAXnFLD 40 /* Max # of fields in any given DE form */
- X#endif
- X
- X/*
- X * Definitions
- X *
- X */
- X
- X#define LPARQ "("
- X#define LBRCQ "{" /* These are pulled out */
- X#define LBKT '[' /* so that vi's ()/[]/{} */
- X#define LBRC '{' /* matchin works properly */
- X#define RBRC '}' /* in moving through the */
- X#define RBKT ']' /* code. */
- X#define RBRCQ "}"
- X#define RPARQ ")"
- X
- X#define usage() fprintf (stderr, "form: format: %sform [formname]%s",SNGCR,SNGCR)
- X
- X#define comment() skip(form,";"); while(skip(form,"#")) goeol(form,NULL);
- X#define nocolon() while(skip(form,"#")) goeol(form,NULL);
- X
- X#define fieldopt(x) (*(options[x]))
- X#define fieldmode(x) (*(modes[x]))
- X
- X/*
- X * Prototypes
- X *
- X */
- X
- X#ifdef LONGARGS
- X void main (int, char **);
- X void parse_args (int, char **);
- X void check_data (int);
- X void check_defin (int);
- X void check_screen (int);
- X void check_fields (int);
- X void check_modes (int);
- X void id_field (char *, char *);
- X extern void writeit (void);
- X#else
- X void main();
- X void parse_args();
- X void check_data();
- X void check_defin();
- X void check_screen();
- X void check_fields();
- X void check_modes();
- X void id_field();
- X extern void writeit();
- X#endif
- X
- Xtypedef relation *relptr;
- Xtypedef char optlist[10][40];
- Xtypedef int modelist[20];
- X
- X/*
- X * Global Variables
- X *
- X */
- X
- Xchar formname[30];
- Xint form;
- X
- Xftype gen_type;
- Xint gen_len;
- X
- Xchar defins[26][50];
- Xchar displ[25][140];
- Xint num_l, pos_y, pos_x, num_f, num_m;
- Xfield fld[MAXnFLD];
- Xint lens[MAXnFLD];
- Xoptlist *options[MAXnFLD];
- Xmodelist *modes[MAXnFLD];
- X
- Xint num_r;
- Xrelptr rel[MAXnREL];
- X
- X/*
- X * Main code
- X *
- X */
- X
- Xvoid
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X parse_args (argc, argv);
- X
- X check_data (form);
- X check_defin (form);
- X check_screen (form);
- X check_fields (form);
- X check_modes (form);
- X
- X close (form);
- X mb_die (); /* Close all open relations */
- X
- X writeit ();
- X exit (0);
- X}
- X
- X/*
- X * Utilities
- X *
- X */
- X
- Xvoid
- Xparse_args (agc, agv)
- Xint agc;
- Xchar **agv;
- X{
- X while (agc > 1 && agv[1][0] == '-')
- X {
- X switch (agv[1][1])
- X { default: fprintf (stderr, "unrecognized option '%s'\n", agv[1]);
- X usage ();
- X exit (1);
- X break;
- X }
- X
- X agc--; agv++;
- X }
- X
- X if (agc != 2)
- X { usage ();
- X exit (1);
- X }
- X
- X strcpy (formname, agv[1]);
- X if (strcmp (&formname[strlen(formname)-4], ".frm"))
- X strcat (formname, ".frm");
- X if ((form = openx (formname, O_RDONLY)) < 0)
- X { fprintf (stderr, "cannot open form '%s'\n", formname);
- X exit (2);
- X }
- X}
- X
- Xvoid
- Xcheck_data (form)
- Xint form;
- X{
- X char temp[80];
- X
- X comment();
- X num_r = 0;
- X if (skip(form,"data") || skip(form,"relations") || skip(form,"relation"))
- X {
- X while (! skip (form, ";"))
- X {
- X if (num_r == MAXnREL)
- X { fprintf (stderr, "Too many relations--see trouble.dox%s", SNGCR);
- X close (form);
- X mb_exit (4);
- X }
- X
- X strcpy (temp, getword(form));
- X skip (form, ","); nocolon();
- X
- X if (! strcmp (&temp[strlen(temp)-4], ".rel"))
- X temp[strlen(temp)-4] = 0;
- X
- X if ((rel[num_r] = mb_inc (temp, 0)) == RNULL)
- X { fprintf (stderr, "Cannot open relation '%s' : %s\n",temp,mb_error);
- X close (form);
- X mb_exit (4);
- X }
- X num_r++;
- X }
- X if (num_r == 0)
- X { fprintf (stderr,"Data keyword implies at least one relation%s",SNGCR);
- X close (form);
- X mb_exit (5);
- X }
- X }
- X}
- X
- Xvoid
- Xcheck_defin (form)
- Xint form;
- X{
- X int i;
- X char temp[80], t2[80];
- X
- X for (i = 0; i < 26; i++) defins[i][0] = 0;
- X
- X while (skip (form, "define"))
- X {
- X strcpy (temp, getword (form));
- X strcpy (t2, getword (form));
- X
- X if (strlen (temp) != 1 || t2[0] == 0)
- X { fprintf (stderr, "DEFINE (%s:%s) syntax error%s", temp, t2, SNGCR);
- X close (form);
- X mb_exit (6);
- X }
- X if (defins[(i = tolower(temp[0])-'a')][0] != 0)
- X { fprintf (stderr, "Multiple references to DEFINE %c%s",temp[0],SNGCR);
- X close (form);
- X mb_exit (6);
- X }
- X
- X strcpy (defins[i], t2);
- X comment ();
- X }
- X}
- X
- Xvoid
- Xcheck_screen (form)
- Xint form;
- X{
- X int i, j, k;
- X char temp[80], c;
- X
- X pos_y = pos_x = 0;
- X
- X if (! skip (form, "screen"))
- X { fprintf (stderr, "Screen{} segment must follow Data and Define%s",SNGCR);
- X close (form);
- X mb_exit (7);
- X }
- X if (! skip (form, LBRCQ))
- X {
- X pos_y = atoi (getword (form));
- X
- X if (! skip (form, LBRCQ))
- X {
- X pos_x = atoi (getword (form));
- X
- X if (! skip (form, LBRCQ))
- X { fprintf (stderr, "Left brace must follow SCREEN keyword%s",SNGCR);
- X close (form);
- X mb_exit (7);
- X }
- X }
- X }
- X goeol (form, NULL);
- X
- X num_f = 0;
- X
- X for (num_l = 0; num_l < 24; num_l++)
- X {
- X goeol (form, displ[num_l]);
- X if (displ[num_l][0] == RBRC) break;
- X
- X for (;;)
- X {
- X for (i = 0; displ[num_l][i] != 0; i++)
- X if (displ[num_l][i] == LBKT || displ[num_l][i] == LBRC)
- X break;
- X if (displ[num_l][i] == 0)
- X break;
- X
- X for (j = i+1; displ[num_l][j] != 0; j++)
- X if ((displ[num_l][j] == RBKT && displ[num_l][i] == LBKT) ||
- X (displ[num_l][j] == RBRC && displ[num_l][i] == LBRC))
- X break;
- X else
- X temp[j-i-1] = displ[num_l][j];
- X temp[j-i-1] = 0;
- X if (displ[num_l][j] == 0)
- X break;
- X
- X if (num_f == MAXnFLD)
- X { fprintf (stderr, "Too many fields--see trouble.dox%s", SNGCR);
- X close (form);
- X mb_exit (8);
- X }
- X
- X for (k = 0; k < j-i-1; k++)
- X if (temp[k] == ' ' || temp[k] == '\t')
- X break;
- X temp[k] = 0;
- X if (k == 1)
- X {
- X k = (toupper (temp[0]) - 'A');
- X if (defins[k][0] == 0)
- X {
- X fprintf (stderr, "Field %c undefined%s", temp[0], SNGCR);
- X close (form);
- X mb_exit (8);
- X }
- X strcpy (temp, defins[k]);
- X }
- X
- X gen_len = j-i;
- X id_field (fld[num_f].name, temp);
- X fld[num_f].type = gen_type;
- X fld[num_f].y = num_l;
- X fld[num_f].x = i + ((c = displ[num_l][i]) == LBKT);
- X fld[num_f].len = j-i-1;
- X lens[num_f] = gen_len;
- X
- X num_f++;
- X
- X for (k = i; i <= j; i++)
- X displ[num_l][i] = ' ';
- X if (c == LBRC)
- X {
- X for (i = k; displ[num_l][i+1] != 0; i++)
- X displ[num_l][i] = displ[num_l][i+1];
- X displ[num_l][i] = 0;
- X i = j-1;
- X for ( ; displ[num_l][i+1] != 0; i++)
- X displ[num_l][i] = displ[num_l][i+1];
- X displ[num_l][i] = 0;
- X }
- X }
- X }
- X comment();
- X}
- X
- Xvoid
- Xcheck_fields (form)
- Xint form;
- X{
- X char temp[80];
- X int i, j, t;
- X
- X for (i = 0; i < MAXnFLD; i++)
- X options[i] = (optlist *)0;
- X
- X while (skip (form, "field"))
- X {
- X id_field (temp, getword(form));
- X
- X for (i = 0; i < num_f; i++)
- X if (! strcmp (fld[i].name, temp)) break;
- X if (i == num_f)
- X { fprintf (stderr, "FIELD variable '%s' unused%s", temp, SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X
- X skip (form, "type");
- X
- X /*
- X * Field credit type choice ("Yy" "Nn" "?");
- X * Field temp type link to credit ("Yes" "No" "Maybe");
- X * Field other type money;
- X *
- X */
- X
- X strcpy (temp, getword (form));
- X
- X if (! strcmp (temp, "choice") || ! strcmp (temp, "link"))
- X {
- X t = 0;
- X if (!strcmp (temp, "link"))
- X {
- X skip (form, "to");
- X id_field (temp, getword(form));
- X t = 1;
- X }
- X
- X if (! skip (form, LPARQ))
- X { fprintf (stderr, "(...) must surround options in FIELD%s", SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X
- X if ((options[i] = New (optlist)) == (optlist *)0)
- X { fprintf (stderr, "fatal error: out of memory%s", SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X
- X fieldopt(i)[0][0] = 0; /* Link-To field name */
- X if (t == 1)
- X strcpy (fieldopt(i)[0], temp); /* Link-To field name */
- X
- X for (j = 1; !skip (form, RPARQ); j++)
- X {
- X if (j == 10) break;
- X strcpy (fieldopt(i)[j], getword(form));
- X }
- X if (j != 10) fieldopt(i)[j][0] = 0;
- X
- X fld[i].option = t+1; /* t: 0 == choice, 1 == link */
- X
- X comment();
- X continue;
- X }
- X
- X if (! strcmp (temp, "char")) fld[i].type = T_CHAR;
- X if (! strcmp (temp, "string")) fld[i].type = T_CHAR;
- X if (! strcmp (temp, "character")) fld[i].type = T_CHAR;
- X if (! strcmp (temp, "short")) fld[i].type = T_SHORT;
- X if (! strcmp (temp, "ushort")) fld[i].type = T_USHORT;
- X if (! strcmp (temp, "long")) fld[i].type = T_LONG;
- X if (! strcmp (temp, "ulong")) fld[i].type = T_ULONG;
- X if (! strcmp (temp, "float")) fld[i].type = T_FLOAT;
- X if (! strcmp (temp, "double")) fld[i].type = T_DOUBLE;
- X if (! strcmp (temp, "money")) fld[i].type = T_MONEY;
- X if (! strcmp (temp, "time")) fld[i].type = T_TIME;
- X if (! strcmp (temp, "date")) fld[i].type = T_DATE;
- X if (! strcmp (temp, "serial")) fld[i].type = T_SERIAL;
- X if (! strcmp (temp, "phone")) fld[i].type = T_PHONE;
- X
- X comment ();
- X }
- X}
- X
- Xvoid
- Xcheck_modes (form)
- Xint form;
- X{
- X char temp[80];
- X int i, j, k;
- X
- X for (i = 0; i < MAXnFLD; i++)
- X modes[i] = (modelist *)0;
- X for (i = 0; i < num_f; i++)
- X if ((modes[i] = New (modelist)) == (modelist *)0)
- X { fprintf (stderr, "fatal error: out of memory%s", SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X
- X num_m = 0;
- X
- X while (skip (form, "mode"))
- X {
- X if ((i = atoi (getword (form))) < 1) { goeol (form, NULL); continue; };
- X
- X strcpy (temp, getword (form));
- X k = FM_INOUT;
- X if (! strcmp (temp, "in")) k = FM_IN;
- X if (! strcmp (temp, "out")) k = FM_OUT;
- X
- X for (j = 0; j < num_f; j++)
- X fieldmode(j)[i-1] = k;
- X
- X while (! skip (form, ";"))
- X {
- X id_field (temp, getword (form));
- X
- X for (j = 0; j < num_f; j++)
- X if (! strcmp (fld[j].name, temp)) break;
- X if (j == num_f)
- X { fprintf (stderr, "MODE variable '%s' unused%s", temp, SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X
- X k = FM_INOUT;
- X strcpy (temp, getword (form));
- X if (! strcmp (temp, "in")) k = FM_IN;
- X if (! strcmp (temp, "out")) k = FM_OUT;
- X fieldmode(j)[i-1] = k;
- X
- X skip (form, ",");
- X }
- X
- X num_m ++;
- X nocolon ();
- X }
- X
- X if (! skip (form, "end"))
- X { fprintf (stderr, "unexpected keyword: END%s", SNGCR);
- X close (form);
- X mb_exit (9);
- X }
- X}
- X
- Xvoid
- Xid_field (buf, str)
- Xchar *buf,*str;
- X{
- X int i, j;
- X
- X strcpy (buf, str);
- X gen_type = T_CHAR;
- X
- X if (strchr (str, '.') == NULL)
- X for (i = 0; i < num_r; i++)
- X {
- X for (j = 0; j < rel[i]->num_f; j++)
- X if (! strcmp (str, rel[i]->name[j]))
- X {
- X sprintf (buf, "%s.%s", rel[i]->relname, rel[i]->name[j]);
- X gen_type = rel[i]->type[j];
- X gen_len = rel[i]->siz[j];
- X break;
- X }
- X if (j != rel[i]->num_f) break;
- X }
- X}
- X
- END_OF_FILE
- if test 12334 -ne `wc -c <'src/form.c'`; then
- echo shar: \"'src/form.c'\" unpacked with wrong size!
- fi
- # end of 'src/form.c'
- fi
- if test -f 'src/lock.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/lock.c'\"
- else
- echo shar: Extracting \"'src/lock.c'\" \(12967 characters\)
- sed "s/^X//" >'src/lock.c' <<'END_OF_FILE'
- X/*
- X * METALBASE 5.0
- X *
- X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
- X * [ t-richj@microsoft.com ]
- X */
- X
- X#define UTIL_C
- X#include "mbase.h"
- X#include "internal.h"
- X
- X#ifdef LONGARGS
- X static mb_err _set_hack (relation *);
- X static void _clr_hack (relation *);
- X static void _lck_pause (void);
- X static int _is_dead (relation *, int);
- X static void _clrstrobe (relation *);
- X#else
- X static mb_err _set_hack();
- X static void _clr_hack();
- X static void _lck_pause();
- X static int _is_dead();
- X static void _clrstrobe();
- X#endif
- X
- X/*****************************************************************************
- X *
- X * LOCK TIMING
- X *
- X */
- X
- Xstatic void
- X_lck_pause () /* Around .1 second pause, to reduce disk I/O */
- X{
- X int i, j = 1;
- X for (i = 0; i < 40000; i++) /* UGLY! CHANGE THIS! */
- X j = 1-j;
- X}
- X
- X/*****************************************************************************
- X *
- X * EXCLUSIVE (RELATION-WIDE) LOCKS
- X *
- X */
- X
- Xmb_err /* Fair warning: */
- X_chk_elck (rel) /* THIS ROUTINE CANNOT BE TRUSTED unless you have a */
- Xrelation *rel; /* temporary lock placed on the relation before calling it! */
- X{
- X ushort pid;
- X if (rel->exc & 1) baderr (MB_OKAY); /* _we_ have the lock set */
- X
- X lseek (rel->lckcode, lckPOS_ELOCK, 0);
- X readx (rel->lckcode, &pid, 2);
- X if (! pid) baderr (MB_OKAY); /* or no one has the lock */
- X
- X baderr (MB_LOCKED);
- X}
- X
- Xmb_err
- Xmb_unl (rel)
- Xrelation *rel;
- X{
- X ushort pid;
- X if (_identify (rel) < 0) reterr (MB_BAD_REL, -1);
- X if (! (rel->exc & 1)) reterr (MB_OKAY, MB_OKAY); /* We didn't lock it */
- X
- X if (_set_lck (rel) != MB_OKAY) baderr (mb_errno);
- X
- X lseek (rel->lckcode, lckPOS_ELOCK, 0);
- X readx (rel->lckcode, &pid, 2);
- X
- X if (pid == rel->pid)
- X {
- X pid = 0;
- X lseek (rel->lckcode, lckPOS_ELOCK, 0);
- X writx (rel->lckcode, &pid, 2);
- X }
- X
- X rel->exc &= 2; /* Clear the exclusive-lock bit */
- X lckerr (rel, MB_OKAY, MB_OKAY);
- X}
- X
- Xmb_err
- Xmb_lck (rel)
- Xrelation *rel;
- X{
- X ushort pid;
- X if (_identify (rel) < 0) reterr (MB_BAD_REL, -1);
- X if (rel->exc & 1) baderr (MB_OKAY); /* We've already locked it */
- X
- X if (_set_lck (rel) != MB_OKAY) baderr (mb_errno);
- X
- X lseek (rel->lckcode, lckPOS_ELOCK, 0);
- X readx (rel->lckcode, &pid, 2);
- X if (pid != 0) lckerr (rel, MB_LOCKED, -1);
- X
- X lseek (rel->lckcode, lckPOS_ELOCK, 0);
- X writx (rel->lckcode, &rel->pid, 2);
- X rel->exc |= 1; /* Set the exclusive-lock bit */
- X
- X lckerr (rel, MB_OKAY, MB_OKAY);
- X}
- X
- X/*****************************************************************************
- X *
- X * HACK LOCKS (CONCURRENCY CONTROL)
- X *
- X */
- X
- Xstatic void
- X_clr_hack (rel)
- Xrelation *rel;
- X{
- X ushort *pid;
- X char pids[6];
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X readx (rel->lckcode, pids, 6);
- X
- X if (*(pid = (ushort *)&pids[0]) == rel->pid) *pid = 0L;
- X if (*(pid = (ushort *)&pids[2]) == rel->pid) *pid = 0L;
- X if (*(pid = (ushort *)&pids[4]) == rel->pid) *pid = 0L;
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X writx (rel->lckcode, pids, 6);
- X}
- X
- Xstatic mb_err
- X_set_hack (rel)
- Xrelation *rel;
- X{
- X ushort *pid;
- X char pids[6];
- X int fChange;
- X mb_time timeStart;
- X
- X timeStart = curtime();
- X
- X for (;;)
- X {
- X if (elap_t (timeStart) > 5)
- X {
- X pids[0] = pids[1] = pids[2] = pids[3] = pids[4] = pids[5] = 0;
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X writx (rel->lckcode, pids, 6);
- X timeStart = curtime();
- X continue;
- X }
- X
- X/*
- X * FIRST ITERATION:
- X *
- X */
- X
- X fChange = 0;
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X readx (rel->lckcode, pids, 6);
- X
- X if (*(pid = (ushort *)&pids[0]) == rel->pid) { *pid = 0; fChange |= 1; }
- X if (*pid != 0) fChange |= 2;
- X if (*(pid = (ushort *)&pids[2]) == rel->pid) { *pid = 0; fChange |= 1; }
- X if (*pid != 0) fChange |= 2;
- X if (*(pid = (ushort *)&pids[4]) == rel->pid) { *pid = 0; fChange |= 1; }
- X if (*pid != 0) fChange |= 2;
- X
- X if (! (fChange & 2))
- X {
- X *pid = rel->pid; fChange |= 1;
- X }
- X
- X if (fChange & 1)
- X {
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X writx (rel->lckcode, pids, 6);
- X }
- X
- X if (fChange & 2)
- X {
- X continue;
- X }
- X
- X/*
- X * SECOND ITERATION:
- X *
- X */
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X readx (rel->lckcode, pids, 6);
- X
- X if (*(pid = (ushort *)&pids[0]) != 0) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[4]) != rel->pid) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[2]) != 0) continue; /* NOTE ORDER */
- X
- X *pid = rel->pid;
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X writx (rel->lckcode, pids, 6);
- X
- X/*
- X * THIRD ITERATION:
- X *
- X */
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X readx (rel->lckcode, pids, 6);
- X
- X if (*(pid = (ushort *)&pids[4]) != rel->pid) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[2]) != rel->pid) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[0]) != 0) continue; /* NOTE ORDER */
- X
- X *pid = rel->pid;
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X writx (rel->lckcode, pids, 6);
- X
- X/*
- X * FINAL CHECK:
- X *
- X */
- X
- X lseek (rel->lckcode, lckPOS_HLOCK, 0);
- X readx (rel->lckcode, pids, 6);
- X
- X if (*(pid = (ushort *)&pids[4]) != rel->pid) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[2]) != rel->pid) continue; /* NOTE ORDER */
- X if (*(pid = (ushort *)&pids[0]) != rel->pid) continue; /* NOTE ORDER */
- X
- X break;
- X }
- X
- X return MB_OKAY;
- X}
- X
- X/*****************************************************************************
- X *
- X * TEMPORARY LOCKS/ QUEUEING
- X *
- X */
- X
- Xmb_err
- X_set_lck (rel)
- Xrelation *rel;
- X{
- X char pids[60];
- X ushort *pid, tpid;
- X int i, j;
- X
- X/*
- X * FLOW FOR GETTING ( example queue: 12 13 14 00 19 22 00 00 00... )
- X * INTO THE QUEUE: ( pos: 0 1 2 3 4 5 6 7 8... )
- X *
- X * set hacklock -- This guarantees that only one process will try to get
- X * into the queue at once--avoids race conditions.
- X *
- X * WAIT:
- X * pos = the first zero in the right-hand set of contiguous zeroes
- X * (position 6 in the example above)
- X * look for a queuehole (position 3 above): -- if we were to just set
- X * a lock when the queue has a hole in it, we'd possibly escalate
- X * the length of the queue, whereas if we wait a few seconds, it'll
- X * shrink itself (when process 19 wakes up and moves itself).
- X * if queuehole
- X * check strobe for our blocking process (pos 5, pid 22 in this case)
- X * if strobe hasn't changed and elapsed time > 3 seconds
- X * pos -= 1 -- move over the dead process and erase its hold on
- X * write PID, 0 -- the queue--try again and we'll start here.
- X * else
- X * pause -- let other processes work without extra I/O
- X * goto WAIT -- go check the queue for a hole again.
- X * if the queue's full (pos == 30 -- no free slots), return MB_BUSY
- X *
- X * clear hacklock -- we're assured this position in the queue now
- X *
- X */
- X
- X if (rel->exc & 2) baderr (MB_OKAY);
- X
- X if (_set_hack (rel)) baderr (mb_errno);
- X
- X _clrstrobe (rel);
- X
- Xlockwait:
- X
- X lseek (rel->lckcode, lckPOS_QUEUE, 0);
- X readx (rel->lckcode, pids, 60);
- X
- X for (i = 29; i >= 0; i--)
- X if (*(pid = (ushort *)&pids[i*2]) != 0)
- X break;
- X i++; /* "i" now == first available zero. */
- X
- X if (i != 0) /* Check for a queuehole before taking the slot. */
- X {
- X for (j = i-1; j >= 0; j--)
- X if (*(pid = (ushort *)&pids[j*2]) == 0)
- X break;
- X
- X if (j != -1) /* If this != -1, there's a 0 right here in the queue */
- X {
- X if (! _is_dead (rel, i-1)) /* If it's not dead, we expect it's */
- X { /* checking the guy before it, and so on-- */
- X _lck_pause (); /* and that eventually, someone will see the */
- X _lck_pause (); /* queuehole exists and will try to get it */
- X } /* filled. */
- X else
- X {
- X i--; /* If it IS dead, though, move over it and try again. */
- X tpid = 0;
- X lseek (rel->lckcode, lckPOS_QUEUE +2*i, 0);
- X writx (rel->lckcode, &tpid, 2);
- X }
- X goto lockwait; /* Look, GOTO was useful here, all right? Sheesh... */
- X }
- X }
- X if (i == 30)
- X {
- X _clr_hack (rel);
- X baderr (MB_BUSY);
- X }
- X
- X lseek (rel->lckcode, lckPOS_QUEUE +2*i, 0);
- X writx (rel->lckcode, &rel->pid, 2);
- X
- X _clr_hack (rel);
- X
- X/*
- X * FLOW FOR WORKING OUR ( example queue: 15 13 12 92 34 16 00... )
- X * WAY UP THE QUEUE: ( pos: 0 1 2 3 4 5 6... )
- X *
- X * (we're in slot #4, PID==34, in the example above):
- X *
- X * WAIT:
- X * If we're in slot 0, goto DONE
- X * Otherwise,
- X * Read pos OurPos-1 (#3)--check pid (92)
- X * If PID==0, -- The process that WAS there has moved,
- X * OR PID is dead -- or hasn't strobed in 3 seconds,
- X * Write our PID in that slot -- move up over it. This way, free
- X * Write zero in our last slot -- slots bubble upwards...
- X * Goto WAIT
- X * Strobe our position
- X * Goto WAIT
- X *
- X * DONE:
- X * We're finished, and a temporary lock is in place. Make sure to strobe
- X * every second during operations, or you'll lose your lock.
- X *
- X */
- X
- X _clrstrobe (rel);
- X
- X for (j = 0; i > 0; j++)
- X {
- X lseek (rel->lckcode, lckPOS_QUEUE +2*(i-1), 0);
- X readx (rel->lckcode, &tpid, 2);
- X if (tpid == 0 || _is_dead (rel, i-1))
- X {
- X i--;
- X tpid = 0;
- X lseek (rel->lckcode, lckPOS_QUEUE +2*i, 0);
- X writx (rel->lckcode, &rel->pid, 2);
- X writx (rel->lckcode, &tpid, 2);
- X continue;
- X }
- X
- X _strobe (rel, i); /* Don't let anyone think we're dead, but let */
- X _lck_pause (); /* other processes think for a second without */
- X continue; /* tons of I/O slowing everything down. */
- X }
- X
- X rel->exc |= 2;
- X
- X baderr (MB_OKAY);
- X}
- X
- Xmb_err
- X_clr_lck (rel)
- Xrelation *rel;
- X{
- X ushort tpid = 0;
- X
- X if (! (rel->exc & 2)) baderr (MB_OKAY);
- X
- X rel->exc &= 1; /* Clear the temp lock bit */
- X
- X lseek (rel->lckcode, lckPOS_QUEUE, 0);
- X writx (rel->lckcode, &tpid, 2);
- X
- X return MB_OKAY;
- X}
- X
- Xstatic int
- X_is_dead (rel, pos)
- Xrelation *rel;
- Xint pos;
- X{
- X char newstrobe[30]; /* Values just read from lockfile */
- X mb_time cur; /* Current time (reduces curtime() calls) */
- X int i;
- X
- X cur = curtime();
- X
- X/*
- X * If you have lots of frequently-dying processes, you may want to change the
- X * thing below to "#if 0"--that way, you can detect ALL processes dying in
- X * exactly three seconds instead of three sec per process--does a bit more
- X * I/O, though.
- X *
- X */
- X
- X#if 1
- X i = pos;
- X
- X lseek (rel->lckcode, lckPOS_STROBE +2*i, 0); /* Get just this one */
- X readx (rel->lckcode, &newstrobe[i], 1); /* position's strobe */
- X#else
- X lseek (rel->lckcode, lckPOS_STROBE, 0); /* First, we read all thirty */
- X readx (rel->lckcode, newstrobe, 30); /* strobes into an array. */
- X
- X for (i = 0; i < 30; i++) /* For each strobe, check if the */
- X#endif
- X if (rel->strobe[i] != newstrobe[i]) /* value's changed--if so, update */
- X rel->times[i] = cur; /* times[] array to current time. */
- X
- X/*
- X * Note: elap_t() will fail at midnight--it'll return a BIG negative number,
- X * which won't pass the IsItDead test below. So it may take 6 seconds
- X * to detect if a process is dead, if successive checks occur right then.
- X *
- X * Now why 10 seconds?
- X * 1-second granularity means two seconds are minimum.
- X * Previous value == current value adds two seconds for trigger (strobing
- X * process won't change it, even if it expects to--and won't try again
- X * for 1 sec, plus granularity safeguard).
- X * 6-second safeguard (just to be SURE, 'cause it's a Bad Thing to be
- X * trigger happy, and a one-time timeout isn't worth fussing over).
- X *
- X */
- X
- X return (elap_t (rel->times[pos]) > 10); /* If not changed yet, dead. */
- X}
- X
- Xvoid
- X_strobe (rel, pos)
- Xrelation *rel;
- Xint pos;
- X{
- X if (elap_t (rel->times[pos]) >= 1)
- X {
- X lseek (rel->lckcode, lckPOS_STROBE +pos, 0);
- X rel->strobe[pos] = (char)( ((int)rel->strobe[pos] +1) % 255 );
- X writx (rel->lckcode, &rel->strobe[pos], 1);
- X rel->times[pos] = curtime();
- X }
- X}
- X
- Xstatic void
- X_clrstrobe (rel)
- Xrelation *rel;
- X{
- X int i;
- X mb_time cur;
- X cur = curtime();
- X for (i = 0; i < 30; i++)
- X rel->times[i] = curtime();
- X}
- X
- END_OF_FILE
- if test 12967 -ne `wc -c <'src/lock.c'`; then
- echo shar: \"'src/lock.c'\" unpacked with wrong size!
- fi
- # end of 'src/lock.c'
- fi
- if test -f 'src/mbase.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/mbase.c'\"
- else
- echo shar: Extracting \"'src/mbase.c'\" \(12702 characters\)
- sed "s/^X//" >'src/mbase.c' <<'END_OF_FILE'
- X/* ******************************************************************** *
- X *** unix compatible! ***
- X * MetalBase 5.0..................................................... *
- X * *
- X * Simultaneous multi-user use of multiple relations! *
- X * Users may have many relations open at once, even the same one! *
- X * Environmentally safe--no chloroflourocarbons to destroy the ozone! *
- X * Loads of wonderful utilities, like data entry and report writing! *
- X * Unlimited indicies per relation/Up to 999 fields per composite index! *
- X * Up to 4.2 billion records per relation (that's a lot, friend...) *
- X * Bizarre intermittent bugs (NOT), just like the expensive programs! *
- X * Portable to most any small-scale platform you can think of! *
- X * And, unless they're weird, your kids will eat it. *
- X * /\ *
- X * Released October 1st, 1992 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 * 206/881-2624 <-----= May 26, 1996 =-----> 615/494-0445 *
- X *** t-richj@microsoft.com / / virtual!root@owlnet.rice.edu ***
- X * ******************************************************************** */
- X
- X#define MBASE_C
- X#include "mbase.h"
- X#include "internal.h"
- X
- Xint _started = 0;
- Xint _really = 1;
- Xrelation *_list [MAX_REL];
- X
- X#ifndef MSDOS
- X#ifdef LONGARGS
- X extern char *getenv (char _FAR_ *);
- X#else
- X extern char *getenv();
- X#endif
- X#endif
- X
- Xrelation *
- Xmb_open (filename, key, useold)
- Xchar *filename;
- Xint key, useold;
- X{
- X relation *rel;
- X int i, rc, fZero = 0;
- X char buf[256], *pch;
- X long fld, idx, tlong;
- X short tshort;
- X
- X _really = 0;
- X if (mb_test (filename, useold) != MB_OKAY)
- X { if (_really != 0)
- X { if (_really < 0) close (0-_really);
- X else close (_really);
- X }
- X _really = 1;
- X relerr (mb_errno, RNULL);
- X }
- X if ((rel = New (relation)) == RNULL)
- X { if (_really != 0)
- X { if (_really < 0) close (0-_really);
- X else close (_really);
- X }
- X _really = 1;
- X relerr (MB_NO_MEMORY, RNULL);
- X }
- X
- X rel->rdonly = (_really < 0) ? 1 : 0;
- X if (_really < 0) _really = 0-_really;
- X rel->relcode = rc = _really; _really = 1;
- X
- X lseek (rel->relcode, 0L, 0);
- X readx (rel->relcode, buf, 1);
- X
- X rel->pos = 0L;
- X rel->exc = 0;
- X rel->pid = getpid();
- X rel->ver = (int)buf[0];
- X
- X for (i=0; i<MAX_REL; i++)
- X if (_list[i] == RNULL)
- X break;
- X _list[i] = rel; /* Assign it so mb_rmv()/mb_die() can find it */
- X
- X if ((pch = strrchr (filename, DIRSEP)) == NULL)
- X pch = filename;
- X else
- X pch++;
- X strcpy (buf, pch);
- X
- X if ((pch = strrchr (buf, '.')) != NULL)
- X *pch = 0;
- X strcpy (rel->relname, buf);
- X
- X lseek (rel->relcode, POS_FIELDPTR(rel->ver), 0);
- X
- X readx (rc, &fld, 4);
- X readx (rc, &idx, 4);
- X readx (rc, &rel->recz, 4);
- X readx (rc, &tlong, 4);
- X readx (rc, &tlong, 4);
- X readx (rc, &tshort, 2); rel->num_f = tshort;
- X readx (rc, &tshort, 2); rel->num_i = tshort;
- X
- X _divine_mask (rel, key);
- X
- X if (rel->ver == verCURRENT && ! rel->rdonly)
- X {
- X if ((pch = getenv ("TMP")) != NULL ||
- X (pch = getenv ("TEMP")) != NULL)
- X {
- X strcpy (buf, pch); /* If they define a directory, use it. */
- X }
- X else /* Otherwise, try to guess a default directory. */
- X {
- X#ifdef UNIX
- X strcpy (buf, "/tmp");
- X#endif
- X }
- X if (! buf[0])
- X {
- X close (rel->relcode);
- X free (rel);
- X relerr (MB_TMPDIR, RNULL);
- X }
- X if (buf[(i = strlen(buf))-1] != DIRSEP)
- X {
- X buf[i] = DIRSEP;
- X buf[i+1] = 0;
- X }
- X strcat (buf, rel->relname);
- X strcat (buf, ".lck");
- X
- X if (access (buf, 0) == -1)
- X if ((rel->lckcode = creatx (buf)) > 0)
- X {
- X close (rel->lckcode);
- X fZero = 1;
- X rel->lckcode = -1;
- X }
- X
- X rel->lckcode = openx (buf, OPENMODE);
- X
- X if (rel->lckcode <= 0)
- X {
- X close (rel->relcode);
- X free (rel);
- X relerr (MB_TMPERR, RNULL);
- X }
- X
- X if (fZero)
- X {
- X modex (buf, 0666); /* The 100 bytes consist of: */
- X for (i = 0; i < 100; i++) /* 2 : Number of users in rel */
- X buf[i] = 0; /* 2 : Exclustive lock */
- X lseek (rel->lckcode, 0L, 0); /* 6 : 3 Hacklock positions */
- X writx (rel->lckcode, buf, 100); /* 60 : 30 Queue positions */
- X } /* 30 : 30 Strobe positions */
- X
- X/*
- X * Lock file has been created; keep going.
- X *
- X */
- X
- X if (_set_lck (rel) || _chk_elck (rel))
- X {
- X if (rel->exc & 2)
- X _clr_lck (rel);
- X close (rel->relcode);
- X free (rel);
- X relerr (mb_errno, RNULL);
- X }
- X }
- X
- X return _fill_info (rel, fld, idx);
- X}
- X
- Xmb_err
- Xmb_test (filename, useold)
- Xchar *filename;
- Xint useold;
- X{
- X int i, rc, rdonly = 0;
- X int ver;
- X char buffer[256];
- X
- X if (_started == 0)
- X {
- X _started = 1;
- X for (_started=1, i=0; i<MAX_REL; i++) /* Initialize list */
- X _list[i] = RNULL; /* (oh boy fun!) */
- X }
- X
- X for (i=0; i<MAX_REL; i++)
- X if (_list[i] == RNULL) break;
- X
- X if (i == MAX_REL)
- X {
- X _really = 0;
- X reterr (MB_NO_ROOM, -1);
- X }
- X
- X strcpy (buffer, filename);
- X if (strcmp (&buffer[strlen(buffer)-4], ".rel"))
- X strcat (buffer, ".rel");
- X
- X if ((rc = openx (buffer, OPENMODE)) == -1)
- X {
- X if ((rc = openx (buffer, READMODE)) == -1)
- X {
- X if (_really) close (rc);
- X else _really = 0;
- X reterr (MB_NO_OPEN, -1); /* Can we open it? */
- X }
- X rdonly = 1;
- X }
- X if (readx (rc, buffer, 2) != 2)
- X {
- X if (_really) close (rc); else _really = 0;
- X reterr (MB_NO_READ, -1); /* Can we read it? */
- X }
- X
- X ver = (int)buffer[0];
- X
- X if (useold && (ver < 40 || ver > verCURRENT))
- X ver = 0;
- X if (! useold && ver != verCURRENT)
- X ver = 0;
- X
- X if (!ver)
- X {
- X if (_really) close (rc); else _really = 0;
- X reterr (MB_FORMAT, -1); /* Is it a 5.0 relation? */
- X }
- X
- X#ifndef UNIX_LOCKS
- X if (ver == verCURRENT && !rdonly && ((int)((uchar)buffer[1]) == 255))
- X {
- X if (_really) close (rc); else _really = 0;
- X reterr (MB_BUSY, -1); /* Are there 255 users already? */
- X }
- X#endif
- X
- X if (_really) close (rc);
- X else _really = (rdonly) ? 0-rc : rc; /* - == readonly */
- X
- X reterr (MB_OKAY, MB_OKAY);
- X}
- X
- Xmb_err
- Xmb_add (rel, rec)
- Xrelation *rel;
- Xdataptr rec;
- X{
- X int i;
- X long rcd;
- X int err;
- X
- X if (_identify (rel) < 0) reterr (MB_BAD_REL, -1);
- X if (rel->rdonly) reterr (MB_NO_WRITE, -1);
- X
- X if (_format (rel, rec, 1)) reterr (mb_errno, -1);
- X if (_set_lck (rel)) reterr (mb_errno, -1);
- X if (_chk_elck (rel)) lckerr (rel, MB_LOCKED, -1);
- X
- X _crypt (rel, rec);
- X for (i=0; i<rel->num_i; i++)
- X if (_check_dup (rel, rec, i, 0L)) lckerr (rel, mb_errno, -1);
- X
- X _format (rel, rec, 2);
- X
- X if (! (rcd = _append (rel, rec))) lckerr (rel, MB_NO_WRITE, -1);
- X if (_link (rel, rcd)) lckerr (rel, MB_CORRUPT, -1);
- X
- X rel->pos = rcd;
- X
- X _crypt (rel, rec);
- X err = MB_OKAY;
- X
- X lckerr (rel, MB_OKAY, MB_OKAY);
- X}
- X
- Xmb_err
- Xmb_upd (rel, rec)
- Xrelation *rel;
- Xdataptr rec;
- X{
- X int i;
- X long rcd;
- X
- X if (_identify (rel) < 0) reterr (MB_BAD_REL, -1);
- X if ((rcd = rel->pos) == 0L) reterr (MB_NO_CURR, -1);
- X if (_format (rel, rec, 1)) reterr (mb_errno, -1);
- X if (rel->rdonly) reterr (MB_NO_WRITE,-1);
- X if (_chk_elck (rel)) reterr (MB_LOCKED, -1);
- X
- X if (rel->iser < rel->num_f)
- X {
- X if (*(long *)((char *)rec + rel->start[rel->iser]) != rel->serial)
- X reterr (MB_BAD_SERIAL, -1);
- X }
- X _crypt (rel, rec);
- X for (i=0; i<rel->num_i; i++)
- X if (_check_dup (rel, rec, i, rcd)) reterr (mb_errno, -1);
- X if (_set_lck (rel)) reterr (mb_errno, -1);
- X
- X if (_delete (rel, rel->pos) <= 0L)
- X if (mb_errno != MB_OKAY) lckerr (rel, mb_errno, -1);
- X
- X GO_RECID (rel, rel->pos);
- X writx (rel->relcode, rec, rel->rec_len);
- X
- X if (_link (rel, rel->pos)) lckerr (rel, MB_CORRUPT, -1);
- X
- X _crypt (rel, rec);
- X lckerr (rel, MB_OKAY, MB_OKAY);
- X}
- X
- Xmb_err
- Xmb_del (rel)
- Xrelation *rel;
- X{
- X if (_identify (rel) < 0) reterr (MB_BAD_REL, -1);
- X if (rel->pos == 0L) reterr (MB_NO_CURR, -1);
- X if (_chk_elck (rel)) reterr (MB_LOCKED, -1);
- X if (rel->rdonly) reterr (MB_NO_WRITE,-1);
- X if (_set_lck (rel)) reterr (mb_errno, -1);
- X
- X if (_delete (rel, rel->pos) <= 0L)
- X if (mb_errno != MB_OKAY) lckerr (rel, mb_errno, -1);
- X
- X _remove (rel, rel->pos);
- X
- X rel->pos = 0L;
- X
- X lckerr (rel, MB_OKAY, MB_OKAY);
- X}
- X
- Xmb_err
- Xmb_rmv (rel)
- Xrelation *rel;
- X{
- X int i;
- X
- X if ((i = _identify (rel)) == -1) reterr (MB_BAD_REL, -1);
- X _list[i] = RNULL;
- X _close_proc (rel);
- X baderr (MB_OKAY);
- X}
- X
- Xvoid
- Xmb_exit (x)
- Xint x;
- X{
- X mb_die ();
- X exit (x);
- X}
- X
- Xvoid
- Xmb_die ()
- X{
- X int i;
- X if (_started)
- X for (i=0; i<MAX_REL; i++)
- X if (_list[i] != RNULL)
- X { _close_proc (_list[i]);
- X _list[i] = RNULL;
- X }
- X _seterr (MB_OKAY);
- X}
- X
- Xlong
- Xmb_num (rel)
- Xrelation *rel;
- X{
- X long x;
- X if (_identify (rel) < 0) longerr (MB_BAD_REL, -1);
- X if (lseek (rel->relcode, POS_NUMREC, 0) != POS_NUMREC)
- X longerr (MB_FORMAT, -1);
- X readx (rel->relcode, &x, 4);
- X longerr (MB_OKAY, x);
- X}
- X
- Xint
- Xstrtokey (str)
- Xchar *str;
- X{
- X char *a;
- X int x;
- X for (x=0, a=str; a && *a; a++)
- X x = (x + (int)*a) % 240 + 15;
- X return x;
- X}
- X
- Xvoid
- Xstrzcpy (new, old, num)
- Xchar *new,*old;
- Xint num;
- X{
- X int i;
- X char *a,*b;
- X
- X if (!new || !old) return;
- X for (a=new,b=old,i=0; i<num && *b; a++,b++,i++)
- X *a = *b;
- X *a = 0;
- X}
- X
- Xmb_err
- Xmb_sel (rel, idx, buf, act, comp)
- Xrelation *rel;
- Xint idx;
- Xmb_action act;
- Xdataptr buf, comp;
- X{
- X dataptr rec;
- X long off, top;
- X
- X _free_cache ();
- X
- X if (_identify (rel) < 0) baderr (MB_BAD_REL);
- X if (act != CURR && (idx < 0 || idx >= rel->num_i)) baderr (MB_BAD_IDX);
- X if (_chk_elck (rel)) baderr (MB_LOCKED);
- X if (_set_lck (rel)) baderr (mb_errno);
- X
- X rec = (comp == NULL) ? buf : comp;
- X if (rec != NULL) _crypt (rel, rec);
- X
- X if (rel->pos == 0L)
- X {
- X if (act == NEXT) act = FRST;
- X if (act == PREV) act = LAST;
- X }
- X
- X switch (act)
- X {
- X case FRST:
- X case LAST: off = _find_ends (rel, idx, (act == FRST) ? -1 : 1);
- X break;
- X case CURR: off = rel->pos;
- X break;
- X case NEXT:
- X case PREV: off = _find_seq (rel, 0L, rel->pos, idx, (act == NEXT)?1:-1);
- X break;
- X case GTEQ:
- X case GTHN:
- X case LTEQ:
- X case LTHN:
- X case EQUL: GO_TOP (rel, idx); readx (rel->relcode, &top, 4);
- X off = _search (rel, top, idx, act, rec);
- X break;
- X default : baderr (MB_UNKNOWN);
- X break;
- X }
- X
- X if (off == 0L)
- X {
- X _seterr (MB_NO_SUCH);
- X }
- X else
- X {
- X _seterr (MB_OKAY);
- X rel->pos = off;
- X }
- X
- X _crypt (rel, rec); /* Reverse-encrypt the comparison buffer */
- X _memrec (rel, rel->pos, buf); /* Read in the output buffer, encrypted */
- X _crypt (rel, buf); /* Decrypt the output buffer */
- X
- X if (rel->pos && rel->iser < rel->num_f)
- X {
- X rel->serial = *(long *)((char *)buf + rel->start[rel->iser]);
- X }
- X
- X _clr_lck (rel);
- X
- X return mb_errno;
- X}
- X
- END_OF_FILE
- if test 12702 -ne `wc -c <'src/mbase.c'`; then
- echo shar: \"'src/mbase.c'\" unpacked with wrong size!
- fi
- # end of 'src/mbase.c'
- fi
- if test -f 'src/mbase.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/mbase.h'\"
- else
- echo shar: Extracting \"'src/mbase.h'\" \(12825 characters\)
- sed "s/^X//" >'src/mbase.h' <<'END_OF_FILE'
- X/*
- X * METALBASE 5.0
- X *
- X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
- X * [ t-richj@microsoft.com ]
- X */
- X
- X#ifndef MBASE_H
- X#define MBASE_H
- X
- X#include <stdinc.h>
- X#include <curses.h>
- X
- X#define verCURRENT 50 /* Signature for 5.0 relations */
- X
- Xextern WINDOW *win;
- X
- X#ifdef MSDOS /* */
- X#ifdef KEY_RIGHT /* If this is defined in curses.h, the curses package */
- X#define USE_CURKEY /* supports keypad mode, and can trap our keys itself. */
- X#endif /* Otherwise, we have to use our own esc-sequences. / */
- X#endif /* */
- X
- X/*
- X * USER-DEFINABLE DEFINITIONS -----------------------------------------------
- X *
- X */
- X
- X#ifndef MAX_REL
- X#define MAX_REL 100 /* Max relations open at once for any given user */
- X#endif
- X#ifndef MAX_FLD
- X#define MAX_FLD 40 /* Maximum number of fields in a relation */
- X#endif
- X#ifndef MAX_IDX
- X#define MAX_IDX 20 /* Maximum number of indices in a relation */
- X#endif
- X#ifndef MAX_CACHE
- X#define MAX_CACHE 500 /* Maximum # of records to cache before flushing */
- X#endif
- X
- X/*
- X * ERROR CODES --------------------------------------------------------------
- X *
- X */
- X
- Xtypedef enum
- X {
- X MB_OKAY = 0,
- X MB_NO_ROOM, /* MAX_REL is #defined to be too small */
- X MB_NO_MEMORY, /* Not enough memory for requested task */
- X MB_NO_OPEN, /* Cannot open given filename */
- X MB_NO_READ, /* Cannot read given filename */
- X MB_FORMAT, /* Relation is not in MB 4.0+ format */
- X MB_LOCKED, /* Relation is locked by another user */
- X MB_BUSY, /* Relation has too many users at once */
- X MB_BAD_REL, /* Function passed bad relation struct */
- X MB_NO_WRITE, /* Cannot write given filename */
- X MB_TIMEOUT, /* Temporary lock has not been removed */
- X MB_BAD_REC, /* A null rec pointer has been received */
- X MB_CORRUPT, /* A corrupt index has been detected */
- X MB_BAD_DUP, /* Addition would violate a nodups idx */
- X MB_NO_CURR, /* Current record required for operation */
- X MB_BAD_IDX, /* A bad index number has been received */
- X MB_NO_SUCH, /* The specified record can't be found */
- X MB_UNKNOWN, /* Search command invalid */
- X MB_NO_FIELDS, /* The new relation has no fields */
- X MB_NO_INDICES, /* The new relation has no indices */
- X MB_BAD_INDEX, /* A proposed new index has no fields */
- X MB_DISKFULL, /* There is not enough free space left */
- X MB_BAD_SERIAL, /* Serial #'s for records can't change */
- X MB_TMPDIR, /* You must define a TMP directory */
- X MB_TMPERR, /* Cannot work with TMP directory */
- X } mb_err;
- X
- X/*
- X * SEARCH CRITERIA ----------------------------------------------------------
- X *
- X */
- X
- Xtypedef enum
- X {
- X FRST = 0,
- X LAST,
- X CURR,
- X NEXT,
- X PREV,
- X GTEQ,
- X GTHN,
- X LTEQ,
- X LTHN,
- X EQUL
- X } mb_action;
- X
- Xtypedef enum
- X {
- X T_CHAR = 0, /* 0 -- length ? (char []) */
- X T_SHORT, /* 1 -- length 2 (short) */
- X T_USHORT, /* 2 -- length 2 (unsigned short) */
- X T_LONG, /* 3 -- length 4 (long) */
- X T_ULONG, /* 4 -- length 4 (unsigned long) */
- X T_FLOAT, /* 5 -- length 4 (float) */
- X T_DOUBLE, /* 6 -- length 8 (double) */
- X T_MONEY, /* 7 -- length 8 (double) */
- X T_TIME, /* 8 -- length 4 (long) */
- X T_DATE, /* 9 -- length 4 (long) */
- X T_SERIAL, /* 10 -- length 4 (long) */
- X T_PHONE /* 11 -- lenght 20 (char []) */
- X } ftype;
- X
- X#define FIRST FRST
- X#define CURRENT CURR
- X#define PREVIOUS PREV
- X#define GTHAN GTHN
- X#define LTHAN LTHN
- X#define EQUAL EQUL
- X
- X#define AR_UP (char)129 /* Arrows for input.c */
- X#define AR_DOWN (char)130
- X#define AR_LEFT (char)131
- X#define AR_RIGHT (char)132
- X#define AR_INS (char)133 /* Insert, Delete, Home, End, PgUp, PgDn */
- X#define AR_DEL (char)134
- X#define AR_HOME (char)135
- X#define AR_END (char)136
- X#define AR_PGUP (char)137
- X#define AR_PGDN (char)138
- X
- X/*
- X * TIME/DATE/PHONE STRUCTURES -----------------------------------------------
- X *
- X */
- X
- Xtypedef long mb_time;
- Xtypedef long mb_date;
- Xtypedef char mb_phone[20];
- X
- X/*
- X * RELATION STRUCTURE -------------------------------------------------------
- X *
- X */
- X
- Xtypedef struct
- X {
- X int relcode; /* File handle for relation */
- X int lckcode; /* Handle for lockfile */
- X int num_i, num_f, rec_len;
- X long recz, pos, hack;
- X long serial; /* Serial value last queried */
- X int iser; /* Serial field index, or num_f */
- X
- X char relname[30]; /* Relation name--no path */
- X
- X int start[MAX_FLD], siz[MAX_FLD]; /* Byte-wise info for fields */
- X ftype type[MAX_FLD]; /* Field types */
- X char name[MAX_FLD][21]; /* Field names */
- X
- X int itype[MAX_IDX]; /* Dups/Nodups */
- X char idxs[MAX_IDX][100]; /* Index fields */
- X char iname[MAX_IDX][21]; /* Index name */
- X
- X char mask; /* Encryption mask */
- X ushort pid; /* This Process ID */
- X int rdonly; /* True if we can't write */
- X int exc; /* True if we've locked it */
- X int ver; /* Version number */
- X
- X char strobe[30]; /* Last read strobe value for each strobe */
- X mb_time times[30]; /* Time strobe value last changed */
- X } relation;
- X
- X#define RNULL (relation *)0
- X
- X/*
- X * DEFINITIONS --------------------------------------------------------------
- X *
- X */
- X
- X#ifndef UTIL_C
- X#define mb_inc(a,b) mb_open(a,b,0)
- X#define mb_old(a,b) mb_open(a,b,1)
- X#define mb_tst(a) mb_test(a,0)
- X
- X#define MB_IncludeRelation mb_inc
- X#define MB_TestInclude mb_tst
- X#define MB_RemoveRelation mb_rmv
- X#define MB_CloseAllRelations mb_die
- X#define MB_NumberOfRecords mb_num
- X#define MB_ResetNumUsers mb_rst
- X#define MB_AddRecord mb_add
- X#define MB_DeleteRecord mb_del
- X#define MB_DebugRelation mb_dbg
- X#define MB_UpdateRecord mb_upd
- X#define MB_SelectRecord mb_sel
- X#define MB_LockRelation mb_lck
- X#define MB_UnlockRelation mb_unl
- X#define MB_FormatDate fmt_date
- X#define MB_FormatTime fmt_time
- X#define MB_FormatPhone fmt_phone
- X#define MB_ScanDate scn_date
- X#define MB_ScanTime scn_time
- X#define MB_ScanPhone scn_phone
- X#endif
- X
- X#define curtime() tmtotime((struct tm *)0)
- X#define curdate() tmtodate((struct tm *)0)
- X#define curdatetime() datetimetotm((mb_date)0,(mb_time)0)
- X#define iswhite(x) (x==' ' ||x=='\n' ||x=='\r' ||x=='\t')
- X#define istoken(x) (x==',' ||x==':' ||x==';' ||x=='#' ||x=='(' || x==')')
- X#define putback(f) lseek(f,_lpos,0)
- X
- X/*
- X * GLOBAL VARIABLES ---------------------------------------------------------
- X *
- X */
- X
- X#ifdef INPUT_C
- X char quit_chars[20] = "";
- X WINDOW *win = (WINDOW *)0;
- X#else
- X extern WINDOW *win;
- X extern char quit_chars[20];
- X#endif
- X
- X#ifdef MBASE_C
- X char *mb_error = "";
- X mb_err mb_errno = MB_OKAY;
- X#else
- X extern char *mb_error;
- X extern mb_err mb_errno;
- X#endif
- X
- X/*
- X * DATA ENTRY STRUCTURES ----------------------------------------------------
- X *
- X */
- X
- X#define FM_IN 1
- X#define FM_OUT 2
- X#define FM_INOUT (FM_IN|FM_OUT)
- X#define fm_refrnum(f,n) fm_refresh(f,&(form->fields[n]))
- X
- Xtypedef int (*int_fn)();
- X
- Xtypedef struct
- X { int y, x, len;
- X ftype type;
- X int inout, option;
- X int *mode;
- X dataptr buffer;
- X char name[40];
- X charptr *opt_arr; } field;
- X
- Xtypedef struct
- X { int curmode;
- X int key; /* Return code from input() */
- X int curfield;
- X int nextfield;
- X int numfields;
- X int nummodes;
- X int_fn valid_fn;
- X int numlines, y, x;
- X field *fields;
- X charptr *_scrn; } de_form;
- X
- X/*
- X * FUNCTION PROTOTYPES ------------------------------------------------------
- X *
- X */
- X
- X#ifdef LONGARGS
- X
- X#ifndef UTIL_C
- X extern relation *mb_open (char *, int, int);
- X extern mb_err mb_test (char *, int);
- X extern mb_err mb_rmv (relation *);
- X extern void mb_die (void);
- X extern long mb_num (relation *);
- X extern mb_err mb_rst (relation *, int);
- X extern mb_err mb_add (relation *, dataptr);
- X extern mb_err mb_upd (relation *, dataptr);
- X extern mb_err mb_del (relation *);
- X extern void mb_dbg (relation *);
- X extern mb_err mb_sel (relation *, int, dataptr, mb_action, dataptr);
- X extern int compare (relation *, char *, char *, int);
- X extern int idxnum (relation *, char *);
- X extern void mb_exit (int);
- X extern int strtokey (char *);
- X extern mb_err mb_lck (relation *);
- X#endif
- X
- X extern mb_err _chk_elck (relation *);
- X extern mb_err mb_unl (relation *);
- X extern void strzcpy (char *, char *, int);
- X
- X#ifndef MBASE_C
- X extern long elap_t (mb_time);
- X extern mb_time tmtotime (struct tm *);
- X extern mb_date tmtodate (struct tm *);
- X extern struct tm *datetimetotm (mb_date, mb_time);
- X extern char *fmt_date (mb_date, int);
- X extern char *fmt_time (mb_time, int);
- X extern char *fmt_phone (long, long, long, long, int);
- X extern void scn_phone (long *, long *, long *, long *, char *);
- X extern mb_date scn_date (char *);
- X extern mb_time scn_time (char *);
- X extern mb_time add_time (char *);
- X extern char input (dataptr, int, int);
- X extern char getarr (void);
- X extern void display (dataptr, int, int);
- X extern void init_curses(void);
- X extern int skip (int, char *);
- X extern void goeol (int, char *);
- X extern char *getword (int);
- X extern int fm_fldnum (de_form *, char *);
- X extern void reltoform (relation *, de_form *, dataptr);
- X extern void formtorel (de_form *, relation *, dataptr);
- X extern void fm_refresh (de_form *, field *);
- X extern void fm_refrall (de_form *);
- X extern void fm_zero (de_form *);
- X extern int do_form (de_form *);
- X extern dataptr fm_data (de_form *, char *);
- X extern void fm_mode (de_form *, int);
- X extern relation *mb_new (void);
- X extern mb_err mb_addindex (relation *, char *, int, char *);
- X extern mb_err mb_addfield (relation *, char *, ftype, long);
- X extern mb_err mb_create (relation *, char *, int);
- X extern int mb_getname (relation *, char *, int);
- X#endif
- X
- X#else /* ifndef LONGARGS */
- X
- X#ifndef UTIL_C
- X extern relation *mb_open();
- X extern mb_err mb_test();
- X extern mb_err mb_rmv();
- X extern void mb_die();
- X extern long mb_num();
- X extern mb_err mb_rst();
- X extern mb_err mb_add();
- X extern mb_err mb_upd();
- X extern mb_err mb_del();
- X extern void mb_dbg();
- X extern mb_err mb_sel();
- X extern int compare();
- X extern int idxnum();
- X extern void mb_exit();
- X extern int strtokey();
- X extern mb_err mb_lck();
- X#endif
- X
- X extern mb_err _chk_elck();
- X extern mb_err mb_unl();
- X extern void strzcpy();
- X
- X#ifndef MBASE_C
- X extern long elap_t();
- X extern mb_time tmtotime();
- X extern mb_date tmtodate();
- X extern struct tm *datetimetotm();
- X extern char *fmt_date();
- X extern char *fmt_time();
- X extern char *fmt_phone();
- X extern void scn_phone();
- X extern mb_date scn_date();
- X extern mb_time scn_time();
- X extern mb_time add_time();
- X extern char input();
- X extern char getarr();
- X extern void display();
- X extern void init_curses();
- X extern int skip();
- X extern void goeol();
- X extern char *getword();
- X extern int fm_fldnum();
- X extern void reltoform();
- X extern void formtorel();
- X extern void fm_refresh();
- X extern void fm_refrall();
- X extern void fm_zero();
- X extern int do_form();
- X extern dataptr fm_data();
- X extern void fm_mode();
- X extern relation *mb_new();
- X extern mb_err mb_addindex();
- X extern mb_err mb_addfield();
- X extern mb_err mb_create();
- X extern int mb_getname();
- X#endif
- X
- X#endif /* LONGARGS */
- X
- X#endif /* MBASE_H */
- X
- END_OF_FILE
- if test 12825 -ne `wc -c <'src/mbase.h'`; then
- echo shar: \"'src/mbase.h'\" unpacked with wrong size!
- fi
- # end of 'src/mbase.h'
- fi
- echo shar: End of archive 4 \(of 8\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-