summaryrefslogtreecommitdiff
path: root/appl/cmd/mash/dump.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/mash/dump.b')
-rw-r--r--appl/cmd/mash/dump.b199
1 files changed, 199 insertions, 0 deletions
diff --git a/appl/cmd/mash/dump.b b/appl/cmd/mash/dump.b
new file mode 100644
index 00000000..ed4b6309
--- /dev/null
+++ b/appl/cmd/mash/dump.b
@@ -0,0 +1,199 @@
+#
+# 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;
+}