1 | /* print_command -- A way to make readable commands from a command tree. */
|
---|
2 |
|
---|
3 | /* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
---|
4 |
|
---|
5 | This file is part of GNU Bash, the Bourne Again SHell.
|
---|
6 |
|
---|
7 | Bash is free software; you can redistribute it and/or modify it under
|
---|
8 | the terms of the GNU General Public License as published by the Free
|
---|
9 | Software Foundation; either version 2, or (at your option) any later
|
---|
10 | version.
|
---|
11 |
|
---|
12 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
---|
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
---|
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
---|
15 | for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License along
|
---|
18 | with Bash; see the file COPYING. If not, write to the Free Software
|
---|
19 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
---|
20 |
|
---|
21 | #include "config.h"
|
---|
22 |
|
---|
23 | #include <stdio.h>
|
---|
24 |
|
---|
25 | #if defined (HAVE_UNISTD_H)
|
---|
26 | # ifdef _MINIX
|
---|
27 | # include <sys/types.h>
|
---|
28 | # endif
|
---|
29 | # include <unistd.h>
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | #if defined (PREFER_STDARG)
|
---|
33 | # include <stdarg.h>
|
---|
34 | #else
|
---|
35 | # include <varargs.h>
|
---|
36 | #endif
|
---|
37 |
|
---|
38 | #include "bashansi.h"
|
---|
39 | #include "bashintl.h"
|
---|
40 |
|
---|
41 | #include "shell.h"
|
---|
42 | #include "flags.h"
|
---|
43 | #include <y.tab.h> /* use <...> so we pick it up from the build directory */
|
---|
44 |
|
---|
45 | #include "shmbutil.h"
|
---|
46 |
|
---|
47 | #include "builtins/common.h"
|
---|
48 |
|
---|
49 | #if !HAVE_DECL_PRINTF
|
---|
50 | extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
|
---|
51 | #endif
|
---|
52 |
|
---|
53 | extern int indirection_level;
|
---|
54 |
|
---|
55 | static int indentation;
|
---|
56 | static int indentation_amount = 4;
|
---|
57 |
|
---|
58 | #if defined (PREFER_STDARG)
|
---|
59 | typedef void PFUNC __P((const char *, ...));
|
---|
60 |
|
---|
61 | static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
---|
62 | static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
---|
63 | #else
|
---|
64 | #define PFUNC VFunction
|
---|
65 | static void cprintf ();
|
---|
66 | static void xprintf ();
|
---|
67 | #endif
|
---|
68 |
|
---|
69 | static void reset_locals __P((void));
|
---|
70 | static void newline __P((char *));
|
---|
71 | static void indent __P((int));
|
---|
72 | static void semicolon __P((void));
|
---|
73 | static void the_printed_command_resize __P((int));
|
---|
74 |
|
---|
75 | static void make_command_string_internal __P((COMMAND *));
|
---|
76 | static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
|
---|
77 | static void command_print_word_list __P((WORD_LIST *, char *));
|
---|
78 | static void print_case_clauses __P((PATTERN_LIST *));
|
---|
79 | static void print_redirection_list __P((REDIRECT *));
|
---|
80 | static void print_redirection __P((REDIRECT *));
|
---|
81 |
|
---|
82 | static void print_for_command __P((FOR_COM *));
|
---|
83 | #if defined (ARITH_FOR_COMMAND)
|
---|
84 | static void print_arith_for_command __P((ARITH_FOR_COM *));
|
---|
85 | #endif
|
---|
86 | #if defined (SELECT_COMMAND)
|
---|
87 | static void print_select_command __P((SELECT_COM *));
|
---|
88 | #endif
|
---|
89 | static void print_group_command __P((GROUP_COM *));
|
---|
90 | static void print_case_command __P((CASE_COM *));
|
---|
91 | static void print_while_command __P((WHILE_COM *));
|
---|
92 | static void print_until_command __P((WHILE_COM *));
|
---|
93 | static void print_until_or_while __P((WHILE_COM *, char *));
|
---|
94 | static void print_if_command __P((IF_COM *));
|
---|
95 | #if defined (COND_COMMAND)
|
---|
96 | static void print_cond_node __P((COND_COM *));
|
---|
97 | #endif
|
---|
98 | static void print_function_def __P((FUNCTION_DEF *));
|
---|
99 |
|
---|
100 | #define PRINTED_COMMAND_INITIAL_SIZE 64
|
---|
101 | #define PRINTED_COMMAND_GROW_SIZE 128
|
---|
102 |
|
---|
103 | char *the_printed_command = (char *)NULL;
|
---|
104 | int the_printed_command_size = 0;
|
---|
105 | int command_string_index = 0;
|
---|
106 |
|
---|
107 | /* Non-zero means the stuff being printed is inside of a function def. */
|
---|
108 | static int inside_function_def;
|
---|
109 | static int skip_this_indent;
|
---|
110 | static int was_heredoc;
|
---|
111 |
|
---|
112 | /* The depth of the group commands that we are currently printing. This
|
---|
113 | includes the group command that is a function body. */
|
---|
114 | static int group_command_nesting;
|
---|
115 |
|
---|
116 | /* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
|
---|
117 | static char indirection_string[100];
|
---|
118 |
|
---|
119 | /* Print COMMAND (a command tree) on standard output. */
|
---|
120 | void
|
---|
121 | print_command (command)
|
---|
122 | COMMAND *command;
|
---|
123 | {
|
---|
124 | command_string_index = 0;
|
---|
125 | printf ("%s", make_command_string (command));
|
---|
126 | }
|
---|
127 |
|
---|
128 | /* Make a string which is the printed representation of the command
|
---|
129 | tree in COMMAND. We return this string. However, the string is
|
---|
130 | not consed, so you have to do that yourself if you want it to
|
---|
131 | remain around. */
|
---|
132 | char *
|
---|
133 | make_command_string (command)
|
---|
134 | COMMAND *command;
|
---|
135 | {
|
---|
136 | command_string_index = was_heredoc = 0;
|
---|
137 | make_command_string_internal (command);
|
---|
138 | return (the_printed_command);
|
---|
139 | }
|
---|
140 |
|
---|
141 | /* The internal function. This is the real workhorse. */
|
---|
142 | static void
|
---|
143 | make_command_string_internal (command)
|
---|
144 | COMMAND *command;
|
---|
145 | {
|
---|
146 | if (command == 0)
|
---|
147 | cprintf ("");
|
---|
148 | else
|
---|
149 | {
|
---|
150 | if (skip_this_indent)
|
---|
151 | skip_this_indent--;
|
---|
152 | else
|
---|
153 | indent (indentation);
|
---|
154 |
|
---|
155 | if (command->flags & CMD_TIME_PIPELINE)
|
---|
156 | {
|
---|
157 | cprintf ("time ");
|
---|
158 | if (command->flags & CMD_TIME_POSIX)
|
---|
159 | cprintf ("-p ");
|
---|
160 | }
|
---|
161 |
|
---|
162 | if (command->flags & CMD_INVERT_RETURN)
|
---|
163 | cprintf ("! ");
|
---|
164 |
|
---|
165 | switch (command->type)
|
---|
166 | {
|
---|
167 | case cm_for:
|
---|
168 | print_for_command (command->value.For);
|
---|
169 | break;
|
---|
170 |
|
---|
171 | #if defined (ARITH_FOR_COMMAND)
|
---|
172 | case cm_arith_for:
|
---|
173 | print_arith_for_command (command->value.ArithFor);
|
---|
174 | break;
|
---|
175 | #endif
|
---|
176 |
|
---|
177 | #if defined (SELECT_COMMAND)
|
---|
178 | case cm_select:
|
---|
179 | print_select_command (command->value.Select);
|
---|
180 | break;
|
---|
181 | #endif
|
---|
182 |
|
---|
183 | case cm_case:
|
---|
184 | print_case_command (command->value.Case);
|
---|
185 | break;
|
---|
186 |
|
---|
187 | case cm_while:
|
---|
188 | print_while_command (command->value.While);
|
---|
189 | break;
|
---|
190 |
|
---|
191 | case cm_until:
|
---|
192 | print_until_command (command->value.While);
|
---|
193 | break;
|
---|
194 |
|
---|
195 | case cm_if:
|
---|
196 | print_if_command (command->value.If);
|
---|
197 | break;
|
---|
198 |
|
---|
199 | #if defined (DPAREN_ARITHMETIC)
|
---|
200 | case cm_arith:
|
---|
201 | print_arith_command (command->value.Arith->exp);
|
---|
202 | break;
|
---|
203 | #endif
|
---|
204 |
|
---|
205 | #if defined (COND_COMMAND)
|
---|
206 | case cm_cond:
|
---|
207 | print_cond_command (command->value.Cond);
|
---|
208 | break;
|
---|
209 | #endif
|
---|
210 |
|
---|
211 | case cm_simple:
|
---|
212 | print_simple_command (command->value.Simple);
|
---|
213 | break;
|
---|
214 |
|
---|
215 | case cm_connection:
|
---|
216 |
|
---|
217 | skip_this_indent++;
|
---|
218 | make_command_string_internal (command->value.Connection->first);
|
---|
219 |
|
---|
220 | switch (command->value.Connection->connector)
|
---|
221 | {
|
---|
222 | case '&':
|
---|
223 | case '|':
|
---|
224 | {
|
---|
225 | char c = command->value.Connection->connector;
|
---|
226 | cprintf (" %c", c);
|
---|
227 | if (c != '&' || command->value.Connection->second)
|
---|
228 | {
|
---|
229 | cprintf (" ");
|
---|
230 | skip_this_indent++;
|
---|
231 | }
|
---|
232 | }
|
---|
233 | break;
|
---|
234 |
|
---|
235 | case AND_AND:
|
---|
236 | cprintf (" && ");
|
---|
237 | if (command->value.Connection->second)
|
---|
238 | skip_this_indent++;
|
---|
239 | break;
|
---|
240 |
|
---|
241 | case OR_OR:
|
---|
242 | cprintf (" || ");
|
---|
243 | if (command->value.Connection->second)
|
---|
244 | skip_this_indent++;
|
---|
245 | break;
|
---|
246 |
|
---|
247 | case ';':
|
---|
248 | if (was_heredoc == 0)
|
---|
249 | cprintf (";");
|
---|
250 | else
|
---|
251 | was_heredoc = 0;
|
---|
252 |
|
---|
253 | if (inside_function_def)
|
---|
254 | cprintf ("\n");
|
---|
255 | else
|
---|
256 | {
|
---|
257 | cprintf (" ");
|
---|
258 | if (command->value.Connection->second)
|
---|
259 | skip_this_indent++;
|
---|
260 | }
|
---|
261 | break;
|
---|
262 |
|
---|
263 | default:
|
---|
264 | cprintf (_("print_command: bad connector `%d'"),
|
---|
265 | command->value.Connection->connector);
|
---|
266 | break;
|
---|
267 | }
|
---|
268 |
|
---|
269 | make_command_string_internal (command->value.Connection->second);
|
---|
270 | break;
|
---|
271 |
|
---|
272 | case cm_function_def:
|
---|
273 | print_function_def (command->value.Function_def);
|
---|
274 | break;
|
---|
275 |
|
---|
276 | case cm_group:
|
---|
277 | print_group_command (command->value.Group);
|
---|
278 | break;
|
---|
279 |
|
---|
280 | case cm_subshell:
|
---|
281 | cprintf ("( ");
|
---|
282 | skip_this_indent++;
|
---|
283 | make_command_string_internal (command->value.Subshell->command);
|
---|
284 | cprintf (" )");
|
---|
285 | break;
|
---|
286 |
|
---|
287 | default:
|
---|
288 | command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
|
---|
289 | break;
|
---|
290 | }
|
---|
291 |
|
---|
292 |
|
---|
293 | if (command->redirects)
|
---|
294 | {
|
---|
295 | cprintf (" ");
|
---|
296 | print_redirection_list (command->redirects);
|
---|
297 | }
|
---|
298 | }
|
---|
299 | }
|
---|
300 |
|
---|
301 | static void
|
---|
302 | _print_word_list (list, separator, pfunc)
|
---|
303 | WORD_LIST *list;
|
---|
304 | char *separator;
|
---|
305 | PFUNC *pfunc;
|
---|
306 | {
|
---|
307 | WORD_LIST *w;
|
---|
308 |
|
---|
309 | for (w = list; w; w = w->next)
|
---|
310 | (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
|
---|
311 | }
|
---|
312 |
|
---|
313 | void
|
---|
314 | print_word_list (list, separator)
|
---|
315 | WORD_LIST *list;
|
---|
316 | char *separator;
|
---|
317 | {
|
---|
318 | _print_word_list (list, separator, xprintf);
|
---|
319 | }
|
---|
320 |
|
---|
321 | /* Return a string denoting what our indirection level is. */
|
---|
322 |
|
---|
323 | char *
|
---|
324 | indirection_level_string ()
|
---|
325 | {
|
---|
326 | register int i, j;
|
---|
327 | char *ps4;
|
---|
328 | char ps4_firstc[MB_LEN_MAX+1];
|
---|
329 | int ps4_firstc_len, ps4_len;
|
---|
330 |
|
---|
331 | indirection_string[0] = '\0';
|
---|
332 | ps4 = get_string_value ("PS4");
|
---|
333 |
|
---|
334 | if (ps4 == 0 || *ps4 == '\0')
|
---|
335 | return (indirection_string);
|
---|
336 |
|
---|
337 | change_flag ('x', FLAG_OFF);
|
---|
338 | ps4 = decode_prompt_string (ps4);
|
---|
339 | change_flag ('x', FLAG_ON);
|
---|
340 |
|
---|
341 | if (ps4 == 0 || *ps4 == '\0')
|
---|
342 | return (indirection_string);
|
---|
343 |
|
---|
344 | #if defined (HANDLE_MULTIBYTE)
|
---|
345 | ps4_len = strnlen (ps4, MB_CUR_MAX);
|
---|
346 | ps4_firstc_len = MBLEN (ps4, ps4_len);
|
---|
347 | if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
|
---|
348 | {
|
---|
349 | ps4_firstc[0] = ps4[0];
|
---|
350 | ps4_firstc[ps4_firstc_len = 1] = '\0';
|
---|
351 | }
|
---|
352 | else
|
---|
353 | memcpy (ps4_firstc, ps4, ps4_firstc_len);
|
---|
354 | #else
|
---|
355 | ps4_firstc[0] = ps4[0];
|
---|
356 | ps4_firstc[ps4_firstc_len = 1] = '\0';
|
---|
357 | #endif
|
---|
358 |
|
---|
359 | for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
|
---|
360 | {
|
---|
361 | if (ps4_firstc_len == 1)
|
---|
362 | indirection_string[i] = ps4_firstc[0];
|
---|
363 | else
|
---|
364 | memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
|
---|
365 | }
|
---|
366 |
|
---|
367 | for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
|
---|
368 | indirection_string[i] = ps4[j];
|
---|
369 |
|
---|
370 | indirection_string[i] = '\0';
|
---|
371 | free (ps4);
|
---|
372 | return (indirection_string);
|
---|
373 | }
|
---|
374 |
|
---|
375 | void
|
---|
376 | xtrace_print_assignment (name, value, assign_list, xflags)
|
---|
377 | char *name, *value;
|
---|
378 | int assign_list, xflags;
|
---|
379 | {
|
---|
380 | char *nval;
|
---|
381 |
|
---|
382 | if (xflags)
|
---|
383 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
384 |
|
---|
385 | /* VALUE should not be NULL when this is called. */
|
---|
386 | if (*value == '\0' || assign_list)
|
---|
387 | nval = value;
|
---|
388 | else if (sh_contains_shell_metas (value))
|
---|
389 | nval = sh_single_quote (value);
|
---|
390 | else if (ansic_shouldquote (value))
|
---|
391 | nval = ansic_quote (value, 0, (int *)0);
|
---|
392 | else
|
---|
393 | nval = value;
|
---|
394 |
|
---|
395 | if (assign_list)
|
---|
396 | fprintf (stderr, "%s=(%s)\n", name, nval);
|
---|
397 | else
|
---|
398 | fprintf (stderr, "%s=%s\n", name, nval);
|
---|
399 |
|
---|
400 | if (nval != value)
|
---|
401 | FREE (nval);
|
---|
402 |
|
---|
403 | fflush (stderr);
|
---|
404 | }
|
---|
405 |
|
---|
406 | /* A function to print the words of a simple command when set -x is on. */
|
---|
407 | void
|
---|
408 | xtrace_print_word_list (list, xtflags)
|
---|
409 | WORD_LIST *list;
|
---|
410 | int xtflags;
|
---|
411 | {
|
---|
412 | WORD_LIST *w;
|
---|
413 | char *t, *x;
|
---|
414 |
|
---|
415 | if (xtflags)
|
---|
416 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
417 |
|
---|
418 | for (w = list; w; w = w->next)
|
---|
419 | {
|
---|
420 | t = w->word->word;
|
---|
421 | if (t == 0 || *t == '\0')
|
---|
422 | fprintf (stderr, "''%s", w->next ? " " : "");
|
---|
423 | else if (sh_contains_shell_metas (t))
|
---|
424 | {
|
---|
425 | x = sh_single_quote (t);
|
---|
426 | fprintf (stderr, "%s%s", x, w->next ? " " : "");
|
---|
427 | free (x);
|
---|
428 | }
|
---|
429 | else if (ansic_shouldquote (t))
|
---|
430 | {
|
---|
431 | x = ansic_quote (t, 0, (int *)0);
|
---|
432 | fprintf (stderr, "%s%s", x, w->next ? " " : "");
|
---|
433 | free (x);
|
---|
434 | }
|
---|
435 | else
|
---|
436 | fprintf (stderr, "%s%s", t, w->next ? " " : "");
|
---|
437 | }
|
---|
438 | fprintf (stderr, "\n");
|
---|
439 | }
|
---|
440 |
|
---|
441 | static void
|
---|
442 | command_print_word_list (list, separator)
|
---|
443 | WORD_LIST *list;
|
---|
444 | char *separator;
|
---|
445 | {
|
---|
446 | _print_word_list (list, separator, cprintf);
|
---|
447 | }
|
---|
448 |
|
---|
449 | void
|
---|
450 | print_for_command_head (for_command)
|
---|
451 | FOR_COM *for_command;
|
---|
452 | {
|
---|
453 | cprintf ("for %s in ", for_command->name->word);
|
---|
454 | command_print_word_list (for_command->map_list, " ");
|
---|
455 | }
|
---|
456 |
|
---|
457 | void
|
---|
458 | xtrace_print_for_command_head (for_command)
|
---|
459 | FOR_COM *for_command;
|
---|
460 | {
|
---|
461 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
462 | fprintf (stderr, "for %s in ", for_command->name->word);
|
---|
463 | xtrace_print_word_list (for_command->map_list, 0);
|
---|
464 | }
|
---|
465 |
|
---|
466 | static void
|
---|
467 | print_for_command (for_command)
|
---|
468 | FOR_COM *for_command;
|
---|
469 | {
|
---|
470 | print_for_command_head (for_command);
|
---|
471 |
|
---|
472 | cprintf (";");
|
---|
473 | newline ("do\n");
|
---|
474 | indentation += indentation_amount;
|
---|
475 | make_command_string_internal (for_command->action);
|
---|
476 | semicolon ();
|
---|
477 | indentation -= indentation_amount;
|
---|
478 | newline ("done");
|
---|
479 | }
|
---|
480 |
|
---|
481 | #if defined (ARITH_FOR_COMMAND)
|
---|
482 | static void
|
---|
483 | print_arith_for_command (arith_for_command)
|
---|
484 | ARITH_FOR_COM *arith_for_command;
|
---|
485 | {
|
---|
486 | cprintf ("for ((");
|
---|
487 | command_print_word_list (arith_for_command->init, " ");
|
---|
488 | cprintf ("; ");
|
---|
489 | command_print_word_list (arith_for_command->test, " ");
|
---|
490 | cprintf ("; ");
|
---|
491 | command_print_word_list (arith_for_command->step, " ");
|
---|
492 | cprintf ("))");
|
---|
493 | newline ("do\n");
|
---|
494 | indentation += indentation_amount;
|
---|
495 | make_command_string_internal (arith_for_command->action);
|
---|
496 | semicolon ();
|
---|
497 | indentation -= indentation_amount;
|
---|
498 | newline ("done");
|
---|
499 | }
|
---|
500 | #endif /* ARITH_FOR_COMMAND */
|
---|
501 |
|
---|
502 | #if defined (SELECT_COMMAND)
|
---|
503 | void
|
---|
504 | print_select_command_head (select_command)
|
---|
505 | SELECT_COM *select_command;
|
---|
506 | {
|
---|
507 | cprintf ("select %s in ", select_command->name->word);
|
---|
508 | command_print_word_list (select_command->map_list, " ");
|
---|
509 | }
|
---|
510 |
|
---|
511 | void
|
---|
512 | xtrace_print_select_command_head (select_command)
|
---|
513 | SELECT_COM *select_command;
|
---|
514 | {
|
---|
515 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
516 | fprintf (stderr, "select %s in ", select_command->name->word);
|
---|
517 | xtrace_print_word_list (select_command->map_list, 0);
|
---|
518 | }
|
---|
519 |
|
---|
520 | static void
|
---|
521 | print_select_command (select_command)
|
---|
522 | SELECT_COM *select_command;
|
---|
523 | {
|
---|
524 | print_select_command_head (select_command);
|
---|
525 |
|
---|
526 | cprintf (";");
|
---|
527 | newline ("do\n");
|
---|
528 | indentation += indentation_amount;
|
---|
529 | make_command_string_internal (select_command->action);
|
---|
530 | semicolon ();
|
---|
531 | indentation -= indentation_amount;
|
---|
532 | newline ("done");
|
---|
533 | }
|
---|
534 | #endif /* SELECT_COMMAND */
|
---|
535 |
|
---|
536 | static void
|
---|
537 | print_group_command (group_command)
|
---|
538 | GROUP_COM *group_command;
|
---|
539 | {
|
---|
540 | group_command_nesting++;
|
---|
541 | cprintf ("{ ");
|
---|
542 |
|
---|
543 | if (inside_function_def == 0)
|
---|
544 | skip_this_indent++;
|
---|
545 | else
|
---|
546 | {
|
---|
547 | /* This is a group command { ... } inside of a function
|
---|
548 | definition, and should be printed as a multiline group
|
---|
549 | command, using the current indentation. */
|
---|
550 | cprintf ("\n");
|
---|
551 | indentation += indentation_amount;
|
---|
552 | }
|
---|
553 |
|
---|
554 | make_command_string_internal (group_command->command);
|
---|
555 |
|
---|
556 | if (inside_function_def)
|
---|
557 | {
|
---|
558 | cprintf ("\n");
|
---|
559 | indentation -= indentation_amount;
|
---|
560 | indent (indentation);
|
---|
561 | }
|
---|
562 | else
|
---|
563 | {
|
---|
564 | semicolon ();
|
---|
565 | cprintf (" ");
|
---|
566 | }
|
---|
567 |
|
---|
568 | cprintf ("}");
|
---|
569 |
|
---|
570 | group_command_nesting--;
|
---|
571 | }
|
---|
572 |
|
---|
573 | void
|
---|
574 | print_case_command_head (case_command)
|
---|
575 | CASE_COM *case_command;
|
---|
576 | {
|
---|
577 | cprintf ("case %s in ", case_command->word->word);
|
---|
578 | }
|
---|
579 |
|
---|
580 | void
|
---|
581 | xtrace_print_case_command_head (case_command)
|
---|
582 | CASE_COM *case_command;
|
---|
583 | {
|
---|
584 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
585 | fprintf (stderr, "case %s in\n", case_command->word->word);
|
---|
586 | }
|
---|
587 |
|
---|
588 | static void
|
---|
589 | print_case_command (case_command)
|
---|
590 | CASE_COM *case_command;
|
---|
591 | {
|
---|
592 | print_case_command_head (case_command);
|
---|
593 |
|
---|
594 | if (case_command->clauses)
|
---|
595 | print_case_clauses (case_command->clauses);
|
---|
596 | newline ("esac");
|
---|
597 | }
|
---|
598 |
|
---|
599 | static void
|
---|
600 | print_case_clauses (clauses)
|
---|
601 | PATTERN_LIST *clauses;
|
---|
602 | {
|
---|
603 | indentation += indentation_amount;
|
---|
604 | while (clauses)
|
---|
605 | {
|
---|
606 | newline ("");
|
---|
607 | command_print_word_list (clauses->patterns, " | ");
|
---|
608 | cprintf (")\n");
|
---|
609 | indentation += indentation_amount;
|
---|
610 | make_command_string_internal (clauses->action);
|
---|
611 | indentation -= indentation_amount;
|
---|
612 | newline (";;");
|
---|
613 | clauses = clauses->next;
|
---|
614 | }
|
---|
615 | indentation -= indentation_amount;
|
---|
616 | }
|
---|
617 |
|
---|
618 | static void
|
---|
619 | print_while_command (while_command)
|
---|
620 | WHILE_COM *while_command;
|
---|
621 | {
|
---|
622 | print_until_or_while (while_command, "while");
|
---|
623 | }
|
---|
624 |
|
---|
625 | static void
|
---|
626 | print_until_command (while_command)
|
---|
627 | WHILE_COM *while_command;
|
---|
628 | {
|
---|
629 | print_until_or_while (while_command, "until");
|
---|
630 | }
|
---|
631 |
|
---|
632 | static void
|
---|
633 | print_until_or_while (while_command, which)
|
---|
634 | WHILE_COM *while_command;
|
---|
635 | char *which;
|
---|
636 | {
|
---|
637 | cprintf ("%s ", which);
|
---|
638 | skip_this_indent++;
|
---|
639 | make_command_string_internal (while_command->test);
|
---|
640 | semicolon ();
|
---|
641 | cprintf (" do\n"); /* was newline ("do\n"); */
|
---|
642 | indentation += indentation_amount;
|
---|
643 | make_command_string_internal (while_command->action);
|
---|
644 | indentation -= indentation_amount;
|
---|
645 | semicolon ();
|
---|
646 | newline ("done");
|
---|
647 | }
|
---|
648 |
|
---|
649 | static void
|
---|
650 | print_if_command (if_command)
|
---|
651 | IF_COM *if_command;
|
---|
652 | {
|
---|
653 | cprintf ("if ");
|
---|
654 | skip_this_indent++;
|
---|
655 | make_command_string_internal (if_command->test);
|
---|
656 | semicolon ();
|
---|
657 | cprintf (" then\n");
|
---|
658 | indentation += indentation_amount;
|
---|
659 | make_command_string_internal (if_command->true_case);
|
---|
660 | indentation -= indentation_amount;
|
---|
661 |
|
---|
662 | if (if_command->false_case)
|
---|
663 | {
|
---|
664 | semicolon ();
|
---|
665 | newline ("else\n");
|
---|
666 | indentation += indentation_amount;
|
---|
667 | make_command_string_internal (if_command->false_case);
|
---|
668 | indentation -= indentation_amount;
|
---|
669 | }
|
---|
670 | semicolon ();
|
---|
671 | newline ("fi");
|
---|
672 | }
|
---|
673 |
|
---|
674 | #if defined (DPAREN_ARITHMETIC)
|
---|
675 | void
|
---|
676 | print_arith_command (arith_cmd_list)
|
---|
677 | WORD_LIST *arith_cmd_list;
|
---|
678 | {
|
---|
679 | cprintf ("((");
|
---|
680 | command_print_word_list (arith_cmd_list, " ");
|
---|
681 | cprintf ("))");
|
---|
682 | }
|
---|
683 | #endif
|
---|
684 |
|
---|
685 | #if defined (COND_COMMAND)
|
---|
686 | static void
|
---|
687 | print_cond_node (cond)
|
---|
688 | COND_COM *cond;
|
---|
689 | {
|
---|
690 | if (cond->flags & CMD_INVERT_RETURN)
|
---|
691 | cprintf ("! ");
|
---|
692 |
|
---|
693 | if (cond->type == COND_EXPR)
|
---|
694 | {
|
---|
695 | cprintf ("( ");
|
---|
696 | print_cond_node (cond->left);
|
---|
697 | cprintf (" )");
|
---|
698 | }
|
---|
699 | else if (cond->type == COND_AND)
|
---|
700 | {
|
---|
701 | print_cond_node (cond->left);
|
---|
702 | cprintf (" && ");
|
---|
703 | print_cond_node (cond->right);
|
---|
704 | }
|
---|
705 | else if (cond->type == COND_OR)
|
---|
706 | {
|
---|
707 | print_cond_node (cond->left);
|
---|
708 | cprintf (" || ");
|
---|
709 | print_cond_node (cond->right);
|
---|
710 | }
|
---|
711 | else if (cond->type == COND_UNARY)
|
---|
712 | {
|
---|
713 | cprintf ("%s", cond->op->word);
|
---|
714 | cprintf (" ");
|
---|
715 | print_cond_node (cond->left);
|
---|
716 | }
|
---|
717 | else if (cond->type == COND_BINARY)
|
---|
718 | {
|
---|
719 | print_cond_node (cond->left);
|
---|
720 | cprintf (" ");
|
---|
721 | cprintf ("%s", cond->op->word);
|
---|
722 | cprintf (" ");
|
---|
723 | print_cond_node (cond->right);
|
---|
724 | }
|
---|
725 | else if (cond->type == COND_TERM)
|
---|
726 | {
|
---|
727 | cprintf ("%s", cond->op->word); /* need to add quoting here */
|
---|
728 | }
|
---|
729 | }
|
---|
730 |
|
---|
731 | void
|
---|
732 | print_cond_command (cond)
|
---|
733 | COND_COM *cond;
|
---|
734 | {
|
---|
735 | cprintf ("[[ ");
|
---|
736 | print_cond_node (cond);
|
---|
737 | cprintf (" ]]");
|
---|
738 | }
|
---|
739 |
|
---|
740 | #ifdef DEBUG
|
---|
741 | void
|
---|
742 | debug_print_cond_command (cond)
|
---|
743 | COND_COM *cond;
|
---|
744 | {
|
---|
745 | fprintf (stderr, "DEBUG: ");
|
---|
746 | command_string_index = 0;
|
---|
747 | print_cond_command (cond);
|
---|
748 | fprintf (stderr, "%s\n", the_printed_command);
|
---|
749 | }
|
---|
750 | #endif
|
---|
751 |
|
---|
752 | void
|
---|
753 | xtrace_print_cond_term (type, invert, op, arg1, arg2)
|
---|
754 | int type, invert;
|
---|
755 | WORD_DESC *op;
|
---|
756 | char *arg1, *arg2;
|
---|
757 | {
|
---|
758 | command_string_index = 0;
|
---|
759 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
760 | fprintf (stderr, "[[ ");
|
---|
761 | if (invert)
|
---|
762 | fprintf (stderr, "! ");
|
---|
763 |
|
---|
764 | if (type == COND_UNARY)
|
---|
765 | {
|
---|
766 | fprintf (stderr, "%s ", op->word);
|
---|
767 | fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
|
---|
768 | }
|
---|
769 | else if (type == COND_BINARY)
|
---|
770 | {
|
---|
771 | fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
|
---|
772 | fprintf (stderr, " %s ", op->word);
|
---|
773 | fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
|
---|
774 | }
|
---|
775 |
|
---|
776 | fprintf (stderr, " ]]\n");
|
---|
777 | }
|
---|
778 | #endif /* COND_COMMAND */
|
---|
779 |
|
---|
780 | #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
|
---|
781 | /* A function to print the words of an arithmetic command when set -x is on. */
|
---|
782 | void
|
---|
783 | xtrace_print_arith_cmd (list)
|
---|
784 | WORD_LIST *list;
|
---|
785 | {
|
---|
786 | WORD_LIST *w;
|
---|
787 |
|
---|
788 | fprintf (stderr, "%s", indirection_level_string ());
|
---|
789 | fprintf (stderr, "(( ");
|
---|
790 | for (w = list; w; w = w->next)
|
---|
791 | fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
|
---|
792 | fprintf (stderr, " ))\n");
|
---|
793 | }
|
---|
794 | #endif
|
---|
795 |
|
---|
796 | void
|
---|
797 | print_simple_command (simple_command)
|
---|
798 | SIMPLE_COM *simple_command;
|
---|
799 | {
|
---|
800 | command_print_word_list (simple_command->words, " ");
|
---|
801 |
|
---|
802 | if (simple_command->redirects)
|
---|
803 | {
|
---|
804 | cprintf (" ");
|
---|
805 | print_redirection_list (simple_command->redirects);
|
---|
806 | }
|
---|
807 | }
|
---|
808 |
|
---|
809 | static void
|
---|
810 | print_redirection_list (redirects)
|
---|
811 | REDIRECT *redirects;
|
---|
812 | {
|
---|
813 | REDIRECT *heredocs, *hdtail, *newredir;
|
---|
814 |
|
---|
815 | heredocs = (REDIRECT *)NULL;
|
---|
816 | hdtail = heredocs;
|
---|
817 |
|
---|
818 | was_heredoc = 0;
|
---|
819 | while (redirects)
|
---|
820 | {
|
---|
821 | /* Defer printing the here documents until we've printed the
|
---|
822 | rest of the redirections. */
|
---|
823 | if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
|
---|
824 | {
|
---|
825 | newredir = copy_redirect (redirects);
|
---|
826 | newredir->next = (REDIRECT *)NULL;
|
---|
827 | if (heredocs)
|
---|
828 | {
|
---|
829 | hdtail->next = newredir;
|
---|
830 | hdtail = newredir;
|
---|
831 | }
|
---|
832 | else
|
---|
833 | hdtail = heredocs = newredir;
|
---|
834 | }
|
---|
835 | else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
|
---|
836 | {
|
---|
837 | /* Temporarily translate it as the execution code does. */
|
---|
838 | redirects->instruction = r_err_and_out;
|
---|
839 | print_redirection (redirects);
|
---|
840 | redirects->instruction = r_duplicating_output_word;
|
---|
841 | }
|
---|
842 | else
|
---|
843 | print_redirection (redirects);
|
---|
844 |
|
---|
845 | redirects = redirects->next;
|
---|
846 | if (redirects)
|
---|
847 | cprintf (" ");
|
---|
848 | }
|
---|
849 |
|
---|
850 | /* Now that we've printed all the other redirections (on one line),
|
---|
851 | print the here documents. */
|
---|
852 | if (heredocs)
|
---|
853 | {
|
---|
854 | cprintf (" ");
|
---|
855 | for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
|
---|
856 | {
|
---|
857 | print_redirection (hdtail);
|
---|
858 | cprintf ("\n");
|
---|
859 | }
|
---|
860 | dispose_redirects (heredocs);
|
---|
861 | was_heredoc = 1;
|
---|
862 | }
|
---|
863 | }
|
---|
864 |
|
---|
865 | static void
|
---|
866 | print_redirection (redirect)
|
---|
867 | REDIRECT *redirect;
|
---|
868 | {
|
---|
869 | int kill_leading, redirector, redir_fd;
|
---|
870 | WORD_DESC *redirectee;
|
---|
871 |
|
---|
872 | kill_leading = 0;
|
---|
873 | redirectee = redirect->redirectee.filename;
|
---|
874 | redirector = redirect->redirector;
|
---|
875 | redir_fd = redirect->redirectee.dest;
|
---|
876 |
|
---|
877 | switch (redirect->instruction)
|
---|
878 | {
|
---|
879 | case r_output_direction:
|
---|
880 | if (redirector != 1)
|
---|
881 | cprintf ("%d", redirector);
|
---|
882 | cprintf (">%s", redirectee->word);
|
---|
883 | break;
|
---|
884 |
|
---|
885 | case r_input_direction:
|
---|
886 | if (redirector != 0)
|
---|
887 | cprintf ("%d", redirector);
|
---|
888 | cprintf ("<%s", redirectee->word);
|
---|
889 | break;
|
---|
890 |
|
---|
891 | case r_inputa_direction: /* Redirection created by the shell. */
|
---|
892 | cprintf ("&");
|
---|
893 | break;
|
---|
894 |
|
---|
895 | case r_appending_to:
|
---|
896 | if (redirector != 1)
|
---|
897 | cprintf ("%d", redirector);
|
---|
898 | cprintf (">>%s", redirectee->word);
|
---|
899 | break;
|
---|
900 |
|
---|
901 | case r_deblank_reading_until:
|
---|
902 | kill_leading++;
|
---|
903 | /* ... */
|
---|
904 | case r_reading_until:
|
---|
905 | if (redirector != 0)
|
---|
906 | cprintf ("%d", redirector);
|
---|
907 | /* If the here document delimiter is quoted, single-quote it. */
|
---|
908 | if (redirect->redirectee.filename->flags & W_QUOTED)
|
---|
909 | {
|
---|
910 | char *x;
|
---|
911 | x = sh_single_quote (redirect->here_doc_eof);
|
---|
912 | cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
|
---|
913 | free (x);
|
---|
914 | }
|
---|
915 | else
|
---|
916 | cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
|
---|
917 | cprintf ("%s%s",
|
---|
918 | redirect->redirectee.filename->word, redirect->here_doc_eof);
|
---|
919 | break;
|
---|
920 |
|
---|
921 | case r_reading_string:
|
---|
922 | if (redirector != 0)
|
---|
923 | cprintf ("%d", redirector);
|
---|
924 | if (ansic_shouldquote (redirect->redirectee.filename->word))
|
---|
925 | {
|
---|
926 | char *x;
|
---|
927 | x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
|
---|
928 | cprintf ("<<< %s", x);
|
---|
929 | free (x);
|
---|
930 | }
|
---|
931 | else
|
---|
932 | cprintf ("<<< %s", redirect->redirectee.filename->word);
|
---|
933 | break;
|
---|
934 |
|
---|
935 | case r_duplicating_input:
|
---|
936 | cprintf ("%d<&%d", redirector, redir_fd);
|
---|
937 | break;
|
---|
938 |
|
---|
939 | case r_duplicating_output:
|
---|
940 | cprintf ("%d>&%d", redirector, redir_fd);
|
---|
941 | break;
|
---|
942 |
|
---|
943 | case r_duplicating_input_word:
|
---|
944 | cprintf ("%d<&%s", redirector, redirectee->word);
|
---|
945 | break;
|
---|
946 |
|
---|
947 | case r_duplicating_output_word:
|
---|
948 | cprintf ("%d>&%s", redirector, redirectee->word);
|
---|
949 | break;
|
---|
950 |
|
---|
951 | case r_move_input:
|
---|
952 | cprintf ("%d<&%d-", redirector, redir_fd);
|
---|
953 | break;
|
---|
954 |
|
---|
955 | case r_move_output:
|
---|
956 | cprintf ("%d>&%d-", redirector, redir_fd);
|
---|
957 | break;
|
---|
958 |
|
---|
959 | case r_move_input_word:
|
---|
960 | cprintf ("%d<&%s-", redirector, redirectee->word);
|
---|
961 | break;
|
---|
962 |
|
---|
963 | case r_move_output_word:
|
---|
964 | cprintf ("%d>&%s-", redirector, redirectee->word);
|
---|
965 | break;
|
---|
966 |
|
---|
967 | case r_close_this:
|
---|
968 | cprintf ("%d>&-", redirector);
|
---|
969 | break;
|
---|
970 |
|
---|
971 | case r_err_and_out:
|
---|
972 | cprintf (">&%s", redirectee->word);
|
---|
973 | break;
|
---|
974 |
|
---|
975 | case r_input_output:
|
---|
976 | if (redirector != 1)
|
---|
977 | cprintf ("%d", redirector);
|
---|
978 | cprintf ("<>%s", redirectee->word);
|
---|
979 | break;
|
---|
980 |
|
---|
981 | case r_output_force:
|
---|
982 | if (redirector != 1)
|
---|
983 | cprintf ("%d", redirector);
|
---|
984 | cprintf (">|%s", redirectee->word);
|
---|
985 | break;
|
---|
986 | }
|
---|
987 | }
|
---|
988 |
|
---|
989 | static void
|
---|
990 | reset_locals ()
|
---|
991 | {
|
---|
992 | inside_function_def = 0;
|
---|
993 | indentation = 0;
|
---|
994 | }
|
---|
995 |
|
---|
996 | static void
|
---|
997 | print_function_def (func)
|
---|
998 | FUNCTION_DEF *func;
|
---|
999 | {
|
---|
1000 | COMMAND *cmdcopy;
|
---|
1001 | REDIRECT *func_redirects;
|
---|
1002 |
|
---|
1003 | func_redirects = NULL;
|
---|
1004 | cprintf ("function %s () \n", func->name->word);
|
---|
1005 | add_unwind_protect (reset_locals, 0);
|
---|
1006 |
|
---|
1007 | indent (indentation);
|
---|
1008 | cprintf ("{ \n");
|
---|
1009 |
|
---|
1010 | inside_function_def++;
|
---|
1011 | indentation += indentation_amount;
|
---|
1012 |
|
---|
1013 | cmdcopy = copy_command (func->command);
|
---|
1014 | if (cmdcopy->type == cm_group)
|
---|
1015 | {
|
---|
1016 | func_redirects = cmdcopy->redirects;
|
---|
1017 | cmdcopy->redirects = (REDIRECT *)NULL;
|
---|
1018 | }
|
---|
1019 | make_command_string_internal (cmdcopy->type == cm_group
|
---|
1020 | ? cmdcopy->value.Group->command
|
---|
1021 | : cmdcopy);
|
---|
1022 |
|
---|
1023 | remove_unwind_protect ();
|
---|
1024 | indentation -= indentation_amount;
|
---|
1025 | inside_function_def--;
|
---|
1026 |
|
---|
1027 | if (func_redirects)
|
---|
1028 | { /* { */
|
---|
1029 | newline ("} ");
|
---|
1030 | print_redirection_list (func_redirects);
|
---|
1031 | cmdcopy->redirects = func_redirects;
|
---|
1032 | }
|
---|
1033 | else
|
---|
1034 | newline ("}");
|
---|
1035 |
|
---|
1036 | dispose_command (cmdcopy);
|
---|
1037 | }
|
---|
1038 |
|
---|
1039 | /* Return the string representation of the named function.
|
---|
1040 | NAME is the name of the function.
|
---|
1041 | COMMAND is the function body. It should be a GROUP_COM.
|
---|
1042 | MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
|
---|
1043 | */
|
---|
1044 | char *
|
---|
1045 | named_function_string (name, command, multi_line)
|
---|
1046 | char *name;
|
---|
1047 | COMMAND *command;
|
---|
1048 | int multi_line;
|
---|
1049 | {
|
---|
1050 | char *result;
|
---|
1051 | int old_indent, old_amount;
|
---|
1052 | COMMAND *cmdcopy;
|
---|
1053 | REDIRECT *func_redirects;
|
---|
1054 |
|
---|
1055 | old_indent = indentation;
|
---|
1056 | old_amount = indentation_amount;
|
---|
1057 | command_string_index = was_heredoc = 0;
|
---|
1058 |
|
---|
1059 | if (name && *name)
|
---|
1060 | cprintf ("%s ", name);
|
---|
1061 |
|
---|
1062 | cprintf ("() ");
|
---|
1063 |
|
---|
1064 | if (multi_line == 0)
|
---|
1065 | {
|
---|
1066 | indentation = 1;
|
---|
1067 | indentation_amount = 0;
|
---|
1068 | }
|
---|
1069 | else
|
---|
1070 | {
|
---|
1071 | cprintf ("\n");
|
---|
1072 | indentation += indentation_amount;
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | inside_function_def++;
|
---|
1076 |
|
---|
1077 | cprintf (multi_line ? "{ \n" : "{ ");
|
---|
1078 |
|
---|
1079 | cmdcopy = copy_command (command);
|
---|
1080 | /* Take any redirections specified in the function definition (which should
|
---|
1081 | apply to the function as a whole) and save them for printing later. */
|
---|
1082 | func_redirects = (REDIRECT *)NULL;
|
---|
1083 | if (cmdcopy->type == cm_group)
|
---|
1084 | {
|
---|
1085 | func_redirects = cmdcopy->redirects;
|
---|
1086 | cmdcopy->redirects = (REDIRECT *)NULL;
|
---|
1087 | }
|
---|
1088 | make_command_string_internal (cmdcopy->type == cm_group
|
---|
1089 | ? cmdcopy->value.Group->command
|
---|
1090 | : cmdcopy);
|
---|
1091 |
|
---|
1092 | indentation = old_indent;
|
---|
1093 | indentation_amount = old_amount;
|
---|
1094 | inside_function_def--;
|
---|
1095 |
|
---|
1096 | if (func_redirects)
|
---|
1097 | { /* { */
|
---|
1098 | newline ("} ");
|
---|
1099 | print_redirection_list (func_redirects);
|
---|
1100 | cmdcopy->redirects = func_redirects;
|
---|
1101 | }
|
---|
1102 | else
|
---|
1103 | newline ("}");
|
---|
1104 |
|
---|
1105 | result = the_printed_command;
|
---|
1106 |
|
---|
1107 | if (!multi_line)
|
---|
1108 | {
|
---|
1109 | #if 0
|
---|
1110 | register int i;
|
---|
1111 | for (i = 0; result[i]; i++)
|
---|
1112 | if (result[i] == '\n')
|
---|
1113 | {
|
---|
1114 | strcpy (result + i, result + i + 1);
|
---|
1115 | --i;
|
---|
1116 | }
|
---|
1117 | #else
|
---|
1118 | if (result[2] == '\n') /* XXX -- experimental */
|
---|
1119 | strcpy (result + 2, result + 3);
|
---|
1120 | #endif
|
---|
1121 | }
|
---|
1122 |
|
---|
1123 | dispose_command (cmdcopy);
|
---|
1124 |
|
---|
1125 | return (result);
|
---|
1126 | }
|
---|
1127 |
|
---|
1128 | static void
|
---|
1129 | newline (string)
|
---|
1130 | char *string;
|
---|
1131 | {
|
---|
1132 | cprintf ("\n");
|
---|
1133 | indent (indentation);
|
---|
1134 | if (string && *string)
|
---|
1135 | cprintf ("%s", string);
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 | static char *indentation_string;
|
---|
1139 | static int indentation_size;
|
---|
1140 |
|
---|
1141 | static void
|
---|
1142 | indent (amount)
|
---|
1143 | int amount;
|
---|
1144 | {
|
---|
1145 | register int i;
|
---|
1146 |
|
---|
1147 | RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
|
---|
1148 |
|
---|
1149 | for (i = 0; amount > 0; amount--)
|
---|
1150 | indentation_string[i++] = ' ';
|
---|
1151 | indentation_string[i] = '\0';
|
---|
1152 | cprintf (indentation_string);
|
---|
1153 | }
|
---|
1154 |
|
---|
1155 | static void
|
---|
1156 | semicolon ()
|
---|
1157 | {
|
---|
1158 | if (command_string_index > 0 &&
|
---|
1159 | (the_printed_command[command_string_index - 1] == '&' ||
|
---|
1160 | the_printed_command[command_string_index - 1] == '\n'))
|
---|
1161 | return;
|
---|
1162 | cprintf (";");
|
---|
1163 | }
|
---|
1164 |
|
---|
1165 | /* How to make the string. */
|
---|
1166 | static void
|
---|
1167 | #if defined (PREFER_STDARG)
|
---|
1168 | cprintf (const char *control, ...)
|
---|
1169 | #else
|
---|
1170 | cprintf (control, va_alist)
|
---|
1171 | const char *control;
|
---|
1172 | va_dcl
|
---|
1173 | #endif
|
---|
1174 | {
|
---|
1175 | register const char *s;
|
---|
1176 | char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
|
---|
1177 | int digit_arg, arg_len, c;
|
---|
1178 | va_list args;
|
---|
1179 |
|
---|
1180 | SH_VA_START (args, control);
|
---|
1181 |
|
---|
1182 | arg_len = strlen (control);
|
---|
1183 | the_printed_command_resize (arg_len + 1);
|
---|
1184 |
|
---|
1185 | char_arg[1] = '\0';
|
---|
1186 | s = control;
|
---|
1187 | while (s && *s)
|
---|
1188 | {
|
---|
1189 | c = *s++;
|
---|
1190 | argp = (char *)NULL;
|
---|
1191 | if (c != '%' || !*s)
|
---|
1192 | {
|
---|
1193 | char_arg[0] = c;
|
---|
1194 | argp = char_arg;
|
---|
1195 | arg_len = 1;
|
---|
1196 | }
|
---|
1197 | else
|
---|
1198 | {
|
---|
1199 | c = *s++;
|
---|
1200 | switch (c)
|
---|
1201 | {
|
---|
1202 | case '%':
|
---|
1203 | char_arg[0] = c;
|
---|
1204 | argp = char_arg;
|
---|
1205 | arg_len = 1;
|
---|
1206 | break;
|
---|
1207 |
|
---|
1208 | case 's':
|
---|
1209 | argp = va_arg (args, char *);
|
---|
1210 | arg_len = strlen (argp);
|
---|
1211 | break;
|
---|
1212 |
|
---|
1213 | case 'd':
|
---|
1214 | /* Represent an out-of-range file descriptor with an out-of-range
|
---|
1215 | integer value. We can do this because the only use of `%d' in
|
---|
1216 | the calls to cprintf is to output a file descriptor number for
|
---|
1217 | a redirection. */
|
---|
1218 | digit_arg = va_arg (args, int);
|
---|
1219 | if (digit_arg < 0)
|
---|
1220 | {
|
---|
1221 | sprintf (intbuf, "%u", (unsigned)-1);
|
---|
1222 | argp = intbuf;
|
---|
1223 | }
|
---|
1224 | else
|
---|
1225 | argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
|
---|
1226 | arg_len = strlen (argp);
|
---|
1227 | break;
|
---|
1228 |
|
---|
1229 | case 'c':
|
---|
1230 | char_arg[0] = va_arg (args, int);
|
---|
1231 | argp = char_arg;
|
---|
1232 | arg_len = 1;
|
---|
1233 | break;
|
---|
1234 |
|
---|
1235 | default:
|
---|
1236 | programming_error (_("cprintf: `%c': invalid format character"), c);
|
---|
1237 | /*NOTREACHED*/
|
---|
1238 | }
|
---|
1239 | }
|
---|
1240 |
|
---|
1241 | if (argp && arg_len)
|
---|
1242 | {
|
---|
1243 | the_printed_command_resize (arg_len + 1);
|
---|
1244 | FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
|
---|
1245 | command_string_index += arg_len;
|
---|
1246 | }
|
---|
1247 | }
|
---|
1248 |
|
---|
1249 | the_printed_command[command_string_index] = '\0';
|
---|
1250 | }
|
---|
1251 |
|
---|
1252 | /* Ensure that there is enough space to stuff LENGTH characters into
|
---|
1253 | THE_PRINTED_COMMAND. */
|
---|
1254 | static void
|
---|
1255 | the_printed_command_resize (length)
|
---|
1256 | int length;
|
---|
1257 | {
|
---|
1258 | if (the_printed_command == 0)
|
---|
1259 | {
|
---|
1260 | the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
|
---|
1261 | the_printed_command = (char *)xmalloc (the_printed_command_size);
|
---|
1262 | command_string_index = 0;
|
---|
1263 | }
|
---|
1264 | else if ((command_string_index + length) >= the_printed_command_size)
|
---|
1265 | {
|
---|
1266 | int new;
|
---|
1267 | new = command_string_index + length + 1;
|
---|
1268 |
|
---|
1269 | /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
|
---|
1270 | new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
|
---|
1271 | the_printed_command_size = new;
|
---|
1272 |
|
---|
1273 | the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
|
---|
1274 | }
|
---|
1275 | }
|
---|
1276 |
|
---|
1277 | #if defined (HAVE_VPRINTF)
|
---|
1278 | /* ``If vprintf is available, you may assume that vfprintf and vsprintf are
|
---|
1279 | also available.'' */
|
---|
1280 |
|
---|
1281 | static void
|
---|
1282 | #if defined (PREFER_STDARG)
|
---|
1283 | xprintf (const char *format, ...)
|
---|
1284 | #else
|
---|
1285 | xprintf (format, va_alist)
|
---|
1286 | const char *format;
|
---|
1287 | va_dcl
|
---|
1288 | #endif
|
---|
1289 | {
|
---|
1290 | va_list args;
|
---|
1291 |
|
---|
1292 | SH_VA_START (args, format);
|
---|
1293 |
|
---|
1294 | vfprintf (stdout, format, args);
|
---|
1295 | va_end (args);
|
---|
1296 | }
|
---|
1297 |
|
---|
1298 | #else
|
---|
1299 |
|
---|
1300 | static void
|
---|
1301 | xprintf (format, arg1, arg2, arg3, arg4, arg5)
|
---|
1302 | const char *format;
|
---|
1303 | {
|
---|
1304 | printf (format, arg1, arg2, arg3, arg4, arg5);
|
---|
1305 | }
|
---|
1306 |
|
---|
1307 | #endif /* !HAVE_VPRINTF */
|
---|