ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
1590 lines
40 KiB
C++
1590 lines
40 KiB
C++
/* Copyright (C) 2021-2024 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
|
|
const char *sysconfdir = getenv("GPROFNG_SYSCONFDIR");
|
|
if (sysconfdir == NULL)
|
|
sysconfdir = SYSCONFDIR;
|
|
rc_path = dbe_sprintf (NTXT ("%s/gprofng.rc"), sysconfdir);
|
|
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, ¶m, 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, ¶m, 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++;
|
|
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;
|
|
}
|