]> Git Repo - binutils.git/blob - gprofng/src/gp-display-text.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / gp-display-text.cc
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 }
This page took 0.185242 seconds and 4 git commands to generate.