|
|
1.1 root 1: # FSET(1)
2: #
3: # Perform set operations on file specifications
4: #
5: # Thomas R. Hicks
6: #
7: # Last modified 8/14/84
8: #
9:
10: procedure main(args)
11: local i, fyls, arglist
12: if not find("sets",&options) then
13: stop("Set extensions must be enabled to run this program.")
14: if *args = 0 then return
15: if *args > 1 then
16: every i := 2 to *args do
17: args[1] ||:= (" " || args[i])
18: (arglist := parse(args[1])) |
19: stop("Invalid file specification expression")
20: case type(arglist) of {
21: "string" : fyls := mkfset(arglist)
22: "list" : fyls := exec(arglist)
23: default : stop("Main: bad type -can't happen")
24: }
25: fyls := sort(fyls)
26: every write(!fyls," ")
27: end
28:
29: procedure Exp() # file spec expression parser
30: local a
31: suspend (a := [Factor(),=Op(),Factor()] & [a[2],a[1],a[3]]) |
32: Factor() |
33: (a := [="(",Exp(),=")"] & .a[2])
34: end
35:
36: procedure Factor() # file spec expression parser
37: local a
38: suspend (a := [Term(),=Op(),Term()] & [a[2],a[1],a[3]]) |
39: Term() |
40: (a := [="(",Factor(),=")"] & .a[2])
41: end
42:
43: procedure Name() # file spec name matcher
44: static valid
45: initial valid := ~'()'
46: suspend (any(~valid) || fail) | tab(find(Op()) | many(valid))
47: end
48:
49: procedure Non() # file spec expression parser
50: local a
51: suspend a := [Name(),=Op(),Name()] & [a[2],a[1],a[3]]
52: end
53:
54: procedure Op() # file spec operation matcher
55: suspend !["++","--","&&"]
56: end
57:
58: procedure Term() # file spec expression parser
59: local a
60: suspend (a := [="(",Non(),=")"] & .a[2]) |
61: Name()
62: end
63:
64: procedure bldfset(arg) # build file set, excluding . and ..
65: local line
66: static dotfiles
67: initial dotfiles := set([".",".."])
68: line := read(open("echo " || arg,"rp"))
69: return str2set(line,' ') -- dotfiles
70: end
71:
72: procedure exec(lst) # process file spec list recursively
73: return setops(lst[1])(exec2(lst[2]),exec2(lst[3]))
74: end
75:
76: procedure exec2(arg) # helping procedure for exec
77: case type(arg) of {
78: "string" : return mkfset(arg)
79: "list" : return exec(arg)
80: default : stop("exec2: can't happen")
81: }
82: end
83:
84: procedure mkfset(fspec) # make file list from specification
85: if fspec == "*" then
86: fspec := "* .*"
87: return bldfset(fspec)
88: end
89:
90: procedure parse(str) # top level of parsing procedures
91: local res
92: str ? (res := Exp() & pos(0)) | fail
93: return res
94: end
95:
96: procedure sdiff(f1,f2) # set difference
97: return f1 -- f2
98: end
99:
100: procedure setops(op) # return correct set operaton
101: case op of {
102: "++" : return sunion
103: "&&" : return sinter
104: "--" : return sdiff
105: }
106: end
107:
108: procedure sinter(f1,f2) # set intersection
109: return f1 ** f2
110: end
111:
112: procedure str2set(str,delim) # convert delimited string into a set
113: local fset, f
114: fset := set([])
115: str ? {
116: while f := (tab(upto(delim))) do {
117: insert(fset,f)
118: move(1)
119: }
120: if "" ~== (f := tab(0)) then
121: insert(fset,f)
122: }
123: return fset
124: end
125:
126: procedure sunion(f1,f2) # set union
127: return f1 ++ f2
128: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.