summaryrefslogtreecommitdiff
path: root/profile.c
diff options
context:
space:
mode:
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c300
1 files changed, 215 insertions, 85 deletions
diff --git a/profile.c b/profile.c
index 3d0b1cbc..ddc8b9b1 100644
--- a/profile.c
+++ b/profile.c
@@ -26,17 +26,20 @@
#include "awk.h"
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);
static char *pp_list(int nargs, const char *paren, const char *delim);
static char *pp_group3(const char *s1, const char *s2, const char *s3);
static char *pp_concat(int nargs);
+static char *pp_string_or_strong_regex(const char *in_str, size_t len, int delim, bool strong_regex);
+static char *pp_strong_regex(const char *in_str, size_t len, int delim);
static bool is_binary(int type);
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 print_comment(INSTRUCTION *pc, long in);
const char *redir2str(int redirtype);
#define pp_str vname
@@ -46,8 +49,8 @@ const char *redir2str(int redirtype);
#define DONT_FREE 1
#define CAN_FREE 2
-static RETSIGTYPE dump_and_exit(int signum) ATTRIBUTE_NORETURN;
-static RETSIGTYPE just_dump(int signum);
+static void dump_and_exit(int signum) ATTRIBUTE_NORETURN;
+static void just_dump(int signum);
/* pretty printing related functions and variables */
@@ -123,10 +126,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++)
@@ -196,7 +201,8 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
NODE *t1;
char *str;
NODE *t2;
- INSTRUCTION *ip;
+ INSTRUCTION *ip1;
+ INSTRUCTION *ip2;
NODE *m;
char *tmp;
int rule;
@@ -206,42 +212,75 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
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) {
- if (! rule_count[rule]++)
- fprintf(prof_fp, _("\t# %s rule(s)\n\n"), ruletab[rule]);
- fprintf(prof_fp, "\t%s {\n", ruletab[rule]);
- ip = (pc + 1)->firsti;
+ /* 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 {", ruletab[rule]);
+ end_line(pc);
} 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);
- if (ip != (pc + 1)->firsti) { /* non-empty pattern */
- pprint(ip->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS);
- 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, 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) {
+ 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, NO_PPRINT_FLAGS);
+ pprint(ip1, ip2, NO_PPRINT_FLAGS);
indent_out();
- fprintf(prof_fp, "\t}\n\n");
+ if (do_profile)
+ indent(0);
+ fprintf(prof_fp, "}\n\n");
pc = (pc + 1)->lasti;
break;
@@ -280,6 +319,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
case Op_push_array:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
m = pc->memory;
switch (m->type) {
case Node_param_list:
@@ -326,7 +366,7 @@ cleanup:
pp_free(t2);
pp_free(t1);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ end_line(pc);
break;
default:
@@ -452,7 +492,7 @@ cleanup:
pp_free(t2);
pp_free(t1);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ end_line(pc);
break;
case Op_concat:
@@ -473,7 +513,7 @@ cleanup:
} else
fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ end_line(pc);
pp_free(t1);
}
break;
@@ -585,18 +625,21 @@ cleanup:
fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
efree(tmp);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ end_line(pc);
break;
case Op_push_re:
- if (pc->memory->type != Node_regex)
+ if (pc->memory->type != Node_regex && pc->memory->type != Node_typedregex)
break;
/* else
fall through */
case Op_match_rec:
{
NODE *re = pc->memory->re_exp;
- str = pp_string(re->stptr, re->stlen, '/');
+ if (pc->memory->type == Node_regex)
+ str = pp_string(re->stptr, re->stlen, '/');
+ else
+ str = pp_strong_regex(re->stptr, re->stlen, '/');
pp_push(pc->opcode, str, CAN_FREE);
}
break;
@@ -618,6 +661,11 @@ cleanup:
txt = t2->pp_str;
str = pp_group3(txt, op2str(pc->opcode), restr);
pp_free(t2);
+ } else if (m->type == Node_typedregex) {
+ NODE *re = m->re_exp;
+ restr = pp_strong_regex(re->stptr, re->stlen, '/');
+ str = pp_group3(txt, op2str(pc->opcode), restr);
+ efree(restr);
} else {
NODE *re = m->re_exp;
restr = pp_string(re->stptr, re->stlen, '/');
@@ -703,33 +751,33 @@ cleanup:
t1 = pp_pop();
fprintf(prof_fp, "%s", t1->pp_str);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ end_line(pc);
pp_free(t1);
break;
case Op_line_range:
- ip = pc + 1;
- pprint(pc->nexti, ip->condpair_left, NO_PPRINT_FLAGS);
- pprint(ip->condpair_left->nexti, ip->condpair_right, NO_PPRINT_FLAGS);
+ ip1 = pc + 1;
+ 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);
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, NO_PPRINT_FLAGS);
+ 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(ip->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
+ pprint(ip1->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -737,13 +785,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, NO_PPRINT_FLAGS);
+ pprint(pc->nexti->nexti, ip1->doloop_cond, NO_PPRINT_FLAGS);
indent_out();
- pprint(ip->doloop_cond, pc->target_break, NO_PPRINT_FLAGS);
+ 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);
@@ -752,24 +800,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, IN_FOR_HEADER);
+ pprint(pc->nexti, ip1->forloop_cond, IN_FOR_HEADER);
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, IN_FOR_HEADER);
+ pprint(ip1->forloop_cond, ip1->forloop_body, IN_FOR_HEADER);
t1 = pp_pop();
fprintf(prof_fp, "%s; ", t1->pp_str);
pp_free(t1);
@@ -779,7 +827,7 @@ cleanup:
}
fprintf(prof_fp, ") {\n");
indent_in();
- pprint(ip->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS);
+ pprint(ip1->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -791,20 +839,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, NO_PPRINT_FLAGS);
+ pprint(ip1->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
@@ -813,13 +861,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, NO_PPRINT_FLAGS);
+ pprint(pc->nexti, ip1->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, NO_PPRINT_FLAGS);
+ pprint(ip1->switch_start, ip1->switch_end, NO_PPRINT_FLAGS);
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
pc = pc->target_break;
@@ -846,12 +894,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, NO_PPRINT_FLAGS);
+ pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
indent_out();
pc = pc->branch_else;
if (pc->nexti->opcode == Op_no_op) { /* no following else */
@@ -901,11 +949,11 @@ cleanup:
size_t len;
pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
- ip = pc->branch_if;
- pprint(ip->nexti, pc->branch_else, NO_PPRINT_FLAGS);
- ip = pc->branch_else->nexti;
+ ip1 = pc->branch_if;
+ pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
+ ip1 = pc->branch_else->nexti;
- pc = ip->nexti;
+ pc = ip1->nexti;
assert(pc->opcode == Op_cond_exp);
pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
@@ -930,6 +978,13 @@ cleanup:
indent(pc->exec_count);
break;
+ case Op_comment:
+ print_comment(pc, 0);
+ break;
+
+ case Op_list:
+ break;
+
default:
cant_happen();
}
@@ -939,6 +994,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 */
/*
@@ -970,7 +1040,7 @@ pp_string_fp(Func_print print_func, FILE *fp, const char *in_str,
/* just_dump --- dump the profile and function stack and keep going */
-static RETSIGTYPE
+static void
just_dump(int signum)
{
extern INSTRUCTION *code_block;
@@ -984,7 +1054,7 @@ just_dump(int signum)
/* dump_and_exit --- dump the profile, the function stack, and exit */
-static RETSIGTYPE
+static void
dump_and_exit(int signum)
{
just_dump(signum);
@@ -1012,6 +1082,31 @@ 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;
+
+ if (in >= 0)
+ 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 */
/*
@@ -1026,7 +1121,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, NO_PPRINT_FLAGS);
}
@@ -1265,11 +1361,27 @@ parenthesize(int type, NODE *left, NODE *right)
pp_parenthesize(right);
}
-/* pp_string --- pretty format a string or regex constant */
+/* pp_string --- pretty format a string or regular regex constant */
char *
pp_string(const char *in_str, size_t len, int delim)
{
+ return pp_string_or_strong_regex(in_str, len, delim, false);
+}
+
+/* pp_strong_regex --- pretty format a hard regex constant */
+
+static char *
+pp_strong_regex(const char *in_str, size_t len, int delim)
+{
+ return pp_string_or_strong_regex(in_str, len, delim, true);
+}
+
+/* pp_string_or_strong_regex --- pretty format a string, regex, or hard regex constant */
+
+char *
+pp_string_or_strong_regex(const char *in_str, size_t len, int delim, bool strong_regex)
+{
static char str_escapes[] = "\a\b\f\n\r\t\v\\";
static char str_printables[] = "abfnrtv\\";
static char re_escapes[] = "\a\b\f\n\r\t\v";
@@ -1301,11 +1413,15 @@ pp_string(const char *in_str, size_t len, int delim)
osiz *= 2; \
} ofre -= (l)
- osiz = len + 3 + 2; /* initial size; 3 for delim + terminating null */
+ /* initial size; 3 for delim + terminating null, 1 for @ */
+ osiz = len + 3 + 1 + (strong_regex == true);
emalloc(obuf, char *, osiz, "pp_string");
obufout = obuf;
ofre = osiz - 1;
+ if (strong_regex)
+ *obufout++ = '@';
+
*obufout++ = delim;
for (; len > 0; len--, str++) {
chksize(2); /* make space for 2 chars */
@@ -1313,10 +1429,9 @@ pp_string(const char *in_str, size_t len, int delim)
*obufout++ = '\\';
*obufout++ = delim;
} else if (*str == '\0') {
- chksize(4);
-
*obufout++ = '\\';
*obufout++ = '0';
+ chksize(2); /* need 2 more chars for this case */
*obufout++ = '0';
*obufout++ = '0';
} else if ((cp = strchr(escapes, *str)) != NULL) {
@@ -1326,7 +1441,7 @@ pp_string(const char *in_str, size_t len, int delim)
/* NB: Deliberate use of lower-case versions. */
} else if (isascii(*str) && isprint(*str)) {
*obufout++ = *str;
- ofre += 1;
+ ofre += 1; /* used 1 less than expected */
} else {
size_t len;
@@ -1560,7 +1675,7 @@ pp_group3(const char *s1, const char *s2, const char *s3)
len1 = strlen(s1);
len2 = strlen(s2);
len3 = strlen(s3);
- l = len1 + len2 + len3 + 2;
+ l = len1 + len2 + len3 + 1;
emalloc(str, char *, l, "pp_group3");
s = str;
if (len1 > 0) {
@@ -1588,14 +1703,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, -1); /* -1 ==> don't indent */
+ fp = fp->nexti;
+ }
+
indent(pc->nexti->exec_count);
fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);
pcount = func->param_cnt;
@@ -1605,11 +1730,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, NO_PPRINT_FLAGS); /* function body */
+ pprint(fp, NULL, NO_PPRINT_FLAGS); /* function body */
indent_out();
- fprintf(prof_fp, "\t}\n");
+ if (do_profile)
+ indent(0);
+ fprintf(prof_fp, "}\n");
return 0;
}