00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "awk.h"
00027
00028
00029 enum redir_placement {
00030 BEFORE = 0,
00031 AFTER = 1
00032 };
00033
00034 #undef tree_eval
00035 static void tree_eval P((NODE *tree));
00036 static void parenthesize P((NODETYPE parent_type, NODE *tree));
00037 static void eval_condition P((NODE *tree));
00038 static void pp_op_assign P((NODE *tree));
00039 static void pp_func_call P((NODE *tree));
00040 static void pp_match_op P((NODE *tree));
00041 static void pp_lhs P((NODE *ptr));
00042 static void pp_print_stmt P((const char *command, NODE *tree));
00043 static void pp_delete P((NODE *tree));
00044 static void pp_in_array P((NODE *array, NODE *subscript));
00045 static void pp_getline P((NODE *tree));
00046 static void pp_builtin P((NODE *tree));
00047 static void pp_list P((NODE *tree));
00048 static void pp_string P((const char *str, size_t len, int delim));
00049 static int is_scalar P((NODETYPE type));
00050 static int prec_level P((NODETYPE type));
00051 #ifdef PROFILING
00052 static RETSIGTYPE dump_and_exit P((int signum)) ATTRIBUTE_NORETURN;
00053 static RETSIGTYPE just_dump P((int signum));
00054 #endif
00055
00056
00057
00058 static char **fparms;
00059 static FILE *prof_fp;
00060
00061 static long indent_level = 0;
00062
00063 static int in_BEGIN_or_END = FALSE;
00064
00065 static int in_expr = FALSE;
00066
00067 #define SPACEOVER 0
00068
00069
00070
00071 void
00072 init_profiling(int *flag ATTRIBUTE_UNUSED, const char *def_file ATTRIBUTE_UNUSED)
00073 {
00074 #ifdef PROFILING
00075 if (*flag == FALSE) {
00076 *flag = TRUE;
00077 set_prof_file(def_file);
00078 }
00079 #endif
00080 }
00081
00082
00083
00084 void
00085 set_prof_file(const char *file)
00086 {
00087 assert(file != NULL);
00088
00089 prof_fp = fopen(file, "w");
00090 if (prof_fp == NULL) {
00091 warning(_("could not open `%s' for writing: %s"),
00092 file, strerror(errno));
00093 warning(_("sending profile to standard error"));
00094 prof_fp = stderr;
00095 }
00096 }
00097
00098
00099
00100 void
00101 init_profiling_signals()
00102 {
00103 #ifdef PROFILING
00104 #ifdef __DJGPP__
00105 signal(SIGINT, dump_and_exit);
00106 signal(SIGQUIT, just_dump);
00107 #else
00108 #ifdef SIGHUP
00109 signal(SIGHUP, dump_and_exit);
00110 #endif
00111 #ifdef SIGUSR1
00112 signal(SIGUSR1, just_dump);
00113 #endif
00114 #endif
00115 #endif
00116 }
00117
00118
00119
00120 static void
00121 indent(long count)
00122 {
00123 int i;
00124
00125 if (count == 0)
00126 putc('\t', prof_fp);
00127 else
00128 fprintf(prof_fp, "%6ld ", count);
00129
00130 assert(indent_level >= 0);
00131 for (i = 0; i < indent_level; i++)
00132 putc('\t', prof_fp);
00133 }
00134
00135
00136
00137 static void
00138 indent_in(void)
00139 {
00140 assert(indent_level >= 0);
00141 indent_level++;
00142 }
00143
00144
00145
00146 static void
00147 indent_out(void)
00148 {
00149 indent_level--;
00150 assert(indent_level >= 0);
00151 }
00152
00153
00154
00155
00156
00157
00158 static void
00159 pprint(register NODE *volatile tree)
00160 {
00161 register NODE *volatile t = NULL;
00162 int volatile traverse = TRUE;
00163
00164
00165 source = NULL;
00166 sourceline = 0;
00167
00168 if (tree == NULL)
00169 return;
00170 sourceline = tree->source_line;
00171 source = tree->source_file;
00172 switch (tree->type) {
00173 case Node_rule_node:
00174 traverse = FALSE;
00175
00176 case Node_rule_list:
00177 for (t = tree; t != NULL; t = t->rnode) {
00178 if (traverse)
00179 tree = t->lnode;
00180 sourceline = tree->source_line;
00181 source = tree->source_file;
00182
00183 if (! in_BEGIN_or_END)
00184 indent(tree->exec_count);
00185
00186 if (tree->lnode) {
00187 eval_condition(tree->lnode);
00188 if (tree->rnode)
00189 fprintf(prof_fp, "\t");
00190 }
00191
00192 if (tree->rnode) {
00193 if (! in_BEGIN_or_END) {
00194 fprintf(prof_fp, "{");
00195 if (tree->lnode != NULL
00196 && tree->lnode->exec_count)
00197 fprintf(prof_fp, " # %ld",
00198 tree->lnode->exec_count);
00199 fprintf(prof_fp, "\n");
00200 }
00201 indent_in();
00202 pprint(tree->rnode);
00203 indent_out();
00204 if (! in_BEGIN_or_END) {
00205 indent(SPACEOVER);
00206 fprintf(prof_fp, "}\n");
00207 }
00208 }
00209
00210 if (! traverse)
00211 break;
00212
00213 if (t->rnode && ! in_BEGIN_or_END)
00214 fprintf(prof_fp, "\n");
00215 }
00216 break;
00217
00218 case Node_statement_list:
00219 for (t = tree; t != NULL; t = t->rnode) {
00220 pprint(t->lnode);
00221 }
00222 break;
00223
00224 case Node_K_if:
00225 indent(tree->exec_count);
00226 fprintf(prof_fp, "if (");
00227 in_expr++;
00228 eval_condition(tree->lnode);
00229 in_expr--;
00230 fprintf(prof_fp, ") {");
00231 #ifdef PROFILING
00232 if (tree->rnode->exec_count)
00233 fprintf(prof_fp, " # %ld", tree->rnode->exec_count);
00234 #endif
00235 fprintf(prof_fp, "\n");
00236 indent_in();
00237 pprint(tree->rnode->lnode);
00238 indent_out();
00239 if (tree->rnode->rnode != NULL) {
00240 if (tree->exec_count - tree->rnode->exec_count > 0)
00241 indent(tree->exec_count - tree->rnode->exec_count);
00242 else
00243 indent(0);
00244 fprintf(prof_fp, "} else {\n");
00245 indent_in();
00246 pprint(tree->rnode->rnode);
00247 indent_out();
00248 }
00249 indent(SPACEOVER);
00250 fprintf(prof_fp, "}\n");
00251 break;
00252
00253 case Node_K_switch:
00254 indent(tree->exec_count);
00255 fprintf(prof_fp, "switch (");
00256 in_expr++;
00257 pprint(tree->lnode);
00258 in_expr--;
00259 fprintf(prof_fp, ") {\n");
00260 pprint(tree->rnode);
00261 indent(SPACEOVER);
00262 fprintf(prof_fp, "}\n");
00263 break;
00264
00265 case Node_switch_body:
00266 case Node_case_list:
00267 pprint(tree->lnode);
00268 pprint(tree->rnode);
00269 break;
00270
00271 case Node_K_case:
00272 indent(tree->exec_count);
00273 fprintf(prof_fp, "case ");
00274 in_expr++;
00275 pprint(tree->lnode);
00276 in_expr--;
00277 fprintf(prof_fp, ":\n");
00278 indent_in();
00279 pprint(tree->rnode);
00280 indent_out();
00281 break;
00282
00283 case Node_K_default:
00284 indent(tree->exec_count);
00285 fprintf(prof_fp, "default:\n");
00286 indent_in();
00287 pprint(tree->rnode);
00288 indent_out();
00289 break;
00290
00291 case Node_K_while:
00292 indent(tree->exec_count);
00293 fprintf(prof_fp, "while (");
00294 in_expr++;
00295 eval_condition(tree->lnode);
00296 in_expr--;
00297 fprintf(prof_fp, ") {\n");
00298 indent_in();
00299 pprint(tree->rnode);
00300 indent_out();
00301 indent(SPACEOVER);
00302 fprintf(prof_fp, "}\n");
00303 break;
00304
00305 case Node_K_do:
00306 indent(tree->exec_count);
00307 fprintf(prof_fp, "do {\n");
00308 indent_in();
00309 pprint(tree->rnode);
00310 indent_out();
00311 indent(SPACEOVER);
00312 fprintf(prof_fp, "} while (");
00313 in_expr++;
00314 eval_condition(tree->lnode);
00315 in_expr--;
00316 fprintf(prof_fp, ")\n");
00317 break;
00318
00319 case Node_K_for:
00320 indent(tree->exec_count);
00321 fprintf(prof_fp, "for (");
00322 in_expr++;
00323 pprint(tree->forloop->init);
00324 fprintf(prof_fp, "; ");
00325 eval_condition(tree->forloop->cond);
00326 fprintf(prof_fp, "; ");
00327 pprint(tree->forloop->incr);
00328 fprintf(prof_fp, ") {\n");
00329 in_expr--;
00330 indent_in();
00331 pprint(tree->lnode);
00332 indent_out();
00333 indent(SPACEOVER);
00334 fprintf(prof_fp, "}\n");
00335 break;
00336
00337 case Node_K_arrayfor:
00338 #define hakvar forloop->init
00339 #define arrvar forloop->incr
00340 indent(tree->exec_count);
00341 fprintf(prof_fp, "for (");
00342 in_expr++;
00343 pp_lhs(tree->hakvar);
00344 in_expr--;
00345 fprintf(prof_fp, " in ");
00346 t = tree->arrvar;
00347 if (t->type == Node_param_list)
00348 fprintf(prof_fp, "%s", fparms[t->param_cnt]);
00349 else
00350 fprintf(prof_fp, "%s", t->vname);
00351 fprintf(prof_fp, ") {\n");
00352 indent_in();
00353 pprint(tree->lnode);
00354 indent_out();
00355 indent(SPACEOVER);
00356 fprintf(prof_fp, "}\n");
00357 break;
00358 #undef hakvar
00359 #undef arrvar
00360
00361 case Node_K_break:
00362 indent(tree->exec_count);
00363 fprintf(prof_fp, "break\n");
00364 break;
00365
00366 case Node_K_continue:
00367 indent(tree->exec_count);
00368 fprintf(prof_fp, "continue\n");
00369 break;
00370
00371 case Node_K_print:
00372 case Node_K_print_rec:
00373 pp_print_stmt("print", tree);
00374 break;
00375
00376 case Node_K_printf:
00377 pp_print_stmt("printf", tree);
00378 break;
00379
00380 case Node_K_delete:
00381 pp_delete(tree);
00382 break;
00383
00384 case Node_K_next:
00385 indent(tree->exec_count);
00386 fprintf(prof_fp, "next\n");
00387 break;
00388
00389 case Node_K_nextfile:
00390 indent(tree->exec_count);
00391 fprintf(prof_fp, "nextfile\n");
00392 break;
00393
00394 case Node_K_exit:
00395 indent(tree->exec_count);
00396 fprintf(prof_fp, "exit");
00397 if (tree->lnode != NULL) {
00398 fprintf(prof_fp, " ");
00399 tree_eval(tree->lnode);
00400 }
00401 fprintf(prof_fp, "\n");
00402 break;
00403
00404 case Node_K_return:
00405 indent(tree->exec_count);
00406 fprintf(prof_fp, "return");
00407 if (tree->lnode != NULL) {
00408 fprintf(prof_fp, " ");
00409 tree_eval(tree->lnode);
00410 }
00411 fprintf(prof_fp, "\n");
00412 break;
00413
00414 default:
00415
00416
00417
00418
00419 if (in_expr)
00420 tree_eval(tree);
00421 else {
00422 indent(tree->exec_count);
00423 tree_eval(tree);
00424 fprintf(prof_fp, "\n");
00425 }
00426 break;
00427 }
00428 }
00429
00430
00431
00432 static void
00433 tree_eval(register NODE *tree)
00434 {
00435 if (tree == NULL)
00436 return;
00437
00438 switch (tree->type) {
00439 case Node_param_list:
00440 fprintf(prof_fp, "%s", fparms[tree->param_cnt]);
00441 return;
00442
00443 case Node_var_new:
00444 case Node_var:
00445 case Node_var_array:
00446 if (tree->vname != NULL)
00447 fprintf(prof_fp, "%s", tree->vname);
00448 else
00449 fatal(_("internal error: %s with null vname"),
00450 nodetype2str(tree->type));
00451 return;
00452
00453 case Node_val:
00454 if ((tree->flags & NUMBER) != 0)
00455 fprintf(prof_fp, "%g", tree->numbr);
00456 else {
00457 if ((tree->flags & INTLSTR) != 0)
00458 fprintf(prof_fp, "_");
00459 pp_string(tree->stptr, tree->stlen, '"');
00460 }
00461 return;
00462
00463 case Node_and:
00464 eval_condition(tree->lnode);
00465 fprintf(prof_fp, " && ");
00466 eval_condition(tree->rnode);
00467 return;
00468
00469 case Node_or:
00470 eval_condition(tree->lnode);
00471 fprintf(prof_fp, " || ");
00472 eval_condition(tree->rnode);
00473 return;
00474
00475 case Node_not:
00476 parenthesize(tree->type, tree->lnode);
00477 return;
00478
00479
00480 case Node_builtin:
00481 pp_builtin(tree);
00482 return;
00483
00484 case Node_in_array:
00485 in_expr++;
00486 pp_in_array(tree->lnode, tree->rnode);
00487 in_expr--;
00488 return;
00489
00490 case Node_func_call:
00491 pp_func_call(tree);
00492 return;
00493
00494 case Node_K_getline:
00495 pp_getline(tree);
00496 return;
00497
00498 case Node_K_delete_loop:
00499 {
00500 char *aname;
00501 NODE *t;
00502
00503 t = tree->lnode;
00504 if (t->type == Node_param_list)
00505 aname = fparms[t->param_cnt];
00506 else
00507 aname = t->vname;
00508
00509 fprintf(prof_fp, "for (");
00510 pp_lhs(tree->rnode->lnode);
00511 fprintf(prof_fp, " in %s) { %s %s'\n", aname,
00512 _("# treated internally as `delete'"), aname);
00513 indent_in();
00514 indent(SPACEOVER);
00515 fprintf(prof_fp, "delete %s[", aname);
00516 pp_lhs(tree->rnode->lnode);
00517 fprintf(prof_fp, "]\n");
00518 indent_out();
00519 indent(SPACEOVER);
00520 fprintf(prof_fp, "}");
00521 }
00522 return;
00523
00524
00525 case Node_NR:
00526 fprintf(prof_fp, "NR");
00527 return;
00528
00529 case Node_FNR:
00530 fprintf(prof_fp, "FNR");
00531 return;
00532
00533 case Node_NF:
00534 fprintf(prof_fp, "NF");
00535 return;
00536
00537 case Node_FIELDWIDTHS:
00538 fprintf(prof_fp, "FIELDWIDTHS");
00539 return;
00540
00541 case Node_FS:
00542 fprintf(prof_fp, "FS");
00543 return;
00544
00545 case Node_RS:
00546 fprintf(prof_fp, "RS");
00547 return;
00548
00549 case Node_IGNORECASE:
00550 fprintf(prof_fp, "IGNORECASE");
00551 return;
00552
00553 case Node_OFS:
00554 fprintf(prof_fp, "OFS");
00555 return;
00556
00557 case Node_ORS:
00558 fprintf(prof_fp, "ORS");
00559 return;
00560
00561 case Node_OFMT:
00562 fprintf(prof_fp, "OFMT");
00563 return;
00564
00565 case Node_CONVFMT:
00566 fprintf(prof_fp, "CONVFMT");
00567 return;
00568
00569 case Node_BINMODE:
00570 fprintf(prof_fp, "BINMODE");
00571 return;
00572
00573 case Node_TEXTDOMAIN:
00574 fprintf(prof_fp, "TEXTDOMAIN");
00575 return;
00576
00577 case Node_field_spec:
00578 case Node_subscript:
00579 pp_lhs(tree);
00580 return;
00581
00582 case Node_unary_minus:
00583 fprintf(prof_fp, " -");
00584 if (is_scalar(tree->subnode->type))
00585 tree_eval(tree->subnode);
00586 else {
00587 fprintf(prof_fp, "(");
00588 tree_eval(tree->subnode);
00589 fprintf(prof_fp, ")");
00590 }
00591 return;
00592
00593 case Node_cond_exp:
00594 eval_condition(tree->lnode);
00595 fprintf(prof_fp, " ? ");
00596 tree_eval(tree->rnode->lnode);
00597 fprintf(prof_fp, " : ");
00598 tree_eval(tree->rnode->rnode);
00599 return;
00600
00601 case Node_match:
00602 case Node_nomatch:
00603 case Node_regex:
00604 case Node_dynregex:
00605 pp_match_op(tree);
00606 return;
00607
00608
00609 case Node_assign:
00610 tree_eval(tree->lnode);
00611 fprintf(prof_fp, " = ");
00612 tree_eval(tree->rnode);
00613 return;
00614
00615 case Node_concat:
00616 fprintf(prof_fp, "(");
00617 tree_eval(tree->lnode);
00618 fprintf(prof_fp, " ");
00619 tree_eval(tree->rnode);
00620 fprintf(prof_fp, ")");
00621 return;
00622
00623
00624 case Node_preincrement:
00625 case Node_predecrement:
00626 case Node_postincrement:
00627 case Node_postdecrement:
00628 case Node_assign_exp:
00629 case Node_assign_times:
00630 case Node_assign_quotient:
00631 case Node_assign_mod:
00632 case Node_assign_plus:
00633 case Node_assign_minus:
00634 pp_op_assign(tree);
00635 return;
00636
00637 default:
00638 break;
00639 }
00640
00641
00642 in_expr++;
00643 parenthesize(tree->type, tree->lnode);
00644
00645 switch (tree->type) {
00646 case Node_geq:
00647 fprintf(prof_fp, " >= ");
00648 break;
00649 case Node_leq:
00650 fprintf(prof_fp, " <= ");
00651 break;
00652 case Node_greater:
00653 fprintf(prof_fp, " > ");
00654 break;
00655 case Node_less:
00656 fprintf(prof_fp, " < ");
00657 break;
00658 case Node_notequal:
00659 fprintf(prof_fp, " != ");
00660 break;
00661 case Node_equal:
00662 fprintf(prof_fp, " == ");
00663 break;
00664 case Node_exp:
00665 fprintf(prof_fp, " ^ ");
00666 break;
00667 case Node_times:
00668 fprintf(prof_fp, " * ");
00669 break;
00670 case Node_quotient:
00671 fprintf(prof_fp, " / ");
00672 break;
00673 case Node_mod:
00674 fprintf(prof_fp, " %% ");
00675 break;
00676 case Node_plus:
00677 fprintf(prof_fp, " + ");
00678 break;
00679 case Node_minus:
00680 fprintf(prof_fp, " - ");
00681 break;
00682 default:
00683 fatal(_("illegal type (%s) in tree_eval"), nodetype2str(tree->type));
00684 }
00685 parenthesize(tree->type, tree->rnode);
00686 in_expr--;
00687
00688 return;
00689 }
00690
00691
00692
00693 static void
00694 eval_condition(register NODE *tree)
00695 {
00696 if (tree == NULL)
00697 return;
00698
00699 if (tree->type == Node_line_range) {
00700
00701 eval_condition(tree->condpair->lnode);
00702 fprintf(prof_fp,", ");
00703 eval_condition(tree->condpair->rnode);
00704 return;
00705 }
00706
00707
00708
00709
00710
00711
00712 tree_eval(tree);
00713 return;
00714 }
00715
00716
00717
00718 static void
00719 pp_op_assign(register NODE *tree)
00720 {
00721 const char *op = NULL;
00722 enum Order {
00723 NA = 0,
00724 PRE = 1,
00725 POST = 2
00726 } order = NA;
00727
00728 switch(tree->type) {
00729 case Node_preincrement:
00730 op = "++";
00731 order = PRE;
00732 break;
00733
00734 case Node_predecrement:
00735 op = "--";
00736 order = PRE;
00737 break;
00738
00739 case Node_postincrement:
00740 op = "++";
00741 order = POST;
00742 break;
00743
00744 case Node_postdecrement:
00745 op = "--";
00746 order = POST;
00747 break;
00748
00749 default:
00750 break;
00751 }
00752
00753 if (order == PRE) {
00754 fprintf(prof_fp, "%s", op);
00755 pp_lhs(tree->lnode);
00756 return;
00757 } else if (order == POST) {
00758 pp_lhs(tree->lnode);
00759 fprintf(prof_fp, "%s", op);
00760 return;
00761 }
00762
00763
00764 pp_lhs(tree->lnode);
00765
00766 switch(tree->type) {
00767 case Node_assign_exp:
00768 fprintf(prof_fp, " ^= ");
00769 break;
00770
00771 case Node_assign_times:
00772 fprintf(prof_fp, " *= ");
00773 break;
00774
00775 case Node_assign_quotient:
00776 fprintf(prof_fp, " /= ");
00777 break;
00778
00779 case Node_assign_mod:
00780 fprintf(prof_fp, " %%= ");
00781 break;
00782
00783 case Node_assign_plus:
00784 fprintf(prof_fp, " += ");
00785 break;
00786
00787 case Node_assign_minus:
00788 fprintf(prof_fp, " -= ");
00789 break;
00790
00791 default:
00792 cant_happen();
00793 }
00794
00795 tree_eval(tree->rnode);
00796 }
00797
00798
00799
00800 static void
00801 pp_lhs(register NODE *ptr)
00802 {
00803 register NODE *n;
00804
00805 switch (ptr->type) {
00806 case Node_var_array:
00807 fatal(_("attempt to use array `%s' in a scalar context"),
00808 ptr->vname);
00809
00810 case Node_var_new:
00811 case Node_var:
00812 fprintf(prof_fp, "%s", ptr->vname);
00813 break;
00814
00815 case Node_FIELDWIDTHS:
00816 fprintf(prof_fp, "FIELDWIDTHS");
00817 break;
00818
00819 case Node_RS:
00820 fprintf(prof_fp, "RS");
00821 break;
00822
00823 case Node_FS:
00824 fprintf(prof_fp, "FS");
00825 break;
00826
00827 case Node_FNR:
00828 fprintf(prof_fp, "FNR");
00829 break;
00830
00831 case Node_NR:
00832 fprintf(prof_fp, "NR");
00833 break;
00834
00835 case Node_NF:
00836 fprintf(prof_fp, "NF");
00837 break;
00838
00839 case Node_IGNORECASE:
00840 fprintf(prof_fp, "IGNORECASE");
00841 break;
00842
00843 case Node_BINMODE:
00844 fprintf(prof_fp, "BINMODE");
00845 break;
00846
00847 case Node_LINT:
00848 fprintf(prof_fp, "LINT");
00849 break;
00850
00851 case Node_OFMT:
00852 fprintf(prof_fp, "OFMT");
00853 break;
00854
00855 case Node_CONVFMT:
00856 fprintf(prof_fp, "CONVFMT");
00857 break;
00858
00859 case Node_ORS:
00860 fprintf(prof_fp, "ORS");
00861 break;
00862
00863 case Node_OFS:
00864 fprintf(prof_fp, "OFS");
00865 break;
00866
00867 case Node_TEXTDOMAIN:
00868 fprintf(prof_fp, "TEXTDOMAIN");
00869 break;
00870
00871 case Node_param_list:
00872 fprintf(prof_fp, "%s", fparms[ptr->param_cnt]);
00873 break;
00874
00875 case Node_field_spec:
00876 fprintf(prof_fp, "$");
00877 if (is_scalar(ptr->lnode->type))
00878 tree_eval(ptr->lnode);
00879 else {
00880 fprintf(prof_fp, "(");
00881 tree_eval(ptr->lnode);
00882 fprintf(prof_fp, ")");
00883 }
00884 break;
00885
00886 case Node_subscript:
00887 n = ptr->lnode;
00888 if (n->type == Node_param_list) {
00889 fprintf(prof_fp, "%s[", fparms[n->param_cnt]);
00890 } else
00891 fprintf(prof_fp, "%s[", n->vname);
00892 if (ptr->rnode->type == Node_expression_list)
00893 pp_list(ptr->rnode);
00894 else
00895 tree_eval(ptr->rnode);
00896 fprintf(prof_fp, "]");
00897 break;
00898
00899 case Node_builtin:
00900 fatal(_("assignment is not allowed to result of builtin function"));
00901
00902 default:
00903 cant_happen();
00904 }
00905 }
00906
00907
00908
00909 static void
00910 pp_match_op(register NODE *tree)
00911 {
00912 register NODE *re;
00913 const char *op;
00914 const char *restr;
00915 size_t relen;
00916 NODE *text = NULL;
00917
00918 if (tree->type == Node_dynregex) {
00919 tree_eval(tree->re_exp);
00920 return;
00921 }
00922
00923 if (tree->type == Node_regex) {
00924 re = tree->re_exp;
00925 restr = re->stptr;
00926 relen = re->stlen;
00927 pp_string(restr, relen, '/');
00928 return;
00929 }
00930
00931
00932
00933 text = tree->lnode;
00934 re = tree->rnode;
00935
00936 if (tree->type == Node_nomatch)
00937 op = "!~";
00938 else if (tree->type == Node_match)
00939 op = "~";
00940 else
00941 op = "";
00942
00943 tree_eval(text);
00944 fprintf(prof_fp, " %s ", op);
00945 tree_eval(re);
00946 }
00947
00948
00949
00950 static void
00951 pp_redir(register NODE *tree, enum redir_placement dir)
00952 {
00953 const char *op = "[BOGUS]";
00954
00955 if (tree == NULL)
00956 return;
00957
00958 switch (tree->type) {
00959 case Node_redirect_output:
00960 op = ">";
00961 break;
00962 case Node_redirect_append:
00963 op = ">>";
00964 break;
00965 case Node_redirect_pipe:
00966 op = "|";
00967 break;
00968 case Node_redirect_pipein:
00969 op = "|";
00970 break;
00971 case Node_redirect_input:
00972 op = "<";
00973 break;
00974 case Node_redirect_twoway:
00975 op = "|&";
00976 break;
00977 default:
00978 cant_happen();
00979 }
00980
00981 if (dir == BEFORE) {
00982 if (! is_scalar(tree->subnode->type)) {
00983 fprintf(prof_fp, "(");
00984 tree_eval(tree->subnode);
00985 fprintf(prof_fp, ")");
00986 } else
00987 tree_eval(tree->subnode);
00988 fprintf(prof_fp, " %s ", op);
00989 } else {
00990 fprintf(prof_fp, " %s ", op);
00991 if (! is_scalar(tree->subnode->type)) {
00992 fprintf(prof_fp, "(");
00993 tree_eval(tree->subnode);
00994 fprintf(prof_fp, ")");
00995 } else
00996 tree_eval(tree->subnode);
00997 }
00998 }
00999
01000
01001
01002 static void
01003 pp_list(register NODE *tree)
01004 {
01005 for (; tree != NULL; tree = tree->rnode) {
01006 if (tree->type != Node_expression_list) {
01007 fprintf(stderr, "pp_list: got %s\n",
01008 nodetype2str(tree->type));
01009 fflush(stderr);
01010 }
01011 assert(tree->type == Node_expression_list);
01012 tree_eval(tree->lnode);
01013 if (tree->rnode != NULL)
01014 fprintf(prof_fp, ", ");
01015 }
01016 }
01017
01018
01019
01020 static void
01021 pp_print_stmt(const char *command, register NODE *tree)
01022 {
01023 NODE *redir = tree->rnode;
01024
01025 indent(tree->exec_count);
01026 fprintf(prof_fp, "%s", command);
01027 if (redir != NULL) {
01028 if (tree->lnode != NULL) {
01029
01030 fprintf(prof_fp, "(");
01031 pp_list(tree->lnode);
01032 fprintf(prof_fp, ")");
01033 } else
01034 fprintf(prof_fp, " $0");
01035 pp_redir(redir, AFTER);
01036 } else {
01037 fprintf(prof_fp, " ");
01038 if (tree->lnode != NULL)
01039 pp_list(tree->lnode);
01040 else
01041 fprintf(prof_fp, "$0");
01042 }
01043 fprintf(prof_fp, "\n");
01044 }
01045
01046
01047
01048 static void
01049 pp_delete(register NODE *tree)
01050 {
01051 NODE *array, *subscript;
01052
01053 array = tree->lnode;
01054 subscript = tree->rnode;
01055 indent(array->exec_count);
01056 if (array->type == Node_param_list)
01057 fprintf(prof_fp, "delete %s", fparms[array->param_cnt]);
01058 else
01059 fprintf(prof_fp, "delete %s", array->vname);
01060 if (subscript != NULL) {
01061 fprintf(prof_fp, "[");
01062 pp_list(subscript);
01063 fprintf(prof_fp, "]");
01064 }
01065 fprintf(prof_fp, "\n");
01066 }
01067
01068
01069
01070 static void
01071 pp_in_array(NODE *array, NODE *subscript)
01072 {
01073 if (subscript->type == Node_expression_list) {
01074 fprintf(prof_fp, "(");
01075 pp_list(subscript);
01076 fprintf(prof_fp, ")");
01077 } else
01078 pprint(subscript);
01079
01080 if (array->type == Node_param_list)
01081 fprintf(prof_fp, " in %s", fparms[array->param_cnt]);
01082 else
01083 fprintf(prof_fp, " in %s", array->vname);
01084 }
01085
01086
01087
01088 static void
01089 pp_getline(register NODE *tree)
01090 {
01091 NODE *redir = tree->rnode;
01092 int before, after;
01093
01094
01095
01096
01097
01098
01099
01100
01101 if (redir != NULL) {
01102 before = (redir->type == Node_redirect_pipein
01103 || redir->type == Node_redirect_twoway);
01104 after = ! before;
01105 } else
01106 before = after = FALSE;
01107
01108 if (before)
01109 pp_redir(redir, BEFORE);
01110
01111 fprintf(prof_fp, "getline");
01112 if (tree->lnode != NULL) {
01113 fprintf(prof_fp, " ");
01114 pp_lhs(tree->lnode);
01115 }
01116
01117 if (after)
01118 pp_redir(redir, AFTER);
01119 }
01120
01121
01122
01123 static void
01124 pp_builtin(register NODE *tree)
01125 {
01126 const char *func = getfname(tree->builtin);
01127
01128 fprintf(prof_fp, "%s(", func ? func : "extension_function");
01129 if (func)
01130 pp_list(tree->subnode);
01131 fprintf(prof_fp, ")");
01132 }
01133
01134
01135
01136 static void
01137 pp_func_call(NODE *tree)
01138 {
01139 NODE *name, *arglist;
01140
01141 name = tree->rnode;
01142 arglist = tree->lnode;
01143 fprintf(prof_fp, "%s(", name->stptr);
01144 pp_list(arglist);
01145 fprintf(prof_fp, ")");
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155 void
01156 dump_prog(NODE *begin, NODE *prog, NODE *end)
01157 {
01158 time_t now;
01159
01160 (void) time(& now);
01161
01162 fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now));
01163
01164 if (begin != NULL) {
01165 fprintf(prof_fp, _("\t# BEGIN block(s)\n\n"));
01166 fprintf(prof_fp, "\tBEGIN {\n");
01167 in_BEGIN_or_END = TRUE;
01168 pprint(begin);
01169 in_BEGIN_or_END = FALSE;
01170 fprintf(prof_fp, "\t}\n");
01171 if (prog != NULL || end != NULL)
01172 fprintf(prof_fp, "\n");
01173 }
01174 if (prog != NULL) {
01175 fprintf(prof_fp, _("\t# Rule(s)\n\n"));
01176 pprint(prog);
01177 if (end != NULL)
01178 fprintf(prof_fp, "\n");
01179 }
01180 if (end != NULL) {
01181 fprintf(prof_fp, _("\t# END block(s)\n\n"));
01182 fprintf(prof_fp, "\tEND {\n");
01183 in_BEGIN_or_END = TRUE;
01184 pprint(end);
01185 in_BEGIN_or_END = FALSE;
01186 fprintf(prof_fp, "\t}\n");
01187 }
01188 }
01189
01190
01191
01192 void
01193 pp_func(const char *name, size_t namelen, NODE *f)
01194 {
01195 int j;
01196 char **pnames;
01197 static int first = TRUE;
01198
01199 if (first) {
01200 first = FALSE;
01201 fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n"));
01202 }
01203
01204 fprintf(prof_fp, "\n");
01205 indent(f->exec_count);
01206 fprintf(prof_fp, "function %.*s(", (int) namelen, name);
01207 pnames = f->parmlist;
01208 fparms = pnames;
01209 for (j = 0; j < f->lnode->param_cnt; j++) {
01210 fprintf(prof_fp, "%s", pnames[j]);
01211 if (j < f->lnode->param_cnt - 1)
01212 fprintf(prof_fp, ", ");
01213 }
01214 fprintf(prof_fp, ")\n\t{\n");
01215 indent_in();
01216 pprint(f->rnode);
01217 indent_out();
01218 fprintf(prof_fp, "\t}\n");
01219 }
01220
01221
01222
01223 static void
01224 pp_string(const char *str, size_t len, int delim)
01225 {
01226 pp_string_fp(prof_fp, str, len, delim, FALSE);
01227 }
01228
01229
01230
01231
01232
01233
01234
01235
01236 void
01237 pp_string_fp(FILE *fp, const char *in_str, size_t len, int delim, int breaklines)
01238 {
01239 static char escapes[] = "\b\f\n\r\t\v\\";
01240 static char printables[] = "bfnrtv\\";
01241 char *cp;
01242 int i;
01243 int count;
01244 #define BREAKPOINT 70
01245 const unsigned char *str = (const unsigned char *) in_str;
01246
01247 fprintf(fp, "%c", delim);
01248 for (count = 0; len > 0; len--, str++) {
01249 if (++count >= BREAKPOINT && breaklines) {
01250 fprintf(fp, "%c\n%c", delim, delim);
01251 count = 0;
01252 }
01253 if (*str == delim) {
01254 fprintf(fp, "\\%c", delim);
01255 count++;
01256 } else if (*str == BELL) {
01257 fprintf(fp, "\\a");
01258 count++;
01259 } else if ((cp = strchr(escapes, *str)) != NULL) {
01260 i = cp - escapes;
01261 putc('\\', fp);
01262 count++;
01263 putc(printables[i], fp);
01264 if (breaklines && *str == '\n' && delim == '"') {
01265 fprintf(fp, "\"\n\"");
01266 count = 0;
01267 }
01268
01269 } else if (isascii(*str) && isprint(*str)) {
01270 putc(*str, fp);
01271 } else {
01272 char buf[10];
01273
01274
01275 if (whiny_users)
01276 sprintf(buf, "%c", *str & 0xff);
01277 else
01278 sprintf(buf, "\\%03o", *str & 0xff);
01279 count += strlen(buf) - 1;
01280 fprintf(fp, "%s", buf);
01281 }
01282 }
01283 fprintf(fp, "%c", delim);
01284 }
01285
01286
01287
01288 static int
01289 is_scalar(NODETYPE type)
01290 {
01291 switch (type) {
01292 case Node_var_new:
01293 case Node_var:
01294 case Node_var_array:
01295 case Node_val:
01296 case Node_BINMODE:
01297 case Node_CONVFMT:
01298