1/* print_command -- A way to make readable commands from a command tree. */ 2 3/* Copyright (C) 1989-2005 Free Software Foundation, Inc. 4 5This file is part of GNU Bash, the Bourne Again SHell. 6 7Bash is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12Bash is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License along 18with Bash; see the file COPYING. If not, write to the Free Software 19Foundation, 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 50extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */ 51#endif 52 53extern int indirection_level; 54 55static int indentation; 56static int indentation_amount = 4; 57 58#if defined (PREFER_STDARG) 59typedef void PFUNC __P((const char *, ...)); 60 61static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2))); 62static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2))); 63#else 64#define PFUNC VFunction 65static void cprintf (); 66static void xprintf (); 67#endif 68 69static void reset_locals __P((void)); 70static void newline __P((char *)); 71static void indent __P((int)); 72static void semicolon __P((void)); 73static void the_printed_command_resize __P((int)); 74 75static void make_command_string_internal __P((COMMAND *)); 76static void _print_word_list __P((WORD_LIST *, char *, PFUNC *)); 77static void command_print_word_list __P((WORD_LIST *, char *)); 78static void print_case_clauses __P((PATTERN_LIST *)); 79static void print_redirection_list __P((REDIRECT *)); 80static void print_redirection __P((REDIRECT *)); 81 82static void print_for_command __P((FOR_COM *)); 83#if defined (ARITH_FOR_COMMAND) 84static void print_arith_for_command __P((ARITH_FOR_COM *)); 85#endif 86#if defined (SELECT_COMMAND) 87static void print_select_command __P((SELECT_COM *)); 88#endif 89static void print_group_command __P((GROUP_COM *)); 90static void print_case_command __P((CASE_COM *)); 91static void print_while_command __P((WHILE_COM *)); 92static void print_until_command __P((WHILE_COM *)); 93static void print_until_or_while __P((WHILE_COM *, char *)); 94static void print_if_command __P((IF_COM *)); 95#if defined (COND_COMMAND) 96static void print_cond_node __P((COND_COM *)); 97#endif 98static void print_function_def __P((FUNCTION_DEF *)); 99 100#define PRINTED_COMMAND_INITIAL_SIZE 64 101#define PRINTED_COMMAND_GROW_SIZE 128 102 103char *the_printed_command = (char *)NULL; 104int the_printed_command_size = 0; 105int command_string_index = 0; 106 107/* Non-zero means the stuff being printed is inside of a function def. */ 108static int inside_function_def; 109static int skip_this_indent; 110static 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. */ 114static int group_command_nesting; 115 116/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */ 117static char indirection_string[100]; 118 119/* Print COMMAND (a command tree) on standard output. */ 120void 121print_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. */ 132char * 133make_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. */ 142static void 143make_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 301static 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 313void 314print_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 323char * 324indirection_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 375void 376xtrace_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. */ 407void 408xtrace_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 441static void 442command_print_word_list (list, separator) 443 WORD_LIST *list; 444 char *separator; 445{ 446 _print_word_list (list, separator, cprintf); 447} 448 449void 450print_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 457void 458xtrace_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 466static void 467print_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) 482static void 483print_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) 503void 504print_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 511void 512xtrace_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 520static void 521print_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 536static void 537print_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 573void 574print_case_command_head (case_command) 575 CASE_COM *case_command; 576{ 577 cprintf ("case %s in ", case_command->word->word); 578} 579 580void 581xtrace_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 588static void 589print_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 599static void 600print_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 618static void 619print_while_command (while_command) 620 WHILE_COM *while_command; 621{ 622 print_until_or_while (while_command, "while"); 623} 624 625static void 626print_until_command (while_command) 627 WHILE_COM *while_command; 628{ 629 print_until_or_while (while_command, "until"); 630} 631 632static void 633print_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 649static void 650print_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) 675void 676print_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) 686static void 687print_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 731void 732print_cond_command (cond) 733 COND_COM *cond; 734{ 735 cprintf ("[[ "); 736 print_cond_node (cond); 737 cprintf (" ]]"); 738} 739 740#ifdef DEBUG 741void 742debug_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 752void 753xtrace_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. */ 782void 783xtrace_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 796void 797print_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 809static void 810print_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 865static void 866print_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 989static void 990reset_locals () 991{ 992 inside_function_def = 0; 993 indentation = 0; 994} 995 996static void 997print_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 */ 1044char * 1045named_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 memmove(result + 2, result + 3, strlen(result+3)+1); 1120#endif 1121 } 1122 1123 dispose_command (cmdcopy); 1124 1125 return (result); 1126} 1127 1128static void 1129newline (string) 1130 char *string; 1131{ 1132 cprintf ("\n"); 1133 indent (indentation); 1134 if (string && *string) 1135 cprintf ("%s", string); 1136} 1137 1138static char *indentation_string; 1139static int indentation_size; 1140 1141static void 1142indent (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 1155static void 1156semicolon () 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. */ 1166static void 1167#if defined (PREFER_STDARG) 1168cprintf (const char *control, ...) 1169#else 1170cprintf (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. */ 1254static void 1255the_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 1281static void 1282#if defined (PREFER_STDARG) 1283xprintf (const char *format, ...) 1284#else 1285xprintf (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 1300static void 1301xprintf (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 */ 1308