]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/MetricList.cc
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
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)
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. */
24 #include "DbeSession.h"
25 #include "MetricList.h"
26 #include "StringBuilder.h"
28 // Build a metric reference list
29 MetricList::MetricList (Vector
<BaseMetric
*> *base_metrics
, MetricType _mtype
)
32 items
= new Vector
<Metric
*>;
37 // loop over the base_metrics, and add in all the appropriate subtypes
38 for (long i
= 0, sz
= base_metrics
? base_metrics
->size () : 0; i
< sz
; i
++)
40 BaseMetric
*mtr
= base_metrics
->get (i
);
41 if (mtr
->is_internal ())
46 if ((mtr
->get_flavors () & BaseMetric::DATASPACE
) != 0)
48 mitem
= new Metric (mtr
, BaseMetric::DATASPACE
);
49 items
->append (mitem
);
55 if ((mtr
->get_flavors () & BaseMetric::INCLUSIVE
) != 0
56 || (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) != 0)
61 Vec_loop (Metric
*, items
, index2
, item2
)
63 if (item2
->get_subtype () == BaseMetric::EXCLUSIVE
64 && dbe_strcmp (item2
->get_cmd (), mtr
->get_cmd ()) == 0)
72 mitem
= new Metric (mtr
, BaseMetric::EXCLUSIVE
);
73 items
->append (mitem
);
81 if ((mtr
->get_flavors () & BaseMetric::ATTRIBUTED
) != 0)
83 mitem
= new Metric (mtr
, BaseMetric::ATTRIBUTED
);
84 items
->append (mitem
);
86 // now fall through to add exclusive and inclusive
90 if (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
)
92 mitem
= new Metric (mtr
, BaseMetric::EXCLUSIVE
);
93 items
->append (mitem
);
95 if (mtr
->get_flavors () & BaseMetric::INCLUSIVE
)
97 mitem
= new Metric (mtr
, BaseMetric::INCLUSIVE
);
98 items
->append (mitem
);
102 if (mtr
->get_flavors () & BaseMetric::INCLUSIVE
)
104 mitem
= new Metric (mtr
, BaseMetric::INCLUSIVE
);
105 items
->append (mitem
);
110 if (mtr
->get_packet_type () == DATA_IOTRACE
111 && ((mtr
->get_flavors () & BaseMetric::INCLUSIVE
) != 0
112 || (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) != 0))
115 Metric
*item2
= NULL
;
117 Vec_loop (Metric
*, items
, index2
, item2
)
119 if (item2
->get_subtype () == BaseMetric::EXCLUSIVE
120 && dbe_strcmp (item2
->get_cmd (), mtr
->get_cmd ()) == 0)
128 mitem
= new Metric (mtr
, BaseMetric::EXCLUSIVE
);
129 items
->append (mitem
);
136 if (mtr
->get_packet_type () == DATA_HEAP
137 && ((mtr
->get_flavors () & BaseMetric::INCLUSIVE
) != 0
138 || (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) != 0))
141 Metric
*item2
= NULL
;
143 Vec_loop (Metric
*, items
, index2
, item2
)
145 if ((item2
->get_subtype () == BaseMetric::EXCLUSIVE
) &&
146 (dbe_strcmp (item2
->get_cmd (), mtr
->get_cmd ()) == 0))
154 mitem
= new Metric (mtr
, BaseMetric::EXCLUSIVE
);
155 items
->append (mitem
);
163 if (mtr
->get_flavors () & BaseMetric::STATIC
)
172 mitem
= new Metric (mtr
, BaseMetric::STATIC
);
173 items
->append (mitem
);
176 if (mtr
->get_type () == BaseMetric::ONAME
)
178 mitem
= new Metric (mtr
, BaseMetric::STATIC
);
179 items
->append (mitem
);
185 // set all metrics visible
186 for (long i
= 0, sz
= items
? items
->size () : 0; i
< sz
; i
++)
187 items
->get (i
)->enable_all_visbits ();
190 // Constructor for an empty list -- items will be added one at a time
191 MetricList::MetricList (MetricType _mtype
)
194 items
= new Vector
<Metric
*>;
196 sort_reverse
= false;
199 MetricList::~MetricList ()
204 // Duplicate a metric list
205 MetricList::MetricList (MetricList
*old
)
209 // get an empty vector
210 items
= new Vector
<Metric
*>;
214 sort_ref_index
= old
->get_sort_ref_index ();
215 sort_reverse
= old
->get_sort_rev ();
216 Vec_loop (Metric
*, old
->items
, index
, item
)
218 nitem
= new Metric (*item
);
219 items
->append (nitem
);
224 // Sets the particular metric list, according to the metric spec
225 // If fromRcFile, updates dbeSession->get_reg_metrics_tree() with new defaults.
227 MetricList::set_metrics (const char *mspec
, bool fromRcFile
,
228 DerivedMetrics
* /* derived_metrics */)
230 BaseMetric::SubType subtypes
[10];
232 int dmetrics_vis
; // literal translation of metrics/dmetrics %.+
233 bool parseOK
= false;
235 Vector
<Metric
*> *old_items
= items
;
236 items
= new Vector
<Metric
*>;
237 Vector
<BaseMetric
*> *base_items
= dbeSession
->get_base_reg_metrics ();
239 // and copy the input specification
240 char *buf
= dbe_strdup (mspec
);
242 // append metric items from parsing the string
243 for (char *mcmd
= strtok (buf
, NTXT (":")); mcmd
!= NULL
;
244 mcmd
= strtok (NULL
, NTXT (":")))
246 // parse the single metric_spec, based on the type of list being constructed, into:
247 // a vector of SubTypes (any of [iead] or STATIC)
248 // a integer mask for the visibility bits
249 // and the string name of the base metric
250 // it might be "all", "any", or "hwc" or it should match a metric in the list
251 // it might also be "bit", meaning any bit-computed metric
252 char *mname
= parse_metric_spec (mcmd
, subtypes
, &nsubtypes
,
253 &dmetrics_vis
, &parseOK
);
256 // error parsing the metric specification
257 // not from an rc file, it's an error
270 // loop over subtypes requested
271 // set the visibility of and sort order according to the vis bits,
272 // and the order of encounter in the processing
273 int ret
= add_matching_dmetrics (base_items
, mname
, subtypes
, nsubtypes
,
274 dmetrics_vis
, fromRcFile
);
275 if (ret
!= 0 && !fromRcFile
)
278 errbuf
= dbe_sprintf (GTXT ("No data recorded to support metric specification: %s\n"),
281 errbuf
= dbe_sprintf (GTXT ("Metric specification for `%s' has appeared before in %s"),
290 } // we've processed the entire spec
292 // update metric defaults
295 for (long i
= 0, sz
= items
->size (); i
< sz
; i
++)
297 Metric
*m
= items
->get (i
);
298 int visbits
= m
->get_visbits ();
299 BaseMetric::SubType subtype
= m
->get_subtype ();
300 BaseMetric
*reg_bm
= m
->get_base_metric ();
301 reg_bm
->set_default_visbits (subtype
, visbits
);
302 BaseMetricTreeNode
*mtree
= dbeSession
->get_reg_metrics_tree ();
303 BaseMetricTreeNode
*bmtnode
= mtree
->register_metric (m
);
304 BaseMetric
*tree_bm
= bmtnode
->get_BaseMetric ();
305 tree_bm
->set_default_visbits (subtype
, visbits
);
309 // ensure that name is present, remove hidden metrics
311 for (long i
= items
->size () - 1; i
>= 0; i
--)
313 Metric
*m
= items
->fetch (i
);
314 if (!m
->is_any_visible ())
320 if (m
->get_type () == BaseMetric::ONAME
)
324 // did we get at least one valid match?
325 if (items
->size () == 0 && !fromRcFile
)
327 errbuf
= dbe_sprintf (GTXT ("No valid metrics specified in `%s'\n"), mspec
);
338 subtypes
[0] = BaseMetric::STATIC
;
339 (void) add_matching_dmetrics (base_items
, NTXT ("name"), subtypes
, 1, VAL_VALUE
, true);
342 // replace the old list of items, with the new set
345 old_items
->destroy ();
348 set_fallback_sort ();
355 MetricList::set_fallback_sort ()
357 // sort by first visible of the appropriate flavor
358 char *sortcmd
= NULL
;
363 sortcmd
= NTXT ("ei.any:name");
366 sortcmd
= NTXT ("i.any:name");
370 sortcmd
= NTXT ("a.any:name");
373 sortcmd
= NTXT ("d.any:name");
376 sortcmd
= NTXT ("e.any:name");
379 sortcmd
= NTXT ("e.any:name");
382 sortcmd
= NTXT ("e.any:name");
386 (void) set_sort (sortcmd
, true);
390 MetricList::set_metrics (MetricList
*mlist
)
392 // verify that the type is appropriate for the call
393 if (mtype
== MET_NORMAL
|| mtype
== MET_COMMON
394 || (mlist
->mtype
!= MET_NORMAL
&& mlist
->mtype
!= MET_COMMON
))
397 Vector
<Metric
*> *mlist_items
= mlist
->get_items ();
401 int sort_ind
= mlist
->get_sort_ref_index ();
402 for (int i
= 0, mlist_sz
= mlist_items
->size (); i
< mlist_sz
; i
++)
404 Metric
*mtr
= mlist_items
->fetch (i
);
405 if (!mtr
->is_any_visible ())
408 // Add a new Metric with probably a new sub_type to this->items:
409 // for MET_CALL and MET_CALL_AGR the matching entry to an e. or i. is itself
410 // for MET_DATA, the matching entry to an e. or i. is the d. metric
411 // for MET_INDX, the matching entry to an e. or i. is the e. metric
412 // for MET_IO, the matching entry to an e. or i. is the e. metric
413 // for MET_HEAP, the matching entry to an e. or i. is the e. metric
414 // Save static entries (SIZES and ADDRESS) only for MET_NORMAL, MET_CALL, MET_CALL_AGR, MET_SRCDIS
415 switch (mtr
->get_type ())
417 case BaseMetric::SIZES
:
418 case BaseMetric::ADDRESS
:
435 BaseMetric::SubType st
= mtr
->get_subtype ();
436 if (st
!= BaseMetric::STATIC
)
438 if (mtype
== MET_CALL
|| mtype
== MET_CALL_AGR
)
440 if ((mtr
->get_flavors () & BaseMetric::ATTRIBUTED
) == 0)
442 st
= BaseMetric::ATTRIBUTED
;
444 else if (mtype
== MET_DATA
)
446 if ((mtr
->get_flavors () & BaseMetric::DATASPACE
) == 0)
448 st
= BaseMetric::DATASPACE
;
450 else if (mtype
== MET_INDX
)
452 if ((mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) == 0)
454 st
= BaseMetric::EXCLUSIVE
;
456 else if (mtype
== MET_IO
)
458 if (mtr
->get_packet_type () != DATA_IOTRACE
||
459 (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) == 0)
461 st
= BaseMetric::EXCLUSIVE
;
463 else if (mtype
== MET_HEAP
)
465 if (mtr
->get_packet_type () != DATA_HEAP
||
466 (mtr
->get_flavors () & BaseMetric::EXCLUSIVE
) == 0)
468 st
= BaseMetric::EXCLUSIVE
;
470 else if (mtype
== MET_SRCDIS
)
472 if ((mtr
->get_flavors () & BaseMetric::INCLUSIVE
) == 0)
474 st
= BaseMetric::INCLUSIVE
;
479 for (int i1
= 0, items_sz
= items
->size (); i1
< items_sz
; i1
++)
481 Metric
*m1
= items
->fetch (i1
);
482 if (mtr
->get_id () == m1
->get_id () && st
== m1
->get_subtype ())
492 Metric
*m
= new Metric (*mtr
);
494 m
->set_raw_visbits (mtr
->get_visbits ());
496 sort_ind
= items
->size ();
499 if (sort_ind
>= items
->size ())
503 if (mtype
== MET_HEAP
)
505 sort_ref_index
= sort_ind
;
511 // Sets the sort for the metric list to the first metric
512 // in mspec that is present; if fromRcFile is false, then
513 // only one metric may be specified. The requested sort
514 // metric must be visible, or it won't be in the metric list
517 MetricList::set_sort (const char *mspec
, bool fromRcFile
)
520 BaseMetric::SubType subtypes
[10];
523 bool parseOK
= false;
524 bool reverse
= false;
529 // copy the input specification
530 snprintf (buf
, sizeof (buf
), NTXT ("%s"), mspec
);
534 // reverse sort specified
539 // search for metric items from parsing the string
540 while ((mcmd
= strtok (listp
, NTXT (":"))) != NULL
)
542 listp
= NULL
; // let strtok keep track
544 // parse the single metric_spec, based on the type of list being constructed, into:
545 // a vector of SubTypes (any of [iead] or STATIC)
546 // a integer mask for the visibility bits
547 // and the string name of the base metric
548 mname
= parse_metric_spec (mcmd
, subtypes
, &nsubtypes
, &vis
, &parseOK
);
551 // error parsing the metric specification
552 // not from an rc file, it's an error
557 if (VAL_IS_HIDDEN (vis
))
560 // loop over subtypes requested to find metric
561 // add a metric of that subtype, with specified vis.bits
562 for (int i
= 0; i
< nsubtypes
; i
++)
564 // make sure the subtype is acceptable
565 if ((mtype
== MET_CALL
|| mtype
== MET_CALL_AGR
)
566 && subtypes
[i
] != BaseMetric::ATTRIBUTED
567 && subtypes
[i
] != BaseMetric::STATIC
)
568 return dbe_sprintf (GTXT ("Inclusive, Exclusive, or Data metrics cannot be specified for caller-callee sort: %s\n"),
570 if (mtype
== MET_DATA
&& subtypes
[i
] != BaseMetric::DATASPACE
571 && subtypes
[i
] != BaseMetric::STATIC
)
572 return dbe_sprintf (GTXT ("Inclusive, Exclusive, or Attributed metrics cannot be specified for data-derived sort: %s\n"),
574 if (mtype
== MET_INDX
&& subtypes
[i
] != BaseMetric::EXCLUSIVE
575 && subtypes
[i
] != BaseMetric::STATIC
)
576 return dbe_sprintf (GTXT ("Inclusive, Data or Attributed metrics cannot be specified for index sort: %s\n"),
578 if ((mtype
== MET_NORMAL
|| mtype
== MET_COMMON
579 || mtype
== MET_SRCDIS
)
580 && (subtypes
[i
] == BaseMetric::DATASPACE
581 || subtypes
[i
] == BaseMetric::ATTRIBUTED
))
582 return dbe_sprintf (GTXT ("Data or Attributed metrics cannot be specified for sort: %s\n"), mcmd
);
583 if (set_sort_metric (mname
, subtypes
[i
], reverse
))
586 // continue looking at entries
589 // not found on the list at all
595 return dbe_sprintf (GTXT ("Invalid sort specification: %s\n"), mspec
);
598 return dbe_sprintf (GTXT ("Invalid caller-callee sort specification: %s\n"),
601 return dbe_sprintf (GTXT ("Invalid data-derived sort specification: %s\n"),
604 return dbe_sprintf (GTXT ("Invalid index sort specification: %s\n"),
607 return dbe_sprintf (GTXT ("Invalid I/O sort specification: %s\n"), mspec
);
609 return dbe_sprintf (GTXT ("Invalid heap sort specification: %s\n"),
615 // set_sort to the metric with the given visible index
618 MetricList::set_sort (int visindex
, bool reverse
)
621 if (visindex
< items
->size ())
623 mitem
= items
->fetch (visindex
);
624 if (mitem
->is_any_visible ())
626 sort_ref_index
= visindex
;
627 sort_reverse
= reverse
;
631 set_fallback_sort ();
635 MetricList::set_sort_metric (char *mname
, BaseMetric::SubType mst
, bool reverse
)
637 bool any
= false, hwc
= false, bit
= false;
639 // check keywords 'any', 'all', 'bit' and 'hwc'
640 if (!strcasecmp (mname
, Command::ANY_CMD
))
642 else if (!strcasecmp (mname
, Command::ALL_CMD
))
644 else if (!strcasecmp (mname
, Command::HWC_CMD
))
646 else if (!strcasecmp (mname
, Command::BIT_CMD
))
649 for (int i
= 0, items_sz
= items
->size (); i
< items_sz
; i
++)
651 Metric
*m
= items
->fetch (i
);
652 if (mst
== m
->get_subtype ()
653 && (any
|| (hwc
&& m
->get_type () == BaseMetric::HWCNTR
)
654 || (bit
&& m
->get_cmd ()
655 && strncmp (Command::BIT_CMD
, m
->get_cmd (),
656 strlen (Command::BIT_CMD
)) == 0)
657 || dbe_strcmp (mname
, m
->get_cmd ()) == 0))
660 sort_reverse
= reverse
;
667 // Print to a file of a list of metrics from a supplied vector
668 // Debug flag = 1, prints the short name and address of the list
669 // Debug flag = 2, prints the details of the list
671 MetricList::print_metric_list (FILE *dis_file
, char *leader
, int debug
)
676 fprintf (dis_file
, NTXT ("%s"), leader
);
679 fprintf (dis_file
, GTXT ("NULL metric list can not be printed; aborting"));
683 if (items
->size () == 0)
685 fprintf (dis_file
, GTXT ("metric list is empty; aborting\n"));
689 // if debugging, print list address and string, and sort name
692 char *s
= get_metrics ();
693 fprintf (dis_file
, "\tmetriclist at 0x%lx: %s, %lld metrics; sort by %s\n",
694 (unsigned long) this, s
, (long long) items
->size (),
701 // Find the longest metric name & command
705 Vec_loop (Metric
*, items
, index
, item
)
708 char *mn
= item
->get_name ();
709 size_t len
= strlen (mn
);
713 mn
= item
->get_mcmd (true);
721 snprintf (fmt_name
, sizeof (fmt_name
), "%%%ds: %%-%ds", (int) max_len
,
724 snprintf (fmt_name
, sizeof (fmt_name
), "%%%ds: %%s", (int) max_len
);
726 Vec_loop (Metric
*, items
, index
, item
)
728 char *mcmd
= item
->get_mcmd (true);
729 fprintf (dis_file
, fmt_name
, item
->get_name (), mcmd
);
732 fprintf (dis_file
, "\t[st %2d, VT %d, vis = %4s, T=%d, sort = %c]",
733 item
->get_subtype (), item
->get_vtype (),
734 item
->get_vis_str (), item
->is_time_val (),
735 sort_ref_index
== index
? 'Y' : 'N');
736 fputc ('\n', dis_file
);
739 fputc ('\n', dis_file
);
743 // Return a string formatted from a vector of metrics
744 // string is in the form suitable for a "metrics <string>" command
746 MetricList::get_metrics ()
751 Vec_loop (Metric
*, items
, index
, item
)
753 if (sb
.length () != 0)
755 char *mcmd
= item
->get_mcmd (false);
759 return sb
.toString ();
763 MetricList::get_listorder (Metric
*mtr
)
765 for (int i
= 0, items_sz
= items
->size (); i
< items_sz
; i
++)
767 Metric
*m
= items
->fetch (i
);
768 if (m
->get_subtype () == mtr
->get_subtype ()
769 && m
->get_id () == mtr
->get_id ())
776 MetricList::get_listorder (char *cmd
, BaseMetric::SubType st
, const char *expr
)
778 for (long i
= 0, items_sz
= items
->size (); i
< items_sz
; i
++)
780 Metric
*m
= items
->fetch (i
);
781 if (m
->get_subtype () == st
&& dbe_strcmp (m
->get_cmd (), cmd
) == 0
782 && dbe_strcmp (m
->get_expr_spec (), expr
) == 0)
789 MetricList::find_metric_by_name (char *cmd
)
791 for (long i
= 0, items_sz
= items
->size (); i
< items_sz
; i
++)
793 Metric
*m
= items
->fetch (i
);
794 if (dbe_strcmp (m
->get_cmd (), cmd
) == 0)
800 // find a metric by name and subtype
802 MetricList::find_metric (char *cmd
, BaseMetric::SubType st
)
804 int i
= get_listorder (cmd
, st
);
807 return items
->fetch (i
);
810 // Get the sort metric from a list; forces sort by first if not set
812 MetricList::get_sort_metric ()
814 int i
= get_sort_ref_index ();
815 return i
>= 0 ? items
->fetch (i
) : NULL
;
819 MetricList::get_sort_name ()
821 Metric
*item
= get_sort_metric ();
823 return dbe_strdup (NTXT (""));
824 char *n
= item
->get_name ();
825 return sort_reverse
? dbe_sprintf ("-%s", n
) : dbe_strdup (n
);
829 MetricList::get_sort_cmd ()
832 Metric
*item
= get_sort_metric ();
834 return dbe_strdup (NTXT (""));
835 char *n
= item
->get_mcmd (false);
838 buf
= dbe_sprintf (NTXT ("-%s"), n
);
847 MetricList::append (BaseMetric
*bm
, BaseMetric::SubType st
, int visbits
)
849 for (long i
= 0, sz
= items
->size (); i
< sz
; i
++)
851 Metric
*m
= items
->get (i
);
852 if (m
->get_id () == bm
->get_id () && m
->get_subtype () == st
)
855 Metric
*met
= new Metric (bm
, st
);
856 met
->set_dmetrics_visbits (visbits
);
862 MetricList::add_matching_dmetrics (Vector
<BaseMetric
*> *base_items
,
863 char *mcmd
, BaseMetric::SubType
*_subtypes
,
864 int nsubtypes
, int dmetrics_visbits
,
867 bool any
= false, hwc
= false, bit
= false;
870 // check keywords 'any', 'all', 'bit', and 'hwc'
871 if (!strcasecmp (mcmd
, Command::ANY_CMD
))
873 else if (!strcasecmp (mcmd
, Command::ALL_CMD
))
875 else if (!strcasecmp (mcmd
, Command::HWC_CMD
))
877 else if (!strcasecmp (mcmd
, Command::BIT_CMD
))
880 BaseMetric::SubType
*subtypes
= _subtypes
;
881 BaseMetric::SubType all_subtypes
[2] =
882 { BaseMetric::EXCLUSIVE
, BaseMetric::INCLUSIVE
};
884 if (nsubtypes
== 0 || (nsubtypes
== 1 && subtypes
[0] == BaseMetric::STATIC
))
886 // user did not specify ei; treat as wildcard and supply both.
887 subtypes
= all_subtypes
;
891 // scan the metrics to find all matches
892 for (int i
= 0, base_sz
= base_items
->size (); i
< base_sz
; i
++)
894 BaseMetric
*item
= base_items
->fetch (i
);
895 if (!(any
|| (hwc
&& item
->get_type () == BaseMetric::HWCNTR
)
896 || (bit
&& item
->get_cmd ()
897 && strncmp (item
->get_cmd (), Command::BIT_CMD
,
898 strlen (Command::BIT_CMD
)) == 0)
899 || dbe_strcmp (item
->get_cmd (), mcmd
) == 0))
901 if (item
->is_internal ())
903 if (item
->get_flavors () & BaseMetric::STATIC
)
906 int vis
= item
->get_type () != BaseMetric::ONAME
?
907 dmetrics_visbits
: VAL_VALUE
;
908 if (append (item
, BaseMetric::STATIC
, vis
) == NULL
&& !fromRcFile
)
913 // special case for omp metrics: make visible only if
914 // omp data has been collected
915 if (!dbeSession
->is_omp_available ()
916 && (strcasecmp (mcmd
, "ompwork") == 0
917 || strcasecmp (mcmd
, "ompwait") == 0))
920 for (int j
= 0; j
< nsubtypes
; j
++)
922 if (append (item
, subtypes
[j
], dmetrics_visbits
) == NULL
927 if (!(any
|| hwc
|| bit
))
933 // parse a single metric specification, to give:
934 // a vector of subtypes, and a count of the number of them
935 // an integer visibility
936 // return the string for the metric name
939 MetricList::parse_metric_spec (char *mcmd
, BaseMetric::SubType
*subtypes
,
940 int *nsubtypes
, int *dmetrics_visb
, bool *isOK
)
945 bool got_e
, got_i
, got_a
, got_d
;
951 // For dynamic metrics, each keyword is of the form <flavor><visibility><metric-name>
952 // For static metrics, each keyword is of the form [<visibility>]<metric-name>
953 // <flavor> can be either "i" for inclusive or "e" for exclusive
954 // <visibility> can be any combination of "." (to show the metric as a time),
955 // "%" (to show it as a percentage), "+" (to show it as a count), and "!" (turn off the metric)
959 size_t len_subtype
= strspn (str
, NTXT ("eiad"));
960 str2
= str
+ len_subtype
;
963 if (len_subtype
== 0)
965 // only a . or ! is possible if no subtypes
966 len_vtype
= strspn (str2
, NTXT (".!"));
971 len_vtype
= strspn (str2
, NTXT (".+%!"));
975 // if no visibility bits, there can't be a subtype
979 if (len_subtype
== 0)
981 // must be a static metric
982 subtypes
[index
++] = BaseMetric::STATIC
;
987 // figure out which subtypes are specified
988 got_e
= got_i
= got_a
= got_d
= false;
989 for (size_t i
= 0; i
< len_subtype
; i
++)
994 if (mtype
== MET_DATA
)
997 return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for data metrics\n"),
1003 subtypes
[index
++] = BaseMetric::EXCLUSIVE
;
1006 else if (mcmd
[i
] == 'i')
1008 if (mtype
== MET_DATA
)
1011 return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for data metrics\n"),
1014 if (mtype
== MET_INDX
)
1017 return dbe_sprintf (GTXT ("Invalid metric specification: %s inapplicable for index metrics\n"),
1023 subtypes
[index
++] = BaseMetric::INCLUSIVE
;
1026 else if (mcmd
[i
] == 'a')
1028 if (mtype
!= MET_CALL
&& mtype
!= MET_CALL_AGR
)
1031 return dbe_sprintf (GTXT ("Invalid metric specification: %s applicable for caller-callee metrics only\n"),
1037 subtypes
[index
++] = BaseMetric::ATTRIBUTED
;
1040 else if (mcmd
[i
] == 'd')
1042 if (mtype
!= MET_DATA
)
1045 return dbe_sprintf (GTXT ("Invalid metric specification: %s applicable for data-derived metrics only\n"),
1051 subtypes
[index
++] = BaseMetric::DATASPACE
;
1058 // now determine the visiblity bits
1061 for (size_t i
= 0; i
< len_vtype
; i
++)
1064 vis
= (vis
| VAL_VALUE
);
1065 else if (str2
[i
] == '.')
1066 vis
= (vis
| VAL_TIMEVAL
);
1067 else if (str2
[i
] == '%')
1068 vis
= (vis
| VAL_PERCENT
);
1069 else if (str2
[i
] == '!')
1070 vis
= (vis
| VAL_HIDE_ALL
);
1073 *dmetrics_visb
= vis
;
1074 return mcmd
+ len_subtype
+ len_vtype
;