summaryrefslogtreecommitdiff
path: root/gprofng/src/Settings.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/Settings.cc')
-rw-r--r--gprofng/src/Settings.cc1586
1 files changed, 1586 insertions, 0 deletions
diff --git a/gprofng/src/Settings.cc b/gprofng/src/Settings.cc
new file mode 100644
index 00000000000..965b9174da6
--- /dev/null
+++ b/gprofng/src/Settings.cc
@@ -0,0 +1,1586 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+#include "enums.h"
+#include "Settings.h"
+#include "DbeSession.h"
+#include "Command.h"
+#include "Application.h"
+#include "MemorySpace.h"
+#include "StringBuilder.h"
+#include "Table.h"
+#include "Emsg.h"
+#include "util.h"
+#include "i18n.h"
+
+// Commands for compiler commentary
+static const char *comp_cmd[] = {
+ NTXT ("basic"),
+ NTXT ("version"),
+ NTXT ("warn"),
+ NTXT ("parallel"),
+ NTXT ("query"),
+ NTXT ("loop"),
+ NTXT ("pipe"),
+ NTXT ("inline"),
+ NTXT ("memops"),
+ NTXT ("fe"),
+ NTXT ("codegen"),
+ NTXT ("src"),
+ NTXT ("asrc"),
+ NTXT ("nosrc"),
+ NTXT ("hex"),
+ NTXT ("nohex"),
+ NTXT ("threshold"),
+ NTXT ("cf")
+};
+
+static const int comp_vis[] = {
+ CCMV_BASIC,
+ CCMV_VER,
+ CCMV_WARN,
+ CCMV_PAR,
+ CCMV_QUERY,
+ CCMV_LOOP,
+ CCMV_PIPE,
+ CCMV_INLINE,
+ CCMV_MEMOPS,
+ CCMV_FE,
+ CCMV_CG,
+ COMP_SRC,
+ COMP_SRC_METRIC,
+ COMP_NOSRC,
+ COMP_HEX,
+ COMP_NOHEX,
+ COMP_THRESHOLD,
+ COMP_CMPLINE
+};
+
+const int comp_size = sizeof (comp_cmd) / sizeof (char *);
+
+// Commands for timeline
+typedef enum
+{
+ TLCMD_INVALID,
+ TLCMD_ENTITY_MODE,
+ TLCMD_ALIGN,
+ TLCMD_DEPTH
+} TLModeSubcommand;
+
+typedef struct
+{
+ const char * cmdText;
+ TLModeSubcommand cmdType;
+ int cmdId;
+} TLModeCmd;
+static const TLModeCmd tlmode_cmd[] = {
+ // MODE commands
+ {NTXT ("lwp"), TLCMD_ENTITY_MODE, PROP_LWPID},
+ {NTXT ("thread"), TLCMD_ENTITY_MODE, PROP_THRID},
+ {NTXT ("cpu"), TLCMD_ENTITY_MODE, PROP_CPUID},
+ {NTXT ("experiment"), TLCMD_ENTITY_MODE, PROP_EXPID},
+ // ALIGN commands
+ {NTXT ("root"), TLCMD_ALIGN, TLSTACK_ALIGN_ROOT},
+ {NTXT ("leaf"), TLCMD_ALIGN, TLSTACK_ALIGN_LEAF},
+ // DEPTH commands
+ {NTXT ("depth"), TLCMD_DEPTH, 0 /* don't care */}
+};
+
+static const int tlmode_size = sizeof (tlmode_cmd) / sizeof (TLModeCmd);
+
+// Constructor
+
+Settings::Settings (Application *_app)
+{
+ // Remember the application
+ app = _app;
+
+ // Clear all default strings
+ str_vmode = NULL;
+ str_en_desc = NULL;
+ str_datamode = NULL;
+ str_scompcom = NULL;
+ str_sthresh = NULL;
+ str_dcompcom = NULL;
+ str_dthresh = NULL;
+ str_dmetrics = NULL;
+ str_dsort = NULL;
+ str_tlmode = NULL;
+ str_tldata = NULL;
+ str_tabs = NULL;
+ str_rtabs = NULL;
+ str_search_path = NULL;
+ str_name_format = NULL;
+ str_limit = NULL;
+ str_printmode = NULL;
+ str_compare = NULL;
+ preload_libdirs = NULL;
+ pathmaps = new Vector<pathmap_t*>;
+ lo_expands = new Vector<lo_expand_t*>;
+ lo_expand_default = LIBEX_SHOW;
+ is_loexpand_default = true;
+ tabs_processed = false;
+
+ // set default-default values
+ name_format = Histable::NA;
+ view_mode = VMODE_USER;
+ en_desc = false;
+ en_desc_cmp = NULL;
+ en_desc_usr = NULL;
+ src_compcom = 2147483647;
+ dis_compcom = 2147483647;
+#define DEFAULT_SRC_DIS_THRESHOLD 75
+ threshold_src = DEFAULT_SRC_DIS_THRESHOLD;
+ threshold_dis = DEFAULT_SRC_DIS_THRESHOLD;
+ src_visible = true;
+ srcmetric_visible = false;
+ hex_visible = false;
+ cmpline_visible = true;
+ funcline_visible = true;
+ tldata = NULL;
+ tlmode = 0;
+ stack_align = 0;
+ stack_depth = 0;
+ limit = 0;
+ // print mode is initialized after the .rc files are read
+ print_delim = ',';
+ compare_mode = CMP_DISABLE;
+ machinemodel = NULL;
+ ignore_no_xhwcprof = false;
+ ignore_fs_warn = false;
+
+ // construct the master list of tabs
+ buildMasterTabList ();
+
+ indx_tab_state = new Vector<bool>;
+ indx_tab_order = new Vector<int>;
+ mem_tab_state = new Vector<bool>;
+ mem_tab_order = new Vector<int>;
+
+ // note that the .rc files are not read here, but later
+}
+
+// Constructor for duplicating an existing Settings class
+
+Settings::Settings (Settings * _settings)
+{
+ int index;
+ app = _settings->app;
+
+ // Copy all default strings
+ str_vmode = dbe_strdup (_settings->str_vmode);
+ str_en_desc = dbe_strdup (_settings->str_en_desc);
+ str_datamode = dbe_strdup (_settings->str_datamode);
+ str_scompcom = dbe_strdup (_settings->str_scompcom);
+ str_sthresh = dbe_strdup (_settings->str_sthresh);
+ str_dcompcom = dbe_strdup (_settings->str_dcompcom);
+ str_dthresh = dbe_strdup (_settings->str_dthresh);
+ str_dmetrics = dbe_strdup (_settings->str_dmetrics);
+ str_dsort = dbe_strdup (_settings->str_dsort);
+ str_tlmode = dbe_strdup (_settings->str_tlmode);
+ str_tldata = dbe_strdup (_settings->str_tldata);
+ str_tabs = dbe_strdup (_settings->str_tabs);
+ str_rtabs = dbe_strdup (_settings->str_rtabs);
+ str_search_path = dbe_strdup (_settings->str_search_path);
+ str_name_format = dbe_strdup (_settings->str_name_format);
+ str_limit = dbe_strdup (_settings->str_limit);
+ str_printmode = dbe_strdup (_settings->str_printmode);
+ str_compare = dbe_strdup (_settings->str_compare);
+ preload_libdirs = dbe_strdup (_settings->preload_libdirs);
+
+ // replicate the pathmap vector
+ pathmap_t *thismap;
+ pathmap_t *newmap;
+ pathmaps = new Vector<pathmap_t*>;
+
+ Vec_loop (pathmap_t*, _settings->pathmaps, index, thismap)
+ {
+ newmap = new pathmap_t;
+ newmap->old_prefix = dbe_strdup (thismap->old_prefix);
+ newmap->new_prefix = dbe_strdup (thismap->new_prefix);
+ pathmaps->append (newmap);
+ }
+
+ // replicate the lo_expand vector and default
+ lo_expand_t *this_lo_ex;
+ lo_expand_t *new_lo_ex;
+ lo_expand_default = _settings->lo_expand_default;
+ is_loexpand_default = _settings->is_loexpand_default;
+ lo_expands = new Vector<lo_expand_t*>;
+
+ Vec_loop (lo_expand_t*, _settings->lo_expands, index, this_lo_ex)
+ {
+ new_lo_ex = new lo_expand_t;
+ new_lo_ex->libname = dbe_strdup (this_lo_ex->libname);
+ new_lo_ex->expand = this_lo_ex->expand;
+ lo_expands->append (new_lo_ex);
+ }
+ tabs_processed = _settings->tabs_processed;
+
+ // Copy the various values from the _settings instance
+ name_format = _settings->name_format;
+ view_mode = _settings->view_mode;
+ en_desc = false;
+ en_desc_cmp = NULL;
+ en_desc_usr = NULL;
+ if (_settings->en_desc_usr)
+ set_en_desc (_settings->en_desc_usr, true);
+ src_compcom = _settings->src_compcom;
+ dis_compcom = _settings->dis_compcom;
+ threshold_src = _settings->threshold_src;
+ threshold_dis = _settings->threshold_dis;
+ src_visible = _settings->src_visible;
+ srcmetric_visible = _settings->srcmetric_visible;
+ hex_visible = _settings->hex_visible;
+ cmpline_visible = _settings->cmpline_visible;
+ funcline_visible = _settings->funcline_visible;
+ tldata = dbe_strdup (_settings->tldata);
+ tlmode = _settings->tlmode;
+ stack_align = _settings->stack_align;
+ stack_depth = _settings->stack_depth;
+ limit = _settings->limit;
+ print_mode = _settings->print_mode;
+ print_delim = _settings->print_delim;
+ compare_mode = _settings->compare_mode;
+ machinemodel = dbe_strdup (_settings->machinemodel);
+ ignore_no_xhwcprof = _settings->ignore_no_xhwcprof;
+ ignore_fs_warn = _settings->ignore_fs_warn;
+
+ // copy the tab list, too
+ tab_list = new Vector<DispTab*>;
+ DispTab *dsptab;
+
+ Vec_loop (DispTab*, _settings->tab_list, index, dsptab)
+ {
+ DispTab *ntab;
+ ntab = new DispTab (dsptab->type, dsptab->order, dsptab->visible, dsptab->cmdtoken);
+ ntab->setAvailability (dsptab->available);
+ tab_list->append (ntab);
+ }
+
+ // construct the master list of memory tabs & copy order
+ index = _settings->mem_tab_state->size ();
+ mem_tab_state = new Vector<bool>(index);
+ mem_tab_order = new Vector<int>(index);
+ for (int i = 0; i < index; i++)
+ {
+ mem_tab_state->append (false);
+ mem_tab_order->append (_settings->mem_tab_order->fetch (i));
+ }
+
+ // construct the master list of index tabs & copy order
+ index = _settings->indx_tab_state->size ();
+ indx_tab_state = new Vector<bool>(index);
+ indx_tab_order = new Vector<int>(index);
+ for (int i = 0; i < index; i++)
+ indx_tab_order->append (_settings->indx_tab_order->fetch (i));
+ set_IndxTabState (_settings->indx_tab_state);
+}
+
+Settings::~Settings ()
+{
+ for (int i = 0; i < pathmaps->size (); ++i)
+ {
+ pathmap_t *pmap = pathmaps->fetch (i);
+ free (pmap->old_prefix);
+ free (pmap->new_prefix);
+ delete pmap;
+ }
+ delete pathmaps;
+
+ for (int i = 0; i < lo_expands->size (); ++i)
+ {
+ lo_expand_t *lo_ex = lo_expands->fetch (i);
+ free (lo_ex->libname);
+ delete lo_ex;
+ }
+ delete lo_expands;
+
+ tab_list->destroy ();
+ delete tab_list;
+ delete indx_tab_state;
+ delete indx_tab_order;
+ delete mem_tab_state;
+ delete mem_tab_order;
+
+ free (str_vmode);
+ free (str_en_desc);
+ free (str_datamode);
+ free (str_scompcom);
+ free (str_sthresh);
+ free (str_dcompcom);
+ free (str_dthresh);
+ free (str_dmetrics);
+ free (str_dsort);
+ free (str_tlmode);
+ free (str_tldata);
+ free (str_tabs);
+ free (str_rtabs);
+ free (str_search_path);
+ free (str_name_format);
+ free (str_limit);
+ free (str_compare);
+ free (str_printmode);
+ free (preload_libdirs);
+ free (tldata);
+ free (en_desc_usr);
+ if (en_desc_cmp)
+ {
+ regfree (en_desc_cmp);
+ delete en_desc_cmp;
+ }
+}
+
+/**
+ * Read .er.rc file from the specified location
+ * @param path
+ * @return
+ */
+char *
+Settings::read_rc (char *path)
+{
+ StringBuilder sb;
+ Emsgqueue *commentq = new Emsgqueue (NTXT ("setting_commentq"));
+
+ // Check file name
+ if (NULL == path)
+ return dbe_strdup (GTXT ("Error: empty file name"));
+ bool override = true;
+ set_rc (path, true, commentq, override);
+ Emsg *msg = commentq->fetch ();
+ while (msg != NULL)
+ {
+ char *str = msg->get_msg ();
+ sb.append (str);
+ msg = msg->next;
+ }
+ return sb.toString ();
+}
+
+void
+Settings::read_rc (bool ipc_or_rdt_mode)
+{
+ bool override = false;
+
+ // Read file from the current working directory
+ char *rc_path = realpath (NTXT ("./.gprofng.rc"), NULL);
+ if (rc_path)
+ set_rc (rc_path, true, app->get_comments_queue (), override, ipc_or_rdt_mode);
+
+ // Read file from the user's home directory
+ char *home = getenv (NTXT ("HOME"));
+ if (home)
+ {
+ char *strbuf = dbe_sprintf (NTXT ("%s/.gprofng.rc"), home);
+ char *home_rc_path = realpath (strbuf, NULL);
+ if (home_rc_path)
+ {
+ if (rc_path == NULL || strcmp (rc_path, home_rc_path) != 0)
+ set_rc (home_rc_path, true, app->get_comments_queue (), override, ipc_or_rdt_mode);
+ free (home_rc_path);
+ }
+ free (strbuf);
+ }
+ free (rc_path);
+
+ // Read system-wide file
+ rc_path = dbe_sprintf (NTXT ("%s/../etc/gprofng.rc"), app->get_run_dir ());
+ if (access (rc_path, R_OK | F_OK) != 0)
+ {
+ StringBuilder sb;
+ sb.sprintf (GTXT ("Warning: Default gprofng.rc file (%s) missing; configuration error "), rc_path);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ app->get_comments_queue ()->append (m);
+ }
+ else
+ set_rc (rc_path, false, app->get_comments_queue (), override);
+ free (rc_path);
+ is_loexpand_default = true;
+ if (str_printmode == NULL)
+ {
+ // only if there's none set
+ print_mode = PM_TEXT;
+ str_printmode = dbe_strdup (NTXT ("text"));
+ }
+}
+
+
+// Handle various settings from reading the name .rc file
+// This function is called for each .rc file read, and, for
+// some settings, it accumulates the strings from the files.
+// For others, it accepts the first appearance for a setting in a
+// .rc file, and ignores subsequent appearances from other files.
+// Error messages are appended to the Emsgqueue specified by the caller
+
+#define MAXARGS 20
+
+void
+Settings::set_rc (const char *path, bool msg, Emsgqueue *commentq,
+ bool override, bool ipc_or_rdt_mode)
+{
+ CmdType cmd_type;
+ int arg_count, cparam;
+ char *cmd, *end_cmd, *strbuf;
+ char *arglist[MAXARGS];
+ StringBuilder sb;
+
+ FILE *fptr = fopen (path, NTXT ("r"));
+ if (fptr == NULL)
+ return;
+
+ if (msg)
+ {
+ sb.sprintf (GTXT ("Processed %s for default settings"), path);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ }
+ int line_no = 0;
+ end_cmd = NULL;
+ while (!feof (fptr))
+ {
+ char *script = read_line (fptr);
+ if (script == NULL)
+ continue;
+ line_no++;
+ strtok (script, NTXT ("\n"));
+
+ // extract the command
+ cmd = strtok (script, NTXT (" \t"));
+ if (cmd == NULL || *cmd == '#' || *cmd == '\n')
+ {
+ free (script);
+ continue;
+ }
+ char *remainder = strtok (NULL, NTXT ("\n"));
+ // now extract the arguments
+ int nargs = 0;
+ for (;;)
+ {
+ if (nargs >= MAXARGS)
+ {
+ if (!msg)
+ {
+ msg = true; // suppress repeats of header
+ Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
+ commentq->append (m);
+ }
+ sb.sprintf (GTXT ("Warning: more than %d arguments to %s command, line %d\n"),
+ MAXARGS, cmd, line_no);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ break;
+ }
+
+ char *nextarg = strtok (remainder, NTXT ("\n"));
+ if (nextarg == NULL || *nextarg == '#')
+ break;
+ arglist[nargs++] = parse_qstring (nextarg, &end_cmd);
+ remainder = end_cmd;
+ if (remainder == NULL)
+ break;
+ // skip any blanks or tabs to get to next argument
+ while (*remainder == ' ' || *remainder == '\t')
+ remainder++;
+ }
+ cmd_type = Command::get_command (cmd, arg_count, cparam);
+ // check for extra arguments
+ if ((cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF) && (nargs > arg_count))
+ {
+ if (!msg)
+ {
+ msg = true; // suppress repeats of header
+ Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
+ commentq->append (m);
+ }
+ sb.sprintf (GTXT ("Warning: extra arguments to %s command, line %d\n"), cmd, line_no);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ }
+ if (nargs < arg_count)
+ {
+ if (!msg)
+ {
+ msg = true; // suppress repeats of header
+ Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
+ commentq->append (m);
+ }
+ sb.sprintf (GTXT ("Error: missing arguments to %s command, line %d\n"),
+ cmd, line_no);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+
+ // ignore this command
+ free (script);
+ continue;
+ }
+ if (ipc_or_rdt_mode && (cmd_type != ADDPATH) && (cmd_type != PATHMAP))
+ {
+ free (script);
+ continue;
+ }
+ switch (cmd_type)
+ {
+ case SCOMPCOM:
+ if (!str_scompcom || override)
+ {
+ str_scompcom = dbe_strdup (arglist[0]);
+ proc_compcom (arglist[0], true, true);
+ }
+ break;
+ case STHRESH:
+ if (!str_sthresh || override)
+ {
+ str_sthresh = dbe_strdup (arglist[0]);
+ proc_thresh (arglist[0], true, true);
+ break;
+ }
+ break;
+ case DCOMPCOM:
+ if (!str_dcompcom || override)
+ {
+ str_dcompcom = dbe_strdup (arglist[0]);
+ proc_compcom (arglist[0], false, true);
+ }
+ break;
+ case COMPCOM:
+ // process as if it were for both source and disassembly
+ // note that if it is set, subsequent SCOMPCOM and DCOMPCOM
+ // will be ignored
+ if (!str_scompcom || override)
+ {
+ str_scompcom = dbe_strdup (arglist[0]);
+ proc_compcom (arglist[0], true, true);
+ }
+ if (!str_dcompcom || override)
+ {
+ str_dcompcom = dbe_strdup (arglist[0]);
+ proc_compcom (arglist[0], false, true);
+ }
+ break;
+ case DTHRESH:
+ if (!str_dthresh || override)
+ {
+ str_dthresh = dbe_strdup (arglist[0]);
+ proc_thresh (arglist[0], false, true);
+ }
+ break;
+ case DMETRICS:
+ // append new settings to old, if necessary
+ if (str_dmetrics)
+ {
+ char *name = strstr (str_dmetrics, ":name");
+ if (name == NULL)
+ strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
+ else
+ {
+ char * next = strstr (name + 1, ":");
+ if (next == NULL)
+ {
+ name[0] = '\0';
+ strbuf = dbe_sprintf ("%s:%s:name", str_dmetrics, arglist[0]);
+ }
+ else
+ strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
+ }
+ free (str_dmetrics);
+ str_dmetrics = strbuf;
+ }
+ else
+ str_dmetrics = dbe_strdup (arglist[0]);
+ break;
+ case DSORT:
+ // append new settings to old, if necessary
+ if (str_dsort)
+ {
+ strbuf = dbe_sprintf (NTXT ("%s:%s"), str_dsort, arglist[0]);
+ free (str_dsort);
+ str_dsort = strbuf;
+ }
+ else
+ str_dsort = dbe_strdup (arglist[0]);
+ break;
+ case TLMODE:
+ if (!str_tlmode || override)
+ {
+ str_tlmode = dbe_strdup (arglist[0]);
+ proc_tlmode (arglist[0], true);
+ }
+ break;
+ case TLDATA:
+ if (!str_tldata || override)
+ {
+ str_tldata = dbe_strdup (arglist[0]);
+ proc_tldata (arglist[0], true);
+ }
+ break;
+ case TABS:
+ if (!str_tabs || override)
+ // the string is processed later, after all .rc files are read
+ str_tabs = dbe_strdup (arglist[0]);
+ break;
+ case RTABS:
+ if (!str_rtabs || override)
+ // the string is processed later, after all .rc files are read
+ str_rtabs = dbe_strdup (arglist[0]);
+ break;
+ case ADDPATH:
+ if (str_search_path)
+ {
+ strbuf = dbe_sprintf (NTXT ("%s:%s"), str_search_path, arglist[0]);
+ free (str_search_path);
+ str_search_path = strbuf;
+ }
+ else
+ str_search_path = dbe_strdup (arglist[0]);
+ break;
+ case PATHMAP:
+ {
+ char *err = add_pathmap (pathmaps, arglist[0], arglist[1]);
+ free (err); // XXX error is not reported
+ break;
+ }
+ case LIBDIRS:
+ if (preload_libdirs == NULL)
+ preload_libdirs = dbe_strdup (arglist[0]);
+ break;
+ case NAMEFMT:
+ if (name_format == Histable::NA)
+ set_name_format (arglist[0]);
+ break;
+ case VIEWMODE:
+ if (!str_vmode || override)
+ {
+ str_vmode = dbe_strdup (arglist[0]);
+ set_view_mode (arglist[0], true);
+ }
+ break;
+ case EN_DESC:
+ if (!str_en_desc || override)
+ {
+ str_en_desc = dbe_strdup (arglist[0]);
+ set_en_desc (arglist[0], true);
+ }
+ break;
+ case LIMIT:
+ if (!str_limit || override)
+ {
+ str_limit = dbe_strdup (arglist[0]);
+ set_limit (arglist[0], true);
+ }
+ break;
+ case PRINTMODE:
+ if (!str_printmode || override)
+ set_printmode (arglist[0]);
+ break;
+ case COMPARE:
+ if (!str_compare || override)
+ {
+ char *s = arglist[0];
+ if (s)
+ str_compare = dbe_strdup (s);
+ else
+ s = NTXT ("");
+ if (strcasecmp (s, NTXT ("OFF")) == 0
+ || strcmp (s, NTXT ("0")) == 0)
+ set_compare_mode (CMP_DISABLE);
+ else if (strcasecmp (s, NTXT ("ON")) == 0
+ || strcmp (s, NTXT ("1")) == 0)
+ set_compare_mode (CMP_ENABLE);
+ else if (strcasecmp (s, NTXT ("DELTA")) == 0)
+ set_compare_mode (CMP_DELTA);
+ else if (strcasecmp (s, NTXT ("RATIO")) == 0)
+ set_compare_mode (CMP_RATIO);
+ else
+ {
+ sb.sprintf (GTXT (" .er.rc:%d The argument of 'compare' should be 'on', 'off', 'delta', or 'ratio'"),
+ (int) line_no);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ }
+ }
+ break;
+
+ case INDXOBJDEF:
+ {
+ char *ret = dbeSession->indxobj_define (arglist[0], NULL, arglist[1], (nargs >= 3) ? PTXT (arglist[2]) : NULL, (nargs >= 4) ? PTXT (arglist[3]) : NULL);
+ if (ret != NULL)
+ {
+ sb.sprintf (GTXT (" %s: line %d `%s %s %s'\n"),
+ ret, line_no, cmd, arglist[0], arglist[1]);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ }
+ break;
+ }
+#ifdef sparc
+ //XXX: should be conditional on the experiment ARCH, not dbe ARCH
+ case IGNORE_NO_XHWCPROF:
+ // ignore absence of -xhwcprof info for dataspace profiling
+ set_ignore_no_xhwcprof (true);
+ break;
+#endif // sparc
+ case IGNORE_FS_WARN:
+ // ignore file system warning in experiments
+ set_ignore_fs_warn (true);
+ break;
+ case OBJECT_SHOW:
+ // Add the named libraries to the lib_expands array
+ set_libexpand (arglist[0], LIBEX_SHOW, true);
+ break;
+ case OBJECT_HIDE:
+ // Add the named libraries to the lib_expands array
+ set_libexpand (arglist[0], LIBEX_HIDE, true);
+ break;
+ case OBJECT_API:
+ // Add the named libraries to the lib_expands array
+ set_libexpand (arglist[0], LIBEX_API, true);
+ break;
+ case COMMENT:
+ // ignore the line
+ break;
+ default:
+ {
+ // unexpected command in an rc file
+ if (!msg)
+ {
+ // if quiet, can remain so no longer
+ msg = true;
+ Emsg *m = new Emsg (CMSG_COMMENT, GTXT ("Processed system gprofng.rc file for default settings"));
+ commentq->append (m);
+ }
+ sb.sprintf (GTXT (" Unrecognized .gprofng.rc command on line %d: `%.64s'"),
+ line_no, cmd);
+ Emsg *m = new Emsg (CMSG_COMMENT, sb);
+ commentq->append (m);
+ break;
+ }
+ }
+ free (script);
+ }
+ fclose (fptr);
+}
+
+Cmd_status
+Settings::set_view_mode (char *arg, bool rc)
+{
+ if (!strcasecmp (arg, NTXT ("user")))
+ view_mode = VMODE_USER;
+ else if (!strcasecmp (arg, NTXT ("expert")))
+ view_mode = VMODE_EXPERT;
+ else if (!strcasecmp (arg, NTXT ("machine")))
+ view_mode = VMODE_MACHINE;
+ else if (!rc)
+ return CMD_BAD_ARG;
+ return CMD_OK;
+}
+
+Cmd_status
+Settings::set_en_desc (char *arg, bool rc)
+{
+ regex_t *regex_desc = NULL;
+
+ // cases below should be similar to Coll_Ctrl::set_follow_mode() cases
+ if (!strcasecmp (arg, NTXT ("on")))
+ en_desc = true;
+ else if (!strcasecmp (arg, NTXT ("off")))
+ en_desc = false;
+ else if (arg[0] == '=' && arg[1] != 0)
+ {
+ // user has specified a string matching specification
+ int ercode;
+ { // compile regex_desc
+ char * str = dbe_sprintf (NTXT ("^%s$"), arg + 1);
+ regex_desc = new regex_t;
+ memset (regex_desc, 0, sizeof (regex_t));
+ ercode = regcomp (regex_desc, str, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
+ free (str);
+ }
+ if (ercode)
+ {
+ // syntax error in parsing string
+ delete regex_desc;
+ if (!rc)
+ return CMD_BAD_ARG;
+ return CMD_OK;
+ }
+ en_desc = true;
+ }
+ else
+ {
+ if (!rc)
+ return CMD_BAD_ARG;
+ return CMD_OK;
+ }
+ free (en_desc_usr);
+ en_desc_usr = dbe_strdup (arg);
+ if (en_desc_cmp)
+ {
+ regfree (en_desc_cmp);
+ delete en_desc_cmp;
+ }
+ en_desc_cmp = regex_desc;
+ return CMD_OK;
+}
+
+// See if a descendant matches either the lineage or the executable name
+bool
+Settings::check_en_desc (const char *lineage, const char *targname)
+{
+ bool rc;
+ if (en_desc_cmp == NULL)
+ return en_desc; // no specification was set, use the binary on/off value
+ if (lineage == NULL) // user doesn't care about specification
+ return en_desc; // use the binary on/off specification
+ if (!regexec (en_desc_cmp, lineage, 0, NULL, 0))
+ rc = true; // this one matches user specification
+ else if (targname == NULL)
+ rc = false; //a NULL name does not match any expression
+ else if (!regexec (en_desc_cmp, targname, 0, NULL, 0))
+ rc = true; // this one matches the executable name
+ else
+ rc = false;
+ return rc;
+}
+
+char *
+Settings::set_limit (char *arg, bool)
+{
+ limit = (int) strtol (arg, (char **) NULL, 10);
+ return NULL;
+}
+
+char *
+Settings::set_printmode (char *arg)
+{
+ if (arg == NULL)
+ return dbe_sprintf (GTXT ("The argument to '%s' must be '%s' or '%s' or a single-character"),
+ NTXT ("printmode"), NTXT ("text"), NTXT ("html"));
+ if (strlen (arg) == 1)
+ {
+ print_mode = PM_DELIM_SEP_LIST;
+ print_delim = arg[0];
+ }
+ else if (!strcasecmp (arg, NTXT ("text")))
+ print_mode = PM_TEXT;
+ else if (!strcasecmp (arg, NTXT ("html")))
+ print_mode = PM_HTML;
+ else
+ return dbe_sprintf (GTXT ("The argument to '%s' must be '%s' or '%s' or a single-character"),
+ NTXT ("printmode"), NTXT ("text"), NTXT ("html"));
+ free (str_printmode);
+ str_printmode = dbe_strdup (arg);
+ return NULL;
+}
+
+Cmd_status
+Settings::proc_compcom (const char *cmd, bool isSrc, bool rc)
+{
+ int ck_compcom_bits, ck_threshold;
+ bool ck_hex_visible = false;
+ bool ck_src_visible = false;
+ bool ck_srcmetric_visible = false;
+ bool got_compcom_bits, got_threshold, got_src_visible, got_srcmetric_visible;
+ bool got_hex_visible, got;
+ int len, i;
+ char *mcmd, *param;
+ int flag, value = 0;
+ Cmd_status status;
+ char buf[BUFSIZ], *list;
+
+ if (cmd == NULL)
+ return CMD_BAD;
+ ck_compcom_bits = 0;
+ ck_threshold = 0;
+ got_compcom_bits = got_threshold = got_src_visible = false;
+ got_srcmetric_visible = got_hex_visible = false;
+ snprintf (buf, sizeof (buf), NTXT ("%s"), cmd);
+ list = buf;
+ while ((mcmd = strtok (list, NTXT (":"))) != NULL)
+ {
+ list = NULL;
+ // if "all" or "none"
+ if (!strcasecmp (mcmd, Command::ALL_CMD))
+ {
+ got_compcom_bits = true;
+ ck_compcom_bits = CCMV_ALL;
+ continue;
+ }
+ else if (!strcasecmp (mcmd, Command::NONE_CMD))
+ {
+ got_compcom_bits = true;
+ ck_compcom_bits = 0;
+ continue;
+ }
+
+ // Find parameter after '='
+ param = strchr (mcmd, '=');
+ if (param)
+ {
+ *param = '\0';
+ param++;
+ }
+ status = CMD_OK;
+ got = false;
+ flag = 0;
+ len = (int) strlen (mcmd);
+ for (i = 0; status == CMD_OK && i < comp_size; i++)
+ if (!strncasecmp (mcmd, comp_cmd[i], len))
+ {
+ if (got) // Ambiguous comp_com command
+ status = CMD_AMBIGUOUS;
+ else
+ {
+ got = true;
+ flag = comp_vis[i];
+ // Check argument
+ if (flag == COMP_THRESHOLD)
+ {
+ if (param == NULL)
+ status = CMD_BAD_ARG;
+ else
+ {
+ value = (int) strtol (param, &param, 10);
+ if (value < 0 || value > 100)
+ status = CMD_OUTRANGE;
+ }
+ }
+ else if (param != NULL)
+ status = CMD_BAD_ARG;
+ }
+ }
+
+ // Not valid comp_com command
+ if (!got)
+ status = CMD_INVALID;
+ if (status != CMD_OK)
+ {
+ if (!rc)
+ return status;
+ continue;
+ }
+
+ // Set bits
+ switch (flag)
+ {
+ case COMP_CMPLINE:
+ cmpline_visible = true;
+ break;
+ case COMP_FUNCLINE:
+ funcline_visible = true;
+ break;
+ case COMP_THRESHOLD:
+ got_threshold = true;
+ ck_threshold = value;
+ break;
+ case COMP_SRC:
+ got_src_visible = true;
+ ck_src_visible = true;
+ break;
+ case COMP_SRC_METRIC:
+ got_srcmetric_visible = true;
+ ck_srcmetric_visible = true;
+ got_src_visible = true;
+ ck_src_visible = true;
+ break;
+ case COMP_NOSRC:
+ got_src_visible = true;
+ ck_src_visible = false;
+ break;
+ case COMP_HEX:
+ got_hex_visible = true;
+ ck_hex_visible = true;
+ break;
+ case COMP_NOHEX:
+ got_hex_visible = true;
+ ck_hex_visible = false;
+ break;
+ case CCMV_BASIC:
+ got_compcom_bits = true;
+ ck_compcom_bits = CCMV_BASIC;
+ break;
+ default:
+ got_compcom_bits = true;
+ ck_compcom_bits |= flag;
+ }
+ }
+
+ // No error, update
+ if (got_compcom_bits)
+ {
+ if (isSrc)
+ src_compcom = ck_compcom_bits;
+ else
+ dis_compcom = ck_compcom_bits;
+ }
+ if (got_threshold)
+ {
+ if (isSrc)
+ threshold_src = ck_threshold;
+ else
+ threshold_dis = ck_threshold;
+ }
+ if (got_src_visible)
+ src_visible = ck_src_visible;
+ if (got_srcmetric_visible)
+ srcmetric_visible = ck_srcmetric_visible;
+ if (got_hex_visible)
+ hex_visible = ck_hex_visible;
+ return CMD_OK;
+}
+
+// Process a threshold setting
+Cmd_status
+Settings::proc_thresh (char *cmd, bool isSrc, bool rc)
+{
+ int value;
+ if (cmd == NULL)
+ value = DEFAULT_SRC_DIS_THRESHOLD; // the default
+ else
+ value = (int) strtol (cmd, &cmd, 10);
+ if (value < 0 || value > 100)
+ {
+ if (!rc)
+ return CMD_OUTRANGE;
+ value = DEFAULT_SRC_DIS_THRESHOLD;
+ }
+ if (isSrc)
+ threshold_src = value;
+ else
+ threshold_dis = value;
+ return CMD_OK;
+}
+
+// return any error string from processing visibility settings
+char *
+Settings::get_compcom_errstr (Cmd_status status, const char *cmd)
+{
+ int i;
+ StringBuilder sb;
+ switch (status)
+ {
+ case CMD_BAD:
+ sb.append (GTXT ("No commentary classes has been specified."));
+ break;
+ case CMD_AMBIGUOUS:
+ sb.append (GTXT ("Ambiguous commentary classes: "));
+ break;
+ case CMD_BAD_ARG:
+ sb.append (GTXT ("Invalid argument for commentary classes: "));
+ break;
+ case CMD_OUTRANGE:
+ sb.append (GTXT ("Out of range commentary classes argument: "));
+ break;
+ case CMD_INVALID:
+ sb.append (GTXT ("Invalid commentary classes: "));
+ break;
+ case CMD_OK:
+ break;
+ }
+ if (cmd)
+ sb.append (cmd);
+ sb.append (GTXT ("\nAvailable commentary classes: "));
+ for (i = 0; i < comp_size; i++)
+ {
+ sb.append (comp_cmd[i]);
+ if (i == comp_size - 1)
+ sb.append (NTXT ("=#\n"));
+ else
+ sb.append (NTXT (":"));
+ }
+ return sb.toString ();
+}
+
+// Process a timeline-mode setting
+Cmd_status
+Settings::proc_tlmode (char *cmd, bool rc)
+{
+ bool got_tlmode, got_stack_align, got_stack_depth, got;
+ int ck_tlmode = 0, ck_stack_align = 0, ck_stack_depth = 0;
+ int len, i;
+ char *mcmd, *param;
+ int cmd_id, value = 0;
+ TLModeSubcommand cmd_type;
+ Cmd_status status;
+ char buf[BUFSIZ], *list;
+ if (cmd == NULL)
+ return CMD_BAD;
+ got_tlmode = got_stack_align = got_stack_depth = false;
+ snprintf (buf, sizeof (buf), NTXT ("%s"), cmd);
+ list = buf;
+ while ((mcmd = strtok (list, NTXT (":"))) != NULL)
+ {
+ list = NULL;
+
+ // Find parameter after '='
+ param = strchr (mcmd, '=');
+ if (param)
+ {
+ *param = '\0';
+ param++;
+ }
+ status = CMD_OK;
+ got = false;
+ cmd_id = 0;
+ cmd_type = TLCMD_INVALID;
+ len = (int) strlen (mcmd);
+ for (i = 0; status == CMD_OK && i < tlmode_size; i++)
+ {
+ if (!strncasecmp (mcmd, tlmode_cmd[i].cmdText, len))
+ {
+ if (got) // Ambiguous timeline mode
+ status = CMD_AMBIGUOUS;
+ else
+ {
+ got = true;
+ cmd_type = tlmode_cmd[i].cmdType;
+ cmd_id = tlmode_cmd[i].cmdId;
+
+ // Check argument
+ if (cmd_type == TLCMD_DEPTH)
+ {
+ if (param == NULL)
+ status = CMD_BAD_ARG;
+ else
+ {
+ value = (int) strtol (param, &param, 10);
+ if (value <= 0 || value > 256)
+ status = CMD_OUTRANGE;
+ }
+ }
+ else if (param != NULL)
+ status = CMD_BAD_ARG;
+ }
+ }
+ }
+
+ // Not valid timeline mode
+ if (!got)
+ status = CMD_INVALID;
+ if (status != CMD_OK)
+ {
+ if (!rc)
+ return status;
+ continue;
+ }
+
+ // Set bits
+ switch (cmd_type)
+ {
+ case TLCMD_ENTITY_MODE:
+ got_tlmode = true;
+ ck_tlmode = cmd_id;
+ break;
+ case TLCMD_ALIGN:
+ got_stack_align = true;
+ ck_stack_align = cmd_id;
+ break;
+ case TLCMD_DEPTH:
+ got_stack_depth = true;
+ ck_stack_depth = value;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // No error, update
+ if (got_tlmode)
+ tlmode = ck_tlmode;
+ if (got_stack_align)
+ stack_align = ck_stack_align;
+ if (got_stack_depth)
+ stack_depth = ck_stack_depth;
+ return CMD_OK;
+}
+
+// Process timeline data specification
+Cmd_status
+Settings::proc_tldata (const char *cmd, bool /* if true, ignore any error */)
+{
+ free (tldata);
+ tldata = dbe_strdup (cmd); // let GUI parse it
+ return CMD_OK;
+}
+
+void
+Settings::set_tldata (const char* _tldata_str)
+{
+ free (tldata);
+ tldata = dbe_strdup (_tldata_str);
+}
+
+char*
+Settings::get_tldata ()
+{
+ return dbe_strdup (tldata);
+}
+
+Cmd_status
+Settings::set_name_format (char *arg)
+{
+ char *colon = strchr (arg, ':');
+ size_t arg_len = (colon) ? (colon - arg) : strlen (arg);
+ Histable::NameFormat fname_fmt = Histable::NA;
+ if (!strncasecmp (arg, NTXT ("long"), arg_len))
+ fname_fmt = Histable::LONG;
+ else if (!strncasecmp (arg, NTXT ("short"), arg_len))
+ fname_fmt = Histable::SHORT;
+ else if (!strncasecmp (arg, NTXT ("mangled"), arg_len))
+ fname_fmt = Histable::MANGLED;
+ else
+ return CMD_BAD_ARG;
+
+ bool soname_fmt = false;
+ if (colon && (colon + 1))
+ {
+ colon++;
+ if (!strcasecmp (colon, NTXT ("soname")))
+ soname_fmt = true;
+ else if (!strcasecmp (colon, NTXT ("nosoname")))
+ soname_fmt = false;
+ else
+ return CMD_BAD_ARG;
+ }
+ name_format = Histable::make_fmt (fname_fmt, soname_fmt);
+ return CMD_OK;
+}
+
+void
+Settings::buildMasterTabList ()
+{
+ tab_list = new Vector<DispTab*>;
+ int i = -1;
+
+ // Add tabs for all the known reports
+ tab_list->append (new DispTab (DSP_DEADLOCKS, i, false, DEADLOCK_EVNTS));
+ tab_list->append (new DispTab (DSP_FUNCTION, i, false, FUNCS));
+ tab_list->append (new DispTab (DSP_TIMELINE, i, false, TIMELINE));
+ tab_list->append (new DispTab (DSP_CALLTREE, i, false, CALLTREE));
+ tab_list->append (new DispTab (DSP_CALLFLAME, i, false, CALLFLAME));
+ tab_list->append (new DispTab (DSP_DUALSOURCE, i, false, DUALSOURCE));
+ tab_list->append (new DispTab (DSP_SOURCE_DISASM, i, false, SOURCEDISAM));
+ tab_list->append (new DispTab (DSP_SOURCE, i, false, SOURCE));
+ tab_list->append (new DispTab (DSP_LINE, i, false, HOTLINES));
+ tab_list->append (new DispTab (DSP_DISASM, i, false, DISASM));
+ tab_list->append (new DispTab (DSP_PC, i, false, HOTPCS));
+ tab_list->append (new DispTab (DSP_LEAKLIST, i, false, LEAKS));
+ tab_list->append (new DispTab (DSP_IOACTIVITY, i, false, IOACTIVITY));
+ tab_list->append (new DispTab (DSP_HEAPCALLSTACK, i, false, HEAP));
+ tab_list->append (new DispTab (DSP_IFREQ, i, false, IFREQ));
+ tab_list->append (new DispTab (DSP_CALLER, i, false, GPROF));
+ tab_list->append (new DispTab (DSP_STATIS, i, false, STATISTICS));
+ tab_list->append (new DispTab (DSP_EXP, i, false, HEADER));
+}
+
+// Update tablist based on data availability
+void
+Settings::updateTabAvailability ()
+{
+ int index;
+ DispTab *dsptab;
+
+ Vec_loop (DispTab*, tab_list, index, dsptab)
+ {
+ if (dsptab->type == DSP_DATAOBJ)
+ dsptab->setAvailability (dbeSession->is_datamode_available ());
+ else if (dsptab->type == DSP_DLAYOUT)
+ dsptab->setAvailability (dbeSession->is_datamode_available ());
+ else if (dsptab->type == DSP_LEAKLIST)
+ dsptab->setAvailability (false);
+ else if (dsptab->type == DSP_IOACTIVITY)
+ dsptab->setAvailability (dbeSession->is_iodata_available ());
+ else if (dsptab->type == DSP_HEAPCALLSTACK)
+ dsptab->setAvailability (dbeSession->is_heapdata_available ());
+ else if (dsptab->type == DSP_TIMELINE)
+ dsptab->setAvailability (dbeSession->is_timeline_available ());
+ else if (dsptab->type == DSP_IFREQ)
+ dsptab->setAvailability (dbeSession->is_ifreq_available ());
+ else if (dsptab->type == DSP_RACES)
+ dsptab->setAvailability (dbeSession->is_racelist_available ());
+ else if (dsptab->type == DSP_DEADLOCKS)
+ dsptab->setAvailability (dbeSession->is_deadlocklist_available ());
+ else if (dsptab->type == DSP_DUALSOURCE)
+ dsptab->setAvailability (dbeSession->is_racelist_available ()
+ || dbeSession->is_deadlocklist_available ());
+ }
+}
+
+// Process a tab setting
+Cmd_status
+Settings::proc_tabs (bool _rdtMode)
+{
+ int arg_cnt, cparam;
+ int count = 0;
+ int index;
+ DispTab *dsptab;
+ char *cmd;
+ if (tabs_processed == true)
+ return CMD_OK;
+ tabs_processed = true;
+ if (_rdtMode == true)
+ {
+ if (str_rtabs == NULL)
+ str_rtabs = strdup ("header");
+ cmd = str_rtabs;
+ }
+ else
+ {
+ if (str_tabs == NULL)
+ str_tabs = strdup ("header");
+ cmd = str_tabs;
+ }
+ if (strcmp (cmd, NTXT ("none")) == 0)
+ return CMD_OK;
+ Vector <char *> *tokens = split_str (cmd, ':');
+ for (long j = 0, sz = VecSize (tokens); j < sz; j++)
+ {
+ char *tabname = tokens->get (j);
+ // search for this tab command token
+ CmdType c = Command::get_command (tabname, arg_cnt, cparam);
+ if (c == INDXOBJ)
+ {
+ // set the bit for this subtype
+ indx_tab_state->store (cparam, true);
+ indx_tab_order->store (cparam, count++);
+ }
+ else
+ {
+ // search for this tab type in the regular tabs
+ Vec_loop (DispTab*, tab_list, index, dsptab)
+ {
+ if (dsptab->cmdtoken == c)
+ {
+ dsptab->visible = true;
+ dsptab->order = count++;
+ break;
+ }
+ }
+ }
+ free (tabname);
+ }
+ delete tokens;
+ return CMD_OK;
+}
+
+void
+Settings::set_MemTabState (Vector<bool>*selected)
+{
+ if (selected->size () == 0)
+ return;
+ for (int j = 0; j < mem_tab_state->size (); j++)
+ mem_tab_state->store (j, selected->fetch (j));
+}
+
+// define a new memory object type
+
+void
+Settings::mobj_define (MemObjType_t */* mobj */, bool state)
+{
+ if (mem_tab_state->size () == 0)
+ state = true;
+ mem_tab_state->append (state);
+ mem_tab_order->append (-1);
+}
+
+void
+Settings::set_IndxTabState (Vector<bool>*selected)
+{
+ for (int j = 0; j < selected->size (); j++)
+ indx_tab_state->store (j, selected->fetch (j));
+}
+
+// define a new index object type
+void
+Settings::indxobj_define (int type, bool state)
+{
+ indx_tab_state->store (type, state);
+ indx_tab_order->store (type, -1);
+}
+
+void
+Settings::set_pathmaps (Vector<pathmap_t*> *newPathMap)
+{
+ if (pathmaps)
+ {
+ pathmaps->destroy ();
+ delete pathmaps;
+ }
+ pathmaps = newPathMap;
+}
+
+static char *
+get_canonical_name (const char *fname)
+{
+ char *nm = dbe_strdup (fname);
+ for (size_t len = strlen (nm); (len > 0) && (nm[len - 1] == '/'); len--)
+ nm[len - 1] = 0;
+ return nm;
+}
+
+char *
+Settings::add_pathmap (Vector<pathmap_t*> *v, const char *from, const char *to)
+{
+ // Check for errors
+ if (from == NULL || to == NULL)
+ return dbe_strdup (GTXT ("Pathmap can have neither from nor to as NULL\n"));
+ if (strcmp (from, to) == 0)
+ return dbe_strdup (GTXT ("Pathmap from must differ from to\n"));
+ char *old_prefix = get_canonical_name (from);
+ char *new_prefix = get_canonical_name (to);
+
+ // Check the pathmap list
+ for (int i = 0, sz = v->size (); i < sz; i++)
+ {
+ pathmap_t *pmp = v->get (i);
+ if ((strcmp (pmp->old_prefix, old_prefix) == 0) &&(strcmp (pmp->new_prefix, new_prefix) == 0))
+ {
+ char *s = dbe_sprintf (GTXT ("Pathmap from `%s' to `%s' already exists\n"), old_prefix, new_prefix);
+ free (old_prefix);
+ free (new_prefix);
+ return s;
+ }
+ }
+ // construct a map for this pair
+ pathmap_t *thismap = new pathmap_t;
+ thismap->old_prefix = old_prefix;
+ thismap->new_prefix = new_prefix;
+ v->append (thismap);
+ return NULL;
+}
+
+// Set all shared object expands back to .rc file defaults,
+// as stored in the DbeSession Settings
+bool
+Settings::set_libdefaults ()
+{
+ // See if this is unchanged
+ if (is_loexpand_default == true)
+ return false; // no change
+
+ // replicate the DbeSession's lo_expand vector and default settings
+ lo_expand_t *this_lo_ex;
+ lo_expand_t *new_lo_ex;
+ int index;
+ lo_expand_default = dbeSession->get_settings ()->lo_expand_default;
+ lo_expands = new Vector<lo_expand_t*>;
+ Vec_loop (lo_expand_t*, dbeSession->get_settings ()->lo_expands, index, this_lo_ex)
+ {
+ new_lo_ex = new lo_expand_t;
+ new_lo_ex->libname = dbe_strdup (this_lo_ex->libname);
+ new_lo_ex->expand = this_lo_ex->expand;
+ lo_expands->append (new_lo_ex);
+ }
+ is_loexpand_default = true;
+ return true;
+}
+
+bool
+Settings::set_libexpand (char *cov, enum LibExpand expand, bool rc)
+{
+ int index;
+ lo_expand_t *loe;
+ bool change = false;
+ if (cov == NULL || !strcasecmp (cov, Command::ALL_CMD))
+ { // set all libraries
+ // set the default
+ if (lo_expand_default != expand)
+ {
+ lo_expand_default = expand;
+ change = true;
+ is_loexpand_default = false;
+ }
+
+ // and force any explicit settings to match, too
+ Vec_loop (lo_expand_t*, lo_expands, index, loe)
+ {
+ if (loe->expand != expand)
+ {
+ loe->expand = expand;
+ change = true;
+ is_loexpand_default = false;
+ }
+ }
+
+ }
+ else
+ { // parsing coverage
+ Vector <char *> *tokens = split_str (cov, ',');
+ for (long j = 0, sz = VecSize (tokens); j < sz; j++)
+ {
+ char *lo_name = tokens->get (j);
+ char *newname = get_basename (lo_name);
+ bool found = false;
+ Vec_loop (lo_expand_t*, lo_expands, index, loe)
+ {
+ if (strcmp (loe->libname, newname) == 0)
+ {
+ if (loe->expand != expand)
+ {
+ if (rc == false)
+ {
+ loe->expand = expand;
+ change = true;
+ is_loexpand_default = false;
+ }
+ }
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false)
+ {
+ // construct a map for this pair
+ lo_expand_t *thisloe;
+ thisloe = new lo_expand_t;
+ thisloe->libname = dbe_strdup (newname);
+ thisloe->expand = expand;
+ change = true;
+ is_loexpand_default = false;
+
+ // add it to the vector
+ lo_expands->append (thisloe);
+ }
+ free (lo_name);
+ }
+ delete tokens;
+ }
+ return change;
+}
+
+enum LibExpand
+Settings::get_lo_setting (char *name)
+{
+ int index;
+ lo_expand_t *loe;
+ char *lo_name = get_basename (name);
+ Vec_loop (lo_expand_t*, lo_expands, index, loe)
+ {
+ if (strcmp (loe->libname, lo_name) == 0)
+ return loe->expand;
+ }
+ return lo_expand_default;
+}