home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
progs
/
grpsort.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
6KB
|
191 lines
############################################################################
#
# File: grpsort.icn
#
# Subject: Program to sort groups of lines
#
# Author: Thomas R. Hicks
#
# Date: June 10, 1988
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# This program sorts input containing ``records'' defined to be
# groups of consecutive lines. Output is written to standard out-
# put. Each input record is separated by one or more repetitions
# of a demarcation line (a line beginning with the separator
# string). The first line of each record is used as the key.
#
# If no separator string is specified on the command line, the
# default is the empty string. Because all input lines are trimmed
# of whitespace (blanks and tabs), empty lines are default demarca-
# tion lines. The separator string specified can be an initial sub-
# string of the string used to demarcate lines, in which case the
# resulting partition of the input file may be different from a
# partition created using the entire demarcation string.
#
# The -o option sorts the input file but does not produce the
# sorted records. Instead it lists the keys (in sorted order) and
# line numbers defining the extent of the record associated with
# each key.
#
# The use of grpsort is illustrated by the following examples.
# The command
#
# grpsort "catscats" <x >y
#
# sorts the file x, whose records are separated by lines containing
# the string "catscats", into the file y placing a single line of
# "catscats" between each output record. Similarly, the command
#
# grpsort "cats" <x >y
#
# sorts the file x as before but assumes that any line beginning
# with the string "cats" delimits a new record. This may or may not
# divide the lines of the input file into a number of records dif-
# ferent from the previous example. In any case, the output
# records will be separated by a single line of "cats". Another
# example is
#
# grpsort -o <bibliography >bibkeys
#
# which sorts the file bibliography and produces a sorted list of
# the keys and the extents of the associated records in bibkeys.
# Each output key line is of the form:
#
# [s-e] key
#
# where
#
# s is the line number of the key line
# e is the line number of the last line
# key is the actual key of the record
#
#
############################################################################
#
# Links: usage
#
############################################################################
link usage
global lcount, linelst, ordflag
procedure main(args)
local division, keytable, keylist, line, info, nexthdr, null
linelst := []
keytable := table()
lcount := 0
if *args = 2 then
if args[1] == "-o" then
ordflag := pop(args)
else
Usage("groupsort [-o] [separator string] <file >sortedfile")
if *args = 1 then {
if args[1] == "?" then
Usage("groupsort [-o] [separator string] <file >sortedfile")
if args[1] == "-o" then
ordflag := pop(args)
else
division := args[1]
}
if *args = 0 then
division := ""
nexthdr := lmany(division) | fail # find at least one record or quit
info := [nexthdr,[lcount]]
# gather all data lines for this group/record
while line := getline() do {
if eorec(division,line) then { # at end of this record
# enter record info into sort key table
put(info[2],lcount-1)
enter(info,keytable)
# look for header of next record
if nexthdr := lmany(division) then
info := [nexthdr,[lcount]] # begin next group/record
else
info := null
}
}
# enter last line info into sort key table
if \info then {
put(info[2],lcount)
enter(info,keytable)
}
keylist := sort(keytable,1) # sort by record headers
if \ordflag then
printord(keylist) # list sorted order of records
else
printrecs(keylist,division) # print records in order
end
# enter - enter the group info into the sort key table
procedure enter(info,tbl)
if /tbl[info[1]] then # new key value
tbl[info[1]] := [info[2]]
else
put(tbl[info[1]],info[2]) # add occurrance info
end
# eorec - suceed if a delimiter string has been found, fail otherwise
procedure eorec(div,str)
if div == "" then # If delimiter string is empty,
if str == div then return # then make exact match
else
fail
if match(div,str) then return # Otherwise match initial string.
else
fail
end
# getline - get the next line (or fail), trim off trailing tabs and blanks.
procedure getline()
local line
static trimset
initial trimset := ' \t'
if line := trim(read(),trimset) then {
if /ordflag then # save only if going to print later
put(linelst,line)
lcount +:= 1
return line
}
end
# lmany - skip over many lines matching string div.
procedure lmany(div)
local line
while line := getline() do {
if eorec(div,line) then next #skip over multiple dividing lines
return line
}
end
# printord - print only the selection order of the records.
procedure printord(slist)
local x, y
every x := !slist do
every y := !x[2] do
write(y[1],"-",y[2],"\t",x[1])
end
# printrecs - write the records in sorted order, separated by div string.
procedure printrecs(slist,div)
local x, y, z
every x := !slist do
every y := !x[2] do {
every z := y[1] to y[2] do
write(linelst[z])
write(div)
}
end