#include "diagnostic-format-text.h"
#include "diagnostic-output-file.h"
#include "diagnostic-buffer.h"
+#include "diagnostic-path.h"
+#include "diagnostic-client-data-hooks.h"
#include "selftest.h"
#include "selftest-diagnostic.h"
#include "pretty-print-format-impl.h"
}
private:
+ void
+ add_stylesheet (std::string url);
+
std::unique_ptr<xml::element>
make_element_for_diagnostic (const diagnostic_info &diagnostic,
- diagnostic_t orig_diag_kind);
+ diagnostic_t orig_diag_kind,
+ bool alert);
std::unique_ptr<xml::element>
make_metadata_element (label_text label,
label_text url);
+ void
+ add_at_nesting_level (size_t nesting_level,
+ std::unique_ptr<xml::element> child_diag_element);
+
+ void
+ push_nesting_level ();
+
+ void
+ pop_nesting_level ();
+
diagnostic_context &m_context;
pretty_printer *m_printer;
const line_maps *m_line_maps;
html_generation_options m_html_gen_opts;
+ const logical_location_manager *m_logical_loc_mgr;
std::unique_ptr<xml::document> m_document;
xml::element *m_head_element;
xml::element *m_title_element;
xml::element *m_diagnostics_element;
std::unique_ptr<xml::element> m_cur_diagnostic_element;
+ std::vector<xml::element *> m_cur_nesting_levels;
int m_next_diag_id; // for handing out unique IDs
json::array m_ui_focus_ids;
+ logical_location m_last_logical_location;
+ location_t m_last_location;
+ expanded_location m_last_expanded_location;
};
static std::unique_ptr<xml::element>
" .ruler { color: red;\n"
" white-space: pre; }\n"
" .source { color: blue;\n"
+ " background-color: white;\n"
" white-space: pre; }\n"
" .annotation { color: green;\n"
+ " background-color: white;\n"
" white-space: pre; }\n"
" .linenum-gap { text-align: center;\n"
" border-top: 1px solid black;\n"
" font-weight: bold; }\n"
" .highlight-b { color: #3f9c35;\n" // pf-green-400
" font-weight: bold; }\n"
+ " .gcc-quoted-text { font-weight: bold;\n"
+ " font-family: mono; }\n"
" </style>\n");
/* A little JavaScript for ease of navigation.
m_printer (&pp),
m_line_maps (line_maps),
m_html_gen_opts (html_gen_opts),
+ m_logical_loc_mgr (nullptr),
m_head_element (nullptr),
m_title_element (nullptr),
m_diagnostics_element (nullptr),
- m_next_diag_id (0)
+ m_next_diag_id (0),
+ m_last_location (UNKNOWN_LOCATION),
+ m_last_expanded_location ({})
{
gcc_assert (m_line_maps);
+ if (auto client_data_hooks = context.get_client_data_hooks ())
+ m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
+
m_document = std::make_unique<xml::document> ();
m_document->m_doctypedecl = std::make_unique<html_doctypedecl> ();
{
xml::auto_print_element title (xp, "title", true);
m_title_element = xp.get_insertion_point ();
}
+
if (m_html_gen_opts.m_css)
- xp.add_raw (HTML_STYLE);
+ {
+ add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly.min.css");
+ add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly-additions.min.css");
+ xp.add_raw (HTML_STYLE);
+ }
if (m_html_gen_opts.m_javascript)
{
xp.push_tag ("script");
}
}
+void
+html_builder::add_stylesheet (std::string url)
+{
+ gcc_assert (m_head_element);
+
+ xml::printer xp (*m_head_element);
+ xp.push_tag ("link", false);
+ xp.set_attr ("rel", "stylesheet");
+ xp.set_attr ("type", "text/css");
+ xp.set_attr ("href", std::move (url));
+}
+
/* Implementation of "on_report_diagnostic" for HTML output. */
void
fnotice (stderr, "Internal compiler error:\n");
}
+ const int nesting_level = m_context.get_diagnostic_nesting_level ();
+ bool alert = true;
+ if (m_cur_diagnostic_element && nesting_level > 0)
+ alert = false;
+ if (!m_cur_diagnostic_element)
+ m_last_logical_location = logical_location ();
auto diag_element
- = make_element_for_diagnostic (diagnostic, orig_diag_kind);
+ = make_element_for_diagnostic (diagnostic, orig_diag_kind, alert);
if (buffer)
{
gcc_assert (!m_cur_diagnostic_element);
else
{
if (m_cur_diagnostic_element)
- /* Nested diagnostic. */
- m_cur_diagnostic_element->add_child (std::move (diag_element));
+ {
+ /* Nested diagnostic. */
+ gcc_assert (nesting_level >= 0);
+ add_at_nesting_level (nesting_level, std::move (diag_element));
+ }
else
/* Top-level diagnostic. */
- m_cur_diagnostic_element = std::move (diag_element);
+ {
+ m_cur_diagnostic_element = std::move (diag_element);
+ m_cur_nesting_levels.clear ();
+ }
+ }
+}
+
+// For ease of comparison with experimental-nesting-show-levels=yes
+
+static void
+add_nesting_level_attr (xml::element &element,
+ int nesting_level)
+{
+ element.set_attr ("nesting-level", std::to_string (nesting_level));
+}
+
+void
+html_builder::
+add_at_nesting_level (size_t nesting_level,
+ std::unique_ptr<xml::element> child_diag_element)
+{
+ gcc_assert (m_cur_diagnostic_element);
+ while (nesting_level > m_cur_nesting_levels.size ())
+ push_nesting_level ();
+ while (nesting_level < m_cur_nesting_levels.size ())
+ pop_nesting_level ();
+
+ if (nesting_level > 0)
+ {
+ gcc_assert (!m_cur_nesting_levels.empty ());
+ auto current_nesting_level = m_cur_nesting_levels.back ();
+ xml::printer xp (*current_nesting_level);
+ xp.push_tag ("li");
+ add_nesting_level_attr (*xp.get_insertion_point (),
+ m_cur_nesting_levels.size ());
+ xp.append (std::move (child_diag_element));
+ xp.pop_tag ("li");
}
+ else
+ m_cur_diagnostic_element->add_child (std::move (child_diag_element));
+}
+
+void
+html_builder::push_nesting_level ()
+{
+ gcc_assert (m_cur_diagnostic_element);
+ auto new_nesting_level = std::make_unique<xml::element> ("ul", false);
+ add_nesting_level_attr (*new_nesting_level,
+ m_cur_nesting_levels.size () + 1);
+ xml::element *current_nesting_level = nullptr;
+ if (!m_cur_nesting_levels.empty ())
+ current_nesting_level = m_cur_nesting_levels.back ();
+ m_cur_nesting_levels.push_back (new_nesting_level.get ());
+ if (current_nesting_level)
+ current_nesting_level->add_child (std::move (new_nesting_level));
+ else
+ m_cur_diagnostic_element->add_child (std::move (new_nesting_level));
+}
+
+void
+html_builder::pop_nesting_level ()
+{
+ gcc_assert (m_cur_diagnostic_element);
+ m_cur_nesting_levels.pop_back ();
}
/* Custom subclass of html_label_writer.
int m_next_event_idx;
};
+/* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts */
+static const char *
+get_pf_class_for_alert_div (diagnostic_t diag_kind)
+{
+ switch (diag_kind)
+ {
+ case DK_DEBUG:
+ case DK_NOTE:
+ return "alert alert-info";
+
+ case DK_ANACHRONISM:
+ case DK_WARNING:
+ return "alert alert-warning";
+
+ case DK_ERROR:
+ case DK_SORRY:
+ case DK_ICE:
+ case DK_ICE_NOBT:
+ case DK_FATAL:
+ return "alert alert-danger";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+static const char *
+get_pf_class_for_alert_icon (diagnostic_t diag_kind)
+{
+ switch (diag_kind)
+ {
+ case DK_DEBUG:
+ case DK_NOTE:
+ return "pficon pficon-info";
+
+ case DK_ANACHRONISM:
+ case DK_WARNING:
+ return "pficon pficon-warning-triangle-o";
+
+ case DK_ERROR:
+ case DK_SORRY:
+ case DK_ICE:
+ case DK_ICE_NOBT:
+ case DK_FATAL:
+ return "pficon pficon-error-circle-o";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+static const char *
+get_label_for_logical_location_kind (enum logical_location_kind kind)
+{
+ switch (kind)
+ {
+ default:
+ gcc_unreachable ();
+ case logical_location_kind::unknown:
+ return nullptr;
+
+ /* Kinds within executable code. */
+ case logical_location_kind::function:
+ return "Function";
+ case logical_location_kind::member:
+ return "Member";
+ case logical_location_kind::module_:
+ return "Module";
+ case logical_location_kind::namespace_:
+ return "Namespace";
+ case logical_location_kind::type:
+ return "Type";
+ case logical_location_kind::return_type:
+ return "Return type";
+ case logical_location_kind::parameter:
+ return "Parameter";
+ case logical_location_kind::variable:
+ return "Variable";
+
+ /* Kinds within XML or HTML documents. */
+ case logical_location_kind::element:
+ return "Element";
+ case logical_location_kind::attribute:
+ return "Attribute";
+ case logical_location_kind::text:
+ return "Text";
+ case logical_location_kind::comment:
+ return "Comment";
+ case logical_location_kind::processing_instruction:
+ return "Processing Instruction";
+ case logical_location_kind::dtd:
+ return "DTD";
+ case logical_location_kind::declaration:
+ return "Declaration";
+
+ /* Kinds within JSON documents. */
+ case logical_location_kind::object:
+ return "Object";
+ case logical_location_kind::array:
+ return "Array";
+ case logical_location_kind::property:
+ return "Property";
+ case logical_location_kind::value:
+ return "Value";
+ }
+}
+
+static void
+add_labelled_value (xml::printer &xp,
+ std::string id,
+ std::string label,
+ std::string value,
+ bool quote_value)
+{
+ xp.push_tag ("div", true);
+ xp.set_attr ("id", id);
+ xp.push_tag ("span");
+ xp.add_text (label);
+ xp.add_text (" ");
+ xp.pop_tag ("span");
+ xp.push_tag ("span");
+ if (quote_value)
+ xp.set_attr ("class", "gcc-quoted-text");
+ xp.add_text (std::move (value));
+ xp.pop_tag ("span");
+ xp.pop_tag ("div");
+}
+
+/* Make a <div class="gcc-diagnostic"> for DIAGNOSTIC.
+
+ If ALERT is true, make it be a PatternFly alert (see
+ https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts) and
+ show severity text (e.g. "error: ").
+
+ If ALERT is false, don't show the severity text and don't show
+ the filename if it's the same as the previous diagnostic within the
+ diagnostic group. */
+
std::unique_ptr<xml::element>
html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
- diagnostic_t orig_diag_kind)
+ diagnostic_t orig_diag_kind,
+ bool alert)
{
class html_token_printer : public token_printer
{
xml::printer m_xp;
};
- auto diag_element = make_div ("gcc-diagnostic");
-
const int diag_idx = m_next_diag_id++;
std::string diag_id;
{
pp_printf (&pp, "gcc-diag-%i", diag_idx);
diag_id = pp_formatted_text (&pp);
}
- diag_element->set_attr ("id", diag_id);
// TODO: might be nice to emulate the text output format, but colorize it
- auto message_span = make_span ("gcc-message");
- std::string message_span_id (diag_id + "-message");
- message_span->set_attr ("id", message_span_id);
- add_focus_id (message_span_id);
+ /* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts
+ which has this example:
+<div class="alert alert-danger">
+ <span class="pficon pficon-error-circle-o"></span>
+ <strong>Hey there is a problem!</strong> Yeah this is really messed up and you should <a href="#" class="alert-link">know about it</a>.
+</div>
+ */
+ auto diag_element = make_div ("gcc-diagnostic");
+ diag_element->set_attr ("id", diag_id);
+ if (alert)
+ diag_element->set_attr ("class",
+ get_pf_class_for_alert_div (diagnostic.kind));
+
+ xml::printer xp (*diag_element.get ());
+ const size_t depth_within_alert_div = 1;
+
+ gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+
+ if (alert)
+ {
+ xp.push_tag_with_class ("span",
+ get_pf_class_for_alert_icon (diagnostic.kind),
+ true);
+ xp.add_text (" ");
+ xp.pop_tag ("span");
+ }
+
+ // The rest goes in the <div>...
+ gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+
+ xp.push_tag_with_class ("div", "gcc-message", true);
+ std::string message_alert_id (diag_id + "-message");
+ xp.set_attr ("id", message_alert_id);
+ add_focus_id (message_alert_id);
- xml::printer xp (*message_span.get ());
+ const size_t depth_within_message_div = depth_within_alert_div + 1;
+ gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
+
+ // Severity e.g. "warning: "
+ bool show_severity = true;
+ if (!alert)
+ show_severity = false;
+ if (show_severity)
+ {
+ xp.push_tag ("strong");
+ xp.add_text (_(get_diagnostic_kind_text (diagnostic.kind)));
+ xp.pop_tag ("strong");
+ xp.add_text (" ");
+ }
+
+ // Add the message itself:
html_token_printer tok_printer (*xp.get_insertion_point ());
m_printer->set_token_printer (&tok_printer);
pp_output_formatted_text (m_printer, m_context.get_urlifier ());
m_printer->set_token_printer (nullptr);
pp_clear_output_area (m_printer);
- diag_element->add_child (std::move (message_span));
+ // Add any metadata as a suffix to the message
if (diagnostic.metadata)
{
- diag_element->add_text (" ");
- diag_element->add_child
- (make_element_for_metadata (*diagnostic.metadata));
+ xp.add_text (" ");
+ xp.append (make_element_for_metadata (*diagnostic.metadata));
}
+ // Add any option as a suffix to the message
+
label_text option_text = label_text::take
(m_context.make_option_name (diagnostic.option_id,
orig_diag_kind, diagnostic.kind));
label_text option_url = label_text::take
(m_context.make_option_url (diagnostic.option_id));
- diag_element->add_text (" ");
+ xp.add_text (" ");
auto option_span = make_span ("gcc-option");
option_span->add_text ("[");
{
option_span->add_text (option_text.get ());
option_span->add_text ("]");
}
- diag_element->add_child (std::move (option_span));
+ xp.append (std::move (option_span));
+ }
+
+ gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
+
+ xp.pop_tag ("div");
+
+ gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+
+ /* Show any logical location. */
+ if (m_logical_loc_mgr)
+ if (auto client_data_hooks = m_context.get_client_data_hooks ())
+ if (auto logical_loc = client_data_hooks->get_current_logical_location ())
+ if (logical_loc != m_last_logical_location)
+ {
+ enum logical_location_kind kind
+ = m_logical_loc_mgr->get_kind (logical_loc);;
+ if (const char *label = get_label_for_logical_location_kind (kind))
+ if (const char *name_with_scope
+ = m_logical_loc_mgr->get_name_with_scope (logical_loc))
+ add_labelled_value (xp, "logical-location",
+ label, name_with_scope, true);
+ m_last_logical_location = logical_loc;
+ }
+
+ /* Show any physical location. */
+ const expanded_location s
+ = diagnostic_expand_location (&diagnostic);
+ if (s != m_last_expanded_location
+ || alert)
+ {
+ if (s.file
+ && (s.file != m_last_expanded_location.file
+ || alert))
+ add_labelled_value (xp, "file", "File", s.file, false);
+ if (s.line)
+ {
+ add_labelled_value (xp, "line", "Line", std::to_string (s.line), false);
+ diagnostic_column_policy column_policy (m_context);
+ int converted_column = column_policy.converted_column (s);
+ if (converted_column >= 0)
+ add_labelled_value (xp, "column", "Column",
+ std::to_string (converted_column),
+ false);
+ }
+ if (s.file)
+ m_last_expanded_location = s;
}
/* Source (and fix-it hints). */
{
- xml::printer xp (*diag_element);
- m_context.m_last_location = UNKNOWN_LOCATION;
+ // TODO: m_context.m_last_location should be moved into the sink
+ location_t saved = m_context.m_last_location;
+ m_context.m_last_location = m_last_location;
m_context.maybe_show_locus_as_html (*diagnostic.richloc,
m_context.m_source_printing,
diagnostic.kind,
xp,
nullptr,
nullptr);
+ m_context.m_last_location = saved;
+ m_last_location = m_context.m_last_location;
}
+ gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+
/* Execution path. */
if (auto path = diagnostic.richloc->get_path ())
{
- xml::printer xp (*diag_element);
+ xp.push_tag ("div");
+ xp.set_attr ("id", "execution-path");
+
+ xp.push_tag ("label", true);
+ const int num_events = path->num_events ();
+ pretty_printer pp;
+ pp_printf_n (&pp, num_events,
+ "Execution path with %i event",
+ "Execution path with %i events",
+ num_events);
+ xp.add_text_from_pp (pp);
+ xp.pop_tag ("label");
+
std::string event_id_prefix (diag_id + "-event-");
html_path_label_writer event_label_writer (xp, *this,
event_id_prefix);
diagnostic_source_print_policy dspp (m_context);
print_path_as_html (xp, *path, m_context, &event_label_writer,
dspp);
+
+ xp.pop_tag ("div");
}
+ gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+
if (auto patch_element = make_element_for_patch (diagnostic))
- diag_element->add_child (std::move (patch_element));
+ {
+ xp.push_tag ("div");
+ xp.set_attr ("id", "suggested-fix");
+ xp.push_tag ("label", true);
+ xp.add_text ("Suggested fix");
+ xp.pop_tag ("label");
+ xp.append (std::move (patch_element));
+ xp.pop_tag ("div");
+ }
return diag_element;
}
" </head>\n"
" <body>\n"
" <div class=\"gcc-diagnostic-list\">\n"
- " <div class=\"gcc-diagnostic\" id=\"gcc-diag-0\">\n"
- " <span class=\"gcc-message\" id=\"gcc-diag-0-message\">this is a test: `<span class=\"gcc-quoted-text\">foo</span>'</span>\n"
+ " <div class=\"alert alert-danger\" id=\"gcc-diag-0\">\n"
+ " <span class=\"pficon pficon-error-circle-o\"> </span>\n"
+ " <div class=\"gcc-message\" id=\"gcc-diag-0-message\"><strong>error: </strong> this is a test: `<span class=\"gcc-quoted-text\">foo</span>'</div>\n"
" </div>\n"
" </div>\n"
" </body>\n"
diag = diag_list.find('xhtml:div', ns)
assert diag is not None
- assert diag.attrib['class'] == 'gcc-diagnostic'
+ assert diag.attrib['class'] == 'alert alert-danger'
+ assert diag.attrib['id'] == 'gcc-diag-0'
- message = diag.find('xhtml:span', ns)
+ icon = diag.find('xhtml:span', ns)
+ assert icon.attrib['class'] == 'pficon pficon-error-circle-o'
+
+ # The message line:
+ message = diag.find("./xhtml:div[@class='gcc-message']", ns)
assert message is not None
- assert message.attrib['class'] == 'gcc-message'
- assert message.text == "expected '"
- assert message[0].tag == make_tag('span')
- assert message[0].attrib['class'] == 'gcc-quoted-text'
- assert message[0].text == ';'
- assert message[0].tail == "' before '"
+ # <html:div xmlns:html="http://www.w3.org/1999/xhtml" class="gcc-message" id="gcc-diag-0-message"><html:strong>error: </html:strong> expected '<html:span class="gcc-quoted-text">;</html:span>' before '<html:span class="gcc-quoted-text">}</html:span>' token</html:div>
+ assert message[0].tag == make_tag('strong')
+ assert message[0].text == 'error: '
+ assert message[0].tail == " expected '"
assert message[1].tag == make_tag('span')
assert message[1].attrib['class'] == 'gcc-quoted-text'
- assert message[1].text == '}'
- assert message[1].tail == "' token"
+ assert message[1].text == ';'
+ assert message[1].tail == "' before '"
+ assert message[2].tag == make_tag('span')
+ assert message[2].attrib['class'] == 'gcc-quoted-text'
+ assert message[2].text == '}'
+ assert message[2].tail == "' token"
+
+ # Logical location
+ logical_loc = diag.find("./xhtml:div[@id='logical-location']", ns)
+ assert logical_loc is not None
+ assert len(logical_loc) == 2
+ assert logical_loc[0].tag == make_tag('span')
+ assert logical_loc[0].text == 'Function '
+ assert logical_loc[1].tag == make_tag('span')
+ assert logical_loc[1].text == 'missing_semicolon'
+ assert logical_loc[1].attrib['class'] == 'gcc-quoted-text'
+
+ # Physical location
+ file_ = diag.find("./xhtml:div[@id='file']", ns)
+ assert file_ is not None
+ assert len(file_) == 2
+ assert file_[0].tag == make_tag('span')
+ assert file_[0].text == 'File '
+ assert file_[1].tag == make_tag('span')
+ assert file_[1].text.endswith('gcc/testsuite/gcc.dg/html-output/missing-semicolon.c')
+
+ line = diag.find("./xhtml:div[@id='line']", ns)
+ assert line is not None
+ assert len(line) == 2
+ assert line[0].tag == make_tag('span')
+ assert line[0].text == 'Line '
+ assert line[1].tag == make_tag('span')
+ assert line[1].text == '8'
+
+ column = diag.find("./xhtml:div[@id='column']", ns)
+ assert column is not None
+ assert len(column) == 2
+ assert column[0].tag == make_tag('span')
+ assert column[0].text == 'Column '
+ assert column[1].tag == make_tag('span')
+ assert column[1].text == '12'
- pre = diag.find('xhtml:pre', ns)
+ # Suggested fix
+ fix = diag.find("./xhtml:div[@id='suggested-fix']", ns)
+ label = fix.find('xhtml:label', ns)
+ assert label.text == "Suggested fix"
+ pre = fix.find('xhtml:pre', ns)
assert pre is not None
assert pre.attrib['class'] == 'gcc-generated-patch'
assert pre.text.startswith('--- ')
assert_annotation_line(annotation_tr,
' ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
- event_ranges = diag.find('xhtml:div', ns)
+ exec_path = diag.find("./xhtml:div[@id='execution-path']", ns)
+ assert exec_path is not None
+
+ label = exec_path.find('xhtml:label', ns)
+ assert label.text == 'Execution path with 9 events'
+
+ event_ranges = exec_path.find('xhtml:div', ns)
assert_class(event_ranges, 'event-ranges')
test_frame_margin = event_ranges.find('xhtml:table', ns)
test_frame = tds[1]
assert_frame(test_frame, 'test')
assert_event_range_with_margin(test_frame[1])
-
-# For reference, generated HTML looks like this:
-"""
-<table class="stack-frame-with-margin"><tr>
- <td class="interprocmargin" style="padding-left: 100px"/>
- <td class="stack-frame">
-<div class="frame-funcname"><span>test</span></div><table class="event-range-with-margin"><tr>
- <td class="event-range">
- <div class="events-hdr"><span class="funcname">test</span>: <span class="event-ids">events 1-2</span></div>
-<table class="locus">
-<tbody class="line-span">
-<tr><td class="linenum"> 27</td> <td class="source">{</td></tr>
-<tr><td class="linenum"/><td class="annotation">^</td></tr>
-<tr><td class="linenum"/><td class="annotation">|</td></tr>
-<tr><td class="linenum"/><td class="annotation">(1) entering 'test'</td></tr>
-<tr><td class="linenum"> 28</td> <td class="source"> register_handler ();</td></tr>
-<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~</td></tr>
-<tr><td class="linenum"/><td class="annotation"> |</td></tr>
-<tr><td class="linenum"/><td class="annotation"> (2) calling 'register_handler'</td></tr>
-</tbody>
-</table>
-</td></tr></table>
-<div class="between-ranges-call">
- <svg height="30" width="150">
- <defs>
- <marker id="arrowhead" markerWidth="10" markerHeight="7"
- refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
- <polygon points="0 0, 10 3.5, 0 7"/>
- </marker>
- </defs>
- <polyline points="20,0 20,10 120,10 120,20"
- style="fill:none;stroke: #0088ce"
- marker-end="url(#arrowhead)"/>
- </svg>
-</div>
-
-<table class="stack-frame-with-margin"><tr>
- <td class="interprocmargin" style="padding-left: 100px"/>
- <td class="stack-frame">
-<div class="frame-funcname"><span>register_handler</span></div><table class="event-range-with-margin"><tr>
- <td class="event-range">
- <div class="events-hdr"><span class="funcname">register_handler</span>: <span class="event-ids">events 3-4</span></div>
-<table class="locus">
-<tbody class="line-span">
-<tr><td class="linenum"> 22</td> <td class="source">{</td></tr>
-<tr><td class="linenum"/><td class="annotation">^</td></tr>
-<tr><td class="linenum"/><td class="annotation">|</td></tr>
-<tr><td class="linenum"/><td class="annotation">(3) entering 'register_handler'</td></tr>
-<tr><td class="linenum"> 23</td> <td class="source"> signal(SIGINT, int_handler);</td></tr>
-<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
-<tr><td class="linenum"/><td class="annotation"> |</td></tr>
-<tr><td class="linenum"/><td class="annotation"> (4) registering 'int_handler' as signal handler</td></tr>
-</tbody>
-</table>
-</td></tr></table>
-</td></tr></table>
-</td></tr></table>
-<div class="between-ranges-return">
- <svg height="30" width="250">
- <defs>
- <marker id="arrowhead" markerWidth="10" markerHeight="7"
- refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
- <polygon points="0 0, 10 3.5, 0 7"/>
- </marker>
- </defs>
- <polyline points="220,0 220,10 20,10 20,20"
- style="fill:none;stroke: #0088ce"
- marker-end="url(#arrowhead)"/>
- </svg>
-</div>
-
-<table class="event-range-with-margin"><tr>
- <td class="event-range">
- <div class="events-hdr"><span class="event-ids">event 5</span></div>
- (5): later on, when the signal is delivered to the process
-</td></tr></table>
-<div class="between-ranges-call">
- <svg height="30" width="150">
- <defs>
- <marker id="arrowhead" markerWidth="10" markerHeight="7"
- refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
- <polygon points="0 0, 10 3.5, 0 7"/>
- </marker>
- </defs>
- <polyline points="20,0 20,10 120,10 120,20"
- style="fill:none;stroke: #0088ce"
- marker-end="url(#arrowhead)"/>
- </svg>
-</div>
-
-<table class="stack-frame-with-margin"><tr>
- <td class="interprocmargin" style="padding-left: 100px"/>
- <td class="stack-frame">
-<div class="frame-funcname"><span>int_handler</span></div><table class="event-range-with-margin"><tr>
- <td class="event-range">
- <div class="events-hdr"><span class="funcname">int_handler</span>: <span class="event-ids">events 6-7</span></div>
-<table class="locus">
-<tbody class="line-span">
-<tr><td class="linenum"> 17</td> <td class="source">{</td></tr>
-<tr><td class="linenum"/><td class="annotation">^</td></tr>
-<tr><td class="linenum"/><td class="annotation">|</td></tr>
-<tr><td class="linenum"/><td class="annotation">(6) entering 'int_handler'</td></tr>
-<tr><td class="linenum"> 18</td> <td class="source"> custom_logger("got signal");</td></tr>
-<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
-<tr><td class="linenum"/><td class="annotation"> |</td></tr>
-<tr><td class="linenum"/><td class="annotation"> (7) calling 'custom_logger'</td></tr>
-</tbody>
-</table>
-</td></tr></table>
-<div class="between-ranges-call">
- <svg height="30" width="150">
- <defs>
- <marker id="arrowhead" markerWidth="10" markerHeight="7"
- refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
- <polygon points="0 0, 10 3.5, 0 7"/>
- </marker>
- </defs>
- <polyline points="20,0 20,10 120,10 120,20"
- style="fill:none;stroke: #0088ce"
- marker-end="url(#arrowhead)"/>
- </svg>
-</div>
-
-<table class="stack-frame-with-margin"><tr>
- <td class="interprocmargin" style="padding-left: 100px"/>
- <td class="stack-frame">
-<div class="frame-funcname"><span>custom_logger</span></div><table class="event-range-with-margin"><tr>
- <td class="event-range">
- <div class="events-hdr"><span class="funcname">custom_logger</span>: <span class="event-ids">events 8-9</span></div>
-<table class="locus">
-<tbody class="line-span">
-<tr><td class="linenum"> 12</td> <td class="source">{</td></tr>
-<tr><td class="linenum"/><td class="annotation">^</td></tr>
-<tr><td class="linenum"/><td class="annotation">|</td></tr>
-<tr><td class="linenum"/><td class="annotation">(8) entering 'custom_logger'</td></tr>
-<tr><td class="linenum"> 13</td> <td class="source"> fprintf(stderr, "LOG: %s", msg); /* { dg-warning "call to 'fprintf' from within signal handler" } */</td></tr>
-<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
-<tr><td class="linenum"/><td class="annotation"> |</td></tr>
-<tr><td class="linenum"/><td class="annotation"> (9) calling 'fprintf'</td></tr>
-</tbody>
-</table>
-</td></tr></table>
-</td></tr></table>
-</td></tr></table>
-
-</div>
- """