Update year range in gprofng copyright notices
[binutils-gdb.git] / gprofng / src / gp-display-text.cc
blob0d0a5e75e44a96969e3aed1472e1fc65fe8ac6da
1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
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.
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.
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. */
21 #include "config.h"
22 #include <unistd.h> // isatty
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"
50 static char *exe_name;
51 static char **new_argv;
53 void
54 reexec ()
56 if (dbeSession != NULL)
57 dbeSession->unlink_tmp_files ();
58 execv (exe_name, new_argv);
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
68 static void
69 reexec_enhance (int argc, char *argv[])
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)
86 fflush (stdout);
87 printf (GTXT ("Warning: History and command editing is not supported on this system.\n"));
88 fflush (stdout);
89 return;
91 else
93 printf (GTXT ("Note: History and command editing is supported on this system.\n"));
94 fflush (stdout);
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;
108 main (int argc, char *argv[])
110 er_print *erprint;
111 int ind = 1;
112 if (argc > ind && *argv[ind] == '-')
114 int arg_count, cparam;
115 if (Command::get_command (argv[ind] + 1, arg_count, cparam) == WHOAMI)
116 ind = ind + 1 + arg_count;
118 if (argc > ind && argv[ind] != NULL && *argv[ind] != '-')
119 reexec_enhance (argc, argv);
121 // Save argv for reexec())
122 exe_name = argv[0];
123 new_argv = argv;
125 if (argc > ind && argv[ind] != NULL && strcmp (argv[ind], "-IPC") == 0)
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);
132 else
134 erprint = new er_print (argc, argv);
135 erprint->start (argc, argv);
138 dbeSession->unlink_tmp_files ();
139 if (DUMP_CALL_STACK)
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]);
149 #if defined(DEBUG)
150 delete erprint;
151 #endif
152 return 0;
155 er_print::er_print (int argc, char *argv[])
156 : DbeApplication (argc, argv)
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;
168 er_print::~er_print ()
170 free (cov_string);
171 delete cstack;
172 if (inp_file != stdin)
173 fclose (inp_file);
176 void
177 er_print::start (int argc, char *argv[])
179 Vector<String> *res = theDbeApplication->initApplication (NULL, NULL, NULL);
180 res->destroy ();
181 delete res;
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)
191 fprintf (stderr, GTXT ("No valid experiments loaded; exiting\n"));
192 return;
194 dbeDetectLoadMachineModel (dbevindex);
195 run (argc, argv);
198 bool
199 er_print::free_memory_before_exit ()
201 return was_QQUIT;
204 void
205 er_print::usage ()
209 Ruud - Isolate this line because it has an argument. Otherwise it would be at the
210 end of the long option list.
212 printf ( GTXT (
213 "Usage: gprofng display text [OPTION(S)] [COMMAND(S)] [-script <script_file>] EXPERIMENT(S)\n"));
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"));
253 int // returns count of experiments read
254 er_print::check_args (int argc, char *argv[])
256 CmdType cmd_type;
257 int arg_count;
258 int cparam;
259 int exp_no;
260 error_msg = NULL;
262 Emsg *rcmsg = fetch_comments ();
263 while (rcmsg != NULL)
265 fprintf (stderr, NTXT ("%s: %s\n"), prog_name, rcmsg->get_msg ());
266 rcmsg = rcmsg->next;
268 delete_comments ();
270 // Set up the list of experiments to add after checking the args
271 Vector<Vector<char*>*> *exp_list = new Vector<Vector<char*>*>();
273 // Prescan the command line arguments, processing only a few
274 for (int i = 1; i < argc; i++)
276 if (*argv[i] != '-')
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)
283 for (int j = 0, list_sz = list->size (); j < list_sz; j++)
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)
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);
296 list->destroy ();
297 list->append (dbe_strdup (argv[i]));
298 exp_list->append (list);
300 else
301 delete list;
302 continue;
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))
308 case WHOAMI:
309 whoami = argv[i] + 1 + cparam;
310 break;
311 case HELP:
312 if (i + 1 + arg_count == argc)
314 usage();
315 exit (0);
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;
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);
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++)
392 Vector<char*>* p = exp_list->get (i);
393 Destroy (p);
395 delete exp_list;
396 if (errstr != NULL)
398 fprintf (stderr, NTXT ("%s"), errstr);
399 free (errstr);
402 return exp_no;
406 er_print::is_valid_seg_name (char *lo_name, int prev)
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;
415 // strip angle brackets from all but <Unknown> and <Total>
416 if (strcmp (lo_name, "<Unknown>") && strcmp (lo_name, "<Total>"))
418 if (*lo_name == '<')
420 name = dbe_strdup (lo_name + 1);
421 p_lo_name = name;
422 char *p = strchr (name, '>');
423 if (p)
424 *p = '\0';
428 // get the load object list from the session
429 Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
430 Vec_loop (LoadObject*, lobjs, index, lo)
432 if (prev > 0)
434 if (lo->seg_idx == prev) // this is where we left off
435 prev = -1;
436 continue;
439 // does this one match?
440 if (cmp_seg_name (lo->get_pathname (), p_lo_name))
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"))))
448 fprintf (stderr, GTXT ("Error: Java class `%s' is not selectable\n"), lo_name);
449 return -1;
451 return lo->seg_idx;
454 delete lobjs;
455 free (name);
456 return -1;
460 er_print::cmp_seg_name (char *full_name, char *lo_name)
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);
470 // processing object_select
471 // Note that this does not affect the strings in Settings,
472 // unlike object_show, object_hide, and object_api
474 er_print::process_object_select (char *names)
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)
485 dbev->set_lo_expand (lo->seg_idx, LIBEX_SHOW);
488 else
489 { // parsing coverage
490 // first, hide functions from all loadobjects
491 // except the java ones
492 Vec_loop (LoadObject*, lobjs, index, lo)
494 char *lo_name = lo->get_name ();
495 if (lo_name != NULL)
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;
502 dbev->set_lo_expand (lo->seg_idx, LIBEX_HIDE);
505 Vector <char *> *tokens = split_str (names, ',');
506 for (long j = 0, sz = VecSize (tokens); j < sz; j++)
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)
514 dbev->set_lo_expand (seg_idx, LIBEX_SHOW);
515 no_lobj++;
516 seg_idx = is_valid_seg_name (lo_name, seg_idx);
518 if (no_lobj == 0)
520 got_err = true;
521 fprintf (stderr, GTXT ("Error: Unknown load object: `%s'\n"), lo_name);
523 free (lo_name);
525 delete tokens;
528 if (!got_err)
529 { // good coverage string
530 free (cov_string);
531 cov_string = strdup (names);
533 else
534 { // bad, restore original coverage
535 no_lobj = -1;
536 process_object_select (cov_string);
538 delete lobjs;
539 return no_lobj;
543 er_print::set_libexpand (char *cov, enum LibExpand expand)
545 bool changed = dbev->set_libexpand (cov, expand);
546 if (changed == true)
547 dbev->update_lo_expands ();
548 return 0;
552 er_print::set_libdefaults ()
554 dbev->set_libdefaults ();
555 return 0;
558 bool
559 er_print::end_command (char *cmd)
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;
572 // Now actually start processing the arguments
573 void
574 er_print::run (int argc, char *argv[])
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++)
582 if (*argv[i] != '-') // open experiment pointer files
583 continue;
584 switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam))
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)
594 fprintf (stderr, GTXT ("Error: Script file cannot be opened: %s\n"), argv[i]);
595 exit (3);
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]))
610 i--;
611 arg1 = argv[i];
612 arg2 = NTXT ("");
614 else
616 arg1 = argv[i - 1];
617 arg2 = argv[i];
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]))
629 i--;
630 proc_cmd (cmd_type, cparam, argv[i], NTXT ("1"));
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]))
645 i--;
646 proc_cmd (cmd_type, cparam, NULL, NULL);
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;
679 if (!got) // no command has been specified
680 proc_script ();
683 #define MAXARGS 20
685 void
686 er_print::proc_script ()
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))
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;
709 // ensure it's terminated by a \n, and remove that character
710 strtok (script, NTXT ("\n"));
712 // extract the command
713 cmd = strtok (script, NTXT (" \t"));
714 if (cmd == NULL)
715 continue;
716 if (*cmd == '#')
718 fprintf (stderr, NTXT ("%s"), line);
719 continue;
721 if (*cmd == '\n')
722 continue;
724 char *remainder = strtok (NULL, NTXT ("\n"));
725 // now extract the arguments
726 int nargs = 0;
727 for (;;)
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)
739 parse_qstring (nextarg, &end_cmd);
740 nargs++;
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++;
752 cmd_type = Command::get_command (cmd, arg_count, cparam);
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)
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;
793 // free up the input line
794 free (script);
795 free (line);
798 void
799 er_print::proc_cmd (CmdType cmd_type, int cparam,
800 char *arg1, char *arg2, char *arg3, char *arg4, bool xdefault)
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)
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 ())
855 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
856 break;
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:
904 if (arg3 != NULL)
905 abort ();
906 if (arg1 == NULL)
908 fprintf (stderr, GTXT ("Error: Invalid function/file setting: \n"));
909 break;
911 char *fcontext = NULL;
912 char *arg = parse_fname (arg1, &fcontext);
913 if (arg == NULL)
915 fprintf (stderr, GTXT ("Error: Invalid function/file setting: %s\n"), arg1);
916 free (fcontext);
917 break;
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;
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)
935 char *ret = dbev->setMetrics (arg1, false);
936 if (ret != NULL)
938 fprintf (stderr, GTXT ("Error: %s\n"), ret);
939 proc_cmd (METRIC_LIST, cparam, NULL, NULL);
940 break;
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)
966 char *ret = dbev->setSort (arg1, MET_NORMAL, false);
967 if (ret != NULL)
969 fprintf (stderr, GTXT ("Error: %s\n"), ret);
970 proc_cmd (METRICS, cparam, NULL, NULL);
971 break;
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);
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)
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"));
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)
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"));
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)
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);
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)
1084 set_outfile (arg1, out_file, false);
1085 if (inp_file != stdin)
1086 dis_file = out_file;
1088 break;
1089 case APPENDFILE:
1090 if (arg1)
1092 set_outfile (arg1, out_file, true);
1093 if (inp_file != stdin)
1094 dis_file = out_file;
1096 break;
1097 case LIMIT:
1098 if (arg1)
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);
1106 limit = dbeGetPrintLimit (dbevindex);
1107 fprintf (stderr, GTXT ("Print limit set to %d\n"), limit);
1108 break;
1109 case NAMEFMT:
1110 if (arg1)
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);
1116 else
1117 fprintf (stderr, GTXT ("Error: No format has been specified.\n"));
1118 break;
1119 case VIEWMODE:
1121 if (arg1)
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);
1127 const char *vname = "unknown";
1128 int vm = dbev->get_view_mode ();
1129 switch (vm)
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;
1141 fprintf (stderr, GTXT ("Viewmode set to %s\n"), vname);
1143 break;
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)
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);
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)
1164 fprintf (dis_file, NTXT ("\t%s\n"), name);
1166 break;
1167 case PATHMAP:
1169 Vector<pathmap_t*> *pathMaps = dbeSession->get_pathmaps ();
1170 if (arg1 != NULL)
1172 if (arg2 == NULL)
1174 fprintf (stderr, GTXT ("Error: No replacement path prefix has been specified.\n"));
1175 break;
1177 // add this mapping to the session
1178 char *err = Settings::add_pathmap (pathMaps, arg1, arg2);
1179 if (err != NULL)
1181 fprintf (stderr, NTXT ("%s"), err);
1182 free (err);
1185 fprintf (dis_file, GTXT ("Path mappings: from -> to\n"));
1186 for (int i = 0, sz = pathMaps->size (); i < sz; i++)
1188 pathmap_t *thismap = pathMaps->get (i);
1189 fprintf (dis_file, NTXT ("\t`%s' -> `%s'\n"), thismap->old_prefix, thismap->new_prefix);
1192 break;
1193 case SAMPLE_DETAIL:
1194 if (get_exp_id (arg1, bgn_index, end_index) != -1)
1196 cd = new er_print_experiment (dbev, bgn_index, end_index, false,
1197 false, false, true, true);
1198 print_cmd (cd);
1199 delete cd;
1201 break;
1202 case STATISTICS:
1203 if (get_exp_id (arg1, bgn_index, end_index) != -1)
1205 cd = new er_print_experiment (dbev, bgn_index, end_index, false,
1206 false, true, true, false);
1207 print_cmd (cd);
1208 delete cd;
1210 break;
1211 case PRINTMODE:
1213 if (arg1 == NULL)
1215 fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex));
1216 break;
1218 char *s = dbeSetPrintMode (dbevindex, arg1);
1219 if (s != NULL)
1221 fprintf (stderr, NTXT ("%s\n"), s);
1222 break;
1224 fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex));
1226 break;
1227 case HEADER:
1228 if (get_exp_id (arg1, bgn_index, end_index) != -1)
1230 cd = new er_print_experiment (dbev, bgn_index, end_index, false,
1231 true, false, false, false);
1232 print_cmd (cd);
1233 delete cd;
1235 break;
1236 case COMPARE:
1237 if (arg1 == NULL)
1239 fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n"));
1240 break;
1242 else
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
1255 fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n"));
1256 break;
1258 int oldMode = dbev->get_compare_mode ();
1259 dbev->set_compare_mode (cmp);
1260 if (oldMode != cmp)
1262 dbev->reset_data (false);
1263 dbeSession->reset_data ();
1266 break;
1267 case LEAKS:
1268 if (!dbeSession->is_leaklist_available ())
1270 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
1271 break;
1273 if (dbev->comparingExperiments ())
1274 { // XXXX show warning for compare
1275 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
1276 break;
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 ())
1285 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
1286 break;
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 ())
1295 fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n"));
1296 break;
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 ())
1305 fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n"));
1306 break;
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 ())
1315 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
1316 break;
1318 if (dbev->comparingExperiments ())
1319 { // XXXX show warning for compare
1320 fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
1321 break;
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 ())
1330 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
1331 break;
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 ())
1340 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
1341 break;
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 ())
1350 fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
1351 break;
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)
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
1371 save_file = inp_file;
1372 inp_file = ck_file;
1373 proc_script ();
1374 inp_file = save_file;
1377 else
1378 fprintf (stderr, GTXT ("Error: No filename has been specified.\n"));
1379 break;
1380 case QUIT:
1381 exit (0);
1382 break;
1384 // commands relating to index Objects
1385 case INDXOBJ:
1386 if ((cparam == -1) && (arg1 == NULL))
1388 fprintf (stderr, GTXT ("Error: No index object name has been specified.\n"));
1389 break;
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;
1401 // define a new IndexObject type
1402 case INDXOBJDEF:
1403 if (arg1 == NULL)
1405 fprintf (stderr, GTXT ("Error: No index object name has been specified.\n"));
1406 break;
1408 if (arg2 == NULL)
1410 fprintf (stderr, GTXT ("Error: No index-expr has been specified.\n"));
1411 break;
1413 indxo_define (arg1, arg2, arg3, arg4);
1414 break;
1416 // the commands following this are unsupported/hidden
1417 case IFREQ:
1418 if (!dbeSession->is_ifreq_available ())
1420 fprintf (out_file, GTXT ("\nInstruction frequency data was not requested when recording experiments\n\n"));
1421 break;
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 ())
1458 fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
1459 break;
1461 dbev->dump_heap (out_file);
1462 break;
1463 case DUMP_IOTRACE:
1464 if (!dbeSession->is_iodata_available ())
1466 fprintf (out_file, GTXT ("\nI/O trace information was not requested when recording experiments\n\n"));
1467 break;
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
1476 Experiment *exp = dbeSession->get_exp (0);
1477 if (exp != NULL)
1478 exp->DBG_memuse (arg1);
1480 break;
1481 case DUMP_GC:
1482 if (!dbeSession->has_java ())
1484 fprintf (out_file, GTXT ("\nJava garbage collection information was not requested when recording experiments\n\n"));
1485 break;
1487 dbev->dump_gc_events (out_file);
1488 break;
1489 case DKILL:
1491 if (arg1 == NULL)
1493 fprintf (stderr, GTXT ("Error: No process has been specified.\n"));
1494 break;
1496 if (arg2 == NULL)
1498 fprintf (stderr, GTXT ("Error: No signal has been specified.\n"));
1499 break;
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);
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
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;
1532 break;
1533 case DROP_EXP:
1535 if (arg1 == NULL)
1536 fprintf (stderr, GTXT ("Error: No experiment name has been specified.\n"));
1537 else
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
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);
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;
1576 // check for any processing error messages
1577 dump_proc_warnings ();
1578 fflush (out_file);
1581 #define MAX_NUM_HEADER 4
1583 void
1584 er_print::disp_list (int num_header, int size, int align[], char *header[],
1585 char **lists[])
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++)
1593 maxlen[i] = strlen (header[i]);
1594 for (int j = 0; j < size; j++)
1596 size_t len = strlen (lists[i][j]);
1597 if (maxlen[i] < len)
1598 maxlen[i] = len;
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]));
1607 // write header
1608 fprintf (out_file, fmt[i], header[i]);
1610 putc ('\n', out_file);
1612 // write separator "==="
1613 size_t np = 0;
1614 for (int i = 0; (i < num_header) && (np < 132); i++)
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;
1624 putc ('\n', out_file);
1626 // write lists
1627 for (int j = 0; j < size; j++)
1629 for (int i = 0; i < num_header; i++)
1630 fprintf (out_file, fmt[i], lists[i][j]);
1631 putc ('\n', out_file);
1635 void
1636 er_print::exp_list ()
1638 int size, index;
1639 int align[MAX_NUM_HEADER];
1640 char *header[MAX_NUM_HEADER];
1641 char **lists[MAX_NUM_HEADER];
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");
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++)
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 ());
1664 disp_list (4, size, align, header, lists);
1665 for (int i = 0; i < 4; i++)
1667 for (int j = 0; j < size; j++)
1668 free (lists[i][j]);
1669 delete[] lists[i];
1673 void
1674 er_print::describe ()
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;
1690 for (int i = 0; i < kwKeyword->size (); i++)
1692 if (kwKeyword->fetch (i) == NULL)
1694 fprintf (dis_file, sectionFormat, kwCategoryI18N->fetch (i));
1695 continue;
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)
1705 fprintf (dis_file, keywordFormat, keyword, kwDescrip->fetch (i));
1706 keyword = empty;
1708 if (kwFormula->fetch (i) != NULL)
1710 fprintf (dis_file, keywordFormat, keyword, kwFormula->fetch (i));
1711 keyword = empty;
1712 continue;
1714 int numEnums = enumDescs != NULL ? enumDescs->size () : 0;
1715 for (int jj = 0; jj < numEnums; jj++)
1717 fprintf (dis_file, keywordFormat, keyword, enumDescs->fetch (jj));
1718 keyword = empty;
1721 destroy (res);
1724 void
1725 er_print::obj_list ()
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)
1735 fprintf (dis_file, GTXT ("There are no load objects in this experiment\n"));
1736 return;
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");
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];
1753 char *lo_name;
1754 int new_index = 0;
1755 Vec_loop (LoadObject*, text_segments, index, lo)
1757 lo_name = lo->get_name ();
1758 if (lo_name != NULL)
1760 size_t len = strlen (lo_name);
1761 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
1762 continue;
1764 LibExpand expand = dbev->get_lo_expand (lo->seg_idx);
1765 switch (expand)
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;
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++;
1782 disp_list (4, new_index, align, header, lists);
1783 for (int i = 0; i < 4; i++)
1785 for (int j = 0; j < new_index; j++)
1786 free (lists[i][j]);
1787 delete[] lists[i];
1789 delete text_segments;
1792 void
1793 er_print::seg_list ()
1795 LoadObject *lo;
1796 int index;
1797 int align[MAX_NUM_HEADER];
1798 char *header[MAX_NUM_HEADER];
1799 char **lists[MAX_NUM_HEADER];
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)
1805 fprintf (dis_file, GTXT ("There are no segments in this experiment\n"));
1806 return;
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");
1815 int size = lobjs->size ();
1816 lists[0] = new char*[size];
1817 lists[1] = new char*[size];
1818 lists[2] = new char*[size];
1820 char *lo_name;
1821 int new_index = 0;
1822 Vec_loop (LoadObject*, lobjs, index, lo)
1824 lo_name = lo->get_name ();
1825 if (lo_name != NULL)
1827 size_t len = strlen (lo_name);
1828 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
1829 continue;
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++;
1838 disp_list (3, new_index, align, header, lists);
1839 for (int i = 0; i < 4; i++)
1841 for (int j = 0; j < new_index; j++)
1842 free (lists[i][j]);
1843 delete[] lists[i];
1845 delete lobjs;
1848 void
1849 er_print::filter_list (CmdType cmd_type)
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;
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;
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");
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++)
1880 switch (cmd_type)
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
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++;
1906 disp_list (3, size, align, header, lists);
1907 for (int i = 0; i < 4; i++)
1909 for (int j = 0; j < new_index; j++)
1910 free (lists[i][j]);
1911 delete[] lists[i];
1916 er_print::check_exp_id (int exp_id, char *sel)
1918 if (exp_id < 0 || exp_id >= dbeSession->nexps ())
1920 fprintf (stderr, GTXT ("Error: Invalid number entered: %s\nType \"exp_list\" for a list of all experiments.\n"),
1921 sel);
1922 return -1;
1924 return exp_id;
1928 er_print::get_exp_id (char *sel, int &bgn_index, int &end_index)
1930 int id, exp_id;
1931 if (sel == NULL || strcmp (sel, NTXT ("all")) == 0)
1933 // loop over all experiments
1934 bgn_index = 0;
1935 end_index = dbeSession->nexps () - 1;
1937 else
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;
1945 return 0;
1948 void
1949 er_print::print_objects ()
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);
1958 void
1959 er_print::print_overview ()
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);
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);
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);
1983 void
1984 er_print::print_overview_nodes (Vector<void*> * data, int level, Vector<char *> *metric_cmds, Vector<char *> *non_metric_cmds)
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);
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);
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)
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);
2015 StringBuilder sb;
2016 for (int i = 0; i < level * 2; i++)
2017 sb.append (NTXT (" ")); // NOI18N
2019 bool selectable = (vstyles_capable != 0) ? true : false;
2020 if (selectable)
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 ("[ ]"));
2028 if ((unit != NULL && dbe_strcmp (unit, UNIT_SECONDS) == 0)
2029 || (unit == NULL && vstyles_capable & VAL_TIMEVAL))
2030 unit = GTXT ("Seconds");
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;
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;
2047 if (show)
2049 sb.append (username == NULL ? NTXT ("") : NTXT (" - ")); // NOI18N
2050 sb.append (name == NULL ? NTXT ("") : name); // NOI18N
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)
2059 if (strcmp (username, NTXT ("Block Covered %")) == 0) Bug16624402_extra_condition = 0;
2060 if (strcmp (username, NTXT ("Instr Covered %")) == 0) Bug16624402_extra_condition = 0;
2062 if (Bug16624402_extra_condition > 0 && values->size () > 0)
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++)
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
2079 found = 1;
2080 break;
2083 if (found)
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++)
2089 char * value_str;
2090 int show_value = 0;
2091 switch (valueVec->type ())
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 ("");
2111 if (show_value)
2113 if (kk == 0)
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 (":"));
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 ("]"));
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);
2137 void
2138 er_print::print_segments ()
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);
2147 void
2148 er_print::print_dobj (Print_mode mode, MetricList *mlist1,
2149 char *dobj_name, char *sel)
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)
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>")))
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;
2185 list_limit = 1;
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 ();
2197 if (hist_data->get_status () != Hist_data::SUCCESS)
2199 // XXXX is this error message adequate?
2200 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
2201 if (errstr)
2203 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2204 free (errstr);
2206 delete hist_data;
2207 return;
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);
2214 delete hist_data;
2215 delete cd;
2218 void
2219 er_print::print_func (Histable::Type type, Print_mode mode, MetricList *mlist1,
2220 MetricList *mlist2, char *func_name, char *sel)
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);
2234 switch (mode)
2236 case MODE_DETAIL:
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>")))
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;
2255 list_limit = 1;
2257 else
2259 // find the sort metric from the reference list
2260 prevsort = mlist2->get_sort_cmd ();
2262 // find the current sort metric from the current list
2263 char *cursort = mlist1->get_sort_cmd ();
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
2270 hist_data = dbev->get_hist_data (mlist2, type, 0, Hist_data::ALL);
2272 // restore
2273 if (sobj == NULL)
2275 if (prevsort == NULL)
2276 abort ();
2277 (void) mlist2->set_sort (prevsort, false);
2279 mlist = mlist2;
2280 free (prevsort);
2281 break;
2283 case MODE_GPROF:
2284 // if specified, find the function from the function name
2285 if (func_name && strcmp (func_name, NTXT ("<All>")))
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;
2296 list_limit = 1;
2297 sb.setLength (0);
2299 sb.append (GTXT ("\nCallers and callees sorted by metric: "));
2300 sname = dbev->getSort (MET_CALL);
2301 sb.append (sname);
2302 free (sname);
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;
2314 if (hist_data->get_status () != Hist_data::SUCCESS)
2316 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
2317 if (errstr)
2319 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2320 free (errstr);
2322 delete hist_data;
2323 return;
2326 if (type == Histable::FUNCTION)
2328 for (index = 0; index < hist_data->size (); index++)
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 ();
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;
2346 void
2347 er_print::print_gprof (CmdType cmd_type, char *func_name, char *sel)
2349 Histable *sobj = NULL;
2350 if (func_name != NULL)
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;
2365 if (cmd_type == CPREPEND)
2367 if (sobj == NULL)
2369 fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
2370 return;
2372 cstack->insert (0, sobj);
2374 else if (cmd_type == CAPPEND)
2376 if (sobj == NULL)
2378 fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
2379 return;
2381 cstack->append (sobj);
2383 else if (cmd_type == CSINGLE)
2385 if (sobj != NULL)
2387 cstack->reset ();
2388 cstack->append (sobj);
2390 else if (cstack->size () == 0)
2392 fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
2393 return;
2396 else if (cmd_type == CRMFIRST)
2398 if (cstack->size () <= 1)
2400 fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n"));
2401 return;
2403 cstack->remove (0);
2405 else if (cmd_type == CRMLAST)
2407 if (cstack->size () <= 1)
2409 fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n"));
2410 return;
2412 cstack->remove (cstack->size () - 1);
2415 er_print_gprof *cd = new er_print_gprof (dbev, cstack);
2416 print_cmd (cd);
2417 delete cd;
2421 * Method print_ctree() prints Functions Call Tree.
2423 void
2424 er_print::print_ctree (CmdType cmd_type)
2426 if (cmd_type != CALLTREE)
2428 fprintf (stderr, GTXT ("Error: Invalid command type: %d\n"), cmd_type);
2429 return;
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;
2441 void
2442 er_print::memobj (char *name, int cparam)
2444 int type;
2445 if (name != NULL)
2447 // find the memory object index for the name
2448 MemObjType_t *mot = MemorySpace::findMemSpaceByName (name);
2449 if (mot == NULL)
2451 // unknown type, report the error
2452 fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name);
2453 return;
2455 type = mot->type;
2457 else
2459 MemObjType_t *mot = MemorySpace::findMemSpaceByIndex (cparam);
2460 if (mot == NULL)
2462 // unknown type, report the error
2463 fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name);
2464 return;
2466 type = cparam;
2468 dbePrintData (0, DSP_MEMOBJ, type, NULL, NULL, out_file);
2471 void
2472 er_print::mo_define (char *moname, char *mo_index_exp, char *machmodel, char *short_desc, char *long_desc)
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);
2479 void
2480 er_print::mo_list (bool showtab, FILE *outf)
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 ();
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
2498 int size = mo_names->size ();
2499 if (size == 0)
2501 if (!getenv ("_BUILDING_MANPAGE"))
2502 fprintf (outf, GTXT (" No Memory Object Types Defined\n"));
2504 else
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++)
2512 if (mtab)
2513 fprintf (outf, NTXT (" %c %s\n"), mtab->fetch (i) ? 'T' : 'F',
2514 mo_names->fetch (i));
2515 else
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));
2526 delete mo_names;
2527 delete mo_expr;
2528 delete mo_mach_m;
2529 delete res;
2532 void
2533 er_print::indxobj (char *name, int cparam)
2535 int type;
2536 if (name != NULL)
2538 // find the index object index for the name
2539 type = dbeSession->findIndexSpaceByName (name);
2540 if (type < 0)
2542 // unknown type, report the error
2543 fprintf (stderr, GTXT ("Error: Unknown Index Object type: %s\n"), name);
2544 return;
2547 else
2549 char *indxname = dbeSession->getIndexSpaceName (cparam);
2550 if (indxname == NULL)
2552 // unknown type, report the error
2553 fprintf (stderr, GTXT ("Error: Unknown Index Object type: %d\n"), cparam);
2554 return;
2556 type = cparam;
2558 dbePrintData (0, DSP_INDXOBJ, type, NULL, NULL, out_file);
2561 void
2562 er_print::indxo_define (char *ioname, char *io_index_exp, char *sdesc, char *ldesc)
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);
2569 void
2570 er_print::indxo_list (bool showtab, FILE *outf)
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++)
2590 name = indxo_names->fetch (i);
2591 i18n_name = indxo_i18nnames->fetch (i);
2592 if (indxtab)
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);
2600 else
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);
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"));
2613 delete indxo_names;
2614 if (showtab)
2615 delete res;
2618 void
2619 er_print::ifreq ()
2621 dbev->ifreq (out_file);
2624 void
2625 er_print::dump_nodes ()
2627 dbev->dump_nodes (out_file);
2630 void
2631 er_print::dump_stacks ()
2633 dbeSession->dump_stacks (out_file);
2636 void
2637 er_print::dump_unk_pcs ()
2639 // Dump the nodes associated with the <Unknown> function
2640 dbev->get_path_tree ()->dumpNodes (out_file, dbeSession->get_Unknown_Function ());
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
2648 Function *fitem;
2649 int index;
2650 Vec_loop (Function*, matches, index, fitem)
2652 dbev->get_path_tree ()->dumpNodes (out_file, fitem);
2654 delete matches;
2658 void
2659 er_print::dump_funcs (char *arg1)
2661 if (arg1 == NULL || strlen (arg1) == 0)
2662 dbeSession->dump_segments (out_file);
2663 else
2665 Vector<Function *> *matches = dbeSession->match_func_names (arg1, dbev->get_name_format ());
2666 if (matches == NULL)
2668 fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1);
2669 return;
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)
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>")));
2682 delete matches;
2686 void
2687 er_print::dump_dataobjects (char *arg1)
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;
2694 if (arg1 == NULL || strlen (arg1) == 0)
2695 dbeSession->dump_dataobjects (out_file);
2696 else
2698 Vector<DataObject *> *matches = dbeSession->match_dobj_names (arg1);
2699 if (matches == NULL)
2701 fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1);
2702 return;
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)
2709 fprintf (out_file, NTXT (" %5lld -- %s\n"), (ll_t) ditem->id, ditem->get_name ());
2711 delete matches;
2715 void
2716 er_print::dump_map ()
2718 dbeSession->dump_map (out_file);
2721 void
2722 er_print::dump_entities ()
2724 int ent_prop_ids[] = {PROP_THRID, PROP_LWPID, PROP_CPUID, PROP_EXPID, -1};
2726 // loop over experiments
2727 for (int exp_id = 0; exp_id < dbeSession->nexps (); exp_id++)
2729 Experiment *exp = dbeSession->get_exp (exp_id);
2730 fprintf (out_file, GTXT ("Experiment %d (%s)\n"),
2731 exp_id, exp->get_expt_name ());
2733 for (int kk = 0; ent_prop_ids[kk] != -1; kk++)
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);
2760 void
2761 er_print::dump_stats ()
2763 Emsg *m = dbev->get_path_tree ()->fetch_stats ();
2764 while (m != NULL)
2766 fprintf (out_file, NTXT ("%s\n"), m->get_msg ());
2767 m = m->next;
2769 dbev->get_path_tree ()->delete_stats ();
2772 void
2773 er_print::dump_proc_warnings ()
2775 PathTree *p = dbev->get_path_tree ();
2776 if (p == NULL)
2777 return;
2778 Emsg *m = p->fetch_warnings ();
2779 while (m != NULL)
2781 fprintf (out_file, NTXT ("%s\n"), m->get_msg ());
2782 m = m->next;
2784 dbev->get_path_tree ()->delete_warnings ();
2787 void
2788 er_print::print_cmd (er_print_common_display *cd)
2790 cd->set_out_file (out_file);
2791 cd->data_dump ();
2794 FILE *
2795 er_print::set_outfile (char *cmd, FILE *&set_file, bool append)
2797 FILE *new_file;
2798 char *home;
2799 if (!strcasecmp (cmd, NTXT ("-")))
2801 new_file = stdout;
2802 out_fname = NTXT ("<stdout>");
2804 else if (!strcasecmp (cmd, NTXT ("--")))
2806 new_file = stderr;
2807 out_fname = NTXT ("<stderr>");
2809 else
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)
2824 fprintf (stderr, GTXT ("Error: Unable to open file: %s\n"), cmd);
2825 free (path);
2826 return NULL;
2828 out_fname = path;
2830 if (set_file && set_file != stdout)
2831 fclose (set_file);
2832 set_file = new_file;
2833 return set_file;