1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 #include "config.h" 22 #include <unistd.h> // isatty 23 #include <errno.h> 24 25 #include "gp-print.h" 26 #include "ipcio.h" 27 #include "Command.h" 28 #include "Dbe.h" 29 #include "DbeApplication.h" 30 #include "DbeSession.h" 31 #include "Experiment.h" 32 #include "Emsg.h" 33 #include "DbeView.h" 34 #include "DataObject.h" 35 #include "Function.h" 36 #include "Hist_data.h" 37 #include "PathTree.h" 38 #include "LoadObject.h" 39 #include "Function.h" 40 #include "FilterSet.h" 41 #include "Filter.h" 42 #include "MetricList.h" 43 #include "MemorySpace.h" 44 #include "Module.h" 45 #include "util.h" 46 #include "i18n.h" 47 #include "StringBuilder.h" 48 #include "debug.h" 49 #include "UserLabel.h" 50 51 static char *exe_name; 52 static char **new_argv; 53 54 void 55 reexec () 56 { 57 if (dbeSession != NULL) 58 dbeSession->unlink_tmp_files (); 59 execvp (exe_name, new_argv); 60 fprintf (stderr, GTXT ("Error: reexec() failed (%d: %s)\n"), errno, 61 STR(strerror (errno))); 62 fflush (stderr); 63 exit (1); 64 } 65 66 /** 67 * Run application under enhance if the following requirements are satisfied: 68 * 1. Environment variable GPROFNG_ENHANCE is not set to "no" 69 * 2. Standard input is terminal 70 * 3. Standard output is terminal 71 * 4. /bin/enhance exists and can work on this system 72 */ 73 static void 74 reexec_enhance (int argc, char *argv[]) 75 { 76 char *gp_enhance = getenv ("GPROFNG_ENHANCE"); 77 if (NULL != gp_enhance && 0 == strcasecmp (gp_enhance, "no")) 78 return; // Do not enhance 79 // Verify that input and output are tty 80 if (!isatty (fileno (stdin))) // stdin is not a terminal 81 return; // Do not enhance 82 if (!isatty (fileno (stdout))) // stdout is not a terminal 83 return; // Do not enhance 84 char *enhance_name = NTXT ("/bin/enhance"); 85 struct stat sbuf; 86 int res = stat (enhance_name, &sbuf); // Check if enhance exists 87 if (res == 0) 88 res = system (NTXT ("/bin/enhance /bin/true")); // Check if enhance can work 89 if (res != 0) 90 { 91 fflush (stdout); 92 printf (GTXT ("Warning: History and command editing is not supported on this system.\n")); 93 fflush (stdout); 94 return; 95 } 96 else 97 { 98 printf (GTXT ("Note: History and command editing is supported on this system.\n")); 99 fflush (stdout); 100 } 101 char **nargv = new char*[argc + 2]; 102 for (int i = 0; i < argc; i++) 103 nargv[i + 1] = argv[i]; 104 nargv[0] = enhance_name; 105 nargv[argc + 1] = NULL; 106 putenv (NTXT ("GPROFNG_ENHANCE=no")); // prevent recursion 107 execv (enhance_name, nargv); 108 // execv failed. Continue to run the program 109 delete[] nargv; 110 } 111 112 int 113 main (int argc, char *argv[]) 114 { 115 er_print *erprint; 116 int ind = 1; 117 if (argc > ind && *argv[ind] == '-') 118 { 119 int arg_count, cparam; 120 if (Command::get_command (argv[ind] + 1, arg_count, cparam) == WHOAMI) 121 ind = ind + 1 + arg_count; 122 } 123 if (argc > ind && argv[ind] != NULL && *argv[ind] != '-') 124 reexec_enhance (argc, argv); 125 126 // Save argv for reexec()) 127 exe_name = argv[0]; 128 new_argv = argv; 129 130 if (argc > ind && argv[ind] != NULL && strcmp (argv[ind], "-IPC") == 0) 131 { 132 putenv (NTXT ("LC_NUMERIC=C")); // Use non-localized numeric data in IPC packets 133 erprint = new er_print (argc, argv); 134 theDbeApplication->rdtMode = false; 135 ipc_mainLoop (argc, argv); 136 } 137 else 138 { 139 erprint = new er_print (argc, argv); 140 erprint->start (argc, argv); 141 } 142 143 dbeSession->unlink_tmp_files (); 144 if (DUMP_CALL_STACK) 145 { 146 extern long total_calls_add_stack, total_stacks, total_nodes, call_stack_size[201]; 147 fprintf (stderr, NTXT ("total_calls_add_stack=%lld\ntotal_stacks=%lld\ntotal_nodes=%lld\n"), 148 (long long) total_calls_add_stack, (long long) total_stacks, (long long) total_nodes); 149 for (int i = 0; i < 201; i++) 150 if (call_stack_size[i] != 0) 151 fprintf (stderr, NTXT (" call_stack_size[%d] = %6lld\n"), i, 152 (long long) call_stack_size[i]); 153 } 154 #if defined(DEBUG) 155 delete erprint; 156 #endif 157 return 0; 158 } 159 160 er_print::er_print (int argc, char *argv[]) 161 : DbeApplication (argc, argv) 162 { 163 out_fname = GTXT ("<stdout>"); 164 inp_file = stdin; 165 out_file = stdout; 166 dis_file = stdout; 167 cov_string = NULL; 168 limit = 0; 169 cstack = new Vector<Histable*>(); 170 was_QQUIT = false; 171 } 172 173 er_print::~er_print () 174 { 175 free (cov_string); 176 delete cstack; 177 if (inp_file != stdin) 178 fclose (inp_file); 179 } 180 181 void 182 er_print::start (int argc, char *argv[]) 183 { 184 Vector<String> *res = theDbeApplication->initApplication (NULL, NULL, NULL); 185 res->destroy (); 186 delete res; 187 188 // Create a view on the session 189 dbevindex = dbeSession->createView (0, -1); 190 dbev = dbeSession->getView (dbevindex); 191 limit = dbev->get_limit (); 192 (void) check_args (argc, argv); 193 int ngood = dbeSession->ngoodexps (); 194 if (ngood == 0) 195 { 196 fprintf (stderr, GTXT ("No valid experiments loaded; exiting\n")); 197 return; 198 } 199 dbeDetectLoadMachineModel (dbevindex); 200 run (argc, argv); 201 } 202 203 bool 204 er_print::free_memory_before_exit () 205 { 206 return was_QQUIT; 207 } 208 209 void 210 er_print::usage () 211 { 212 213 /* 214 Ruud - Isolate this line because it has an argument. Otherwise it would be at the 215 end of the long option list. 216 */ 217 printf ( GTXT ( 218 "Usage: gprofng display text [OPTION(S)] [COMMAND(S)] [-script <script_file>] EXPERIMENT(S)\n")); 219 220 printf ( GTXT ( 221 "\n" 222 "Print a plain text version of the various displays supported by gprofng.\n" 223 "\n" 224 "Options:\n" 225 "\n" 226 " --version print the version number and exit.\n" 227 " --help print usage information and exit.\n" 228 " --verbose {on|off} enable (on) or disable (off) verbose mode; the default is \"off\".\n" 229 "\n" 230 " -script <script-file> execute the commands stored in the script file;\n" 231 " this feature may be combined with commands specified\n" 232 " at the command line.\n" 233 "\n" 234 "Commands:\n" 235 "\n" 236 "This tool supports a rich set of commands to control the display of the\n" 237 "data; instead of, or in addition to, including these commands in a script\n" 238 "file, it is also allowed to include such commands at the command line;\n" 239 "in this case, the commands need to be prepended with the \"-\" symbol; the\n" 240 "commands are processed and interpreted left from right, so the order matters;\n" 241 "The gprofng manual documents the commands that are supported.\n" 242 "\n" 243 "If this tool is invoked without options, commands, or a script file, it starts\n" 244 "in interpreter mode. The user can then issue the commands interactively; the\n" 245 "session is terminated with the \"exit\" command in the interpreter.\n" 246 "\n" 247 "Documentation:\n" 248 "\n" 249 "A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n" 250 "gprofng programs are properly installed at your site, the command \"info gprofng\"\n" 251 "should give you access to this document.\n" 252 "\n" 253 "See also:\n" 254 "\n" 255 "gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-html(1), gp-display-src(1)\n")); 256 } 257 258 int // returns count of experiments read 259 er_print::check_args (int argc, char *argv[]) 260 { 261 CmdType cmd_type; 262 int arg_count; 263 int cparam; 264 int exp_no; 265 error_msg = NULL; 266 267 Emsg *rcmsg = fetch_comments (); 268 while (rcmsg != NULL) 269 { 270 fprintf (stderr, NTXT ("%s: %s\n"), prog_name, rcmsg->get_msg ()); 271 rcmsg = rcmsg->next; 272 } 273 delete_comments (); 274 275 // Set up the list of experiments to add after checking the args 276 Vector<Vector<char*>*> *exp_list = new Vector<Vector<char*>*>(); 277 278 // Prescan the command line arguments, processing only a few 279 for (int i = 1; i < argc; i++) 280 { 281 if (*argv[i] != '-') 282 { 283 // we're at the end -- get the list of experiments 284 // Build the list of experiments, and set the searchpath 285 Vector<char*> *list = dbeSession->get_group_or_expt (argv[i]); 286 if (list->size () > 0) 287 { 288 for (int j = 0, list_sz = list->size (); j < list_sz; j++) 289 { 290 char *path = list->fetch (j); 291 if (strlen (path) == 0 || strcmp (path, NTXT ("\\")) == 0) 292 continue; 293 char *p = strrchr (path, '/'); 294 if (p) 295 { 296 // there's a directory in front of the name; add it to search path 297 *p = '\0'; 298 dbeSession->set_search_path (path, false); 299 } 300 } 301 list->destroy (); 302 list->append (dbe_strdup (argv[i])); 303 exp_list->append (list); 304 } 305 else 306 delete list; 307 continue; 308 } 309 310 // Not at the end yet, treat the next argument as a command 311 switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam)) 312 { 313 case WHOAMI: 314 whoami = argv[i] + 1 + cparam; 315 break; 316 case HELP: 317 if (i + 1 + arg_count == argc) 318 { 319 usage(); 320 exit (0); 321 } 322 break; 323 case HHELP: 324 Command::print_help (whoami, true, false, stdout); 325 fprintf (stdout, "\n"); 326 indxo_list (false, stdout); 327 fprintf (stdout, "\n"); 328 mo_list (false, stdout); 329 if (!getenv ("_BUILDING_MANPAGE")) 330 fprintf (stdout, GTXT ("\nSee gprofng(1) for more details\n")); 331 exit (0); 332 case ADD_EXP: 333 case DROP_EXP: 334 case OPEN_EXP: 335 printf (GTXT ("Error: command %s can not appear on the command line\n"), argv[i]); 336 exit (2); 337 case VERSION_cmd: 338 Application::print_version_info (); 339 exit (0); 340 case AMBIGUOUS_CMD: 341 fprintf (stderr, GTXT ("Error: Ambiguous command: %s\n"), argv[i]); 342 exit (2); 343 case UNKNOWN_CMD: 344 fprintf (stderr, GTXT ("Error: Invalid command: %s\n"), argv[i]); 345 exit (2); 346 // it's a plausible argument; see if we process now or later 347 case SOURCE: 348 case DISASM: 349 case CSINGLE: 350 case CPREPEND: 351 case CAPPEND: 352 case FSINGLE: 353 case SAMPLE_DETAIL: 354 case STATISTICS: 355 case HEADER: 356 //skip the arguments to that command 357 i += arg_count; 358 if (i >= argc || end_command (argv[i])) 359 i--; 360 break; 361 case PRINTMODE: 362 case INDXOBJDEF: 363 case ADDPATH: 364 case SETPATH: 365 case PATHMAP: 366 case OBJECT_SHOW: 367 case OBJECT_HIDE: 368 case OBJECT_API: 369 case OBJECTS_DEFAULT: 370 case EN_DESC: 371 // these are processed in the initial pass over the arguments 372 proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL, 373 (arg_count > 1) ? argv[i + 2] : NULL, 374 (arg_count > 2) ? argv[i + 3] : NULL, 375 (arg_count > 3) ? argv[i + 4] : NULL); 376 i += arg_count; 377 break; 378 default: 379 // any others, we skip for now 380 i += arg_count; 381 break; 382 } 383 } 384 385 // Make sure some experiments were specified 386 exp_no = exp_list->size (); 387 if (exp_no == 0) 388 { // no experiment name 389 fprintf (stderr, GTXT ("%s: Missing experiment directory (use the --help option to get a usage overview)\n"), whoami); 390 exit (1); 391 } 392 393 // add the experiments to the session 394 char *errstr = dbeOpenExperimentList (0, exp_list, false); 395 for (long i = 0; i < exp_list->size (); i++) 396 { 397 Vector<char*>* p = exp_list->get (i); 398 Destroy (p); 399 } 400 delete exp_list; 401 if (errstr != NULL) 402 { 403 fprintf (stderr, NTXT ("%s"), errstr); 404 free (errstr); 405 } 406 407 return exp_no; 408 } 409 410 int 411 er_print::is_valid_seg_name (char *lo_name, int prev) 412 { 413 // prev is the loadobject segment index that was last returned 414 // search starts following that loadobject 415 int index; 416 LoadObject *lo; 417 char *p_lo_name = lo_name; 418 char *name = NULL; 419 420 // strip angle brackets from all but <Unknown> and <Total> 421 if (strcmp (lo_name, "<Unknown>") && strcmp (lo_name, "<Total>")) 422 { 423 if (*lo_name == '<') 424 { 425 name = dbe_strdup (lo_name + 1); 426 p_lo_name = name; 427 char *p = strchr (name, '>'); 428 if (p) 429 *p = '\0'; 430 } 431 } 432 433 // get the load object list from the session 434 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); 435 Vec_loop (LoadObject*, lobjs, index, lo) 436 { 437 if (prev > 0) 438 { 439 if (lo->seg_idx == prev) // this is where we left off 440 prev = -1; 441 continue; 442 } 443 444 // does this one match? 445 if (cmp_seg_name (lo->get_pathname (), p_lo_name)) 446 { 447 delete lobjs; 448 free (name); 449 size_t len = strlen (lo_name); 450 if ((len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) || 451 (len > 6 && streq (lo_name + len - 6, NTXT (".class")))) 452 { 453 fprintf (stderr, GTXT ("Error: Java class `%s' is not selectable\n"), lo_name); 454 return -1; 455 } 456 return lo->seg_idx; 457 } 458 } 459 delete lobjs; 460 free (name); 461 return -1; 462 } 463 464 int 465 er_print::cmp_seg_name (char *full_name, char *lo_name) 466 { 467 char *cmp_name; 468 if (!strchr (lo_name, '/') && (cmp_name = strrchr (full_name, '/'))) 469 cmp_name++; // basename 470 else 471 cmp_name = full_name; // full path name 472 return !strcmp (lo_name, cmp_name); 473 } 474 475 // processing object_select 476 // Note that this does not affect the strings in Settings, 477 // unlike object_show, object_hide, and object_api 478 int 479 er_print::process_object_select (char *names) 480 { 481 int index; 482 LoadObject *lo; 483 int no_lobj = 0; 484 bool got_err = false; 485 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); 486 if ((names == NULL) || !strcasecmp (names, Command::ALL_CMD)) 487 { // full coverage 488 Vec_loop (LoadObject*, lobjs, index, lo) 489 { 490 dbev->set_lo_expand (lo->seg_idx, LIBEX_SHOW); 491 } 492 } 493 else 494 { // parsing coverage 495 // first, hide functions from all loadobjects 496 // except the java ones 497 Vec_loop (LoadObject*, lobjs, index, lo) 498 { 499 char *lo_name = lo->get_name (); 500 if (lo_name != NULL) 501 { 502 size_t len = strlen (lo_name); 503 if ((len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) || 504 (len > 6 && streq (lo_name + len - 6, NTXT (".class")))) 505 continue; 506 } 507 dbev->set_lo_expand (lo->seg_idx, LIBEX_HIDE); 508 } 509 510 Vector <char *> *tokens = split_str (names, ','); 511 for (long j = 0, sz = VecSize (tokens); j < sz; j++) 512 { 513 // loop over the provided names 514 char *lo_name = tokens->get (j); 515 int seg_idx = -1; 516 seg_idx = is_valid_seg_name (lo_name, seg_idx); 517 while (seg_idx != -1) 518 { 519 dbev->set_lo_expand (seg_idx, LIBEX_SHOW); 520 no_lobj++; 521 seg_idx = is_valid_seg_name (lo_name, seg_idx); 522 } 523 if (no_lobj == 0) 524 { 525 got_err = true; 526 fprintf (stderr, GTXT ("Error: Unknown load object: `%s'\n"), lo_name); 527 } 528 free (lo_name); 529 } 530 delete tokens; 531 } 532 533 if (!got_err) 534 { // good coverage string 535 free (cov_string); 536 cov_string = strdup (names); 537 } 538 else 539 { // bad, restore original coverage 540 no_lobj = -1; 541 process_object_select (cov_string); 542 } 543 delete lobjs; 544 return no_lobj; 545 } 546 547 int 548 er_print::set_libexpand (char *cov, enum LibExpand expand) 549 { 550 bool changed = dbev->set_libexpand (cov, expand); 551 if (changed == true) 552 dbev->update_lo_expands (); 553 return 0; 554 } 555 556 int 557 er_print::set_libdefaults () 558 { 559 dbev->set_libdefaults (); 560 return 0; 561 } 562 563 bool 564 er_print::end_command (char *cmd) 565 { 566 if (cmd == NULL || *cmd == '-') 567 return true; 568 size_t len = strlen (cmd); 569 if (cmd[len - 1] == '/') 570 len--; 571 if ((len > 3 && !strncmp (&cmd[len - 3], NTXT (".er"), 3)) || 572 (len > 4 && !strncmp (&cmd[len - 4], NTXT (".erg"), 4))) 573 return true; 574 return false; 575 } 576 577 // Now actually start processing the arguments 578 void 579 er_print::run (int argc, char *argv[]) 580 { 581 CmdType cmd_type; 582 int arg_count, cparam, i; 583 bool got = false; 584 char *arg1, *arg2; 585 for (i = 1; i < argc; i++) 586 { 587 if (*argv[i] != '-') // open experiment pointer files 588 continue; 589 switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam)) 590 { 591 case WHOAMI: 592 whoami = argv[i] + 1 + cparam; 593 break; 594 case SCRIPT: 595 got = true; 596 inp_file = fopen (argv[++i], "r"); 597 if (inp_file == NULL) 598 { 599 fprintf (stderr, GTXT ("Error: Script file cannot be opened: %s\n"), argv[i]); 600 exit (3); 601 } 602 proc_script (); 603 break; 604 case STDIN: 605 got = true; 606 inp_file = stdin; 607 proc_script (); 608 break; 609 case SOURCE: // with option arg_count == 2 610 case DISASM: 611 got = true; 612 i += arg_count; 613 if ((i >= argc) || end_command (argv[i])) 614 { 615 i--; 616 arg1 = argv[i]; 617 arg2 = NTXT (""); 618 } 619 else 620 { 621 arg1 = argv[i - 1]; 622 arg2 = argv[i]; 623 } 624 proc_cmd (cmd_type, cparam, arg1, arg2, NULL, NULL, true); 625 break; 626 case CSINGLE: 627 case CPREPEND: 628 case CAPPEND: 629 case FSINGLE: 630 got = true; 631 i += arg_count; 632 if ((i >= argc) || end_command (argv[i])) 633 { 634 i--; 635 proc_cmd (cmd_type, cparam, argv[i], NTXT ("1")); 636 } 637 else 638 proc_cmd (cmd_type, cparam, argv[i - 1], argv[i]); 639 break; 640 case SAMPLE_DETAIL: // with option arg_count == 1 641 case STATISTICS: 642 case HEADER: 643 got = true; 644 // now fall through to process the command 645 case COMPARE: 646 got = true; 647 i += arg_count; 648 if ((i >= argc) || end_command (argv[i])) 649 { 650 i--; 651 proc_cmd (cmd_type, cparam, NULL, NULL); 652 } 653 else 654 proc_cmd (cmd_type, cparam, argv[i], NULL); 655 break; 656 case PRINTMODE: 657 case INDXOBJDEF: 658 case ADDPATH: 659 case SETPATH: 660 case PATHMAP: 661 case OBJECT_SHOW: 662 case OBJECT_HIDE: 663 case OBJECT_API: 664 case OBJECTS_DEFAULT: 665 case EN_DESC: 666 got = true; 667 // these have been processed already 668 i += arg_count; 669 break; 670 case LIMIT: 671 got = true; 672 proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL, 673 (arg_count > 1) ? argv[i + 2] : NULL); 674 i += arg_count; 675 break; 676 default: 677 got = true; 678 proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL, 679 (arg_count > 1) ? argv[i + 2] : NULL); 680 i += arg_count; 681 break; 682 } 683 } 684 if (!got) // no command has been specified 685 proc_script (); 686 } 687 688 #define MAXARGS 20 689 690 void 691 er_print::proc_script () 692 { 693 CmdType cmd_type; 694 int arg_count, cparam; 695 char *cmd, *end_cmd; 696 char *script = NULL; 697 char *arglist[MAXARGS]; 698 char *line = NULL; 699 int lineno = 0; 700 while (!feof (inp_file)) 701 { 702 if (inp_file == stdin) 703 printf (NTXT ("(%s) "), get_basename (prog_name)); 704 free (script); 705 script = read_line (inp_file); 706 if (script == NULL) 707 continue; 708 free (line); 709 line = dbe_strdup (script); 710 lineno++; 711 for (int i = 0; i < MAXARGS; i++) 712 arglist[i] = NULL; 713 714 // ensure it's terminated by a \n, and remove that character 715 strtok (script, NTXT ("\n")); 716 717 // extract the command 718 cmd = strtok (script, NTXT (" \t")); 719 if (cmd == NULL) 720 continue; 721 if (*cmd == '#') 722 { 723 fprintf (stderr, NTXT ("%s"), line); 724 continue; 725 } 726 if (*cmd == '\n') 727 continue; 728 729 char *remainder = strtok (NULL, NTXT ("\n")); 730 // now extract the arguments 731 int nargs = 0; 732 for (;;) 733 { 734 end_cmd = NULL; 735 if (nargs >= MAXARGS) 736 fprintf (stderr, GTXT ("Warning: more than %d arguments to %s command, line %d\n"), 737 MAXARGS, cmd, lineno); 738 char *nextarg = strtok (remainder, NTXT ("\n")); 739 if ((nextarg == NULL) || (*nextarg == '#')) 740 // either the end of the line, or a comment indicator 741 break; 742 if (nargs >= MAXARGS) 743 { 744 parse_qstring (nextarg, &end_cmd); 745 nargs++; 746 } 747 else 748 arglist[nargs++] = parse_qstring (nextarg, &end_cmd); 749 remainder = end_cmd; 750 if (remainder == NULL) 751 break; 752 // skip any blanks or tabs to get to next argument 753 while (*remainder == ' ' || *remainder == '\t') 754 remainder++; 755 } 756 757 cmd_type = Command::get_command (cmd, arg_count, cparam); 758 759 // check for extra arguments 760 if (cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF && nargs > arg_count) 761 fprintf (stderr, GTXT ("Warning: extra arguments to %s command, line %d\n"), 762 cmd, lineno); 763 switch (cmd_type) 764 { 765 case SOURCE: 766 case DISASM: 767 // ignore any third parameter 768 // if there was, we have written a warning 769 proc_cmd (cmd_type, cparam, arglist[0], arglist[1], NULL, NULL, 770 (inp_file != stdin)); 771 break; 772 case QUIT: 773 free (script); 774 free (line); 775 exit (0); 776 case QQUIT: 777 was_QQUIT = true; 778 free (script); 779 free (line); 780 return; 781 case STDIN: 782 break; 783 case COMMENT: 784 fprintf (dis_file, NTXT ("%s"), line); 785 break; 786 case AMBIGUOUS_CMD: 787 fprintf (stderr, GTXT ("Error: Ambiguous command: %s\n"), cmd); 788 break; 789 case UNKNOWN_CMD: 790 if (*cmd != '\n') 791 fprintf (stderr, GTXT ("Error: Invalid command: %s\n"), cmd); 792 break; 793 default: 794 proc_cmd (cmd_type, cparam, arglist[0], arglist[1]); 795 break; 796 } 797 } 798 // free up the input line 799 free (script); 800 free (line); 801 } 802 803 void 804 er_print::proc_cmd (CmdType cmd_type, int cparam, 805 char *arg1, char *arg2, char *arg3, char *arg4, bool xdefault) 806 { 807 er_print_common_display *cd; 808 FILE *ck_file, *save_file; 809 char *name; 810 int bgn_index, end_index, index; 811 Cmd_status status; 812 char *scratch, *scratch1; 813 switch (cmd_type) 814 { 815 case FUNCS: 816 print_func (Histable::FUNCTION, MODE_LIST, 817 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL)); 818 break; 819 case FDETAIL: 820 print_func (Histable::FUNCTION, MODE_DETAIL, 821 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL)); 822 break; 823 case FSINGLE: 824 print_func (Histable::FUNCTION, MODE_DETAIL, 825 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL), 826 arg1, arg2); 827 break; 828 case HOTPCS: 829 print_func (Histable::INSTR, MODE_LIST, 830 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL)); 831 break; 832 case PDETAIL: 833 print_func (Histable::INSTR, MODE_DETAIL, 834 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL)); 835 break; 836 case HOTLINES: 837 print_func (Histable::LINE, MODE_LIST, 838 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL)); 839 break; 840 case LDETAIL: 841 print_func (Histable::LINE, MODE_DETAIL, 842 dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL)); 843 break; 844 case OBJECTS: 845 print_objects (); 846 break; 847 case OVERVIEW_NEW: 848 print_overview (); 849 break; 850 case LOADOBJECT: 851 print_segments (); 852 break; 853 case GPROF: 854 print_func (Histable::FUNCTION, MODE_GPROF, 855 dbev->get_metric_list (MET_CALL), dbev->get_metric_list (MET_NORMAL)); 856 break; 857 case CALLTREE: 858 if (dbev->comparingExperiments ()) 859 { 860 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n")); 861 break; 862 } 863 print_ctree (cmd_type); 864 break; 865 case CSINGLE: 866 case CPREPEND: 867 case CAPPEND: 868 case CRMFIRST: 869 case CRMLAST: 870 print_gprof (cmd_type, arg1, arg2); 871 break; 872 case EXP_LIST: 873 exp_list (); 874 break; 875 case DESCRIBE: 876 describe (); 877 break; 878 case SCOMPCOM: 879 status = dbev->proc_compcom (arg1, true, false); 880 if (status != CMD_OK) 881 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 882 break; 883 case STHRESH: 884 status = dbev->proc_thresh (arg1, true, false); 885 if (status != CMD_OK) 886 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 887 break; 888 case DCOMPCOM: 889 status = dbev->proc_compcom (arg1, false, false); 890 if (status != CMD_OK) 891 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 892 break; 893 case COMPCOM: 894 status = dbev->proc_compcom (arg1, true, false); 895 if (status != CMD_OK) 896 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 897 status = dbev->proc_compcom (arg1, false, false); 898 if (status != CMD_OK) 899 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 900 break; 901 case DTHRESH: 902 status = dbev->proc_thresh (arg1, false, false); 903 if (status != CMD_OK) 904 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 905 break; 906 case SOURCE: 907 case DISASM: 908 { 909 if (arg3 != NULL) 910 abort (); 911 if (arg1 == NULL) 912 { 913 fprintf (stderr, GTXT ("Error: Invalid function/file setting: \n")); 914 break; 915 } 916 char *fcontext = NULL; 917 char *arg = parse_fname (arg1, &fcontext); 918 if (arg == NULL) 919 { 920 fprintf (stderr, GTXT ("Error: Invalid function/file setting: %s\n"), arg1); 921 free (fcontext); 922 break; 923 } 924 if (arg2 && (strlen (arg2) == 0)) 925 arg2 = NULL; 926 print_anno_file (arg, arg2, fcontext, cmd_type == DISASM, 927 dis_file, inp_file, out_file, dbev, xdefault); 928 free (arg); 929 free (fcontext); 930 break; 931 } 932 case METRIC_LIST: 933 proc_cmd (METRICS, cparam, NULL, NULL); 934 dbev->get_metric_ref (MET_NORMAL)->print_metric_list (dis_file, 935 GTXT ("Available metrics:\n"), false); 936 break; 937 case METRICS: 938 if (arg1) 939 { 940 char *ret = dbev->setMetrics (arg1, false); 941 if (ret != NULL) 942 { 943 fprintf (stderr, GTXT ("Error: %s\n"), ret); 944 proc_cmd (METRIC_LIST, cparam, NULL, NULL); 945 break; 946 } 947 } 948 scratch = dbev->get_metric_list (MET_NORMAL)->get_metrics (); 949 fprintf (dis_file, GTXT ("Current metrics: %s\n"), scratch); 950 free (scratch); 951 proc_cmd (SORT, cparam, NULL, NULL); 952 break; 953 case GMETRIC_LIST: 954 scratch = dbev->get_metric_list (MET_CALL)->get_metrics (); 955 fprintf (dis_file, GTXT ("Current caller-callee metrics: %s\n"), scratch); 956 free (scratch); 957 fprintf (dis_file, GTXT ("Current caller-callee sort Metric: %s\n"), 958 dbev->getSort (MET_DATA)); 959 break; 960 case INDX_METRIC_LIST: 961 scratch = dbev->get_metric_list (MET_INDX)->get_metrics (); 962 fprintf (dis_file, GTXT ("Current index-object metrics: %s\n"), scratch); 963 free (scratch); 964 scratch = dbev->getSort (MET_INDX); 965 fprintf (dis_file, GTXT ("Current index-object sort Metric: %s\n"), scratch); 966 free (scratch); 967 break; 968 case SORT: 969 if (arg1) 970 { 971 char *ret = dbev->setSort (arg1, MET_NORMAL, false); 972 if (ret != NULL) 973 { 974 fprintf (stderr, GTXT ("Error: %s\n"), ret); 975 proc_cmd (METRICS, cparam, NULL, NULL); 976 break; 977 } 978 dbev->setSort (arg1, MET_SRCDIS, false); 979 dbev->setSort (arg1, MET_CALL, false); 980 dbev->setSort (arg1, MET_DATA, false); 981 dbev->setSort (arg1, MET_INDX, false); 982 dbev->setSort (arg1, MET_CALL_AGR, false); 983 dbev->setSort (arg1, MET_IO, false); 984 dbev->setSort (arg1, MET_HEAP, false); 985 } 986 scratch = dbev->getSort (MET_NORMAL); 987 scratch1 = dbev->getSortCmd (MET_NORMAL); 988 fprintf (dis_file, 989 GTXT ("Current Sort Metric: %s ( %s )\n"), scratch, scratch1); 990 free (scratch1); 991 free (scratch); 992 break; 993 case OBJECT_SHOW: 994 if (arg1) 995 set_libexpand (arg1, LIBEX_SHOW); 996 obj_list (); 997 break; 998 case OBJECT_HIDE: 999 if (arg1) 1000 set_libexpand (arg1, LIBEX_HIDE); 1001 obj_list (); 1002 break; 1003 case OBJECT_API: 1004 if (arg1) 1005 set_libexpand (arg1, LIBEX_API); 1006 obj_list (); 1007 break; 1008 case OBJECTS_DEFAULT: 1009 set_libdefaults (); 1010 obj_list (); 1011 break; 1012 case OBJECT_LIST: 1013 obj_list (); 1014 break; 1015 case OBJECT_SELECT: 1016 if (arg1) 1017 { 1018 if (process_object_select (arg1) != -1) 1019 proc_cmd (OBJECT_LIST, cparam, NULL, NULL); 1020 else 1021 fprintf (stderr, GTXT ("Error: Type \"object_list\" for a list of all load objects.\n")); 1022 } 1023 else 1024 fprintf (stderr, GTXT ("Error: No load object has been specified.\n")); 1025 break; 1026 case LOADOBJECT_LIST: 1027 seg_list (); 1028 break; 1029 case LOADOBJECT_SELECT: 1030 if (arg1) 1031 { 1032 if (process_object_select (arg1) != -1) 1033 proc_cmd (LOADOBJECT_LIST, cparam, NULL, NULL); 1034 else 1035 fprintf (stderr, GTXT ("Error: Type \"segment_list\" for a list of all segments.\n")); 1036 } 1037 else 1038 fprintf (stderr, GTXT ("Error: No segment has been specified.\n")); 1039 break; 1040 case SAMPLE_LIST: 1041 filter_list (SAMPLE_LIST); 1042 break; 1043 case SAMPLE_SELECT: 1044 if (arg1 && !dbev->set_pattern (SAMPLE_FILTER_IDX, arg1)) 1045 fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1); 1046 proc_cmd (SAMPLE_LIST, cparam, NULL, NULL); 1047 break; 1048 case THREAD_LIST: 1049 filter_list (THREAD_LIST); 1050 break; 1051 case THREAD_SELECT: 1052 if (arg1 && !dbev->set_pattern (THREAD_FILTER_IDX, arg1)) 1053 fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1); 1054 proc_cmd (THREAD_LIST, cparam, NULL, NULL); 1055 break; 1056 case LWP_LIST: 1057 filter_list (LWP_LIST); 1058 break; 1059 case LWP_SELECT: 1060 if (arg1 && !dbev->set_pattern (LWP_FILTER_IDX, arg1)) 1061 fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1); 1062 proc_cmd (LWP_LIST, cparam, NULL, NULL); 1063 break; 1064 case CPU_LIST: 1065 filter_list (CPU_LIST); 1066 break; 1067 case CPU_SELECT: 1068 if (arg1 && !dbev->set_pattern (CPU_FILTER_IDX, arg1)) 1069 fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1); 1070 proc_cmd (CPU_LIST, cparam, NULL, NULL); 1071 break; 1072 case FILTERS: 1073 if (arg1 != NULL) 1074 { 1075 if (strcmp (arg1, NTXT ("True")) == 0) 1076 scratch = dbev->set_filter (NULL); 1077 else 1078 scratch = dbev->set_filter (arg1); 1079 if (scratch != NULL) 1080 fprintf (stderr, GTXT ("Error: %s\n"), scratch); 1081 } 1082 scratch = dbev->get_filter (); 1083 fprintf (dis_file, GTXT ("current filter setting: \"%s\"\n"), 1084 scratch == NULL ? GTXT ("<none>") : scratch); 1085 break; 1086 case OUTFILE: 1087 if (arg1) 1088 { 1089 set_outfile (arg1, out_file, false); 1090 if (inp_file != stdin) 1091 dis_file = out_file; 1092 } 1093 break; 1094 case APPENDFILE: 1095 if (arg1) 1096 { 1097 set_outfile (arg1, out_file, true); 1098 if (inp_file != stdin) 1099 dis_file = out_file; 1100 } 1101 break; 1102 case LIMIT: 1103 if (arg1) 1104 { 1105 limit = (int) strtol (arg1, (char **) NULL, 10); 1106 char *res = dbeSetPrintLimit (dbevindex, limit); 1107 if (res != NULL) 1108 fprintf (stderr, NTXT ("%s\n"), res); 1109 } 1110 1111 limit = dbeGetPrintLimit (dbevindex); 1112 fprintf (stderr, GTXT ("Print limit set to %d\n"), limit); 1113 break; 1114 case NAMEFMT: 1115 if (arg1) 1116 { 1117 status = dbev->set_name_format (arg1); 1118 if (status != CMD_OK) 1119 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 1120 } 1121 else 1122 fprintf (stderr, GTXT ("Error: No format has been specified.\n")); 1123 break; 1124 case VIEWMODE: 1125 { 1126 if (arg1) 1127 { 1128 status = dbev->set_view_mode (arg1, false); 1129 if (status != CMD_OK) 1130 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 1131 } 1132 const char *vname = "unknown"; 1133 int vm = dbev->get_view_mode (); 1134 switch (vm) 1135 { 1136 case VMODE_USER: 1137 vname = "user"; 1138 break; 1139 case VMODE_EXPERT: 1140 vname = "expert"; 1141 break; 1142 case VMODE_MACHINE: 1143 vname = "machine"; 1144 break; 1145 } 1146 fprintf (stderr, GTXT ("Viewmode set to %s\n"), vname); 1147 } 1148 break; 1149 1150 // EN_DESC does not make sense after experiments are read, but it does make sense on the command line, 1151 // processed before the experiments are read. 1152 case EN_DESC: 1153 if (arg1) 1154 { 1155 status = dbev->set_en_desc (arg1, false); 1156 if (status != CMD_OK) 1157 fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1); 1158 } 1159 else 1160 fprintf (stderr, GTXT ("Error: No descendant processing has been specified.\n")); 1161 break; 1162 case SETPATH: 1163 case ADDPATH: 1164 if (arg1) 1165 dbeSession->set_search_path (arg1, (cmd_type == SETPATH)); 1166 fprintf (dis_file, GTXT ("search path:\n")); 1167 Vec_loop (char*, dbeSession->get_search_path (), index, name) 1168 { 1169 fprintf (dis_file, NTXT ("\t%s\n"), name); 1170 } 1171 break; 1172 case PATHMAP: 1173 { 1174 Vector<pathmap_t*> *pathMaps = dbeSession->get_pathmaps (); 1175 if (arg1 != NULL) 1176 { 1177 if (arg2 == NULL) 1178 { 1179 fprintf (stderr, GTXT ("Error: No replacement path prefix has been specified.\n")); 1180 break; 1181 } 1182 // add this mapping to the session 1183 char *err = Settings::add_pathmap (pathMaps, arg1, arg2); 1184 if (err != NULL) 1185 { 1186 fprintf (stderr, NTXT ("%s"), err); 1187 free (err); 1188 } 1189 } 1190 fprintf (dis_file, GTXT ("Path mappings: from -> to\n")); 1191 for (int i = 0, sz = pathMaps->size (); i < sz; i++) 1192 { 1193 pathmap_t *thismap = pathMaps->get (i); 1194 fprintf (dis_file, NTXT ("\t`%s' -> `%s'\n"), thismap->old_prefix, thismap->new_prefix); 1195 } 1196 } 1197 break; 1198 case SAMPLE_DETAIL: 1199 if (get_exp_id (arg1, bgn_index, end_index) != -1) 1200 { 1201 cd = new er_print_experiment (dbev, bgn_index, end_index, false, 1202 false, false, true, true); 1203 print_cmd (cd); 1204 delete cd; 1205 } 1206 break; 1207 case STATISTICS: 1208 if (get_exp_id (arg1, bgn_index, end_index) != -1) 1209 { 1210 cd = new er_print_experiment (dbev, bgn_index, end_index, false, 1211 false, true, true, false); 1212 print_cmd (cd); 1213 delete cd; 1214 } 1215 break; 1216 case PRINTMODE: 1217 { 1218 if (arg1 == NULL) 1219 { 1220 fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex)); 1221 break; 1222 } 1223 char *s = dbeSetPrintMode (dbevindex, arg1); 1224 if (s != NULL) 1225 { 1226 fprintf (stderr, NTXT ("%s\n"), s); 1227 break; 1228 } 1229 fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex)); 1230 } 1231 break; 1232 case HEADER: 1233 if (get_exp_id (arg1, bgn_index, end_index) != -1) 1234 { 1235 cd = new er_print_experiment (dbev, bgn_index, end_index, false, 1236 true, false, false, false); 1237 print_cmd (cd); 1238 delete cd; 1239 } 1240 break; 1241 case COMPARE: 1242 if (arg1 == NULL) 1243 { 1244 fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n")); 1245 break; 1246 } 1247 else 1248 { 1249 int cmp; 1250 if (strcasecmp (arg1, NTXT ("OFF")) == 0 || strcmp (arg1, NTXT ("0")) == 0) 1251 cmp = CMP_DISABLE; 1252 else if (strcasecmp (arg1, NTXT ("ON")) == 0 || strcmp (arg1, NTXT ("1")) == 0) 1253 cmp = CMP_ENABLE; 1254 else if (strcasecmp (arg1, NTXT ("DELTA")) == 0) 1255 cmp = CMP_DELTA; 1256 else if (strcasecmp (arg1, NTXT ("RATIO")) == 0) 1257 cmp = CMP_RATIO; 1258 else 1259 { 1260 fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n")); 1261 break; 1262 } 1263 int oldMode = dbev->get_compare_mode (); 1264 dbev->set_compare_mode (cmp); 1265 if (oldMode != cmp) 1266 { 1267 dbev->reset_data (false); 1268 dbeSession->reset_data (); 1269 } 1270 } 1271 break; 1272 case LEAKS: 1273 if (!dbeSession->is_leaklist_available ()) 1274 { 1275 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n")); 1276 break; 1277 } 1278 if (dbev->comparingExperiments ()) 1279 { // XXXX show warning for compare 1280 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n")); 1281 break; 1282 } 1283 cd = new er_print_leaklist (dbev, true, false, dbev->get_limit ()); 1284 print_cmd (cd); 1285 delete cd; 1286 break; 1287 case ALLOCS: 1288 if (!dbeSession->is_leaklist_available ()) 1289 { 1290 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n")); 1291 break; 1292 } 1293 cd = new er_print_leaklist (dbev, false, true, dbev->get_limit ()); 1294 print_cmd (cd); 1295 delete cd; 1296 break; 1297 case HEAP: 1298 if (!dbeSession->is_heapdata_available ()) 1299 { 1300 fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n")); 1301 break; 1302 } 1303 cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, false, dbev->get_limit ()); 1304 print_cmd (cd); 1305 delete cd; 1306 break; 1307 case HEAPSTAT: 1308 if (!dbeSession->is_heapdata_available ()) 1309 { 1310 fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n")); 1311 break; 1312 } 1313 cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, true, dbev->get_limit ()); 1314 print_cmd (cd); 1315 delete cd; 1316 break; 1317 case IOACTIVITY: 1318 if (!dbeSession->is_iodata_available ()) 1319 { 1320 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n")); 1321 break; 1322 } 1323 if (dbev->comparingExperiments ()) 1324 { // XXXX show warning for compare 1325 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n")); 1326 break; 1327 } 1328 cd = new er_print_ioactivity (dbev, Histable::IOACTFILE, false, dbev->get_limit ()); 1329 print_cmd (cd); 1330 delete cd; 1331 break; 1332 case IOVFD: 1333 if (!dbeSession->is_iodata_available ()) 1334 { 1335 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n")); 1336 break; 1337 } 1338 cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, false, dbev->get_limit ()); 1339 print_cmd (cd); 1340 delete cd; 1341 break; 1342 case IOCALLSTACK: 1343 if (!dbeSession->is_iodata_available ()) 1344 { 1345 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n")); 1346 break; 1347 } 1348 cd = new er_print_ioactivity (dbev, Histable::IOCALLSTACK, false, dbev->get_limit ()); 1349 print_cmd (cd); 1350 delete cd; 1351 break; 1352 case IOSTAT: 1353 if (!dbeSession->is_iodata_available ()) 1354 { 1355 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n")); 1356 break; 1357 } 1358 cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, true, dbev->get_limit ()); 1359 print_cmd (cd); 1360 delete cd; 1361 break; 1362 case HELP: 1363 Command::print_help(whoami, false, true, out_file); 1364 break; 1365 case VERSION_cmd: 1366 Application::print_version_info (); 1367 break; 1368 case SCRIPT: 1369 if (arg1) 1370 { 1371 ck_file = fopen (arg1, NTXT ("r")); 1372 if (ck_file == NULL) 1373 fprintf (stderr, GTXT ("Error: Script file cannot be opened: %s\n"), arg1); 1374 else 1375 { 1376 save_file = inp_file; 1377 inp_file = ck_file; 1378 proc_script (); 1379 inp_file = save_file; 1380 } 1381 } 1382 else 1383 fprintf (stderr, GTXT ("Error: No filename has been specified.\n")); 1384 break; 1385 case QUIT: 1386 exit (0); 1387 break; 1388 1389 // commands relating to index Objects 1390 case INDXOBJ: 1391 if ((cparam == -1) && (arg1 == NULL)) 1392 { 1393 fprintf (stderr, GTXT ("Error: No index object name has been specified.\n")); 1394 break; 1395 } 1396 // automatically load machine model if applicable 1397 dbeDetectLoadMachineModel (dbevindex); 1398 indxobj (arg1, cparam); 1399 break; 1400 case INDXOBJLIST: 1401 // automatically load machine model if applicable 1402 dbeDetectLoadMachineModel (dbevindex); 1403 indxo_list (false, out_file); 1404 break; 1405 1406 // define a new IndexObject type 1407 case INDXOBJDEF: 1408 if (arg1 == NULL) 1409 { 1410 fprintf (stderr, GTXT ("Error: No index object name has been specified.\n")); 1411 break; 1412 } 1413 if (arg2 == NULL) 1414 { 1415 fprintf (stderr, GTXT ("Error: No index-expr has been specified.\n")); 1416 break; 1417 } 1418 indxo_define (arg1, arg2, arg3, arg4); 1419 break; 1420 1421 // the commands following this are unsupported/hidden 1422 case IFREQ: 1423 if (!dbeSession->is_ifreq_available ()) 1424 { 1425 fprintf (out_file, GTXT ("\nInstruction frequency data was not requested when recording experiments\n\n")); 1426 break; 1427 } 1428 ifreq (); 1429 break; 1430 case DUMPNODES: 1431 dump_nodes (); 1432 break; 1433 case DUMPSTACKS: 1434 dump_stacks (); 1435 break; 1436 case DUMPUNK: 1437 dump_unk_pcs (); 1438 break; 1439 case DUMPFUNC: 1440 dump_funcs (arg1); 1441 break; 1442 case DUMPDOBJS: 1443 dump_dataobjects (arg1); 1444 break; 1445 case DUMPMAP: 1446 dump_map (); 1447 break; 1448 case DUMPENTITIES: 1449 dump_entities (); 1450 break; 1451 case DUMP_PROFILE: 1452 dbev->dump_profile (out_file); 1453 break; 1454 case DUMP_SYNC: 1455 dbev->dump_sync (out_file); 1456 break; 1457 case DUMP_HWC: 1458 dbev->dump_hwc (out_file); 1459 break; 1460 case DUMP_HEAP: 1461 if (!dbeSession->is_leaklist_available ()) 1462 { 1463 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n")); 1464 break; 1465 } 1466 dbev->dump_heap (out_file); 1467 break; 1468 case DUMP_IOTRACE: 1469 if (!dbeSession->is_iodata_available ()) 1470 { 1471 fprintf (out_file, GTXT ("\nI/O trace information was not requested when recording experiments\n\n")); 1472 break; 1473 } 1474 dbev->dump_iotrace (out_file); 1475 break; 1476 case DMEM: 1477 if (arg1 == NULL) 1478 fprintf (stderr, GTXT ("Error: No sample has been specified.\n")); 1479 else 1480 { 1481 Experiment *exp = dbeSession->get_exp (0); 1482 if (exp != NULL) 1483 exp->DBG_memuse (arg1); 1484 } 1485 break; 1486 case DUMP_GC: 1487 if (!dbeSession->has_java ()) 1488 { 1489 fprintf (out_file, GTXT ("\nJava garbage collection information was not requested when recording experiments\n\n")); 1490 break; 1491 } 1492 dbev->dump_gc_events (out_file); 1493 break; 1494 case DKILL: 1495 { 1496 if (arg1 == NULL) 1497 { 1498 fprintf (stderr, GTXT ("Error: No process has been specified.\n")); 1499 break; 1500 } 1501 if (arg2 == NULL) 1502 { 1503 fprintf (stderr, GTXT ("Error: No signal has been specified.\n")); 1504 break; 1505 } 1506 pid_t p = (pid_t) atoi (arg1); 1507 int signum = atoi (arg2); 1508 char *ret = dbeSendSignal (p, signum); 1509 if (ret != NULL) 1510 fprintf (stderr, GTXT ("Error: %s"), ret); 1511 } 1512 break; 1513 case PROCSTATS: 1514 dump_stats (); 1515 break; 1516 case ADD_EXP: 1517 case OPEN_EXP: 1518 if (arg1 == NULL) 1519 fprintf (stderr, GTXT ("Error: No experiment name has been specified.\n")); 1520 else 1521 { 1522 Vector<Vector<char*>*> *groups = new Vector<Vector<char*>*>(1); 1523 Vector<char*> *list = new Vector<char*>(1); 1524 list->append (arg1); 1525 groups->append (list); 1526 char *res = dbeOpenExperimentList (dbevindex, groups, cmd_type == OPEN_EXP); 1527 if (cmd_type == OPEN_EXP) 1528 fprintf (stderr, GTXT ("Previously loaded experiment have been dropped.\n")); 1529 if (res != NULL) 1530 fprintf (stderr, NTXT ("%s"), res); 1531 else 1532 fprintf (stderr, GTXT ("Experiment %s has been loaded\n"), arg1); 1533 free (res); 1534 delete list; 1535 delete groups; 1536 } 1537 break; 1538 case DROP_EXP: 1539 { 1540 if (arg1 == NULL) 1541 fprintf (stderr, GTXT ("Error: No experiment name has been specified.\n")); 1542 else 1543 { 1544 int exp_index = dbeSession->find_experiment (arg1); 1545 if (exp_index < 0) 1546 fprintf (stderr, GTXT ("Error: experiment %s has not been opened.\n"), arg1); 1547 else 1548 { 1549 Vector<int> *expid = new Vector<int> (1); 1550 expid->append (exp_index); 1551 char *res = dbeDropExperiment (dbevindex, expid); 1552 if (res != NULL) 1553 fprintf (stderr, NTXT ("%s"), res); 1554 else 1555 fprintf (stderr, GTXT ("Experiment %s has been dropped\n"), arg1); 1556 delete expid; 1557 free (res); 1558 } 1559 } 1560 } 1561 break; 1562 case HHELP: 1563 // automatically load machine model if applicable 1564 dbeDetectLoadMachineModel (dbevindex); 1565 Command::print_help (whoami, false, false, out_file); 1566 fprintf (out_file, NTXT ("\n")); 1567 indxo_list (false, out_file); 1568 fprintf (out_file, NTXT ("\n")); 1569 mo_list (false, out_file); 1570 if (!getenv ("_BUILDING_MANPAGE")) 1571 fprintf (out_file, GTXT ("\nSee gprofng(1) for more details\n")); 1572 break; 1573 case QQUIT: 1574 was_QQUIT = true; 1575 return; 1576 default: 1577 fprintf (stderr, GTXT ("Error: Invalid option\n")); 1578 break; 1579 } 1580 1581 // check for any processing error messages 1582 dump_proc_warnings (); 1583 fflush (out_file); 1584 } 1585 1586 #define MAX_NUM_HEADER 4 1587 1588 void 1589 er_print::disp_list (int num_header, int size, int align[], char *header[], 1590 char **lists[]) 1591 { 1592 size_t maxlen[MAX_NUM_HEADER]; 1593 char fmt[MAX_NUM_HEADER][64]; 1594 if (num_header > MAX_NUM_HEADER) 1595 abort (); 1596 for (int i = 0; i < num_header; i++) 1597 { 1598 maxlen[i] = strlen (header[i]); 1599 for (int j = 0; j < size; j++) 1600 { 1601 size_t len = strlen (lists[i][j]); 1602 if (maxlen[i] < len) 1603 maxlen[i] = len; 1604 } 1605 1606 // get format string 1607 if ((align[i] == -1) && (i == num_header - 1)) 1608 snprintf (fmt[i], sizeof (fmt[i]), NTXT ("%%s ")); 1609 else 1610 snprintf (fmt[i], sizeof (fmt[i]), NTXT ("%%%ds "), (int) (align[i] * maxlen[i])); 1611 1612 // write header 1613 fprintf (out_file, fmt[i], header[i]); 1614 } 1615 putc ('\n', out_file); 1616 1617 // write separator "===" 1618 size_t np = 0; 1619 for (int i = 0; (i < num_header) && (np < 132); i++) 1620 { 1621 size_t nc = maxlen[i]; 1622 if (nc + np > 132) 1623 nc = 132 - np; 1624 for (size_t j = 0; j < nc; j++) 1625 putc ('=', out_file); 1626 putc (' ', out_file); 1627 np += nc + 1; 1628 } 1629 putc ('\n', out_file); 1630 1631 // write lists 1632 for (int j = 0; j < size; j++) 1633 { 1634 for (int i = 0; i < num_header; i++) 1635 fprintf (out_file, fmt[i], lists[i][j]); 1636 putc ('\n', out_file); 1637 } 1638 } 1639 1640 void 1641 er_print::exp_list () 1642 { 1643 int size, index; 1644 int align[MAX_NUM_HEADER]; 1645 char *header[MAX_NUM_HEADER]; 1646 char **lists[MAX_NUM_HEADER]; 1647 1648 align[0] = 1; // right-justify 1649 align[1] = 1; // right-justify 1650 align[2] = 1; // right-justify 1651 align[3] = -1; // left-justify 1652 header[0] = GTXT ("ID"); 1653 header[1] = GTXT ("Sel"); 1654 header[2] = GTXT ("PID"); 1655 header[3] = GTXT ("Experiment"); 1656 1657 size = dbeSession->nexps (); 1658 lists[0] = new char*[size]; 1659 lists[1] = new char*[size]; 1660 lists[2] = new char*[size]; 1661 lists[3] = new char*[size]; 1662 for (index = 0; index < size; index++) 1663 { 1664 lists[0][index] = dbe_sprintf (NTXT ("%d"), index + 1); 1665 lists[1][index] = strdup (dbev->get_exp_enable (index) ? GTXT ("yes") : GTXT ("no")); 1666 lists[2][index] = dbe_sprintf (NTXT ("%d"), dbeSession->get_exp (index)->getPID ()); 1667 lists[3][index] = strdup (dbeSession->get_exp (index)->get_expt_name ()); 1668 } 1669 disp_list (4, size, align, header, lists); 1670 for (int i = 0; i < 4; i++) 1671 { 1672 for (int j = 0; j < size; j++) 1673 free (lists[i][j]); 1674 delete[] lists[i]; 1675 } 1676 } 1677 1678 void 1679 er_print::describe () 1680 { 1681 Vector<void*> *res = dbeGetFilterKeywords (dbev->vindex); 1682 if (res == NULL) 1683 return; 1684 Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1); 1685 Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3); 1686 Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4); 1687 Vector <char*> *kwDescrip = (Vector<char*>*) res->fetch (5); 1688 Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6); 1689 String sectionFormat = NTXT ("\n------ %s ------\n"); 1690 String categoryFormat = NTXT ("\n%s\n"); 1691 String keywordFormat = NTXT (" %-20s %s\n"); 1692 String empty = NTXT (""); 1693 String previousCategory = empty; 1694 1695 for (int i = 0; i < kwKeyword->size (); i++) 1696 { 1697 if (kwKeyword->fetch (i) == NULL) 1698 { 1699 fprintf (dis_file, sectionFormat, kwCategoryI18N->fetch (i)); 1700 continue; 1701 } 1702 String cat = kwCategoryI18N->fetch (i); 1703 if (dbe_strcmp (previousCategory, cat) != 0) 1704 fprintf (dis_file, categoryFormat, cat); 1705 previousCategory = cat; 1706 Vector <String> *enumDescs = (Vector <String> *) kwEnumDescs->fetch (i); 1707 String keyword = kwKeyword->fetch (i); 1708 if (kwDescrip->fetch (i) != NULL) 1709 { 1710 fprintf (dis_file, keywordFormat, keyword, kwDescrip->fetch (i)); 1711 keyword = empty; 1712 } 1713 if (kwFormula->fetch (i) != NULL) 1714 { 1715 fprintf (dis_file, keywordFormat, keyword, kwFormula->fetch (i)); 1716 keyword = empty; 1717 continue; 1718 } 1719 int numEnums = enumDescs != NULL ? enumDescs->size () : 0; 1720 for (int jj = 0; jj < numEnums; jj++) 1721 { 1722 fprintf (dis_file, keywordFormat, keyword, enumDescs->fetch (jj)); 1723 keyword = empty; 1724 } 1725 } 1726 destroy (res); 1727 } 1728 1729 void 1730 er_print::obj_list () 1731 { 1732 LoadObject *lo; 1733 int index; 1734 int align[MAX_NUM_HEADER]; 1735 char *header[MAX_NUM_HEADER]; 1736 char **lists[MAX_NUM_HEADER]; 1737 Vector<LoadObject*> *text_segments = dbeSession->get_text_segments (); 1738 if (text_segments->size () == 0) 1739 { 1740 fprintf (dis_file, GTXT ("There are no load objects in this experiment\n")); 1741 return; 1742 } 1743 align[0] = -1; // left-justify 1744 align[1] = -1; // left-justify 1745 align[2] = -1; // left-justify 1746 align[3] = -1; // left-justify 1747 header[0] = GTXT ("Sel"); 1748 header[1] = GTXT ("Load Object"); 1749 header[2] = GTXT ("Index"); 1750 header[3] = GTXT ("Path"); 1751 1752 int size = text_segments->size (); 1753 lists[0] = new char*[size]; 1754 lists[1] = new char*[size]; 1755 lists[2] = new char*[size]; 1756 lists[3] = new char*[size]; 1757 1758 char *lo_name; 1759 int new_index = 0; 1760 Vec_loop (LoadObject*, text_segments, index, lo) 1761 { 1762 lo_name = lo->get_name (); 1763 if (lo_name != NULL) 1764 { 1765 size_t len = strlen (lo_name); 1766 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) 1767 continue; 1768 } 1769 LibExpand expand = dbev->get_lo_expand (lo->seg_idx); 1770 switch (expand) 1771 { 1772 case LIBEX_SHOW: 1773 lists[0][new_index] = dbe_strdup (GTXT ("show")); 1774 break; 1775 case LIBEX_HIDE: 1776 lists[0][new_index] = dbe_strdup (GTXT ("hide")); 1777 break; 1778 case LIBEX_API: 1779 lists[0][new_index] = dbe_strdup (GTXT ("API-only")); 1780 break; 1781 } 1782 lists[1][new_index] = dbe_strdup (lo_name); 1783 lists[2][new_index] = dbe_sprintf (NTXT ("%d"), lo->seg_idx); 1784 lists[3][new_index] = dbe_strdup (lo->get_pathname ()); 1785 new_index++; 1786 } 1787 disp_list (4, new_index, align, header, lists); 1788 for (int i = 0; i < 4; i++) 1789 { 1790 for (int j = 0; j < new_index; j++) 1791 free (lists[i][j]); 1792 delete[] lists[i]; 1793 } 1794 delete text_segments; 1795 } 1796 1797 void 1798 er_print::seg_list () 1799 { 1800 LoadObject *lo; 1801 int index; 1802 int align[MAX_NUM_HEADER]; 1803 char *header[MAX_NUM_HEADER]; 1804 char **lists[MAX_NUM_HEADER]; 1805 1806 // XXX seg_list only prints text segments; should extend to all 1807 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); 1808 if (lobjs->size () == 0) 1809 { 1810 fprintf (dis_file, GTXT ("There are no segments in this experiment\n")); 1811 return; 1812 } 1813 align[0] = -1; // left-justify 1814 align[1] = 1; // right-justify 1815 align[2] = -1; // left-justify 1816 header[0] = GTXT ("Sel"); 1817 header[1] = GTXT ("Size"); 1818 header[2] = GTXT ("Segment"); 1819 1820 int size = lobjs->size (); 1821 lists[0] = new char*[size]; 1822 lists[1] = new char*[size]; 1823 lists[2] = new char*[size]; 1824 1825 char *lo_name; 1826 int new_index = 0; 1827 Vec_loop (LoadObject*, lobjs, index, lo) 1828 { 1829 lo_name = lo->get_name (); 1830 if (lo_name != NULL) 1831 { 1832 size_t len = strlen (lo_name); 1833 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) 1834 continue; 1835 } 1836 bool expand = dbev->get_lo_expand (lo->seg_idx); 1837 lists[0][new_index] = strdup (expand ? GTXT ("yes") : GTXT ("no")); 1838 lists[1][new_index] = dbe_sprintf (NTXT ("%lld"), (ll_t) lo->get_size ()); 1839 lists[2][new_index] = strdup (lo->get_pathname ()); 1840 new_index++; 1841 } 1842 1843 disp_list (3, new_index, align, header, lists); 1844 for (int i = 0; i < 4; i++) 1845 { 1846 for (int j = 0; j < new_index; j++) 1847 free (lists[i][j]); 1848 delete[] lists[i]; 1849 } 1850 delete lobjs; 1851 } 1852 1853 void 1854 er_print::filter_list (CmdType cmd_type) 1855 { 1856 FilterNumeric *select; 1857 int index; 1858 int align[MAX_NUM_HEADER]; 1859 char *header[MAX_NUM_HEADER]; 1860 char **lists[MAX_NUM_HEADER]; 1861 char *pattern; 1862 1863 // first ensure that the data has been read 1864 MetricList *mlist = dbev->get_metric_list (MET_INDX); 1865 Hist_data *data = dbev->get_hist_data (mlist, Histable::INDEXOBJ, 0, Hist_data::ALL); 1866 delete data; 1867 1868 align[0] = 1; // right-justify 1869 align[1] = -1; // left-justify 1870 align[2] = 1; // right-justify 1871 align[3] = 1; // right-justify 1872 header[0] = GTXT ("Exp"); 1873 header[1] = GTXT ("Sel"); 1874 header[2] = GTXT ("Total"); 1875 header[3] = GTXT ("Status"); 1876 1877 int size = dbeSession->nexps (); 1878 lists[0] = new char*[size]; 1879 lists[1] = new char*[size]; 1880 lists[2] = new char*[size]; 1881 lists[3] = new char*[size]; 1882 int new_index = 0; 1883 for (index = 0; index < size; index++) 1884 { 1885 switch (cmd_type) 1886 { 1887 case SAMPLE_LIST: 1888 select = dbev->get_FilterNumeric (index, SAMPLE_FILTER_IDX); 1889 break; 1890 case THREAD_LIST: 1891 select = dbev->get_FilterNumeric (index, THREAD_FILTER_IDX); 1892 break; 1893 case LWP_LIST: 1894 select = dbev->get_FilterNumeric (index, LWP_FILTER_IDX); 1895 break; 1896 case CPU_LIST: 1897 select = dbev->get_FilterNumeric (index, CPU_FILTER_IDX); 1898 break; 1899 default: 1900 abort (); // internal error 1901 } 1902 if (select == NULL) 1903 continue; 1904 lists[0][new_index] = dbe_sprintf (NTXT ("%d"), index + 1); 1905 pattern = dbev->get_exp_enable (index) ? select->get_pattern () : NULL; 1906 lists[1][new_index] = strdup (pattern && *pattern ? pattern : GTXT ("none")); 1907 lists[2][new_index] = dbe_sprintf (NTXT ("%lld"), (ll_t) select->nelem ()); 1908 lists[3][new_index] = select->get_status (); 1909 new_index++; 1910 } 1911 disp_list (3, size, align, header, lists); 1912 for (int i = 0; i < 4; i++) 1913 { 1914 for (int j = 0; j < new_index; j++) 1915 free (lists[i][j]); 1916 delete[] lists[i]; 1917 } 1918 } 1919 1920 int 1921 er_print::check_exp_id (int exp_id, char *sel) 1922 { 1923 if (exp_id < 0 || exp_id >= dbeSession->nexps ()) 1924 { 1925 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\nType \"exp_list\" for a list of all experiments.\n"), 1926 sel); 1927 return -1; 1928 } 1929 return exp_id; 1930 } 1931 1932 int 1933 er_print::get_exp_id (char *sel, int &bgn_index, int &end_index) 1934 { 1935 int id, exp_id; 1936 if (sel == NULL || strcmp (sel, NTXT ("all")) == 0) 1937 { 1938 // loop over all experiments 1939 bgn_index = 0; 1940 end_index = dbeSession->nexps () - 1; 1941 } 1942 else 1943 { 1944 id = (int) strtol (sel, (char **) NULL, 10) - 1; 1945 exp_id = check_exp_id (id, sel); 1946 if (exp_id == -1) 1947 return -1; 1948 bgn_index = end_index = exp_id; 1949 } 1950 return 0; 1951 } 1952 1953 void 1954 er_print::print_objects () 1955 { 1956 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); 1957 char *msg = pr_load_objects (lobjs, NTXT ("")); 1958 delete lobjs; 1959 fprintf (out_file, NTXT ("%s\n"), msg); 1960 free (msg); 1961 } 1962 1963 void 1964 er_print::print_overview () 1965 { 1966 //fprintf(out_file, NTXT("%s\n"), GTXT("Not implemented yet."));//YXXX 1967 Vector<char*> *status = dbeGetOverviewText (dbevindex); 1968 StringBuilder sb; 1969 sb.append (GTXT ("Experiment(s):\n\n")); 1970 for (int i = 0; i < status->size (); i++) 1971 sb.appendf (NTXT ("%s\n"), status->fetch (i)); 1972 sb.append (GTXT ("Metrics:\n")); 1973 sb.toFile (out_file); 1974 1975 Vector<void*> *data = dbeGetRefMetricTree (dbevindex, false); 1976 Vector<char *> *metric_cmds = new Vector<char *>(); 1977 Vector<char *> *non_metric_cmds = new Vector<char *>(); 1978 print_overview_nodes (data, 0, metric_cmds, non_metric_cmds); 1979 Vector<void*> *values = dbeGetRefMetricTreeValues (0, metric_cmds, non_metric_cmds); 1980 print_overview_tree (data, 0, values, metric_cmds, non_metric_cmds); 1981 1982 StringBuilder sb2; 1983 sb2.append (GTXT ("\nNotes: '*' indicates hot metrics, '[X]' indicates currently enabled metrics.\n")); 1984 sb2.append (GTXT (" The metrics command can be used to change selections. The metric_list command lists all available metrics.\n")); 1985 sb2.toFile (out_file); 1986 } 1987 1988 void 1989 er_print::print_overview_nodes (Vector<void*> * data, int level, Vector<char *> *metric_cmds, Vector<char *> *non_metric_cmds) 1990 { 1991 Vector<void*> *fields = (Vector<void*> *) data->fetch (0); 1992 Vector<void*> *children = (Vector<void*> *) data->fetch (1); 1993 char *name = ((Vector<char*> *)fields->fetch (0))->fetch (0); 1994 int vstyles_capable = ((Vector<int>*) fields->fetch (5))->fetch (0); //bitmask e.g.VAL_TIMEVAL 1995 bool has_value = ((Vector<bool>*) fields->fetch (10))->fetch (0); 1996 bool selectable = (vstyles_capable != 0) ? true : false; 1997 if (selectable) 1998 metric_cmds->append (name); 1999 else if (has_value) 2000 non_metric_cmds->append (name); 2001 2002 level++; 2003 for (int i = 0; i < children->size (); i++) 2004 print_overview_nodes ((Vector<void*> *)(children->fetch (i)), level, metric_cmds, non_metric_cmds); 2005 } 2006 2007 void 2008 er_print::print_overview_tree (Vector<void*> * data, int level, Vector<void*> * values, Vector<char *> *metric_cmds, Vector<char *> *non_metric_cmds) 2009 { 2010 Vector<void*> * fields = (Vector<void*> *) data->fetch (0); 2011 Vector<void*> * children = (Vector<void*> *) data->fetch (1); 2012 char *name = ((Vector<char*> *)fields->fetch (0))->fetch (0); 2013 char *username = ((Vector<char*> *)fields->fetch (1))->fetch (0); 2014 int flavors = ((Vector<int>*) fields->fetch (3))->fetch (0); //bitmask e.g. EXCLUSIVE 2015 int vstyles_capable = ((Vector<int>*) fields->fetch (5))->fetch (0); //bitmask e.g.VAL_TIMEVAL 2016 // bool aggregation = ((Vector<bool>*) fields->fetch(9))->fetch(0); 2017 // bool has_value = ((Vector<bool>*) fields->fetch(10))->fetch(0); 2018 char *unit = ((Vector<char*> *) fields->fetch (11))->fetch (0); 2019 2020 StringBuilder sb; 2021 for (int i = 0; i < level * 2; i++) 2022 sb.append (NTXT (" ")); // NOI18N 2023 2024 bool selectable = (vstyles_capable != 0) ? true : false; 2025 if (selectable) 2026 { 2027 bool isSelected = dbev->get_metric_list (MET_NORMAL)->find_metric_by_name (name) == NULL ? false : true; 2028 if (isSelected) 2029 sb.append (NTXT ("[X]")); 2030 else 2031 sb.append (NTXT ("[ ]")); 2032 } 2033 if ((unit != NULL && dbe_strcmp (unit, UNIT_SECONDS) == 0) 2034 || (unit == NULL && vstyles_capable & VAL_TIMEVAL)) 2035 unit = GTXT ("Seconds"); 2036 2037 bool isHiddenInOverview = ((flavors & BaseMetric::STATIC) != 0); 2038 if (name != NULL && dbe_strcmp (name, L1_STATIC) == 0) 2039 isHiddenInOverview = true; 2040 if (!dbeSession->has_java () && name != NULL && dbe_strcmp (name, L1_GCDURATION) == 0) 2041 isHiddenInOverview = true; 2042 if (isHiddenInOverview) 2043 return; 2044 2045 sb.append (username == NULL ? NTXT ("") : username); // NOI18N 2046 int show = 0; 2047 if (name == NULL) 2048 show = 0; 2049 else if (strstr (name, NTXT ("PROFDATA_TYPE_")) == NULL) 2050 show = 1; 2051 2052 if (show) 2053 { 2054 sb.append (username == NULL ? NTXT ("") : NTXT (" - ")); // NOI18N 2055 sb.append (name == NULL ? NTXT ("") : name); // NOI18N 2056 } 2057 2058 // "Bugs 16624403 and 19539622" (leave this string intact for searches) 2059 // add an extra condition for now 2060 // once we have proper fixes, eliminate test on Bug16624402_extra_condition 2061 int Bug16624402_extra_condition = 1; 2062 if (username) 2063 { 2064 if (strcmp (username, NTXT ("Block Covered %")) == 0) Bug16624402_extra_condition = 0; 2065 if (strcmp (username, NTXT ("Instr Covered %")) == 0) Bug16624402_extra_condition = 0; 2066 } 2067 if (Bug16624402_extra_condition > 0 && values->size () > 0) 2068 { 2069 Vector<void*> * valueColumns = (Vector<void*> *)values->fetch (0); 2070 Vector<void*> * highlightColumns = (Vector<void*> *)values->fetch (1); 2071 int jj = 0; 2072 int found = 0; 2073 for (jj = 0; jj < valueColumns->size (); jj++) 2074 { 2075 const char *value_name = ""; 2076 if (jj < metric_cmds->size ()) 2077 value_name = metric_cmds->fetch (jj); 2078 else 2079 value_name = non_metric_cmds->fetch (jj - metric_cmds->size ()); 2080 if (dbe_strcmp (value_name, name) != 0) 2081 continue; 2082 else 2083 { 2084 found = 1; 2085 break; 2086 } 2087 } 2088 if (found) 2089 { 2090 Vector<void*> * valueVec = (Vector<void*> *)valueColumns->fetch (jj); 2091 Vector<bool> * highlights = (Vector<bool> *)highlightColumns->fetch (jj); 2092 for (int kk = 0; kk < valueVec->size (); kk++) 2093 { 2094 char * value_str; 2095 int show_value = 0; 2096 switch (valueVec->type ()) 2097 { 2098 case VEC_INTEGER: 2099 value_str = dbe_sprintf (NTXT ("%ld"), (long) (((Vector<int> *)valueVec)->fetch (kk))); 2100 show_value = 1; 2101 break; 2102 case VEC_DOUBLE: 2103 value_str = dbe_sprintf (NTXT ("%.3f"), (double) (((Vector<double> *)valueVec)->fetch (kk))); 2104 show_value = 1; 2105 break; 2106 case VEC_LLONG: 2107 value_str = dbe_sprintf (NTXT ("%lld"), (long long) (((Vector<long> *)valueVec)->fetch (kk))); 2108 show_value = 1; 2109 break; 2110 case VEC_STRING: 2111 value_str = NTXT (""); 2112 break; 2113 default: 2114 value_str = NTXT (""); 2115 } 2116 if (show_value) 2117 { 2118 if (kk == 0) 2119 { 2120 sb.append (unit == NULL ? NTXT ("") : NTXT (" (")); 2121 sb.append (unit == NULL ? NTXT ("") : unit); 2122 sb.append (unit == NULL ? NTXT ("") : NTXT (")")); 2123 sb.append (NTXT (":")); 2124 } 2125 bool highlight = highlights->fetch (kk); 2126 const char * hilite = highlight ? NTXT ("*") : NTXT (""); 2127 sb.append (NTXT (" [")); 2128 sb.append (hilite); 2129 sb.append (value_str); 2130 sb.append (NTXT ("]")); 2131 } 2132 } 2133 } 2134 } 2135 sb.append (NTXT ("\n")); 2136 sb.toFile (out_file); 2137 level++; 2138 for (int i = 0; i < children->size (); i++) 2139 print_overview_tree ((Vector<void*> *)(children->fetch (i)), level, values, metric_cmds, non_metric_cmds); 2140 } 2141 2142 void 2143 er_print::print_segments () 2144 { 2145 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments (); 2146 char *msg = pr_load_objects (lobjs, NTXT ("")); 2147 delete lobjs; 2148 fprintf (dis_file, NTXT ("Not implemented yet!\n")); 2149 free (msg); 2150 } 2151 2152 void 2153 er_print::print_dobj (Print_mode mode, MetricList *mlist1, 2154 char *dobj_name, char *sel) 2155 { 2156 Hist_data *hist_data = NULL; 2157 char *errstr; 2158 er_print_common_display *cd; 2159 int list_limit = limit; 2160 Histable *sobj = NULL; 2161 Dprintf (DEBUG_DATAOBJ, NTXT ("er_print::print_dobj(mode=%d,dobj=%s,sel=%s)\n"), 2162 mode, (dobj_name == NULL) ? NTXT ("0") : dobj_name, (sel == NULL) ? NTXT ("0") : sel); 2163 char *name = dbev->getSort (MET_DATA); 2164 switch (mode) 2165 { 2166 case MODE_LIST: 2167 hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::ALL); 2168 break; 2169 case MODE_DETAIL: 2170 // if specified, find the dataobject from the name 2171 if (dobj_name && strcmp (dobj_name, NTXT ("<All>"))) 2172 { 2173 if (!dbeSession->find_obj (dis_file, inp_file, sobj, dobj_name, 2174 sel, Histable::DOBJECT, (inp_file != stdin))) 2175 return; 2176 if (sobj == NULL) 2177 { // dataobject/segment not found 2178 hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::DETAIL); 2179 if (!dbeSession->find_obj (dis_file, inp_file, sobj, dobj_name, 2180 sel, Histable::DOBJECT, (inp_file != stdin))) 2181 return; 2182 if (sobj == NULL) 2183 { // dataobject/segment not found 2184 fprintf (stderr, GTXT ("Error: No dataobject with given name `%s' found.\n"), 2185 dobj_name); 2186 return; 2187 } 2188 } 2189 2190 list_limit = 1; 2191 } 2192 if (!hist_data) 2193 hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::DETAIL); 2194 break; 2195 case MODE_ANNOTATED: 2196 hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::LAYOUT); 2197 break; 2198 default: // MODE_GPROF is not relevant for DataObjects 2199 abort (); 2200 } 2201 2202 if (hist_data->get_status () != Hist_data::SUCCESS) 2203 { 2204 // XXXX is this error message adequate? 2205 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); 2206 if (errstr) 2207 { 2208 fprintf (stderr, GTXT ("Error: %s\n"), errstr); 2209 free (errstr); 2210 } 2211 delete hist_data; 2212 return; 2213 } 2214 cd = (er_print_common_display *) new er_print_histogram (dbev, hist_data, 2215 hist_data->get_metric_list (), mode, list_limit, name, sobj, false, false); 2216 free (name); 2217 print_cmd (cd); 2218 2219 delete hist_data; 2220 delete cd; 2221 } 2222 2223 void 2224 er_print::print_func (Histable::Type type, Print_mode mode, MetricList *mlist1, 2225 MetricList *mlist2, char *func_name, char *sel) 2226 { 2227 Hist_data *hist_data; 2228 Hist_data::HistItem *hitem; 2229 int index; 2230 char *errstr; 2231 int list_limit = limit; 2232 Histable *sobj = NULL; 2233 MetricList *mlist; 2234 StringBuilder sb; 2235 char *sname = dbev->getSort (MET_NORMAL); 2236 sb.append (sname); 2237 free (sname); 2238 2239 switch (mode) 2240 { 2241 case MODE_DETAIL: 2242 { 2243 // The first metric list, mlist1, is only used to pick out the sort 2244 // mlist2 is the one used to generate the data 2245 char *prevsort = NULL; 2246 // if specified, find the function from the function name 2247 if (func_name && strcmp (func_name, NTXT ("<All>"))) 2248 { 2249 if ((!dbeSession->find_obj (dis_file, inp_file, sobj, func_name, 2250 sel, Histable::FUNCTION, (inp_file != stdin)) || (sobj == NULL)) && 2251 !dbeSession->find_obj (dis_file, inp_file, sobj, func_name, 2252 sel, Histable::LOADOBJECT, (inp_file != stdin))) 2253 return; 2254 if (sobj == NULL) 2255 { // function/segment object not found 2256 fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"), 2257 func_name); 2258 return; 2259 } 2260 list_limit = 1; 2261 } 2262 else 2263 { 2264 // find the sort metric from the reference list 2265 prevsort = mlist2->get_sort_cmd (); 2266 2267 // find the current sort metric from the current list 2268 char *cursort = mlist1->get_sort_cmd (); 2269 2270 // find the corresponding metric in the reference list 2271 (void) mlist2->set_sort (cursort, false); 2272 free (cursort); 2273 // if it fails, nothing is needed 2274 } 2275 hist_data = dbev->get_hist_data (mlist2, type, 0, Hist_data::ALL); 2276 2277 // restore 2278 if (sobj == NULL) 2279 { 2280 if (prevsort == NULL) 2281 abort (); 2282 (void) mlist2->set_sort (prevsort, false); 2283 } 2284 mlist = mlist2; 2285 free (prevsort); 2286 break; 2287 } 2288 case MODE_GPROF: 2289 // if specified, find the function from the function name 2290 if (func_name && strcmp (func_name, NTXT ("<All>"))) 2291 { 2292 if (!dbeSession->find_obj (dis_file, inp_file, sobj, func_name, 2293 sel, Histable::FUNCTION, (inp_file != stdin))) 2294 return; 2295 if (sobj == NULL) 2296 { // function/segment object not found 2297 fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"), 2298 func_name); 2299 return; 2300 } 2301 list_limit = 1; 2302 sb.setLength (0); 2303 } 2304 sb.append (GTXT ("\nCallers and callees sorted by metric: ")); 2305 sname = dbev->getSort (MET_CALL); 2306 sb.append (sname); 2307 free (sname); 2308 2309 // Use mlist2 to generate the sort order. 2310 // mlist1 is used to generate the data. 2311 hist_data = dbev->get_hist_data (mlist2, type, 0, Hist_data::ALL); 2312 mlist = mlist1; 2313 break; 2314 default: 2315 hist_data = dbev->get_hist_data (mlist1, type, 0, Hist_data::ALL); 2316 mlist = mlist1; 2317 } 2318 2319 if (hist_data->get_status () != Hist_data::SUCCESS) 2320 { 2321 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA); 2322 if (errstr) 2323 { 2324 fprintf (stderr, GTXT ("Error: %s\n"), errstr); 2325 free (errstr); 2326 } 2327 delete hist_data; 2328 return; 2329 } 2330 2331 if (type == Histable::FUNCTION) 2332 { 2333 for (index = 0; index < hist_data->size (); index++) 2334 { 2335 hitem = hist_data->fetch (index); 2336 if (hitem->obj->get_type () == Histable::FUNCTION) 2337 // fetch the name, since that will force a format conversion 2338 ((Function *) hitem->obj)->get_name (); 2339 } 2340 } 2341 2342 char *name = sb.toString (); 2343 er_print_histogram *cd = new er_print_histogram (dbev, hist_data, 2344 mlist, mode, list_limit, name, sobj, false, false); 2345 print_cmd (cd); 2346 delete hist_data; 2347 free (name); 2348 delete cd; 2349 } 2350 2351 void 2352 er_print::print_gprof (CmdType cmd_type, char *func_name, char *sel) 2353 { 2354 Histable *sobj = NULL; 2355 if (func_name != NULL) 2356 { 2357 if ((!dbeSession->find_obj (dis_file, inp_file, sobj, func_name, 2358 sel, Histable::FUNCTION, (inp_file != stdin)) 2359 || sobj == NULL) 2360 && !dbeSession->find_obj (dis_file, inp_file, sobj, func_name, 2361 sel, Histable::LOADOBJECT, (inp_file != stdin))) 2362 return; 2363 if (sobj == NULL) 2364 { // function/segment object not found 2365 fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"), 2366 func_name); 2367 return; 2368 } 2369 } 2370 if (cmd_type == CPREPEND) 2371 { 2372 if (sobj == NULL) 2373 { 2374 fprintf (stderr, GTXT ("Error: No function name has been specified.\n")); 2375 return; 2376 } 2377 cstack->insert (0, sobj); 2378 } 2379 else if (cmd_type == CAPPEND) 2380 { 2381 if (sobj == NULL) 2382 { 2383 fprintf (stderr, GTXT ("Error: No function name has been specified.\n")); 2384 return; 2385 } 2386 cstack->append (sobj); 2387 } 2388 else if (cmd_type == CSINGLE) 2389 { 2390 if (sobj != NULL) 2391 { 2392 cstack->reset (); 2393 cstack->append (sobj); 2394 } 2395 else if (cstack->size () == 0) 2396 { 2397 fprintf (stderr, GTXT ("Error: No function name has been specified.\n")); 2398 return; 2399 } 2400 } 2401 else if (cmd_type == CRMFIRST) 2402 { 2403 if (cstack->size () <= 1) 2404 { 2405 fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n")); 2406 return; 2407 } 2408 cstack->remove (0); 2409 } 2410 else if (cmd_type == CRMLAST) 2411 { 2412 if (cstack->size () <= 1) 2413 { 2414 fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n")); 2415 return; 2416 } 2417 cstack->remove (cstack->size () - 1); 2418 } 2419 2420 er_print_gprof *cd = new er_print_gprof (dbev, cstack); 2421 print_cmd (cd); 2422 delete cd; 2423 } 2424 2425 /* 2426 * Method print_ctree() prints Functions Call Tree. 2427 */ 2428 void 2429 er_print::print_ctree (CmdType cmd_type) 2430 { 2431 if (cmd_type != CALLTREE) 2432 { 2433 fprintf (stderr, GTXT ("Error: Invalid command type: %d\n"), cmd_type); 2434 return; 2435 } 2436 2437 Histable *sobj = dbeSession->get_Total_Function (); 2438 Vector<Histable*> *ctree_cstack = new Vector<Histable*>(); 2439 ctree_cstack->reset (); 2440 er_print_ctree *cd = new er_print_ctree (dbev, ctree_cstack, sobj, limit); 2441 print_cmd (cd); 2442 delete ctree_cstack; 2443 delete cd; 2444 } 2445 2446 void 2447 er_print::memobj (char *name, int cparam) 2448 { 2449 int type; 2450 if (name != NULL) 2451 { 2452 // find the memory object index for the name 2453 MemObjType_t *mot = MemorySpace::findMemSpaceByName (name); 2454 if (mot == NULL) 2455 { 2456 // unknown type, report the error 2457 fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name); 2458 return; 2459 } 2460 type = mot->type; 2461 } 2462 else 2463 { 2464 MemObjType_t *mot = MemorySpace::findMemSpaceByIndex (cparam); 2465 if (mot == NULL) 2466 { 2467 // unknown type, report the error 2468 fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name); 2469 return; 2470 } 2471 type = cparam; 2472 } 2473 dbePrintData (0, DSP_MEMOBJ, type, NULL, NULL, out_file); 2474 } 2475 2476 void 2477 er_print::mo_define (char *moname, char *mo_index_exp, char *machmodel, char *short_desc, char *long_desc) 2478 { 2479 char *ret = MemorySpace::mobj_define (moname, mo_index_exp, machmodel, short_desc, long_desc); 2480 if (ret != NULL) 2481 fprintf (stderr, GTXT ("mobj_define for %s failed: %s\n"), moname, ret); 2482 } 2483 2484 void 2485 er_print::mo_list (bool showtab, FILE *outf) 2486 { 2487 Vector<bool> *mtab = NULL; 2488 Vector<void*>*res = MemorySpace::getMemObjects (); 2489 if (showtab) 2490 mtab = dbev->get_MemTabState (); 2491 if (res == NULL) 2492 // Since we checked already, this is an internal error 2493 abort (); 2494 2495 // unpack the return 2496 // Vector<char*> *index = (Vector<int> *)res->fetch(0); // not used 2497 Vector<char*> *mo_names = (Vector<char*> *)res->fetch (1); 2498 // Vector<char*> *mnemonic = (Vector<char> *)res->fetch(2); // not used 2499 Vector<char*> *mo_expr = (Vector<char*> *)res->fetch (3); 2500 Vector<char*> *mo_mach_m = (Vector<char*> *)res->fetch (4); 2501 // Vector<char*> *tmpOrder = (Vector<int> *)res->fetch(5); // not used 2502 2503 int size = mo_names->size (); 2504 if (size == 0) 2505 { 2506 if (!getenv ("_BUILDING_MANPAGE")) 2507 fprintf (outf, GTXT (" No Memory Object Types Defined\n")); 2508 } 2509 else 2510 { 2511 if (!getenv ("_BUILDING_MANPAGE")) 2512 fprintf (outf, GTXT (" Memory Object Types Available:\n")); 2513 else 2514 fprintf (outf, GTXT ("*Memory Object Types*\n")); 2515 for (int i = 0; i < size; i++) 2516 { 2517 if (mtab) 2518 fprintf (outf, NTXT (" %c %s\n"), mtab->fetch (i) ? 'T' : 'F', 2519 mo_names->fetch (i)); 2520 else 2521 { 2522 if (mo_mach_m->fetch (i) != NULL) 2523 fprintf (outf, NTXT (" %s\t\t\"%s\"\t\t(machinemodel: %s)\n"), 2524 mo_names->fetch (i), mo_expr->fetch (i), mo_mach_m->fetch (i)); 2525 else 2526 fprintf (outf, NTXT (" %s\t\t\"%s\"\n"), 2527 mo_names->fetch (i), mo_expr->fetch (i)); 2528 } 2529 } 2530 } 2531 delete mo_names; 2532 delete mo_expr; 2533 delete mo_mach_m; 2534 delete res; 2535 } 2536 2537 void 2538 er_print::indxobj (char *name, int cparam) 2539 { 2540 int type; 2541 if (name != NULL) 2542 { 2543 // find the index object index for the name 2544 type = dbeSession->findIndexSpaceByName (name); 2545 if (type < 0) 2546 { 2547 // unknown type, report the error 2548 fprintf (stderr, GTXT ("Error: Unknown Index Object type: %s\n"), name); 2549 return; 2550 } 2551 } 2552 else 2553 { 2554 char *indxname = dbeSession->getIndexSpaceName (cparam); 2555 if (indxname == NULL) 2556 { 2557 // unknown type, report the error 2558 fprintf (stderr, GTXT ("Error: Unknown Index Object type: %d\n"), cparam); 2559 return; 2560 } 2561 type = cparam; 2562 } 2563 dbePrintData (0, DSP_INDXOBJ, type, NULL, NULL, out_file); 2564 } 2565 2566 void 2567 er_print::indxo_define (char *ioname, char *io_index_exp, char *sdesc, char *ldesc) 2568 { 2569 char *ret = dbeDefineIndxObj (ioname, io_index_exp, sdesc, ldesc); 2570 if (ret != NULL) 2571 fprintf (stderr, GTXT ("indxobj_define for %s failed: %s\n"), ioname, ret); 2572 } 2573 2574 void 2575 er_print::indxo_list (bool showtab, FILE *outf) 2576 { 2577 Vector<bool> *indxtab = NULL; 2578 char *name; 2579 char *i18n_name; 2580 if (!getenv ("_BUILDING_MANPAGE")) 2581 fprintf (outf, GTXT (" Index Object Types Available:\n")); 2582 else 2583 fprintf (outf, GTXT ("*Index Object Types*\n")); 2584 Vector<void*>*res = dbeGetIndxObjDescriptions (0); 2585 if (showtab) 2586 indxtab = dbev->get_IndxTabState (); 2587 if (res == NULL) // If none is defined 2588 return; 2589 Vector<char*> *indxo_names = (Vector<char*> *)res->fetch (1); 2590 Vector<char*> *indxo_i18nnames = (Vector<char*> *)res->fetch (3); 2591 Vector<char*> *indxo_exprlist = (Vector<char*> *)res->fetch (5); 2592 int size = indxo_names->size (); 2593 for (int i = 0; i < size; i++) 2594 { 2595 name = indxo_names->fetch (i); 2596 i18n_name = indxo_i18nnames->fetch (i); 2597 if (indxtab) 2598 { 2599 if ((i18n_name != NULL) && (strcmp (i18n_name, name) != 0)) 2600 fprintf (outf, NTXT (" %c %s (%s)\n"), indxtab->fetch (i) ? 'T' : 'F', 2601 i18n_name, name); 2602 else 2603 fprintf (outf, NTXT (" %c %s\n"), indxtab->fetch (i) ? 'T' : 'F', name); 2604 } 2605 else 2606 { 2607 if (i18n_name != NULL && strcmp (i18n_name, indxo_names->fetch (i)) != 0) 2608 fprintf (outf, NTXT (" %s (%s)"), i18n_name, name); 2609 else 2610 fprintf (outf, NTXT (" %s"), name); 2611 } 2612 char *exprs = indxo_exprlist->fetch (i); 2613 if (exprs != NULL) 2614 fprintf (outf, NTXT (" \t%s\n"), exprs); 2615 else 2616 fprintf (outf, NTXT ("\n")); 2617 } 2618 delete indxo_names; 2619 if (showtab) 2620 delete res; 2621 } 2622 2623 void 2624 er_print::ifreq () 2625 { 2626 dbev->ifreq (out_file); 2627 } 2628 2629 void 2630 er_print::dump_nodes () 2631 { 2632 dbev->dump_nodes (out_file); 2633 } 2634 2635 void 2636 er_print::dump_stacks () 2637 { 2638 dbeSession->dump_stacks (out_file); 2639 } 2640 2641 void 2642 er_print::dump_unk_pcs () 2643 { 2644 // Dump the nodes associated with the <Unknown> function 2645 dbev->get_path_tree ()->dumpNodes (out_file, dbeSession->get_Unknown_Function ()); 2646 2647 // Dump the nodes associated with the <no Java callstack recorded> function 2648 Vector<Function *> *matches = dbeSession->match_func_names ("<no Java callstack recorded>", dbev->get_name_format ()); 2649 if (matches == NULL || matches->size () == 0) 2650 fprintf (out_file, GTXT ("No %s functions found\n"), "<no Java callstack recorded>"); 2651 else 2652 { 2653 Function *fitem; 2654 int index; 2655 Vec_loop (Function*, matches, index, fitem) 2656 { 2657 dbev->get_path_tree ()->dumpNodes (out_file, fitem); 2658 } 2659 delete matches; 2660 } 2661 } 2662 2663 void 2664 er_print::dump_funcs (char *arg1) 2665 { 2666 if (arg1 == NULL || strlen (arg1) == 0) 2667 dbeSession->dump_segments (out_file); 2668 else 2669 { 2670 Vector<Function *> *matches = dbeSession->match_func_names (arg1, dbev->get_name_format ()); 2671 if (matches == NULL) 2672 { 2673 fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1); 2674 return; 2675 } 2676 fprintf (out_file, GTXT ("%d Function's match `%s'\n"), (int) matches->size (), arg1); 2677 Function *fitem; 2678 int index; 2679 Vec_loop (Function*, matches, index, fitem) 2680 { 2681 fprintf (out_file, NTXT (" %5lld -- %s (%s) [%s]\n"), 2682 (ll_t) fitem->id, fitem->get_name (), 2683 (fitem->module ? fitem->module->file_name : NTXT ("<unknown>")), 2684 ((fitem->module && fitem->module->loadobject) ? 2685 get_basename (fitem->module->loadobject->get_name ()) : NTXT ("<unknown>"))); 2686 } 2687 delete matches; 2688 } 2689 } 2690 2691 void 2692 er_print::dump_dataobjects (char *arg1) 2693 { 2694 // Force computation of data objects, to update master table; discard it 2695 MetricList *mlist1 = dbev->get_metric_list (MET_DATA); 2696 Hist_data *data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::ALL); 2697 delete data; 2698 2699 if (arg1 == NULL || strlen (arg1) == 0) 2700 dbeSession->dump_dataobjects (out_file); 2701 else 2702 { 2703 Vector<DataObject *> *matches = dbeSession->match_dobj_names (arg1); 2704 if (matches == NULL) 2705 { 2706 fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1); 2707 return; 2708 } 2709 fprintf (out_file, GTXT ("%d DataObject's match `%s'\n"), (int) matches->size (), arg1); 2710 DataObject *ditem; 2711 int index; 2712 Vec_loop (DataObject*, matches, index, ditem) 2713 { 2714 fprintf (out_file, NTXT (" %5lld -- %s\n"), (ll_t) ditem->id, ditem->get_name ()); 2715 } 2716 delete matches; 2717 } 2718 } 2719 2720 void 2721 er_print::dump_map () 2722 { 2723 dbeSession->dump_map (out_file); 2724 } 2725 2726 void 2727 er_print::dump_entities () 2728 { 2729 int ent_prop_ids[] = {PROP_THRID, PROP_LWPID, PROP_CPUID, PROP_EXPID, -1}; 2730 2731 // loop over experiments 2732 for (int exp_id = 0; exp_id < dbeSession->nexps (); exp_id++) 2733 { 2734 Experiment *exp = dbeSession->get_exp (exp_id); 2735 fprintf (out_file, GTXT ("Experiment %d (%s)\n"), 2736 exp_id, exp->get_expt_name ()); 2737 2738 for (int kk = 0; ent_prop_ids[kk] != -1; kk++) 2739 { 2740 int ent_prop_id = ent_prop_ids[kk]; 2741 Vector<void*> *elist = dbeGetEntities (0, exp_id, ent_prop_id); 2742 if (!elist) 2743 continue; 2744 Vector<int> *entity_vals = (Vector<int> *) elist->fetch (0); 2745 Vector<char*> *jthr_names = (Vector<char*> *)elist->fetch (1); 2746 Vector<char*> *jthr_g_names = (Vector<char*> *)elist->fetch (2); 2747 Vector<char*> *jthr_p_names = (Vector<char*> *)elist->fetch (3); 2748 Vector<char*> *entity_name = (Vector<char*> *)elist->fetch (4); 2749 int nent = entity_vals->size (); 2750 char *entName = entity_name->fetch (0); 2751 if (!entName) 2752 entName = NTXT ("<unknown>"); 2753 fprintf (out_file, GTXT (" %s\n"), entName); 2754 for (int i = 0; i < nent; i++) 2755 fprintf (out_file, GTXT (" %s=%d: %s, %s, %s\n"), 2756 entName, entity_vals->fetch (i), 2757 jthr_names->fetch (i) != NULL ? jthr_names->fetch (i) : NTXT ("N/A"), 2758 jthr_g_names->fetch (i) != NULL ? jthr_g_names->fetch (i) : NTXT ("N/A"), 2759 jthr_p_names->fetch (i) != NULL ? jthr_names->fetch (i) : NTXT ("N/A")); 2760 destroy (elist); 2761 } 2762 } 2763 } 2764 2765 void 2766 er_print::dump_stats () 2767 { 2768 Emsg *m = dbev->get_path_tree ()->fetch_stats (); 2769 while (m != NULL) 2770 { 2771 fprintf (out_file, NTXT ("%s\n"), m->get_msg ()); 2772 m = m->next; 2773 } 2774 dbev->get_path_tree ()->delete_stats (); 2775 } 2776 2777 void 2778 er_print::dump_proc_warnings () 2779 { 2780 PathTree *p = dbev->get_path_tree (); 2781 if (p == NULL) 2782 return; 2783 Emsg *m = p->fetch_warnings (); 2784 while (m != NULL) 2785 { 2786 fprintf (out_file, NTXT ("%s\n"), m->get_msg ()); 2787 m = m->next; 2788 } 2789 dbev->get_path_tree ()->delete_warnings (); 2790 } 2791 2792 void 2793 er_print::print_cmd (er_print_common_display *cd) 2794 { 2795 cd->set_out_file (out_file); 2796 cd->data_dump (); 2797 } 2798 2799 FILE * 2800 er_print::set_outfile (char *cmd, FILE *&set_file, bool append) 2801 { 2802 FILE *new_file; 2803 char *home; 2804 if (!strcasecmp (cmd, NTXT ("-"))) 2805 { 2806 new_file = stdout; 2807 out_fname = NTXT ("<stdout>"); 2808 } 2809 else if (!strcasecmp (cmd, NTXT ("--"))) 2810 { 2811 new_file = stderr; 2812 out_fname = NTXT ("<stderr>"); 2813 } 2814 else 2815 { 2816 char *fname; 2817 char *path = NULL; 2818 // Handle ~ in file names 2819 home = getenv (NTXT ("HOME")); 2820 if ((fname = strstr (cmd, NTXT ("~/"))) != NULL && home != NULL) 2821 path = dbe_sprintf (NTXT ("%s/%s"), home, fname + 2); 2822 else if ((fname = strstr (cmd, NTXT ("~"))) != NULL && home != NULL) 2823 path = dbe_sprintf (NTXT ("/home/%s"), fname + 1); 2824 else 2825 path = strdup (cmd); 2826 new_file = fopen (path, append ? NTXT ("a") : NTXT ("w")); 2827 if (new_file == NULL) 2828 { 2829 fprintf (stderr, GTXT ("Error: Unable to open file: %s\n"), cmd); 2830 free (path); 2831 return NULL; 2832 } 2833 out_fname = path; 2834 } 2835 if (set_file && set_file != stdout) 2836 fclose (set_file); 2837 set_file = new_file; 2838 return set_file; 2839 } 2840