aboutsummaryrefslogtreecommitdiffstats
path: root/profile.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2016-02-18 19:40:10 +0200
committerArnold D. Robbins <arnold@skeeve.com>2016-02-18 19:40:10 +0200
commit8635225f337cc96b28b411a7599962503059cc25 (patch)
tree7e74b90a3fa27cf02d8681753dea391a4824fe08 /profile.c
parent7224d3f6b8db04439e8fdf8025b99db321a3f5ea (diff)
downloadegawk-8635225f337cc96b28b411a7599962503059cc25.tar.gz
egawk-8635225f337cc96b28b411a7599962503059cc25.tar.bz2
egawk-8635225f337cc96b28b411a7599962503059cc25.zip
Make pretty-printing and profiling chain else-if's.
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/profile.c b/profile.c
index dc89d006..3d0b1cbc 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 pp_parenthesize(NODE *n);
static void parenthesize(int type, NODE *left, NODE *right);
static char *pp_list(int nargs, const char *paren, const char *delim);
@@ -57,9 +57,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
@@ -187,7 +190,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;
@@ -219,7 +222,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
ip = pc->nexti;
indent(ip->exec_count);
if (ip != (pc + 1)->firsti) { /* non-empty pattern */
- pprint(ip->nexti, (pc + 1)->firsti, false);
+ pprint(ip->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s {", t1->pp_str);
pp_free(t1);
@@ -236,7 +239,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
ip = ip->nexti;
}
indent_in();
- pprint(ip, (pc + 1)->lasti, false);
+ pprint(ip, (pc + 1)->lasti, NO_PPRINT_FLAGS);
indent_out();
fprintf(prof_fp, "\t}\n\n");
pc = (pc + 1)->lasti;
@@ -322,7 +325,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)
fprintf(prof_fp, "\n");
break;
@@ -344,7 +347,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);
@@ -448,7 +451,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)
fprintf(prof_fp, "\n");
break;
@@ -469,7 +472,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)
fprintf(prof_fp, "\n");
pp_free(t1);
}
@@ -581,7 +584,7 @@ cleanup:
} else
fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
efree(tmp);
- if (! in_for_header)
+ if ((flags & IN_FOR_HEADER) == 0)
fprintf(prof_fp, "\n");
break;
@@ -699,15 +702,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)
fprintf(prof_fp, "\n");
pp_free(t1);
break;
case Op_line_range:
ip = pc + 1;
- pprint(pc->nexti, ip->condpair_left, false);
- pprint(ip->condpair_left->nexti, ip->condpair_right, false);
+ pprint(pc->nexti, ip->condpair_left, NO_PPRINT_FLAGS);
+ pprint(ip->condpair_left->nexti, ip->condpair_right, NO_PPRINT_FLAGS);
t2 = pp_pop();
t1 = pp_pop();
str = pp_group3(t1->pp_str, ", ", t2->pp_str);
@@ -721,12 +724,12 @@ cleanup:
ip = pc + 1;
indent(ip->while_body->exec_count);
fprintf(prof_fp, "%s (", op2str(pc->opcode));
- pprint(pc->nexti, ip->while_body, false);
+ pprint(pc->nexti, ip->while_body, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {\n", t1->pp_str);
pp_free(t1);
indent_in();
- pprint(ip->while_body->nexti, pc->target_break, false);
+ pprint(ip->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -738,9 +741,9 @@ cleanup:
indent(pc->nexti->exec_count);
fprintf(prof_fp, "%s {\n", op2str(pc->opcode));
indent_in();
- pprint(pc->nexti->nexti, ip->doloop_cond, false);
+ pprint(pc->nexti->nexti, ip->doloop_cond, NO_PPRINT_FLAGS);
indent_out();
- pprint(ip->doloop_cond, pc->target_break, false);
+ pprint(ip->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);
@@ -759,24 +762,24 @@ cleanup:
&& pc->target_continue->opcode == Op_jmp) {
fprintf(prof_fp, ";;");
} else {
- pprint(pc->nexti, ip->forloop_cond, true);
+ pprint(pc->nexti, ip->forloop_cond, IN_FOR_HEADER);
fprintf(prof_fp, "; ");
if (ip->forloop_cond->opcode == Op_no_op &&
ip->forloop_cond->nexti == ip->forloop_body)
fprintf(prof_fp, "; ");
else {
- pprint(ip->forloop_cond, ip->forloop_body, true);
+ pprint(ip->forloop_cond, ip->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(ip->forloop_body->nexti, pc->target_continue, false);
+ pprint(ip->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -801,7 +804,7 @@ cleanup:
item, op2str(Op_in_array), array);
indent_in();
pp_free(t1);
- pprint(ip->forloop_body->nexti, pc->target_break, false);
+ pprint(ip->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -812,11 +815,11 @@ cleanup:
case Op_K_switch:
ip = pc + 1;
fprintf(prof_fp, "%s (", op2str(pc->opcode));
- pprint(pc->nexti, ip->switch_start, false);
+ pprint(pc->nexti, ip->switch_start, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {\n", t1->pp_str);
pp_free(t1);
- pprint(ip->switch_start, ip->switch_end, false);
+ pprint(ip->switch_start, ip->switch_end, NO_PPRINT_FLAGS);
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
pc = pc->target_break;
@@ -832,13 +835,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);
@@ -848,22 +851,47 @@ cleanup:
fprintf(prof_fp, " # %ld", ip->exec_count);
fprintf(prof_fp, "\n");
indent_in();
- pprint(ip->nexti, pc->branch_else, false);
+ pprint(ip->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;
@@ -872,14 +900,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);
ip = pc->branch_if;
- pprint(ip->nexti, pc->branch_else, false);
+ pprint(ip->nexti, pc->branch_else, NO_PPRINT_FLAGS);
ip = pc->branch_else->nexti;
pc = ip->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();
@@ -898,7 +926,7 @@ cleanup:
break;
case Op_exec_count:
- if (! in_for_header)
+ if (flags == NO_PPRINT_FLAGS)
indent(pc->exec_count);
break;
@@ -1000,7 +1028,7 @@ dump_prog(INSTRUCTION *code)
/* \n on purpose, with \n in ctime() output */
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 */
@@ -1579,7 +1607,7 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
}
fprintf(prof_fp, ")\n\t{\n");
indent_in();
- pprint(pc->nexti->nexti, NULL, false); /* function body */
+ pprint(pc->nexti->nexti, NULL, NO_PPRINT_FLAGS); /* function body */
indent_out();
fprintf(prof_fp, "\t}\n");
return 0;