|
1 /* |
|
2 * text.c - textual representations of syntax trees |
|
3 * |
|
4 * This file is part of zsh, the Z shell. |
|
5 * |
|
6 * Copyright (c) 1992-1997 Paul Falstad |
|
7 * All rights reserved. |
|
8 * |
|
9 * Permission is hereby granted, without written agreement and without |
|
10 * license or royalty fees, to use, copy, modify, and distribute this |
|
11 * software and to distribute modified versions of this software for any |
|
12 * purpose, provided that the above copyright notice and the following |
|
13 * two paragraphs appear in all copies of this software. |
|
14 * |
|
15 * In no event shall Paul Falstad or the Zsh Development Group be liable |
|
16 * to any party for direct, indirect, special, incidental, or consequential |
|
17 * damages arising out of the use of this software and its documentation, |
|
18 * even if Paul Falstad and the Zsh Development Group have been advised of |
|
19 * the possibility of such damage. |
|
20 * |
|
21 * Paul Falstad and the Zsh Development Group specifically disclaim any |
|
22 * warranties, including, but not limited to, the implied warranties of |
|
23 * merchantability and fitness for a particular purpose. The software |
|
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the |
|
25 * Zsh Development Group have no obligation to provide maintenance, |
|
26 * support, updates, enhancements, or modifications. |
|
27 * |
|
28 */ |
|
29 |
|
30 #include "zsh.mdh" |
|
31 #include "text.pro" |
|
32 |
|
33 static char *tptr, *tbuf, *tlim; |
|
34 static int tsiz, tindent, tnewlins, tjob; |
|
35 |
|
36 /* add a character to the text buffer */ |
|
37 |
|
38 /**/ |
|
39 static void |
|
40 taddchr(int c) |
|
41 { |
|
42 *tptr++ = c; |
|
43 if (tptr == tlim) { |
|
44 if (!tbuf) { |
|
45 tptr--; |
|
46 return; |
|
47 } |
|
48 tbuf = realloc(tbuf, tsiz *= 2); |
|
49 tlim = tbuf + tsiz; |
|
50 tptr = tbuf + tsiz / 2; |
|
51 } |
|
52 } |
|
53 |
|
54 /* add a string to the text buffer */ |
|
55 |
|
56 /**/ |
|
57 static void |
|
58 taddstr(char *s) |
|
59 { |
|
60 int sl = strlen(s); |
|
61 char c; |
|
62 |
|
63 while (tptr + sl >= tlim) { |
|
64 int x = tptr - tbuf; |
|
65 |
|
66 if (!tbuf) |
|
67 return; |
|
68 tbuf = realloc(tbuf, tsiz *= 2); |
|
69 tlim = tbuf + tsiz; |
|
70 tptr = tbuf + x; |
|
71 } |
|
72 if (tnewlins) { |
|
73 memcpy(tptr, s, sl); |
|
74 tptr += sl; |
|
75 } else |
|
76 while ((c = *s++)) |
|
77 *tptr++ = (c == '\n' ? ' ' : c); |
|
78 } |
|
79 |
|
80 /**/ |
|
81 static void |
|
82 taddlist(Estate state, int num) |
|
83 { |
|
84 if (num) { |
|
85 while (num--) { |
|
86 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
87 taddchr(' '); |
|
88 } |
|
89 tptr--; |
|
90 } |
|
91 } |
|
92 |
|
93 /* add a newline, or something equivalent, to the text buffer */ |
|
94 |
|
95 /**/ |
|
96 static void |
|
97 taddnl(void) |
|
98 { |
|
99 int t0; |
|
100 |
|
101 if (tnewlins) { |
|
102 taddchr('\n'); |
|
103 for (t0 = 0; t0 != tindent; t0++) |
|
104 taddchr('\t'); |
|
105 } else |
|
106 taddstr("; "); |
|
107 } |
|
108 |
|
109 /* get a permanent textual representation of n */ |
|
110 |
|
111 /**/ |
|
112 mod_export char * |
|
113 getpermtext(Eprog prog, Wordcode c) |
|
114 { |
|
115 struct estate s; |
|
116 |
|
117 if (!c) |
|
118 c = prog->prog; |
|
119 |
|
120 useeprog(prog); /* mark as used */ |
|
121 |
|
122 s.prog = prog; |
|
123 s.pc = c; |
|
124 s.strs = prog->strs; |
|
125 |
|
126 tnewlins = 1; |
|
127 tbuf = (char *)zalloc(tsiz = 32); |
|
128 tptr = tbuf; |
|
129 tlim = tbuf + tsiz; |
|
130 tindent = 1; |
|
131 tjob = 0; |
|
132 if (prog->len) |
|
133 gettext2(&s); |
|
134 *tptr = '\0'; |
|
135 freeeprog(prog); /* mark as unused */ |
|
136 untokenize(tbuf); |
|
137 return tbuf; |
|
138 } |
|
139 |
|
140 /* get a representation of n in a job text buffer */ |
|
141 |
|
142 /**/ |
|
143 char * |
|
144 getjobtext(Eprog prog, Wordcode c) |
|
145 { |
|
146 static char jbuf[JOBTEXTSIZE]; |
|
147 |
|
148 struct estate s; |
|
149 |
|
150 if (!c) |
|
151 c = prog->prog; |
|
152 |
|
153 useeprog(prog); /* mark as used */ |
|
154 s.prog = prog; |
|
155 s.pc = c; |
|
156 s.strs = prog->strs; |
|
157 |
|
158 tnewlins = 0; |
|
159 tbuf = NULL; |
|
160 tptr = jbuf; |
|
161 tlim = tptr + JOBTEXTSIZE - 1; |
|
162 tindent = 1; |
|
163 tjob = 1; |
|
164 gettext2(&s); |
|
165 *tptr = '\0'; |
|
166 freeeprog(prog); /* mark as unused */ |
|
167 untokenize(jbuf); |
|
168 return jbuf; |
|
169 } |
|
170 |
|
171 /* |
|
172 * gettext2() shows one way to walk through the word code without |
|
173 * recursion. We start by reading a word code and executing the |
|
174 * action for it. Some codes have sub-structures (like, e.g. WC_FOR) |
|
175 * and require something to be done after the sub-structure has been |
|
176 * handled. For these codes a tstack structure which describes what |
|
177 * has to be done is pushed onto a stack. Codes without sub-structures |
|
178 * arrange for the next structure being taken from the stack so that |
|
179 * the action for it is executed instead of the one for the next |
|
180 * word code. If the stack is empty at this point, we have handled |
|
181 * the whole structure we were called for. |
|
182 */ |
|
183 |
|
184 typedef struct tstack *Tstack; |
|
185 |
|
186 struct tstack { |
|
187 Tstack prev; |
|
188 wordcode code; |
|
189 int pop; |
|
190 union { |
|
191 struct { |
|
192 LinkList list; |
|
193 } _redir; |
|
194 struct { |
|
195 char *strs; |
|
196 Wordcode end; |
|
197 } _funcdef; |
|
198 struct { |
|
199 Wordcode end; |
|
200 } _case; |
|
201 struct { |
|
202 int cond; |
|
203 Wordcode end; |
|
204 } _if; |
|
205 struct { |
|
206 int par; |
|
207 } _cond; |
|
208 struct { |
|
209 Wordcode end; |
|
210 } _subsh; |
|
211 } u; |
|
212 }; |
|
213 |
|
214 static Tstack tstack, tfree; |
|
215 |
|
216 static Tstack |
|
217 tpush(wordcode code, int pop) |
|
218 { |
|
219 Tstack s; |
|
220 |
|
221 if ((s = tfree)) |
|
222 tfree = s->prev; |
|
223 else |
|
224 s = (Tstack) zalloc(sizeof(*s)); |
|
225 |
|
226 s->prev = tstack; |
|
227 tstack = s; |
|
228 s->code = code; |
|
229 s->pop = pop; |
|
230 |
|
231 return s; |
|
232 } |
|
233 |
|
234 /**/ |
|
235 static void |
|
236 gettext2(Estate state) |
|
237 { |
|
238 Tstack s, n; |
|
239 int stack = 0; |
|
240 wordcode code; |
|
241 |
|
242 while (1) { |
|
243 if (stack) { |
|
244 if (!(s = tstack)) |
|
245 return; |
|
246 if (s->pop) { |
|
247 tstack = s->prev; |
|
248 s->prev = tfree; |
|
249 tfree = s; |
|
250 } |
|
251 code = s->code; |
|
252 stack = 0; |
|
253 } else { |
|
254 s = NULL; |
|
255 code = *state->pc++; |
|
256 } |
|
257 switch (wc_code(code)) { |
|
258 case WC_LIST: |
|
259 if (!s) { |
|
260 s = tpush(code, (WC_LIST_TYPE(code) & Z_END)); |
|
261 stack = 0; |
|
262 } else { |
|
263 if (WC_LIST_TYPE(code) & Z_ASYNC) { |
|
264 taddstr(" &"); |
|
265 if (WC_LIST_TYPE(code) & Z_DISOWN) |
|
266 taddstr("|"); |
|
267 } |
|
268 if (!(stack = (WC_LIST_TYPE(code) & Z_END))) { |
|
269 if (tnewlins) |
|
270 taddnl(); |
|
271 else |
|
272 taddstr((WC_LIST_TYPE(code) & Z_ASYNC) ? " " : "; "); |
|
273 s->code = *state->pc++; |
|
274 s->pop = (WC_LIST_TYPE(s->code) & Z_END); |
|
275 } |
|
276 } |
|
277 if (!stack && (WC_LIST_TYPE(s->code) & Z_SIMPLE)) |
|
278 state->pc++; |
|
279 break; |
|
280 case WC_SUBLIST: |
|
281 if (!s) { |
|
282 if (!(WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) && |
|
283 wc_code(*state->pc) != WC_PIPE) |
|
284 stack = -1; |
|
285 if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) |
|
286 taddstr(stack ? "!" : "! "); |
|
287 if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_COPROC) |
|
288 taddstr(stack ? "coproc" : "coproc "); |
|
289 s = tpush(code, (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END)); |
|
290 } else { |
|
291 if (!(stack = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END))) { |
|
292 taddstr((WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR) ? |
|
293 " || " : " && "); |
|
294 s->code = *state->pc++; |
|
295 s->pop = (WC_SUBLIST_TYPE(s->code) == WC_SUBLIST_END); |
|
296 if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_NOT) |
|
297 taddstr("! "); |
|
298 if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_COPROC) |
|
299 taddstr("coproc "); |
|
300 } |
|
301 } |
|
302 if (stack < 1 && (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_SIMPLE)) |
|
303 state->pc++; |
|
304 break; |
|
305 case WC_PIPE: |
|
306 if (!s) { |
|
307 tpush(code, (WC_PIPE_TYPE(code) == WC_PIPE_END)); |
|
308 if (WC_PIPE_TYPE(code) == WC_PIPE_MID) |
|
309 state->pc++; |
|
310 } else { |
|
311 if (!(stack = (WC_PIPE_TYPE(code) == WC_PIPE_END))) { |
|
312 taddstr(" | "); |
|
313 s->code = *state->pc++; |
|
314 if (!(s->pop = (WC_PIPE_TYPE(s->code) == WC_PIPE_END))) |
|
315 state->pc++; |
|
316 } |
|
317 } |
|
318 break; |
|
319 case WC_REDIR: |
|
320 if (!s) { |
|
321 state->pc--; |
|
322 n = tpush(code, 1); |
|
323 n->u._redir.list = ecgetredirs(state); |
|
324 } else { |
|
325 getredirs(s->u._redir.list); |
|
326 stack = 1; |
|
327 } |
|
328 break; |
|
329 case WC_ASSIGN: |
|
330 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
331 if (WC_ASSIGN_TYPE2(code) == WC_ASSIGN_INC) taddchr('+'); |
|
332 taddchr('='); |
|
333 if (WC_ASSIGN_TYPE(code) == WC_ASSIGN_ARRAY) { |
|
334 taddchr('('); |
|
335 taddlist(state, WC_ASSIGN_NUM(code)); |
|
336 taddstr(") "); |
|
337 } else { |
|
338 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
339 taddchr(' '); |
|
340 } |
|
341 break; |
|
342 case WC_SIMPLE: |
|
343 taddlist(state, WC_SIMPLE_ARGC(code)); |
|
344 stack = 1; |
|
345 break; |
|
346 case WC_SUBSH: |
|
347 if (!s) { |
|
348 taddstr("("); |
|
349 tindent++; |
|
350 taddnl(); |
|
351 n = tpush(code, 1); |
|
352 n->u._subsh.end = state->pc + WC_SUBSH_SKIP(code); |
|
353 /* skip word only use for try/always */ |
|
354 state->pc++; |
|
355 } else { |
|
356 state->pc = s->u._subsh.end; |
|
357 tindent--; |
|
358 taddnl(); |
|
359 taddstr(")"); |
|
360 stack = 1; |
|
361 } |
|
362 break; |
|
363 case WC_CURSH: |
|
364 if (!s) { |
|
365 taddstr("{"); |
|
366 tindent++; |
|
367 taddnl(); |
|
368 n = tpush(code, 1); |
|
369 n->u._subsh.end = state->pc + WC_CURSH_SKIP(code); |
|
370 /* skip word only use for try/always */ |
|
371 state->pc++; |
|
372 } else { |
|
373 state->pc = s->u._subsh.end; |
|
374 tindent--; |
|
375 taddnl(); |
|
376 taddstr("}"); |
|
377 stack = 1; |
|
378 } |
|
379 break; |
|
380 case WC_TIMED: |
|
381 if (!s) { |
|
382 taddstr("time"); |
|
383 if (WC_TIMED_TYPE(code) == WC_TIMED_PIPE) { |
|
384 taddchr(' '); |
|
385 tindent++; |
|
386 tpush(code, 1); |
|
387 } else |
|
388 stack = 1; |
|
389 } else { |
|
390 tindent--; |
|
391 stack = 1; |
|
392 } |
|
393 break; |
|
394 case WC_FUNCDEF: |
|
395 if (!s) { |
|
396 Wordcode p = state->pc; |
|
397 Wordcode end = p + WC_FUNCDEF_SKIP(code); |
|
398 |
|
399 taddlist(state, *state->pc++); |
|
400 if (tjob) { |
|
401 taddstr(" () { ... }"); |
|
402 state->pc = end; |
|
403 stack = 1; |
|
404 } else { |
|
405 taddstr(" () {"); |
|
406 tindent++; |
|
407 taddnl(); |
|
408 n = tpush(code, 1); |
|
409 n->u._funcdef.strs = state->strs; |
|
410 n->u._funcdef.end = end; |
|
411 state->strs += *state->pc; |
|
412 state->pc += 3; |
|
413 } |
|
414 } else { |
|
415 state->strs = s->u._funcdef.strs; |
|
416 state->pc = s->u._funcdef.end; |
|
417 tindent--; |
|
418 taddnl(); |
|
419 taddstr("}"); |
|
420 stack = 1; |
|
421 } |
|
422 break; |
|
423 case WC_FOR: |
|
424 if (!s) { |
|
425 taddstr("for "); |
|
426 if (WC_FOR_TYPE(code) == WC_FOR_COND) { |
|
427 taddstr("(("); |
|
428 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
429 taddstr("; "); |
|
430 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
431 taddstr("; "); |
|
432 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
433 taddstr(")) do"); |
|
434 } else { |
|
435 taddlist(state, *state->pc++); |
|
436 if (WC_FOR_TYPE(code) == WC_FOR_LIST) { |
|
437 taddstr(" in "); |
|
438 taddlist(state, *state->pc++); |
|
439 } |
|
440 taddnl(); |
|
441 taddstr("do"); |
|
442 } |
|
443 tindent++; |
|
444 taddnl(); |
|
445 tpush(code, 1); |
|
446 } else { |
|
447 tindent--; |
|
448 taddnl(); |
|
449 taddstr("done"); |
|
450 stack = 1; |
|
451 } |
|
452 break; |
|
453 case WC_SELECT: |
|
454 if (!s) { |
|
455 taddstr("select "); |
|
456 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
457 if (WC_SELECT_TYPE(code) == WC_SELECT_LIST) { |
|
458 taddstr(" in "); |
|
459 taddlist(state, *state->pc++); |
|
460 } |
|
461 tindent++; |
|
462 taddnl(); |
|
463 tpush(code, 1); |
|
464 } else { |
|
465 tindent--; |
|
466 taddnl(); |
|
467 taddstr("done"); |
|
468 stack = 1; |
|
469 } |
|
470 break; |
|
471 case WC_WHILE: |
|
472 if (!s) { |
|
473 taddstr(WC_WHILE_TYPE(code) == WC_WHILE_UNTIL ? |
|
474 "until " : "while "); |
|
475 tindent++; |
|
476 tpush(code, 0); |
|
477 } else if (!s->pop) { |
|
478 tindent--; |
|
479 taddnl(); |
|
480 taddstr("do"); |
|
481 tindent++; |
|
482 taddnl(); |
|
483 s->pop = 1; |
|
484 } else { |
|
485 tindent--; |
|
486 taddnl(); |
|
487 taddstr("done"); |
|
488 stack = 1; |
|
489 } |
|
490 break; |
|
491 case WC_REPEAT: |
|
492 if (!s) { |
|
493 taddstr("repeat "); |
|
494 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
495 taddnl(); |
|
496 taddstr("do"); |
|
497 tindent++; |
|
498 taddnl(); |
|
499 tpush(code, 1); |
|
500 } else { |
|
501 tindent--; |
|
502 taddnl(); |
|
503 taddstr("done"); |
|
504 stack = 1; |
|
505 } |
|
506 break; |
|
507 case WC_CASE: |
|
508 if (!s) { |
|
509 Wordcode end = state->pc + WC_CASE_SKIP(code); |
|
510 |
|
511 taddstr("case "); |
|
512 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
513 taddstr(" in"); |
|
514 |
|
515 if (state->pc >= end) { |
|
516 if (tnewlins) |
|
517 taddnl(); |
|
518 else |
|
519 taddchr(' '); |
|
520 taddstr("esac"); |
|
521 stack = 1; |
|
522 } else { |
|
523 tindent++; |
|
524 if (tnewlins) |
|
525 taddnl(); |
|
526 else |
|
527 taddchr(' '); |
|
528 taddstr("("); |
|
529 code = *state->pc++; |
|
530 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
531 state->pc++; |
|
532 taddstr(") "); |
|
533 tindent++; |
|
534 n = tpush(code, 0); |
|
535 n->u._case.end = end; |
|
536 n->pop = (state->pc - 2 + WC_CASE_SKIP(code) >= end); |
|
537 } |
|
538 } else if (state->pc < s->u._case.end) { |
|
539 tindent--; |
|
540 taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&"); |
|
541 if (tnewlins) |
|
542 taddnl(); |
|
543 else |
|
544 taddchr(' '); |
|
545 taddstr("("); |
|
546 code = *state->pc++; |
|
547 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
548 state->pc++; |
|
549 taddstr(") "); |
|
550 tindent++; |
|
551 s->code = code; |
|
552 s->pop = ((state->pc - 2 + WC_CASE_SKIP(code)) >= |
|
553 s->u._case.end); |
|
554 } else { |
|
555 tindent--; |
|
556 taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&"); |
|
557 tindent--; |
|
558 if (tnewlins) |
|
559 taddnl(); |
|
560 else |
|
561 taddchr(' '); |
|
562 taddstr("esac"); |
|
563 stack = 1; |
|
564 } |
|
565 break; |
|
566 case WC_IF: |
|
567 if (!s) { |
|
568 Wordcode end = state->pc + WC_IF_SKIP(code); |
|
569 |
|
570 taddstr("if "); |
|
571 tindent++; |
|
572 state->pc++; |
|
573 |
|
574 n = tpush(code, 0); |
|
575 n->u._if.end = end; |
|
576 n->u._if.cond = 1; |
|
577 } else if (s->pop) { |
|
578 stack = 1; |
|
579 } else if (s->u._if.cond) { |
|
580 tindent--; |
|
581 taddnl(); |
|
582 taddstr("then"); |
|
583 tindent++; |
|
584 taddnl(); |
|
585 s->u._if.cond = 0; |
|
586 } else if (state->pc < s->u._if.end) { |
|
587 tindent--; |
|
588 taddnl(); |
|
589 code = *state->pc++; |
|
590 if (WC_IF_TYPE(code) == WC_IF_ELIF) { |
|
591 taddstr("elif "); |
|
592 tindent++; |
|
593 s->u._if.cond = 1; |
|
594 } else { |
|
595 taddstr("else"); |
|
596 tindent++; |
|
597 taddnl(); |
|
598 } |
|
599 } else { |
|
600 s->pop = 1; |
|
601 tindent--; |
|
602 taddnl(); |
|
603 taddstr("fi"); |
|
604 stack = 1; |
|
605 } |
|
606 break; |
|
607 case WC_COND: |
|
608 { |
|
609 static char *c1[] = { |
|
610 "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq", |
|
611 "-ne", "-lt", "-gt", "-le", "-ge" |
|
612 }; |
|
613 |
|
614 int ctype; |
|
615 |
|
616 if (!s) { |
|
617 taddstr("[[ "); |
|
618 n = tpush(code, 1); |
|
619 n->u._cond.par = 2; |
|
620 } else if (s->u._cond.par == 2) { |
|
621 taddstr(" ]]"); |
|
622 stack = 1; |
|
623 break; |
|
624 } else if (s->u._cond.par == 1) { |
|
625 taddstr(" )"); |
|
626 stack = 1; |
|
627 break; |
|
628 } else if (WC_COND_TYPE(s->code) == COND_AND) { |
|
629 taddstr(" && "); |
|
630 code = *state->pc++; |
|
631 if (WC_COND_TYPE(code) == COND_OR) { |
|
632 taddstr("( "); |
|
633 n = tpush(code, 1); |
|
634 n->u._cond.par = 1; |
|
635 } |
|
636 } else if (WC_COND_TYPE(s->code) == COND_OR) { |
|
637 taddstr(" || "); |
|
638 code = *state->pc++; |
|
639 if (WC_COND_TYPE(code) == COND_AND) { |
|
640 taddstr("( "); |
|
641 n = tpush(code, 1); |
|
642 n->u._cond.par = 1; |
|
643 } |
|
644 } |
|
645 while (!stack) { |
|
646 switch ((ctype = WC_COND_TYPE(code))) { |
|
647 case COND_NOT: |
|
648 taddstr("! "); |
|
649 code = *state->pc++; |
|
650 if (WC_COND_TYPE(code) <= COND_OR) { |
|
651 taddstr("( "); |
|
652 n = tpush(code, 1); |
|
653 n->u._cond.par = 1; |
|
654 } |
|
655 break; |
|
656 case COND_AND: |
|
657 n = tpush(code, 1); |
|
658 n->u._cond.par = 0; |
|
659 code = *state->pc++; |
|
660 if (WC_COND_TYPE(code) == COND_OR) { |
|
661 taddstr("( "); |
|
662 n = tpush(code, 1); |
|
663 n->u._cond.par = 1; |
|
664 } |
|
665 break; |
|
666 case COND_OR: |
|
667 n = tpush(code, 1); |
|
668 n->u._cond.par = 0; |
|
669 code = *state->pc++; |
|
670 if (WC_COND_TYPE(code) == COND_AND) { |
|
671 taddstr("( "); |
|
672 n = tpush(code, 1); |
|
673 n->u._cond.par = 1; |
|
674 } |
|
675 break; |
|
676 case COND_MOD: |
|
677 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
678 taddchr(' '); |
|
679 taddlist(state, WC_COND_SKIP(code)); |
|
680 stack = 1; |
|
681 break; |
|
682 case COND_MODI: |
|
683 { |
|
684 char *name = ecgetstr(state, EC_NODUP, NULL); |
|
685 |
|
686 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
687 taddchr(' '); |
|
688 taddstr(name); |
|
689 taddchr(' '); |
|
690 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
691 stack = 1; |
|
692 } |
|
693 break; |
|
694 default: |
|
695 if (ctype <= COND_GE) { |
|
696 /* Binary test: `a = b' etc. */ |
|
697 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
698 taddstr(" "); |
|
699 taddstr(c1[ctype - COND_STREQ]); |
|
700 taddstr(" "); |
|
701 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
702 if (ctype == COND_STREQ || |
|
703 ctype == COND_STRNEQ) |
|
704 state->pc++; |
|
705 } else { |
|
706 /* Unary test: `-f foo' etc. */ |
|
707 char c2[4]; |
|
708 |
|
709 c2[0] = '-'; |
|
710 c2[1] = ctype; |
|
711 c2[2] = ' '; |
|
712 c2[3] = '\0'; |
|
713 taddstr(c2); |
|
714 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
715 } |
|
716 stack = 1; |
|
717 break; |
|
718 } |
|
719 } |
|
720 } |
|
721 break; |
|
722 case WC_ARITH: |
|
723 taddstr("(("); |
|
724 taddstr(ecgetstr(state, EC_NODUP, NULL)); |
|
725 taddstr("))"); |
|
726 stack = 1; |
|
727 break; |
|
728 case WC_TRY: |
|
729 if (!s) { |
|
730 taddstr("{"); |
|
731 tindent++; |
|
732 taddnl(); |
|
733 n = tpush(code, 0); |
|
734 state->pc++; |
|
735 /* this is the end of the try block alone */ |
|
736 n->u._subsh.end = state->pc + WC_CURSH_SKIP(state->pc[-1]); |
|
737 } else if (!s->pop) { |
|
738 state->pc = s->u._subsh.end; |
|
739 tindent--; |
|
740 taddnl(); |
|
741 taddstr("} always {"); |
|
742 tindent++; |
|
743 taddnl(); |
|
744 s->pop = 1; |
|
745 } else { |
|
746 tindent--; |
|
747 taddnl(); |
|
748 taddstr("}"); |
|
749 stack = 1; |
|
750 } |
|
751 break; |
|
752 case WC_END: |
|
753 stack = 1; |
|
754 break; |
|
755 default: |
|
756 DPUTS(1, "unknown word code in gettext2()"); |
|
757 return; |
|
758 } |
|
759 } |
|
760 } |
|
761 |
|
762 /**/ |
|
763 void |
|
764 getredirs(LinkList redirs) |
|
765 { |
|
766 LinkNode n; |
|
767 static char *fstr[] = |
|
768 { |
|
769 ">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<", |
|
770 "<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">" |
|
771 }; |
|
772 taddchr(' '); |
|
773 for (n = firstnode(redirs); n; incnode(n)) { |
|
774 Redir f = (Redir) getdata(n); |
|
775 |
|
776 switch (f->type) { |
|
777 case REDIR_WRITE: |
|
778 case REDIR_WRITENOW: |
|
779 case REDIR_APP: |
|
780 case REDIR_APPNOW: |
|
781 case REDIR_ERRWRITE: |
|
782 case REDIR_ERRWRITENOW: |
|
783 case REDIR_ERRAPP: |
|
784 case REDIR_ERRAPPNOW: |
|
785 case REDIR_READ: |
|
786 case REDIR_READWRITE: |
|
787 case REDIR_HERESTR: |
|
788 case REDIR_MERGEIN: |
|
789 case REDIR_MERGEOUT: |
|
790 case REDIR_INPIPE: |
|
791 case REDIR_OUTPIPE: |
|
792 if (f->fd1 != (IS_READFD(f->type) ? 0 : 1)) |
|
793 taddchr('0' + f->fd1); |
|
794 taddstr(fstr[f->type]); |
|
795 taddchr(' '); |
|
796 if (f->type == REDIR_HERESTR) { |
|
797 if (has_token(f->name)) { |
|
798 taddchr('\"'); |
|
799 taddstr(bslashquote(f->name, NULL, 2)); |
|
800 taddchr('\"'); |
|
801 } else { |
|
802 taddchr('\''); |
|
803 taddstr(bslashquote(f->name, NULL, 1)); |
|
804 taddchr('\''); |
|
805 } |
|
806 } else |
|
807 taddstr(f->name); |
|
808 taddchr(' '); |
|
809 break; |
|
810 #ifdef DEBUG |
|
811 case REDIR_CLOSE: |
|
812 DPUTS(1, "BUG: CLOSE in getredirs()"); |
|
813 taddchr(f->fd1 + '0'); |
|
814 taddstr(">&- "); |
|
815 break; |
|
816 default: |
|
817 DPUTS(1, "BUG: unknown redirection in getredirs()"); |
|
818 #endif |
|
819 } |
|
820 } |
|
821 tptr--; |
|
822 } |