|
|
BSD 4.3
# FSET(1)
#
# Perform set operations on file specifications
#
# Thomas R. Hicks
#
# Last modified 8/14/84
#
procedure main(args)
local i, fyls, arglist
if not find("sets",&options) then
stop("Set extensions must be enabled to run this program.")
if *args = 0 then return
if *args > 1 then
every i := 2 to *args do
args[1] ||:= (" " || args[i])
(arglist := parse(args[1])) |
stop("Invalid file specification expression")
case type(arglist) of {
"string" : fyls := mkfset(arglist)
"list" : fyls := exec(arglist)
default : stop("Main: bad type -can't happen")
}
fyls := sort(fyls)
every write(!fyls," ")
end
procedure Exp() # file spec expression parser
local a
suspend (a := [Factor(),=Op(),Factor()] & [a[2],a[1],a[3]]) |
Factor() |
(a := [="(",Exp(),=")"] & .a[2])
end
procedure Factor() # file spec expression parser
local a
suspend (a := [Term(),=Op(),Term()] & [a[2],a[1],a[3]]) |
Term() |
(a := [="(",Factor(),=")"] & .a[2])
end
procedure Name() # file spec name matcher
static valid
initial valid := ~'()'
suspend (any(~valid) || fail) | tab(find(Op()) | many(valid))
end
procedure Non() # file spec expression parser
local a
suspend a := [Name(),=Op(),Name()] & [a[2],a[1],a[3]]
end
procedure Op() # file spec operation matcher
suspend !["++","--","&&"]
end
procedure Term() # file spec expression parser
local a
suspend (a := [="(",Non(),=")"] & .a[2]) |
Name()
end
procedure bldfset(arg) # build file set, excluding . and ..
local line
static dotfiles
initial dotfiles := set([".",".."])
line := read(open("echo " || arg,"rp"))
return str2set(line,' ') -- dotfiles
end
procedure exec(lst) # process file spec list recursively
return setops(lst[1])(exec2(lst[2]),exec2(lst[3]))
end
procedure exec2(arg) # helping procedure for exec
case type(arg) of {
"string" : return mkfset(arg)
"list" : return exec(arg)
default : stop("exec2: can't happen")
}
end
procedure mkfset(fspec) # make file list from specification
if fspec == "*" then
fspec := "* .*"
return bldfset(fspec)
end
procedure parse(str) # top level of parsing procedures
local res
str ? (res := Exp() & pos(0)) | fail
return res
end
procedure sdiff(f1,f2) # set difference
return f1 -- f2
end
procedure setops(op) # return correct set operaton
case op of {
"++" : return sunion
"&&" : return sinter
"--" : return sdiff
}
end
procedure sinter(f1,f2) # set intersection
return f1 ** f2
end
procedure str2set(str,delim) # convert delimited string into a set
local fset, f
fset := set([])
str ? {
while f := (tab(upto(delim))) do {
insert(fset,f)
move(1)
}
if "" ~== (f := tab(0)) then
insert(fset,f)
}
return fset
end
procedure sunion(f1,f2) # set union
return f1 ++ f2
end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.