Update year range in copyright notice of binutils files
[binutils-gdb.git] / gprofng / src / Settings.cc
blob6d1d357a1756f95623f3646a2d3cd9a46b6198e6
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
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.
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.
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. */
21 #include "config.h"
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/param.h>
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"
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")
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
82 const int comp_size = sizeof (comp_cmd) / sizeof (char *);
84 // Commands for timeline
85 typedef enum
87 TLCMD_INVALID,
88 TLCMD_ENTITY_MODE,
89 TLCMD_ALIGN,
90 TLCMD_DEPTH
91 } TLModeSubcommand;
93 typedef struct
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 */}
112 static const int tlmode_size = sizeof (tlmode_cmd) / sizeof (TLModeCmd);
114 // Constructor
116 Settings::Settings (Application *_app)
118 // Remember the application
119 app = _app;
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;
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;
175 // construct the master list of tabs
176 buildMasterTabList ();
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>;
183 // note that the .rc files are not read here, but later
186 // Constructor for duplicating an existing Settings class
188 Settings::Settings (Settings * _settings)
190 int index;
191 app = _settings->app;
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);
214 // replicate the pathmap vector
215 pathmap_t *thismap;
216 pathmap_t *newmap;
217 pathmaps = new Vector<pathmap_t*>;
219 Vec_loop (pathmap_t*, _settings->pathmaps, index, thismap)
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);
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*>;
234 Vec_loop (lo_expand_t*, _settings->lo_expands, index, this_lo_ex)
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);
241 tabs_processed = _settings->tabs_processed;
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;
272 // copy the tab list, too
273 tab_list = new Vector<DispTab*>;
274 DispTab *dsptab;
276 Vec_loop (DispTab*, _settings->tab_list, index, dsptab)
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);
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++)
290 mem_tab_state->append (false);
291 mem_tab_order->append (_settings->mem_tab_order->fetch (i));
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);
303 Settings::~Settings ()
305 for (int i = 0; i < pathmaps->size (); ++i)
307 pathmap_t *pmap = pathmaps->fetch (i);
308 free (pmap->old_prefix);
309 free (pmap->new_prefix);
310 delete pmap;
312 delete pathmaps;
314 for (int i = 0; i < lo_expands->size (); ++i)
316 lo_expand_t *lo_ex = lo_expands->fetch (i);
317 free (lo_ex->libname);
318 delete lo_ex;
320 delete lo_expands;
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;
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)
352 regfree (en_desc_cmp);
353 delete en_desc_cmp;
358 * Read .er.rc file from the specified location
359 * @param path
360 * @return
362 char *
363 Settings::read_rc (char *path)
365 StringBuilder sb;
366 Emsgqueue *commentq = new Emsgqueue (NTXT ("setting_commentq"));
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)
376 char *str = msg->get_msg ();
377 sb.append (str);
378 msg = msg->next;
380 return sb.toString ();
383 void
384 Settings::read_rc (bool ipc_or_rdt_mode)
386 bool override = false;
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);
393 // Read file from the user's home directory
394 char *home = getenv (NTXT ("HOME"));
395 if (home)
397 char *strbuf = dbe_sprintf (NTXT ("%s/.gprofng.rc"), home);
398 char *home_rc_path = realpath (strbuf, NULL);
399 if (home_rc_path)
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);
405 free (strbuf);
407 free (rc_path);
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)
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);
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)
427 // only if there's none set
428 print_mode = PM_TEXT;
429 str_printmode = dbe_strdup (NTXT ("text"));
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
441 #define MAXARGS 20
443 void
444 Settings::set_rc (const char *path, bool msg, Emsgqueue *commentq,
445 bool override, bool ipc_or_rdt_mode)
447 CmdType cmd_type;
448 int arg_count, cparam;
449 char *cmd, *end_cmd, *strbuf;
450 char *arglist[MAXARGS];
451 StringBuilder sb;
453 FILE *fptr = fopen (path, NTXT ("r"));
454 if (fptr == NULL)
455 return;
457 if (msg)
459 sb.sprintf (GTXT ("Processed %s for default settings"), path);
460 Emsg *m = new Emsg (CMSG_COMMENT, sb);
461 commentq->append (m);
463 int line_no = 0;
464 end_cmd = NULL;
465 while (!feof (fptr))
467 char *script = read_line (fptr);
468 if (script == NULL)
469 continue;
470 line_no++;
471 strtok (script, NTXT ("\n"));
473 // extract the command
474 cmd = strtok (script, NTXT (" \t"));
475 if (cmd == NULL || *cmd == '#' || *cmd == '\n')
477 free (script);
478 continue;
480 char *remainder = strtok (NULL, NTXT ("\n"));
481 // now extract the arguments
482 int nargs = 0;
483 for (;;)
485 if (nargs >= MAXARGS)
487 if (!msg)
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);
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;
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++;
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))
515 if (!msg)
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);
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);
525 if (nargs < arg_count)
527 if (!msg)
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);
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);
538 // ignore this command
539 free (script);
540 continue;
542 if (ipc_or_rdt_mode && (cmd_type != ADDPATH) && (cmd_type != PATHMAP))
544 free (script);
545 continue;
547 switch (cmd_type)
549 case SCOMPCOM:
550 if (!str_scompcom || override)
552 str_scompcom = dbe_strdup (arglist[0]);
553 proc_compcom (arglist[0], true, true);
555 break;
556 case STHRESH:
557 if (!str_sthresh || override)
559 str_sthresh = dbe_strdup (arglist[0]);
560 proc_thresh (arglist[0], true, true);
561 break;
563 break;
564 case DCOMPCOM:
565 if (!str_dcompcom || override)
567 str_dcompcom = dbe_strdup (arglist[0]);
568 proc_compcom (arglist[0], false, true);
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)
577 str_scompcom = dbe_strdup (arglist[0]);
578 proc_compcom (arglist[0], true, true);
580 if (!str_dcompcom || override)
582 str_dcompcom = dbe_strdup (arglist[0]);
583 proc_compcom (arglist[0], false, true);
585 break;
586 case DTHRESH:
587 if (!str_dthresh || override)
589 str_dthresh = dbe_strdup (arglist[0]);
590 proc_thresh (arglist[0], false, true);
592 break;
593 case DMETRICS:
594 // append new settings to old, if necessary
595 if (str_dmetrics)
597 char *name = strstr (str_dmetrics, ":name");
598 if (name == NULL)
599 strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
600 else
602 char * next = strstr (name + 1, ":");
603 if (next == NULL)
605 name[0] = '\0';
606 strbuf = dbe_sprintf ("%s:%s:name", str_dmetrics, arglist[0]);
608 else
609 strbuf = dbe_sprintf ("%s:%s", str_dmetrics, arglist[0]);
611 free (str_dmetrics);
612 str_dmetrics = strbuf;
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)
621 strbuf = dbe_sprintf (NTXT ("%s:%s"), str_dsort, arglist[0]);
622 free (str_dsort);
623 str_dsort = strbuf;
625 else
626 str_dsort = dbe_strdup (arglist[0]);
627 break;
628 case TLMODE:
629 if (!str_tlmode || override)
631 str_tlmode = dbe_strdup (arglist[0]);
632 proc_tlmode (arglist[0], true);
634 break;
635 case TLDATA:
636 if (!str_tldata || override)
638 str_tldata = dbe_strdup (arglist[0]);
639 proc_tldata (arglist[0], true);
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)
655 strbuf = dbe_sprintf (NTXT ("%s:%s"), str_search_path, arglist[0]);
656 free (str_search_path);
657 str_search_path = strbuf;
659 else
660 str_search_path = dbe_strdup (arglist[0]);
661 break;
662 case PATHMAP:
664 char *err = add_pathmap (pathmaps, arglist[0], arglist[1]);
665 free (err); // XXX error is not reported
666 break;
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)
679 str_vmode = dbe_strdup (arglist[0]);
680 set_view_mode (arglist[0], true);
682 break;
683 case EN_DESC:
684 if (!str_en_desc || override)
686 str_en_desc = dbe_strdup (arglist[0]);
687 set_en_desc (arglist[0], true);
689 break;
690 case LIMIT:
691 if (!str_limit || override)
693 str_limit = dbe_strdup (arglist[0]);
694 set_limit (arglist[0], true);
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)
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
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);
727 break;
729 case INDXOBJDEF:
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)
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);
739 break;
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:
769 // unexpected command in an rc file
770 if (!msg)
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);
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;
784 free (script);
786 fclose (fptr);
789 Cmd_status
790 Settings::set_view_mode (char *arg, bool rc)
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;
803 Cmd_status
804 Settings::set_en_desc (char *arg, bool rc)
806 regex_t *regex_desc = NULL;
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)
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);
824 if (ercode)
826 // syntax error in parsing string
827 delete regex_desc;
828 if (!rc)
829 return CMD_BAD_ARG;
830 return CMD_OK;
832 en_desc = true;
834 else
836 if (!rc)
837 return CMD_BAD_ARG;
838 return CMD_OK;
840 free (en_desc_usr);
841 en_desc_usr = dbe_strdup (arg);
842 if (en_desc_cmp)
844 regfree (en_desc_cmp);
845 delete en_desc_cmp;
847 en_desc_cmp = regex_desc;
848 return CMD_OK;
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)
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;
871 char *
872 Settings::set_limit (char *arg, bool)
874 limit = (int) strtol (arg, (char **) NULL, 10);
875 return NULL;
878 char *
879 Settings::set_printmode (char *arg)
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)
886 print_mode = PM_DELIM_SEP_LIST;
887 print_delim = arg[0];
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;
901 Cmd_status
902 Settings::proc_compcom (const char *cmd, bool isSrc, bool rc)
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;
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)
926 list = NULL;
927 // if "all" or "none"
928 if (!strcasecmp (mcmd, Command::ALL_CMD))
930 got_compcom_bits = true;
931 ck_compcom_bits = CCMV_ALL;
932 continue;
934 else if (!strcasecmp (mcmd, Command::NONE_CMD))
936 got_compcom_bits = true;
937 ck_compcom_bits = 0;
938 continue;
941 // Find parameter after '='
942 param = strchr (mcmd, '=');
943 if (param)
945 *param = '\0';
946 param++;
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))
955 if (got) // Ambiguous comp_com command
956 status = CMD_AMBIGUOUS;
957 else
959 got = true;
960 flag = comp_vis[i];
961 // Check argument
962 if (flag == COMP_THRESHOLD)
964 if (param == NULL)
965 status = CMD_BAD_ARG;
966 else
968 value = (int) strtol (param, &param, 10);
969 if (value < 0 || value > 100)
970 status = CMD_OUTRANGE;
973 else if (param != NULL)
974 status = CMD_BAD_ARG;
978 // Not valid comp_com command
979 if (!got)
980 status = CMD_INVALID;
981 if (status != CMD_OK)
983 if (!rc)
984 return status;
985 continue;
988 // Set bits
989 switch (flag)
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;
1033 // No error, update
1034 if (got_compcom_bits)
1036 if (isSrc)
1037 src_compcom = ck_compcom_bits;
1038 else
1039 dis_compcom = ck_compcom_bits;
1041 if (got_threshold)
1043 if (isSrc)
1044 threshold_src = ck_threshold;
1045 else
1046 threshold_dis = ck_threshold;
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;
1057 // Process a threshold setting
1058 Cmd_status
1059 Settings::proc_thresh (char *cmd, bool isSrc, bool rc)
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)
1068 if (!rc)
1069 return CMD_OUTRANGE;
1070 value = DEFAULT_SRC_DIS_THRESHOLD;
1072 if (isSrc)
1073 threshold_src = value;
1074 else
1075 threshold_dis = value;
1076 return CMD_OK;
1079 // return any error string from processing visibility settings
1080 char *
1081 Settings::get_compcom_errstr (Cmd_status status, const char *cmd)
1083 int i;
1084 StringBuilder sb;
1085 switch (status)
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;
1105 if (cmd)
1106 sb.append (cmd);
1107 sb.append (GTXT ("\nAvailable commentary classes: "));
1108 for (i = 0; i < comp_size; i++)
1110 sb.append (comp_cmd[i]);
1111 if (i == comp_size - 1)
1112 sb.append (NTXT ("=#\n"));
1113 else
1114 sb.append (NTXT (":"));
1116 return sb.toString ();
1119 // Process a timeline-mode setting
1120 Cmd_status
1121 Settings::proc_tlmode (char *cmd, bool rc)
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)
1138 list = NULL;
1140 // Find parameter after '='
1141 param = strchr (mcmd, '=');
1142 if (param)
1144 *param = '\0';
1145 param++;
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++)
1154 if (!strncasecmp (mcmd, tlmode_cmd[i].cmdText, len))
1156 if (got) // Ambiguous timeline mode
1157 status = CMD_AMBIGUOUS;
1158 else
1160 got = true;
1161 cmd_type = tlmode_cmd[i].cmdType;
1162 cmd_id = tlmode_cmd[i].cmdId;
1164 // Check argument
1165 if (cmd_type == TLCMD_DEPTH)
1167 if (param == NULL)
1168 status = CMD_BAD_ARG;
1169 else
1171 value = (int) strtol (param, &param, 10);
1172 if (value <= 0 || value > 256)
1173 status = CMD_OUTRANGE;
1176 else if (param != NULL)
1177 status = CMD_BAD_ARG;
1182 // Not valid timeline mode
1183 if (!got)
1184 status = CMD_INVALID;
1185 if (status != CMD_OK)
1187 if (!rc)
1188 return status;
1189 continue;
1192 // Set bits
1193 switch (cmd_type)
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;
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;
1222 // Process timeline data specification
1223 Cmd_status
1224 Settings::proc_tldata (const char *cmd, bool /* if true, ignore any error */)
1226 free (tldata);
1227 tldata = dbe_strdup (cmd); // let GUI parse it
1228 return CMD_OK;
1231 void
1232 Settings::set_tldata (const char* _tldata_str)
1234 free (tldata);
1235 tldata = dbe_strdup (_tldata_str);
1238 char*
1239 Settings::get_tldata ()
1241 return dbe_strdup (tldata);
1244 Cmd_status
1245 Settings::set_name_format (char *arg)
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;
1259 bool soname_fmt = false;
1260 if (colon)
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;
1270 name_format = Histable::make_fmt (fname_fmt, soname_fmt);
1271 return CMD_OK;
1274 void
1275 Settings::buildMasterTabList ()
1277 tab_list = new Vector<DispTab*>;
1278 int i = -1;
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));
1301 // Update tablist based on data availability
1302 void
1303 Settings::updateTabAvailability ()
1305 int index;
1306 DispTab *dsptab;
1308 Vec_loop (DispTab*, tab_list, index, dsptab)
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 ());
1334 // Process a tab setting
1335 Cmd_status
1336 Settings::proc_tabs (bool _rdtMode)
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)
1348 if (str_rtabs == NULL)
1349 str_rtabs = strdup ("header");
1350 cmd = str_rtabs;
1352 else
1354 if (str_tabs == NULL)
1355 str_tabs = strdup ("header");
1356 cmd = str_tabs;
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++)
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)
1368 // set the bit for this subtype
1369 indx_tab_state->store (cparam, true);
1370 indx_tab_order->store (cparam, count++);
1372 else
1374 // search for this tab type in the regular tabs
1375 Vec_loop (DispTab*, tab_list, index, dsptab)
1377 if (dsptab->cmdtoken == c)
1379 dsptab->visible = true;
1380 dsptab->order = count++;
1381 break;
1385 free (tabname);
1387 delete tokens;
1388 return CMD_OK;
1391 void
1392 Settings::set_MemTabState (Vector<bool>*selected)
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));
1400 // define a new memory object type
1402 void
1403 Settings::mobj_define (MemObjType_t */* mobj */, bool state)
1405 if (mem_tab_state->size () == 0)
1406 state = true;
1407 mem_tab_state->append (state);
1408 mem_tab_order->append (-1);
1411 void
1412 Settings::set_IndxTabState (Vector<bool>*selected)
1414 for (int j = 0; j < selected->size (); j++)
1415 indx_tab_state->store (j, selected->fetch (j));
1418 // define a new index object type
1419 void
1420 Settings::indxobj_define (int type, bool state)
1422 indx_tab_state->store (type, state);
1423 indx_tab_order->store (type, -1);
1426 void
1427 Settings::set_pathmaps (Vector<pathmap_t*> *newPathMap)
1429 if (pathmaps)
1431 pathmaps->destroy ();
1432 delete pathmaps;
1434 pathmaps = newPathMap;
1437 static char *
1438 get_canonical_name (const char *fname)
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;
1446 char *
1447 Settings::add_pathmap (Vector<pathmap_t*> *v, const char *from, const char *to)
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);
1457 // Check the pathmap list
1458 for (int i = 0, sz = v->size (); i < sz; i++)
1460 pathmap_t *pmp = v->get (i);
1461 if ((strcmp (pmp->old_prefix, old_prefix) == 0) &&(strcmp (pmp->new_prefix, new_prefix) == 0))
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;
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;
1477 // Set all shared object expands back to .rc file defaults,
1478 // as stored in the DbeSession Settings
1479 bool
1480 Settings::set_libdefaults ()
1482 // See if this is unchanged
1483 if (is_loexpand_default == true)
1484 return false; // no change
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)
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);
1499 is_loexpand_default = true;
1500 return true;
1503 bool
1504 Settings::set_libexpand (char *cov, enum LibExpand expand, bool rc)
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)
1514 lo_expand_default = expand;
1515 change = true;
1516 is_loexpand_default = false;
1519 // and force any explicit settings to match, too
1520 Vec_loop (lo_expand_t*, lo_expands, index, loe)
1522 if (loe->expand != expand)
1524 loe->expand = expand;
1525 change = true;
1526 is_loexpand_default = false;
1531 else
1532 { // parsing coverage
1533 Vector <char *> *tokens = split_str (cov, ',');
1534 for (long j = 0, sz = VecSize (tokens); j < sz; j++)
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)
1541 if (strcmp (loe->libname, newname) == 0)
1543 if (loe->expand != expand)
1545 if (rc == false)
1547 loe->expand = expand;
1548 change = true;
1549 is_loexpand_default = false;
1552 found = true;
1553 break;
1557 if (found == false)
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;
1567 // add it to the vector
1568 lo_expands->append (thisloe);
1570 free (lo_name);
1572 delete tokens;
1574 return change;
1577 enum LibExpand
1578 Settings::get_lo_setting (char *name)
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)
1585 if (strcmp (loe->libname, lo_name) == 0)
1586 return loe->expand;
1588 return lo_expand_default;