home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / PARASOL / VIDEOSTO.ARK / FULLSORT.LIB < prev    next >
Text File  |  1986-07-20  |  21KB  |  597 lines

  1. byte                sort.rec.present;
  2. print off;
  3. {------------------------------------------------------------
  4. {    start of FULL.SORT procedure (including sub-procs)
  5. {    F U L L     S O R T     (M U L T I - M E R G E)
  6. {------------------------------------------------------------
  7. procedure    full.sort:
  8. begin
  9.  
  10. set    sr.sz    =    ((128 / ##sort.rec) * ##sort.rec);
  11.  
  12. {---------------------------------------------------
  13. {    Record and File for intermediate sort storage
  14. {---------------------------------------------------
  15. record    partial.rec;
  16.     string    128;
  17.     endrec;
  18.  
  19. file    partial.sort.file,
  20.         disk,
  21.         random,
  22.         key part.actual.key,
  23.         record partial.rec,
  24.         status part.stat,
  25.         value "PARTIAL.DAT";
  26.  
  27. word                part.key;
  28. pointer to string    part.rec.ptr;
  29. word                part.key.limit;
  30. word                part.ptr.limit;
  31. {*debug*}    string    wk.str    81;
  32.  
  33. {-------------------------------------------
  34. {        DATA  FOR  ALPHABETIC  FULLSORT
  35. {-------------------------------------------
  36.  
  37. external label entry address 5;
  38.  
  39. word                mid.key.tbl.start;
  40.  
  41. word                mid.ix.limit;
  42. pointer to word        mid.ix;
  43.  
  44. external word        avail.mem.top    address 6;
  45. word                master.himem        value himem;
  46.  
  47. word pointer        sort.ptr.tbl.wp;
  48. string pointer        sort.ptr.tbl.start;
  49. string pointer        sort.ptr.tbl.end;
  50. word                sort.ptr.save.end;
  51. word                sort.ptr.tbl.size;
  52.  
  53. string pointer        sort.value.tbl.sp;
  54. word                sort.value.tbl.end;
  55. pointer to word        x;
  56. pointer to word        wk.ptr;
  57.  
  58.  
  59. field                hi.value.field    ##sort.field;
  60. field                lowest.field     ##sort.field;
  61. pointer to word        lowest.ix;
  62. string pointer        lowest.tbl.ptr;
  63. pointer to string    lowest.field.ix;
  64.  
  65. record            merge.ptr.tbl.rec;
  66.     word            mid.end.key;
  67.     string pointer    curr.value.ptr;
  68.     string pointer    curr.rec.ptr;
  69.     endrec;
  70.  
  71. word                counter.input    value 0;
  72. word                counter.part    value 0;
  73. word                counter.sorted    value 0;
  74.  
  75. {-------------------------------
  76. {    END OF DATA FOR FULL-SORT
  77. {-------------------------------
  78. procedure    display.counters:
  79. begin
  80. string    wk.str    6;
  81. string    cr        2    value    "~0d~";
  82.     convert counter.input to dec wk.str;
  83.     display cr,"input:",wk.str,;
  84.     convert counter.part to dec wk.str;
  85.     display "   partial:",wk.str,;
  86.     convert counter.sorted to dec wk.str;
  87.     display "   sorted:",wk.str,cr,;
  88.     end;
  89.  
  90. {-----------------------------------------------------
  91. {        G E T     P A R T I A L     S O R T
  92. {
  93. {    ---    When 'get.partial.sort' is called, 'part.key'
  94. {        will have a value for the logical record
  95. {        date which is to be returned.
  96. {        'get.partial.sort' should compute the actual
  97. {        record number, and index into the record which
  98. {        correspond to the value of 'part.key', and read
  99. {        the appropriate record.
  100. {-----------------------------------------------------
  101. procedure    get.partial.sort:
  102. begin
  103.  
  104. word    last.part.key    value    ^hffff;
  105.  
  106.     divide part.key by (128 / ##sort.rec) giving part.actual.key
  107.                         remainder part.rec.ptr;
  108.     multiply part.rec.ptr by ##sort.rec;
  109.     if part.actual.key <> last.part.key then
  110.         move part.actual.key to last.part.key;
  111.         read partial.sort.file error standard;
  112.         fi;
  113. end;
  114.  
  115.  
  116.  
  117. {-----------------------------------------------------
  118. {        P U T     P A R T I A L     S O R T
  119. {
  120. {    ---    'part.key' will be zero the first time 'put.-
  121. {        partial.sort' is called, and will be incre-
  122. {        mented by 1 on each successive call.
  123. {    ---    If 'put.partial.sort' is blocking records,
  124. {        'part.key' need not be used as an actual key
  125. {        value, but the routine 'get.partial.sort'
  126. {        most be able to retrieve the same values for
  127. {        any value of 'part.key' as corresponded to it
  128. {        when 'put.partial.sort' was called.
  129. {    ---    When there is no more data to be written,
  130. {        'put.partial.sort' will be called with
  131. {        'ptr.to.value.to.sort' equal to zero.
  132. {    ***    NOTE:  If there are few enough entries to be
  133. {        sorted, neither 'put.partial.sort' nor 'get.-
  134. {        partial.sort' will be called.
  135. {-----------------------------------------------------
  136. procedure    put.partial.sort:
  137. begin
  138.     divide part.key by (128 / ##sort.rec) giving part.actual.key
  139.                         remainder part.rec.ptr;
  140.     multiply part.rec.ptr by ##sort.rec;
  141.     add #partial.rec to part.rec.ptr;
  142.     if sort.rec.present <> 'N' then
  143.         move sort.rec[string] to @part.rec.ptr length ##sort.rec;
  144.         if part.rec.ptr >= (#partial.rec + (sr.sz - ##sort.rec)) then
  145.             write partial.sort.file error standard;
  146.             fi;
  147.     else
  148.         write partial.sort.file error standard;
  149.         fi;
  150. end;
  151.  
  152.  
  153.  
  154.  
  155.  
  156. {-----------------------------------------------------
  157. {
  158. {        P A R T I A L      S O R T
  159. {
  160. {            (Using the Merge-Sort Algorithm)
  161. {
  162. {    External Parameters:
  163. {        sort.ptr.tbl.start
  164. {        sort.ptr.tbl.end
  165. {        sort.ptr.tbl.size
  166. {
  167. {
  168. {-----------------------------------------------------
  169. procedure    partial.sort:
  170. begin
  171.  
  172. pointer to word        sublst.1st.strt;
  173. pointer to word        sublst.1st.wk;
  174. pointer to word        sublst.2nd.strt;
  175. pointer to word        sublst.2nd.wk;
  176. pointer to word        sublst.limit;
  177. pointer to word        last.entry.ptr;
  178. pointer to word        x;
  179.  
  180. pointer to string    temp.ptr.to.value1;
  181. pointer to string    temp.ptr.to.value2;
  182.  
  183. word                sublst.size;
  184. word                last.sublst.size
  185. word                sort.size;
  186.  
  187.  
  188.  
  189.  
  190.     {-------------------------------------------------------
  191.     {    Compute # bytes in list of pointers to be sorted
  192.     {-------------------------------------------------------
  193.     subtract sort.ptr.tbl.start from sort.ptr.tbl.end giving sort.size;
  194.     subtract 2 from sort.ptr.tbl.end giving last.entry.ptr;
  195.     {-------------------------------------------------------
  196.     {    Presort list so that adjacent entries are sorted
  197.     {-------------------------------------------------------
  198.     move sort.ptr.tbl.start to x;
  199.     do
  200.         move @x    to     temp.ptr.to.value1;
  201.         add    2    to     x;
  202.         move @x    to     temp.ptr.to.value2;
  203.         if @temp.ptr.to.value1 > @temp.ptr.to.value2
  204.                                             length ##sort.field then
  205.             {---------------------------------------
  206.             {    values out of order - swap then
  207.             {---------------------------------------
  208.             move temp.ptr.to.value1    to @x;
  209.             subtract 2    from    x giving wk.ptr;
  210.             move temp.ptr.to.value2    to @wk.ptr;
  211.             fi;
  212.         add    2        to x;
  213.         od until x >= last.entry.ptr;
  214.  
  215.     {-----------------------------------------------------------
  216.     {   sublst.size is # bytes in pointer-lists aleady sorted
  217.     {   last.sublst.size is sublst.size from prev. pass
  218.     {-----------------------------------------------------------
  219.     move 4 to sublst.size;
  220.     move 2 to last.sublst.size;
  221.  
  222.     {------------------------------------------------------------
  223.     {   keep going until the size of the lists sorted includes
  224.     {   all of the list to be sorted.
  225.     {------------------------------------------------------------
  226.     while last.sublst.size    <    sort.size    do
  227.         move sort.ptr.tbl.start    to sublst.1st.strt;
  228.         {-----------------------------------------------------------
  229.         {   go through each pair of sorted sublists and merge them
  230.         {-----------------------------------------------------------
  231.         while sublst.1st.strt    <    sort.ptr.tbl.end    do
  232.             move sublst.1st.strt    to sublst.1st.wk;
  233.             add    sublst.size    to sublst.1st.strt giving sublst.2nd.strt;
  234.             move sublst.2nd.strt    to sublst.2nd.wk;
  235.             add    sublst.size    to sublst.2nd.strt giving sublst.limit;
  236.             {---------------------------------------------------
  237.             {   the following loop merges one pair of sublists
  238.             {---------------------------------------------------
  239.             do
  240.                 {-------------------------------------------
  241.                 {   check if first sublist is exhausted
  242.                 {    if so, copy out remainder of 2nd sublist
  243.                 {-------------------------------------------
  244.                 if    sublst.1st.wk    >=    sublst.2nd.strt   then
  245.                     while    sublst.1st.strt      <      sublst.limit    do
  246.                         if    sublst.1st.strt      >  last.entry.ptr    then
  247.                             move sublst.limit    to sublst.1st.strt;
  248.                         else
  249.                             add    sort.ptr.tbl.size    to sublst.1st.strt
  250.                                                     giving x;
  251.                             move @sublst.2nd.wk    to @x;
  252.                             add 2 to sublst.1st.strt;
  253.                             add 2 to sublst.2nd.wk;
  254.                             fi;
  255.                         od;
  256.                     exitdo;
  257.                     fi;
  258.                 {---------------------------------------------------
  259.                 {    special case when 2nd sublist goes past end
  260.                 {---------------------------------------------------
  261.                 if    sublst.2nd.wk    >    last.entry.ptr        then
  262.                     add    2    to last.entry.ptr    giving    sublst.limit;
  263.                     fi;
  264.                 {-----------------------------------------------
  265.                 {    check if 2nd sublist is exhausted, if so
  266.                 {    copy out reaminder of 1st sublist
  267.                 {-----------------------------------------------
  268.                 if    sublst.2nd.wk    >=    sublst.limit    then
  269.                     while    sublst.1st.strt      <   sublst.limit    do
  270.                         add    sort.ptr.tbl.size    to sublst.1st.strt
  271.                                                 giving x;
  272.                         move @sublst.1st.wk        to @x;
  273.                         add 2 to sublst.1st.wk;
  274.                         add 2 to sublst.1st.strt;
  275.                         od;
  276.                     exitdo;
  277.                     fi;
  278.                 {---------------------------------------------------
  279.                 {    Neither sublist is exhausted, compare current
  280.                 {    entries in each, and copy out lowest one
  281.                 {---------------------------------------------------
  282.                 add sort.ptr.tbl.size to sublst.1st.strt giving x;
  283.                 move @sublst.1st.wk    to temp.ptr.to.value1;
  284.                 move @sublst.2nd.wk    to temp.ptr.to.value2;
  285.                 if @temp.ptr.to.value1 > @temp.ptr.to.value2
  286.                                             length ##sort.field    then
  287.                     move @sublst.2nd.wk    to @x;
  288.                     add    2                to sublst.2nd.wk;
  289.                 else
  290.                     move @sublst.1st.wk    to @x;
  291.                     add    2                to sublst.1st.wk;
  292.                     fi;
  293.                 add 2 to sublst.1st.strt;
  294.                 od;
  295.             {-----------------------------------------------
  296.             {    End of loop to merge one pair of sublists
  297.             {-----------------------------------------------
  298.             od;
  299.         {-----------------------------------------------------------
  300.         {    All pairs of sublists are merged into sublists of
  301.         {    twice the size.  Adjust size-counters to reflect this
  302.         {    Copy pointer-save area into pointer-work area.
  303.         {-----------------------------------------------------------
  304.         move sublst.size        to     last.sublst.size;
  305.         add    sublst.size            to     sublst.size;
  306.         move @sort.ptr.tbl.end    to @sort.ptr.tbl.start
  307.                                 length sort.ptr.tbl.size;
  308.         od;
  309.     end;
  310. {-----------------------------------------------------
  311. {            E N D    O F    P A R T I A L    S O R T
  312. {-----------------------------------------------------
  313.  
  314.  
  315.  
  316.  
  317.  
  318.     {-----------------------}
  319.     {    initialize stuff    }
  320.     {-----------------------}
  321.     mcall entry using 12 giving counter.input;
  322.     if counter.input[+1,byte] <> 0 then        {---running MP/M---}
  323.         mcall entry using 153 giving ,,,counter.input[byte];
  324.         add '0' to counter.input[byte]
  325.                                     giving partial.sort.file[+8,byte];
  326.         fi;
  327.     fill hi.value.field with ^hff;
  328.     move 0 to counter.input;
  329.     move 0 to counter.part;
  330.     move 0 to counter.sorted;
  331.     move 0 to part.key;
  332.     open partial.sort.file output remove error standard;
  333.  
  334.  
  335.     {-------------------}
  336.     {    room for stack    }
  337.     {-------------------}
  338.     subtract 40 from avail.mem.top giving sort.value.tbl.end;
  339.     {-------------------------------------------------------}
  340.     {    values to be sorted built from top of memory down    }
  341.     {-------------------------------------------------------}
  342.     move sort.value.tbl.end        to sort.value.tbl.sp;
  343.     {-----------------------------------------------}
  344.     {    first is table of keys to partial sorts        }
  345.     {-----------------------------------------------}
  346.     move master.himem            to mid.key.tbl.start;
  347.     move mid.key.tbl.start        to mid.ix;
  348.     add  2                        to master.himem;
  349.     {---------------------------------------------------}
  350.     {    next is table of pointers to sort.rec values    }
  351.     {---------------------------------------------------}
  352.     move master.himem            to sort.ptr.tbl.start;
  353.     move sort.ptr.tbl.start        to sort.ptr.tbl.end;
  354.     move sort.ptr.tbl.start        to sort.ptr.tbl.wp;
  355.     move sort.ptr.tbl.start        to sort.ptr.save.end;
  356.     move 0                        to sort.ptr.tbl.size;
  357.     move 0                        to part.key;
  358.     {---------------------------------------------------}
  359.     {    loop to read in all input, doing partial sorts    }
  360.     {    when available memory fills up                    }
  361.     {---------------------------------------------------}
  362.     do
  363.         {-----------------------------------------------}
  364.         {    check if memory for new entry is available    }
  365.         {    sort.ptr.save.end is hi-limit of low mem
  366.         {    sort.value.tbl.sp is lo-limit of high mem
  367.         {-----------------------------------------------}
  368.         subtract sort.ptr.save.end from sort.value.tbl.sp giving x;
  369.         if x < (##sort.rec + 4) then
  370.             {---------------------------------------}
  371.             {    memory is full - do a partial sort    }
  372.             {---------------------------------------}
  373.             move sort.ptr.tbl.wp to sort.ptr.tbl.end;
  374.             call display.counters;
  375.             call partial.sort;
  376.             call display.counters;
  377.             {-----------------------------------------------}
  378.             {    save the key to this partial sort in table    }
  379.             {-----------------------------------------------}
  380.             move part.key            to @mid.ix;
  381.             add    2                    to mid.ix;
  382.             {-----------------------------------------------}
  383.             {    write the sorted partial list to temp file    }
  384.             {-----------------------------------------------}
  385.             move sort.ptr.tbl.start    to sort.ptr.tbl.wp;
  386.             do
  387.                 move @sort.ptr.tbl.wp    to sort.value.tbl.sp;
  388.                 move @sort.value.tbl.sp    to sort.rec[string]
  389.                                         length ##sort.rec;
  390.                 move 'Y' to sort.rec.present;
  391.                 call put.partial.sort;
  392.                 add    1                to part.key;
  393.                 add 2 to sort.ptr.tbl.wp;
  394.                 od until sort.ptr.tbl.wp >= sort.ptr.tbl.end;
  395.             move part.key to counter.part;
  396.             call display.counters;
  397.             {---------------------------------------------------}
  398.             {    room for next key in table of partial.sort keys    }
  399.             {---------------------------------------------------}
  400.             add  2                        to sort.ptr.tbl.start;
  401.             {---------------------------------------------------}
  402.             {    reset pointers for next load of stuff to sort    }
  403.             {---------------------------------------------------}
  404.             move sort.value.tbl.end        to sort.value.tbl.sp;
  405.             move sort.ptr.tbl.start        to sort.ptr.tbl.end;
  406.             move sort.ptr.tbl.start        to sort.ptr.tbl.wp;
  407.             move sort.ptr.tbl.start        to sort.ptr.save.end;
  408.             move 0                        to sort.ptr.tbl.size;
  409.             fi;
  410.         {---------------------------}
  411.         {    get something to sort    }
  412.         {---------------------------}
  413.         call sort.input;
  414.         {-----------------------}
  415.         {    check if finished    }
  416.         {-----------------------}
  417.         if sort.rec.present = 'N' then
  418.             exitdo;
  419.             fi;
  420.         {-------------------------------------------}
  421.         {    move value to value-table, and pointer    }
  422.         {    to value in pointer table                }
  423.         {-------------------------------------------}
  424.         add 1 to counter.input;
  425.         subtract ##sort.rec        from sort.value.tbl.sp;
  426.         move sort.rec[string]    to @sort.value.tbl.sp
  427.                                                     length ##sort.rec;
  428.         move sort.value.tbl.sp    to @sort.ptr.tbl.wp;
  429.         add 2                    to sort.ptr.tbl.wp;
  430.         add 2                    to sort.ptr.tbl.size;
  431.         add 4                    to sort.ptr.save.end;
  432.         od;
  433.     {---------------------------------------------------}
  434.     {    all input is done - sort remainder in memory    }
  435.     {---------------------------------------------------}
  436.     call display.counters;
  437.     move sort.ptr.tbl.wp to sort.ptr.tbl.end;
  438.     call partial.sort;
  439.     call display.counters;
  440.     if part.key  =  0 then
  441.         {-------------------------------------------}
  442.         {    no previous partial sorts were done,    }
  443.         {    no need to use temporary file            }
  444.         {-------------------------------------------}
  445.         move sort.ptr.tbl.start        to sort.ptr.tbl.wp;
  446.         while sort.ptr.tbl.wp < sort.ptr.tbl.end do
  447.             move @sort.ptr.tbl.wp    to sort.value.tbl.sp;
  448.             move @sort.value.tbl.sp    to sort.rec[string]
  449.                                                     length ##sort.rec;
  450.             move 'Y' to sort.rec.present;
  451.             call sort.output;
  452.             add 1 to counter.sorted;
  453.             add 2 to sort.ptr.tbl.wp;
  454.             od;
  455.     else
  456.         {-----------------------------------------------}
  457.         {    there was more input than could be done in    }
  458.         {    memory at one time, flush remainder of sort    }
  459.         {    out to temporary file                        }
  460.         {-----------------------------------------------}
  461.         move part.key                to @mid.ix;
  462.         add    2                        to mid.ix;
  463.         move sort.ptr.tbl.start        to sort.ptr.tbl.wp;
  464.         while sort.ptr.tbl.wp < sort.ptr.tbl.end do
  465.             move @sort.ptr.tbl.wp    to sort.value.tbl.sp;
  466.             move @sort.value.tbl.sp    to sort.rec[string]
  467.                                                     length ##sort.rec;
  468.             move 'Y' to sort.rec.present;
  469.             call put.partial.sort;
  470.             add    1                to part.key;
  471.             add    2                to sort.ptr.tbl.wp;
  472.             od;
  473.         move part.key            to counter.part;
  474.         call display.counters;
  475.         move part.key            to @mid.ix;
  476.         move mid.ix                to mid.ix.limit;
  477.         add 2 to mid.ix.limit    giving sort.ptr.tbl.start;
  478.         {--force write of last recd of partial-sort file--
  479.         move 'N' to sort.rec.present;
  480.         call put.partial.sort;
  481.         {-------------------------------------------------------}
  482.         {    'himem' usage is now different, the table of keys    }
  483.         {    to the temp file stays in place, followed by the    }
  484.         {    table of merge-pointers.  A list of RECORDS from    }
  485.         {    the temp file is built down from the top of memory    }
  486.         {-------------------------------------------------------}
  487.         move sort.value.tbl.end    to sort.value.tbl.sp;
  488.         move sort.ptr.tbl.start    to sort.ptr.tbl.wp;
  489.         move mid.key.tbl.start            to mid.ix;
  490.         while    mid.ix    <    mid.ix.limit    do
  491.             subtract sort.ptr.tbl.wp from sort.value.tbl.sp giving x;
  492.             if x < (##merge.ptr.tbl.rec + sr.sz) then
  493.                 display "too many records to sort - sort not done";
  494.                 goto end;
  495.                 fi;
  496.             move @mid.ix        to part.key;
  497.             add    2                to mid.ix;
  498.             move @mid.ix        to mid.end.key;
  499.             call get.partial.sort;
  500.             subtract sr.sz from sort.value.tbl.sp;
  501.             add part.rec.ptr    to sort.value.tbl.sp
  502.                                                 giving curr.value.ptr;
  503.             move sort.value.tbl.sp    to curr.rec.ptr;
  504.             move partial.rec[string] to @sort.value.tbl.sp
  505.                                                         length sr.sz;
  506.             move merge.ptr.tbl.rec[string] to @sort.ptr.tbl.wp[sp]
  507.                                             length ##merge.ptr.tbl.rec;
  508.             add ##merge.ptr.tbl.rec    to sort.ptr.tbl.wp;
  509.             od;
  510.         {-------------------------------------------------------}
  511.         {    loop to find lowest value from all partial sorts    }
  512.         {    and write it to the output file.                    }
  513.         {-------------------------------------------------------}
  514.         do
  515.             move hi.value.field        to lowest.field;
  516.             move mid.key.tbl.start    to mid.ix;
  517.             move 0                    to lowest.ix;
  518.             move sort.ptr.tbl.start    to sort.ptr.tbl.wp;
  519.             while    mid.ix  <  mid.ix.limit        do
  520.                 move @sort.ptr.tbl.wp[sp] to merge.ptr.tbl.rec[string]
  521.                                             length ##merge.ptr.tbl.rec;
  522.                 if @curr.value.ptr < lowest.field[string]
  523.                                             length ##sort.field then
  524.                     move mid.ix             to lowest.ix;
  525.                     move sort.ptr.tbl.wp to lowest.tbl.ptr;
  526.                     move @curr.value.ptr to lowest.field[string]
  527.                                             length ##sort.field;
  528.                     move  curr.value.ptr    to lowest.field.ix;
  529.                     fi;
  530.                 add    2                    to mid.ix;
  531.                 add ##merge.ptr.tbl.rec    to sort.ptr.tbl.wp;
  532.                 od;
  533.             {-----------------------------------------------}
  534.             {    check if finished -- NOTE: if sorting keys    }
  535.             {    which might be all (hex) FF's, more will    }
  536.             {    need to be done here                        }
  537.             {-----------------------------------------------}
  538.             if lowest.ix = 0 then
  539.                 exitdo;
  540.                 fi;
  541.             {-------------------------------}
  542.             {    write out the lowest value    }
  543.             {-------------------------------}
  544.             move @lowest.field.ix    to sort.rec[string]
  545.                                                     length ##sort.rec;
  546.             move 'Y' to sort.rec.present;
  547.             call sort.output;
  548.             add 1                to counter.sorted;
  549.             {-------------------------------------------}
  550.             {    count to next record for this sub-sort    }
  551.             {-------------------------------------------}
  552.             add    1                to @lowest.ix;
  553.             {-------------------------------------------}
  554.             {    get merge-table entry for this sub-sort    }
  555.             {    check if list is exhausted                }
  556.             {-------------------------------------------}
  557.             move @lowest.tbl.ptr to merge.ptr.tbl.rec[string]
  558.                                             length ##merge.ptr.tbl.rec;
  559.             if    @lowest.ix    >=    mid.end.key    then
  560.                 {-------------------------------}
  561.                 {    this sub-sort is exhausted    }
  562.                 {-------------------------------}
  563.                 move hi.value.field[string]    to @lowest.field.ix
  564.                                                 length ##sort.field;
  565.             else
  566.                 {---------------------------------------------------}
  567.                 {    bump value-pointer to next value within record    }
  568.                 {---------------------------------------------------}
  569.                 add ##sort.rec to curr.value.ptr;
  570.                 {---------------------------------------------------}
  571.                 {    if no more values in this record, read next one    }
  572.                 {---------------------------------------------------}
  573.                 add sr.sz to curr.rec.ptr giving x;
  574.                 if curr.value.ptr >= x then
  575.                     move @lowest.ix        to part.key;
  576.                     call get.partial.sort;
  577.                     move partial.rec[string] to @curr.rec.ptr length
  578.                                                             sr.sz;
  579.                     move curr.rec.ptr    to curr.value.ptr;
  580.                     call display.counters;
  581.                     fi;
  582.                 move merge.ptr.tbl.rec[string] to @lowest.tbl.ptr
  583.                                     length ##merge.ptr.tbl.rec;
  584.                 fi;
  585.             od;
  586.         fi;
  587.     move 'N' to sort.rec.present;
  588.     call sort.output;
  589.     call display.counters;
  590.     close partial.sort.file error standard;
  591.     remove partial.sort.file;
  592. end;
  593. {-----------------------------------------------------
  594. {            E N D    O F    F U L L - S O R T
  595. {-----------------------------------------------------
  596. print on;
  597.