openenvutils/commandshell/shell/src/text.c
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     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 }