]> Git Repo - binutils.git/blob - gprofng/src/Settings.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / Settings.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 <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
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
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
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 *
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
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
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
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
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
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 *
872 Settings::set_limit (char *arg, bool)
873 {
874   limit = (int) strtol (arg, (char **) NULL, 10);
875   return NULL;
876 }
877
878 char *
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
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
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 *
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
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
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
1232 Settings::set_tldata (const char* _tldata_str)
1233 {
1234   free (tldata);
1235   tldata = dbe_strdup (_tldata_str);
1236 }
1237
1238 char*
1239 Settings::get_tldata ()
1240 {
1241   return dbe_strdup (tldata);
1242 }
1243
1244 Cmd_status
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 && (colon + 1))
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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 }
This page took 0.109755 seconds and 4 git commands to generate.