aboutsummaryrefslogtreecommitdiffstats
path: root/profile.c
diff options
context:
space:
mode:
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c206
1 files changed, 180 insertions, 26 deletions
diff --git a/profile.c b/profile.c
index ac08a61d..e023f55b 100644
--- a/profile.c
+++ b/profile.c
@@ -208,6 +208,14 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
int rule;
static int rule_count[MAXRULE];
static bool skip_comment = false;
+ static const char tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+ static const size_t tabs_len = sizeof(tabs) - 1;
+
+#define check_indent_level()
+ if (indent_level + 1 > tabs_len) \
+ /* We're allowed to be snarky, occasionally. */ \
+ fatal(_("Program indentation level too deep. Consider refactoring your code"));
+
for (pc = startp; pc != endp; pc = pc->nexti) {
if (pc->source_line > 0)
@@ -238,9 +246,9 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
if (rule != Rule) {
/* Allow for pre-non-rule-block comment */
- if (pc->nexti != (pc +1)->firsti
+ if (pc->nexti != (pc+1)->firsti
&& pc->nexti->opcode == Op_comment
- && pc->nexti->memory->comment_type == FULL_COMMENT)
+ && pc->nexti->memory->comment_type == BLOCK_COMMENT)
print_comment(pc->nexti, -1);
ip1 = (pc + 1)->firsti;
ip2 = (pc + 1)->lasti;
@@ -399,7 +407,21 @@ cleanup:
t2 = pp_pop();
t1 = pp_pop();
parenthesize(pc->opcode, t1, t2);
- str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
+ if (pc->comment == NULL)
+ str = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
+ else {
+ check_indent_level();
+
+ size_t len = strlen(t1->pp_str)
+ + strlen(op2str(pc->opcode)) + strlen(t2->pp_str) // foo && bar
+ + indent_level + 1 // indent
+ + pc->comment->memory->stlen + 3; // tab comment
+
+ emalloc(str, char *, len, "pprint");
+ sprintf(str, "%s%s%s%.*s %s", t1->pp_str, op2str(pc->opcode),
+ pc->comment->memory->stptr,
+ (int) indent_level + 1, tabs, t2->pp_str);
+ }
pp_free(t1);
pp_free(t2);
pp_push(pc->opcode, str, CAN_FREE);
@@ -624,7 +646,8 @@ cleanup:
case Op_K_printf:
case Op_K_print_rec:
if (pc->opcode == Op_K_print_rec)
- tmp = pp_group3(" ", op2str(Op_field_spec), "0");
+ // instead of `print $0', just `print'
+ tmp = strdup("");
else if (pc->redir_type != 0)
tmp = pp_list(pc->expr_count, "()", ", ");
else {
@@ -820,13 +843,34 @@ cleanup:
indent(SPACEOVER);
t1 = pp_pop();
fprintf(prof_fp, "} %s (%s)", op2str(Op_K_while), t1->pp_str);
+ if (pc->comment)
+ fprintf(prof_fp, "\t%s", pc->comment->memory->stptr);
+ else {
+ end_line(pc->target_break);
+ skip_comment = true;
+ }
pp_free(t1);
- end_line(pc->target_break);
- skip_comment = true;
pc = pc->target_break;
break;
case Op_K_for:
+ {
+ INSTRUCTION *comment1 = NULL, *comment2 = NULL;
+
+ if (pc->comment != NULL) {
+ comment1 = pc->comment;
+ pc->comment = NULL;
+ if (comment1 != NULL && comment1->comment != NULL) {
+ comment2 = comment1->comment;
+ comment1->comment = NULL;
+ }
+ if (comment2 == NULL && comment1->memory->comment_type == FOR_COMMENT) {
+ comment2 = comment1;
+ comment2->memory->comment_type = EOL_COMMENT;
+ comment1 = NULL;
+ }
+ }
+
ip1 = pc + 1;
indent(ip1->forloop_body->exec_count);
fprintf(prof_fp, "%s (", op2str(pc->opcode));
@@ -834,12 +878,19 @@ cleanup:
/* If empty for looop header, print it a little more nicely. */
if ( pc->nexti->opcode == Op_no_op
&& ip1->forloop_cond == pc->nexti
- && pc->target_continue->opcode == Op_jmp) {
+ && pc->target_continue->opcode == Op_jmp
+ && comment1 == NULL && comment2 == NULL) {
fprintf(prof_fp, ";;");
} else {
pprint(pc->nexti, ip1->forloop_cond, IN_FOR_HEADER);
fprintf(prof_fp, "; ");
+ if (comment1 != NULL) {
+ print_comment(comment1, 0);
+ indent(ip1->forloop_body->exec_count);
+ indent(1);
+ }
+
if (ip1->forloop_cond->opcode == Op_no_op &&
ip1->forloop_cond->nexti == ip1->forloop_body)
fprintf(prof_fp, "; ");
@@ -850,6 +901,12 @@ cleanup:
pp_free(t1);
}
+ if (comment2 != NULL) {
+ print_comment(comment2, 0);
+ indent(ip1->forloop_body->exec_count);
+ indent(1);
+ }
+
pprint(pc->target_continue, pc->target_break, IN_FOR_HEADER);
}
fprintf(prof_fp, ") {");
@@ -863,6 +920,7 @@ cleanup:
end_line(pc->target_break);
skip_comment = true;
pc = pc->target_break;
+ }
break;
case Op_K_arrayfor:
@@ -901,10 +959,14 @@ cleanup:
pprint(pc->nexti, ip1->switch_start, NO_PPRINT_FLAGS);
t1 = pp_pop();
fprintf(prof_fp, "%s) {\n", t1->pp_str);
+ if (pc->comment)
+ print_comment(pc->comment, 0);
pp_free(t1);
pprint(ip1->switch_start, ip1->switch_end, NO_PPRINT_FLAGS);
indent(SPACEOVER);
fprintf(prof_fp, "}\n");
+ if (ip1->switch_end->comment)
+ print_comment(ip1->switch_end->comment, 0);
pc = pc->target_break;
break;
@@ -914,13 +976,20 @@ cleanup:
if (pc->opcode == Op_K_case) {
t1 = pp_pop();
fprintf(prof_fp, "%s %s:", op2str(pc->opcode), t1->pp_str);
- pc = end_line(pc);
pp_free(t1);
- } else {
+ } else
fprintf(prof_fp, "%s:", op2str(pc->opcode));
- pc = end_line(pc);
- }
+
indent_in();
+ if (pc->comment != NULL) {
+ if (pc->comment->memory->comment_type == EOL_COMMENT)
+ fprintf(prof_fp, "\t%s", pc->comment->memory->stptr);
+ else {
+ fprintf(prof_fp, "\n");
+ print_comment(pc->comment, indent_level);
+ }
+ } else
+ fprintf(prof_fp, "\n");
pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, NO_PPRINT_FLAGS);
indent_out();
break;
@@ -937,6 +1006,8 @@ cleanup:
fprintf(prof_fp, " # %ld", ip1->exec_count);
ip1 = end_line(ip1);
indent_in();
+ if (pc->comment != NULL)
+ print_comment(pc->comment, indent_level);
pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS);
indent_out();
pc = pc->branch_else;
@@ -944,7 +1015,7 @@ cleanup:
indent(SPACEOVER);
fprintf(prof_fp, "}");
if (pc->nexti->nexti->opcode != Op_comment
- || pc->nexti->nexti->memory->comment_type == FULL_COMMENT)
+ || pc->nexti->nexti->memory->comment_type == BLOCK_COMMENT)
fprintf(prof_fp, "\n");
/* else
It will be printed at the top. */
@@ -980,6 +1051,8 @@ cleanup:
end_line(pc);
skip_comment = true;
indent_in();
+ if (pc->comment != NULL)
+ print_comment(pc->comment, indent_level);
pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
indent_out();
indent(SPACEOVER);
@@ -999,6 +1072,9 @@ cleanup:
{
NODE *f, *t, *cond;
size_t len;
+ INSTRUCTION *qm_comment = NULL, *colon_comment = NULL;
+
+ qm_comment = pc->comment;
pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS);
ip1 = pc->branch_if;
@@ -1006,6 +1082,7 @@ cleanup:
ip1 = pc->branch_else->nexti;
pc = ip1->nexti;
+ colon_comment = pc->comment;
assert(pc->opcode == Op_cond_exp);
pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
@@ -1013,9 +1090,72 @@ cleanup:
t = pp_pop();
cond = pp_pop();
- len = f->pp_len + t->pp_len + cond->pp_len + 12;
- emalloc(str, char *, len, "pprint");
- sprintf(str, "%s ? %s : %s", cond->pp_str, t->pp_str, f->pp_str);
+ /*
+ * This stuff handles comments that come after a ?, :, or both.
+ * Allowing newlines after ? and : is a gawk extension.
+ * Theoretically this is fragile, since ?: expressions can be nested.
+ * In practice, it's not, since if there was a comment following ? or :
+ * in the original code, then it wasn't nested.
+ */
+
+ len = f->pp_len + t->pp_len + cond->pp_len + 12;
+ if (qm_comment == NULL && colon_comment == NULL) {
+ // easy case
+ emalloc(str, char *, len, "pprint");
+ sprintf(str, "%s ? %s : %s", cond->pp_str, t->pp_str, f->pp_str);
+ } else if (qm_comment != NULL && colon_comment != NULL) {
+ check_indent_level();
+ len += qm_comment->memory->stlen + // comments
+ colon_comment->memory->stlen +
+ 2 * (indent_level + 1) + 3 + // indentation
+ t->pp_len + 6;
+ emalloc(str, char *, len, "pprint");
+ sprintf(str,
+ "%s ? %s" // cond ? comment
+ "%.*s %s" // indent true-part
+ " : %s" // : comment
+ "%.*s %s", // indent false-part
+ cond->pp_str, // condition
+ qm_comment->memory->stptr, // comment
+ (int) indent_level + 1, tabs, // indent
+ t->pp_str, // true part
+ colon_comment->memory->stptr, // comment
+ (int) indent_level + 1, tabs, // indent
+ f->pp_str // false part
+ );
+ } else if (qm_comment != NULL) {
+ check_indent_level();
+ len += qm_comment->memory->stlen + // comment
+ 1 * (indent_level + 1) + 3 + // indentation
+ t->pp_len + 3;
+ emalloc(str, char *, len, "pprint");
+ sprintf(str,
+ "%s ? %s" // cond ? comment
+ "%.*s %s" // indent true-part
+ " : %s", // : false-part
+ cond->pp_str, // condition
+ qm_comment->memory->stptr, // comment
+ (int) indent_level + 1, tabs, // indent
+ t->pp_str, // true part
+ f->pp_str // false part
+ );
+ } else {
+ check_indent_level();
+ len += colon_comment->memory->stlen + // comment
+ 1 * (indent_level + 1) + 3 + // indentation
+ t->pp_len + 3;
+ emalloc(str, char *, len, "pprint");
+ sprintf(str,
+ "%s ? %s" // cond ? true-part
+ " : %s" // : comment
+ "%.*s %s", // indent false-part
+ cond->pp_str, // condition
+ t->pp_str, // true part
+ colon_comment->memory->stptr, // comment
+ (int) indent_level + 1, tabs, // indent
+ f->pp_str // false part
+ );
+ }
pp_free(cond);
pp_free(t);
@@ -1065,7 +1205,7 @@ end_line(INSTRUCTION *ip)
return ret;
}
-/* pp_string_fp --- printy print a string to the fp */
+/* pp_string_fp --- pretty print a string to the fp */
/*
* This routine concentrates string pretty printing in one place,
@@ -1124,17 +1264,28 @@ print_lib_list(FILE *prof_fp)
{
SRCFILE *s;
static bool printed_header = false;
+ const char *indent = "";
+ bool found = false;
+
+ if (do_profile)
+ indent = "\t";
for (s = srcfiles->next; s != srcfiles; s = s->next) {
if (s->stype == SRC_EXTLIB) {
- if (! printed_header) {
+ if (do_profile && ! printed_header) {
printed_header = true;
- fprintf(prof_fp, _("\t# Loaded extensions (-l and/or @load)\n\n"));
+ fprintf(prof_fp, _("%s# Loaded extensions (-l and/or @load)\n\n"), indent);
}
- fprintf(prof_fp, "\t@load \"%s\"\n", s->src);
+ found = true;
+ fprintf(prof_fp, "%s@load \"%s\"", indent, s->src);
+ if (s->comment != NULL) {
+ fprintf(prof_fp, "\t");
+ print_comment(s->comment, indent_level + 1);
+ } else
+ fprintf(prof_fp, "\n");
}
}
- if (printed_header) /* we found some */
+ if (found) /* we found some */
fprintf(prof_fp, "\n");
}
@@ -1158,8 +1309,13 @@ print_comment(INSTRUCTION* pc, long in)
after_newline = false;
}
putc(*text, prof_fp);
- if (*text == '\n')
- after_newline = true;
+ after_newline = (*text == '\n');
+ }
+
+ if (pc->comment) {
+ // chaining should only be two deep
+ assert(pc->comment->comment == NULL);
+ print_comment(pc->comment, in);
}
}
@@ -1736,10 +1892,8 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
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;
- }
+ if (pc->comment != NULL)
+ print_comment(pc->comment, -1); /* -1 ==> don't indent */
indent(pc->nexti->exec_count);
fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);