Charles.Forsyth20060303a828770d19 years agoHistory
313 lines · 4.8 KB · Brainfuck
RawDownload
##	Miscellaneous routines.# Cmd.cmd1(op: int, l: ref Cmd): ref Cmd{	return ref Cmd(op, nil, l, nil, nil, nil, nil, 0);} Cmd.cmd2(op: int, l, r: ref Cmd): ref Cmd{	return ref Cmd(op, nil, l, r, nil, nil, nil, 0);} Cmd.cmd1i(op: int, l: ref Cmd, i: ref Item): ref Cmd{	return ref Cmd(op, nil, l, nil, i, nil, nil, 0);} Cmd.cmd1w(op: int, l: ref Cmd, w: list of ref Item): ref Cmd{	return ref Cmd(op, w, l, nil, nil, nil, nil, 0);} Cmd.cmde(c: self ref Cmd, op: int, l, r: ref Cmd): ref Cmd{	c.op = op;	c.left = l;	c.right = r;	return c;} Cmd.cmdiw(op: int, i: ref Item, w: list of ref Item): ref Cmd{	return ref Cmd(op, revitems(w), nil, nil, i, nil, nil, 0);} Pin, Pout:	con 1 << iota; rdmap := array[] of{	Rin => Pin,	Rout or Rappend => Pout,	Rinout => Pin | Pout,}; rdsymbs := array[] of{	Rin => "<",	Rout => ">",	Rappend => ">>",	Rinout => "<>",}; ionames := array[] of{	Pin => "input",	Pout => "ouput",	Pin | Pout => "input/output",}; ##	Check a pipeline for ambiguities.#Cmd.checkpipe(c: self ref Cmd, e: ref Env, f: int): int{	if (c.error)		return 0;	if (c.op == Cpipe) {		if (!c.left.checkpipe(e, f | Pout))			return 0;		if (!c.right.checkpipe(e, f | Pin))			return 0;	}	if (f) {		t := 0;		for (l := c.redirs; l != nil; l = tl l)			t |= rdmap[(hd l).op];		f &= t;		if (f) {			e.report(sys->sprint("%s redirection conflicts with pipe", ionames[f]));			return 0;		}	}	return 1;} ##	Update a command with another redirection.#Cmd.cmdio(c: self ref Cmd, e: ref Env, i: ref Item){	f := 0;	for (l := c.redirs; l != nil; l = tl l)		f |= rdmap[(hd l).op];	r := i.redir;	f &= rdmap[r.op];	if (f != 0) {		e.report(sys->sprint("repeat %s redirection", ionames[f]));		c.error = 1;	}	c.redirs = r :: c.redirs;} ##	Make a basic command.#Cmd.mkcmd(c: self ref Cmd, e: ref Env, async: int): ref Cmd{	if (!c.checkpipe(e, 0))		return nil;	if (async)		return ref Cmd(Casync, nil, c, nil, nil, nil, nil, 0);	else		return c;} ##	Rotate parse tree of cases.#Cmd.rotcases(c: self ref Cmd): ref Cmd{	l := c;	c = nil;	while (l != nil) {		t := l.right;		l.right = c;		c = l;		l = l.left;		c.left = t;	}	return c;} Item.item1(op: int, l: ref Item): ref Item{	return ref Item(op, nil, l, nil, nil, nil);} Item.item2(op: int, l, r: ref Item): ref Item{	return ref Item(op, nil, l, r, nil, nil);} Item.itemc(op: int, c: ref Cmd): ref Item{	return ref Item(op, nil, nil, nil, c, nil);} ##	Make an item from a list of strings.#Item.iteml(l: list of string): ref Item{	if (l != nil && tl l == nil)		return Item.itemw(hd l);	r: list of string;	while (l != nil) {		r = (hd l) :: r;		l = tl l;	}	c := ref Cmd;	c.op = Clist;	c.value = revstrs(r);	return Item.itemc(Iexpr, c);} Item.itemr(op: int, i: ref Item): ref Item{	return ref Item(Iredir, nil, nil, nil, nil, ref Redir(op, i));} qword:	Word = (nil, Wquoted, (0, nil)); Item.itemw(s: string): ref Item{	w := ref qword;	w.text = s;	return ref Item(Iword, w, nil, nil, nil, nil);} revitems(l: list of ref Item): list of ref Item{	r: list of ref Item;	while (l != nil) {		r = (hd l) :: r;		l = tl l;	}	return r;} revstrs(l: list of string): list of string{	r: list of string;	while (l != nil) {		r = (hd l) :: r;		l = tl l;	}	return r;} prepend(l: list of string, r: list of string): list of string{	while (r != nil) {		l = (hd r) :: l;		r = tl r;	}	return l;} concat(l: list of string): string{	s := hd l;	for (;;) {		l = tl l;		if (l == nil)			return s;		s += " ";		s += hd l;	}} ##	Make an item list, no redirections allowed.#Env.mklist(e: self ref Env, l: list of ref Item): list of ref Item{	r: list of ref Item;	while (l != nil) {		i := hd l;		if (i.op == Iredir)			e.report("redirection in list");		else			r = i :: r;		l = tl l;	}	return r;} ##	Make a simple command.#Env.mksimple(e: self ref Env, l: list of ref Item): ref Cmd{	r: list of ref Item;	c := ref Cmd;	c.op = Csimple;	c.error = 0;	while (l != nil) {		i := hd l;		if (i.op == Iredir)			c.cmdio(e, i);		else			r = i :: r;		l = tl l;	}	c.words = r;	return c;} Env.diag(e: self ref Env, s: string): string{	return where(e) + s;} Env.usage(e: self ref Env, s: string){	e.report("usage: " + s);} Env.report(e: self ref Env, s: string){	sys->fprint(e.stderr, "%s\n", e.diag(s));	if (e.flags & ERaise)		exits("error");} Env.error(e: self ref Env, s: string){	e.report(s);	cleanup();} panic(s: string){	raise "panic: " + s;} prprompt(n: int){	case n {	0 =>		sys->print("%s", prompt);	1 =>		sys->print("%s", contin);	}} Env.couldnot(e: self ref Env, what, who: string){	sys->fprint(e.stderr, "could not %s %s: %r\n", what, who);	exits("system error");} cleanup(){	exit;} exits(s: string){	raise "fail: mash " + s;}