2 * profile.c - gawk bytecode pretty-printer with counts
6 * Copyright (C) 1999-2013 the Free Software Foundation, Inc.
8 * This file is part of GAWK, the GNU implementation of the
9 * AWK Programming Language.
11 * GAWK is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * GAWK is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header);
29 static void pp_parenthesize(NODE *n);
30 static void parenthesize(int type, NODE *left, NODE *right);
31 static char *pp_list(int nargs, const char *paren, const char *delim);
32 static char *pp_group3(const char *s1, const char *s2, const char *s3);
33 static char *pp_concat(int nargs);
34 static bool is_binary(int type);
35 static bool is_scalar(int type);
36 static int prec_level(int type);
37 static void pp_push(int type, char *s, int flag);
38 static NODE *pp_pop(void);
39 static void pp_free(NODE *n);
40 const char *redir2str(int redirtype);
43 #define pp_len sub.nodep.reserved
49 static RETSIGTYPE dump_and_exit(int signum) ATTRIBUTE_NORETURN;
50 static RETSIGTYPE just_dump(int signum);
52 /* pretty printing related functions and variables */
54 static NODE *pp_stack = NULL;
55 static NODE *func_params; /* function parameters */
56 static FILE *prof_fp; /* where to send the profile */
58 static long indent_level = 0;
63 /* set_prof_file --- set the output file for profiling or pretty-printing */
66 set_prof_file(const char *file)
69 prof_fp = fopen(file, "w");
70 if (prof_fp == NULL) {
71 warning(_("could not open `%s' for writing: %s"),
72 file, strerror(errno));
73 warning(_("sending profile to standard error"));
78 /* init_profiling_signals --- set up signal handling for gawk --profile */
81 init_profiling_signals()
84 signal(SIGINT, dump_and_exit);
85 signal(SIGQUIT, just_dump);
86 #else /* !__DJGPP__ */
88 signal(SIGHUP, dump_and_exit);
91 signal(SIGUSR1, just_dump);
93 #endif /* !__DJGPP__ */
96 /* indent --- print out enough tabs */
104 fprintf(prof_fp, "\t");
106 fprintf(prof_fp, "%6ld ", count);
108 assert(indent_level >= 0);
109 for (i = 0; i < indent_level; i++)
110 fprintf(prof_fp, "\t");
113 /* indent_in --- increase the level, with error checking */
118 assert(indent_level >= 0);
122 /* indent_out --- decrease the level, with error checking */
128 assert(indent_level >= 0);
131 /* pp_push --- push a pretty printed string onto the stack */
134 pp_push(int type, char *s, int flag)
139 n->pp_len = strlen(s);
142 n->pp_next = pp_stack;
146 /* pp_pop --- pop a pretty printed string off the stack */
153 pp_stack = n->pp_next;
157 /* pp_free --- release a pretty printed node */
162 if ((n->flags & CAN_FREE) != 0)
167 /* pprint --- pretty print a program segment */
170 pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
180 static int rule_count[MAXRULE];
182 for (pc = startp; pc != endp; pc = pc->nexti) {
183 if (pc->source_line > 0)
184 sourceline = pc->source_line;
186 switch (pc->opcode) {
188 source = pc->source_file;
192 if (! rule_count[rule]++)
193 fprintf(prof_fp, _("\t# %s block(s)\n\n"), ruletab[rule]);
194 fprintf(prof_fp, "\t%s {\n", ruletab[rule]);
195 ip = (pc + 1)->firsti;
197 if (! rule_count[rule]++)
198 fprintf(prof_fp, _("\t# Rule(s)\n\n"));
200 indent(ip->exec_count);
201 if (ip != (pc + 1)->firsti) { /* non-empty pattern */
202 pprint(ip->nexti, (pc + 1)->firsti, false);
204 fprintf(prof_fp, "%s {", t1->pp_str);
206 ip = (pc + 1)->firsti;
208 if (do_profile && ip->exec_count > 0)
209 fprintf(prof_fp, " # %ld", ip->exec_count);
211 fprintf(prof_fp, "\n");
213 fprintf(prof_fp, "{\n");
214 ip = (pc + 1)->firsti;
219 pprint(ip, (pc + 1)->lasti, false);
221 fprintf(prof_fp, "\t}\n\n");
222 pc = (pc + 1)->lasti;
229 memset(rule_count, 0, MAXRULE * sizeof(int));
234 if (m == Nnull_string) /* optional return or exit value; don't print 0 or "" */
235 pp_push(pc->opcode, m->stptr, DONT_FREE);
236 else if ((m->flags & NUMBER) != 0)
237 pp_push(pc->opcode, pp_number(m), CAN_FREE);
239 str = pp_string(m->stptr, m->stlen, '"');
240 if ((m->flags & INTLSTR) != 0) {
242 str = pp_group3("_", tmp, "");
245 pp_push(pc->opcode, str, CAN_FREE);
250 if (pc->initval != NULL)
251 pp_push(Op_push_i, pp_node(pc->initval), CAN_FREE);
254 case Op_assign_concat:
262 case Node_param_list:
263 pp_push(pc->opcode, func_params[m->param_cnt].param, DONT_FREE);
269 if (m->vname != NULL)
270 pp_push(pc->opcode, m->vname, DONT_FREE);
272 fatal(_("internal error: %s with null vname"),
273 nodetype2str(m->type));
280 switch (pc->opcode) {
282 t2 = pp_pop(); /* l.h.s. */
283 t1 = pp_pop(); /* r.h.s. */
284 fprintf(prof_fp, "%s%s%s", t2->pp_str, op2str(pc->opcode), t1->pp_str);
288 t1 = pp_pop(); /* array */
289 tmp = pp_list(pc->expr_count, op2str(Op_subscript), ", "); /*subscript*/
290 t2 = pp_pop(); /* r.h.s. */
291 fprintf(prof_fp, "%s%s%s%s", t1->pp_str, tmp,
292 op2str(pc->opcode), t2->pp_str);
296 case Op_assign_concat:
297 t2 = pp_pop(); /* l.h.s. */
299 tmp = pp_group3(t2->pp_str, op2str(Op_concat), t1->pp_str);
300 fprintf(prof_fp, "%s%s%s", t2->pp_str, op2str(Op_assign), tmp);
306 fprintf(prof_fp, "\n");
315 case Op_subscript_lhs:
317 tmp = pp_list(pc->sub_count, op2str(pc->opcode), ", ");
319 str = pp_group3(t1->pp_str, tmp, "");
322 pp_push(pc->opcode, str, CAN_FREE);
327 pprint(pc->nexti, pc->target_jmp, in_for_header);
330 parenthesize(pc->opcode, t1, t2);
331 str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
334 pp_push(pc->opcode, str, CAN_FREE);
346 if (prec_level(pc->opcode) > prec_level(t1->type)
347 && is_binary(t1->type)) /* (a - b) * 1 */
349 if ((m->flags & NUMBER) != 0)
352 tmp = pp_string(m->stptr, m->stlen, '"');
353 str = pp_group3(t1->pp_str, op2str(pc->opcode), tmp);
356 pp_push(pc->opcode, str, CAN_FREE);
373 parenthesize(pc->opcode, t1, t2);
374 str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
377 pp_push(pc->opcode, str, CAN_FREE);
380 case Op_preincrement:
381 case Op_predecrement:
382 case Op_postincrement:
383 case Op_postdecrement:
385 if (pc->opcode == Op_preincrement || pc->opcode == Op_predecrement)
386 str = pp_group3(op2str(pc->opcode), t1->pp_str, "");
388 str = pp_group3(t1->pp_str, op2str(pc->opcode), "");
390 pp_push(pc->opcode, str, CAN_FREE);
394 case Op_field_spec_lhs:
398 if (is_binary(t1->type))
401 /* optypes table (eval.c) includes space after ! */
402 str = pp_group3(op2str(pc->opcode), t1->pp_str, "");
404 pp_push(pc->opcode, str, CAN_FREE);
409 case Op_assign_minus:
410 case Op_assign_times:
411 case Op_assign_quotient:
414 t2 = pp_pop(); /* l.h.s. */
416 str = pp_group3(t2->pp_str, op2str(pc->opcode), t1->pp_str);
419 pp_push(pc->opcode, str, CAN_FREE);
423 t1 = pp_pop(); /* field num */
424 if (is_binary(t1->type))
426 t2 = pp_pop(); /* r.h.s. */
427 fprintf(prof_fp, "$%s%s%s", t1->pp_str, op2str(pc->opcode), t2->pp_str);
431 fprintf(prof_fp, "\n");
435 str = pp_concat(pc->expr_count);
436 pp_push(Op_concat, str, CAN_FREE);
444 if (pc->expr_count > 0) {
446 sub = pp_list(pc->expr_count, NULL, pc->expr_count > 1 ? "][" : ", ");
447 fprintf(prof_fp, "%s %s[%s]", op2str(Op_K_delete), array, sub);
450 fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array);
452 fprintf(prof_fp, "\n");
457 case Op_K_delete_loop:
458 /* Efficency hack not in effect because of exec_count instruction */
467 if (pc->expr_count > 1) {
468 sub = pp_list(pc->expr_count, "()", ", ");
469 str = pp_group3(sub, op2str(Op_in_array), array);
473 if (prec_level(t2->type) < prec_level(Op_in_array)) {
477 str = pp_group3(sub, op2str(Op_in_array), array);
481 pp_push(Op_in_array, str, CAN_FREE);
487 case Op_field_assign:
488 case Op_subscript_assign:
489 case Op_arrayfor_init:
490 case Op_arrayfor_incr:
491 case Op_arrayfor_final:
502 case Op_after_beginfile:
503 case Op_after_endfile:
508 const char *fname = "sub";
509 if ((pc->sub_flags & GSUB) != 0)
511 else if ((pc->sub_flags & GENSUB) != 0)
513 tmp = pp_list(pc->expr_count, "()", ", ");
514 str = pp_group3(fname, tmp, "");
516 pp_push(Op_sub_builtin, str, CAN_FREE);
524 if (pc->opcode == Op_builtin)
525 fname = getfname(pc->builtin);
527 fname = (pc + 1)->func_name;
529 if (pc->expr_count > 0) {
530 tmp = pp_list(pc->expr_count, "()", ", ");
531 str = pp_group3(fname, tmp, "");
534 str = pp_group3(fname, "()", "");
535 pp_push(Op_builtin, str, CAN_FREE);
537 fatal(_("internal error: builtin with null fname"));
544 if (pc->opcode == Op_K_print_rec)
545 tmp = pp_group3(" ", op2str(Op_field_spec), "0");
546 else if (pc->redir_type != 0)
547 tmp = pp_list(pc->expr_count, "()", ", ");
549 tmp = pp_list(pc->expr_count, " ", ", ");
550 tmp[strlen(tmp) - 1] = '\0'; /* remove trailing space */
553 if (pc->redir_type != 0) {
555 if (is_binary(t1->type))
557 fprintf(prof_fp, "%s%s%s%s", op2str(pc->opcode),
558 tmp, redir2str(pc->redir_type), t1->pp_str);
561 fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
564 fprintf(prof_fp, "\n");
568 if (pc->memory->type != Node_regex)
574 NODE *re = pc->memory->re_exp;
575 str = pp_string(re->stptr, re->stlen, '/');
576 pp_push(pc->opcode, str, CAN_FREE);
585 if (is_binary(t1->type))
589 if (m->type == Node_dynregex) {
592 if (is_binary(t2->type))
595 str = pp_group3(txt, op2str(pc->opcode), restr);
598 NODE *re = m->re_exp;
599 restr = pp_string(re->stptr, re->stlen, '/');
600 str = pp_group3(txt, op2str(pc->opcode), restr);
604 pp_push(pc->opcode, str, CAN_FREE);
609 case Op_K_getline_redir:
612 tmp = pp_group3(op2str(Op_K_getline), " ", t1->pp_str);
615 tmp = pp_group3(op2str(Op_K_getline), "", "");
617 if (pc->redir_type != 0) {
618 int before = (pc->redir_type == redirect_pipein
619 || pc->redir_type == redirect_twoway);
622 if (is_binary(t2->type))
625 str = pp_group3(t2->pp_str, redir2str(pc->redir_type), tmp);
627 str = pp_group3(tmp, redir2str(pc->redir_type), t2->pp_str);
632 pp_push(pc->opcode, str, CAN_FREE);
635 case Op_indirect_func_call:
638 char *fname = pc->func_name;
642 if (pc->opcode == Op_indirect_func_call)
646 pcount = (pc + 1)->expr_count;
648 tmp = pp_list(pcount, "()", ", ");
649 str = pp_group3(pre, fname, tmp);
652 str = pp_group3(pre, fname, "()");
653 if (pc->opcode == Op_indirect_func_call) {
654 t1 = pp_pop(); /* indirect var */
657 pp_push(pc->opcode, str, CAN_FREE);
665 fprintf(prof_fp, "%s\n", op2str(pc->opcode));
671 if (is_binary(t1->type))
673 if (pc->source_line > 0) /* don't print implicit 'return' at end of function */
674 fprintf(prof_fp, "%s %s\n", op2str(pc->opcode), t1->pp_str);
680 fprintf(prof_fp, "%s", t1->pp_str);
682 fprintf(prof_fp, "\n");
688 pprint(pc->nexti, ip->condpair_left, false);
689 pprint(ip->condpair_left->nexti, ip->condpair_right, false);
692 str = pp_group3(t1->pp_str, ", ", t2->pp_str);
695 pp_push(Op_line_range, str, CAN_FREE);
696 pc = ip->condpair_right;
701 indent(ip->while_body->exec_count);
702 fprintf(prof_fp, "%s (", op2str(pc->opcode));
703 pprint(pc->nexti, ip->while_body, false);
705 fprintf(prof_fp, "%s) {\n", t1->pp_str);
708 pprint(ip->while_body->nexti, pc->target_break, false);
711 fprintf(prof_fp, "}\n");
712 pc = pc->target_break;
717 indent(pc->nexti->exec_count);
718 fprintf(prof_fp, "%s {\n", op2str(pc->opcode));
720 pprint(pc->nexti->nexti, ip->doloop_cond, false);
722 pprint(ip->doloop_cond, pc->target_break, false);
725 fprintf(prof_fp, "} %s (%s)\n", op2str(Op_K_while), t1->pp_str);
727 pc = pc->target_break;
732 indent(ip->forloop_body->exec_count);
733 fprintf(prof_fp, "%s (", op2str(pc->opcode));
734 pprint(pc->nexti, ip->forloop_cond, true);
735 fprintf(prof_fp, "; ");
737 if (ip->forloop_cond->opcode == Op_no_op &&
738 ip->forloop_cond->nexti == ip->forloop_body)
739 fprintf(prof_fp, "; ");
741 pprint(ip->forloop_cond, ip->forloop_body, true);
743 fprintf(prof_fp, "%s; ", t1->pp_str);
747 pprint(pc->target_continue, pc->target_break, true);
748 fprintf(prof_fp, ") {\n");
750 pprint(ip->forloop_body->nexti, pc->target_continue, false);
753 fprintf(prof_fp, "}\n");
754 pc = pc->target_break;
765 m = ip->forloop_cond->array_var;
766 if (m->type == Node_param_list)
767 item = func_params[m->param_cnt].param;
770 indent(ip->forloop_body->exec_count);
771 fprintf(prof_fp, "%s (%s%s%s) {\n", op2str(Op_K_arrayfor),
772 item, op2str(Op_in_array), array);
775 pprint(ip->forloop_body->nexti, pc->target_break, false);
778 fprintf(prof_fp, "}\n");
779 pc = pc->target_break;
785 fprintf(prof_fp, "%s (", op2str(pc->opcode));
786 pprint(pc->nexti, ip->switch_start, false);
788 fprintf(prof_fp, "%s) {\n", t1->pp_str);
790 pprint(ip->switch_start, ip->switch_end, false);
792 fprintf(prof_fp, "}\n");
793 pc = pc->target_break;
798 indent(pc->stmt_start->exec_count);
799 if (pc->opcode == Op_K_case) {
801 fprintf(prof_fp, "%s %s:\n", op2str(pc->opcode), t1->pp_str);
804 fprintf(prof_fp, "%s:\n", op2str(pc->opcode));
806 pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, false);
811 fprintf(prof_fp, "%s (", op2str(pc->opcode));
812 pprint(pc->nexti, pc->branch_if, false);
814 fprintf(prof_fp, "%s) {", t1->pp_str);
818 if (ip->exec_count > 0)
819 fprintf(prof_fp, " # %ld", ip->exec_count);
820 fprintf(prof_fp, "\n");
822 pprint(ip->nexti, pc->branch_else, false);
824 pc = pc->branch_else;
825 if (pc->nexti->opcode == Op_no_op) {
827 fprintf(prof_fp, "}\n");
832 fprintf(prof_fp, "} %s {\n", op2str(pc->opcode));
834 pprint(pc->nexti, pc->branch_end, false);
837 fprintf(prof_fp, "}\n");
846 pprint(pc->nexti, pc->branch_if, false);
848 pprint(ip->nexti, pc->branch_else, false);
849 ip = pc->branch_else->nexti;
852 assert(pc->opcode == Op_cond_exp);
853 pprint(pc->nexti, pc->branch_end, false);
859 len = f->pp_len + t->pp_len + cond->pp_len + 12;
860 emalloc(str, char *, len, "pprint");
861 sprintf(str, "(%s ? %s : %s)", cond->pp_str, t->pp_str, f->pp_str);
866 pp_push(Op_cond_exp, str, CAN_FREE);
873 indent(pc->exec_count);
885 /* pp_string_fp --- printy print a string to the fp */
888 * This routine concentrates string pretty printing in one place,
889 * so that it can be called from multiple places within gawk.
893 pp_string_fp(Func_print print_func, FILE *fp, const char *in_str,
894 size_t len, int delim, bool breaklines)
896 char *s = pp_string(in_str, len, delim);
899 const char *str = (const char *) s;
900 #define BREAKPOINT 70 /* arbitrary */
903 for (count = 0; slen > 0; slen--, str++) {
904 if (++count >= BREAKPOINT && breaklines) {
905 print_func(fp, "%c\n%c", delim, delim);
908 print_func(fp, "%c", *str);
914 /* just_dump --- dump the profile and function stack and keep going */
917 just_dump(int signum)
919 extern INSTRUCTION *code_block;
921 dump_prog(code_block);
923 dump_fcall_stack(prof_fp);
925 signal(signum, just_dump); /* for OLD Unix systems ... */
928 /* dump_and_exit --- dump the profile, the function stack, and exit */
931 dump_and_exit(int signum)
934 final_exit(EXIT_FAILURE);
937 /* print_lib_list --- print a list of all libraries loaded */
940 print_lib_list(FILE *prof_fp)
943 static bool printed_header = false;
945 for (s = srcfiles->next; s != srcfiles; s = s->next) {
946 if (s->stype == SRC_EXTLIB) {
947 if (! printed_header) {
948 printed_header = true;
949 fprintf(prof_fp, _("\t# Loaded extensions (-l and/or @load)\n\n"));
951 fprintf(prof_fp, "\t@load \"%s\"\n", s->src);
954 if (printed_header) /* we found some */
955 fprintf(prof_fp, "\n");
958 /* dump_prog --- dump the program */
961 * XXX: I am not sure it is right to have the strings in the dump
962 * be translated, but I'll leave it alone for now.
966 dump_prog(INSTRUCTION *code)
971 /* \n on purpose, with \n in ctime() output */
972 fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
973 print_lib_list(prof_fp);
974 pprint(code, NULL, false);
977 /* prec_level --- return the precedence of an operator, for paren tests */
991 case Op_subscript_lhs:
993 case Op_K_delete_loop:
998 case Op_field_spec_lhs:
1005 case Op_preincrement:
1006 case Op_predecrement:
1007 case Op_postincrement:
1008 case Op_postdecrement:
1011 case Op_unary_minus:
1030 case Op_assign_concat:
1043 case Op_K_getline_redir:
1060 case Op_assign_times:
1061 case Op_assign_quotient:
1063 case Op_assign_plus:
1064 case Op_assign_minus:
1073 /* is_scalar --- return true if scalar, false otherwise */
1086 case Op_subscript_lhs:
1090 case Op_field_spec_lhs:
1091 case Op_preincrement:
1092 case Op_predecrement:
1093 case Op_postincrement:
1094 case Op_postdecrement:
1095 case Op_unary_minus:
1104 /* is_binary --- return true if type represents a binary operator */
1129 case Op_assign_concat:
1133 case Op_assign_times:
1134 case Op_assign_quotient:
1136 case Op_assign_plus:
1137 case Op_assign_minus:
1143 case Op_K_getline_redir: /* sometimes */
1152 /* pp_parenthesize --- parenthesize an expression in stack */
1155 pp_parenthesize(NODE *sp)
1157 char *p = sp->pp_str;
1158 size_t len = sp->pp_len;
1160 emalloc(p, char *, len + 3, "pp_parenthesize");
1162 memcpy(p + 1, sp->pp_str, len);
1165 if ((sp->flags & CAN_FREE) != 0)
1169 sp->flags |= CAN_FREE;
1172 /* parenthesize --- parenthesize two nodes relative to parent node type */
1175 parenthesize(int type, NODE *left, NODE *right)
1177 int rprec = prec_level(right->type);
1178 int lprec = prec_level(left->type);
1179 int prec = prec_level(type);
1182 pp_parenthesize(left);
1184 pp_parenthesize(right);
1187 /* pp_string --- pretty format a string or regex constant */
1190 pp_string(const char *in_str, size_t len, int delim)
1192 static char str_escapes[] = "\a\b\f\n\r\t\v\\";
1193 static char str_printables[] = "abfnrtv\\";
1194 static char re_escapes[] = "\a\b\f\n\r\t\v";
1195 static char re_printables[] = "abfnrtv";
1200 const unsigned char *str = (const unsigned char *) in_str;
1202 char *obuf, *obufout;
1204 assert(delim == '"' || delim == '/');
1207 escapes = re_escapes;
1208 printables = re_printables;
1210 escapes = str_escapes;
1211 printables = str_printables;
1214 /* make space for something l big in the buffer */
1215 #define chksize(l) if ((l) > ofre) { \
1216 long olen = obufout - obuf; \
1217 erealloc(obuf, char *, osiz * 2, "pp_string"); \
1218 obufout = obuf + olen; \
1223 osiz = len + 3 + 2; /* initial size; 3 for delim + terminating null */
1224 emalloc(obuf, char *, osiz, "pp_string");
1229 for (; len > 0; len--, str++) {
1230 chksize(2); /* make space for 2 chars */
1231 if (delim != '/' && *str == delim) {
1234 } else if (*str == '\0') {
1241 } else if ((cp = strchr(escapes, *str)) != NULL) {
1244 *obufout++ = printables[i];
1245 /* NB: Deliberate use of lower-case versions. */
1246 } else if (isascii(*str) && isprint(*str)) {
1252 chksize(8); /* total available space is 10 */
1254 sprintf(obufout, "\\%03o", *str & 0xff);
1255 len = strlen(obufout);
1256 ofre += (10 - len); /* adjust free space count */
1267 /* pp_number --- pretty format a number */
1272 #define PP_PRECISION 6
1275 emalloc(str, char *, PP_PRECISION + 10, "pp_number");
1277 if (is_mpg_float(n))
1278 mpfr_sprintf(str, "%0.*R*g", PP_PRECISION, ROUND_MODE, n->mpg_numbr);
1279 else if (is_mpg_integer(n))
1280 mpfr_sprintf(str, "%Zd", n->mpg_i);
1283 sprintf(str, "%0.*g", PP_PRECISION, n->numbr);
1288 /* pp_node --- pretty format a node */
1293 if ((n->flags & NUMBER) != 0)
1294 return pp_number(n);
1295 return pp_string(n->stptr, n->stlen, '"');
1298 /* pp_list --- pretty print a list, with surrounding characters and separator */
1300 static NODE **pp_args = NULL;
1301 static int npp_args;
1304 pp_list(int nargs, const char *paren, const char *delim)
1312 if (pp_args == NULL) {
1314 emalloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_list");
1315 } else if (nargs > npp_args) {
1317 erealloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_list");
1320 delimlen = strlen(delim);
1322 for (i = 1; i <= nargs; i++) {
1323 r = pp_args[i] = pp_pop();
1324 len += r->pp_len + delimlen;
1326 if (paren != NULL) {
1327 assert(strlen(paren) == 2);
1331 emalloc(str, char *, len + 1, "pp_list");
1336 memcpy(s, r->pp_str, r->pp_len);
1339 for (i = nargs - 1; i > 0; i--) {
1341 memcpy(s, delim, delimlen);
1345 memcpy(s, r->pp_str, r->pp_len);
1355 /* pp_concat --- handle concatenation and correct parenthesizing of expressions */
1358 pp_concat(int nargs)
1363 static const size_t delimlen = 1; /* " " */
1367 if (pp_args == NULL) {
1369 emalloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_concat");
1370 } else if (nargs > npp_args) {
1372 erealloc(pp_args, NODE **, (nargs + 2) * sizeof(NODE *), "pp_concat");
1376 * items are on the stack in reverse order that they
1377 * will be printed to pop them off backwards.
1381 for (i = nargs; i >= 1; i--) {
1382 r = pp_args[i] = pp_pop();
1383 len += r->pp_len + delimlen + 2;
1386 emalloc(str, char *, len + 1, "pp_concat");
1390 for (i = 1; i < nargs; i++) {
1393 pl_l = prec_level(pp_args[i]->type);
1394 pl_r = prec_level(pp_args[i+1]->type);
1396 if (is_scalar(pp_args[i]->type) && is_scalar(pp_args[i+1]->type)) {
1397 memcpy(s, r->pp_str, r->pp_len);
1399 } else if (pl_l <= pl_r || is_scalar(pp_args[i+1]->type)) {
1401 memcpy(s, r->pp_str, r->pp_len);
1405 memcpy(s, r->pp_str, r->pp_len);
1415 pl_l = prec_level(pp_args[nargs-1]->type);
1416 pl_r = prec_level(pp_args[nargs]->type);
1418 if (pl_l >= pl_r && ! is_scalar(pp_args[nargs]->type)) {
1420 memcpy(s, r->pp_str, r->pp_len);
1424 memcpy(s, r->pp_str, r->pp_len);
1433 /* pp_group3 --- string together up to 3 strings */
1436 pp_group3(const char *s1, const char *s2, const char *s3)
1438 size_t len1, len2, len3, l;
1444 l = len1 + len2 + len3 + 2;
1445 emalloc(str, char *, l, "pp_group3");
1448 memcpy(s, s1, len1);
1452 memcpy(s, s2, len2);
1456 memcpy(s, s3, len3);
1463 /* pp_func --- pretty print a function */
1466 pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
1469 static bool first = true;
1475 fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n"));
1478 func = pc->func_body;
1479 fprintf(prof_fp, "\n");
1480 indent(pc->nexti->exec_count);
1481 fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);
1482 pcount = func->param_cnt;
1483 func_params = func->fparms;
1484 for (j = 0; j < pcount; j++) {
1485 fprintf(prof_fp, "%s", func_params[j].param);
1487 fprintf(prof_fp, ", ");
1489 fprintf(prof_fp, ")\n\t{\n");
1491 pprint(pc->nexti->nexti, NULL, false); /* function body */
1493 fprintf(prof_fp, "\t}\n");
1497 /* redir2str --- convert a redirection type into a printable value */
1500 redir2str(int redirtype)
1502 static const char *const redirtab[] = {
1504 " > ", /* redirect_output */
1505 " >> ", /* redirect_append */
1506 " | ", /* redirect_pipe */
1507 " | ", /* redirect_pipein */
1508 " < ", /* redirect_input */
1509 " |& ", /* redirect_twoway */
1512 if (redirtype < 0 || redirtype > redirect_twoway)
1513 fatal(_("redir2str: unknown redirection type %d"), redirtype);
1514 return redirtab[redirtype];