code: 9ferno

ref: 6bfe4cf8107de7a01ff8a0667db7f28f08e4d238
dir: /appl/cmd/mash/dump.b/

View raw version
#
#	Output routines.
#

#
#	Echo list of strings.
#
echo(e: ref Env, s: list of string)
{
	out := e.outfile();
	if (out == nil)
		return;
	out.putc('+');
	for (t := s; t != nil; t = tl t) {
		out.putc(' ');
		out.puts(hd t);
	}
	out.putc('\n');
	out.close();
}

#
#	Return text representation of Word/Item/Cmd.
#

Word.word(w: self ref Word, d: string): string
{
	if (w == nil)
		return nil;
	if (d != nil)
		return d + w.text;
	if (w.flags & Wquoted)
		return enquote(w.text);
	return w.text;
}

Item.text(i: self ref Item): string
{
	if (i == nil)
		return nil;
	case i.op {
	Icaret =>
		return i.left.text() + " ^ " + i.right.text();
	Iicaret =>
		return i.left.text() + i.right.text();
	Idollarq =>
		return i.word.word("$\"");
	Idollar or Imatch =>
		return i.word.word("$");
	Iword =>
		return i.word.word(nil);
	Iexpr =>
		return "(" + i.cmd.text() + ")";
	Ibackq =>
		return "`" + group(i.cmd);
	Iquote =>
		return "\"" + group(i.cmd);
	Iinpipe =>
		return "<" + group(i.cmd);
	Ioutpipe =>
		return ">" + group(i.cmd);
	* =>
		return "?" + string i.op;
	}
}

words(l: list of ref Item): string
{
	s: string;
	while (l != nil) {
		if (s == nil)
			s = (hd l).text();
		else
			s = s + " " + (hd l).text();
		l = tl l;
	}
	return s;
}

redir(s: string, c: ref Cmd): string
{
	if (c == nil)
		return s;
	for (l := c.redirs; l != nil; l = tl l) {
		r := hd l;
		s = s + " " + rdsymbs[r.op] + " " + r.word.text();
	}
	return s;
}

cmd2in(c: ref Cmd, s: string): string
{
	return c.left.text() + " " + s + " " + c.right.text();
}

group(c: ref Cmd): string
{
	if (c == nil)
		return "{ }";
	return redir("{ " + c.text() + " }", c);
}

sequence(c: ref Cmd): string
{
	s: string;
	do {
		r := c.right;
		t := ";";
		if (r.op == Casync) {
			r = r.left;
			t = "&";
		}
		if (s == nil)
			s = r.text() + t;
		else
			s = r.text() + t + " " + s;
		c = c.left;
	} while (c != nil);
	return s;
}

Cmd.text(c: self ref Cmd): string
{
	if (c == nil)
		return nil;
	case c.op {
	Csimple =>
		return redir(words(c.words), c);
	Cseq =>
		return sequence(c);
	Cfor =>
		return "for (" + c.item.text() + " in " + words(c.words) + ") " + c.left.text();
	Cif =>
		return "if (" + c.left.text() +") " + c.right.text();
	Celse =>
		return c.left.text() +" else " + c.right.text();
	Cwhile =>
		return "while (" + c.left.text() +") " + c.right.text();
	Ccase =>
		return redir("case " + c.left.text() + " { " + c.right.text() + "}", c);
	Ccases =>
		s := c.left.text();
		if (s[len s - 1] != '&')
			return s + "; " + c.right.text();
		return s + " " + c.right.text();
	Cmatched =>
		return cmd2in(c, "=>");
	Cdefeq =>
		return c.item.text() + " := " + words(c.words);
	Ceq =>
		return c.item.text() + " = " + words(c.words);
	Cfn =>
		return "fn " + c.item.text() + " " + group(c.left);
	Crescue =>
		return "rescue " + c.item.text() + " " + group(c.left);
	Casync =>
		return c.left.text() + "&";
	Cgroup =>
		return group(c.left);
	Clistgroup =>
		return ":" + group(c.left);
	Csubgroup =>
		return "@" + group(c.left);
	Cnop =>
		return nil;
	Cword =>
		return c.item.text();
	Ccaret =>
		return cmd2in(c, "^");
	Chd =>
		return "hd " + c.left.text();
	Clen =>
		return "len " + c.left.text();
	Cnot =>
		return "!" + c.left.text();
	Ctl =>
		return "tl " + c.left.text();
	Ccons =>
		return cmd2in(c, "::");
	Ceqeq =>
		return cmd2in(c, "==");
	Cnoteq =>
		return cmd2in(c, "!=");
	Cmatch =>
		return cmd2in(c, "~");
	Cpipe =>
		return cmd2in(c, "|");
	Cdepend =>
		return words(c.words) + " : " + words(c.left.words) + " " + c.left.text();
	Crule =>
		return c.item.text() + " :~ " + c.left.item.text() + " " + c.left.text();
	* =>
		if (c.op >= Cprivate)
			return "Priv+" + string (c.op - Cprivate);
		else
			return "?" + string c.op;
	}
	return nil;
}