summaryrefslogtreecommitdiff
path: root/profile.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2016-02-18 19:51:19 +0200
committerArnold D. Robbins <arnold@skeeve.com>2016-02-18 19:51:19 +0200
commitd72ecc9b4250d05b7ed635815515c3816fbde8fb (patch)
treeb63feca1c64d88bf23a3f8c70bd8c7c41cf583e0 /profile.c
parenteaec4c7a7ca63e0123ee8bddba7aef632c5e47ef (diff)
parent8635225f337cc96b28b411a7599962503059cc25 (diff)
downloadgawk-d72ecc9b4250d05b7ed635815515c3816fbde8fb.tar.gz
Merge branch 'gawk-4.1-stable'
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c109
1 files changed, 68 insertions, 41 deletions
diff --git a/profile.c b/profile.c
index d49dbbf9..ddc8b9b1 100644
--- a/profile.c
+++ b/profile.c
@@ -25,7 +25,7 @@
#include "awk.h"
-static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header);
+static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags);
static void end_line(INSTRUCTION *ip);
static void pp_parenthesize(NODE *n);
static void parenthesize(int type, NODE *left, NODE *right);
@@ -39,7 +39,6 @@ static bool is_scalar(int type);
static int prec_level(int type);
static void pp_push(int type, char *s, int flag);
static NODE *pp_pop(void);
-static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header);
static void print_comment(INSTRUCTION *pc, long in);
const char *redir2str(int redirtype);
@@ -61,9 +60,12 @@ static FILE *prof_fp; /* where to send the profile */
static long indent_level = 0;
-
#define SPACEOVER 0
+#define NO_PPRINT_FLAGS 0
+#define IN_FOR_HEADER 1
+#define IN_ELSE_IF 2
+
/* set_prof_file --- set the output file for profiling or pretty-printing */
void
@@ -193,7 +195,7 @@ pp_free(NODE *n)
/* pprint --- pretty print a program segment */
static void
-pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
+pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
{
INSTRUCTION *pc;
NODE *t1;
@@ -250,7 +252,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
ip1 = pc->nexti;
indent(ip1->exec_count);
if (ip1 != (pc + 1)->firsti) { /* non-empty pattern */
- pprint(ip1->nexti, (pc + 1)->firsti, false);
+ pprint(ip1->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS);
/* Allow for case where the "pattern" is just a comment */
if (ip1->nexti->nexti->nexti != (pc +1)->firsti
|| ip1->nexti->opcode != Op_comment) {
@@ -274,7 +276,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
ip1 = ip1->nexti;
}
indent_in();
- pprint(ip1, ip2, false);
+ pprint(ip1, ip2, NO_PPRINT_FLAGS);
indent_out();
if (do_profile)
indent(0);
@@ -363,7 +365,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
cleanup:
pp_free(t2);
pp_free(t1);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
end_line(pc);
break;
@@ -385,7 +387,7 @@ cleanup:
case Op_and:
case Op_or:
- pprint(pc->nexti, pc->target_jmp, in_for_header);
+ pprint(pc->nexti, pc->target_jmp, flags);
t2 = pp_pop();
t1 = pp_pop();
parenthesize(pc->opcode, t1, t2);
@@ -489,7 +491,7 @@ cleanup:
fprintf(prof_fp, "$%s%s%s", t1->pp_str, op2str(pc->opcode), t2->pp_str);
pp_free(t2);
pp_free(t1);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
end_line(pc);
break;
@@ -510,7 +512,7 @@ cleanup:
efree(sub);
} else
fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
end_line(pc);
pp_free(t1);
}
@@ -622,7 +624,7 @@ cleanup:
} else
fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
efree(tmp);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
end_line(pc);
break;
@@ -748,15 +750,15 @@ cleanup:
case Op_pop:
t1 = pp_pop();
fprintf(prof_fp, "%s", t1->pp_str);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
end_line(pc);
pp_free(t1);
break;
case Op_line_range:
ip1 = pc + 1;
- pprint(pc->nexti, ip1->condpair_left, false);
- pprint(ip1->condpair_left->nexti, ip1->condpair_right, false);
+ pprint(pc->nexti, ip1->condpair_left, NO_PPRINT_FLAGS);
+ pprint(ip1->condpair_left->nexti, ip1->condpair_right, NO_PPRINT_FLAGS);
t2 = pp_pop();
t1 = pp_pop();
str = pp_group3(t1->pp_str, ", ", t2->pp_str);
@@ -770,12 +772,12 @@ cleanup:
ip1 = pc + 1;
indent(ip1->while_body->exec_count);
fprintf(prof_fp, "%s (", op2str(pc->opcode));
- pprint(pc->nexti, ip1->while_body, false);
+ pprint(pc->nexti, ip1->while_body, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {\n", t1->pp_str);
pp_free(t1);
indent_in();
- pprint(ip1->while_body->nexti, pc->target_break, false);
+ pprint(ip1->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -787,9 +789,9 @@ cleanup:
indent(pc->nexti->exec_count);
fprintf(prof_fp, "%s {\n", op2str(pc->opcode));
indent_in();
- pprint(pc->nexti->nexti, ip1->doloop_cond, false);
+ pprint(pc->nexti->nexti, ip1->doloop_cond, NO_PPRINT_FLAGS);
indent_out();
- pprint(ip1->doloop_cond, pc->target_break, false);
+ pprint(ip1->doloop_cond, pc->target_break, NO_PPRINT_FLAGS);
indent(SPACEOVER);
t1 = pp_pop();
fprintf(prof_fp, "} %s (%s)\n", op2str(Op_K_while), t1->pp_str);
@@ -808,24 +810,24 @@ cleanup:
&& pc->target_continue->opcode == Op_jmp) {
fprintf(prof_fp, ";;");
} else {
- pprint(pc->nexti, ip1->forloop_cond, true);
+ pprint(pc->nexti, ip1->forloop_cond, IN_FOR_HEADER);
fprintf(prof_fp, "; ");
if (ip1->forloop_cond->opcode == Op_no_op &&
ip1->forloop_cond->nexti == ip1->forloop_body)
fprintf(prof_fp, "; ");
else {
- pprint(ip1->forloop_cond, ip1->forloop_body, true);
+ pprint(ip1->forloop_cond, ip1->forloop_body, IN_FOR_HEADER);
t1 = pp_pop();
fprintf(prof_fp, "%s; ", t1->pp_str);
pp_free(t1);
}
- pprint(pc->target_continue, pc->target_break, true);
+ pprint(pc->target_continue, pc->target_break, IN_FOR_HEADER);
}
fprintf(prof_fp, ") {\n");
indent_in();
- pprint(ip1->forloop_body->nexti, pc->target_continue, false);
+ pprint(ip1->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -850,7 +852,7 @@ cleanup:
item, op2str(Op_in_array), array);
indent_in();
pp_free(t1);
- pprint(ip1->forloop_body->nexti, pc->target_break, false);
+ pprint(ip1->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -861,11 +863,11 @@ cleanup:
case Op_K_switch:
ip1 = pc + 1;
fprintf(prof_fp, "%s (", op2str(pc->opcode));
- pprint(pc->nexti, ip1->switch_start, false);
+ pprint(pc->nexti, ip1->switch_start, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {\n", t1->pp_str);
pp_free(t1);
- pprint(ip1->switch_start, ip1->switch_end, false);
+ pprint(ip1->switch_start, ip1->switch_end, NO_PPRINT_FLAGS);
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
pc = pc->target_break;
@@ -881,13 +883,13 @@ cleanup:
} else
fprintf(prof_fp, "%s:\n", op2str(pc->opcode));
indent_in();
- pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, false);
+ pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, NO_PPRINT_FLAGS);
indent_out();
break;
case Op_K_if:
fprintf(prof_fp, "%s (", op2str(pc->opcode));
- pprint(pc->nexti, pc->branch_if, false);
+ pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {", t1->pp_str);
pp_free(t1);
@@ -897,22 +899,47 @@ cleanup:
fprintf(prof_fp, " # %ld", ip1->exec_count);
end_line(pc);
indent_in();
- pprint(ip1->nexti, pc->branch_else, false);
+ pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
indent_out();
pc = pc->branch_else;
- if (pc->nexti->opcode == Op_no_op) {
+ if (pc->nexti->opcode == Op_no_op) { /* no following else */
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
}
+ /*
+ * See next case; turn off the flag so that the
+ * following else is correctly indented.
+ */
+ flags &= ~IN_ELSE_IF;
break;
case Op_K_else:
- fprintf(prof_fp, "} %s {\n", op2str(pc->opcode));
- indent_in();
- pprint(pc->nexti, pc->branch_end, false);
- indent_out();
- indent(SPACEOVER);
- fprintf(prof_fp, "}\n");
+ /*
+ * If possible, chain else-if's together on the
+ * same line.
+ *
+ * See awkgram.y:mk_condition to understand
+ * what is being checked here.
+ *
+ * Op_exec_count follows Op_K_else, check the
+ * opcode of the following instruction.
+ * Additionally, check that the subsequent if
+ * terminates where this else does; in that case
+ * it's ok to compact the if to follow the else.
+ */
+
+ fprintf(prof_fp, "} %s ", op2str(pc->opcode));
+ if (pc->nexti->nexti->opcode == Op_K_if
+ && pc->branch_end == pc->nexti->nexti->branch_else->lasti) {
+ pprint(pc->nexti, pc->branch_end, IN_ELSE_IF);
+ } else {
+ fprintf(prof_fp, "{\n", op2str(pc->opcode));
+ indent_in();
+ pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
+ indent_out();
+ indent(SPACEOVER);
+ fprintf(prof_fp, "}\n");
+ }
pc = pc->branch_end;
break;
@@ -921,14 +948,14 @@ cleanup:
NODE *f, *t, *cond;
size_t len;
- pprint(pc->nexti, pc->branch_if, false);
+ pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
ip1 = pc->branch_if;
- pprint(ip1->nexti, pc->branch_else, false);
+ pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
ip1 = pc->branch_else->nexti;
pc = ip1->nexti;
assert(pc->opcode == Op_cond_exp);
- pprint(pc->nexti, pc->branch_end, false);
+ pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
f = pp_pop();
t = pp_pop();
@@ -947,7 +974,7 @@ cleanup:
break;
case Op_exec_count:
- if (! in_for_header)
+ if (flags == NO_PPRINT_FLAGS)
indent(pc->exec_count);
break;
@@ -1097,7 +1124,7 @@ dump_prog(INSTRUCTION *code)
if (do_profile)
fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
print_lib_list(prof_fp);
- pprint(code, NULL, false);
+ pprint(code, NULL, NO_PPRINT_FLAGS);
}
/* prec_level --- return the precedence of an operator, for paren tests */
@@ -1708,7 +1735,7 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
indent(0);
fprintf(prof_fp, "{\n");
indent_in();
- pprint(fp, NULL, false); /* function body */
+ pprint(fp, NULL, NO_PPRINT_FLAGS); /* function body */
indent_out();
if (do_profile)
indent(0);