aboutsummaryrefslogtreecommitdiffstats
path: root/profile.c
diff options
context:
space:
mode:
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c180
1 files changed, 145 insertions, 35 deletions
diff --git a/profile.c b/profile.c
index d07bea4a..59542ab9 100644
--- a/profile.c
+++ b/profile.c
@@ -36,7 +36,8 @@ 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 pp_free(NODE *n);
+static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header);
+static void print_comment(INSTRUCTION *pc, long in);
const char *redir2str(int redirtype);
#define pp_str vname
@@ -100,10 +101,12 @@ indent(long count)
{
int i;
- if (count == 0)
- fprintf(prof_fp, "\t");
- else
- fprintf(prof_fp, "%6ld ", count);
+ if (do_profile) {
+ if (count == 0)
+ fprintf(prof_fp, "\t");
+ else
+ fprintf(prof_fp, "%6ld ", count);
+ }
assert(indent_level >= 0);
for (i = 0; i < indent_level; i++)
@@ -177,6 +180,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
NODE *m;
char *tmp;
int rule;
+ long lind;
static int rule_count[MAXRULE];
for (pc = startp; pc != endp; pc = pc->nexti) {
@@ -189,16 +193,35 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
rule = pc->in_rule;
if (rule != Rule) {
- if (! rule_count[rule]++)
- fprintf(prof_fp, _("\t# %s block(s)\n\n"), ruletab[rule]);
- fprintf(prof_fp, "\t%s {\n", ruletab[rule]);
ip = (pc + 1)->firsti;
+
+ /* print pre-begin/end comments */
+ if (ip->opcode == Op_comment) {
+ print_comment(ip, 0);
+ ip = ip->nexti;
+ }
+
+ 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]);
} else {
- if (! rule_count[rule]++)
+ if (do_profile && ! rule_count[rule]++)
fprintf(prof_fp, _("\t# Rule(s)\n\n"));
ip = pc->nexti;
- indent(ip->exec_count);
+ 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);
@@ -218,7 +241,9 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
indent_in();
pprint(ip, (pc + 1)->lasti, false);
indent_out();
- fprintf(prof_fp, "\t}\n\n");
+ if (do_profile)
+ indent(0);
+ fprintf(prof_fp, "}\n\n");
pc = (pc + 1)->lasti;
break;
@@ -395,7 +420,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 ! */
@@ -881,6 +907,13 @@ cleanup:
indent(pc->exec_count);
break;
+ case Op_comment:
+ print_comment(pc, 0);
+ break;
+
+ case Op_list:
+ break;
+
default:
cant_happen();
}
@@ -909,11 +942,11 @@ pp_string_fp(Func_print print_func, FILE *fp, const char *in_str,
slen = strlen(str);
for (count = 0; slen > 0; slen--, str++) {
+ print_func(fp, "%c", *str);
if (++count >= BREAKPOINT && breaklines) {
print_func(fp, "%c\n%c", delim, delim);
count = 0;
- } else
- print_func(fp, "%c", *str);
+ }
}
efree(s);
}
@@ -963,6 +996,30 @@ print_lib_list(FILE *prof_fp)
fprintf(prof_fp, "\n");
}
+/* print_comment --- print comment text with proper indentation */
+
+static void
+print_comment(INSTRUCTION* pc, long in)
+{
+ char *text;
+ size_t count;
+ bool after_newline = false;
+
+ count = pc->memory->stlen;
+ text = pc->memory->stptr;
+
+ indent(in); /* is this correct? Where should comments go? */
+ for (; count > 0; count--, text++) {
+ if (after_newline) {
+ indent(in);
+ after_newline = false;
+ }
+ putc(*text, prof_fp);
+ if (*text == '\n')
+ after_newline = true;
+ }
+}
+
/* dump_prog --- dump the program */
/*
@@ -977,7 +1034,8 @@ dump_prog(INSTRUCTION *code)
(void) time(& now);
/* \n on purpose, with \n in ctime() output */
- fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
+ if (do_profile)
+ fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
print_lib_list(prof_fp);
pprint(code, NULL, false);
}
@@ -1000,25 +1058,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 +1084,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 +1112,6 @@ prec_level(int type)
case Op_K_getline_redir:
return 6;
- case Op_less:
case Op_in_array:
return 5;
@@ -1177,6 +1237,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
@@ -1186,9 +1266,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);
}
@@ -1360,6 +1442,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 +1491,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 +1518,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;
@@ -1477,14 +1572,24 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
static bool first = true;
NODE *func;
int pcount;
+ INSTRUCTION *fp;
if (first) {
first = false;
- fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n"));
+ if (do_profile)
+ fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n"));
}
+ fp = pc->nexti->nexti;
func = pc->func_body;
fprintf(prof_fp, "\n");
+
+ /* print any function comment */
+ if (fp->opcode == Op_comment && fp->source_line == 0) {
+ print_comment(fp, 0);
+ fp = fp->nexti;
+ }
+
indent(pc->nexti->exec_count);
fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);
pcount = func->param_cnt;
@@ -1494,11 +1599,16 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
if (j < pcount - 1)
fprintf(prof_fp, ", ");
}
- fprintf(prof_fp, ")\n\t{\n");
+ fprintf(prof_fp, ")\n");
+ if (do_profile)
+ indent(0);
+ fprintf(prof_fp, "{\n");
indent_in();
- pprint(pc->nexti->nexti, NULL, false); /* function body */
+ pprint(fp, NULL, false); /* function body */
indent_out();
- fprintf(prof_fp, "\t}\n");
+ if (do_profile)
+ indent(0);
+ fprintf(prof_fp, "}\n");
return 0;
}