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 / delam.icn < prev    next >
Text File  |  2000-07-29  |  5KB  |  183 lines

  1. ############################################################################
  2. #
  3. #    File:     delam.icn
  4. #
  5. #    Subject:  Program to delaminate file
  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 delaminates standard input into several output
  18. #  files according to the specified fields.  It writes the fields in
  19. #  each line to the corresponding output files as individual lines.
  20. #  If no data occurs in the specified position for a given input
  21. #  line an empty output line is written. This insures that all out-
  22. #  put files contain the same number of lines as the input file.
  23. #  
  24. #     If - is used for the input file, the standard input is read.
  25. #  If - is used as an output file name, the corresponding field is
  26. #  written to the standard output.
  27. #  
  28. #     The fields are defined by a list of field specifications,
  29. #  separated by commas or colons, of the following form:
  30. #  
  31. #          n    the character in column n
  32. #          n-m  the characters in columns n through m
  33. #          n+m  m characters beginning at column n
  34. #  
  35. #  where the columns in a line are numbered from 1 to the length of
  36. #  the line.
  37. #  
  38. #     The use of delam is illustrated by the following examples.
  39. #  The command
  40. #  
  41. #          delam 1-10,5 x.txt y.txt
  42. #  
  43. #  reads standard input and writes characters 1 through 10 to file
  44. #  x.txt and character 5 to file y.txt.  The command
  45. #  
  46. #          delam 10+5:1-10:1-10:80 mid x1 x2 end
  47. #  
  48. #  writes characters 10 through 14 to mid, 1 through 10 to x1 and
  49. #  x2, and character 80 to end.  The command
  50. #  
  51. #          delam 1-80,1-80 - -
  52. #  
  53. #  copies standard input to standard output, replicating the first
  54. #  eighty columns of each line twice.
  55. #  
  56. ############################################################################
  57. #
  58. #  Links: usage
  59. #
  60. ############################################################################
  61.  
  62. link usage
  63.  
  64. procedure main(a)
  65.    local fylist, ranges
  66.    if any(&digits,a[1]) then
  67.       ranges := fldecode(a[1])
  68.    else
  69.       {
  70.       write(&errout,"Bad argument to delam: ",a[1])
  71.       Usage("delam fieldlist {outputfile | -} ...")
  72.       }
  73.    if not a[2] then
  74.       Usage("delam fieldlist {outputfile | -} ...")
  75.    fylist := doutfyls(a,2)
  76.    if *fylist ~= *ranges then
  77.       stop("Unequal number of field args and output files")
  78.    delamr(ranges,fylist)
  79. end
  80.  
  81. # delamr - do actual division of input file
  82. #
  83. procedure delamr(ranges,fylist)
  84.    local i, j, k, line
  85.    while line := read() do
  86.       {
  87.       i := 1
  88.       while i <= *fylist do
  89.          {
  90.          j := ranges[i][1]
  91.          k := ranges[i][2]
  92.          if k > 0 then
  93.             write(fylist[i][2],line[j+:k] | line[j:0] | "")
  94.          i +:= 1
  95.          }
  96.       }
  97. end
  98.  
  99. # doutfyls - process the output file arguments; return list
  100. #
  101. procedure doutfyls(a,i)
  102.    local lst, x
  103.    lst := []
  104.    while \a[i] do
  105.       {
  106.       if x := llu(a[i],lst) then        # already in list
  107.          lst |||:= [[a[i],lst[x][2]]]
  108.       else                    # not in list
  109.          if a[i] == "-" then            # standard out
  110.             lst |||:= [[a[i],&output]]
  111.          else                    # new file
  112.             if not (x := open(a[i],"w")) then
  113.                stop("Cannot open ",a[i]," for output")
  114.             else
  115.                lst |||:= [[a[i],x]]
  116.       i +:= 1
  117.       }
  118.    return lst
  119.  
  120. end
  121.  
  122. # fldecode - decode the fieldlist argument
  123. #
  124. procedure fldecode(fldlst)
  125.    local fld, flst, poslst, m, n, x
  126.    poslst := []
  127.    flst := str2lst(fldlst,':,')
  128.    every fld := !flst do
  129.       {
  130.       if x := upto('-+',fld) then
  131.          {
  132.          if not (m := integer(fld[1:x])) then
  133.             stop("bad argument in field list; ",fld)
  134.          if not (n := integer(fld[x+1:0])) then
  135.             stop("bad argument in field list; ",fld)
  136.          if upto('-',fld) then
  137.             {
  138.             if n < m then
  139.                n := 0
  140.             else
  141.                n := (n - m) + 1
  142.             }
  143.          }
  144.       else {
  145.          if not (m := integer(fld)) then
  146.             stop("bad argument in field list; ",fld)
  147.          n := 1
  148.          }
  149.       poslst |||:= [[m,n]]
  150.       }
  151.    return poslst
  152. end
  153.  
  154. # llu - lookup file name in output file list
  155. #
  156. procedure llu(str,lst)
  157.    local i
  158.    i := 1
  159.    while \lst[i] do
  160.       {
  161.       if \lst[i][1] == str then
  162.          return i
  163.       i +:= 1
  164.       }
  165. end
  166.  
  167. # str2lst - create a list from a delimited string
  168. #
  169. procedure str2lst(str,delim)
  170.    local lst, f
  171.    lst := []
  172.    str ? {
  173.       while f := (tab(upto(delim))) do
  174.       {
  175.       lst |||:= [f]
  176.       move(1)
  177.       }
  178.         if "" ~== (f := tab(0)) then
  179.         lst |||:= [f]
  180.         }
  181.    return lst
  182. end
  183.