home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 311_01 / sort.c < prev    next >
C/C++ Source or Header  |  1990-04-22  |  16KB  |  675 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                 S O R T  -  Callable Sort Facility                       */
  4. /*                             (c) 1987-1990 Ken Harris                     */
  5. /*                                                                          */
  6. /****************************************************************************/
  7. /*                                                                          */
  8. /*      This software is made available on an AS-IS basis. Unrestricted     */
  9. /*      use is granted provided that the copyright notice remains intact.   */
  10. /*      The author makes no warranties expressed or implied.                */
  11. /*                                                                          */
  12. /****************************************************************************/
  13.  
  14. char *copywrite = "sort v1.3 (c) 1987-1990  Ken Harris";
  15.  
  16. #include "dblib.h"
  17.  
  18. #define SORT_CLOSED          0
  19. #define SORT_OPEN         1
  20. #define SORT_DONE         2
  21. #define SORT_EOF             3
  22. #define MIN_BUFFER_SIZE   1000
  23. #define MAX_BUFFER_SIZE  32000
  24.  
  25. struct sort_buffer
  26. {    int   sb_file;            /* file descriptor        */
  27.     long  sb_fcnt;            /* file block count        */
  28.     long  sb_fpos;            /* file position        */
  29.     char *sb_badr;            /* buffer address        */
  30.     long  sb_bsiz;            /* buffer size in bytes     */
  31.     long  sb_rsiz;            /* buffer size in records    */
  32.     long  sb_rcnt;            /* current record count     */
  33.     char *sb_radr;            /* current record address    */
  34. };
  35.  
  36. struct key_field
  37. {    struct key_field *kf_next;    /* next key field        */
  38.     char   kf_type;         /* field type  'A' = Ascii    */
  39.                     /*           'I' = Integer    */
  40.                     /*           'U' = Unsigned    */
  41.     char   kf_seq;            /* sort order  'A' = Ascending    */
  42.                     /*           'D' = Descending */
  43.     int    kf_pos;            /* starting position        */
  44.     int    kf_size;         /* field size            */
  45. };
  46.  
  47. static int  sfile1;            /* temp file #1         */
  48. static int  sfile2;            /* temp file #2         */
  49. static int  sfile3;            /* temp file #3         */
  50.  
  51. static int  sort_state = 0;        /* current state of the sort    */  
  52.                     /* 0 = Sort not initialized    */
  53.                     /* 1 = Sort is    initialized    */
  54.                     /* 2 = Sort has been done    */
  55.  
  56. static int  sort_rec_size;        /* Size of user data record    */
  57. static long sort_rec_cnt;        /* Record Count         */
  58. static int  sort_key_size;        /* Size of user key        */
  59. static int  sort_krec_size;        /* Size of key + control info    */   
  60. static long sort_merge_cnt;        /* count records in merge pass    */
  61. static long sort_next_fpos;        /* position of next file block    */
  62. static struct key_field *key_spec=NULL; /* sort key specs        */
  63. static char *sort_key_rec;
  64.  
  65. static struct sort_buffer sbuf1;    /* Sort buffer #1        */
  66. static struct sort_buffer sbuf2;    /* Sort buffer #2        */
  67. static struct sort_buffer sbuf3;    /* Sort buffer #3        */
  68.  
  69. #ifdef ANSI
  70.     static one_merge_pass();
  71.     static char *sort_read(struct sort_buffer *);
  72.     static merge_write(struct sort_buffer *);
  73.     static sort_close();
  74.     static sort_write(int, char *, int);
  75.     static sort_error(char *);
  76. #else
  77.     static one_merge_pass();
  78.     static char *sort_read();
  79.     static merge_write();
  80.     static sort_close();
  81.     static sort_write();
  82.     static sort_error();
  83. #endif
  84.  
  85. long lseek();
  86.  
  87. /*
  88.  *    sort_init  -  Initialize the sort data
  89.  */
  90.  
  91. sort_init(rec_size, spec_str)
  92.  int   rec_size;
  93.  char *spec_str;
  94. {
  95. #ifdef MSC
  96.         unsigned _memavl();
  97. #endif
  98. #ifdef TURBO
  99.     unsigned coreleft();
  100. #endif
  101.         long  buf_size;
  102.         char *calloc();
  103.  
  104.     if (sort_state != SORT_CLOSED)
  105.         sort_error("Sort Already Initialized");
  106.  
  107.     sort_rec_size    = rec_size;
  108.     bld_key_spec(spec_str);
  109.  
  110.         sort_krec_size  = sort_key_size + sizeof(long);
  111.     sort_krec_size += sort_krec_size % 2;
  112.     sort_rec_cnt    = 0;
  113.  
  114.         sort_key_rec = (char *) calloc(1,sort_key_size);
  115.  
  116. #ifdef ULTRIX
  117.         sfile1 = open("SORT1.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  118.         sfile2 = open("SORT2.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  119.         sfile3 = open("SORT3.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  120. #endif
  121. #ifdef SYSV
  122.         sfile1 = open("SORT1.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  123.         sfile2 = open("SORT2.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  124.         sfile3 = open("SORT3.TMP", O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
  125. #endif
  126. #ifdef MSC
  127.         sfile1 = open("SORT1.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  128.         sfile2 = open("SORT2.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  129.         sfile3 = open("SORT3.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  130. #endif
  131. #ifdef TURBO
  132.         sfile1 = open("SORT1.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  133.         sfile2 = open("SORT2.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  134.         sfile3 = open("SORT3.TMP", O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE);
  135. #endif
  136.  
  137.     if (sfile1 < 0 || sfile2 < 0 || sfile3 < 0)
  138.         sort_error("Can't Open Temp Files");
  139.  
  140. #ifdef ULTRIX
  141.     buf_size  = MAX_BUFFER_SIZE;
  142. #endif
  143. #ifdef SYSV
  144.     buf_size  = MAX_BUFFER_SIZE;
  145. #endif
  146. #ifdef MSC
  147.         buf_size  = _memavl();
  148. #endif
  149. #ifdef TURBO
  150.     buf_size  = coreleft();
  151. #endif
  152.     if (buf_size > MAX_BUFFER_SIZE) buf_size = MAX_BUFFER_SIZE;
  153.     buf_size  = (buf_size * 3)/4;
  154.     buf_size -= buf_size % sort_krec_size;
  155.  
  156.     if (buf_size < MIN_BUFFER_SIZE)
  157.         sort_error("Insufficient Memory");
  158.  
  159.         sbuf1.sb_badr = (char *) calloc(1,buf_size);
  160.     sbuf1.sb_bsiz = buf_size;
  161.     sbuf1.sb_rsiz = buf_size/sort_krec_size;
  162.     sbuf1.sb_radr = sbuf1.sb_badr;
  163.     sbuf1.sb_rcnt = 0;
  164.  
  165.     sort_state = SORT_OPEN;
  166. }                      
  167.  
  168. /*
  169.  *    bld_key_spec  -  Build Sort Key Spec
  170.  */
  171. bld_key_spec(s)
  172.  char *s;
  173. {
  174.         struct  key_field *f;
  175.         char   *calloc(), ch;
  176.  
  177.     sort_key_size = 0;
  178.     f = key_spec  = NULL;
  179.     while (*s)
  180.     {
  181.         if (!key_spec)
  182.                         key_spec = f = (struct key_field *) calloc(1,sizeof(struct key_field));
  183.         else
  184.                 {       f->kf_next = (struct key_field *) calloc(1,sizeof(struct key_field));
  185.             f = f->kf_next;
  186.         }
  187.  
  188.         f->kf_next = NULL;
  189.         ch = *s++;
  190.         if (islower(ch)) ch = toupper(ch);
  191.         if (ch=='A' || ch=='D')
  192.             f->kf_seq = ch;
  193.         else
  194.             sort_error("Invalid Key Spec - Unknown Sequence");
  195.  
  196.         ch = *s++;
  197.         if (islower(ch)) ch = toupper(ch);
  198.         if (ch=='A' || ch=='I' || ch=='U' || ch=='R')
  199.             f->kf_type = ch;
  200.         else
  201.             sort_error("Invalid Key Spec - Unknown Field Type");
  202.  
  203.         f->kf_pos=0;
  204.         while (isdigit(*s))
  205.             f->kf_pos = 10 * f->kf_pos + (*s++ - '0');
  206.  
  207.         if (f->kf_pos < 1)
  208.             sort_error("Invalid Sort Spec - Invalid Starting Position");
  209.  
  210.         if (*s++ != '.')
  211.             sort_error("Invalid Sort Spec - Missing Field Size");
  212.  
  213.         f->kf_size=0;
  214.         while (isdigit(*s))
  215.             f->kf_size = 10 * f->kf_size + (*s++ - '0');
  216.              
  217.         sort_key_size += f->kf_size;
  218.  
  219.         if (f->kf_pos + f->kf_size - 1 > sort_rec_size)
  220.             sort_error("Invalid Sort Spec - Field Exceeds Record");
  221.  
  222.         if (*s==',') s++;
  223.     }
  224. }
  225.  
  226. /*
  227.  *    sort_release  -  Release a record to the sort
  228.  */
  229.  
  230. sort_release(data)
  231.  char *data;
  232. {
  233.     int  sort_cmp();
  234.     long *k_cnt;
  235.     char *k_dat;
  236.  
  237.  
  238.     if (sort_state != SORT_OPEN)
  239.         sort_error("Improper Record Release");
  240.  
  241.     bld_sort_key(data);
  242.  
  243.     sort_rec_cnt++;
  244.     sort_write(sfile1, data, sort_rec_size);
  245.  
  246.     k_cnt  = (long *) sbuf1.sb_radr;
  247.     k_dat  = sbuf1.sb_radr + sizeof(long);
  248.     *k_cnt = sort_rec_cnt;
  249.     memcpy(k_dat, sort_key_rec, sort_key_size);
  250.  
  251.     sbuf1.sb_rcnt++;
  252.         if (sbuf1.sb_rcnt < sbuf1.sb_rsiz)
  253.         sbuf1.sb_radr += sort_krec_size;
  254.     else
  255.     {    qsort(sbuf1.sb_badr, (int)sbuf1.sb_rcnt, sort_krec_size, sort_cmp);
  256.         sort_write(sfile2, (char *)&sbuf1.sb_rcnt, sizeof(long));
  257.         sort_write(sfile2, sbuf1.sb_badr, sbuf1.sb_rcnt*sort_krec_size);
  258.         sbuf1.sb_rcnt = 0;
  259.         sbuf1.sb_radr = sbuf1.sb_badr;
  260.     }
  261. }
  262.  
  263.  
  264.  
  265.  
  266. /*
  267.  *    sort_cmp  -  sort compare function
  268.  */
  269.  sort_cmp(s1,s2)
  270.   char *s1, *s2;
  271. {
  272.     return(memcmp(s1+sizeof(long),s2+sizeof(long),sort_key_size));
  273. }
  274.  
  275. /*
  276.  *    bld_sort_key  -  Build the sort key record
  277.  */
  278.  
  279. bld_sort_key(data)
  280.  char *data;
  281. {
  282.     struct key_field *f;
  283.     char *s,*d;
  284.     int  i, tmp, cmpl;
  285.  
  286.     d = sort_key_rec;
  287.     f = key_spec;     
  288.  
  289.     while (f)
  290.     {
  291.         s = data + f->kf_pos - 1;
  292.  
  293.         switch(f->kf_type)
  294.         {    case 'A':      
  295.                 for (i=0; i < f->kf_size; i++)
  296.                     if (f->kf_seq == 'A')
  297.                         *d++ = *s++;
  298.                     else
  299.                         *d++ = ~*s++;
  300.                 break;
  301.  
  302.                         case 'U':
  303.                 s += f->kf_size - 1;
  304.  
  305.                                 for (i=0; i < f->kf_size; i++)
  306.                     if (f->kf_seq == 'A')
  307.                         *d++ = *s--;
  308.                     else
  309.                         *d++ = ~*s--;
  310.                 break;
  311.  
  312.             case 'I':
  313.                 s += f->kf_size - 1;
  314.  
  315.                                 if (f->kf_seq == 'A')
  316.                     *d++ = (*s--)^0200;
  317.                 else
  318.                     *d++ = ~((*s--)^0200);
  319.  
  320.                                 for (i=1; i < f->kf_size; i++)
  321.                     if (f->kf_seq == 'A')
  322.                         *d++ = *s--;
  323.                     else
  324.                         *d++ = ~*s--;
  325.  
  326.                                 break;
  327.  
  328.                         case 'R':
  329.                 s += f->kf_size - 1;
  330.  
  331.                 if (*s & 0200)
  332.                 {    cmpl = 1;
  333.                     tmp  = ~(*s--);
  334.                 }              
  335.                 else
  336.                 {    cmpl = 0;
  337.                     tmp  = (*s--) ^ 0200;
  338.                 }
  339.  
  340.                 if (f->kf_seq == 'D') 
  341.                 {    cmpl ^= 1;
  342.                     *d++  = ~tmp;
  343.                 }
  344.                 else
  345.                     *d++ = tmp;
  346.  
  347.                 for (i=1; i < f->kf_size; i++)
  348.                 {    if (cmpl)
  349.                         *d++ = ~*s--;
  350.                     else
  351.                         *d++ = *s--;
  352.                 }
  353.                                 break;
  354.  
  355.                         default: break;
  356.         }
  357.  
  358.         f = f->kf_next;
  359.     }
  360. }
  361.  
  362. /*
  363.  *    sort_merge  -  Do the merge
  364.  */
  365.  
  366. sort_merge()
  367. {
  368.     if (sort_state != SORT_OPEN)
  369.         sort_error("Merge Called Out of Sequence");
  370.  
  371.         if (!sort_rec_cnt)
  372.         {       sort_state = SORT_EOF;
  373.                 return;
  374.         }
  375.  
  376.     merge_init();
  377.  
  378.         while (sort_state != SORT_DONE)
  379.     {    lseek(sfile2, 0L, 0);
  380.         lseek(sfile3, 0L, 0);
  381.  
  382.         sort_merge_cnt = 0;
  383.         sort_next_fpos = 0;
  384.  
  385.         sbuf3.sb_radr = sbuf3.sb_badr;
  386.         sbuf3.sb_rsiz = sbuf3.sb_bsiz / sort_krec_size;
  387.         sbuf3.sb_rcnt = 0;
  388.  
  389.                 one_merge_pass();
  390.  
  391.         if (sort_merge_cnt != sort_rec_cnt)
  392.             sort_error("Merge Count Error");
  393.  
  394.         if (sort_state != SORT_DONE)
  395.         {    sbuf1.sb_file = sbuf3.sb_file;
  396.             sbuf3.sb_file = sbuf2.sb_file;
  397.             sbuf2.sb_file = sbuf1.sb_file;
  398.         }
  399.     }
  400.  
  401.     sort_merge_cnt = 0;
  402.     sort_next_fpos = 0;
  403.         sbuf1.sb_bsiz += sbuf2.sb_bsiz + sbuf3.sb_bsiz;
  404.         sbuf1.sb_rsiz =  sbuf1.sb_rcnt = 0;
  405.         sbuf1.sb_radr = NULL;
  406.     lseek(sbuf1.sb_file, 0L, 0);
  407.         get_merge_block(&sbuf1);
  408. }
  409.  
  410. static one_merge_pass()
  411. {
  412.         char *r1, *r2, *sort_read();
  413.     long block_size;
  414.  
  415.     while (sort_merge_cnt < sort_rec_cnt)
  416.     {    get_merge_block(&sbuf1);
  417.         get_merge_block(&sbuf2);
  418.  
  419.         if (sbuf1.sb_fcnt >= sort_rec_cnt)
  420.         {    sort_state = SORT_DONE;
  421.             return;
  422.         }
  423.  
  424.         block_size = sbuf1.sb_fcnt + sbuf2.sb_fcnt;
  425.         sort_write(sbuf3.sb_file, (char *)&block_size, sizeof(long));
  426.  
  427.         r1 = sort_read(&sbuf1);
  428.                 r2 = sort_read(&sbuf2);
  429.  
  430.         while (r1 && r2)
  431.         {    switch (sort_cmp(r1,r2))
  432.             {    case -1: merge_write(&sbuf1);
  433.                      r1 = sort_read(&sbuf1);
  434.                      break;
  435.  
  436.                 case  0: merge_write(&sbuf1);
  437.                      merge_write(&sbuf2);
  438.                      r1 = sort_read(&sbuf1);
  439.                      r2 = sort_read(&sbuf2);
  440.                      break;
  441.  
  442.                 case  1: merge_write(&sbuf2);
  443.                      r2 = sort_read(&sbuf2);
  444.                      break;
  445.             }
  446.         }
  447.         while (r1)
  448.         {    merge_write(&sbuf1);
  449.             r1 = sort_read(&sbuf1);
  450.         }
  451.  
  452.         while (r2)
  453.         {    merge_write(&sbuf2);
  454.             r2 = sort_read(&sbuf2);
  455.         }
  456.  
  457.         if (sbuf3.sb_rcnt)
  458.         {    sort_write(sbuf3.sb_file, sbuf3.sb_badr, sbuf3.sb_rcnt*sort_krec_size);
  459.             sbuf3.sb_rcnt = 0;
  460.             sbuf3.sb_radr = sbuf3.sb_badr;
  461.         }
  462.         }
  463. }
  464.  
  465. /*
  466.  *    merge_init  -  Merge Initialization
  467.  */
  468.  
  469. merge_init()
  470. {
  471.     unsigned int buf_size;
  472.  
  473.  
  474.     if (sbuf1.sb_rcnt)
  475.     {    qsort(sbuf1.sb_badr, (int)sbuf1.sb_rcnt, sort_krec_size, sort_cmp);
  476.         sort_write(sfile2, (char *)&sbuf1.sb_rcnt, sizeof(long));
  477.         sort_write(sfile2, sbuf1.sb_badr, sbuf1.sb_rcnt*sort_krec_size);
  478.         sbuf1.sb_rcnt = 0;
  479.         sbuf1.sb_radr = sbuf1.sb_badr;
  480.     }
  481.  
  482.     buf_size  = sbuf1.sb_bsiz / 3;
  483.     buf_size -= buf_size % sort_krec_size;         
  484.  
  485.     sbuf1.sb_bsiz = buf_size;
  486.     sbuf2.sb_bsiz = buf_size;
  487.     sbuf3.sb_bsiz = buf_size;
  488.  
  489.     sbuf2.sb_badr = sbuf1.sb_badr + buf_size;
  490.     sbuf3.sb_badr = sbuf2.sb_badr + buf_size;
  491.  
  492.         sbuf1.sb_rsiz = sbuf1.sb_rcnt = 0;
  493.         sbuf2.sb_rsiz = sbuf2.sb_rcnt = 0;
  494.         sbuf3.sb_rsiz = sbuf3.sb_rcnt = 0;
  495.  
  496.         sbuf1.sb_radr = NULL;
  497.         sbuf2.sb_radr = NULL;
  498.         sbuf3.sb_radr = NULL;
  499.  
  500.         sbuf1.sb_file = sfile2;
  501.     sbuf1.sb_fcnt = 0;
  502.     sbuf1.sb_fpos = 0L;
  503.  
  504.     sbuf2.sb_file = sfile2;
  505.     sbuf2.sb_fcnt = 0;
  506.     sbuf2.sb_fpos = 0L;
  507.  
  508.     sbuf3.sb_file = sfile3;
  509.     sbuf3.sb_fcnt = 0;
  510.     sbuf3.sb_fpos = 0L;
  511. }
  512.  
  513. /*
  514.  *    sort_return  -    return a record from the sort
  515.  */
  516.  
  517. char *sort_return(buf)
  518.  char *buf;
  519. {      
  520.     long *key;
  521.         char *sort_read();
  522.  
  523.         if (sort_state == SORT_EOF)
  524.     {    sort_close();
  525.         return(NULL);
  526.     }
  527.  
  528.     if (sort_state != SORT_DONE)
  529.         sort_error("Sort Return Sequence Error");
  530.  
  531.         key = (long *) sort_read(&sbuf1);
  532.  
  533.     if (!key)
  534.     {    sort_close();
  535.         return(NULL);
  536.     }
  537.  
  538.         lseek(sfile1, (long)((*key-1)*sort_rec_size), 0);
  539.         if (read(sfile1, buf, sort_rec_size) != sort_rec_size)
  540.         sort_error("Return Read Error");
  541.  
  542.         return(buf);
  543. }
  544.  
  545. /*
  546.  *    sort_read  -  Read record from merge buffer
  547.  */
  548.  
  549. static char *sort_read(buf)
  550.  struct sort_buffer *buf;
  551. {               
  552.     int cnt;
  553.  
  554.     if (buf->sb_rcnt < buf->sb_rsiz)
  555.     {    buf->sb_rcnt++;
  556.         buf->sb_radr += sort_krec_size;
  557.         return(buf->sb_radr);
  558.     }
  559.  
  560.     if (!buf->sb_fcnt) return(NULL);
  561.  
  562.     lseek(buf->sb_file, buf->sb_fpos, 0);
  563.  
  564.     buf->sb_rsiz = buf->sb_bsiz / sort_krec_size;
  565.     if (buf->sb_rsiz > buf->sb_fcnt)
  566.         buf->sb_rsiz = buf->sb_fcnt;
  567.  
  568.     if (read(buf->sb_file, buf->sb_badr, buf->sb_rsiz * sort_krec_size) <= 0)
  569.         sort_error("Temp File Read Error");
  570.     
  571.     buf->sb_fcnt   -= buf->sb_rsiz;
  572.     buf->sb_fpos   += buf->sb_rsiz * sort_krec_size;
  573.     buf->sb_rcnt    = 1;
  574.     buf->sb_radr    = buf->sb_badr;
  575.  
  576.     return(buf->sb_radr);
  577. }
  578.  
  579. /*
  580.  *    get_merge_block  -  Read up the next merge block
  581.  */
  582. get_merge_block(buf)
  583.  struct sort_buffer *buf;
  584. {
  585.     buf->sb_rsiz = 0;
  586.     buf->sb_rcnt = 0;
  587.     buf->sb_radr = 0;
  588.  
  589.         if (sort_merge_cnt >= sort_rec_cnt)
  590.     {    buf->sb_fcnt = 0;
  591.         return;
  592.     }
  593.  
  594.     lseek(buf->sb_file, sort_next_fpos, 0);
  595.     if (read(buf->sb_file, &buf->sb_fcnt, sizeof(long)) <= 0)
  596.         sort_error("Merge Read Error");
  597.  
  598.     buf->sb_fpos    = sort_next_fpos + sizeof(long);
  599.     sort_merge_cnt += buf->sb_fcnt;
  600.     sort_next_fpos += sizeof(long) + buf->sb_fcnt * sort_krec_size;
  601. }
  602.                                          
  603. /*
  604.  *    merge_write  -    merge output
  605.  */
  606.  
  607. static merge_write(buf)
  608.  struct sort_buffer *buf;
  609. {
  610.     memcpy(sbuf3.sb_radr, buf->sb_radr, sort_krec_size);
  611.  
  612.     sbuf3.sb_rcnt++;
  613.     if (sbuf3.sb_rcnt < sbuf3.sb_rsiz)
  614.         sbuf3.sb_radr += sort_krec_size;
  615.     else
  616.     {    sort_write(sbuf3.sb_file, sbuf3.sb_badr, sbuf3.sb_rcnt*sort_krec_size);
  617.         sbuf3.sb_rcnt = 0;
  618.         sbuf3.sb_radr = sbuf3.sb_badr;
  619.     }
  620. }
  621.  
  622. /*
  623.  *    sort_close  -  Cleanup after a sort
  624.  */
  625.  
  626. static sort_close()
  627. {
  628.     struct key_field *f, *t;
  629.  
  630.         if (sort_state == SORT_CLOSED) return;
  631.  
  632.     close(sfile1);
  633.     close(sfile2);
  634.     close(sfile3);
  635.  
  636.     unlink("SORT1.TMP");
  637.     unlink("SORT2.TMP");
  638.     unlink("SORT3.TMP");
  639.  
  640.         f = key_spec;
  641.     while (f)
  642.     {    t = f->kf_next;
  643.         free(f);
  644.         f = t;
  645.     }
  646.  
  647.         free(sort_key_rec);
  648.         free(sbuf1.sb_badr);
  649.  
  650.     sort_state = SORT_CLOSED;
  651. }
  652.  
  653. /*
  654.  *    sort_write  -  Write a reord to temp file
  655.  */
  656.  
  657. static sort_write(fd, buf, cnt)
  658.  int   fd, cnt;
  659.  char *buf;    
  660. {
  661.     if (write(fd, buf, cnt) < cnt)
  662.         sort_error("Write Error, Check Disk Space");
  663. }
  664.  
  665. /*
  666.  *    sort_error  -    Sort Error Exit
  667.  */
  668.  
  669. static sort_error(text)
  670.  char *text;
  671. {
  672.     fprintf(stderr,"\n\nSort Error: %s\7\n\n",text);
  673.     exit(1);
  674. }
  675.