home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c004 / 1.ddi / CTADDK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-18  |  17.0 KB  |  738 lines

  1. /*
  2.  *    add key
  3.  *
  4.  *    This program is the CONFIDENTIAL and PROPRIETARY property 
  5.  *    of FairCom(R) Corporation. Any unauthorized use, reproduction or
  6.  *    transfer of this program is strictly prohibited.
  7.  *
  8.  *      Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 FairCom Corporation
  9.  *    (Subject to limited distribution and
  10.  *     restricted disclosure only.)
  11.  *    *** ALL RIGHTS RESERVED ***
  12.  *
  13.  *    4006 West Broadway
  14.  *    Columbia, MO 65203
  15.  *
  16.  *
  17.  *    c-tree(R)    Version 4.3
  18.  *            Release C 
  19.  *            February 7, 1989 17:30
  20.  *
  21.  */
  22.  
  23. #include "ctstdr.h"        /* standard i/o header         */
  24. #include "ctoptn.h"        /* c-tree configuration options */
  25. #include "cterrc.h"        /* c-tree error codes        */
  26. #include "ctstrc.h"        /* c-tree data structures    */
  27. #include "ctgvar.h"        /* c-tree global variables    */
  28.  
  29. #ifdef VARLDATA
  30. #include "ctvrec.h"
  31. #endif
  32.  
  33. COUNT uerr(),putnod(),LOCK(),UNLOCK();
  34.  
  35. LOCAL TEXT   hghbuf[MAXLEN];
  36.  
  37. /* --------------------------------------------------------------------
  38.    ADDKEY enters the key value pointed to by target into the index file
  39.    specified by keyno and associates the value of recbyt with the key value.
  40.    if successful, ADDKEY returns a value of zero. if the index already
  41.    contains the key value, then a value of 2 (two) is returned and no
  42.    change is made to the index file. values greater than 2 indicate an error 
  43.    has occurred.
  44.  */
  45.    
  46. COUNT ADDKEY(keyno,target,recbyt,typadd)
  47.  
  48. COUNT   keyno;
  49. TEXT   *target;
  50. POINTER recbyt;
  51. COUNT   typadd;
  52.  
  53. {
  54.     TEXT *idxval;
  55.     FAST KEYFILE *knum;
  56.     FAST TREEBUFF *buffer;
  57.     COUNT npoint;
  58.     LOCAL LONG    node;
  59.  
  60.     VOID prpdup();
  61.     COUNT nodser(),insert(),adroot(),tstupd(),hdrupd();
  62.     KEYFILE *tstfnm();
  63.     TREEBUFF *getnod();
  64.     TREEBUFF *movrgt();
  65.     LONG    gtroot(),nodpnt();
  66.  
  67.     uerr_cod = 0;    /* set user error cod to zero */
  68.     if ((knum = tstfnm(keyno)) == NULL) /* test for leagl keyno */
  69.         return(uerr_cod);
  70.     if (chkredf(knum))
  71.         return(uerr_cod);
  72.     if (!recbyt)
  73.         return(uerr(ZDRN_ERR));
  74.  
  75.     cpybuf((idxval = ct_dupkey),target,knum->length);
  76.     if (knum->autodup == DUPKEY)
  77.         prpdup(idxval,knum,&recbyt);
  78.  
  79.     ct_lnode = btlev = 0;
  80.  
  81. #ifndef FPUTFGET
  82.     if (!(node = gtroot(knum))) {    /* tree may be empty or gtroot err */
  83.         if (uerr_cod || tstupd(knum) ||
  84.             adroot(knum,recbyt,DRNZERO,idxval) ||
  85.             hdrupd(knum,(POINTER) 1))
  86.             return(uerr_cod);
  87.         return(NO_ERROR);
  88.     }
  89. #else
  90.     if (!(node = gtroot(knum))) {
  91.         if (uerr_cod || tstupd(knum))
  92.             return(uerr_cod);
  93.         else if ((npoint = adroot(knum,recbyt,DRNZERO,idxval)) == -1)
  94.             node = gtroot(knum);
  95.         else if (npoint || hdrupd(knum,(POINTER) 1))
  96.             return(uerr_cod);
  97.         else
  98.             return(NO_ERROR);
  99.     }
  100.  
  101. #endif
  102.  
  103.     while (node) {    /* walk down or across tree until leaf node found */
  104.         ct_lnode = node;
  105.         if ((buffer = getnod(node,knum)) == NULL)
  106.             return(uerr_cod);
  107.         if (buffer->leaf == LEAF)
  108.             break;
  109.  
  110.         if ((npoint = nodser(buffer,idxval,'L')) != -1) {
  111.             if (npoint == -2)
  112.                 terr(218);
  113.             if (++btlev >= MAXLEV)
  114.                 terr(240);
  115.             ct_npath[btlev] = node;
  116.             node = nodpnt(buffer,npoint);
  117.         } else
  118.             node = buffer->sucesr;
  119.     }
  120.  
  121.     if (!node)    /* => no leaf node found */
  122.         terr(219);
  123.  
  124. #ifdef FPUTFGET
  125.     if (LOCK(node,knum) ||
  126.         (buffer = movrgt(idxval,knum,getnod(node,knum))) == NULL)
  127. #else
  128.     if (LOCK(node,knum) ||
  129.         (buffer = movrgt(idxval,knum,buffer)) == NULL)
  130. #endif
  131.         return(uerr_cod);
  132.     if (!ct_tky) {
  133.         if (UNLOCK(buffer->nodeid,knum))
  134.             return(uerr_cod);
  135.         return(uerr(KDUP_ERR)); /* ct_key already exists */
  136.     }
  137.  
  138.     if (tstupd(knum) || insert(buffer,knum,idxval,recbyt,typadd) ||
  139.         hdrupd(knum,(POINTER) 1))
  140.         return(uerr_cod);
  141.     return(NO_ERROR);
  142. }
  143.  
  144. /* --------------------------------------------------------------------
  145.    insert key value & backtrack as necessary
  146. */
  147.  
  148. COUNT insert(buffer,knum,idxval,pntr,typadd)
  149.  
  150. PFAST TREEBUFF *buffer;
  151. PFAST KEYFILE  *knum;
  152. TEXT           *idxval;
  153. POINTER         pntr;
  154. COUNT           typadd;
  155.  
  156. {
  157.     COUNT        temp,spltel;
  158.     UCOUNT        tempb;
  159.     LONG           node,oldnode;
  160.     FAST TREEBUFF  *new;
  161.     TEXT           *tp;
  162.     
  163.     TREEBUFF *getnod(),*newnod();
  164.     TREEBUFF *movrgt();
  165.     COUNT     adroot();
  166.     TEXT     *hghpnt(),*valpnt();
  167.     LONG      nodpnt();
  168.     POINTER   drnpnt();
  169.     VOID      insexp();
  170.  
  171. again:
  172.     temp = buffer->nkv + 1;
  173.  
  174.     /* for leaf nodes, if node already full, then must save high key.
  175.        (note that leaf holds maxkv-1 keys (besides high key))
  176.     */
  177.  
  178.     if (buffer->leaf == LEAF)
  179.         cpybuf(hghbuf,hghpnt(buffer),buffer->klen);
  180.  
  181.     if (!ct_elm || ct_elm > buffer->nkv)
  182.         ct_tky = 0;
  183.     insexp(buffer,idxval,pntr);
  184.     tempb = buffer->nkb;
  185.     
  186.     if (tempb <= buffer->maxb) {
  187.         node = buffer->nodeid;
  188.         if (putnod(buffer,temp) || UNLOCK(node,knum))
  189.             return(uerr_cod);
  190.         return(NO_ERROR);
  191.     }
  192.  
  193.     if ((new = newnod(knum,&ct_nwnod,NO)) == NULL)
  194.         return(uerr_cod);
  195.     if (buffer->leaf == LEAF) {
  196.         new->maxkv  = knum->maxkvl;
  197.         new->maxb   = knum->maxkbl;
  198.         if (knum->autodup == DUPKEY)
  199.             new->confg = DUPLEAF;
  200.         else
  201.             new->confg = REGULAR;
  202.     } else {
  203.         new->maxkv = knum->maxkvn;
  204.         new->maxb  = knum->maxkbn;
  205.         if (knum->autodup == DUPKEY)
  206.             new->confg = DUPNONL;
  207.         else
  208.             new->confg = REGULAR;
  209.     }
  210.     if (typadd == REGADD)
  211.         spltel = temp / 2;
  212.     else if (typadd == INCADD)
  213.         spltel = 6 * temp / 7;
  214.     else
  215.         spltel = temp / 7 + 1;
  216.     tp = valpnt(buffer,spltel);
  217.     /* begbyt counts to beg of split ct_key: check that split ct_key actually
  218.        fits - INCADD with ct_key compression & keys out of order can cause
  219.        a problem.
  220.     */
  221.     if ((buffer->begbyt + buffer->actlen) > buffer->maxb) {
  222.         spltel    = temp / 2;
  223.         tp    = valpnt(buffer,spltel);
  224.     }
  225.     cpybuf(spkey,tp,buffer->klen);
  226.  
  227.     pntr = drnpnt(buffer,spltel + 1);
  228.     ct_tky = ct_tkp = tempb = 0;
  229.     if (!buffer->ktipe)
  230.         tp = buffer->ct_kyval + buffer->begbyt;
  231. #ifdef VARLKEYS
  232.     else
  233.         tp = buffer->keyexp;
  234. #endif
  235.     if (buffer->confg & REGULAR)
  236.         tempb = sizeof(POINTER);
  237.     insexp(new,tp + tempb,pntr);
  238.     tempb  = buffer->begbyt + buffer->actlen;
  239.     cpybuf(new->ct_kyval + new->nkb,buffer->ct_kyval + tempb,
  240.         buffer->nkb - tempb);
  241.     new->nkb      += (buffer->nkb - tempb);
  242.     buffer->nkb    = buffer->begbyt;
  243.     buffer->begbyt = buffer->actlen = buffer->lstpos = 0;
  244.     
  245.  
  246.     if (buffer->leaf == LEAF) { /* set high keys */
  247.         /* copy over high key for new node */
  248.         cpybuf(hghpnt(new),hghbuf,buffer->klen);
  249.  
  250.         /* spkey holds the high key for the oldnode */
  251.         cpybuf(hghpnt(buffer),spkey,buffer->klen);
  252.     }
  253.  
  254.     new->sucesr = buffer->sucesr;
  255.     oldnode = buffer->nodeid;
  256.     if ((new->leaf = buffer->leaf) == LEAF)
  257.         new->predsr = oldnode;
  258.  
  259.     buffer->sucesr = ct_nwnod;
  260.     if (putnod(new,temp - spltel) || putnod(buffer,spltel))
  261.         return(uerr_cod);
  262.     if (new->sucesr && new->leaf == LEAF) {
  263.         if (LOCK((LONG) new->sucesr,knum) ||
  264.             (buffer = getnod((LONG) new->sucesr,knum)) == NULL)
  265.             return(uerr_cod);
  266.         buffer->predsr = ct_nwnod;
  267.         if (putnod(buffer,buffer->nkv) || UNLOCK((LONG) new->sucesr,knum))
  268.             return(uerr_cod);
  269.     }
  270.  
  271.     idxval = spkey;
  272.     pntr = oldnode;
  273.     if (node = ct_npath[btlev--]) { /* parent node exists, repeat process */
  274.         if (LOCK(node,knum) ||
  275.             (buffer = movrgt(idxval,knum,getnod(node,knum))) == NULL)
  276.             return(uerr_cod);
  277.         if (nodpnt(buffer,ct_elm) != oldnode)
  278.             /*
  279.              * apparently we have encountered a prematurely
  280.              * terminated node split. parent does not have
  281.              * complete set of pointers. move right strategy
  282.              * avoids crash.
  283.              */
  284.             pntr = nodpnt(buffer,ct_elm);
  285.             
  286.         if (UNLOCK(oldnode,knum))
  287.             return(uerr_cod);
  288.  
  289.         cpybuf(buffer->ct_kyval + buffer->begbyt,&ct_nwnod,sizeof(POINTER));
  290.         if (buffer->ktipe)
  291.             cpybuf(buffer->keyexp,&ct_nwnod,sizeof(POINTER));
  292. #ifdef UNIFRMAT
  293.         revobj(buffer->ct_kyval + buffer->begbyt,sizeof(POINTER));
  294.         if (buffer->ktipe)
  295.             revobj(buffer->keyexp,sizeof(POINTER));
  296. #endif
  297.         goto again;
  298.     } else { /* create new non-leaf root */
  299.         if (UNLOCK(oldnode,knum) ||
  300.             adroot(knum,pntr,(POINTER) ct_nwnod,spkey))
  301.             return(uerr_cod);
  302.     }
  303.     return(NO_ERROR);
  304. }
  305.  
  306.  
  307. /* --------------------------------------------------------------------
  308.    add new root to b-tree pointed to by knum. lpntr & rpntr are the left
  309.    and right pointers associated with the key value pointed to by idxval.
  310.  */
  311.  
  312. COUNT adroot(knum,lpntr,rpntr,idxval)
  313.  
  314. PFAST KEYFILE *knum;
  315. POINTER lpntr,rpntr;
  316. TEXT *idxval;
  317.  
  318. {
  319.     FAST TEXT *tp;    
  320.     FAST TREEBUFF *new;
  321.     COUNT i,typ;
  322.  
  323.     TREEBUFF *newnod();
  324.     TEXT     *hghpnt(),*valpnt();
  325.     COUNT     redhdr(),wrthdr();
  326.     VOID      insexp();
  327.  
  328.     /* if last parameter in newnod == YES, the header lock
  329.        acquired in newnod is NOT released by newnod if newnod
  330.        is successful. If two or more processes call newnod for 
  331.        a virgin tree, then only the first will return a non-null 
  332.        value. The other calls to newnod will result in uerr_cod 
  333.        set to -1 as a signal to ADDKEY to skip regular adroot procedure. 
  334.     */
  335.     if ((new = newnod(knum,&ct_nwnod,rpntr ? NO : YES)) == NULL)
  336.         return(uerr_cod);
  337.  
  338.     if (rpntr) { /* then non-leaf root; add adjacent max high key */
  339.         new->leaf  = NOLEAF;
  340.         new->maxkv = knum->maxkvn;
  341.         new->maxb  = knum->maxkbn;
  342.         if (knum->autodup == DUPKEY)
  343.             new->confg = DUPNONL;
  344.         else
  345.             new->confg = REGULAR;
  346.     } else { /* leaf root (virgin tree) */
  347.         new->leaf  = LEAF;
  348.         new->maxkv = knum->maxkvl;
  349.         new->maxb  = knum->maxkbl;
  350.         if (knum->autodup == DUPKEY)
  351.             new->confg = DUPLEAF;
  352.         else
  353.             new->confg = REGULAR;
  354.         tp = hghpnt(new);
  355.     }
  356.  
  357.     ct_tky = ct_tkp = 0;
  358.     insexp(new,idxval,lpntr);
  359.     if (new->leaf == NOLEAF)
  360.         tp = hghbuf;
  361.  
  362. /*
  363.  * if additional key types are added to c-tree, then the following
  364.  * lines of code must be expanded to properly construct the highest
  365.  * possible key value for each type of ct_key, starting at the byte 
  366.  * pointed to by tp.
  367.  *
  368.  */ 
  369.     i   = knum->length;
  370.     typ = knum->ktype & MSK_ALT;
  371.  
  372. #ifdef FLOATKEY
  373.     if (typ == SFLOATKEY || typ == DFLOATKEY) {
  374.     
  375.     /* single & double float high key based on IEEE standard. note  */
  376.     /* that some compilers will accept 7f ff ff ff ff ff ff ff     */
  377.     /* instead of 7f ef ff ff ff ff ff ff for the highest value.     */
  378.     /* we would not    suggest changing to this since the index files  */
  379.     /* will be compiler dependent.                    */
  380.  
  381. #ifdef LOW_HIGH
  382.         for ( ; i > 0; i--)
  383.         *tp++ = 0xff;
  384.         if (typ == SFLOATKEY) {
  385.         tp   -= (knum->length + 1 - sizeof(float));
  386.         *tp++ = 0x7e;
  387.         } else {
  388.          tp   -= (knum->length + 2 - sizeof(double));
  389.         *tp++ = 0xef;
  390.         *tp   = 0x7f;
  391.         }
  392. #else
  393. #ifdef UNIFRMAT
  394.         for ( ; i > 0; i--)
  395.         *tp++ = 0xff;
  396.         if (typ == SFLOATKEY) {
  397.         tp   -= (knum->length + 1 - sizeof(float));
  398.         *tp++ = 0x7e;
  399.         } else {
  400.          tp   -= (knum->length + 2 - sizeof(double));
  401.         *tp++ = 0xef;
  402.         *tp   = 0x7f;
  403.         }
  404. #else
  405.         if (typ == SFLOATKEY) {
  406.         *tp++ = 0x7e;
  407.         typ   = 1;
  408.         } else {
  409.         *tp++ = 0x7f;
  410.         *tp++ = 0xef;
  411.         typ   = 2;
  412.         }
  413.         for ( ; i > typ; i--)
  414.         *tp++ = 0xff;
  415. #endif
  416. #endif
  417.         
  418.     } else
  419. #endif
  420.  
  421.     for ( ; i > 0; i--)
  422.         *tp++ = 0xff;
  423.  
  424. /*
  425.  * end of code where highest possible key value is constructed
  426.  */
  427.  
  428.     if (rpntr) {
  429.         new->nkv = i = 2;
  430.         valpnt(new,1); /* to set last position */
  431.         insexp(new,hghbuf,rpntr);
  432.     } else
  433.         i = 1;
  434.     if (putnod(new,i))
  435.         return(uerr_cod);
  436.  
  437. #ifdef FPUTFGET
  438.     if (rpntr && (LOCK(NODEZERO,knum) || redhdr(knum - knum->kmem)))
  439.         return(uerr_cod);
  440. #endif
  441.  
  442.     knum->root = ct_nwnod;
  443.  
  444. #ifdef NOTFORCE
  445.     /* no action needed */
  446. #else
  447.     if (wrthdr(knum))
  448.         return(uerr_cod);
  449. #ifdef FPUTFGET
  450.     if (UNLOCK(NODEZERO,knum))
  451.         return(uerr_cod);
  452. #endif
  453. #endif
  454.  
  455.     return(NO_ERROR);
  456. }
  457.  
  458.  
  459. /* --------------------------------------------------------------------
  460.    routine to get next available node. 
  461. */
  462.  
  463. TREEBUFF *newnod(knum,pnode,virgin)
  464. PFAST KEYFILE *knum;
  465. LONG    *pnode;
  466. COUNT virgin; /* virgin adroot: YES or NO */
  467. {
  468.     FAST TREEBUFF *buf;
  469.  
  470.     TREEBUFF *lrubuf(),*getnod();
  471.     COUNT     redhdr(),wrthdr();
  472.     LONG      extfil();
  473.  
  474. #ifndef FPUTFGET
  475.     CTFILE     *ctnum;
  476. #endif
  477. #ifdef VARLDATA
  478.     VHDR      vrhdr;
  479.     COUNT     putvhdr();
  480. #endif
  481.  
  482.  
  483. #ifdef FPUTFGET
  484.     if (LOCK(NODEZERO,knum) || redhdr(knum - knum->kmem))
  485.         return(NULL);
  486.     if (virgin == YES && knum->root) {
  487.         /* someone has already added a root: send signal to adroot
  488.            to skip virgin adroot and proceed with regular insert */
  489.         UNLOCK(NODEZERO,knum);
  490.         uerr_cod = -1;
  491.         return(NULL);
  492.     }
  493. #endif
  494.  
  495. #ifndef FPUTFGET
  496. #ifdef CTSERVER
  497.     ctnum = knum->hmem;
  498. #else
  499.     ctnum = knum - knum->kmem;
  500. #endif
  501.     if (*pnode = ctnum->delstk) {
  502.         if ((buf = getnod(*pnode,ctnum)) == NULL)
  503.             return(NULL);
  504.         if (buf->predsr != -1L) {
  505.             uerr_cod = KLNK_ERR;
  506.             return(NULL);
  507.         }
  508.         ctnum->delstk = buf->sucesr;
  509. #ifdef FPUTONLY
  510.         if (wrthdr(ctnum))
  511.             return(NULL);
  512. #endif
  513.         goto buf_return;
  514.     }
  515. #endif
  516.  
  517. #ifndef VARLDATA
  518.     /* no variable length data routine support */
  519.     if (knum->clstyp == VAT_CLOSE)
  520.         terr(225);
  521.     else if (!(*pnode = extfil(knum,knum->recsiz))) {
  522. #ifdef FPUTFGET
  523.         UNLOCK(NODEZERO,knum);
  524. #endif
  525.         return(NULL);
  526.     }
  527. #else
  528.     /* variable length data routines supported */
  529.     if (knum->clstyp == VAT_CLOSE) {
  530.         if (*pnode = extfil(knum,knum->recsiz + SIZVHDR)) {
  531.             *pnode += SIZVHDR;
  532.             vrhdr.recmrk = VNOD_FLAG;
  533.             vrhdr.trclen = vrhdr.urclen = knum->recsiz;
  534.             if (putvhdr(knum,*pnode,&vrhdr)) {
  535. #ifdef FPUTFGET
  536.                 UNLOCK(NODEZERO,knum);
  537. #endif
  538.                 return(NULL);
  539.             }
  540.         } else {
  541. #ifdef FPUTFGET
  542.             UNLOCK(NODEZERO,knum);
  543. #endif
  544.             return(NULL);
  545.         }
  546.     } else if (!(*pnode = extfil(knum,knum->recsiz))) {
  547. #ifdef FPUTFGET
  548.         UNLOCK(NODEZERO,knum);
  549. #endif
  550.         return(NULL);
  551.     }
  552. #endif
  553.  
  554. #ifdef NOTFORCE
  555.     /* no action */
  556. #else
  557.     if (wrthdr(knum))
  558.         return(NULL);
  559. #ifdef FPUTFGET
  560.     /* do not unlock header if virgin adroot in progress */
  561.     if (virgin == NO && UNLOCK(NODEZERO,knum))
  562.         return(NULL);
  563. #endif
  564. #endif
  565.  
  566.     if ((buf    = lrubuf(NULL)) == NULL)
  567.         return(NULL);
  568. buf_return:
  569.     buf->nkv    = buf->nkb = buf->begbyt = buf->actlen = buf->lstpos = 0;
  570.     buf->ktipe  = knum->ktype & COL_BOTH;
  571.     buf->keyid  = knum->filnum;
  572.     buf->klen   = knum->length;
  573.     buf->nodeid = *pnode;
  574.     buf->update = 'y';
  575.     buf->predsr = buf->sucesr = NODEZERO;
  576.     buf->bmem   = knum->kmem;
  577.     return(buf);
  578. }
  579.  
  580. VOID insexp(bp,ip,pntr)
  581. TREEBUFF   *bp;
  582. TEXT          *ip;
  583. POINTER              pntr;
  584. {
  585.     COUNT      kl,kls,movcnt,movct2,pfxcnt,pfxct2,sfxcnt,sfxct2;
  586.     COUNT       n,poff,colpfx,colpad;
  587.     TEXT      *kp;
  588.     FAST TEXT *tp;
  589.     FAST COUNT i;
  590.  
  591.     if (ct_tky > 0 || ct_tkp < 0)
  592.         terr(235);
  593.  
  594.     kp     = ip; /* save ip for possible latter use */
  595.     kl     = kls = bp->klen;
  596.     colpfx = bp->ktipe & COL_PREFIX;
  597.     colpad = bp->ktipe & COL_SUFFIX;
  598.     if (bp->confg == DUPLEAF || bp->confg == DUPNONL)
  599.         kls -= sizeof(POINTER);
  600.  
  601. /* determine repeating suffix count */
  602.  
  603. #ifdef VARLKEYS
  604.     if (colpad) {
  605.         sfxcnt = i = 0;
  606.         tp     = kp + kls;
  607.         while (i++ < kls && *--tp == PADDING)
  608.             sfxcnt++;
  609.     } else
  610.         sfxcnt = 0;
  611. #else
  612.     sfxcnt = 0;
  613. #endif
  614.  
  615. /* prefix count */
  616.  
  617.     n = kls - sfxcnt;
  618.  
  619. #ifdef VARLKEYS
  620.     if (colpfx)
  621.         if ((pfxcnt = ct_tkp - 1) > 0) {
  622.             if (pfxcnt > n)
  623.                 pfxcnt = n;
  624.             if (colpad && (pfxcnt + ct_sfxctp) > kls)
  625.                 pfxcnt = kls - ct_sfxctp;
  626.             kp += pfxcnt;
  627.             n  -= pfxcnt;
  628.         } else
  629.             pfxcnt = 0;
  630. #else
  631.     pfxcnt = 0;
  632. #endif
  633.  
  634. /* check for addition to end of buffer (& empty buffer ) */
  635.  
  636.     if (ct_tky == 0)    /* assumes values for lstpos begbyt & actlen */
  637.         tp = bp->ct_kyval + bp->begbyt + bp->actlen;
  638.     else { 
  639.  
  640. /* insertion in middle or beginning of buffer */
  641.  
  642.         ct_tky = -ct_tky;
  643.         movcnt = n + kl - kls;
  644.  
  645. #ifdef VARLKEYS
  646.         if (colpfx)
  647.             movcnt++;
  648.         if (colpad)
  649.             movcnt++;
  650. #endif
  651.  
  652.     /* see if following value is further compressed and shift */
  653.  
  654.         if (bp->confg & REGULAR)
  655.             movcnt += (poff = sizeof(POINTER));
  656.         else
  657.             poff = 0;
  658.  
  659.         tp = bp->ct_kyval + bp->begbyt;
  660.  
  661. #ifdef VARLKEYS
  662.         if (colpfx) {        
  663.             pfxct2 = *(tp + poff) & 0x00ff;
  664.             if (colpad)
  665.                 sfxct2 = *(tp + poff + 1) & 0x00ff;
  666.             else
  667.                 sfxct2 = 0;
  668.  
  669.             if (--ct_tky + sfxct2 > kls)
  670.                 ct_tky = kls - sfxct2;
  671.             while ((ct_tky + sfxcnt) > kls)
  672.                 if (ip[ct_tky - 1] == PADDING)
  673.                     ct_tky--;
  674.                 else
  675.                     break;
  676.             if (ct_tky <= pfxct2)
  677.                 shfrgt(movcnt,bp,bp->begbyt);
  678.             else {
  679.                 if ((movct2 = ct_tky - pfxct2) > movcnt)
  680.                     terr(236);
  681.                 bp->actlen -= movct2;
  682.                 *(tp + movct2 + poff) = ct_tky;
  683.                 if (colpad)
  684.                     *(tp + movct2 + poff + 1) = sfxct2;
  685.                 if (poff) {
  686.                     shflft(movct2,bp,bp->begbyt + poff +
  687.                         movct2);
  688.                     bp->nkb -= movct2;
  689.                     shfrgt(movcnt,bp,bp->begbyt);
  690.                 } else {
  691.                     shfrgt(movcnt - movct2,bp,
  692.                         bp->begbyt + movct2);
  693.                     bp->nkb -= movct2;
  694.                 }
  695.             }
  696.         } else
  697. #endif
  698.             shfrgt(movcnt,bp,bp->begbyt);
  699.  
  700.         tp = bp->ct_kyval + bp->begbyt;
  701.         bp->lstpos++;
  702.         bp->begbyt += movcnt;
  703.     }
  704.  
  705.     /* stuff bytes in place */
  706.  
  707.     if (bp->confg & REGULAR) {
  708. #ifdef UNIFRMAT
  709.         revobj(&pntr,sizeof(POINTER));
  710. #endif
  711.         cpybuf(tp,&pntr,sizeof(POINTER));
  712.         tp      += sizeof(POINTER);
  713.         bp->nkb += sizeof(POINTER);
  714.     }
  715.  
  716. #ifdef VARLKEYS
  717.     if (colpfx) {
  718.         bp->nkb++;
  719.         *tp++ = pfxcnt;
  720.     }
  721.     if (colpad) {
  722.         bp->nkb++;
  723.         *tp++ = sfxcnt;
  724.     }
  725. #endif
  726.  
  727.     cpybuf(tp,kp,n);
  728.     bp->nkb += n;
  729.  
  730.     if (kls < kl) {
  731.         bp->nkb += sizeof(POINTER);
  732.         cpybuf(tp + n,ip + kls,sizeof(POINTER));
  733.     }
  734.     
  735. }
  736.  
  737. /* end of ctaddk.c */
  738.