xref: /inferno-os/appl/cmd/mash/misc.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth#
2*37da2899SCharles.Forsyth#	Miscellaneous routines.
3*37da2899SCharles.Forsyth#
4*37da2899SCharles.Forsyth
5*37da2899SCharles.ForsythCmd.cmd1(op: int, l: ref Cmd): ref Cmd
6*37da2899SCharles.Forsyth{
7*37da2899SCharles.Forsyth	return ref Cmd(op, nil, l, nil, nil, nil, nil, 0);
8*37da2899SCharles.Forsyth}
9*37da2899SCharles.Forsyth
10*37da2899SCharles.ForsythCmd.cmd2(op: int, l, r: ref Cmd): ref Cmd
11*37da2899SCharles.Forsyth{
12*37da2899SCharles.Forsyth	return ref Cmd(op, nil, l, r, nil, nil, nil, 0);
13*37da2899SCharles.Forsyth}
14*37da2899SCharles.Forsyth
15*37da2899SCharles.ForsythCmd.cmd1i(op: int, l: ref Cmd, i: ref Item): ref Cmd
16*37da2899SCharles.Forsyth{
17*37da2899SCharles.Forsyth	return ref Cmd(op, nil, l, nil, i, nil, nil, 0);
18*37da2899SCharles.Forsyth}
19*37da2899SCharles.Forsyth
20*37da2899SCharles.ForsythCmd.cmd1w(op: int, l: ref Cmd, w: list of ref Item): ref Cmd
21*37da2899SCharles.Forsyth{
22*37da2899SCharles.Forsyth	return ref Cmd(op, w, l, nil, nil, nil, nil, 0);
23*37da2899SCharles.Forsyth}
24*37da2899SCharles.Forsyth
25*37da2899SCharles.ForsythCmd.cmde(c: self ref Cmd, op: int, l, r: ref Cmd): ref Cmd
26*37da2899SCharles.Forsyth{
27*37da2899SCharles.Forsyth	c.op = op;
28*37da2899SCharles.Forsyth	c.left = l;
29*37da2899SCharles.Forsyth	c.right = r;
30*37da2899SCharles.Forsyth	return c;
31*37da2899SCharles.Forsyth}
32*37da2899SCharles.Forsyth
33*37da2899SCharles.ForsythCmd.cmdiw(op: int, i: ref Item, w: list of ref Item): ref Cmd
34*37da2899SCharles.Forsyth{
35*37da2899SCharles.Forsyth	return ref Cmd(op, revitems(w), nil, nil, i, nil, nil, 0);
36*37da2899SCharles.Forsyth}
37*37da2899SCharles.Forsyth
38*37da2899SCharles.ForsythPin, Pout:	con 1 << iota;
39*37da2899SCharles.Forsyth
40*37da2899SCharles.Forsythrdmap := array[] of
41*37da2899SCharles.Forsyth{
42*37da2899SCharles.Forsyth	Rin => Pin,
43*37da2899SCharles.Forsyth	Rout or Rappend => Pout,
44*37da2899SCharles.Forsyth	Rinout => Pin | Pout,
45*37da2899SCharles.Forsyth};
46*37da2899SCharles.Forsyth
47*37da2899SCharles.Forsythrdsymbs := array[] of
48*37da2899SCharles.Forsyth{
49*37da2899SCharles.Forsyth	Rin => "<",
50*37da2899SCharles.Forsyth	Rout => ">",
51*37da2899SCharles.Forsyth	Rappend => ">>",
52*37da2899SCharles.Forsyth	Rinout => "<>",
53*37da2899SCharles.Forsyth};
54*37da2899SCharles.Forsyth
55*37da2899SCharles.Forsythionames := array[] of
56*37da2899SCharles.Forsyth{
57*37da2899SCharles.Forsyth	Pin => "input",
58*37da2899SCharles.Forsyth	Pout => "ouput",
59*37da2899SCharles.Forsyth	Pin | Pout => "input/output",
60*37da2899SCharles.Forsyth};
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsyth#
63*37da2899SCharles.Forsyth#	Check a pipeline for ambiguities.
64*37da2899SCharles.Forsyth#
65*37da2899SCharles.ForsythCmd.checkpipe(c: self ref Cmd, e: ref Env, f: int): int
66*37da2899SCharles.Forsyth{
67*37da2899SCharles.Forsyth	if (c.error)
68*37da2899SCharles.Forsyth		return 0;
69*37da2899SCharles.Forsyth	if (c.op == Cpipe) {
70*37da2899SCharles.Forsyth		if (!c.left.checkpipe(e, f | Pout))
71*37da2899SCharles.Forsyth			return 0;
72*37da2899SCharles.Forsyth		if (!c.right.checkpipe(e, f | Pin))
73*37da2899SCharles.Forsyth			return 0;
74*37da2899SCharles.Forsyth	}
75*37da2899SCharles.Forsyth	if (f) {
76*37da2899SCharles.Forsyth		t := 0;
77*37da2899SCharles.Forsyth		for (l := c.redirs; l != nil; l = tl l)
78*37da2899SCharles.Forsyth			t |= rdmap[(hd l).op];
79*37da2899SCharles.Forsyth		f &= t;
80*37da2899SCharles.Forsyth		if (f) {
81*37da2899SCharles.Forsyth			e.report(sys->sprint("%s redirection conflicts with pipe", ionames[f]));
82*37da2899SCharles.Forsyth			return 0;
83*37da2899SCharles.Forsyth		}
84*37da2899SCharles.Forsyth	}
85*37da2899SCharles.Forsyth	return 1;
86*37da2899SCharles.Forsyth}
87*37da2899SCharles.Forsyth
88*37da2899SCharles.Forsyth#
89*37da2899SCharles.Forsyth#	Update a command with another redirection.
90*37da2899SCharles.Forsyth#
91*37da2899SCharles.ForsythCmd.cmdio(c: self ref Cmd, e: ref Env, i: ref Item)
92*37da2899SCharles.Forsyth{
93*37da2899SCharles.Forsyth	f := 0;
94*37da2899SCharles.Forsyth	for (l := c.redirs; l != nil; l = tl l)
95*37da2899SCharles.Forsyth		f |= rdmap[(hd l).op];
96*37da2899SCharles.Forsyth	r := i.redir;
97*37da2899SCharles.Forsyth	f &= rdmap[r.op];
98*37da2899SCharles.Forsyth	if (f != 0) {
99*37da2899SCharles.Forsyth		e.report(sys->sprint("repeat %s redirection", ionames[f]));
100*37da2899SCharles.Forsyth		c.error = 1;
101*37da2899SCharles.Forsyth	}
102*37da2899SCharles.Forsyth	c.redirs = r :: c.redirs;
103*37da2899SCharles.Forsyth}
104*37da2899SCharles.Forsyth
105*37da2899SCharles.Forsyth#
106*37da2899SCharles.Forsyth#	Make a basic command.
107*37da2899SCharles.Forsyth#
108*37da2899SCharles.ForsythCmd.mkcmd(c: self ref Cmd, e: ref Env, async: int): ref Cmd
109*37da2899SCharles.Forsyth{
110*37da2899SCharles.Forsyth	if (!c.checkpipe(e, 0))
111*37da2899SCharles.Forsyth		return nil;
112*37da2899SCharles.Forsyth	if (async)
113*37da2899SCharles.Forsyth		return ref Cmd(Casync, nil, c, nil, nil, nil, nil, 0);
114*37da2899SCharles.Forsyth	else
115*37da2899SCharles.Forsyth		return c;
116*37da2899SCharles.Forsyth}
117*37da2899SCharles.Forsyth
118*37da2899SCharles.Forsyth#
119*37da2899SCharles.Forsyth#	Rotate parse tree of cases.
120*37da2899SCharles.Forsyth#
121*37da2899SCharles.ForsythCmd.rotcases(c: self ref Cmd): ref Cmd
122*37da2899SCharles.Forsyth{
123*37da2899SCharles.Forsyth	l := c;
124*37da2899SCharles.Forsyth	c = nil;
125*37da2899SCharles.Forsyth	while (l != nil) {
126*37da2899SCharles.Forsyth		t := l.right;
127*37da2899SCharles.Forsyth		l.right = c;
128*37da2899SCharles.Forsyth		c = l;
129*37da2899SCharles.Forsyth		l = l.left;
130*37da2899SCharles.Forsyth		c.left = t;
131*37da2899SCharles.Forsyth	}
132*37da2899SCharles.Forsyth	return c;
133*37da2899SCharles.Forsyth}
134*37da2899SCharles.Forsyth
135*37da2899SCharles.ForsythItem.item1(op: int, l: ref Item): ref Item
136*37da2899SCharles.Forsyth{
137*37da2899SCharles.Forsyth	return ref Item(op, nil, l, nil, nil, nil);
138*37da2899SCharles.Forsyth}
139*37da2899SCharles.Forsyth
140*37da2899SCharles.ForsythItem.item2(op: int, l, r: ref Item): ref Item
141*37da2899SCharles.Forsyth{
142*37da2899SCharles.Forsyth	return ref Item(op, nil, l, r, nil, nil);
143*37da2899SCharles.Forsyth}
144*37da2899SCharles.Forsyth
145*37da2899SCharles.ForsythItem.itemc(op: int, c: ref Cmd): ref Item
146*37da2899SCharles.Forsyth{
147*37da2899SCharles.Forsyth	return ref Item(op, nil, nil, nil, c, nil);
148*37da2899SCharles.Forsyth}
149*37da2899SCharles.Forsyth
150*37da2899SCharles.Forsyth#
151*37da2899SCharles.Forsyth#	Make an item from a list of strings.
152*37da2899SCharles.Forsyth#
153*37da2899SCharles.ForsythItem.iteml(l: list of string): ref Item
154*37da2899SCharles.Forsyth{
155*37da2899SCharles.Forsyth	if (l != nil && tl l == nil)
156*37da2899SCharles.Forsyth		return Item.itemw(hd l);
157*37da2899SCharles.Forsyth	r: list of string;
158*37da2899SCharles.Forsyth	while (l != nil) {
159*37da2899SCharles.Forsyth		r = (hd l) :: r;
160*37da2899SCharles.Forsyth		l = tl l;
161*37da2899SCharles.Forsyth	}
162*37da2899SCharles.Forsyth	c := ref Cmd;
163*37da2899SCharles.Forsyth	c.op = Clist;
164*37da2899SCharles.Forsyth	c.value = revstrs(r);
165*37da2899SCharles.Forsyth	return Item.itemc(Iexpr, c);
166*37da2899SCharles.Forsyth}
167*37da2899SCharles.Forsyth
168*37da2899SCharles.ForsythItem.itemr(op: int, i: ref Item): ref Item
169*37da2899SCharles.Forsyth{
170*37da2899SCharles.Forsyth	return ref Item(Iredir, nil, nil, nil, nil, ref Redir(op, i));
171*37da2899SCharles.Forsyth}
172*37da2899SCharles.Forsyth
173*37da2899SCharles.Forsythqword:	Word = (nil, Wquoted, (0, nil));
174*37da2899SCharles.Forsyth
175*37da2899SCharles.ForsythItem.itemw(s: string): ref Item
176*37da2899SCharles.Forsyth{
177*37da2899SCharles.Forsyth	w := ref qword;
178*37da2899SCharles.Forsyth	w.text = s;
179*37da2899SCharles.Forsyth	return ref Item(Iword, w, nil, nil, nil, nil);
180*37da2899SCharles.Forsyth}
181*37da2899SCharles.Forsyth
182*37da2899SCharles.Forsythrevitems(l: list of ref Item): list of ref Item
183*37da2899SCharles.Forsyth{
184*37da2899SCharles.Forsyth	r: list of ref Item;
185*37da2899SCharles.Forsyth	while (l != nil) {
186*37da2899SCharles.Forsyth		r = (hd l) :: r;
187*37da2899SCharles.Forsyth		l = tl l;
188*37da2899SCharles.Forsyth	}
189*37da2899SCharles.Forsyth	return r;
190*37da2899SCharles.Forsyth}
191*37da2899SCharles.Forsyth
192*37da2899SCharles.Forsythrevstrs(l: list of string): list of string
193*37da2899SCharles.Forsyth{
194*37da2899SCharles.Forsyth	r: list of string;
195*37da2899SCharles.Forsyth	while (l != nil) {
196*37da2899SCharles.Forsyth		r = (hd l) :: r;
197*37da2899SCharles.Forsyth		l = tl l;
198*37da2899SCharles.Forsyth	}
199*37da2899SCharles.Forsyth	return r;
200*37da2899SCharles.Forsyth}
201*37da2899SCharles.Forsyth
202*37da2899SCharles.Forsythprepend(l: list of string, r: list of string): list of string
203*37da2899SCharles.Forsyth{
204*37da2899SCharles.Forsyth	while (r != nil) {
205*37da2899SCharles.Forsyth		l = (hd r) :: l;
206*37da2899SCharles.Forsyth		r = tl r;
207*37da2899SCharles.Forsyth	}
208*37da2899SCharles.Forsyth	return l;
209*37da2899SCharles.Forsyth}
210*37da2899SCharles.Forsyth
211*37da2899SCharles.Forsythconcat(l: list of string): string
212*37da2899SCharles.Forsyth{
213*37da2899SCharles.Forsyth	s := hd l;
214*37da2899SCharles.Forsyth	for (;;) {
215*37da2899SCharles.Forsyth		l = tl l;
216*37da2899SCharles.Forsyth		if (l == nil)
217*37da2899SCharles.Forsyth			return s;
218*37da2899SCharles.Forsyth		s += " ";
219*37da2899SCharles.Forsyth		s += hd l;
220*37da2899SCharles.Forsyth	}
221*37da2899SCharles.Forsyth}
222*37da2899SCharles.Forsyth
223*37da2899SCharles.Forsyth#
224*37da2899SCharles.Forsyth#	Make an item list, no redirections allowed.
225*37da2899SCharles.Forsyth#
226*37da2899SCharles.ForsythEnv.mklist(e: self ref Env, l: list of ref Item): list of ref Item
227*37da2899SCharles.Forsyth{
228*37da2899SCharles.Forsyth	r: list of ref Item;
229*37da2899SCharles.Forsyth	while (l != nil) {
230*37da2899SCharles.Forsyth		i := hd l;
231*37da2899SCharles.Forsyth		if (i.op == Iredir)
232*37da2899SCharles.Forsyth			e.report("redirection in list");
233*37da2899SCharles.Forsyth		else
234*37da2899SCharles.Forsyth			r = i :: r;
235*37da2899SCharles.Forsyth		l = tl l;
236*37da2899SCharles.Forsyth	}
237*37da2899SCharles.Forsyth	return r;
238*37da2899SCharles.Forsyth}
239*37da2899SCharles.Forsyth
240*37da2899SCharles.Forsyth#
241*37da2899SCharles.Forsyth#	Make a simple command.
242*37da2899SCharles.Forsyth#
243*37da2899SCharles.ForsythEnv.mksimple(e: self ref Env, l: list of ref Item): ref Cmd
244*37da2899SCharles.Forsyth{
245*37da2899SCharles.Forsyth	r: list of ref Item;
246*37da2899SCharles.Forsyth	c := ref Cmd;
247*37da2899SCharles.Forsyth	c.op = Csimple;
248*37da2899SCharles.Forsyth	c.error = 0;
249*37da2899SCharles.Forsyth	while (l != nil) {
250*37da2899SCharles.Forsyth		i := hd l;
251*37da2899SCharles.Forsyth		if (i.op == Iredir)
252*37da2899SCharles.Forsyth			c.cmdio(e, i);
253*37da2899SCharles.Forsyth		else
254*37da2899SCharles.Forsyth			r = i :: r;
255*37da2899SCharles.Forsyth		l = tl l;
256*37da2899SCharles.Forsyth	}
257*37da2899SCharles.Forsyth	c.words = r;
258*37da2899SCharles.Forsyth	return c;
259*37da2899SCharles.Forsyth}
260*37da2899SCharles.Forsyth
261*37da2899SCharles.ForsythEnv.diag(e: self ref Env, s: string): string
262*37da2899SCharles.Forsyth{
263*37da2899SCharles.Forsyth	return where(e) + s;
264*37da2899SCharles.Forsyth}
265*37da2899SCharles.Forsyth
266*37da2899SCharles.ForsythEnv.usage(e: self ref Env, s: string)
267*37da2899SCharles.Forsyth{
268*37da2899SCharles.Forsyth	e.report("usage: " + s);
269*37da2899SCharles.Forsyth}
270*37da2899SCharles.Forsyth
271*37da2899SCharles.ForsythEnv.report(e: self ref Env, s: string)
272*37da2899SCharles.Forsyth{
273*37da2899SCharles.Forsyth	sys->fprint(e.stderr, "%s\n", e.diag(s));
274*37da2899SCharles.Forsyth	if (e.flags & ERaise)
275*37da2899SCharles.Forsyth		exits("error");
276*37da2899SCharles.Forsyth}
277*37da2899SCharles.Forsyth
278*37da2899SCharles.ForsythEnv.error(e: self ref Env, s: string)
279*37da2899SCharles.Forsyth{
280*37da2899SCharles.Forsyth	e.report(s);
281*37da2899SCharles.Forsyth	cleanup();
282*37da2899SCharles.Forsyth}
283*37da2899SCharles.Forsyth
284*37da2899SCharles.Forsythpanic(s: string)
285*37da2899SCharles.Forsyth{
286*37da2899SCharles.Forsyth	raise "panic: " + s;
287*37da2899SCharles.Forsyth}
288*37da2899SCharles.Forsyth
289*37da2899SCharles.Forsythprprompt(n: int)
290*37da2899SCharles.Forsyth{
291*37da2899SCharles.Forsyth	case n {
292*37da2899SCharles.Forsyth	0 =>
293*37da2899SCharles.Forsyth		sys->print("%s", prompt);
294*37da2899SCharles.Forsyth	1 =>
295*37da2899SCharles.Forsyth		sys->print("%s", contin);
296*37da2899SCharles.Forsyth	}
297*37da2899SCharles.Forsyth}
298*37da2899SCharles.Forsyth
299*37da2899SCharles.ForsythEnv.couldnot(e: self ref Env, what, who: string)
300*37da2899SCharles.Forsyth{
301*37da2899SCharles.Forsyth	sys->fprint(e.stderr, "could not %s %s: %r\n", what, who);
302*37da2899SCharles.Forsyth	exits("system error");
303*37da2899SCharles.Forsyth}
304*37da2899SCharles.Forsyth
305*37da2899SCharles.Forsythcleanup()
306*37da2899SCharles.Forsyth{
307*37da2899SCharles.Forsyth	exit;
308*37da2899SCharles.Forsyth}
309*37da2899SCharles.Forsyth
310*37da2899SCharles.Forsythexits(s: string)
311*37da2899SCharles.Forsyth{
312*37da2899SCharles.Forsyth	raise "fail: mash " + s;
313*37da2899SCharles.Forsyth}
314