From c2cda8d3736b59738f579fce748e94ca109ccc58 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 30 Oct 2014 21:33:59 +0200 Subject: Fixes in pretty-printer. --- profile.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'profile.c') diff --git a/profile.c b/profile.c index a5ed381b..ed17e62b 100644 --- a/profile.c +++ b/profile.c @@ -395,7 +395,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 ! */ @@ -1000,25 +1001,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: @@ -1026,23 +1027,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; @@ -1051,7 +1055,6 @@ prec_level(int type) case Op_K_getline_redir: return 6; - case Op_less: case Op_in_array: return 5; @@ -1360,6 +1363,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 * @@ -1401,7 +1412,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)) { @@ -1423,7 +1439,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; -- cgit v1.2.3 From c5227d1685aa158e63d4b6a6289063ae985673c1 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 2 Nov 2014 21:29:20 +0200 Subject: Additional profiling fix. --- profile.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'profile.c') diff --git a/profile.c b/profile.c index ed17e62b..316ba393 100644 --- a/profile.c +++ b/profile.c @@ -1180,6 +1180,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 @@ -1189,9 +1209,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); } -- cgit v1.2.3 From fa9d1a09cfe9e7386746a2c6523b5503d1b4aff9 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 12 Dec 2014 06:16:43 +0200 Subject: Improve comment handling in pretty printing. --- profile.c | 181 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 104 insertions(+), 77 deletions(-) (limited to 'profile.c') diff --git a/profile.c b/profile.c index 59542ab9..ad879a3c 100644 --- a/profile.c +++ b/profile.c @@ -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,80 @@ 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; + 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; } - 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 +339,7 @@ cleanup: pp_free(t2); pp_free(t1); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); break; default: @@ -454,7 +465,7 @@ cleanup: pp_free(t2); pp_free(t1); if (! in_for_header) - fprintf(prof_fp, "\n"); + end_line(pc); break; case Op_concat: @@ -475,7 +486,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; @@ -587,7 +598,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: @@ -705,33 +716,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"); @@ -739,13 +750,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); @@ -754,24 +765,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); @@ -781,7 +792,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"); @@ -793,20 +804,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"); @@ -815,13 +826,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; @@ -848,12 +859,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) { @@ -878,11 +889,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); @@ -923,6 +934,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 */ /* @@ -1008,7 +1034,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); @@ -1586,7 +1613,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; } -- cgit v1.2.3 From 399ec4931adce151b7633f2b66b04d021d3ae78c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 24 Dec 2014 20:38:00 +0200 Subject: Minor bug fix in pretty printing code. --- profile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'profile.c') diff --git a/profile.c b/profile.c index ad879a3c..233bca0f 100644 --- a/profile.c +++ b/profile.c @@ -246,6 +246,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header) } else { fprintf(prof_fp, "{\n"); ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; } ip1 = ip1->nexti; } -- cgit v1.2.3 From b3dcca92ca8160c07dad32617339fc5d3c636425 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 10 Feb 2015 22:22:11 +0200 Subject: Bug fix in profile.c. --- profile.c | 1 + 1 file changed, 1 insertion(+) (limited to 'profile.c') diff --git a/profile.c b/profile.c index 233bca0f..2cb9e159 100644 --- a/profile.c +++ b/profile.c @@ -226,6 +226,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header) if (do_profile && ! rule_count[rule]++) fprintf(prof_fp, _("\t# Rule(s)\n\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 */ -- cgit v1.2.3 From cffd09247c1681fbf3d5cad5253b3199704f83e7 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 17 Mar 2015 22:46:11 +0200 Subject: Fix bad allocs -M and profiling. --- profile.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'profile.c') diff --git a/profile.c b/profile.c index 316ba393..fd37bc61 100644 --- a/profile.c +++ b/profile.c @@ -1304,16 +1304,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 } -- cgit v1.2.3