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 >
Text File  |  2000-07-29  |  6KB  |  191 lines

  1. ############################################################################
  2. #
  3. #    File:     grpsort.icn
  4. #
  5. #    Subject:  Program to sort groups of lines
  6. #
  7. #    Author:   Thomas R. Hicks
  8. #
  9. #    Date:     June 10, 1988
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #  
  17. #     This program sorts input containing ``records'' defined to be
  18. #  groups of consecutive lines. Output is written to standard out-
  19. #  put.  Each input record is separated by one or more repetitions
  20. #  of a demarcation line (a line beginning with the separator
  21. #  string).  The first line of each record is used as the key.
  22. #  
  23. #     If no separator string is specified on the command line, the
  24. #  default is the empty string. Because all input lines are trimmed
  25. #  of whitespace (blanks and tabs), empty lines are default demarca-
  26. #  tion lines. The separator string specified can be an initial sub-
  27. #  string of the string used to demarcate lines, in which case the
  28. #  resulting partition of the input file may be different from a
  29. #  partition created using the entire demarcation string.
  30. #  
  31. #     The -o option sorts the input file but does not produce the
  32. #  sorted records.  Instead it lists the keys (in sorted order) and
  33. #  line numbers defining the extent of the record associated with
  34. #  each key.
  35. #  
  36. #     The use of grpsort is illustrated by the following examples.
  37. #  The command
  38. #  
  39. #          grpsort "catscats" <x >y
  40. #  
  41. #  sorts the file x, whose records are separated by lines containing
  42. #  the string "catscats", into the file y placing a single line of
  43. #  "catscats" between each output record. Similarly, the command
  44. #  
  45. #          grpsort "cats" <x >y
  46. #  
  47. #  sorts the file x as before but assumes that any line beginning
  48. #  with the string "cats" delimits a new record. This may or may not
  49. #  divide the lines of the input file into a number of records dif-
  50. #  ferent from the previous example.  In any case, the output
  51. #  records will be separated by a single line of "cats".  Another
  52. #  example is
  53. #  
  54. #          grpsort -o <bibliography >bibkeys
  55. #  
  56. #  which sorts the file bibliography and produces a sorted list of
  57. #  the keys and the extents of the associated records in bibkeys.
  58. #  Each output key line is of the form:
  59. #  
  60. #          [s-e] key
  61. #  
  62. #  where
  63. #  
  64. #          s     is the line number of the key line
  65. #          e     is the line number of the last line
  66. #          key   is the actual key of the record
  67. #  
  68. #  
  69. ############################################################################
  70. #
  71. #  Links: usage
  72. #
  73. ############################################################################
  74.  
  75. link usage
  76.  
  77. global lcount, linelst, ordflag
  78.  
  79. procedure main(args)
  80.    local division, keytable, keylist, line, info, nexthdr, null
  81.    linelst := []
  82.    keytable := table()
  83.    lcount := 0
  84.  
  85.    if *args = 2 then
  86.       if args[1] == "-o" then
  87.           ordflag := pop(args)
  88.       else
  89.           Usage("groupsort [-o] [separator string] <file >sortedfile")
  90.  
  91.    if *args = 1 then {
  92.       if args[1] == "?" then
  93.           Usage("groupsort [-o] [separator string] <file >sortedfile")
  94.       if args[1] == "-o" then
  95.           ordflag := pop(args)
  96.       else
  97.           division := args[1]
  98.       }
  99.  
  100.    if *args = 0 then
  101.       division := ""
  102.  
  103.    nexthdr := lmany(division) | fail    # find at least one record or quit
  104.    info := [nexthdr,[lcount]]
  105.  
  106.    # gather all data lines for this group/record
  107.    while line := getline() do {
  108.       if eorec(division,line) then {    # at end of this record
  109.           # enter record info into sort key table
  110.           put(info[2],lcount-1)
  111.           enter(info,keytable)
  112.           # look for header of next record
  113.           if nexthdr := lmany(division) then
  114.           info := [nexthdr,[lcount]] # begin next group/record
  115.           else
  116.           info := null
  117.           }
  118.       }
  119.    # enter last line info into sort key table
  120.    if \info then {
  121.       put(info[2],lcount)
  122.       enter(info,keytable)
  123.       }
  124.  
  125.    keylist := sort(keytable,1)        # sort by record headers
  126.    if \ordflag then
  127.       printord(keylist)        # list sorted order of records
  128.    else
  129.       printrecs(keylist,division)    # print records in order
  130. end
  131.  
  132. # enter - enter the group info into the sort key table
  133. procedure enter(info,tbl)
  134.    if /tbl[info[1]] then        # new key value
  135.       tbl[info[1]] := [info[2]]
  136.    else
  137.       put(tbl[info[1]],info[2])    # add occurrance info
  138. end
  139.  
  140. # eorec - suceed if a delimiter string has been found, fail otherwise
  141. procedure eorec(div,str)
  142.    if div == "" then            # If delimiter string is empty,
  143.       if str == div then return    # then make exact match
  144.       else
  145.           fail
  146.    if match(div,str) then return    # Otherwise match initial string.
  147.    else
  148.       fail
  149. end
  150.  
  151. # getline - get the next line (or fail), trim off trailing tabs and blanks.
  152. procedure getline()
  153.    local line
  154.    static trimset
  155.    initial trimset := ' \t'
  156.    if line := trim(read(),trimset) then {
  157.       if /ordflag then    # save only if going to print later
  158.           put(linelst,line)
  159.       lcount +:= 1
  160.       return line
  161.       }
  162. end
  163.  
  164. # lmany - skip over many lines matching string div.
  165. procedure lmany(div)
  166.    local line
  167.    while line := getline() do {
  168.       if eorec(div,line) then next    #skip over multiple dividing lines
  169.       return line
  170.       }
  171. end
  172.  
  173. # printord - print only the selection order of the records.
  174. procedure printord(slist)
  175.    local x, y
  176.    every x := !slist do
  177.       every y := !x[2] do
  178.           write(y[1],"-",y[2],"\t",x[1])
  179. end
  180.  
  181. # printrecs - write the records in sorted order, separated by div string.
  182. procedure printrecs(slist,div)
  183.    local x, y, z
  184.    every x := !slist do 
  185.       every y := !x[2] do {
  186.           every z := y[1] to y[2] do
  187.           write(linelst[z])
  188.           write(div)
  189.           }
  190. end
  191.