summaryrefslogtreecommitdiffhomepage
path: root/shell/hush_doc.txt
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush_doc.txt')
-rw-r--r--shell/hush_doc.txt77
1 files changed, 77 insertions, 0 deletions
diff --git a/shell/hush_doc.txt b/shell/hush_doc.txt
index 973fe44c5..ec5dd00f2 100644
--- a/shell/hush_doc.txt
+++ b/shell/hush_doc.txt
@@ -1,3 +1,80 @@
+2008-07-14
+
+ Command parsing
+
+Command parsing results in "pipe" structures. "Pipe" structure
+does not always correspond to what sh language calls "pipe",
+it also controls execution of if, while, etc statements.
+
+struct pipe fields:
+ smallint res_word - "none" for normal commands,
+ "if" for if condition etc
+ struct child_prog progs[] - array of commands in pipe
+ smallint followup - how this pipe is related to next: is it
+ "pipe; pipe", "pipe & pipe" "pipe && pipe",
+ "pipe || pipe"?
+
+Blocks of commands { pipe; pipe; } and (pipe; pipe) are represented
+as one pipe struct with one progs[0] element which is a "group" -
+struct child_prog can contain a list of pipes. Sometimes these
+"groups" are created implicitly, e.g. every control
+statement (if, while, etc) sits inside its own "pipe" struct).
+
+res_word controls statement execution. Examples:
+
+"echo Hello" -
+pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
+pipe 1 res_word=NONE followup=1 SEQ
+
+"echo foo || echo bar" -
+pipe 0 res_word=NONE followup=OR prog[0] 'echo' 'foo'
+pipe 1 res_word=NONE followup=SEQ prog[0] 'echo' 'bar'
+pipe 2 res_word=NONE followup=SEQ
+
+"if true; then echo Hello; true; fi" -
+res_word=NONE followup=SEQ
+ prog 0 group {}:
+ pipe 0 res_word=IF followup=SEQ prog[0] 'true'
+ pipe 1 res_word=THEN followup=SEQ prog[0] 'echo' 'Hello'
+ pipe 2 res_word=THEN followup=SEQ prog[0] 'true'
+ pipe 3 res_word=FI followup=SEQ
+ pipe 4 res_word=NONE followup=(null)
+pipe 1 res_word=NONE followup=SEQ
+
+"if true; then { echo Hello; true; }; fi" -
+pipe 0 res_word=NONE followup=SEQ
+ prog 0 group {}:
+ pipe 0 res_word=IF followup=SEQ prog[0] 'true'
+ pipe 1 res_word=THEN followup=SEQ
+ prog 0 group {}:
+ pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
+ pipe 1 res_word=NONE followup=SEQ prog[0] 'true'
+ pipe 2 res_word=NONE followup=SEQ
+ pipe 2 res_word=NONE followup=(null)
+pipe 1 res_word=NONE followup=1 SEQ
+
+"for v in a b; do echo $v; true; done" -
+pipe 0 res_word=NONE followup=SEQ
+ prog 0 group {}:
+ pipe 0 res_word=FOR followup=SEQ prog[0] 'v'
+ pipe 1 res_word=IN followup=SEQ prog[0] 'a' 'b'
+ pipe 2 res_word=DO followup=SEQ prog[0] 'echo' '$v'
+ pipe 3 res_word=DO followup=SEQ prog[0] 'true'
+ pipe 4 res_word=DONE followup=SEQ
+ pipe 5 res_word=NONE followup=(null)
+pipe 1 res_word=NONE followup=SEQ
+
+Note how "THEN" and "DO" does not just mark the first pipe,
+it "sticks" to all pipes in the body. This is used when
+hush executes parsed pipes.
+
+Dummy trailing pipes with no commands are artifacts of imperfect
+parsing algorithm - done_pipe() appends new pipe struct beforehand
+and last one ends up empty and unused.
+
+
+2008-01
+
This is how hush runs commands:
/* callsite: process_command_subs */