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