xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/Settings.cc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/param.h>
26 
27 #include "enums.h"
28 #include "Settings.h"
29 #include "DbeSession.h"
30 #include "Command.h"
31 #include "Application.h"
32 #include "MemorySpace.h"
33 #include "StringBuilder.h"
34 #include "Table.h"
35 #include "Emsg.h"
36 #include "util.h"
37 #include "i18n.h"
38 
39 // Commands for compiler commentary
40 static const char *comp_cmd[] = {
41   NTXT ("basic"),
42   NTXT ("version"),
43   NTXT ("warn"),
44   NTXT ("parallel"),
45   NTXT ("query"),
46   NTXT ("loop"),
47   NTXT ("pipe"),
48   NTXT ("inline"),
49   NTXT ("memops"),
50   NTXT ("fe"),
51   NTXT ("codegen"),
52   NTXT ("src"),
53   NTXT ("asrc"),
54   NTXT ("nosrc"),
55   NTXT ("hex"),
56   NTXT ("nohex"),
57   NTXT ("threshold"),
58   NTXT ("cf")
59 };
60 
61 static const int comp_vis[] = {
62   CCMV_BASIC,
63   CCMV_VER,
64   CCMV_WARN,
65   CCMV_PAR,
66   CCMV_QUERY,
67   CCMV_LOOP,
68   CCMV_PIPE,
69   CCMV_INLINE,
70   CCMV_MEMOPS,
71   CCMV_FE,
72   CCMV_CG,
73   COMP_SRC,
74   COMP_SRC_METRIC,
75   COMP_NOSRC,
76   COMP_HEX,
77   COMP_NOHEX,
78   COMP_THRESHOLD,
79   COMP_CMPLINE
80 };
81 
82 const int comp_size = sizeof (comp_cmd) / sizeof (char *);
83 
84 // Commands for timeline
85 typedef enum
86 {
87   TLCMD_INVALID,
88   TLCMD_ENTITY_MODE,
89   TLCMD_ALIGN,
90   TLCMD_DEPTH
91 } TLModeSubcommand;
92 
93 typedef struct
94 {
95   const char * cmdText;
96   TLModeSubcommand cmdType;
97   int cmdId;
98 } TLModeCmd;
99 static const TLModeCmd tlmode_cmd[] = {
100   // MODE commands
101   {NTXT ("lwp"),        TLCMD_ENTITY_MODE, PROP_LWPID},
102   {NTXT ("thread"),     TLCMD_ENTITY_MODE, PROP_THRID},
103   {NTXT ("cpu"),        TLCMD_ENTITY_MODE, PROP_CPUID},
104   {NTXT ("experiment"), TLCMD_ENTITY_MODE, PROP_EXPID},
105   // ALIGN commands
106   {NTXT ("root"),       TLCMD_ALIGN, TLSTACK_ALIGN_ROOT},
107   {NTXT ("leaf"),       TLCMD_ALIGN, TLSTACK_ALIGN_LEAF},
108   // DEPTH commands
109   {NTXT ("depth"),      TLCMD_DEPTH, 0 /* don't care */}
110 };
111 
112 static const int tlmode_size = sizeof (tlmode_cmd) / sizeof (TLModeCmd);
113 
114 // Constructor
115 
Settings(Application * _app)116 Settings::Settings (Application *_app)
117 {
118   // Remember the application
119   app = _app;
120 
121   // Clear all default strings
122   str_vmode = NULL;
123   str_en_desc = NULL;
124   str_datamode = NULL;
125   str_scompcom = NULL;
126   str_sthresh = NULL;
127   str_dcompcom = NULL;
128   str_dthresh = NULL;
129   str_dmetrics = NULL;
130   str_dsort = NULL;
131   str_tlmode = NULL;
132   str_tldata = NULL;
133   str_tabs = NULL;
134   str_rtabs = NULL;
135   str_search_path = NULL;
136   str_name_format = NULL;
137   str_limit = NULL;
138   str_printmode = NULL;
139   str_compare = NULL;
140   preload_libdirs = NULL;
141   pathmaps = new Vector<pathmap_t*>;
142   lo_expands = new Vector<lo_expand_t*>;
143   lo_expand_default = LIBEX_SHOW;
144   is_loexpand_default = true;
145   tabs_processed = false;
146 
147   // set default-default values
148   name_format = Histable::NA;
149   view_mode = VMODE_USER;
150   en_desc = false;
151   en_desc_cmp = NULL;
152   en_desc_usr = NULL;
153   src_compcom = 2147483647;
154   dis_compcom = 2147483647;
155 #define DEFAULT_SRC_DIS_THRESHOLD 75
156   threshold_src = DEFAULT_SRC_DIS_THRESHOLD;
157   threshold_dis = DEFAULT_SRC_DIS_THRESHOLD;
158   src_visible = true;
159   srcmetric_visible = false;
160   hex_visible = false;
161   cmpline_visible = true;
162   funcline_visible = true;
163   tldata = NULL;
164   tlmode = 0;
165   stack_align = 0;
166   stack_depth = 0;
167   limit = 0;
168   // print mode is initialized after the .rc files are read
169   print_delim = ',';
170   compare_mode = CMP_DISABLE;
171   machinemodel = NULL;
172   ignore_no_xhwcprof = false;
173   ignore_fs_warn = false;
174 
175   // construct the master list of tabs
176   buildMasterTabList ();
177 
178   indx_tab_state = new Vector<bool>;
179   indx_tab_order = new Vector<int>;
180   mem_tab_state = new Vector<bool>;
181   mem_tab_order = new Vector<int>;
182 
183   // note that the .rc files are not read here, but later
184 }
185 
186 // Constructor for duplicating an existing Settings class
187 
Settings(Settings * _settings)188 Settings::Settings (Settings * _settings)
189 {
190   int index;
191   app = _settings->app;
192 
193   // Copy all default strings
194   str_vmode = dbe_strdup (_settings->str_vmode);
195   str_en_desc = dbe_strdup (_settings->str_en_desc);
196   str_datamode = dbe_strdup (_settings->str_datamode);
197   str_scompcom = dbe_strdup (_settings->str_scompcom);
198   str_sthresh = dbe_strdup (_settings->str_sthresh);
199   str_dcompcom = dbe_strdup (_settings->str_dcompcom);
200   str_dthresh = dbe_strdup (_settings->str_dthresh);
201   str_dmetrics = dbe_strdup (_settings->str_dmetrics);
202   str_dsort = dbe_strdup (_settings->str_dsort);
203   str_tlmode = dbe_strdup (_settings->str_tlmode);
204   str_tldata = dbe_strdup (_settings->str_tldata);
205   str_tabs = dbe_strdup (_settings->str_tabs);
206   str_rtabs = dbe_strdup (_settings->str_rtabs);
207   str_search_path = dbe_strdup (_settings->str_search_path);
208   str_name_format = dbe_strdup (_settings->str_name_format);
209   str_limit = dbe_strdup (_settings->str_limit);
210   str_printmode = dbe_strdup (_settings->str_printmode);
211   str_compare = dbe_strdup (_settings->str_compare);
212   preload_libdirs = dbe_strdup (_settings->preload_libdirs);
213 
214   // replicate the pathmap vector
215   pathmap_t *thismap;
216   pathmap_t *newmap;
217   pathmaps = new Vector<pathmap_t*>;
218 
219   Vec_loop (pathmap_t*, _settings->pathmaps, index, thismap)
220   {
221     newmap = new pathmap_t;
222     newmap->old_prefix = dbe_strdup (thismap->old_prefix);
223     newmap->new_prefix = dbe_strdup (thismap->new_prefix);
224     pathmaps->append (newmap);
225   }
226 
227   // replicate the lo_expand vector and default
228   lo_expand_t *this_lo_ex;
229   lo_expand_t *new_lo_ex;
230   lo_expand_default = _settings->lo_expand_default;
231   is_loexpand_default = _settings->is_loexpand_default;
232   lo_expands = new Vector<lo_expand_t*>;
233 
234   Vec_loop (lo_expand_t*, _settings->lo_expands, index, this_lo_ex)
235   {
236     new_lo_ex = new lo_expand_t;
237     new_lo_ex->libname = dbe_strdup (this_lo_ex->libname);
238     new_lo_ex->expand = this_lo_ex->expand;
239     lo_expands->append (new_lo_ex);
240   }
241   tabs_processed = _settings->tabs_processed;
242 
243   // Copy the various values from the _settings instance
244   name_format = _settings->name_format;
245   view_mode = _settings->view_mode;
246   en_desc = false;
247   en_desc_cmp = NULL;
248   en_desc_usr = NULL;
249   if (_settings->en_desc_usr)
250     set_en_desc (_settings->en_desc_usr, true);
251   src_compcom = _settings->src_compcom;
252   dis_compcom = _settings->dis_compcom;
253   threshold_src = _settings->threshold_src;
254   threshold_dis = _settings->threshold_dis;
255   src_visible = _settings->src_visible;
256   srcmetric_visible = _settings->srcmetric_visible;
257   hex_visible = _settings->hex_visible;
258   cmpline_visible = _settings->cmpline_visible;
259   funcline_visible = _settings->funcline_visible;
260   tldata = dbe_strdup (_settings->tldata);
261   tlmode = _settings->tlmode;
262   stack_align = _settings->stack_align;
263   stack_depth = _settings->stack_depth;
264   limit = _settings->limit;
265   print_mode = _settings->print_mode;
266   print_delim = _settings->print_delim;
267   compare_mode = _settings->compare_mode;
268   machinemodel = dbe_strdup (_settings->machinemodel);
269   ignore_no_xhwcprof = _settings->ignore_no_xhwcprof;
270   ignore_fs_warn = _settings->ignore_fs_warn;
271 
272   // copy the tab list, too
273   tab_list = new Vector<DispTab*>;
274   DispTab *dsptab;
275 
276   Vec_loop (DispTab*, _settings->tab_list, index, dsptab)
277   {
278     DispTab *ntab;
279     ntab = new DispTab (dsptab->type, dsptab->order, dsptab->visible, dsptab->cmdtoken);
280     ntab->setAvailability (dsptab->available);
281     tab_list->append (ntab);
282   }
283 
284   // construct the master list of memory tabs & copy order
285   index = _settings->mem_tab_state->size ();
286   mem_tab_state = new Vector<bool>(index);
287   mem_tab_order = new Vector<int>(index);
288   for (int i = 0; i < index; i++)
289     {
290       mem_tab_state->append (false);
291       mem_tab_order->append (_settings->mem_tab_order->fetch (i));
292     }
293 
294   // construct the master list of index tabs & copy order
295   index = _settings->indx_tab_state->size ();
296   indx_tab_state = new Vector<bool>(index);
297   indx_tab_order = new Vector<int>(index);
298   for (int i = 0; i < index; i++)
299     indx_tab_order->append (_settings->indx_tab_order->fetch (i));
300   set_IndxTabState (_settings->indx_tab_state);
301 }
302 
~Settings()303 Settings::~Settings ()
304 {
305   for (int i = 0; i < pathmaps->size (); ++i)
306     {
307       pathmap_t *pmap = pathmaps->fetch (i);
308       free (pmap->old_prefix);
309       free (pmap->new_prefix);
310       delete pmap;
311     }
312   delete pathmaps;
313 
314   for (int i = 0; i < lo_expands->size (); ++i)
315     {
316       lo_expand_t *lo_ex = lo_expands->fetch (i);
317       free (lo_ex->libname);
318       delete lo_ex;
319     }
320   delete lo_expands;
321 
322   tab_list->destroy ();
323   delete tab_list;
324   delete indx_tab_state;
325   delete indx_tab_order;
326   delete mem_tab_state;
327   delete mem_tab_order;
328 
329   free (str_vmode);
330   free (str_en_desc);
331   free (str_datamode);
332   free (str_scompcom);
333   free (str_sthresh);
334   free (str_dcompcom);
335   free (str_dthresh);
336   free (str_dmetrics);
337   free (str_dsort);
338   free (str_tlmode);
339   free (str_tldata);
340   free (str_tabs);
341   free (str_rtabs);
342   free (str_search_path);
343   free (str_name_format);
344   free (str_limit);
345   free (str_compare);
346   free (str_printmode);
347   free (preload_libdirs);
348   free (tldata);
349   free (en_desc_usr);
350   if (en_desc_cmp)
351     {
352       regfree (en_desc_cmp);
353       delete en_desc_cmp;
354     }
355 }
356 
357 /**
358  * Read .er.rc file from the specified location
359  * @param path
360  * @return
361  */
362 char *
read_rc(char * path)363 Settings::read_rc (char *path)
364 {
365   StringBuilder sb;
366   Emsgqueue *commentq = new Emsgqueue (NTXT ("setting_commentq"));
367 
368   // Check file name
369   if (NULL == path)
370     return dbe_strdup (GTXT ("Error: empty file name"));
371   bool override = true;
372   set_rc (path, true, commentq, override);
373   Emsg *msg = commentq->fetch ();
374   while (msg != NULL)
375     {
376       char *str = msg->get_msg ();
377       sb.append (str);
378       msg = msg->next;
379     }
380   return sb.toString ();
381 }
382 
383 void
read_rc(bool ipc_or_rdt_mode)384 Settings::read_rc (bool ipc_or_rdt_mode)
385 {
386   bool override = false;
387 
388   // Read file from the current working directory
389   char *rc_path = realpath (NTXT ("./.gprofng.rc"), NULL);
390   if (rc_path)
391     set_rc (rc_path, true, app->get_comments_queue (), override, ipc_or_rdt_mode);
392 
393   // Read file from the user's home directory
394   char *home = getenv (NTXT ("HOME"));
395   if (home)
396     {
397       char *strbuf = dbe_sprintf (NTXT ("%s/.gprofng.rc"), home);
398       char *home_rc_path = realpath (strbuf, NULL);
399       if (home_rc_path)
400 	{
401 	  if (rc_path == NULL || strcmp (rc_path, home_rc_path) != 0)
402 	    set_rc (home_rc_path, true, app->get_comments_queue (), override, ipc_or_rdt_mode);
403 	  free (home_rc_path);
404 	}
405       free (strbuf);
406     }
407   free (rc_path);
408 
409   // Read system-wide file
410   const char *sysconfdir = getenv("GPROFNG_SYSCONFDIR");
411   if (sysconfdir == NULL)
412     sysconfdir = SYSCONFDIR;
413   rc_path = dbe_sprintf (NTXT ("%s/gprofng.rc"), sysconfdir);
414   if (access (rc_path, R_OK | F_OK) != 0)
415     {
416       StringBuilder sb;
417       sb.sprintf (GTXT ("Warning: Default gprofng.rc file (%s) missing; configuration error "), rc_path);
418       Emsg *m = new Emsg (CMSG_COMMENT, sb);
419       app->get_comments_queue ()->append (m);
420     }
421   else
422     set_rc (rc_path, false, app->get_comments_queue (), override);
423   free (rc_path);
424   is_loexpand_default = true;
425   if (str_printmode == NULL)
426     {
427       // only if there's none set
428       print_mode = PM_TEXT;
429       str_printmode = dbe_strdup (NTXT ("text"));
430     }
431 }
432 
433 
434 //  Handle various settings from reading the name .rc file
435 //	This function is called for each .rc file read, and, for
436 //	some settings, it accumulates the strings from the files.
437 //	For others, it accepts the first appearance for a setting in a
438 //	.rc file, and ignores subsequent appearances from other files.
439 //  Error messages are appended to the Emsgqueue specified by the caller
440 
441 #define MAXARGS 20
442 
443 void
set_rc(const char * path,bool msg,Emsgqueue * commentq,bool override,bool ipc_or_rdt_mode)444 Settings::set_rc (const char *path, bool msg, Emsgqueue *commentq,
445 		  bool override, bool ipc_or_rdt_mode)
446 {
447   CmdType cmd_type;
448   int arg_count, cparam;
449   char *cmd, *end_cmd, *strbuf;
450   char *arglist[MAXARGS];
451   StringBuilder sb;
452 
453   FILE *fptr = fopen (path, NTXT ("r"));
454   if (fptr == NULL)
455     return;
456 
457   if (msg)
458     {
459       sb.sprintf (GTXT ("Processed %s for default settings"), path);
460       Emsg *m = new Emsg (CMSG_COMMENT, sb);
461       commentq->append (m);
462     }
463   int line_no = 0;
464   end_cmd = NULL;
465   while (!feof (fptr))
466     {
467       char *script = read_line (fptr);
468       if (script == NULL)
469 	continue;
470       line_no++;
471       strtok (script, NTXT ("\n"));
472 
473       // extract the command
474       cmd = strtok (script, NTXT (" \t"));
475       if (cmd == NULL || *cmd == '#' || *cmd == '\n')
476 	{
477 	  free (script);
478 	  continue;
479 	}
480       char *remainder = strtok (NULL, NTXT ("\n"));
481       // now extract the arguments
482       int nargs = 0;
483       for (;;)
484 	{
485 	  if (nargs >= MAXARGS)
486 	    {
487 	      if (!msg)
488 		{
489 		  msg = true; // suppress repeats of header
490 		  Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
491 		  commentq->append (m);
492 		}
493 	      sb.sprintf (GTXT ("Warning: more than %d arguments to %s command, line %d\n"),
494 			  MAXARGS, cmd, line_no);
495 	      Emsg *m = new Emsg (CMSG_COMMENT, sb);
496 	      commentq->append (m);
497 	      break;
498 	    }
499 
500 	  char *nextarg = strtok (remainder, NTXT ("\n"));
501 	  if (nextarg == NULL || *nextarg == '#')
502 	    break;
503 	  arglist[nargs++] = parse_qstring (nextarg, &end_cmd);
504 	  remainder = end_cmd;
505 	  if (remainder == NULL)
506 	    break;
507 	  // skip any blanks or tabs to get to next argument
508 	  while (*remainder == ' ' || *remainder == '\t')
509 	    remainder++;
510 	}
511       cmd_type = Command::get_command (cmd, arg_count, cparam);
512       // check for extra arguments
513       if ((cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF) && (nargs > arg_count))
514 	{
515 	  if (!msg)
516 	    {
517 	      msg = true; // suppress repeats of header
518 	      Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
519 	      commentq->append (m);
520 	    }
521 	  sb.sprintf (GTXT ("Warning: extra arguments to %s command, line %d\n"), cmd, line_no);
522 	  Emsg *m = new Emsg (CMSG_COMMENT, sb);
523 	  commentq->append (m);
524 	}
525       if (nargs < arg_count)
526 	{
527 	  if (!msg)
528 	    {
529 	      msg = true; // suppress repeats of header
530 	      Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
531 	      commentq->append (m);
532 	    }
533 	  sb.sprintf (GTXT ("Error: missing arguments to %s command, line %d\n"),
534 		      cmd, line_no);
535 	  Emsg *m = new Emsg (CMSG_COMMENT, sb);
536 	  commentq->append (m);
537 
538 	  // ignore this command
539 	  free (script);
540 	  continue;
541 	}
542       if (ipc_or_rdt_mode && (cmd_type != ADDPATH) && (cmd_type != PATHMAP))
543 	{
544 	  free (script);
545 	  continue;
546 	}
547       switch (cmd_type)
548 	{
549 	case SCOMPCOM:
550 	  if (!str_scompcom || override)
551 	    {
552 	      str_scompcom = dbe_strdup (arglist[0]);
553 	      proc_compcom (arglist[0], true, true);
554 	    }
555 	  break;
556 	case STHRESH:
557 	  if (!str_sthresh || override)
558 	    {
559 	      str_sthresh = dbe_strdup (arglist[0]);
560 	      proc_thresh (arglist[0], true, true);
561 	      break;
562 	    }
563 	  break;
564 	case DCOMPCOM:
565 	  if (!str_dcompcom || override)
566 	    {
567 	      str_dcompcom = dbe_strdup (arglist[0]);
568 	      proc_compcom (arglist[0], false, true);
569 	    }
570 	  break;
571 	case COMPCOM:
572 	  // process as if it were for both source and disassembly
573 	  //	note that if it is set, subsequent SCOMPCOM and DCOMPCOM
574 	  //	will be ignored
575 	  if (!str_scompcom || override)
576 	    {
577 	      str_scompcom = dbe_strdup (arglist[0]);
578 	      proc_compcom (arglist[0], true, true);
579 	    }
580 	  if (!str_dcompcom || override)
581 	    {
582 	      str_dcompcom = dbe_strdup (arglist[0]);
583 	      proc_compcom (arglist[0], false, true);
584 	    }
585 	  break;
586 	case DTHRESH:
587 	  if (!str_dthresh || override)
588 	    {
589 	      str_dthresh = dbe_strdup (arglist[0]);
590 	      proc_thresh (arglist[0], false, true);
591 	    }
592 	  break;
593 	case DMETRICS:
594 	  // append new settings to old, if necessary
595 	  if (str_dmetrics)
596 	    {
597 	      char *name = strstr (str_dmetrics, ":name");
598 	      if (name == NULL)
599 		strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
600 	      else
601 		{
602 		  char * next = strstr (name + 1, ":");
603 		  if (next == NULL)
604 		    {
605 		      name[0] = '\0';
606 		      strbuf = dbe_sprintf ("%s:%s:name", str_dmetrics, arglist[0]);
607 		    }
608 		  else
609 		    strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
610 		}
611 	      free (str_dmetrics);
612 	      str_dmetrics = strbuf;
613 	    }
614 	  else
615 	    str_dmetrics = dbe_strdup (arglist[0]);
616 	  break;
617 	case DSORT:
618 	  // append new settings to old, if necessary
619 	  if (str_dsort)
620 	    {
621 	      strbuf = dbe_sprintf (NTXT ("%s:%s"), str_dsort, arglist[0]);
622 	      free (str_dsort);
623 	      str_dsort = strbuf;
624 	    }
625 	  else
626 	    str_dsort = dbe_strdup (arglist[0]);
627 	  break;
628 	case TLMODE:
629 	  if (!str_tlmode || override)
630 	    {
631 	      str_tlmode = dbe_strdup (arglist[0]);
632 	      proc_tlmode (arglist[0], true);
633 	    }
634 	  break;
635 	case TLDATA:
636 	  if (!str_tldata || override)
637 	    {
638 	      str_tldata = dbe_strdup (arglist[0]);
639 	      proc_tldata (arglist[0], true);
640 	    }
641 	  break;
642 	case TABS:
643 	  if (!str_tabs || override)
644 	    // the string is processed later, after all .rc files are read
645 	    str_tabs = dbe_strdup (arglist[0]);
646 	  break;
647 	case RTABS:
648 	  if (!str_rtabs || override)
649 	    // the string is processed later, after all .rc files are read
650 	    str_rtabs = dbe_strdup (arglist[0]);
651 	  break;
652 	case ADDPATH:
653 	  if (str_search_path)
654 	    {
655 	      strbuf = dbe_sprintf (NTXT ("%s:%s"), str_search_path, arglist[0]);
656 	      free (str_search_path);
657 	      str_search_path = strbuf;
658 	    }
659 	  else
660 	    str_search_path = dbe_strdup (arglist[0]);
661 	  break;
662 	case PATHMAP:
663 	  {
664 	    char *err = add_pathmap (pathmaps, arglist[0], arglist[1]);
665 	    free (err);     // XXX error is not reported
666 	    break;
667 	  }
668 	case LIBDIRS:
669 	  if (preload_libdirs == NULL)
670 	    preload_libdirs = dbe_strdup (arglist[0]);
671 	  break;
672 	case NAMEFMT:
673 	  if (name_format == Histable::NA)
674 	    set_name_format (arglist[0]);
675 	  break;
676 	case VIEWMODE:
677 	  if (!str_vmode || override)
678 	    {
679 	      str_vmode = dbe_strdup (arglist[0]);
680 	      set_view_mode (arglist[0], true);
681 	    }
682 	  break;
683 	case EN_DESC:
684 	  if (!str_en_desc || override)
685 	    {
686 	      str_en_desc = dbe_strdup (arglist[0]);
687 	      set_en_desc (arglist[0], true);
688 	    }
689 	  break;
690 	case LIMIT:
691 	  if (!str_limit || override)
692 	    {
693 	      str_limit = dbe_strdup (arglist[0]);
694 	      set_limit (arglist[0], true);
695 	    }
696 	  break;
697 	case PRINTMODE:
698 	  if (!str_printmode || override)
699 	    set_printmode (arglist[0]);
700 	  break;
701 	case COMPARE:
702 	  if (!str_compare || override)
703 	    {
704 	      char *s = arglist[0];
705 	      if (s)
706 		str_compare = dbe_strdup (s);
707 	      else
708 		s = NTXT ("");
709 	      if (strcasecmp (s, NTXT ("OFF")) == 0
710 		  || strcmp (s, NTXT ("0")) == 0)
711 		set_compare_mode (CMP_DISABLE);
712 	      else if (strcasecmp (s, NTXT ("ON")) == 0
713 		       || strcmp (s, NTXT ("1")) == 0)
714 		set_compare_mode (CMP_ENABLE);
715 	      else if (strcasecmp (s, NTXT ("DELTA")) == 0)
716 		set_compare_mode (CMP_DELTA);
717 	      else if (strcasecmp (s, NTXT ("RATIO")) == 0)
718 		set_compare_mode (CMP_RATIO);
719 	      else
720 		{
721 		  sb.sprintf (GTXT ("   .er.rc:%d The argument of 'compare' should be 'on', 'off', 'delta', or 'ratio'"),
722 			      (int) line_no);
723 		  Emsg *m = new Emsg (CMSG_COMMENT, sb);
724 		  commentq->append (m);
725 		}
726 	    }
727 	  break;
728 
729 	case INDXOBJDEF:
730 	  {
731 	    char *ret = dbeSession->indxobj_define (arglist[0], NULL, arglist[1], (nargs >= 3) ? PTXT (arglist[2]) : NULL, (nargs >= 4) ? PTXT (arglist[3]) : NULL);
732 	    if (ret != NULL)
733 	      {
734 		sb.sprintf (GTXT ("   %s: line %d `%s %s %s'\n"),
735 			    ret, line_no, cmd, arglist[0], arglist[1]);
736 		Emsg *m = new Emsg (CMSG_COMMENT, sb);
737 		commentq->append (m);
738 	      }
739 	    break;
740 	  }
741 #ifdef sparc
742 	  //XXX: should be conditional on the experiment ARCH, not dbe ARCH
743 	case IGNORE_NO_XHWCPROF:
744 	  // ignore absence of -xhwcprof info for dataspace profiling
745 	  set_ignore_no_xhwcprof (true);
746 	  break;
747 #endif // sparc
748 	case IGNORE_FS_WARN:
749 	  // ignore file system warning in experiments
750 	  set_ignore_fs_warn (true);
751 	  break;
752 	case OBJECT_SHOW:
753 	  // Add the named libraries to the lib_expands array
754 	  set_libexpand (arglist[0], LIBEX_SHOW, true);
755 	  break;
756 	case OBJECT_HIDE:
757 	  // Add the named libraries to the lib_expands array
758 	  set_libexpand (arglist[0], LIBEX_HIDE, true);
759 	  break;
760 	case OBJECT_API:
761 	  // Add the named libraries to the lib_expands array
762 	  set_libexpand (arglist[0], LIBEX_API, true);
763 	  break;
764 	case COMMENT:
765 	  // ignore the line
766 	  break;
767 	default:
768 	  {
769 	    // unexpected command in an rc file
770 	    if (!msg)
771 	      {
772 		// if quiet, can remain so no longer
773 		msg = true;
774 		Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
775 		commentq->append (m);
776 	      }
777 	    sb.sprintf (GTXT ("   Unrecognized .gprofng.rc command on line %d: `%.64s'"),
778 			line_no, cmd);
779 	    Emsg *m = new Emsg (CMSG_COMMENT, sb);
780 	    commentq->append (m);
781 	    break;
782 	  }
783 	}
784       free (script);
785     }
786   fclose (fptr);
787 }
788 
789 Cmd_status
set_view_mode(char * arg,bool rc)790 Settings::set_view_mode (char *arg, bool rc)
791 {
792   if (!strcasecmp (arg, NTXT ("user")))
793     view_mode = VMODE_USER;
794   else if (!strcasecmp (arg, NTXT ("expert")))
795     view_mode = VMODE_EXPERT;
796   else if (!strcasecmp (arg, NTXT ("machine")))
797     view_mode = VMODE_MACHINE;
798   else if (!rc)
799     return CMD_BAD_ARG;
800   return CMD_OK;
801 }
802 
803 Cmd_status
set_en_desc(char * arg,bool rc)804 Settings::set_en_desc (char *arg, bool rc)
805 {
806   regex_t *regex_desc = NULL;
807 
808   // cases below should be similar to Coll_Ctrl::set_follow_mode() cases
809   if (!strcasecmp (arg, NTXT ("on")))
810     en_desc = true;
811   else if (!strcasecmp (arg, NTXT ("off")))
812     en_desc = false;
813   else if (arg[0] == '=' && arg[1] != 0)
814     {
815       // user has specified a string matching specification
816       int ercode;
817       { // compile regex_desc
818 	char * str = dbe_sprintf (NTXT ("^%s$"), arg + 1);
819 	regex_desc = new regex_t;
820 	memset (regex_desc, 0, sizeof (regex_t));
821 	ercode = regcomp (regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
822 	free (str);
823       }
824       if (ercode)
825 	{
826 	  // syntax error in parsing string
827 	  delete regex_desc;
828 	  if (!rc)
829 	    return CMD_BAD_ARG;
830 	  return CMD_OK;
831 	}
832       en_desc = true;
833     }
834   else
835     {
836       if (!rc)
837 	return CMD_BAD_ARG;
838       return CMD_OK;
839     }
840   free (en_desc_usr);
841   en_desc_usr = dbe_strdup (arg);
842   if (en_desc_cmp)
843     {
844       regfree (en_desc_cmp);
845       delete en_desc_cmp;
846     }
847   en_desc_cmp = regex_desc;
848   return CMD_OK;
849 }
850 
851 // See if a descendant matches either the lineage or the executable name
852 bool
check_en_desc(const char * lineage,const char * targname)853 Settings::check_en_desc (const char *lineage, const char *targname)
854 {
855   bool rc;
856   if (en_desc_cmp == NULL)
857     return en_desc;     // no specification was set, use the binary on/off value
858   if (lineage == NULL)  // user doesn't care about specification
859     return en_desc;     // use the binary on/off specification
860   if (!regexec (en_desc_cmp, lineage, 0, NULL, 0))
861     rc = true;          // this one matches user specification
862   else if (targname == NULL)
863     rc = false;         //a NULL name does not match any expression
864   else if (!regexec (en_desc_cmp, targname, 0, NULL, 0))
865     rc = true;          // this one matches the executable name
866   else
867     rc = false;
868   return rc;
869 }
870 
871 char *
set_limit(char * arg,bool)872 Settings::set_limit (char *arg, bool)
873 {
874   limit = (int) strtol (arg, (char **) NULL, 10);
875   return NULL;
876 }
877 
878 char *
set_printmode(char * arg)879 Settings::set_printmode (char *arg)
880 {
881   if (arg == NULL)
882     return dbe_sprintf (GTXT ("The argument to '%s' must be '%s' or '%s' or a single-character"),
883 			NTXT ("printmode"), NTXT ("text"), NTXT ("html"));
884   if (strlen (arg) == 1)
885     {
886       print_mode = PM_DELIM_SEP_LIST;
887       print_delim = arg[0];
888     }
889   else if (!strcasecmp (arg, NTXT ("text")))
890     print_mode = PM_TEXT;
891   else if (!strcasecmp (arg, NTXT ("html")))
892     print_mode = PM_HTML;
893   else
894     return dbe_sprintf (GTXT ("The argument to '%s' must be '%s' or '%s' or a single-character"),
895 			NTXT ("printmode"), NTXT ("text"), NTXT ("html"));
896   free (str_printmode);
897   str_printmode = dbe_strdup (arg);
898   return NULL;
899 }
900 
901 Cmd_status
proc_compcom(const char * cmd,bool isSrc,bool rc)902 Settings::proc_compcom (const char *cmd, bool isSrc, bool rc)
903 {
904   int ck_compcom_bits, ck_threshold;
905   bool ck_hex_visible = false;
906   bool ck_src_visible = false;
907   bool ck_srcmetric_visible = false;
908   bool got_compcom_bits, got_threshold, got_src_visible, got_srcmetric_visible;
909   bool got_hex_visible, got;
910   int len, i;
911   char *mcmd, *param;
912   int flag, value = 0;
913   Cmd_status status;
914   char buf[BUFSIZ], *list;
915 
916   if (cmd == NULL)
917     return CMD_BAD;
918   ck_compcom_bits = 0;
919   ck_threshold = 0;
920   got_compcom_bits = got_threshold = got_src_visible = false;
921   got_srcmetric_visible = got_hex_visible = false;
922   snprintf (buf, sizeof (buf), NTXT ("%s"), cmd);
923   list = buf;
924   while ((mcmd = strtok (list, NTXT (":"))) != NULL)
925     {
926       list = NULL;
927       // if "all" or "none"
928       if (!strcasecmp (mcmd, Command::ALL_CMD))
929 	{
930 	  got_compcom_bits = true;
931 	  ck_compcom_bits = CCMV_ALL;
932 	  continue;
933 	}
934       else if (!strcasecmp (mcmd, Command::NONE_CMD))
935 	{
936 	  got_compcom_bits = true;
937 	  ck_compcom_bits = 0;
938 	  continue;
939 	}
940 
941       // Find parameter after '='
942       param = strchr (mcmd, '=');
943       if (param)
944 	{
945 	  *param = '\0';
946 	  param++;
947 	}
948       status = CMD_OK;
949       got = false;
950       flag = 0;
951       len = (int) strlen (mcmd);
952       for (i = 0; status == CMD_OK && i < comp_size; i++)
953 	if (!strncasecmp (mcmd, comp_cmd[i], len))
954 	  {
955 	    if (got) // Ambiguous comp_com command
956 	      status = CMD_AMBIGUOUS;
957 	    else
958 	      {
959 		got = true;
960 		flag = comp_vis[i];
961 		// Check argument
962 		if (flag == COMP_THRESHOLD)
963 		  {
964 		    if (param == NULL)
965 		      status = CMD_BAD_ARG;
966 		    else
967 		      {
968 			value = (int) strtol (param, &param, 10);
969 			if (value < 0 || value > 100)
970 			  status = CMD_OUTRANGE;
971 		      }
972 		  }
973 		else if (param != NULL)
974 		  status = CMD_BAD_ARG;
975 	      }
976 	  }
977 
978       // Not valid comp_com command
979       if (!got)
980 	status = CMD_INVALID;
981       if (status != CMD_OK)
982 	{
983 	  if (!rc)
984 	    return status;
985 	  continue;
986 	}
987 
988       // Set bits
989       switch (flag)
990 	{
991 	case COMP_CMPLINE:
992 	  cmpline_visible = true;
993 	  break;
994 	case COMP_FUNCLINE:
995 	  funcline_visible = true;
996 	  break;
997 	case COMP_THRESHOLD:
998 	  got_threshold = true;
999 	  ck_threshold = value;
1000 	  break;
1001 	case COMP_SRC:
1002 	  got_src_visible = true;
1003 	  ck_src_visible = true;
1004 	  break;
1005 	case COMP_SRC_METRIC:
1006 	  got_srcmetric_visible = true;
1007 	  ck_srcmetric_visible = true;
1008 	  got_src_visible = true;
1009 	  ck_src_visible = true;
1010 	  break;
1011 	case COMP_NOSRC:
1012 	  got_src_visible = true;
1013 	  ck_src_visible = false;
1014 	  break;
1015 	case COMP_HEX:
1016 	  got_hex_visible = true;
1017 	  ck_hex_visible = true;
1018 	  break;
1019 	case COMP_NOHEX:
1020 	  got_hex_visible = true;
1021 	  ck_hex_visible = false;
1022 	  break;
1023 	case CCMV_BASIC:
1024 	  got_compcom_bits = true;
1025 	  ck_compcom_bits = CCMV_BASIC;
1026 	  break;
1027 	default:
1028 	  got_compcom_bits = true;
1029 	  ck_compcom_bits |= flag;
1030 	}
1031     }
1032 
1033   // No error, update
1034   if (got_compcom_bits)
1035     {
1036       if (isSrc)
1037 	src_compcom = ck_compcom_bits;
1038       else
1039 	dis_compcom = ck_compcom_bits;
1040     }
1041   if (got_threshold)
1042     {
1043       if (isSrc)
1044 	threshold_src = ck_threshold;
1045       else
1046 	threshold_dis = ck_threshold;
1047     }
1048   if (got_src_visible)
1049       src_visible = ck_src_visible;
1050   if (got_srcmetric_visible)
1051       srcmetric_visible = ck_srcmetric_visible;
1052   if (got_hex_visible)
1053       hex_visible = ck_hex_visible;
1054   return CMD_OK;
1055 }
1056 
1057 // Process a threshold setting
1058 Cmd_status
proc_thresh(char * cmd,bool isSrc,bool rc)1059 Settings::proc_thresh (char *cmd, bool isSrc, bool rc)
1060 {
1061   int value;
1062   if (cmd == NULL)
1063     value = DEFAULT_SRC_DIS_THRESHOLD; // the default
1064   else
1065     value = (int) strtol (cmd, &cmd, 10);
1066   if (value < 0 || value > 100)
1067     {
1068       if (!rc)
1069 	return CMD_OUTRANGE;
1070       value = DEFAULT_SRC_DIS_THRESHOLD;
1071     }
1072   if (isSrc)
1073     threshold_src = value;
1074   else
1075     threshold_dis = value;
1076   return CMD_OK;
1077 }
1078 
1079 // return any error string from processing visibility settings
1080 char *
get_compcom_errstr(Cmd_status status,const char * cmd)1081 Settings::get_compcom_errstr (Cmd_status status, const char *cmd)
1082 {
1083   int i;
1084   StringBuilder sb;
1085   switch (status)
1086     {
1087     case CMD_BAD:
1088       sb.append (GTXT ("No commentary classes has been specified."));
1089       break;
1090     case CMD_AMBIGUOUS:
1091       sb.append (GTXT ("Ambiguous commentary classes: "));
1092       break;
1093     case CMD_BAD_ARG:
1094       sb.append (GTXT ("Invalid argument for commentary classes: "));
1095       break;
1096     case CMD_OUTRANGE:
1097       sb.append (GTXT ("Out of range commentary classes argument: "));
1098       break;
1099     case CMD_INVALID:
1100       sb.append (GTXT ("Invalid commentary classes: "));
1101       break;
1102     case CMD_OK:
1103       break;
1104     }
1105   if (cmd)
1106     sb.append (cmd);
1107   sb.append (GTXT ("\nAvailable commentary classes: "));
1108   for (i = 0; i < comp_size; i++)
1109     {
1110       sb.append (comp_cmd[i]);
1111       if (i == comp_size - 1)
1112 	sb.append (NTXT ("=#\n"));
1113       else
1114 	sb.append (NTXT (":"));
1115     }
1116   return sb.toString ();
1117 }
1118 
1119 // Process a timeline-mode setting
1120 Cmd_status
proc_tlmode(char * cmd,bool rc)1121 Settings::proc_tlmode (char *cmd, bool rc)
1122 {
1123   bool got_tlmode, got_stack_align, got_stack_depth, got;
1124   int ck_tlmode = 0, ck_stack_align = 0, ck_stack_depth = 0;
1125   int len, i;
1126   char *mcmd, *param;
1127   int cmd_id, value = 0;
1128   TLModeSubcommand cmd_type;
1129   Cmd_status status;
1130   char buf[BUFSIZ], *list;
1131   if (cmd == NULL)
1132     return CMD_BAD;
1133   got_tlmode = got_stack_align = got_stack_depth = false;
1134   snprintf (buf, sizeof (buf), NTXT ("%s"), cmd);
1135   list = buf;
1136   while ((mcmd = strtok (list, NTXT (":"))) != NULL)
1137     {
1138       list = NULL;
1139 
1140       // Find parameter after '='
1141       param = strchr (mcmd, '=');
1142       if (param)
1143 	{
1144 	  *param = '\0';
1145 	  param++;
1146 	}
1147       status = CMD_OK;
1148       got = false;
1149       cmd_id = 0;
1150       cmd_type = TLCMD_INVALID;
1151       len = (int) strlen (mcmd);
1152       for (i = 0; status == CMD_OK && i < tlmode_size; i++)
1153 	{
1154 	  if (!strncasecmp (mcmd, tlmode_cmd[i].cmdText, len))
1155 	    {
1156 	      if (got) // Ambiguous timeline mode
1157 		status = CMD_AMBIGUOUS;
1158 	      else
1159 		{
1160 		  got = true;
1161 		  cmd_type = tlmode_cmd[i].cmdType;
1162 		  cmd_id = tlmode_cmd[i].cmdId;
1163 
1164 		  // Check argument
1165 		  if (cmd_type == TLCMD_DEPTH)
1166 		    {
1167 		      if (param == NULL)
1168 			status = CMD_BAD_ARG;
1169 		      else
1170 			{
1171 			  value = (int) strtol (param, &param, 10);
1172 			  if (value <= 0 || value > 256)
1173 			    status = CMD_OUTRANGE;
1174 			}
1175 		    }
1176 		  else if (param != NULL)
1177 		    status = CMD_BAD_ARG;
1178 		}
1179 	    }
1180 	}
1181 
1182       // Not valid timeline mode
1183       if (!got)
1184 	status = CMD_INVALID;
1185       if (status != CMD_OK)
1186 	{
1187 	  if (!rc)
1188 	    return status;
1189 	  continue;
1190 	}
1191 
1192       // Set bits
1193       switch (cmd_type)
1194 	{
1195 	case TLCMD_ENTITY_MODE:
1196 	  got_tlmode = true;
1197 	  ck_tlmode = cmd_id;
1198 	  break;
1199 	case TLCMD_ALIGN:
1200 	  got_stack_align = true;
1201 	  ck_stack_align = cmd_id;
1202 	  break;
1203 	case TLCMD_DEPTH:
1204 	  got_stack_depth = true;
1205 	  ck_stack_depth = value;
1206 	  break;
1207 	default:
1208 	  break;
1209 	}
1210     }
1211 
1212   // No error, update
1213   if (got_tlmode)
1214     tlmode = ck_tlmode;
1215   if (got_stack_align)
1216     stack_align = ck_stack_align;
1217   if (got_stack_depth)
1218     stack_depth = ck_stack_depth;
1219   return CMD_OK;
1220 }
1221 
1222 // Process timeline data specification
1223 Cmd_status
proc_tldata(const char * cmd,bool)1224 Settings::proc_tldata (const char *cmd, bool /* if true, ignore any error */)
1225 {
1226   free (tldata);
1227   tldata = dbe_strdup (cmd); // let GUI parse it
1228   return CMD_OK;
1229 }
1230 
1231 void
set_tldata(const char * _tldata_str)1232 Settings::set_tldata (const char* _tldata_str)
1233 {
1234   free (tldata);
1235   tldata = dbe_strdup (_tldata_str);
1236 }
1237 
1238 char*
get_tldata()1239 Settings::get_tldata ()
1240 {
1241   return dbe_strdup (tldata);
1242 }
1243 
1244 Cmd_status
set_name_format(char * arg)1245 Settings::set_name_format (char *arg)
1246 {
1247   char *colon = strchr (arg, ':');
1248   size_t arg_len = (colon) ? (colon - arg) : strlen (arg);
1249   Histable::NameFormat fname_fmt = Histable::NA;
1250   if (!strncasecmp (arg, NTXT ("long"), arg_len))
1251     fname_fmt = Histable::LONG;
1252   else if (!strncasecmp (arg, NTXT ("short"), arg_len))
1253     fname_fmt = Histable::SHORT;
1254   else if (!strncasecmp (arg, NTXT ("mangled"), arg_len))
1255     fname_fmt = Histable::MANGLED;
1256   else
1257     return CMD_BAD_ARG;
1258 
1259   bool soname_fmt = false;
1260   if (colon)
1261     {
1262       colon++;
1263       if (!strcasecmp (colon, NTXT ("soname")))
1264 	soname_fmt = true;
1265       else if (!strcasecmp (colon, NTXT ("nosoname")))
1266 	soname_fmt = false;
1267       else
1268 	return CMD_BAD_ARG;
1269     }
1270   name_format = Histable::make_fmt (fname_fmt, soname_fmt);
1271   return CMD_OK;
1272 }
1273 
1274 void
buildMasterTabList()1275 Settings::buildMasterTabList ()
1276 {
1277   tab_list = new Vector<DispTab*>;
1278   int i = -1;
1279 
1280   // Add tabs for all the known reports
1281   tab_list->append (new DispTab (DSP_DEADLOCKS, i, false, DEADLOCK_EVNTS));
1282   tab_list->append (new DispTab (DSP_FUNCTION, i, false, FUNCS));
1283   tab_list->append (new DispTab (DSP_TIMELINE, i, false, TIMELINE));
1284   tab_list->append (new DispTab (DSP_CALLTREE, i, false, CALLTREE));
1285   tab_list->append (new DispTab (DSP_CALLFLAME, i, false, CALLFLAME));
1286   tab_list->append (new DispTab (DSP_DUALSOURCE, i, false, DUALSOURCE));
1287   tab_list->append (new DispTab (DSP_SOURCE_DISASM, i, false, SOURCEDISAM));
1288   tab_list->append (new DispTab (DSP_SOURCE, i, false, SOURCE));
1289   tab_list->append (new DispTab (DSP_LINE, i, false, HOTLINES));
1290   tab_list->append (new DispTab (DSP_DISASM, i, false, DISASM));
1291   tab_list->append (new DispTab (DSP_PC, i, false, HOTPCS));
1292   tab_list->append (new DispTab (DSP_LEAKLIST, i, false, LEAKS));
1293   tab_list->append (new DispTab (DSP_IOACTIVITY, i, false, IOACTIVITY));
1294   tab_list->append (new DispTab (DSP_HEAPCALLSTACK, i, false, HEAP));
1295   tab_list->append (new DispTab (DSP_IFREQ, i, false, IFREQ));
1296   tab_list->append (new DispTab (DSP_CALLER, i, false, GPROF));
1297   tab_list->append (new DispTab (DSP_STATIS, i, false, STATISTICS));
1298   tab_list->append (new DispTab (DSP_EXP, i, false, HEADER));
1299 }
1300 
1301 // Update tablist based on data availability
1302 void
updateTabAvailability()1303 Settings::updateTabAvailability ()
1304 {
1305   int index;
1306   DispTab *dsptab;
1307 
1308   Vec_loop (DispTab*, tab_list, index, dsptab)
1309   {
1310     if (dsptab->type == DSP_DATAOBJ)
1311       dsptab->setAvailability (dbeSession->is_datamode_available ());
1312     else if (dsptab->type == DSP_DLAYOUT)
1313       dsptab->setAvailability (dbeSession->is_datamode_available ());
1314     else if (dsptab->type == DSP_LEAKLIST)
1315       dsptab->setAvailability (false);
1316     else if (dsptab->type == DSP_IOACTIVITY)
1317       dsptab->setAvailability (dbeSession->is_iodata_available ());
1318     else if (dsptab->type == DSP_HEAPCALLSTACK)
1319       dsptab->setAvailability (dbeSession->is_heapdata_available ());
1320     else if (dsptab->type == DSP_TIMELINE)
1321       dsptab->setAvailability (dbeSession->is_timeline_available ());
1322     else if (dsptab->type == DSP_IFREQ)
1323       dsptab->setAvailability (dbeSession->is_ifreq_available ());
1324     else if (dsptab->type == DSP_RACES)
1325       dsptab->setAvailability (dbeSession->is_racelist_available ());
1326     else if (dsptab->type == DSP_DEADLOCKS)
1327       dsptab->setAvailability (dbeSession->is_deadlocklist_available ());
1328     else if (dsptab->type == DSP_DUALSOURCE)
1329       dsptab->setAvailability (dbeSession->is_racelist_available ()
1330 			       || dbeSession->is_deadlocklist_available ());
1331   }
1332 }
1333 
1334 // Process a tab setting
1335 Cmd_status
proc_tabs(bool _rdtMode)1336 Settings::proc_tabs (bool _rdtMode)
1337 {
1338   int arg_cnt, cparam;
1339   int count = 0;
1340   int index;
1341   DispTab *dsptab;
1342   char *cmd;
1343   if (tabs_processed == true)
1344     return CMD_OK;
1345   tabs_processed = true;
1346   if (_rdtMode == true)
1347     {
1348       if (str_rtabs == NULL)
1349 	str_rtabs = strdup ("header");
1350       cmd = str_rtabs;
1351     }
1352   else
1353     {
1354       if (str_tabs == NULL)
1355 	str_tabs = strdup ("header");
1356       cmd = str_tabs;
1357     }
1358   if (strcmp (cmd, NTXT ("none")) == 0)
1359     return CMD_OK;
1360   Vector <char *> *tokens = split_str (cmd, ':');
1361   for (long j = 0, sz = VecSize (tokens); j < sz; j++)
1362     {
1363       char *tabname = tokens->get (j);
1364       // search for this tab command token
1365       CmdType c = Command::get_command (tabname, arg_cnt, cparam);
1366       if (c == INDXOBJ)
1367 	{
1368 	  // set the bit for this subtype
1369 	  indx_tab_state->store (cparam, true);
1370 	  indx_tab_order->store (cparam, count++);
1371 	}
1372       else
1373 	{
1374 	  // search for this tab type in the regular tabs
1375 	  Vec_loop (DispTab*, tab_list, index, dsptab)
1376 	  {
1377 	    if (dsptab->cmdtoken == c)
1378 	      {
1379 		dsptab->visible = true;
1380 		dsptab->order = count++;
1381 		break;
1382 	      }
1383 	  }
1384 	}
1385       free (tabname);
1386     }
1387   delete tokens;
1388   return CMD_OK;
1389 }
1390 
1391 void
set_MemTabState(Vector<bool> * selected)1392 Settings::set_MemTabState (Vector<bool>*selected)
1393 {
1394   if (selected->size () == 0)
1395     return;
1396   for (int j = 0; j < mem_tab_state->size (); j++)
1397     mem_tab_state->store (j, selected->fetch (j));
1398 }
1399 
1400 // define a new memory object type
1401 
1402 void
mobj_define(MemObjType_t *,bool state)1403 Settings::mobj_define (MemObjType_t */* mobj */, bool state)
1404 {
1405   if (mem_tab_state->size () == 0)
1406     state = true;
1407   mem_tab_state->append (state);
1408   mem_tab_order->append (-1);
1409 }
1410 
1411 void
set_IndxTabState(Vector<bool> * selected)1412 Settings::set_IndxTabState (Vector<bool>*selected)
1413 {
1414   for (int j = 0; j < selected->size (); j++)
1415     indx_tab_state->store (j, selected->fetch (j));
1416 }
1417 
1418 // define a new index object type
1419 void
indxobj_define(int type,bool state)1420 Settings::indxobj_define (int type, bool state)
1421 {
1422   indx_tab_state->store (type, state);
1423   indx_tab_order->store (type, -1);
1424 }
1425 
1426 void
set_pathmaps(Vector<pathmap_t * > * newPathMap)1427 Settings::set_pathmaps (Vector<pathmap_t*> *newPathMap)
1428 {
1429   if (pathmaps)
1430     {
1431       pathmaps->destroy ();
1432       delete pathmaps;
1433     }
1434   pathmaps = newPathMap;
1435 }
1436 
1437 static char *
get_canonical_name(const char * fname)1438 get_canonical_name (const char *fname)
1439 {
1440   char *nm = dbe_strdup (fname);
1441   for (size_t len = strlen (nm); (len > 0) && (nm[len - 1] == '/'); len--)
1442     nm[len - 1] = 0;
1443   return nm;
1444 }
1445 
1446 char *
add_pathmap(Vector<pathmap_t * > * v,const char * from,const char * to)1447 Settings::add_pathmap (Vector<pathmap_t*> *v, const char *from, const char *to)
1448 {
1449   // Check for errors
1450   if (from == NULL || to == NULL)
1451     return dbe_strdup (GTXT ("Pathmap can have neither from nor to as NULL\n"));
1452   if (strcmp (from, to) == 0)
1453     return dbe_strdup (GTXT ("Pathmap from must differ from to\n"));
1454   char *old_prefix = get_canonical_name (from);
1455   char *new_prefix = get_canonical_name (to);
1456 
1457   // Check the pathmap list
1458   for (int i = 0, sz = v->size (); i < sz; i++)
1459     {
1460       pathmap_t *pmp = v->get (i);
1461       if ((strcmp (pmp->old_prefix, old_prefix) == 0) &&(strcmp (pmp->new_prefix, new_prefix) == 0))
1462 	{
1463 	  char *s = dbe_sprintf (GTXT ("Pathmap from `%s' to `%s' already exists\n"), old_prefix, new_prefix);
1464 	  free (old_prefix);
1465 	  free (new_prefix);
1466 	  return s;
1467 	}
1468     }
1469   // construct a map for this pair
1470   pathmap_t *thismap = new pathmap_t;
1471   thismap->old_prefix = old_prefix;
1472   thismap->new_prefix = new_prefix;
1473   v->append (thismap);
1474   return NULL;
1475 }
1476 
1477 // Set all shared object expands back to .rc file defaults,
1478 //	as stored in the DbeSession Settings
1479 bool
set_libdefaults()1480 Settings::set_libdefaults ()
1481 {
1482   // See if this is unchanged
1483   if (is_loexpand_default == true)
1484     return false; // no change
1485 
1486   // replicate the DbeSession's lo_expand vector and default settings
1487   lo_expand_t *this_lo_ex;
1488   lo_expand_t *new_lo_ex;
1489   int index;
1490   lo_expand_default = dbeSession->get_settings ()->lo_expand_default;
1491   lo_expands = new Vector<lo_expand_t*>;
1492   Vec_loop (lo_expand_t*, dbeSession->get_settings ()->lo_expands, index, this_lo_ex)
1493   {
1494     new_lo_ex = new lo_expand_t;
1495     new_lo_ex->libname = dbe_strdup (this_lo_ex->libname);
1496     new_lo_ex->expand = this_lo_ex->expand;
1497     lo_expands->append (new_lo_ex);
1498   }
1499   is_loexpand_default = true;
1500   return true;
1501 }
1502 
1503 bool
set_libexpand(char * cov,enum LibExpand expand,bool rc)1504 Settings::set_libexpand (char *cov, enum LibExpand expand, bool rc)
1505 {
1506   int index;
1507   lo_expand_t *loe;
1508   bool change = false;
1509   if (cov == NULL || !strcasecmp (cov, Command::ALL_CMD))
1510     { // set all libraries
1511       // set the default
1512       if (lo_expand_default != expand)
1513 	{
1514 	  lo_expand_default = expand;
1515 	  change = true;
1516 	  is_loexpand_default = false;
1517 	}
1518 
1519       // and force any explicit settings to match, too
1520       Vec_loop (lo_expand_t*, lo_expands, index, loe)
1521       {
1522 	if (loe->expand != expand)
1523 	  {
1524 	    loe->expand = expand;
1525 	    change = true;
1526 	    is_loexpand_default = false;
1527 	  }
1528       }
1529 
1530     }
1531   else
1532     { // parsing coverage
1533       Vector <char *> *tokens = split_str (cov, ',');
1534       for (long j = 0, sz = VecSize (tokens); j < sz; j++)
1535 	{
1536 	  char *lo_name = tokens->get (j);
1537 	  char *newname = get_basename (lo_name);
1538 	  bool found = false;
1539 	  Vec_loop (lo_expand_t*, lo_expands, index, loe)
1540 	  {
1541 	    if (strcmp (loe->libname, newname) == 0)
1542 	      {
1543 		if (loe->expand != expand)
1544 		  {
1545 		    if (rc == false)
1546 		      {
1547 			loe->expand = expand;
1548 			change = true;
1549 			is_loexpand_default = false;
1550 		      }
1551 		  }
1552 		found = true;
1553 		break;
1554 	      }
1555 	  }
1556 
1557 	  if (found == false)
1558 	    {
1559 	      // construct a map for this pair
1560 	      lo_expand_t *thisloe;
1561 	      thisloe = new lo_expand_t;
1562 	      thisloe->libname = dbe_strdup (newname);
1563 	      thisloe->expand = expand;
1564 	      change = true;
1565 	      is_loexpand_default = false;
1566 
1567 	      // add it to the vector
1568 	      lo_expands->append (thisloe);
1569 	    }
1570 	  free (lo_name);
1571 	}
1572       delete tokens;
1573     }
1574   return change;
1575 }
1576 
1577 enum LibExpand
get_lo_setting(char * name)1578 Settings::get_lo_setting (char *name)
1579 {
1580   int index;
1581   lo_expand_t *loe;
1582   char *lo_name = get_basename (name);
1583   Vec_loop (lo_expand_t*, lo_expands, index, loe)
1584   {
1585     if (strcmp (loe->libname, lo_name) == 0)
1586       return loe->expand;
1587   }
1588   return lo_expand_default;
1589 }
1590