Bump to version 1.22.1
[platform/upstream/busybox.git] / shell / hush_doc.txt
1 2008-07-14
2
3         Command parsing
4
5 Command parsing results in a list of "pipe" structures.
6 This list correspond not only to usual "pipe1 || pipe2 && pipe3"
7 lists, but it also controls execution of if, while, etc statements.
8 Every such statement is a list for hush. List consists of pipes.
9
10 struct pipe fields:
11   smallint res_word - "none" for normal commands,
12                       "if" for if condition etc
13   struct child_prog progs[] - array of commands in pipe
14   smallint followup - how this pipe is related to next: is it
15                       "pipe; pipe", "pipe & pipe" "pipe && pipe",
16                       "pipe || pipe"?
17
18 Blocks of commands { pipe; pipe; } and (pipe; pipe) are represented
19 as one pipe struct with one progs[0] element which is a "group" -
20 struct child_prog can contain a list of pipes. Sometimes these
21 "groups" are created implicitly, e.g. every control
22 statement (if, while, etc) sits inside its own group.
23
24 res_word controls statement execution. Examples:
25
26 "echo Hello" -
27 pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
28 pipe 1 res_word=NONE followup=SEQ
29
30 "echo foo || echo bar" -
31 pipe 0 res_word=NONE followup=OR  prog[0] 'echo' 'foo'
32 pipe 1 res_word=NONE followup=SEQ prog[0] 'echo' 'bar'
33 pipe 2 res_word=NONE followup=SEQ
34
35 "if true; then echo Hello; true; fi" -
36 res_word=NONE followup=SEQ
37  prog 0 group {}:
38   pipe 0 res_word=IF followup=SEQ prog[0] 'true'
39   pipe 1 res_word=THEN followup=SEQ prog[0] 'echo' 'Hello'
40   pipe 2 res_word=THEN followup=SEQ prog[0] 'true'
41   pipe 3 res_word=FI followup=SEQ
42   pipe 4 res_word=NONE followup=(null)
43 pipe 1 res_word=NONE followup=SEQ
44
45 Above you see that if is a list, and it sits in a {} group
46 implicitly created by hush. Also note two THEN res_word's -
47 it is explained below.
48
49 "if true; then { echo Hello; true; }; fi" -
50 pipe 0 res_word=NONE followup=SEQ
51  prog 0 group {}:
52   pipe 0 res_word=IF followup=SEQ prog[0] 'true'
53   pipe 1 res_word=THEN followup=SEQ
54    prog 0 group {}:
55     pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
56     pipe 1 res_word=NONE followup=SEQ prog[0] 'true'
57     pipe 2 res_word=NONE followup=SEQ
58   pipe 2 res_word=NONE followup=(null)
59 pipe 1 res_word=NONE followup=SEQ
60
61 "for v in a b; do echo $v; true; done" -
62 pipe 0 res_word=NONE followup=SEQ
63  prog 0 group {}:
64   pipe 0 res_word=FOR followup=SEQ prog[0] 'v'
65   pipe 1 res_word=IN followup=SEQ prog[0] 'a' 'b'
66   pipe 2 res_word=DO followup=SEQ prog[0] 'echo' '$v'
67   pipe 3 res_word=DO followup=SEQ prog[0] 'true'
68   pipe 4 res_word=DONE followup=SEQ
69   pipe 5 res_word=NONE followup=(null)
70 pipe 1 res_word=NONE followup=SEQ
71
72 Note how "THEN" and "DO" does not just mark the first pipe,
73 it "sticks" to all pipes in the body. This is used when
74 hush executes parsed pipes.
75
76 Dummy trailing pipes with no commands are artifacts of imperfect
77 parsing algorithm - done_pipe() appends new pipe struct beforehand
78 and last one ends up empty and unused.
79
80 "for" and "case" statements (ab)use progs[] to keep their data
81 instead of argv vector progs[] usually do. "for" keyword is forcing
82 pipe termination after first word, which makes hush see
83 "for v in..." as "for v; in...". "case" keyword does the same.
84 Other judiciuosly placed hacks make hush see
85 "case word in a) cmd1;; b) cmd2;; esac" as if it was
86 "case word; match a; cmd; match b; cmd2; esac"
87 ("match" is a fictitious keyword here):
88
89 "case word in a) cmd1;; b) cmd2; esac" -
90 pipe 0 res_word=NONE followup=1 SEQ
91  prog 0 group {}:
92   pipe 0 res_word=CASE followup=SEQ prog[0] 'word'
93   pipe 1 res_word=MATCH followup=SEQ prog[0] 'a'
94   pipe 2 res_word=CASEI followup=SEQ prog[0] 'cmd1'
95   pipe 3 res_word=MATCH followup=SEQ prog[0] 'b'
96   pipe 4 res_word=CASEI followup=SEQ prog[0] 'cmd2'
97   pipe 5 res_word=CASEI followup=SEQ prog[0] 'cmd3'
98   pipe 6 res_word=ESAC followup=SEQ
99   pipe 7 res_word=NONE followup=(null)
100 pipe 1 res_word=NONE followup=SEQ
101
102
103 2008-01
104
105         Command execution
106
107 /* callsite: process_command_subs */
108 generate_stream_from_list(struct pipe *head) - handles `cmds`
109   create UNIX pipe
110   [v]fork
111   child:
112   redirect pipe output to stdout
113   _exit(run_list(head));   /* leaks memory */
114   parent:
115   return UNIX pipe's output fd
116   /* head is freed by the caller */
117
118 /* callsite: parse_and_run_stream */
119 run_and_free_list(struct pipe *)
120   run_list(struct pipe *)
121   free_pipe_list(struct pipe *)
122
123 /* callsites: generate_stream_from_list, run_and_free_list, pseudo_exec, run_pipe */
124 run_list(struct pipe *) - handles "cmd; cmd2 && cmd3", while/for/do loops
125   run_pipe - for every pipe in list
126
127 /* callsite: run_list */
128 run_pipe - runs "cmd1 | cmd2 | cmd3 [&]"
129   run_list - used if only one cmd and it is of the form "{cmds;}"
130   forks for every cmd if more than one cmd or if & is there
131   pseudo_exec - runs each "cmdN" (handles builtins etc)
132
133 /* callsite: run_pipe */
134 pseudo_exec - runs "cmd" (handles builtins etc)
135   exec - execs external programs
136   run_list - used if cmdN is "(cmds)" or "{cmds;}"
137   /* problem: putenv's malloced strings into environ -
138   ** with vfork they will leak into parent process
139   */
140   /* problem with ENABLE_FEATURE_SH_STANDALONE:
141   ** run_applet_no_and_exit(a, argv) uses exit - this can interfere
142   ** with vfork - switch to _exit there?
143   */