diff options
Diffstat (limited to 'profile.c')
-rw-r--r-- | profile.c | 281 |
1 files changed, 181 insertions, 100 deletions
@@ -26,6 +26,7 @@ #include "awk.h" static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header); +static void end_line(INSTRUCTION *ip); 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); @@ -176,70 +177,82 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header) NODE *t1; char *str; NODE *t2; - INSTRUCTION *ip; + INSTRUCTION *ip1; + INSTRUCTION *ip2; NODE *m; char *tmp; int rule; - long lind; static int rule_count[MAXRULE]; for (pc = startp; pc != endp; pc = pc->nexti) { if (pc->source_line > 0) sourceline = pc->source_line; + /* skip leading EOL comment as it has already been printed */ + if (pc->opcode == Op_comment + && pc->memory->comment_type == EOL_COMMENT) + continue; switch (pc->opcode) { case Op_rule: + /* + * Rules are three instructions long. + * See append_rule in awkgram.y. + * The first has the Rule Op Code, nexti etc. + * The second, (pc + 1) has firsti and lasti: + * the first/last ACTION instructions for this rule. + * The third has first_line and last_line: + * the first and last source line numbers. + */ source = pc->source_file; rule = pc->in_rule; if (rule != Rule) { - ip = (pc + 1)->firsti; - - /* print pre-begin/end comments */ - if (ip->opcode == Op_comment) { - print_comment(ip, 0); - ip = ip->nexti; - } + /* Allow for pre-non-rule-block comment */ + if (pc->nexti != (pc +1)->firsti + && pc->nexti->opcode == Op_comment + && pc->nexti->memory->comment_type == FULL_COMMENT) + print_comment(pc->nexti, -1); + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; if (do_profile) { if (! rule_count[rule]++) fprintf(prof_fp, _("\t# %s rule(s)\n\n"), ruletab[rule]); indent(0); } - fprintf(prof_fp, "%s {\n", ruletab[rule]); + fprintf(prof_fp, "%s {", ruletab[rule]); + end_line(pc); } else { if (do_profile && ! rule_count[rule]++) fprintf(prof_fp, _("\t# Rule(s)\n\n")); - ip = pc->nexti; - lind = ip->exec_count; - /* print pre-block comments */ - if (ip->opcode == Op_exec_count && ip->nexti->opcode == Op_comment) - ip = ip->nexti; - if (ip->opcode == Op_comment) { - print_comment(ip, lind); - if (ip->nexti->nexti == (pc + 1)->firsti) - ip = ip->nexti->nexti; - } - if (ip != (pc + 1)->firsti) { /* non-empty pattern */ - indent(lind); - pprint(ip->nexti, (pc + 1)->firsti, false); - t1 = pp_pop(); - fprintf(prof_fp, "%s {", t1->pp_str); - pp_free(t1); - ip = (pc + 1)->firsti; - - if (do_profile && ip->exec_count > 0) - fprintf(prof_fp, " # %ld", ip->exec_count); - - fprintf(prof_fp, "\n"); + ip1 = pc->nexti; + indent(ip1->exec_count); + if (ip1 != (pc + 1)->firsti) { /* non-empty pattern */ + pprint(ip1->nexti, (pc + 1)->firsti, false); + /* Allow for case where the "pattern" is just a comment */ + if (ip1->nexti->nexti->nexti != (pc +1)->firsti + || ip1->nexti->opcode != Op_comment) { + t1 = pp_pop(); + fprintf(prof_fp, "%s {", t1->pp_str); + pp_free(t1); + } else + fprintf(prof_fp, "{"); + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; + + if (do_profile && ip1->exec_count > 0) + fprintf(prof_fp, " # %ld", ip1->exec_count); + + end_line(ip1); } else { fprintf(prof_fp, "{\n"); - ip = (pc + 1)->firsti; + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; } - ip = ip->nexti; + ip1 = ip1->nexti; } indent_in(); - pprint(ip, (pc + 1)->lasti, false); + pprint(ip1, ip2, false); indent_out(); if (do_profile) indent(0); @@ -328,7 +341,7 @@ cleanup: pp_free(t2); pp_free(t1); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); break; default: @@ -420,7 +433,8 @@ cleanup: case Op_unary_minus: case Op_not: t1 = pp_pop(); - if (is_binary(t1->type)) + if (is_binary(t1->type) + || (((OPCODE) t1->type) == pc->opcode && pc->opcode == Op_unary_minus)) pp_parenthesize(t1); /* optypes table (eval.c) includes space after ! */ @@ -453,7 +467,7 @@ cleanup: pp_free(t2); pp_free(t1); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); break; case Op_concat: @@ -474,7 +488,7 @@ cleanup: } else fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); pp_free(t1); } break; @@ -586,7 +600,7 @@ cleanup: fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp); efree(tmp); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); break; case Op_push_re: @@ -704,33 +718,33 @@ cleanup: t1 = pp_pop(); fprintf(prof_fp, "%s", t1->pp_str); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); 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); + ip1 = pc + 1; + pprint(pc->nexti, ip1->condpair_left, false); + pprint(ip1->condpair_left->nexti, ip1->condpair_right, false); t2 = pp_pop(); t1 = pp_pop(); str = pp_group3(t1->pp_str, ", ", t2->pp_str); pp_free(t1); pp_free(t2); pp_push(Op_line_range, str, CAN_FREE); - pc = ip->condpair_right; + pc = ip1->condpair_right; break; case Op_K_while: - ip = pc + 1; - indent(ip->while_body->exec_count); + ip1 = pc + 1; + indent(ip1->while_body->exec_count); fprintf(prof_fp, "%s (", op2str(pc->opcode)); - pprint(pc->nexti, ip->while_body, false); + pprint(pc->nexti, ip1->while_body, false); 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(ip1->while_body->nexti, pc->target_break, false); indent_out(); indent(SPACEOVER); fprintf(prof_fp, "}\n"); @@ -738,13 +752,13 @@ cleanup: break; case Op_K_do: - ip = pc + 1; + ip1 = pc + 1; 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, ip1->doloop_cond, false); indent_out(); - pprint(ip->doloop_cond, pc->target_break, false); + pprint(ip1->doloop_cond, pc->target_break, false); indent(SPACEOVER); t1 = pp_pop(); fprintf(prof_fp, "} %s (%s)\n", op2str(Op_K_while), t1->pp_str); @@ -753,24 +767,24 @@ cleanup: break; case Op_K_for: - ip = pc + 1; - indent(ip->forloop_body->exec_count); + ip1 = pc + 1; + indent(ip1->forloop_body->exec_count); fprintf(prof_fp, "%s (", op2str(pc->opcode)); /* If empty for looop header, print it a little more nicely. */ if ( pc->nexti->opcode == Op_no_op - && ip->forloop_cond == pc->nexti + && ip1->forloop_cond == pc->nexti && pc->target_continue->opcode == Op_jmp) { fprintf(prof_fp, ";;"); } else { - pprint(pc->nexti, ip->forloop_cond, true); + pprint(pc->nexti, ip1->forloop_cond, true); fprintf(prof_fp, "; "); - if (ip->forloop_cond->opcode == Op_no_op && - ip->forloop_cond->nexti == ip->forloop_body) + if (ip1->forloop_cond->opcode == Op_no_op && + ip1->forloop_cond->nexti == ip1->forloop_body) fprintf(prof_fp, "; "); else { - pprint(ip->forloop_cond, ip->forloop_body, true); + pprint(ip1->forloop_cond, ip1->forloop_body, true); t1 = pp_pop(); fprintf(prof_fp, "%s; ", t1->pp_str); pp_free(t1); @@ -780,7 +794,7 @@ cleanup: } fprintf(prof_fp, ") {\n"); indent_in(); - pprint(ip->forloop_body->nexti, pc->target_continue, false); + pprint(ip1->forloop_body->nexti, pc->target_continue, false); indent_out(); indent(SPACEOVER); fprintf(prof_fp, "}\n"); @@ -792,20 +806,20 @@ cleanup: char *array; const char *item; - ip = pc + 1; + ip1 = pc + 1; t1 = pp_pop(); array = t1->pp_str; - m = ip->forloop_cond->array_var; + m = ip1->forloop_cond->array_var; if (m->type == Node_param_list) item = func_params[m->param_cnt].param; else item = m->vname; - indent(ip->forloop_body->exec_count); + indent(ip1->forloop_body->exec_count); fprintf(prof_fp, "%s (%s%s%s) {\n", op2str(Op_K_arrayfor), item, op2str(Op_in_array), array); indent_in(); pp_free(t1); - pprint(ip->forloop_body->nexti, pc->target_break, false); + pprint(ip1->forloop_body->nexti, pc->target_break, false); indent_out(); indent(SPACEOVER); fprintf(prof_fp, "}\n"); @@ -814,13 +828,13 @@ cleanup: break; case Op_K_switch: - ip = pc + 1; + ip1 = pc + 1; fprintf(prof_fp, "%s (", op2str(pc->opcode)); - pprint(pc->nexti, ip->switch_start, false); + pprint(pc->nexti, ip1->switch_start, false); t1 = pp_pop(); fprintf(prof_fp, "%s) {\n", t1->pp_str); pp_free(t1); - pprint(ip->switch_start, ip->switch_end, false); + pprint(ip1->switch_start, ip1->switch_end, false); indent(SPACEOVER); fprintf(prof_fp, "}\n"); pc = pc->target_break; @@ -847,12 +861,12 @@ cleanup: fprintf(prof_fp, "%s) {", t1->pp_str); pp_free(t1); - ip = pc->branch_if; - if (ip->exec_count > 0) - fprintf(prof_fp, " # %ld", ip->exec_count); - fprintf(prof_fp, "\n"); + ip1 = pc->branch_if; + if (ip1->exec_count > 0) + fprintf(prof_fp, " # %ld", ip1->exec_count); + end_line(pc); indent_in(); - pprint(ip->nexti, pc->branch_else, false); + pprint(ip1->nexti, pc->branch_else, false); indent_out(); pc = pc->branch_else; if (pc->nexti->opcode == Op_no_op) { @@ -877,11 +891,11 @@ cleanup: size_t len; pprint(pc->nexti, pc->branch_if, false); - ip = pc->branch_if; - pprint(ip->nexti, pc->branch_else, false); - ip = pc->branch_else->nexti; + ip1 = pc->branch_if; + pprint(ip1->nexti, pc->branch_else, false); + ip1 = pc->branch_else->nexti; - pc = ip->nexti; + pc = ip1->nexti; assert(pc->opcode == Op_cond_exp); pprint(pc->nexti, pc->branch_end, false); @@ -922,6 +936,21 @@ cleanup: } } +/* end_line --- end pretty print line with new line or on-line comment */ + +void +end_line(INSTRUCTION *ip) +{ + if (ip->nexti->opcode == Op_comment + && ip->nexti->memory->comment_type == EOL_COMMENT) { + fprintf(prof_fp, "\t"); + print_comment(ip->nexti, -1); + ip = ip->nexti->nexti; + } + else + fprintf(prof_fp, "\n"); +} + /* pp_string_fp --- printy print a string to the fp */ /* @@ -1007,7 +1036,8 @@ print_comment(INSTRUCTION* pc, long in) count = pc->memory->stlen; text = pc->memory->stptr; - indent(in); /* is this correct? Where should comments go? */ + if (in >= 0) + indent(in); /* is this correct? Where should comments go? */ for (; count > 0; count--, text++) { if (after_newline) { indent(in); @@ -1057,25 +1087,25 @@ prec_level(int type) case Op_func_call: case Op_K_delete_loop: case Op_builtin: - return 15; + return 16; case Op_field_spec: case Op_field_spec_lhs: - return 14; - - case Op_exp: - case Op_exp_i: - return 13; + return 15; case Op_preincrement: case Op_predecrement: case Op_postincrement: case Op_postdecrement: - return 12; + return 14; + + case Op_exp: + case Op_exp_i: + return 13; case Op_unary_minus: case Op_not: - return 11; + return 12; case Op_times: case Op_times_i: @@ -1083,23 +1113,26 @@ prec_level(int type) case Op_quotient_i: case Op_mod: case Op_mod_i: - return 10; + return 11; case Op_plus: case Op_plus_i: case Op_minus: case Op_minus_i: - return 9; + return 10; case Op_concat: case Op_assign_concat: - return 8; + return 9; case Op_equal: case Op_notequal: case Op_greater: + case Op_less: case Op_leq: case Op_geq: + return 8; + case Op_match: case Op_nomatch: return 7; @@ -1108,7 +1141,6 @@ prec_level(int type) case Op_K_getline_redir: return 6; - case Op_less: case Op_in_array: return 5; @@ -1234,6 +1266,26 @@ pp_parenthesize(NODE *sp) sp->flags |= CAN_FREE; } +/* div_on_left_mul_on_right --- have / or % on left and * on right */ + +static bool +div_on_left_mul_on_right(int o1, int o2) +{ + OPCODE op1 = (OPCODE) o1; + OPCODE op2 = (OPCODE) o2; + + switch (op1) { + case Op_quotient: + case Op_quotient_i: + case Op_mod: + case Op_mod_i: + return (op2 == Op_times || op2 == Op_times_i); + + default: + return false; + } +} + /* parenthesize --- parenthesize two nodes relative to parent node type */ static void @@ -1243,9 +1295,11 @@ parenthesize(int type, NODE *left, NODE *right) int lprec = prec_level(left->type); int prec = prec_level(type); - if (lprec < prec) + if (lprec < prec + || (lprec == prec && div_on_left_mul_on_right(left->type, type))) pp_parenthesize(left); - if (rprec < prec) + if (rprec < prec + || (rprec == prec && div_on_left_mul_on_right(type, right->type))) pp_parenthesize(right); } @@ -1336,16 +1390,30 @@ pp_number(NODE *n) { #define PP_PRECISION 6 char *str; + size_t count; - emalloc(str, char *, PP_PRECISION + 10, "pp_number"); #ifdef HAVE_MPFR - if (is_mpg_float(n)) - mpfr_sprintf(str, "%0.*R*g", PP_PRECISION, ROUND_MODE, n->mpg_numbr); - else if (is_mpg_integer(n)) + if (is_mpg_float(n)) { + count = mpfr_get_prec(n->mpg_numbr) / 3; /* ~ 3.22 binary digits per decimal digit */ + emalloc(str, char *, count, "pp_number"); + /* + * 3/2015: Format string used to be "%0.*R*g". That padded + * with leading zeros. But it doesn't do that for regular + * numbers in the non-MPFR case. + */ + mpfr_sprintf(str, "%.*R*g", PP_PRECISION, ROUND_MODE, n->mpg_numbr); + } else if (is_mpg_integer(n)) { + count = mpz_sizeinbase(n->mpg_i, 10) + 2; /* +1 for sign, +1 for NUL at end */ + emalloc(str, char *, count, "pp_number"); mpfr_sprintf(str, "%Zd", n->mpg_i); - else + } else #endif - sprintf(str, "%0.*g", PP_PRECISION, n->numbr); + { + count = PP_PRECISION + 10; + emalloc(str, char *, count, "pp_number"); + sprintf(str, "%0.*g", PP_PRECISION, n->numbr); + } + return str; #undef PP_PRECISION } @@ -1417,6 +1485,14 @@ pp_list(int nargs, const char *paren, const char *delim) return str; } +/* is_unary_minus --- return true if string starts with unary minus */ + +static bool +is_unary_minus(const char *str) +{ + return str[0] == '-' && str[1] != '-'; +} + /* pp_concat --- handle concatenation and correct parenthesizing of expressions */ static char * @@ -1458,7 +1534,12 @@ pp_concat(int nargs) pl_l = prec_level(pp_args[i]->type); pl_r = prec_level(pp_args[i+1]->type); - if (is_scalar(pp_args[i]->type) && is_scalar(pp_args[i+1]->type)) { + if (i >= 2 && is_unary_minus(r->pp_str)) { + *s++ = '('; + memcpy(s, r->pp_str, r->pp_len); + s += r->pp_len; + *s++ = ')'; + } else if (is_scalar(pp_args[i]->type) && is_scalar(pp_args[i+1]->type)) { memcpy(s, r->pp_str, r->pp_len); s += r->pp_len; } else if (pl_l <= pl_r || is_scalar(pp_args[i+1]->type)) { @@ -1480,7 +1561,7 @@ pp_concat(int nargs) pl_l = prec_level(pp_args[nargs-1]->type); pl_r = prec_level(pp_args[nargs]->type); r = pp_args[nargs]; - if (pl_l >= pl_r && ! is_scalar(pp_args[nargs]->type)) { + if (is_unary_minus(r->pp_str) || ((pl_l >= pl_r && ! is_scalar(pp_args[nargs]->type)))) { *s++ = '('; memcpy(s, r->pp_str, r->pp_len); s += r->pp_len; @@ -1548,7 +1629,7 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED) /* print any function comment */ if (fp->opcode == Op_comment && fp->source_line == 0) { - print_comment(fp, 0); + print_comment(fp, -1); /* -1 ==> don't indent */ fp = fp->nexti; } |