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 >
Wrap
Text File
|
1986-07-20
|
21KB
|
597 lines
byte sort.rec.present;
print off;
{------------------------------------------------------------
{ start of FULL.SORT procedure (including sub-procs)
{ F U L L S O R T (M U L T I - M E R G E)
{------------------------------------------------------------
procedure full.sort:
begin
set sr.sz = ((128 / ##sort.rec) * ##sort.rec);
{---------------------------------------------------
{ Record and File for intermediate sort storage
{---------------------------------------------------
record partial.rec;
string 128;
endrec;
file partial.sort.file,
disk,
random,
key part.actual.key,
record partial.rec,
status part.stat,
value "PARTIAL.DAT";
word part.key;
pointer to string part.rec.ptr;
word part.key.limit;
word part.ptr.limit;
{*debug*} string wk.str 81;
{-------------------------------------------
{ DATA FOR ALPHABETIC FULLSORT
{-------------------------------------------
external label entry address 5;
word mid.key.tbl.start;
word mid.ix.limit;
pointer to word mid.ix;
external word avail.mem.top address 6;
word master.himem value himem;
word pointer sort.ptr.tbl.wp;
string pointer sort.ptr.tbl.start;
string pointer sort.ptr.tbl.end;
word sort.ptr.save.end;
word sort.ptr.tbl.size;
string pointer sort.value.tbl.sp;
word sort.value.tbl.end;
pointer to word x;
pointer to word wk.ptr;
field hi.value.field ##sort.field;
field lowest.field ##sort.field;
pointer to word lowest.ix;
string pointer lowest.tbl.ptr;
pointer to string lowest.field.ix;
record merge.ptr.tbl.rec;
word mid.end.key;
string pointer curr.value.ptr;
string pointer curr.rec.ptr;
endrec;
word counter.input value 0;
word counter.part value 0;
word counter.sorted value 0;
{-------------------------------
{ END OF DATA FOR FULL-SORT
{-------------------------------
procedure display.counters:
begin
string wk.str 6;
string cr 2 value "~0d~";
convert counter.input to dec wk.str;
display cr,"input:",wk.str,;
convert counter.part to dec wk.str;
display " partial:",wk.str,;
convert counter.sorted to dec wk.str;
display " sorted:",wk.str,cr,;
end;
{-----------------------------------------------------
{ G E T P A R T I A L S O R T
{
{ --- When 'get.partial.sort' is called, 'part.key'
{ will have a value for the logical record
{ date which is to be returned.
{ 'get.partial.sort' should compute the actual
{ record number, and index into the record which
{ correspond to the value of 'part.key', and read
{ the appropriate record.
{-----------------------------------------------------
procedure get.partial.sort:
begin
word last.part.key value ^hffff;
divide part.key by (128 / ##sort.rec) giving part.actual.key
remainder part.rec.ptr;
multiply part.rec.ptr by ##sort.rec;
if part.actual.key <> last.part.key then
move part.actual.key to last.part.key;
read partial.sort.file error standard;
fi;
end;
{-----------------------------------------------------
{ P U T P A R T I A L S O R T
{
{ --- 'part.key' will be zero the first time 'put.-
{ partial.sort' is called, and will be incre-
{ mented by 1 on each successive call.
{ --- If 'put.partial.sort' is blocking records,
{ 'part.key' need not be used as an actual key
{ value, but the routine 'get.partial.sort'
{ most be able to retrieve the same values for
{ any value of 'part.key' as corresponded to it
{ when 'put.partial.sort' was called.
{ --- When there is no more data to be written,
{ 'put.partial.sort' will be called with
{ 'ptr.to.value.to.sort' equal to zero.
{ *** NOTE: If there are few enough entries to be
{ sorted, neither 'put.partial.sort' nor 'get.-
{ partial.sort' will be called.
{-----------------------------------------------------
procedure put.partial.sort:
begin
divide part.key by (128 / ##sort.rec) giving part.actual.key
remainder part.rec.ptr;
multiply part.rec.ptr by ##sort.rec;
add #partial.rec to part.rec.ptr;
if sort.rec.present <> 'N' then
move sort.rec[string] to @part.rec.ptr length ##sort.rec;
if part.rec.ptr >= (#partial.rec + (sr.sz - ##sort.rec)) then
write partial.sort.file error standard;
fi;
else
write partial.sort.file error standard;
fi;
end;
{-----------------------------------------------------
{
{ P A R T I A L S O R T
{
{ (Using the Merge-Sort Algorithm)
{
{ External Parameters:
{ sort.ptr.tbl.start
{ sort.ptr.tbl.end
{ sort.ptr.tbl.size
{
{
{-----------------------------------------------------
procedure partial.sort:
begin
pointer to word sublst.1st.strt;
pointer to word sublst.1st.wk;
pointer to word sublst.2nd.strt;
pointer to word sublst.2nd.wk;
pointer to word sublst.limit;
pointer to word last.entry.ptr;
pointer to word x;
pointer to string temp.ptr.to.value1;
pointer to string temp.ptr.to.value2;
word sublst.size;
word last.sublst.size
word sort.size;
{-------------------------------------------------------
{ Compute # bytes in list of pointers to be sorted
{-------------------------------------------------------
subtract sort.ptr.tbl.start from sort.ptr.tbl.end giving sort.size;
subtract 2 from sort.ptr.tbl.end giving last.entry.ptr;
{-------------------------------------------------------
{ Presort list so that adjacent entries are sorted
{-------------------------------------------------------
move sort.ptr.tbl.start to x;
do
move @x to temp.ptr.to.value1;
add 2 to x;
move @x to temp.ptr.to.value2;
if @temp.ptr.to.value1 > @temp.ptr.to.value2
length ##sort.field then
{---------------------------------------
{ values out of order - swap then
{---------------------------------------
move temp.ptr.to.value1 to @x;
subtract 2 from x giving wk.ptr;
move temp.ptr.to.value2 to @wk.ptr;
fi;
add 2 to x;
od until x >= last.entry.ptr;
{-----------------------------------------------------------
{ sublst.size is # bytes in pointer-lists aleady sorted
{ last.sublst.size is sublst.size from prev. pass
{-----------------------------------------------------------
move 4 to sublst.size;
move 2 to last.sublst.size;
{------------------------------------------------------------
{ keep going until the size of the lists sorted includes
{ all of the list to be sorted.
{------------------------------------------------------------
while last.sublst.size < sort.size do
move sort.ptr.tbl.start to sublst.1st.strt;
{-----------------------------------------------------------
{ go through each pair of sorted sublists and merge them
{-----------------------------------------------------------
while sublst.1st.strt < sort.ptr.tbl.end do
move sublst.1st.strt to sublst.1st.wk;
add sublst.size to sublst.1st.strt giving sublst.2nd.strt;
move sublst.2nd.strt to sublst.2nd.wk;
add sublst.size to sublst.2nd.strt giving sublst.limit;
{---------------------------------------------------
{ the following loop merges one pair of sublists
{---------------------------------------------------
do
{-------------------------------------------
{ check if first sublist is exhausted
{ if so, copy out remainder of 2nd sublist
{-------------------------------------------
if sublst.1st.wk >= sublst.2nd.strt then
while sublst.1st.strt < sublst.limit do
if sublst.1st.strt > last.entry.ptr then
move sublst.limit to sublst.1st.strt;
else
add sort.ptr.tbl.size to sublst.1st.strt
giving x;
move @sublst.2nd.wk to @x;
add 2 to sublst.1st.strt;
add 2 to sublst.2nd.wk;
fi;
od;
exitdo;
fi;
{---------------------------------------------------
{ special case when 2nd sublist goes past end
{---------------------------------------------------
if sublst.2nd.wk > last.entry.ptr then
add 2 to last.entry.ptr giving sublst.limit;
fi;
{-----------------------------------------------
{ check if 2nd sublist is exhausted, if so
{ copy out reaminder of 1st sublist
{-----------------------------------------------
if sublst.2nd.wk >= sublst.limit then
while sublst.1st.strt < sublst.limit do
add sort.ptr.tbl.size to sublst.1st.strt
giving x;
move @sublst.1st.wk to @x;
add 2 to sublst.1st.wk;
add 2 to sublst.1st.strt;
od;
exitdo;
fi;
{---------------------------------------------------
{ Neither sublist is exhausted, compare current
{ entries in each, and copy out lowest one
{---------------------------------------------------
add sort.ptr.tbl.size to sublst.1st.strt giving x;
move @sublst.1st.wk to temp.ptr.to.value1;
move @sublst.2nd.wk to temp.ptr.to.value2;
if @temp.ptr.to.value1 > @temp.ptr.to.value2
length ##sort.field then
move @sublst.2nd.wk to @x;
add 2 to sublst.2nd.wk;
else
move @sublst.1st.wk to @x;
add 2 to sublst.1st.wk;
fi;
add 2 to sublst.1st.strt;
od;
{-----------------------------------------------
{ End of loop to merge one pair of sublists
{-----------------------------------------------
od;
{-----------------------------------------------------------
{ All pairs of sublists are merged into sublists of
{ twice the size. Adjust size-counters to reflect this
{ Copy pointer-save area into pointer-work area.
{-----------------------------------------------------------
move sublst.size to last.sublst.size;
add sublst.size to sublst.size;
move @sort.ptr.tbl.end to @sort.ptr.tbl.start
length sort.ptr.tbl.size;
od;
end;
{-----------------------------------------------------
{ E N D O F P A R T I A L S O R T
{-----------------------------------------------------
{-----------------------}
{ initialize stuff }
{-----------------------}
mcall entry using 12 giving counter.input;
if counter.input[+1,byte] <> 0 then {---running MP/M---}
mcall entry using 153 giving ,,,counter.input[byte];
add '0' to counter.input[byte]
giving partial.sort.file[+8,byte];
fi;
fill hi.value.field with ^hff;
move 0 to counter.input;
move 0 to counter.part;
move 0 to counter.sorted;
move 0 to part.key;
open partial.sort.file output remove error standard;
{-------------------}
{ room for stack }
{-------------------}
subtract 40 from avail.mem.top giving sort.value.tbl.end;
{-------------------------------------------------------}
{ values to be sorted built from top of memory down }
{-------------------------------------------------------}
move sort.value.tbl.end to sort.value.tbl.sp;
{-----------------------------------------------}
{ first is table of keys to partial sorts }
{-----------------------------------------------}
move master.himem to mid.key.tbl.start;
move mid.key.tbl.start to mid.ix;
add 2 to master.himem;
{---------------------------------------------------}
{ next is table of pointers to sort.rec values }
{---------------------------------------------------}
move master.himem to sort.ptr.tbl.start;
move sort.ptr.tbl.start to sort.ptr.tbl.end;
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
move sort.ptr.tbl.start to sort.ptr.save.end;
move 0 to sort.ptr.tbl.size;
move 0 to part.key;
{---------------------------------------------------}
{ loop to read in all input, doing partial sorts }
{ when available memory fills up }
{---------------------------------------------------}
do
{-----------------------------------------------}
{ check if memory for new entry is available }
{ sort.ptr.save.end is hi-limit of low mem
{ sort.value.tbl.sp is lo-limit of high mem
{-----------------------------------------------}
subtract sort.ptr.save.end from sort.value.tbl.sp giving x;
if x < (##sort.rec + 4) then
{---------------------------------------}
{ memory is full - do a partial sort }
{---------------------------------------}
move sort.ptr.tbl.wp to sort.ptr.tbl.end;
call display.counters;
call partial.sort;
call display.counters;
{-----------------------------------------------}
{ save the key to this partial sort in table }
{-----------------------------------------------}
move part.key to @mid.ix;
add 2 to mid.ix;
{-----------------------------------------------}
{ write the sorted partial list to temp file }
{-----------------------------------------------}
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
do
move @sort.ptr.tbl.wp to sort.value.tbl.sp;
move @sort.value.tbl.sp to sort.rec[string]
length ##sort.rec;
move 'Y' to sort.rec.present;
call put.partial.sort;
add 1 to part.key;
add 2 to sort.ptr.tbl.wp;
od until sort.ptr.tbl.wp >= sort.ptr.tbl.end;
move part.key to counter.part;
call display.counters;
{---------------------------------------------------}
{ room for next key in table of partial.sort keys }
{---------------------------------------------------}
add 2 to sort.ptr.tbl.start;
{---------------------------------------------------}
{ reset pointers for next load of stuff to sort }
{---------------------------------------------------}
move sort.value.tbl.end to sort.value.tbl.sp;
move sort.ptr.tbl.start to sort.ptr.tbl.end;
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
move sort.ptr.tbl.start to sort.ptr.save.end;
move 0 to sort.ptr.tbl.size;
fi;
{---------------------------}
{ get something to sort }
{---------------------------}
call sort.input;
{-----------------------}
{ check if finished }
{-----------------------}
if sort.rec.present = 'N' then
exitdo;
fi;
{-------------------------------------------}
{ move value to value-table, and pointer }
{ to value in pointer table }
{-------------------------------------------}
add 1 to counter.input;
subtract ##sort.rec from sort.value.tbl.sp;
move sort.rec[string] to @sort.value.tbl.sp
length ##sort.rec;
move sort.value.tbl.sp to @sort.ptr.tbl.wp;
add 2 to sort.ptr.tbl.wp;
add 2 to sort.ptr.tbl.size;
add 4 to sort.ptr.save.end;
od;
{---------------------------------------------------}
{ all input is done - sort remainder in memory }
{---------------------------------------------------}
call display.counters;
move sort.ptr.tbl.wp to sort.ptr.tbl.end;
call partial.sort;
call display.counters;
if part.key = 0 then
{-------------------------------------------}
{ no previous partial sorts were done, }
{ no need to use temporary file }
{-------------------------------------------}
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
while sort.ptr.tbl.wp < sort.ptr.tbl.end do
move @sort.ptr.tbl.wp to sort.value.tbl.sp;
move @sort.value.tbl.sp to sort.rec[string]
length ##sort.rec;
move 'Y' to sort.rec.present;
call sort.output;
add 1 to counter.sorted;
add 2 to sort.ptr.tbl.wp;
od;
else
{-----------------------------------------------}
{ there was more input than could be done in }
{ memory at one time, flush remainder of sort }
{ out to temporary file }
{-----------------------------------------------}
move part.key to @mid.ix;
add 2 to mid.ix;
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
while sort.ptr.tbl.wp < sort.ptr.tbl.end do
move @sort.ptr.tbl.wp to sort.value.tbl.sp;
move @sort.value.tbl.sp to sort.rec[string]
length ##sort.rec;
move 'Y' to sort.rec.present;
call put.partial.sort;
add 1 to part.key;
add 2 to sort.ptr.tbl.wp;
od;
move part.key to counter.part;
call display.counters;
move part.key to @mid.ix;
move mid.ix to mid.ix.limit;
add 2 to mid.ix.limit giving sort.ptr.tbl.start;
{--force write of last recd of partial-sort file--
move 'N' to sort.rec.present;
call put.partial.sort;
{-------------------------------------------------------}
{ 'himem' usage is now different, the table of keys }
{ to the temp file stays in place, followed by the }
{ table of merge-pointers. A list of RECORDS from }
{ the temp file is built down from the top of memory }
{-------------------------------------------------------}
move sort.value.tbl.end to sort.value.tbl.sp;
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
move mid.key.tbl.start to mid.ix;
while mid.ix < mid.ix.limit do
subtract sort.ptr.tbl.wp from sort.value.tbl.sp giving x;
if x < (##merge.ptr.tbl.rec + sr.sz) then
display "too many records to sort - sort not done";
goto end;
fi;
move @mid.ix to part.key;
add 2 to mid.ix;
move @mid.ix to mid.end.key;
call get.partial.sort;
subtract sr.sz from sort.value.tbl.sp;
add part.rec.ptr to sort.value.tbl.sp
giving curr.value.ptr;
move sort.value.tbl.sp to curr.rec.ptr;
move partial.rec[string] to @sort.value.tbl.sp
length sr.sz;
move merge.ptr.tbl.rec[string] to @sort.ptr.tbl.wp[sp]
length ##merge.ptr.tbl.rec;
add ##merge.ptr.tbl.rec to sort.ptr.tbl.wp;
od;
{-------------------------------------------------------}
{ loop to find lowest value from all partial sorts }
{ and write it to the output file. }
{-------------------------------------------------------}
do
move hi.value.field to lowest.field;
move mid.key.tbl.start to mid.ix;
move 0 to lowest.ix;
move sort.ptr.tbl.start to sort.ptr.tbl.wp;
while mid.ix < mid.ix.limit do
move @sort.ptr.tbl.wp[sp] to merge.ptr.tbl.rec[string]
length ##merge.ptr.tbl.rec;
if @curr.value.ptr < lowest.field[string]
length ##sort.field then
move mid.ix to lowest.ix;
move sort.ptr.tbl.wp to lowest.tbl.ptr;
move @curr.value.ptr to lowest.field[string]
length ##sort.field;
move curr.value.ptr to lowest.field.ix;
fi;
add 2 to mid.ix;
add ##merge.ptr.tbl.rec to sort.ptr.tbl.wp;
od;
{-----------------------------------------------}
{ check if finished -- NOTE: if sorting keys }
{ which might be all (hex) FF's, more will }
{ need to be done here }
{-----------------------------------------------}
if lowest.ix = 0 then
exitdo;
fi;
{-------------------------------}
{ write out the lowest value }
{-------------------------------}
move @lowest.field.ix to sort.rec[string]
length ##sort.rec;
move 'Y' to sort.rec.present;
call sort.output;
add 1 to counter.sorted;
{-------------------------------------------}
{ count to next record for this sub-sort }
{-------------------------------------------}
add 1 to @lowest.ix;
{-------------------------------------------}
{ get merge-table entry for this sub-sort }
{ check if list is exhausted }
{-------------------------------------------}
move @lowest.tbl.ptr to merge.ptr.tbl.rec[string]
length ##merge.ptr.tbl.rec;
if @lowest.ix >= mid.end.key then
{-------------------------------}
{ this sub-sort is exhausted }
{-------------------------------}
move hi.value.field[string] to @lowest.field.ix
length ##sort.field;
else
{---------------------------------------------------}
{ bump value-pointer to next value within record }
{---------------------------------------------------}
add ##sort.rec to curr.value.ptr;
{---------------------------------------------------}
{ if no more values in this record, read next one }
{---------------------------------------------------}
add sr.sz to curr.rec.ptr giving x;
if curr.value.ptr >= x then
move @lowest.ix to part.key;
call get.partial.sort;
move partial.rec[string] to @curr.rec.ptr length
sr.sz;
move curr.rec.ptr to curr.value.ptr;
call display.counters;
fi;
move merge.ptr.tbl.rec[string] to @lowest.tbl.ptr
length ##merge.ptr.tbl.rec;
fi;
od;
fi;
move 'N' to sort.rec.present;
call sort.output;
call display.counters;
close partial.sort.file error standard;
remove partial.sort.file;
end;
{-----------------------------------------------------
{ E N D O F F U L L - S O R T
{-----------------------------------------------------
print on;