home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / sources / misc / 4124 / src / util1.c
Encoding:
C/C++ Source or Header  |  1992-11-23  |  15.7 KB  |  639 lines

  1. /*
  2.  * METALBASE 5.0
  3.  *
  4.  * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  5.  *                                       [ t-richj@microsoft.com ]
  6.  */
  7.  
  8. #define UTIL_C
  9. #include "mbase.h"
  10. #include "internal.h"
  11.  
  12. extern int       _started;
  13. extern relation *_list[MAX_REL];
  14.  
  15. /****************************************************************************/
  16.  
  17. #ifdef LONGARGS
  18.    static void  _dec_user (relation *);
  19. #else
  20.    static void  _dec_user();
  21. #endif
  22.  
  23. void
  24. _seterr (err)
  25. mb_err   err;
  26. {
  27.    switch (mb_errno = err)
  28.       {
  29.       case MB_OKAY:     mb_error="No error";                             break;
  30.       case MB_NO_ROOM:  mb_error="MAX_REL is #defined to be too small";  break;
  31.       case MB_NO_MEMORY:mb_error="Not enough memory for requested task"; break;
  32.       case MB_NO_OPEN:  mb_error="Cannot open given filename";           break;
  33.       case MB_NO_READ:  mb_error="Cannot read given filename";           break;
  34.       case MB_FORMAT:   mb_error="Relation is not in MB 5.0 format";     break;
  35.       case MB_LOCKED:   mb_error="Relation is locked by another user";   break;
  36.       case MB_BUSY:     mb_error="Relation is too busy";                 break;
  37.       case MB_BAD_REL:  mb_error="Function passed bad relation struct";  break;
  38.       case MB_NO_WRITE: mb_error="Cannot write given to relation";       break;
  39.       case MB_TIMEOUT:  mb_error="Temporary lock has not been removed";  break;
  40.       case MB_BAD_REC:  mb_error="A null rec pointer has been received"; break;
  41.       case MB_CORRUPT:  mb_error="A corrupt index has been detected";    break;
  42.       case MB_BAD_DUP:  mb_error="Addition would violate a nodups idx";  break;
  43.       case MB_NO_CURR:  mb_error="Current record required for operation";break;
  44.       case MB_BAD_IDX:  mb_error="A bad index number has been received"; break;
  45.       case MB_NO_SUCH:  mb_error="The specified record can't be found";  break;
  46.       case MB_UNKNOWN:  mb_error="Search command invalid";               break;
  47.       case MB_NO_FIELDS:  mb_error="The new relation has no fields";     break;
  48.       case MB_NO_INDICES: mb_error="The new relation has no indices";    break;
  49.       case MB_BAD_INDEX:  mb_error="The new index has no fields";        break;
  50.       case MB_DISKFULL: mb_error="There is not enough free space left";  break;
  51.       case MB_BAD_SERIAL: mb_error="The record's serial number changed"; break;
  52.       case MB_TMPDIR:   mb_error="You must define a TMP directory";      break;
  53.       case MB_TMPERR:   mb_error="Cannot work with TMP directory";       break;
  54.       default:          mb_error="Undefined error--rebuild and pray";    break;
  55.       }
  56. }
  57.  
  58. relation *
  59. _fill_info (rel, fld, idx)
  60. relation   *rel;
  61. long             fld, idx;
  62. {
  63.    register int  i, j;
  64.    int           s, e;
  65.    char          temp[4], buf[128];
  66.    short         tshort;
  67. #ifdef STRUCT_4
  68.    int           done = 0;
  69. #endif
  70.  
  71.    rel->iser = rel->num_f;  /* Until we find otherwise */
  72.  
  73.    for (i=rel->rec_len=0; i<rel->num_f; i++)
  74.       {
  75.       if (lseek (rel->relcode, fld, 0) != fld)
  76.          {
  77.          _clr_lck (rel);  free (rel);
  78.          relerr (MB_FORMAT, RNULL);
  79.          }
  80.  
  81.       readx (rel->relcode,  buf,    1);  rel->type[i] = (ftype)buf[0];
  82.       readx (rel->relcode, &tshort, 2);
  83.       switch (rel->type[i])
  84.          {
  85.          case T_SHORT:
  86.          case T_USHORT:  rel->siz[i] =  2; /* sizeof(short)  */   break;
  87.          case T_FLOAT:   rel->siz[i] =  4; /* sizeof(float)  */   break;
  88.          case T_DOUBLE:
  89.          case T_MONEY:   rel->siz[i] =  8; /* sizeof(double) */   break;
  90.          case T_TIME:
  91.          case T_LONG:
  92.          case T_ULONG:   rel->siz[i] =  4; /* sizeof(long)   */   break;
  93.          case T_DATE:    rel->siz[i] =  4; /* sizeof(long)   */   break;
  94.          case T_PHONE:   rel->siz[i] = 20; /* char[20]       */   break;
  95.          case T_SERIAL:  rel->siz[i] =  4; /* sizeof(long)   */
  96.                          rel->iser = i;
  97.                         break;
  98.          default:  rel->siz[i] = (int)tshort;              break;
  99.          }
  100.  
  101. #ifdef STRUCT_1
  102.       if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
  103.          {
  104.          if (rel->siz[i] == 8)       rel->rec_len = round8(rel->rec_len);
  105.          else if (rel->siz[i] == 4)  rel->rec_len = round4(rel->rec_len);
  106.          else                        rel->rec_len = round2(rel->rec_len);
  107.          }
  108. #endif
  109.  
  110. #ifdef STRUCT_3
  111.       if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
  112.          {
  113.          if (rel->siz[i] == 2)  rel->rec_len = round2(rel->rec_len);
  114.          else                   rel->rec_len = round4(rel->rec_len);
  115.          }
  116. #endif
  117.  
  118. #ifdef STRUCT_4
  119.       if (rel->type[i] != T_CHAR && rel->type[i] != T_PHONE)
  120.          {
  121.          done=1;
  122.          rel->rec_len = round2(rel->rec_len);
  123.          }
  124. #endif
  125.  
  126.       rel->start[i] = rel->rec_len;
  127.       rel->rec_len += rel->siz[i];
  128.  
  129.       readx (rel->relcode, buf, 20);
  130.  
  131.       for (j=0; buf[j]!='|'; j++)
  132.          ;
  133.       fld += (long)j+4;  /* Advance to next field */
  134.  
  135.       buf[j] = 0;  strcpy (rel->name[i], buf);
  136.       }
  137.  
  138. #ifdef STRUCT_1
  139.    rel->rec_len = round8(rel->rec_len);
  140. #endif
  141.  
  142. #ifdef STRUCT_3
  143.    rel->rec_len = round4(rel->rec_len);
  144. #endif
  145.  
  146. #ifdef STRUCT_4
  147.    if (done)
  148.       rel->rec_len = round2(rel->rec_len);
  149. #endif
  150.  
  151.    if (lseek (rel->relcode, idx, 0) != idx)
  152.       {
  153.       _clr_lck (rel);
  154.       free (rel);
  155.       relerr (MB_FORMAT, RNULL);
  156.       }
  157.  
  158.    for (i=0; i<rel->num_i; i++)
  159.       { 
  160.       readx (rel->relcode, buf,  1);  e=(int)buf[0];  /* Dups/NoDups */
  161.       readx (rel->relcode, buf,  1);  s=(int)buf[0];  /* Num/Fields  */
  162.       readx (rel->relcode, buf, 20);
  163.  
  164.       for (j=0; buf[j]!=':'; j++)
  165.          ;
  166.  
  167.       idx += (long)j + 3L;
  168.       lseek (rel->relcode, idx, 0); /* Advance to index' fields */
  169.  
  170.       buf[j] = 0;
  171.       strcpy (rel->iname[i], buf);
  172.       rel->itype[i]=e;  sprintf (rel->idxs[i], "%03d", s);
  173.  
  174.       for (j=0; j<s; j++)
  175.          {
  176.          readx (rel->relcode, &tshort, 2);
  177.          sprintf (temp, "%03d", tshort);
  178.          strcat (rel->idxs[i], temp);
  179.          }
  180.  
  181.       idx = lseek (rel->relcode, 0L, 1);    /* Get current position */
  182.       }
  183.  
  184.    rel->hack = idx;  /* Current position == reserved segment */
  185.  
  186.    if (rel->ver == verCURRENT && ! rel->rdonly)
  187.       {
  188.       lseek (rel->lckcode, lckPOS_USERS, 0);
  189.       readx (rel->lckcode, buf, 1);
  190.       buf[0] = (char)((unsigned int)buf[0] +1);   /* Increment the   */
  191.       lseek (rel->lckcode, lckPOS_USERS, 0);      /* number of users */
  192.       writx (rel->lckcode, buf, 1);
  193.  
  194.       _clr_lck (rel);
  195.       }
  196.  
  197.    relerr (MB_OKAY, rel);
  198. }
  199.  
  200. void
  201. _close_proc (rel)
  202. relation    *rel;
  203. {
  204.    if (rel->ver == verCURRENT)
  205.       {
  206.       (void)mb_unl (rel);
  207.       _dec_user (rel);
  208.       }
  209.  
  210.    close (rel->relcode);
  211.    free  (rel);
  212. }
  213.  
  214. void
  215. _divine_mask (rel, key)
  216. relation     *rel;
  217. int                key;
  218. {
  219.    rel->mask = (char)(
  220.       ((key & (int)0x04) << 5) |  /* 00000100 -> 10000000 */
  221.       ((key & (int)0x30) << 1) |  /* 00110000 -> 01100000 */
  222.       ((key & (int)0x80) >> 3) |  /* 10000000 -> 00010000 */
  223.       ((key & (int)0x03) << 2) |  /* 00000011 -> 00001100 */
  224.       ((key & (int)0x40) >> 5) |  /* 01000000 -> 00000010 */
  225.       ((key & (int)0x08) >> 3));  /* 00001000 -> 00000001 */
  226. }
  227.  
  228. int
  229. _identify (rel)
  230. relation  *rel;
  231. {
  232.    register int  i;
  233.    if (rel == RNULL || !_started)  return -1;
  234.    for (i=0; i<MAX_REL; i++)
  235.       if (_list[i] == rel)  break;
  236.    if (i == MAX_REL)   return -1;
  237.    if (rel->ver != verCURRENT)  return -2;
  238.    return i;
  239. }
  240.  
  241. mb_err
  242. _format  (rel, rec, stage)
  243. relation *rel;
  244. dataptr        rec;
  245. int                 stage;
  246. {
  247.    register int  i;
  248.    double        tdbl;
  249.    long          nexts, tlong;
  250.    int           a;
  251.    long          ac,pre,num,ext;
  252.    char         *pch, temp[25];
  253.  
  254.    if (! rec)  baderr (MB_BAD_REC);
  255.  
  256.    if (stage == 2)
  257.     { GO_NEXTS (rel);
  258.       readx    (rel->relcode, &nexts, 4);
  259.     }
  260.  
  261.    for (i=a=0; i<rel->num_f; i++)
  262.       {
  263.       if (stage == 1)
  264.          {
  265.          if (rel->type[i] == T_PHONE)
  266.             {
  267.             pch = (char *)rec + rel->start[i];
  268.             scn_phone (&ac,&pre,&num,&ext, pch);
  269.             strcpy (temp, fmt_phone (ac,pre,num,ext, -1));
  270.             strncpy (pch, temp, 20);
  271.             }
  272.          if (rel->type[i] == T_MONEY)
  273.             {
  274.             tdbl = *(double *)((char *)rec+rel->start[i]);
  275.             tlong = (long)(tdbl * 100.0);  tdbl = (double)tlong / 100.0;
  276.             *(double *)((char *)rec+rel->start[i]) = tdbl;
  277.             }
  278.          }
  279.       else
  280.          {
  281.          if (rel->type[i] == T_SERIAL)
  282.             {
  283.             *(long *)((char *)rec+rel->start[i]) = nexts;
  284.             rel->serial = nexts;
  285.             _cryptf ((dataptr)((char *)rec+rel->start[i]), 4, rel->mask);
  286.             a = 1;
  287.             }
  288.          }
  289.       }
  290.  
  291.    if (a)
  292.       {
  293.       GO_NEXTS (rel);  nexts++;
  294.       writx    (rel->relcode, &nexts, 4);
  295.       }
  296.  
  297.    return MB_OKAY;
  298. }
  299.  
  300. void
  301. _crypt   (rel, rec)
  302. relation *rel;
  303. dataptr        rec;
  304. {
  305. #ifndef NOENCRYPT
  306.    register int  i;
  307.  
  308.    if (rel->mask)
  309.       for (i=0; i<rel->num_f; i++)
  310.          _cryptf ((char *)rec+rel->start[i], rel->siz[i], rel->mask);
  311. #else
  312.    ;  /* Some compilers complain about null-functions */
  313. #endif
  314. }
  315.  
  316. void
  317. _cryptf (rec, siz, mask)
  318. dataptr  rec;
  319. int           siz, mask;
  320. {
  321. #ifndef NOENCRYPT
  322.    register int    i;
  323.    register char  *c;
  324.  
  325.    if (mask != 0)
  326.       for (i=0,c=rec; i<siz; i++,c++)
  327.        { *c ^= mask;
  328.          mask  = (mask + 1) & (int)0xFF;
  329.        }
  330. #else
  331.    ;  /* Some compilers complain about null-functions */
  332. #endif
  333. }
  334.  
  335. mb_err
  336. _check_dup (rel, rec, idx, ign)
  337. relation   *rel;
  338. dataptr          rec;
  339. int                   idx;
  340. long                       ign;
  341. {
  342.    dataptr  mem;
  343.    long     pos;
  344.    int      dir;
  345.  
  346.    if (rel->itype[idx] == 1)  reterr (MB_OKAY, 0);
  347.  
  348.    GO_TOP (rel, idx);
  349.    readx (rel->relcode, &pos, 4);
  350.    if (pos==0L)
  351.       reterr (MB_OKAY, 0);
  352.  
  353.    if ((mem = (dataptr)malloc (1+ rel->rec_len)) == NULL)
  354.       reterr (MB_NO_MEMORY, -1);
  355.  
  356.    for (;;)
  357.       {
  358.       dir = _compare (rel, rec, _memrec(rel,pos,mem), idx);
  359.  
  360.       if (dir == 0)
  361.          {
  362.          if (pos == ign)  break;  /* If we're about to change the rec, okay */
  363.          free (mem);
  364.  
  365.          reterr (MB_BAD_DUP, -1);
  366.          }
  367.  
  368.       GO_POINT (rel, pos, idx, dir);
  369.       readx (rel->relcode, &pos, 4);
  370.  
  371.       if (pos == 0L)  break;
  372.       }
  373.    free (mem);
  374.  
  375.    reterr (MB_OKAY, MB_OKAY);
  376. }
  377.  
  378. long
  379. _append  (rel, rec)
  380. relation *rel;
  381. dataptr        rec;
  382. {
  383.    long           rcd, temp;
  384.    register int   i;
  385.    char           buf[2];
  386.  
  387.    lseek (rel->relcode, POS_NUMREC, 0);
  388.    readx (rel->relcode, &rcd, 4);  rcd++;
  389.    lseek (rel->relcode, POS_NUMREC, 0);
  390.    writx (rel->relcode, &rcd, 4);
  391.  
  392.    GO_START (rel, rcd);
  393.  
  394.    for (i=0,temp=0L,buf[0]=BAL_EV; i<rel->num_i; i++)
  395.       {
  396.       writx (rel->relcode, &temp, 4);
  397.       writx (rel->relcode, &temp, 4);
  398.       writx (rel->relcode, &temp, 4);
  399.       writx (rel->relcode, buf,   1);
  400.       }
  401.    writx (rel->relcode, rec, rel->rec_len);
  402.  
  403.    return rcd;
  404. }
  405.  
  406. void
  407. _remove  (rel, bad)
  408. relation *rel;
  409. long           bad;
  410. {
  411.    int      i,   dir;
  412.    long     rep, tmp;
  413.    char     temp[5];
  414.    dataptr  buf;
  415.  
  416.    lseek (rel->relcode, POS_NUMREC, 0);
  417.    readx (rel->relcode, &rep, 4);  rep--;
  418.    lseek (rel->relcode, POS_NUMREC, 0);
  419.    writx (rel->relcode, &rep, 4);  rep++;  /* Find replacement record */
  420.  
  421.    if (rep == bad)  return;
  422.  
  423.    if ((buf=(dataptr)malloc (rel->rec_len +13*rel->num_i +1)) == NULL)  return;
  424.  
  425.    GO_START (rel, rep);
  426.    readx    (rel->relcode, buf, rel->rec_len +13*rel->num_i);
  427.    GO_START (rel, bad);
  428.    writx    (rel->relcode, buf, rel->rec_len +13*rel->num_i);
  429.  
  430.    for (i = 0; i < rel->num_i; i++)
  431.       {
  432.       GO_POINT (rel, rep, i, 0);
  433.       readx (rel->relcode, &tmp, 4);
  434.       GO_BAL   (rel, rep, i);
  435.       readx (rel->relcode, temp, 1);  dir = (temp[0] & PARDIR);
  436.  
  437.       if (tmp == 0L)
  438.          GO_TOP (rel, i);
  439.       else
  440.          GO_POINT (rel, tmp, i, (dir ? 1 : -1));
  441.       writx (rel->relcode, &bad, 4);
  442.  
  443.       GO_POINT (rel, rep, i, -1);
  444.       readx (rel->relcode, &tmp, 4);
  445.       if (tmp != 0L)
  446.          {
  447.          GO_POINT (rel, tmp, i, 0);
  448.          writx (rel->relcode, &bad, 4);
  449.          }
  450.  
  451.       GO_POINT (rel, rep, i, 1);
  452.       readx (rel->relcode, &tmp, 4);
  453.       if (tmp != 0L)
  454.          {
  455.          GO_POINT (rel, tmp, i, 0);
  456.          writx (rel->relcode, &bad, 4);
  457.          }
  458.       }
  459.  
  460.    free (buf);
  461. }
  462.  
  463. mb_err
  464. _link    (rel, rcd)   /* CACHED */
  465. relation *rel;
  466. long           rcd;
  467. {
  468.    register int  i;
  469.  
  470.    _free_cache ();
  471.  
  472.    for (i=0; i<rel->num_i; i++)
  473.       {
  474.       _drop (rel, rcd, i, 0L);
  475.       if (_check (rel, rcd, 0L, i))
  476.          {
  477.          _flush_cache (rel, i);
  478.          return mb_errno;
  479.          }
  480.       _flush_cache (rel, i);
  481.       }
  482.    return MB_OKAY;
  483. }
  484.  
  485. void
  486. _drop    (rel, rcd, idx, top)  /* CACHED */
  487. relation *rel;
  488. long           rcd,      top;
  489. int                 idx;
  490. {
  491.    long     pos, par;
  492.    int      dir;
  493.    char     temp[5];
  494.    dataptr  a, b;
  495.    cache   *ptr;
  496.  
  497.    ptr = _read_cache (rel, top, idx);
  498.    if (top == 0L)
  499.       {
  500.       pos = ptr->num;
  501.       par = 0L;
  502.       }
  503.    else
  504.       {
  505.       par = ptr->parent;
  506.       pos = top;
  507.       }
  508.  
  509.    a = (dataptr)malloc (1+ rel->rec_len);
  510.    b = (dataptr)malloc (1+ rel->rec_len);
  511.  
  512.    for ( ; pos != 0L; )
  513.       {
  514.       ptr = _read_cache (rel, pos, idx);
  515.       temp[0] = ptr->parbal;
  516.  
  517.       dir = _compare (rel, _memrec(rel,rcd,a), b=_memrec(rel,pos,b), idx );
  518. /*
  519.  * POSSIBLE ERROR POINT -- _memrec is being used twice in one
  520.  * function call.  If it's going to be a problem, it'll show up after
  521.  * the second add, delete or update.... if it doesn't, this isn't
  522.  * the cause of your trouble.
  523.  *
  524.  */
  525.  
  526.       if (dir == 0)
  527.          {
  528.          dir = ((temp[0] & BAL) == BAL_RT || (temp[0] & BAL) == BAL_FR) ? -1:1;
  529.          }
  530.       temp[0] += dir;
  531.  
  532.       _change_cache (ptr, parbal, temp[0]);
  533.  
  534.       par = pos;
  535.       pos = _cache_field (ptr, dir);
  536.       }
  537.  
  538.    free (a);  free (b);
  539.  
  540.    if (par == 0L)
  541.       {
  542.       ptr = _read_cache (rel, 0L, idx);
  543.       _change_cache (ptr, num, rcd);
  544.       }
  545.    else
  546.       {
  547.       temp[0] = (char)(((dir==1) ? PARDIR:0) | BAL_EV);
  548.  
  549.       ptr = _read_cache (rel, rcd, idx);
  550.       _change_cache (ptr, parbal, temp[0]);
  551.  
  552.       ptr = _read_cache (rel, par, idx);
  553.       if (dir == -1)      _changeqcache (ptr, left, rcd);
  554.       else if (dir == 0)  _changeqcache (ptr, parent, rcd);
  555.       else                _changeqcache (ptr, right, rcd);
  556.       ptr->changed = 1;
  557.       }
  558.  
  559.    ptr = _read_cache (rel, rcd, idx);
  560.    _change_cache (ptr, parent, par);
  561. }
  562.  
  563. mb_err
  564. _check   (rel, st, ed, idx)  /* CACHED */
  565. relation *rel;
  566. long           st, ed;
  567. int                    idx;
  568. {
  569.    long   pos, tmp;
  570.    cache *ptr;
  571.  
  572.    for (pos = st; pos != ed; )
  573.       {
  574.       if (pos == 0L)  break;
  575.  
  576.       ptr = _read_cache (rel, pos, idx);
  577.       tmp = ptr->parent;
  578.  
  579.       if (! BALANCED ( (ptr->parbal & BAL) ))
  580.          if (_balance (rel, pos, idx, (int)(ptr->parbal & BAL)))
  581.             return mb_errno;
  582.       pos = tmp;
  583.       }
  584.  
  585.    return MB_OKAY;
  586. }
  587.  
  588. /****************************************************************************/
  589.  
  590. int
  591. compare  (rel, ptra, ptrb, idx)  /* -1 == ptra < ptrb */
  592. relation *rel;
  593. dataptr        ptra, ptrb;
  594. int                        idx;
  595. {
  596.    int  i;
  597.    if (_identify (rel) < 0)           interr (MB_BAD_REL, -1);
  598.    if (idx < 0 || idx >= rel->num_i)  interr (MB_BAD_IDX, -1);
  599.    if (ptra == ptrb)                  interr (MB_OKAY,     0);
  600.  
  601.    _crypt (rel, ptra);
  602.    _crypt (rel, ptrb);
  603.    i = _compare (rel, ptra, ptrb, idx);
  604.    _crypt (rel, ptra);
  605.    _crypt (rel, ptrb);
  606.    interr (MB_OKAY, i);
  607. }
  608.  
  609. int
  610. idxnum   (rel, name)
  611. relation *rel;
  612. char          *name;
  613. {
  614.    int  i;
  615.  
  616.    if (_identify (rel) < 0)  interr (MB_BAD_REL, -1);
  617.  
  618.    for (i = 0; i < rel->num_i; i++)
  619.       if (! strcmp (name, rel->iname[i]))
  620.          break;
  621.    if (i == rel->num_i)  interr (MB_BAD_IDX, -1);
  622.  
  623.    interr (MB_OKAY, i);
  624. }
  625.  
  626. static void
  627. _dec_user (rel)
  628. relation  *rel;
  629. {
  630.    char  buf[2];
  631.  
  632.    lseek (rel->lckcode, lckPOS_USERS, 0);
  633.    readx (rel->lckcode, buf, 1);
  634.    buf[0] = (char)((unsigned int)buf[0] -1);
  635.    if ((uchar)buf[0] > 254)  buf[0] = 0;
  636.    lseek (rel->lckcode, lckPOS_USERS, 0);  writx (rel->lckcode, buf, 1);
  637. }
  638.  
  639.