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