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

  1. /*
  2.  *    rebuild support routines
  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. /*
  24.  * To disable interactive rebuild prompts and/or to suppress normal
  25.  * rebuild output, "comment out" one or both of the following
  26.  * defines:
  27.  */
  28.  
  29. #define RB_INTERACTIVE
  30. #define RB_OUTPUT
  31.  
  32. /*
  33.  * To disable the index entry count as described in Section 6.2,
  34.  * add the following #define to the CTOPTN.H module before compiling:
  35.  *
  36.  *    #define NO_IDXENT
  37.  *
  38.  */
  39.  
  40.  
  41. #include "ctstdr.h"        /* standard i/o header         */
  42. #include "ctoptn.h"        /* c-tree configuration options */
  43. #include "cterrc.h"        /* c-tree error codes        */
  44. #include "ctstrc.h"        /* c-tree data structures    */
  45. #include "ctgvar.h"        /* c-tree global variables    */
  46. #include "ctisam.h"        /* c-tree isam header        */
  47. #include "ctvrec.h"        /* variable length header    */
  48.  
  49. TEXT           *ct_rbuf;
  50. POINTER        *ct_pbuf;
  51. COUNT        rerr_cod,rerr_fil,ct_fp,ct_redom;
  52. VRLEN        ct_bsz;
  53. LONG        ct_spc;
  54.  
  55. #ifdef FPUTFGET
  56.  
  57. COUNT RBLDAT(datno,datnam,datlen,xtdsiz,filemd)
  58. COUNT  datno;  /* data number temporary assigned to file */
  59. TEXT  *datnam; /* pointer to file name    */
  60. COUNT  datlen; /* data record length    */
  61. UCOUNT xtdsiz; /* file chunk size    */
  62. COUNT  filemd; /* file mode parameter    */
  63. {
  64.     printf(
  65. "\nCTRBL2 should not be compiled with the FPUTFGET option!\n");
  66.     exit(2);
  67. }
  68.  
  69. COUNT RBLIDX(datno,datname,idxname,keyno,klen,ktyp,dflg,nomemb,xtdsiz,filemd)
  70. COUNT  datno;
  71. TEXT  *datname,*idxname;
  72. COUNT  keyno,klen,ktyp,dflg,nomemb;
  73. UCOUNT xtdsiz;
  74. COUNT  filemd;
  75. {
  76.     exit(2);
  77. }
  78. COUNT RBLMEM(datno,datname,idxname,keyno,klen,ktyp,dflg,membno)
  79. COUNT  datno;
  80. TEXT  *datname,*idxname;
  81. COUNT  keyno,klen,ktyp,dflg,membno;
  82. {
  83.     exit(2);
  84. }
  85.  
  86. #else
  87.  
  88. LOCAL COUNT    redo_dat,redo_idx,slen;
  89. LOCAL COUNT    fhdr,all_idx,duprej;
  90. LOCAL COUNT    *lbuf;
  91. LOCAL TEXT    lenkey[VARI_LEN],lastky[MAXLEN];
  92. LOCAL TEXT     *kbuf;
  93. LOCAL KEYFILE  *snum;
  94. LOCAL COUNT     srtlev,maxsrt;
  95.  
  96. TEXT        *mballc();
  97. RNDFILE        mbopen();
  98. COUNT        compar(),ctio(),redhdr(),wrthdr(),mbclos(),frmkey();
  99. COUNT        getintr(),getdatr(),getidxr(),getambr(),uerr();
  100. COUNT        ADDKEY(),CREIDX(),OPNFIL(),CLSFIL(),CREMEM(),REDREC();
  101.  
  102. #ifndef NO_IDXENT
  103.     POINTER IDXENT();
  104. #endif
  105.  
  106. #ifdef VARLDATA
  107. COUNT frmlkey(),getvhdr(),putvhdr();
  108. #else
  109. #define VS1    "\n\nAttempt to rebuild variable record length data file."
  110. #define VS2    "\nCTRBLD.C compiled with variable length data disabled."
  111. #define VS3    "\nRecompile with VARLDATA defined in CTOPTN.H\n"
  112. #endif
  113.  
  114. COUNT rerr(err_cod,file_no)
  115.  
  116. COUNT err_cod;
  117. COUNT file_no;
  118.  
  119. {
  120.     rerr_fil = file_no;
  121.     return(rerr_cod = err_cod);
  122. }
  123.  
  124. COUNT yesno()
  125. {
  126. #ifdef RB_INTERACTIVE
  127.     for (;;) {
  128.         gets(ct_buf);
  129.         switch (ct_buf[0]) {
  130. case 'y':
  131. case 'Y':
  132.             return(YES);
  133. case 'n':
  134. case 'N':
  135.             return(NO);
  136. default:
  137.             ct_buf[0] = '\0';
  138.         }
  139.         printf("Improper choice. Try again (y or n)>> ");
  140.     }
  141. #else
  142.     return(YES);
  143. #endif
  144. }
  145.  
  146. COUNT vcparm(pp,rv,txt)
  147. UCOUNT *pp;
  148. UCOUNT  rv;
  149. TEXT   *txt;
  150. {
  151.     COUNT prnprm();
  152.  
  153.     if (rv != *pp && prnprm(*pp,rv,txt)) {
  154.         *pp = rv;
  155.         return(NO);
  156.     }
  157.     return(YES);
  158. }
  159.  
  160. COUNT vtparm(pp,rv,txt)
  161. TEXT  *pp,*txt;
  162. UCOUNT rv;
  163. {
  164.     COUNT prnprm();
  165.  
  166.     if (rv != *pp && prnprm((UCOUNT) *pp,rv,txt)) {
  167.         *pp = rv;
  168.         return(NO);
  169.     }
  170.     return(YES);
  171. }
  172.  
  173. COUNT prnprm(hv,rv,txt)
  174. UCOUNT hv,rv;
  175. TEXT  *txt;
  176. {
  177.     COUNT yesno();
  178.  
  179. #ifdef RB_INTERACTIVE
  180.     printf("\n\nWARNING: %s discrepancy.",txt);
  181.     printf("\nParameter file %s = %d",txt,rv);
  182.     printf("\n        Header %s = %d",txt,hv);
  183.     printf("\n\nUse parameter file value? (y or n)>> ");
  184. #endif
  185.     return(yesno());
  186. }
  187.  
  188. COUNT RBLDAT(datno,datnam,datlen,xtdsiz,filemd)
  189. COUNT  datno;  /* data number temporary assigned to file */
  190. TEXT  *datnam; /* pointer to file name    */
  191. COUNT  datlen; /* data record length    */
  192. UCOUNT xtdsiz; /* file chunk size    */
  193. COUNT  filemd; /* file mode parameter    */
  194. {
  195.     FAST DATFILE *dnum;
  196.  
  197.     COUNT scndat();
  198.  
  199. #ifdef RB_OUTPUT
  200.     printf("\n\nExamining data file %s.",datnam);
  201. #endif
  202.     uerr_cod = 0;
  203.     dnum = ct_key + datno;
  204.     if (dnum->chnacs != 'n')
  205.         return(rerr(FUSE_ERR,datno));
  206.  
  207.     cpybuf(dnum->flname,datnam,MAX_NAME);
  208. #ifdef CT_ANSI
  209.     if ((dnum->fd = mbopen(dnum,(EXCLUSIVE | PERMANENT))) == (RNDFILE) NULL)
  210. #else
  211.     if ((dnum->fd = mbopen(dnum,(EXCLUSIVE | PERMANENT))) < 0)
  212. #endif
  213.         /* file does not exist */
  214.         return(rerr(FNOP_ERR,datno));
  215.  
  216.     if (redhdr(dnum)) {
  217.         mbclos(dnum,COMPLETE);
  218.         return(rerr(uerr_cod,datno));
  219.     }
  220.  
  221.     dnum->chnacs = 'y';
  222.     dnum->filnum = datno;
  223.     fhdr         = NO;
  224.     all_idx      = NO;
  225.     ct_redom     = NO;
  226.  
  227.     if (dnum->verson < CT_V4) /* V3.3 data file */
  228.         dnum->length = dnum->recsiz = dnum->nmem = dnum->kmem = dnum->flmode = 0;
  229.     if (dnum->verson < CT_V4E && (dnum->flmode & VLENGTH)) {
  230.         /* V4.1D or earlier var length data file */
  231.         dnum->maxkbn = dnum->recsiz - STATUS;
  232.         dnum->maxkbl = (dnum->maxkvl - 1) * VARI_LEN;
  233.     }
  234.  
  235.     if (!ct_fp && dnum->verson != ct_ver) {
  236. #ifdef RB_INTERACTIVE
  237.         printf("\nData file version incompatibility detected:");
  238.         printf("\n\tDo you wish to continue? If so, data file and ");
  239.         printf("\n\tindex files must be rebuilt. (y or n) >> ");
  240. #endif
  241.         if (yesno())
  242.             ct_fp = YES;
  243.         else
  244.             return(rerr(FVER_ERR,datno));
  245.     }
  246.  
  247.     if (dnum->nmem != 0 || dnum->kmem != 0) {
  248.         dnum->nmem = dnum->kmem = 0;
  249.         fhdr       = YES;
  250.     }
  251.  
  252.     if (dnum->updflg == COMPACT) {
  253. #ifdef RB_OUTPUT
  254.         printf(
  255. "\nData File has been compacted. Associated indices must be rebuilt.");
  256. #endif
  257.         dnum->updflg = NO;
  258.         fhdr         = YES;
  259.         all_idx      = YES;
  260.         ct_redom     = YES;
  261.     }
  262. #ifdef RB_OUTPUT
  263.     else if (dnum->updflg)
  264.         printf("\nData File is corrupt (flag = %d).",dnum->updflg);
  265. #endif
  266.  
  267.     if (!vcparm(&dnum->reclen,datlen,"data record length"))
  268.         ct_fp = YES;
  269.     if (!vcparm(&dnum->extsiz,xtdsiz,"file extension size"))
  270.         fhdr  = YES;
  271.     if ((dnum->flmode & VLENGTH) != (filemd & VLENGTH))
  272.         return(rerr(RMOD_ERR,datno));
  273.     if (dnum->flmode & VLENGTH) {
  274. #ifdef VARLDATA
  275.         if (dnum->clstyp != VAT_CLOSE) {
  276.             dnum->clstyp = VAT_CLOSE;
  277.             fhdr         = YES;
  278.         }
  279. #else
  280.         printf("%s%s%s",VS1,VS2,VS3);
  281.         return(rerr(RMOD_ERR,datno));
  282. #endif
  283.     } else
  284.         if (dnum->clstyp != DAT_CLOSE) {
  285.             dnum->clstyp = DAT_CLOSE;
  286.             fhdr         = YES;
  287.         }
  288.  
  289.     if (fhdr && wrthdr(dnum))
  290.         return(uerr_cod);
  291.     if (dnum->updflg || ct_fp) {
  292. #ifdef RB_OUTPUT
  293.         printf("\n\nRebuilding data file.\n");
  294. #endif
  295.         dnum->verson = ct_ver;
  296.         redo_dat = YES;
  297.         dnum->updflg = UPDATED;
  298.         dnum->nument = 0L;
  299.         if (wrthdr(dnum))
  300.             return(uerr_cod);
  301.         if (scndat(dnum))
  302.             return(rerr(uerr_cod,datno));
  303. #ifdef RB_OUTPUT
  304.         printf("\nData file rebuild complete (%ld bytes",
  305.             dnum->numrec + 1L);
  306.         if (dnum->clstyp == DAT_CLOSE)
  307.             printf(" / %ld active records).",dnum->nument);
  308.         else
  309.             printf(").");
  310. #endif
  311.     } else {
  312. #ifdef RB_OUTPUT
  313.         printf("\n\nNo data file rebuild necessary.");
  314. #endif
  315.         redo_dat = NO;
  316.     }
  317.  
  318.     return(rerr(CLSFIL(datno,COMPLETE),datno));
  319. }
  320.  
  321. COUNT RBLIDX(datno,datname,idxname,keyno,klen,ktyp,dflg,nomemb,xtdsiz,filemd)
  322. COUNT  datno;
  323. TEXT  *datname,*idxname;
  324. COUNT  keyno,klen,ktyp,dflg,nomemb;
  325. UCOUNT xtdsiz;
  326. COUNT  filemd;
  327. {
  328.     KEYFILE *knum;
  329.  
  330.     COUNT   chkpar(),getdt();
  331.  
  332. #ifdef RB_OUTPUT
  333.     printf("\n\nExamining index file %s.",idxname);
  334. #endif
  335.  
  336.     fhdr = NO;
  337.     if (!all_idx && !redo_dat) {
  338.         if (OPNFIL(keyno,idxname,filemd) == NO_ERROR){
  339.             knum = ct_key + keyno;
  340.             if (chkpar(knum,klen,ktyp,dflg,nomemb,xtdsiz,filemd)) 
  341.             redo_idx = NO;
  342.             else {
  343.             redo_idx = YES;
  344.             CLSFIL(keyno,COMPLETE);
  345.             }
  346.         } else
  347.             redo_idx = YES;
  348.     } else
  349.         redo_idx = YES;
  350.  
  351.  
  352.     if (!redo_idx && fhdr && wrthdr(knum))
  353.         return(rerr(uerr_cod,keyno));
  354.  
  355.     if (redo_idx) {
  356. #ifdef RB_OUTPUT
  357.         printf("\n\nRebuilding index file ");
  358. #endif
  359.         remove(idxname);
  360.         if (CREIDX(keyno,idxname,klen,ktyp,dflg,nomemb,xtdsiz,filemd) ||
  361.             CLSFIL(keyno,filemd) || OPNFIL(keyno,idxname,filemd))
  362.             return(rerr(uerr_cod,keyno));
  363.         ct_redom = YES;
  364.         if (getdt(keyno,datno,datname))
  365.             return(rerr_cod);
  366.  
  367. #ifdef RB_OUTPUT
  368. #ifndef NO_IDXENT
  369.         printf("\nIndex file rebuild complete (%ld entries).",
  370.             IDXENT(keyno));
  371. #else
  372.         printf("\nIndex file rebuild complete.");
  373. #endif
  374. #endif
  375.  
  376.     } else {
  377.         ct_redom = NO;
  378.         printf("\nNo index file rebuild necessary.");
  379.     }
  380.     return(rerr(CLSFIL(keyno,COMPLETE),keyno));
  381. }
  382.  
  383. COUNT RBLMEM(datno,datname,idxname,keyno,klen,ktyp,dflg,membno)
  384. COUNT  datno;
  385. TEXT  *datname,*idxname;
  386. COUNT  keyno,klen,ktyp,dflg,membno;
  387. {
  388.     COUNT getdt();
  389.  
  390.     CTFILE *knum;
  391.  
  392. #ifdef RB_OUTPUT
  393.     printf("\n\nRebuilding additional index #%d ",membno);
  394. #endif
  395.     if (OPNFIL(keyno,idxname,(EXCLUSIVE | PERMANENT)))
  396.         return(rerr(uerr_cod,keyno));
  397.     knum = ct_key + keyno;
  398.     if (membno < 1 || membno > knum->nmem)
  399.         return(rerr(KMEM_ERR,knum->nmem));
  400.     (knum += membno)->chnacs = 'm';
  401.     if (CREMEM(keyno,klen,ktyp,dflg,membno))
  402.         return(rerr(uerr_cod,membno));
  403.     if (getdt(keyno + membno,datno,datname))
  404.         return(rerr_cod);
  405. #ifdef RB_OUTPUT
  406. #ifndef NO_IDXENT
  407.     printf("\nAdditional index member rebuild complete (%ld entries).",
  408.         IDXENT(keyno + membno));
  409. #else
  410.     printf("\nAdditional index member rebuild complete.");
  411. #endif
  412. #endif
  413.  
  414.     return(rerr(CLSFIL(keyno,COMPLETE),keyno));
  415. }
  416.  
  417.  
  418. COUNT chkpar(knum,kl,kt,df,nm,xt,fm)
  419.  
  420. KEYFILE *knum;
  421. COUNT    kl,kt,df,nm;
  422. UCOUNT   xt;
  423. COUNT    fm;
  424.  
  425. {
  426.     COUNT result;
  427.  
  428.     result = vcparm(&knum->recsiz,ct_ndsec * SECSIZ,"node size");
  429.     result = (vcparm((UCOUNT *) &knum->length,kl,"key length") && result);
  430.     result = (vtparm(&knum->ktype,kt,"key type") && result);
  431.     result = (vtparm(&knum->autodup,df,"duplicate flag") && result);
  432.     result = (vcparm((UCOUNT *) &knum->nmem,nm,"# of additional indices")
  433.         && result);
  434.     if (!vcparm(&knum->extsiz,xt,"file size extension"))
  435.         fhdr = YES;
  436. /*
  437.     if (!vcparm((UCOUNT *) &knum->flmode,fm,"file mode"))
  438.         fhdr = YES;
  439. */
  440.     if (knum->verson != ct_ver) {
  441.         knum->verson = ct_ver;
  442.         result = NO;
  443.     }
  444.     return(result);
  445. }
  446.  
  447. VOID updkey(knum)
  448.  
  449. PFAST KEYFILE *knum;
  450.  
  451. {
  452.         knum->maxkbn = knum->recsiz - STATUS;
  453.         knum->maxkvn = knum->maxkbn / (knum->length + sizeof(POINTER));
  454.         if (knum->maxkvn < 3) {
  455.             printf(
  456. "\n\nKey length too long for node size. (KMIN_ERR)");
  457.             exit(0);
  458.         }
  459.         knum->maxkvl = knum->maxkbn / knum->length;
  460.         knum->maxkbl = (knum->maxkvl - 1) * knum->length;
  461. }
  462.  
  463.  
  464. COUNT getdt(keyno,datno,datname)
  465. COUNT keyno,datno;
  466. TEXT *datname;
  467.  
  468. {
  469. #ifdef VARLDATA
  470.     COUNT RDVREC();
  471. #endif
  472.     COUNT addbat();
  473.  
  474.     DATFILE *dnum;
  475.     KEYFILE *knum;
  476.     POINTER  newbyt,curbyt;
  477.     POINTER *pp;
  478.     COUNT    batch,kl,delrec,serflg;
  479.     UCOUNT   batsiz,bp;
  480.     COUNT   *lp;
  481.     TEXT    *kp;
  482. #ifdef VARLDATA
  483.     VHDR     vrhdr;
  484. #endif
  485.  
  486.     dnum = ct_key + datno;
  487.     knum = ct_key + keyno;
  488.  
  489.     bp   = dnum->srlpos;
  490.     if (OPNFIL(datno,datname,(EXCLUSIVE | PERMANENT)))
  491.         return(rerr(uerr_cod,datno));
  492.     dnum->srlpos = bp;
  493.     serflg         = NO;
  494.  
  495.     kl     = knum->length;
  496.     duprej = 0;
  497.     batsiz = ct_spc / (kl + sizeof(POINTER) + sizeof(COUNT)) - 1;
  498.  
  499.     if (dnum->clstyp == DAT_CLOSE)
  500.         curbyt = ((SECSIZ + dnum->reclen - 1) / dnum->reclen) *
  501.             dnum->reclen;
  502.     else
  503.         curbyt = (dnum->recsiz + SIZVHDR);
  504.  
  505.     lbuf   = (COUNT *) (ct_pbuf + batsiz);
  506.     kbuf   = (TEXT *)  (lbuf + batsiz);
  507.  
  508. #ifdef RB_OUTPUT
  509.     printf("with Batch Size = %u.\n",batsiz);
  510. #endif
  511.  
  512.     batch = 0;
  513.     bp = batsiz - 1;
  514.     while (curbyt < dnum->numrec) {
  515.         delrec = NO;
  516.         if (dnum->clstyp == DAT_CLOSE) {
  517.         if (REDREC(datno,curbyt,ct_rbuf))
  518.             return(rerr(uerr_cod,datno));
  519.         newbyt = curbyt + dnum->reclen;
  520.         if (ct_rbuf[0] == DELFLG)
  521.             delrec = YES;
  522.         } else {
  523. #ifdef VARLDATA
  524.         if (getvhdr(dnum,curbyt,&vrhdr))
  525.             return(rerr(uerr_cod,datno));
  526.         if (vrhdr.recmrk == VDEL_FLAG || vrhdr.recmrk == VNOD_FLAG)
  527.             delrec = YES;
  528.         else if (vrhdr.recmrk != VACT_FLAG)
  529.             return(rerr(RVHD_ERR,datno));
  530.         else {
  531.             if (vrhdr.urclen > ct_bsz) {
  532.                 mbfree(ct_rbuf);
  533.                 if ((ct_rbuf = mballc(1,ct_bsz = vrhdr.urclen)) ==
  534.                     NULL)
  535.                     return(rerr(RRLN_ERR,datno));
  536.             }
  537.             if (RDVREC(datno,curbyt,ct_rbuf,ct_bsz))
  538.                 return(rerr(isam_err,datno));
  539.         }
  540.         newbyt = curbyt + vrhdr.trclen + SIZVHDR;
  541. #else
  542.         return(rerr(RMOD_ERR,datno));
  543. #endif
  544.         }
  545.         if (!delrec && dnum->srlpos) {
  546.         cpybuf(&ct_gsrl,ct_rbuf + dnum->srlpos - 1,sizeof(POINTER));
  547. #ifndef NATURAL_SERIAL
  548. #ifdef LOW_HIGH
  549.         revobj(&ct_gsrl,sizeof(POINTER));
  550. #endif
  551. #endif
  552.         if ((unsigned long) dnum->sernum < (unsigned long) ct_gsrl) {
  553.             dnum->sernum = ct_gsrl;
  554.             serflg         = YES;
  555.         }
  556.         }
  557.         if (!delrec && frmkey(keyno,ct_rbuf,ct_kyval,curbyt)) {
  558.             if (++bp == batsiz) {
  559.             if (batch)
  560.                 if (addbat(keyno,kl,batch,bp - 1))
  561.                     return(rerr_cod);
  562.             bp = 0;
  563.             batch++;
  564.             pp = ct_pbuf;
  565.             kp = kbuf;
  566.             lp = lbuf;
  567.             }
  568.             cpybuf(kp,ct_kyval,kl);
  569.             kp += kl;
  570.             *pp++ = curbyt;
  571.             *lp++ = bp;
  572.         }
  573.         curbyt = newbyt;
  574.     }
  575.     if (batch)
  576.         if (addbat(keyno,kl,batch,bp))
  577.             return(rerr_cod);
  578.     if (duprej) {
  579.         printf(
  580. "\nWARNING: %d record(s) contained rejected duplicate key values.\n",duprej);
  581.         printf("\nPress RETURN to continue ...");
  582.         gets(ct_buf);
  583.     }
  584.  
  585.     if (serflg && wrthdr(dnum))
  586.         return(rerr(uerr_cod,datno));
  587.     return(rerr(CLSFIL(datno,COMPLETE),datno));
  588. }
  589.         
  590. COUNT addbat(keyno,klen,batno,bs)
  591.  
  592. COUNT keyno,klen,batno,bs;
  593.  
  594. {
  595.     LOCAL UCOUNT t;
  596.     COUNT        i,j,k,add_mode;
  597.     FAST COUNT  *lp;
  598.     TEXT        *kp;
  599.     POINTER     *pp;
  600.  
  601.     VOID srtbat();
  602.  
  603.  
  604.     snum = ct_key + keyno;
  605.     slen = klen;
  606.     srtlev = maxsrt = 0;
  607.     srtbat(0,bs);
  608.  
  609.     if (batno == 1) {
  610.         add_mode = INCADD;
  611.         t = 0;
  612.     } else if (compar(lastky,kbuf + (lbuf[0] * slen),snum) <= 0)
  613.             add_mode = INCADD;
  614.         else
  615.             add_mode = REGADD;
  616.     if (batno == 1 || compar(lastky,kbuf + (lbuf[bs] * slen),snum) < 0)
  617.         cpybuf(lastky,kbuf + (lbuf[bs] * klen),snum->length);
  618.  
  619.     lp = lbuf;
  620.     for (i = 0; i <= bs; i++) {
  621.         j  = *lp++;
  622.         pp = ct_pbuf + j;        
  623.         kp = kbuf + (j * klen);
  624.         switch (ADDKEY(keyno,kp,*pp,add_mode)) {
  625.  
  626. case NO_ERROR:
  627.             break;
  628. case KDUP_ERR:
  629.             printf(
  630. "\nDuplicate key rejected for record at offset %lxx [",*pp);
  631.             for (k = 0; k < klen; k++)
  632.                 printf("%02x",*(kp + k) & 0x00ff);
  633.             printf("]\n");
  634.             duprej++;
  635.             break;
  636. default:
  637.             printf("\nADDKEY terminating with code %d",uerr_cod);
  638.             return(rerr(uerr_cod,keyno));
  639.         }
  640. #ifdef RB_OUTPUT
  641.         if (!(++t % 128))
  642.             printf("i");
  643. #endif
  644.     }
  645. #ifdef RB_OUTPUT
  646.     printf(" B%d ",batno);
  647. #endif
  648.     return(NO_ERROR);
  649. }
  650.             
  651. VOID exchg(i,j)
  652.  
  653. COUNT i,j;
  654.  
  655. {
  656.     FAST COUNT temp;
  657.  
  658.     temp = lbuf[i];
  659.     lbuf[i] = lbuf[j];
  660.     lbuf[j] = temp;
  661. }
  662.  
  663. COUNT comsrt(k,tp)
  664.  
  665. COUNT k;
  666. TEXT *tp;
  667.  
  668. {
  669.     TEXT *temp;
  670.  
  671.     temp = kbuf + (lbuf[k] * slen);
  672.     return(compar(temp,tp,snum));
  673. }
  674.  
  675. COUNT comadj(k)
  676. COUNT k;
  677. {
  678.     TEXT *t1,*t2;
  679.  
  680.     t1 = kbuf + (lbuf[k] * slen);
  681.     t2 = kbuf + (lbuf[k + 1] * slen);
  682.     return(compar(t1,t2,snum));
  683. }
  684.  
  685. VOID srtbat(lo,hi) /* recursive quicksort with bubble-like exchanges */
  686.  
  687. COUNT lo,hi;
  688.  
  689. {
  690.   FAST COUNT  i,j;
  691.   COUNT       size,f,lf,rf;
  692.   TEXT       *piv;
  693.  
  694.   if (++srtlev > maxsrt)
  695.     maxsrt = srtlev;
  696.   if ((i = lo) < (j = hi)) {
  697.     lf = rf = NO;
  698.     f       = YES;
  699.     piv     = kbuf + (lbuf[(i + j) / 2] * slen);
  700.  
  701.     while (f) {
  702.     while (comsrt(i,piv) < 0 && i != j) {
  703.         if (i > lo && comadj(i - 1) > 0) {
  704.             exchg(i - 1,i);
  705.             lf = YES;
  706.         }
  707.         i++;
  708.     }
  709.  
  710.     while (comsrt(j,piv) >= 0 && i != j) {
  711.         if (j < hi && comadj(j) > 0) {
  712.             exchg(j,j + 1);
  713.             rf = YES;
  714.         }
  715.         j--;
  716.     }
  717.  
  718.     if (i != j)
  719.         exchg(i,j);
  720.     else {
  721.         if (comsrt(j,piv) >= 0) {
  722.             if (j < hi && comadj(j) > 0) {
  723.                 exchg(j,j + 1);
  724.                 rf = YES;
  725.             }
  726.         } else {
  727.             if (i > lo && comadj(i - 1) > 0) {
  728.                 exchg(i - 1,i);
  729.                 lf = YES;
  730.             }
  731.             if ((i - 1) > lo && comadj(i - 2) > 0)
  732.                 exchg(i - 2,i - 1);
  733.         }
  734.         f = NO;
  735.     } /* i = j */
  736.     } /* while (f) */
  737.  
  738.     if ((size = i - lo) > 2)
  739.     if (lf)
  740.         if (size == 3) {
  741.             if (comadj(lo) > 0)
  742.                 exchg(lo,lo + 1);
  743.         } else
  744.             srtbat(lo,i - 2);
  745.  
  746.     if ((size = hi - j + 1) > 2)
  747.     if (rf)
  748.         if (size == 3) {
  749.             if (comadj(j + 1) > 0)
  750.                 exchg(j + 1,j + 2);
  751.         } else
  752.             srtbat(j + 1,hi);
  753.   }
  754.   --srtlev;
  755. }
  756.  
  757. COUNT scndat(dnum)
  758.  
  759. DATFILE *dnum;
  760.  
  761. {
  762.     POINTER curbyt;
  763.     UCOUNT  t;
  764. #ifdef VARLDATA
  765.     POINTER lstbyt;
  766.     UCOUNT  lstmrk;
  767.     VRLEN   savlen;
  768.     VHDR    vrhdr;
  769. #endif
  770.  
  771.  
  772.     if (dnum->clstyp == DAT_CLOSE) {
  773.         curbyt       = ((SECSIZ + dnum->reclen - 1) /
  774.                 dnum->reclen) * dnum->reclen;
  775.         dnum->delstk = DRNZERO;
  776.         t = 0;
  777.         while (!ctio(CTREAD,dnum,curbyt,ct_rbuf,0)) {
  778.         if (ct_rbuf[0] == DELFLG) {
  779.             cpybuf(ct_rbuf+1,&dnum->delstk,sizeof(POINTER));
  780. #ifdef UNIFRMAT
  781.             revobj(ct_rbuf + 1,sizeof(POINTER));
  782. #endif
  783.             dnum->delstk = curbyt;
  784.             if (ctio(CTWRITE,dnum,curbyt,ct_rbuf,0))
  785.                 return(uerr_cod);
  786.         } else
  787.             dnum->nument++;
  788. #ifdef RB_OUTPUT
  789.         if (!(++t % 128))
  790.             printf("d");
  791. #endif
  792.         curbyt += dnum->reclen;
  793.         }
  794.         dnum->numrec  = dnum->phyrec = curbyt - (POINTER) 1;
  795.         return(NO_ERROR);
  796.     } else if (dnum->clstyp == VAT_CLOSE) {
  797. #ifdef VARLDATA
  798.         curbyt        = dnum->recsiz + SIZVHDR;
  799.         t             = lstmrk = 0;
  800.  
  801.         dnum->root    = dnum->nodstk = NODEZERO;
  802.         dnum->length  = VARI_LEN;
  803.         dnum->autodup = 1;
  804.         dnum->ktype   = 0;
  805.         dnum->nument  = DRNZERO;
  806.  
  807.         if (dnum->recsiz > (ct_ndsec * SECSIZ))
  808.         return(uerr(KSIZ_ERR));
  809.         else if (dnum->length < 0 || dnum->length > MAXLEN)
  810.         return(uerr(KLEN_ERR));
  811.         updkey(dnum);
  812.  
  813. /* all existing tree nodes are marked deleted */
  814.  
  815.         while (!getvhdr(dnum,curbyt,&vrhdr)) {
  816.         if (vrhdr.recmrk == VNOD_FLAG) {
  817.             if (vrhdr.trclen != dnum->recsiz)
  818.                 return(uerr(KSIZ_ERR));
  819.             vrhdr.urclen = 0;
  820.             vrhdr.recmrk = VDEL_FLAG;
  821.             if (putvhdr(dnum,curbyt,&vrhdr))
  822.                 return(uerr_cod);
  823.         } else if (vrhdr.recmrk == VACT_FLAG) {
  824.             if (vrhdr.urclen == 0) {
  825.                 vrhdr.recmrk = VDEL_FLAG;
  826.                 if (putvhdr(dnum,curbyt,&vrhdr))
  827.                     return(uerr_cod);
  828.             }
  829.         } else if (vrhdr.recmrk == VDEL_FLAG)
  830.             /* no action necessary */ ;
  831.         else    /* no recognizable header. truncate file */
  832.             break;
  833.  
  834.         if (vrhdr.recmrk == VDEL_FLAG && lstmrk == VDEL_FLAG) {
  835.             /* collapse consecutive deleted areas */
  836.             savlen  = vrhdr.trclen;
  837.             if (getvhdr(dnum,lstbyt,&vrhdr))
  838.                 return(uerr_cod);
  839.             if (vrhdr.recmrk != VDEL_FLAG)
  840.                 terr(228);
  841.             savlen += vrhdr.trclen + SIZVHDR;
  842.             if (savlen < vrhdr.trclen)
  843.                 /* overflow: don't collapse space */
  844.                 vrhdr.recmrk = (VRLEN) 0; /* reset lstmrk */
  845.             else {
  846.                 vrhdr.trclen = savlen;
  847.                 if (putvhdr(dnum,lstbyt,&vrhdr))
  848.                     return(uerr_cod);
  849.             }
  850.         } else
  851.             /* no consecutive deleted areas */
  852.             lstbyt  = curbyt;
  853.  
  854.         lstmrk  = vrhdr.recmrk;
  855.         curbyt  = lstbyt + (vrhdr.trclen + SIZVHDR);
  856. #ifdef RB_OUTPUT
  857.         if (!(++t % 256))
  858.             printf("d");
  859. #endif
  860.         }
  861.         dnum->numrec = dnum->phyrec = curbyt - (SIZVHDR + 1);
  862.         curbyt       = dnum->recsiz + SIZVHDR;
  863.  
  864. /* create all new delete space nodes in variable length files */
  865.  
  866.         while (curbyt < dnum->numrec) {
  867.         if (getvhdr(dnum,curbyt,&vrhdr))
  868.             return(uerr_cod);
  869.         else if (vrhdr.recmrk == VDEL_FLAG) {
  870.             frmlkey(lenkey,&vrhdr.trclen,DRNZERO);
  871.             if (ADDKEY(dnum->filnum,lenkey,curbyt,REGADD))
  872.                 return(uerr_cod);
  873.         }
  874. #ifdef RB_OUTPUT
  875.         if (!(++t % 256))
  876.             printf("d");
  877. #endif
  878.         curbyt += (vrhdr.trclen + SIZVHDR);
  879.         }
  880.         return(NO_ERROR);
  881. #else
  882.       printf("%s%s%s",VS1,VS2,VS3);
  883.       return(RMOD_ERR);
  884. #endif
  885.     } else
  886.         return(RMOD_ERR);
  887. }
  888.  
  889. #endif
  890.  
  891. /* end of ctrbl2.c */
  892.