4.3BSD/usr/contrib/icon/src/cmd/delam.icn

#	DELAM(1)
#
#	Delaminate file using field list
#
#	Thomas R. Hicks
#
#	Last modified 7/10/83
#

procedure main(a)
   local inpt, fylist, ranges
   if (not a[1]) | a[1] == "?" then
      Usage()
   else if any('0123456789',a[1]) then
      ranges := fldecode(a[1])
   else
      {
      write(&errout,"Bad argument to delam: ",a[1])
      Usage()
      }
   if not a[2] then
      Usage()
   else if (match("-",a[2])) then
      inpt := &input
       else if not (inpt := open(a[2])) then
         stop("Cannot open ",a[2])
   fylist := doutfyls(a,3)
   if *fylist ~= *ranges then
      stop("Unequal number of field args and output files")
   delamr(inpt,ranges,fylist)
end

# Usage - write usage message
#
procedure Usage()
   stop("Usage: delam fieldlist {infile | -} {outputfile | -}...")
end

# delamr - do actual division of input file
#
procedure delamr(ifd,ranges,fylist)
   local i, j, k, line
   while line := read(ifd) do
      {
      i := 1
      while i <= *fylist do
         {
         j := ranges[i][1]
         k := ranges[i][2]
         if k > 0 then
            write(fylist[i][2],line[j+:k] | line[j:0] | "")
         i +:= 1
         }
      }
end

# doutfyls - process the output file arguments; return list
#
procedure doutfyls(a,i)
   local lst, x
   lst := []
   while \a[i] do
      {
      if x := llu(a[i],lst) then		# already in list
         lst |||:= [[a[i],lst[x][2]]]
      else					# not in list
         if a[i] == "-" then			# standard out
            lst |||:= [[a[i],&output]]
         else					# new file
            if not (x := open(a[i],"w")) then
               stop("Cannot open ",a[i]," for output")
            else
               lst |||:= [[a[i],x]]
      i +:= 1
      }
   return lst

end

# fldecode - decode the fieldlist argument
#
procedure fldecode(fldlst)
   local fld, flst, poslst, m, n, x
   poslst := []
   flst := str2lst(fldlst,':,;')
   every fld := !flst do
      {
      if x := upto('-+',fld) then
         {
         if not (m := integer(fld[1:x])) then
            stop("bad argument in field list; ",fld)
         if not (n := integer(fld[x+1:0])) then
            stop("bad argument in field list; ",fld)
         if upto('-',fld) then
            {
            if n < m then
               n := 0
            else
               n := (n - m) + 1
            }
         }
      else {
         if not (m := integer(fld)) then
            stop("bad argument in field list; ",fld)
         n := 1
         }
      poslst |||:= [[m,n]]
      }
   return poslst
end

# llu - lookup file name in output file list
#
procedure llu(str,lst)
   local i
   i := 1
   while \lst[i] do
      {
      if \lst[i][1] == str then
         return i
      i +:= 1
      }
end

# str2lst - create a list from a delimited string
#
procedure str2lst(str,delim)
   local lst, f
   lst := []
   str ? {
      while f := (tab(upto(delim))) do
      {
      lst |||:= [f]
      move(1)
      }
        if "" ~== (f := tab(0)) then
        lst |||:= [f]
        }
   return lst
end