home *** CD-ROM | disk | FTP | other *** search
- /*
- * METALBASE 5.1
- *
- * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
- *
- */
-
- #include <mbase.h>
- #include "internal.h"
-
-
- /*
- * PROTOTYPES -----------------------------------------------------------------
- *
- */
-
- static mb_err _balance XARGS( (relation *, long, int, int) );
-
- static int _comp_fld XARGS( (relation *, dataptr, dataptr, int) );
- static int _comp_short XARGS( (short *, short *) );
- static int _comp_ushort XARGS( (ushort *, ushort *) );
- static int _comp_long XARGS( (long *, long *) );
- static int _comp_ulong XARGS( (ulong *, ulong *) );
- static int _comp_float XARGS( (float *, float *) );
- static int _comp_double XARGS( (double *, double *) );
- static int _comp_string XARGS( (char *, char *, int) );
- static int _comp_byte XARGS( (dataptr, dataptr, int) );
- static int _comp_phone XARGS( (mb_phone *, mb_phone *) );
-
-
- /*
- * ROUTINES -------------------------------------------------------------------
- *
- */
-
- byte *
- numcpy (new, old, num)
- byte *new,*old;
- int num;
- {
- if (new)
- {
- if (old)
- {
- for ( ; num; num--)
- *new++ = *old++;
- }
- else
- {
- for ( ; num; num--)
- *new++ = (byte)0;
- }
- }
- return new;
- }
-
- charptr
- strzcpy (new, old, num)
- charptr new, old;
- int num;
- {
- if (new && old)
- {
- for ( ; num && *old; num--)
- *new++ = *old++;
- *new = 0;
- }
-
- return new;
- }
-
- int
- fldnum (rel, name)
- relation *rel;
- charptr name;
- {
- int fld;
-
- for (fld = 0; fld < rel->nFld; fld++)
- if (! strcmp (name, rel->fldName[fld]))
- break;
-
- if (fld == rel->nFld)
- {
- SetError (MB_BAD_FLD);
- return -1;
- }
-
- SetError (MB_OKAY);
- return fld;
- }
-
- int
- idxnum (rel, name)
- relation *rel;
- charptr name;
- {
- int idx;
-
- for (idx = 0; idx < rel->nIdx; idx++)
- if (! strcmp (name, rel->idxName[idx]))
- break;
-
- if (idx == rel->nIdx)
- {
- SetError (MB_BAD_IDX);
- return -1;
- }
-
- SetError (MB_OKAY);
- return idx;
- }
-
-
- /*
- * SERVICE ROUTINES -----------------------------------------------------------
- *
- */
-
- int
- _identify (rel)
- relation *rel;
- {
- register int i;
-
- if (rel == RNULL || !fStarted)
- return -1;
-
- for (i = 0; i < MAX_REL; i++)
- if (aRel[i] == rel)
- break;
-
- if (i == MAX_REL)
- return -1;
-
- if (rel->ver < verLOWEST || rel->ver > verCURRENT)
- return -2;
-
- return i;
- }
-
- mb_err
- _drop (rel, rcd, idx, top) /* CACHED */
- relation *rel;
- long rcd, top;
- int idx;
- {
- dataptr a, b;
- cache *ptr;
- long pos, par;
- int dir;
- char temp;
-
- ptr = _read_cache (rel, top, idx);
- if (top == 0L)
- {
- pos = ptr->num;
- par = 0L;
- }
- else
- {
- par = ptr->parent;
- pos = top;
- }
-
- if ((a = (dataptr)malloc (rel->cbRecord +1)) == (dataptr)0)
- {
- Error (MB_NO_MEMORY);
- }
- if ((b = (dataptr)malloc (rel->cbRecord +1)) == (dataptr)0)
- {
- Error_2 (MB_NO_MEMORY);
- }
-
- _memrec (rel, a, rcd);
-
- for ( ; pos != 0L; )
- {
- ptr = _read_cache (rel, pos, idx);
- temp = ptr->parbal;
-
- _memrec (rel, b, pos);
-
- if ((dir = _compare (rel, a, b, idx)) == 0)
- {
- dir = ((temp & BAL) > BAL_EV) ? -1 : 1;
- }
- temp += dir;
-
- _change_cache (ptr, parbal, temp);
-
- par = pos;
- pos = _cache_field (ptr, dir);
- }
-
- if (par == 0L)
- {
- ptr = _read_cache (rel, 0L, idx);
- _change_cache (ptr, num, rcd);
- }
- else
- {
- temp = (char)(((dir==1) ? PARDIR:0) | BAL_EV);
-
- ptr = _read_cache (rel, rcd, idx);
- _change_cache (ptr, parbal, temp);
-
- ptr = _read_cache (rel, par, idx);
- if (dir == -1) _changeqcache (ptr, left, rcd);
- else if (dir == 0) _changeqcache (ptr, parent, rcd);
- else _changeqcache (ptr, right, rcd);
- ptr->changed = 1;
- }
-
- ptr = _read_cache (rel, rcd, idx);
- _change_cache (ptr, parent, par);
-
- SetError (MB_OKAY);
-
- free (b);
-
- lblERROR_2:
- free (a);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- _check (rel, st, ed, idx) /* CACHED */
- relation *rel;
- long st, ed;
- int idx;
- {
- cache *ptr;
- long pos, tmp;
-
- for (pos = st; pos != ed; )
- {
- if (pos == 0L) break;
-
- ptr = _read_cache (rel, pos, idx);
- tmp = ptr->parent;
-
- if (! BALANCED ( (ptr->parbal & BAL) ))
- if (_balance (rel, pos, idx, (int)(ptr->parbal & BAL)))
- {
- Error (mb_errno);
- }
- pos = tmp;
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
-
- /*
- * COMPARISON FUNCTIONS -------------------------------------------------------
- *
- */
-
- int
- compare (rel, ptra, ptrb, idx) /* -1 = ptra < ptrb */
- relation *rel; /* 1 = ptra > ptrb */
- dataptr ptra, ptrb; /* 0 = ptra == ptrb */
- int idx; /* -2 = error */
- {
- int x = -2; /* Error condition */
-
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (idx < 0 || idx >= rel->nIdx) Error (MB_BAD_IDX);
-
- if (ptra == ptrb) Error (MB_OKAY);
-
-
- /*
- * _compare() expects the records it compares to be encrypted, so encrypt and
- * decrypt the records we get, around the function call. Note that we do not
- * assign temp files to multi-length fields; since indices can't be placed on
- * that kind of field, there's no reason to worry about 'em here.
- *
- */
-
- _encrypt (rel, ptra);
- _encrypt (rel, ptrb);
- x = _compare (rel, ptra, ptrb, idx);
- _decrypt (rel, ptra);
- _decrypt (rel, ptrb);
-
- SetError (MB_OKAY);
-
- lblERROR:
- return x;
- }
-
- int
- _compare (rel, ptra, ptrb, idx) /* -1 = ptra < ptrb */
- relation *rel; /* 1 = ptra > ptrb */
- dataptr ptra, ptrb; /* 0 = ptra == ptrb */
- int idx;
- {
- register int i;
- int n;
-
- for (i = 0; i < rel->nIdxFld[idx]; i++)
- {
- if ((n = _comp_fld (rel, ptra, ptrb, rel->idxFld[idx][i])) != 0)
- {
- return n;
- }
- }
-
- return 0;
- }
-
- static int
- _comp_fld (rel, ptra, ptrb, fld)
- relation *rel;
- dataptr ptra, ptrb;
- int fld;
- {
- charptr a, b;
- int n;
-
- n = rel->cbLen[fld];
- a = (charptr)ptra + rel->cbStart[fld];
- b = (charptr)ptrb + rel->cbStart[fld];
-
- _decryptf (a, n, rel->mask);
- _decryptf (b, n, rel->mask);
-
- switch (rel->fldType[fld])
- {
- case T_SHORT: n = _comp_short ((short *)a, (short *)b); break;
- case T_USHORT: n = _comp_ushort ((ushort *)a, (ushort *)b); break;
- case T_LONG: n = _comp_long ((long *)a, (long *)b); break;
- case T_ULONG: n = _comp_ulong ((ulong *)a, (ulong *)b); break;
- case T_FLOAT: n = _comp_float ((float *)a, (float *)b); break;
- case T_DOUBLE: n = _comp_double ((double *)a, (double *)b); break;
- case T_MONEY: n = _comp_double ((double *)a, (double *)b); break;
- case T_TIME: n = _comp_long ((long *)a, (long *)b); break;
- case T_DATE: n = _comp_long ((long *)a, (long *)b); break;
- case T_SERIAL: n = _comp_long ((long *)a, (long *)b); break;
- case T_BYTE: n = _comp_byte ((byte *)a, (byte *)b, n); break;
- case T_PHONE: n = _comp_phone ((mb_phone *)a, (mb_phone *)b); break;
- default: n = _comp_string (a, b, n); break;
- }
-
- _encryptf (b, rel->cbLen[fld], rel->mask);
- _encryptf (a, rel->cbLen[fld], rel->mask);
-
- return n;
- }
-
- static int
- _comp_byte (a, b, n)
- byte *a,*b;
- int n;
- {
- for ( ; n; n--)
- {
- if (*a < *b) return -1;
- if (*a > *b) return 1;
- a++;
- b++;
- }
- return 0;
- }
-
- static int
- _comp_short (a, b)
- short *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_ushort (a, b)
- ushort *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_long (a, b)
- long *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_ulong (a, b)
- ulong *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_float (a, b)
- float *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_double (a, b)
- double *a,*b;
- {
- return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
- }
-
- static int
- _comp_string (a, b, n)
- char *a,*b;
- int n;
- {
- int i;
- i = strncmp (a,b,n); /* THIS WON'T RETURN -1,0,1!! It returns */
- return (i < 0) ? -1 : (i > 0); /* different amounts on different systems */
- }
-
- static int
- _comp_phone (a, b)
- mb_phone *a,*b;
- {
- if (a->area != b->area) return ((a->area < b->area) ? -1 : 1);
- if (a->prefix != b->prefix) return ((a->prefix < b->prefix) ? -1 : 1);
- if (a->number != b->number) return ((a->number < b->number) ? -1 : 1);
- if (a->ext != b->ext) return ((a->ext < b->ext) ? -1 : 1);
-
- return 0;
- }
-
-
- /*
- * ENCRYPTION -----------------------------------------------------------------
- *
- */
-
- void
- _crypt (rel, rec)
- relation *rel;
- dataptr rec;
- {
- #ifdef NO_ENCRYPT
- (void)rel; /* Reference these arguments, so the compiler */
- (void)rec; /* won't complain. */
- #else
- register int i;
-
- if (rel->mask)
- {
- for (i = 0; i < rel->nFld; i++)
- {
- if (rel->fldType[i] != T_MCHAR && rel->fldType[i] != T_MBYTE)
- {
- _cryptf ((charptr)rec +rel->cbStart[i], rel->cbLen[i], rel->mask);
- }
- }
- }
- #endif
- }
-
- void
- _cryptf (rec, siz, mask)
- charptr rec;
- int siz, mask;
- {
- #ifdef NO_ENCRYPT
- (void)rec; /* Reference these arguments, so the compiler */
- (void)siz; /* won't complain. */
- (void)mask;
- #else
- register int i;
-
- if (mask != 0)
- {
- for (i = 0; i < siz; i++)
- {
- *rec ^= mask;
- mask = (mask + 1) & (int)0xFF;
- rec++;
- }
- }
- #endif
- }
-
-
- /*
- * SERVICE ROUTINES -----------------------------------------------------------
- *
- */
-
- static mb_err
- _balance (rel, rcd, idx, bal) /* CACHED */
- relation *rel;
- long rcd;
- int idx, bal;
- {
- long rep, rp;
- cache *ptr;
-
- if (! (rep = _find_seq (rel, 0L, rcd, idx, NUM_BAL(bal))) )
- {
- Error (MB_CORRUPT);
- }
-
- ptr = _read_cache (rel, rep, idx);
- rp = ptr->parent;
-
- _dislink (rel, rep, idx, rcd);
- _replace (rel, rcd, rep, idx);
-
- if (_drop (rel, rcd, idx, rep) != MB_OKAY)
- {
- Error (mb_errno);
- }
-
- if (rp != rcd)
- {
- if (_check (rel, rp, rep, idx) != MB_OKAY)
- {
- Error (mb_errno);
- }
- }
-
- ptr = _read_cache (rel, rcd, idx);
- rp = ptr->parent;
-
- if (_check (rel, rp, rep, idx) != MB_OKAY)
- {
- Error (mb_errno);
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- void
- _dislink (rel, pos, idx, end) /* CACHED */
- relation *rel;
- long pos, end;
- int idx;
- {
- char temp;
- long ch, par, tmp;
- int dir = 0, tdir;
- cache *ptr;
-
- ptr = _read_cache (rel, pos, idx); /* There will be one child, at most */
- ch = ptr->left;
- if (ch)
- dir = -1;
- else
- {
- ch = ptr->right; /* We already read in this record! */
- dir = (ch ? 1 : 0);
- }
-
- par = ptr->parent;
- temp = (char)((int)ptr->parbal & PARDIR);
- tdir = temp?1:-1;
-
- ptr = _read_cache (rel, par, idx);
- ptr->changed = 1;
- if (par == 0L)
- {
- _changeqcache (ptr, num, ch);
- }
- else
- {
- if (temp) _changeqcache (ptr, right, ch);
- else _changeqcache (ptr, left, ch);
- }
-
- if (ch)
- {
- ptr = _read_cache (rel, ch, idx);
- _change_cache (ptr, parent, par);
- temp = ptr->parbal;
- temp = (char)((int)(temp & BAL) | (tdir == 1 ? PARDIR : 0));
-
- _change_cache (ptr, parbal, temp);
- }
-
- for (tmp=par, dir=tdir; tmp != 0L; ) /* Update balances: */
- {
- ptr = _read_cache (rel, tmp, idx);
- temp = ptr->parbal;
- temp = (char)((int)(temp & PARDIR) | ((temp & BAL) - dir));
-
- _change_cache (ptr, parbal, temp);
-
- dir = (temp & PARDIR) ? 1 : -1;
- if (tmp == end) break;
-
- tmp = ptr->parent;
- }
- }
-
- void
- _replace (rel, old, new, idx) /* CACHED */
- relation *rel;
- long old, new;
- int idx;
- {
- char pba;
- long lef, rig, par;
- cache *ptr;
-
- ptr = _read_cache (rel, old, idx);
- lef = ptr->left;
- rig = ptr->right;
- par = ptr->parent;
- pba = ptr->parbal;
- ptr = _read_cache (rel, new, idx);
- _change_cache (ptr, left, lef);
- _changeqcache (ptr, right, rig);
- _changeqcache (ptr, parent, par);
- _changeqcache (ptr, parbal, pba);
-
- if (par == 0L) /* Parent */
- {
- ptr = _read_cache (rel, 0L, idx);
- _change_cache (ptr, num, new);
- }
- else
- {
- ptr = _read_cache (rel, par, idx);
- if (pba & PARDIR) _changeqcache (ptr, right, new);
- else _changeqcache (ptr, left, new);
- ptr->changed = 1;
- }
-
- if (lef != 0L) /* Left child */
- {
- ptr = _read_cache (rel, lef, idx);
- _change_cache (ptr, parent, new);
- }
-
- if (rig != 0L) /* Right child */
- {
- ptr = _read_cache (rel, rig, idx);
- _change_cache (ptr, parent, new);
- }
-
- ptr = _read_cache (rel, old, idx);
- _change_cache (ptr, parbal, BAL_EV);
- _changeqcache (ptr, left, 0L);
- _changeqcache (ptr, right, 0L);
- _changeqcache (ptr, parent, 0L);
- }
-
- long
- _find_seq (rel, top, rcd, idx, dir) /* CACHED */
- relation *rel;
- long top, rcd;
- int idx, dir;
- {
- char temp[5];
- long pos, tmp;
- cache *ptr;
-
- _strobe (rel, 0); /* Don't let anyone think we're dead */
-
- ptr = _read_cache (rel, rcd, idx);
- pos = _cache_field (ptr, dir);
-
- if (pos == 0L)
- {
- if (rcd == top) return 0L; /* hit top=no sequential available */
- for (pos = rcd; ; pos = tmp)
- {
- ptr = _read_cache (rel, pos, idx);
- tmp = ptr->parent;
-
- if (tmp == top) return 0L; /* hit top=no sequential available */
-
- temp[0] = ptr->parbal;
- if (dir == ((temp[0] & PARDIR) ? -1 : 1)) return tmp;
- }
- }
-
- for (dir = 0-dir; ; pos = tmp)
- {
- ptr = _read_cache (rel, pos, idx);
- tmp = _cache_field (ptr, dir);
- if (tmp == 0L) return pos;
- }
- }
-
- /*
- * HEX DISPLAY ----------------------------------------------------------------
- *
- */
-
- static char HexString[] = "0123456789ABCDEF";
-
- void
- strtohex (buf, str, num)
- dataptr buf;
- charptr str;
- int num;
- {
- byte *ptr;
- bool fHigh;
- int val;
-
- for (ptr = buf, fHigh = TRUE; num && *str; str++)
- {
- for (val = 0; val < 16; val++)
- if (HexString[val] == toupper(*str))
- break;
- if (val == 16)
- {
- if (! fHigh) /* If we just found 1 hex digit */
- {
- *ptr >>= 4;
- ptr++;
- num--;
- }
- fHigh = TRUE;
- continue;
- }
-
- if (fHigh)
- {
- *ptr = (byte)((int)val << 4);
- }
- else
- {
- *ptr |= (byte)val;
- ptr ++;
- num--;
- }
- fHigh = (fHigh) ? FALSE : TRUE;
- }
-
- if (! fHigh)
- {
- *ptr >>= 4;
- ptr++;
- num--;
- }
-
- for ( ; num; ptr++,num--)
- {
- *ptr = 0;
- }
- }
-
- void
- hextostr (str, buf, num) /* Requires ( 3*num -1 ) characters */
- charptr str;
- dataptr buf;
- int num;
- {
- byte *ptr;
-
- for (ptr = (byte *)buf; num; num--,ptr++)
- {
- if (ptr != (byte *)buf)
- *str++ = ' ';
- *str++ = HexString[ ((*ptr & 0xF0) >> 4) ];
- *str++ = HexString[ (*ptr & 0x0F) ];
- }
-
- *str = 0;
- }
-
-