aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostics/output-spec.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostics/output-spec.cc')
-rw-r--r--gcc/diagnostics/output-spec.cc654
1 files changed, 338 insertions, 316 deletions
diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc
index 8ec638a..28ea044f 100644
--- a/gcc/diagnostics/output-spec.cc
+++ b/gcc/diagnostics/output-spec.cc
@@ -42,13 +42,24 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostics/output-spec.h"
/* A namespace for handling the DSL of the arguments of
- -fdiagnostics-add-output= and -fdiagnostics-set-output=. */
+ -fdiagnostics-add-output= and -fdiagnostics-set-output=
+ which look like:
+ SCHEME[:KEY=VALUE(,KEY=VALUE)*]
+ We call this an output spec. */
namespace diagnostics {
namespace output_spec {
+class scheme_handler;
+
/* Decls. */
+/* A class for the result of the first stage of parsing an output spec,
+ where values are represented as untyped strings.
+ The scheme might not exist.
+ The keys have not been validated against the scheme.
+ The values have not been validated against their keys. */
+
struct scheme_name_and_params
{
std::string m_scheme_name;
@@ -62,94 +73,12 @@ struct scheme_name_and_params
class output_factory
{
public:
- class scheme_handler
- {
- public:
- scheme_handler (std::string scheme_name)
- : m_scheme_name (std::move (scheme_name))
- {}
- virtual ~scheme_handler () {}
-
- const std::string &get_scheme_name () const { return m_scheme_name; }
-
- virtual std::unique_ptr<sink>
- make_sink (const context &ctxt,
- diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const = 0;
-
- protected:
- bool
- parse_bool_value (const context &ctxt,
- const char *unparsed_arg,
- const std::string &key,
- const std::string &value,
- bool &out) const
- {
- if (value == "yes")
- {
- out = true;
- return true;
- }
- else if (value == "no")
- {
- out = false;
- return true;
- }
- else
- {
- ctxt.report_error
- ("%<%s%s%>:"
- " unexpected value %qs for key %qs; expected %qs or %qs",
- ctxt.get_option_name (), unparsed_arg,
- value.c_str (),
- key.c_str (),
- "yes", "no");
-
- return false;
- }
- }
- template <typename EnumType, size_t NumValues>
- bool
- parse_enum_value (const context &ctxt,
- const char *unparsed_arg,
- const std::string &key,
- const std::string &value,
- const std::array<std::pair<const char *, EnumType>, NumValues> &value_names,
- EnumType &out) const
- {
- for (auto &iter : value_names)
- if (value == iter.first)
- {
- out = iter.second;
- return true;
- }
-
- auto_vec<const char *> known_values;
- for (auto iter : value_names)
- known_values.safe_push (iter.first);
- pp_markup::comma_separated_quoted_strings e (known_values);
- ctxt.report_error
- ("%<%s%s%>:"
- " unexpected value %qs for key %qs; known values: %e",
- ctxt.get_option_name (), unparsed_arg,
- value.c_str (),
- key.c_str (),
- &e);
- return false;
- }
-
- private:
- const std::string m_scheme_name;
- };
-
output_factory ();
std::unique_ptr<sink>
make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg);
+ const scheme_name_and_params &scheme_and_kvs);
const scheme_handler *get_scheme_handler (const std::string &scheme_name);
@@ -157,44 +86,158 @@ private:
std::vector<std::unique_ptr<scheme_handler>> m_scheme_handlers;
};
-class text_scheme_handler : public output_factory::scheme_handler
+class scheme_handler
{
public:
+ scheme_handler (std::string scheme_name)
+ : m_scheme_name (std::move (scheme_name))
+ {}
+ virtual ~scheme_handler () {}
+
+ const std::string &get_scheme_name () const { return m_scheme_name; }
+
+ virtual std::unique_ptr<sink>
+ make_sink (const context &ctxt,
+ diagnostics::context &dc,
+ const scheme_name_and_params &scheme_and_kvs) const = 0;
+
+protected:
+ bool
+ parse_bool_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ bool &out) const
+ {
+ if (value == "yes")
+ {
+ out = true;
+ return true;
+ }
+ else if (value == "no")
+ {
+ out = false;
+ return true;
+ }
+ else
+ {
+ ctxt.report_error
+ ("%<%s%s%>:"
+ " unexpected value %qs for key %qs; expected %qs or %qs",
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
+ value.c_str (),
+ key.c_str (),
+ "yes", "no");
+
+ return false;
+ }
+ }
+ template <typename EnumType, size_t NumValues>
+ bool
+ parse_enum_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ const std::array<std::pair<const char *, EnumType>, NumValues> &value_names,
+ EnumType &out) const
+ {
+ for (auto &iter : value_names)
+ if (value == iter.first)
+ {
+ out = iter.second;
+ return true;
+ }
+
+ auto_vec<const char *> known_values;
+ for (auto iter : value_names)
+ known_values.safe_push (iter.first);
+ pp_markup::comma_separated_quoted_strings e (known_values);
+ ctxt.report_error
+ ("%<%s%s%>:"
+ " unexpected value %qs for key %qs; known values: %e",
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
+ value.c_str (),
+ key.c_str (),
+ &e);
+ return false;
+ }
+
+private:
+ const std::string m_scheme_name;
+};
+
+class text_scheme_handler : public scheme_handler
+{
+public:
+ struct decoded_args
+ {
+ bool m_show_color;
+ bool m_show_nesting;
+ bool m_show_locations_in_nesting;
+ bool m_show_levels;
+ };
+
text_scheme_handler () : scheme_handler ("text") {}
std::unique_ptr<sink>
make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const final override;
+ const scheme_name_and_params &scheme_and_kvs) const final override;
+
+ bool
+ decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &out_opts) const;
};
-class sarif_scheme_handler : public output_factory::scheme_handler
+class sarif_scheme_handler : public scheme_handler
{
public:
+ struct decoded_args
+ {
+ label_text m_filename;
+ enum sarif_serialization_kind m_serialization_kind;
+ sarif_generation_options m_generation_opts;
+ };
+
sarif_scheme_handler () : scheme_handler ("sarif") {}
std::unique_ptr<sink>
make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const final override;
+ const scheme_name_and_params &scheme_and_kvs) const final override;
+
+ bool
+ decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &out_opts) const;
private:
static std::unique_ptr<sarif_serialization_format>
make_sarif_serialization_object (enum sarif_serialization_kind);
};
-class html_scheme_handler : public output_factory::scheme_handler
+class html_scheme_handler : public scheme_handler
{
public:
+ struct decoded_args
+ {
+ label_text m_filename;
+ html_generation_options m_html_gen_opts;
+ };
+
html_scheme_handler () : scheme_handler ("experimental-html") {}
std::unique_ptr<sink>
make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const final override;
+ const scheme_name_and_params &scheme_and_kvs) const final override;
+
+ bool
+ decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &opts_out) const;
};
/* struct context. */
@@ -209,8 +252,7 @@ context::report_error (const char *gmsgid, ...) const
}
void
-context::report_unknown_key (const char *unparsed_arg,
- const std::string &key,
+context::report_unknown_key (const std::string &key,
const std::string &scheme_name,
auto_vec<const char *> &known_keys) const
{
@@ -218,13 +260,12 @@ context::report_unknown_key (const char *unparsed_arg,
report_error
("%<%s%s%>:"
" unknown key %qs for format %qs; known keys: %e",
- get_option_name (), unparsed_arg,
+ get_option_name (), get_unparsed_spec (),
key.c_str (), scheme_name.c_str (), &e);
}
void
-context::report_missing_key (const char *unparsed_arg,
- const std::string &key,
+context::report_missing_key (const std::string &key,
const std::string &scheme_name,
const char *metavar) const
{
@@ -232,7 +273,7 @@ context::report_missing_key (const char *unparsed_arg,
("%<%s%s%>:"
" missing required key %qs for format %qs;"
" try %<%s%s:%s=%s%>",
- get_option_name (), unparsed_arg,
+ get_option_name (), get_unparsed_spec (),
key.c_str (), scheme_name.c_str (),
get_option_name (), scheme_name.c_str (), key.c_str (), metavar);
}
@@ -250,12 +291,13 @@ context::open_output_file (label_text &&filename) const
}
static std::unique_ptr<scheme_name_and_params>
-parse (const context &ctxt, const char *unparsed_arg)
+parse (const context &ctxt)
{
scheme_name_and_params result;
- if (const char *const colon = strchr (unparsed_arg, ':'))
+ const char *const unparsed_spec = ctxt.get_unparsed_spec ();
+ if (const char *const colon = strchr (unparsed_spec, ':'))
{
- result.m_scheme_name = std::string (unparsed_arg, colon - unparsed_arg);
+ result.m_scheme_name = std::string (unparsed_spec, colon - unparsed_spec);
/* Expect zero of more of KEY=VALUE,KEY=VALUE, etc .*/
const char *iter = colon + 1;
const char *last_separator = ":";
@@ -271,7 +313,7 @@ parse (const context &ctxt, const char *unparsed_arg)
" expected KEY=VALUE-style parameter for format %qs"
" after %qs;"
" got %qs",
- ctxt.get_option_name (), unparsed_arg,
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
result.m_scheme_name.c_str (),
last_separator,
iter);
@@ -295,23 +337,22 @@ parse (const context &ctxt, const char *unparsed_arg)
}
}
else
- result.m_scheme_name = unparsed_arg;
+ result.m_scheme_name = unparsed_spec;
return std::make_unique<scheme_name_and_params> (std::move (result));
}
std::unique_ptr<sink>
-context::parse_and_make_sink (const char *unparsed_arg,
- diagnostics::context &dc)
+context::parse_and_make_sink (diagnostics::context &dc)
{
- auto parsed_arg = parse (*this, unparsed_arg);
+ auto parsed_arg = parse (*this);
if (!parsed_arg)
return nullptr;
output_factory factory;
- return factory.make_sink (*this, dc, unparsed_arg, *parsed_arg);
+ return factory.make_sink (*this, dc, *parsed_arg);
}
-/* class output_factory::scheme_handler. */
+/* class scheme_handler. */
/* class output_factory. */
@@ -322,7 +363,7 @@ output_factory::output_factory ()
m_scheme_handlers.push_back (std::make_unique<html_scheme_handler> ());
}
-const output_factory::scheme_handler *
+const scheme_handler *
output_factory::get_scheme_handler (const std::string &scheme_name)
{
for (auto &iter : m_scheme_handlers)
@@ -334,10 +375,9 @@ output_factory::get_scheme_handler (const std::string &scheme_name)
std::unique_ptr<sink>
output_factory::make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg)
+ const scheme_name_and_params &scheme_and_kvs)
{
- auto scheme_handler = get_scheme_handler (parsed_arg.m_scheme_name);
+ auto scheme_handler = get_scheme_handler (scheme_and_kvs.m_scheme_name);
if (!scheme_handler)
{
auto_vec<const char *> strings;
@@ -346,155 +386,97 @@ output_factory::make_sink (const context &ctxt,
pp_markup::comma_separated_quoted_strings e (strings);
ctxt.report_error ("%<%s%s%>:"
" unrecognized format %qs; known formats: %e",
- ctxt.get_option_name (), unparsed_arg,
- parsed_arg.m_scheme_name.c_str (), &e);
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
+ scheme_and_kvs.m_scheme_name.c_str (), &e);
return nullptr;
}
- return scheme_handler->make_sink (ctxt, dc, unparsed_arg, parsed_arg);
+ return scheme_handler->make_sink (ctxt, dc, scheme_and_kvs);
}
-/* class text_scheme_handler : public output_factory::scheme_handler. */
+/* class text_scheme_handler : public scheme_handler. */
std::unique_ptr<sink>
text_scheme_handler::make_sink (const context &ctxt,
diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const
+ const scheme_name_and_params &scheme_and_kvs) const
{
- bool show_color = pp_show_color (dc.get_reference_printer ());
- bool show_nesting = true;
- bool show_locations_in_nesting = true;
- bool show_levels = false;
- for (auto& iter : parsed_arg.m_kvs)
+ decoded_args opts;
+ opts.m_show_color = pp_show_color (dc.get_reference_printer ());
+ opts.m_show_nesting = true;
+ opts.m_show_locations_in_nesting = true;
+ opts.m_show_levels = false;
+ for (auto& iter : scheme_and_kvs.m_kvs)
{
const std::string &key = iter.first;
const std::string &value = iter.second;
- if (key == "color")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_color))
- return nullptr;
- continue;
- }
- if (key == "show-nesting")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- show_nesting))
- return nullptr;
- continue;
- }
- if (key == "show-nesting-locations")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- show_locations_in_nesting))
- return nullptr;
- continue;
- }
- if (key == "show-nesting-levels")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_levels))
- return nullptr;
- continue;
- }
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("color");
- known_keys.safe_push ("show-nesting");
- known_keys.safe_push ("show-nesting-locations");
- known_keys.safe_push ("show-nesting-levels");
- ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- known_keys);
- return nullptr;
+ if (!decode_kv (ctxt, key, value, opts))
+ return nullptr;
}
auto sink = std::make_unique<diagnostics::text_sink> (dc);
- sink->set_show_nesting (show_nesting);
- sink->set_show_locations_in_nesting (show_locations_in_nesting);
- sink->set_show_nesting_levels (show_levels);
+ sink->set_show_nesting (opts.m_show_nesting);
+ sink->set_show_locations_in_nesting (opts.m_show_locations_in_nesting);
+ sink->set_show_nesting_levels (opts.m_show_levels);
+ pp_show_color (sink->get_printer ()) = opts.m_show_color;
return sink;
}
-/* class sarif_scheme_handler : public output_factory::scheme_handler. */
+bool
+text_scheme_handler::decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &opts_out) const
+{
+ if (key == "color")
+ return parse_bool_value (ctxt, key, value, opts_out.m_show_color);
+ if (key == "show-nesting")
+ return parse_bool_value (ctxt, key, value, opts_out.m_show_nesting);
+ if (key == "show-nesting-locations")
+ return parse_bool_value (ctxt, key, value,
+ opts_out.m_show_locations_in_nesting);
+ if (key == "show-nesting-levels")
+ return parse_bool_value (ctxt, key, value, opts_out.m_show_levels);
+
+ /* Key not found. */
+ auto_vec<const char *> known_keys;
+ known_keys.safe_push ("color");
+ known_keys.safe_push ("show-nesting");
+ known_keys.safe_push ("show-nesting-locations");
+ known_keys.safe_push ("show-nesting-levels");
+ ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
+ return false;
+}
+
+/* class sarif_scheme_handler : public scheme_handler. */
std::unique_ptr<sink>
-sarif_scheme_handler::make_sink (const context &ctxt,
- diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const
+sarif_scheme_handler::
+make_sink (const context &ctxt,
+ diagnostics::context &dc,
+ const scheme_name_and_params &scheme_and_kvs) const
{
- label_text filename;
- enum sarif_serialization_kind serialization_kind
- = sarif_serialization_kind::json;
- sarif_generation_options sarif_gen_opts;
- for (auto& iter : parsed_arg.m_kvs)
+ decoded_args opts;
+ opts.m_serialization_kind = sarif_serialization_kind::json;
+
+ for (auto& iter : scheme_and_kvs.m_kvs)
{
const std::string &key = iter.first;
const std::string &value = iter.second;
- if (key == "file")
- {
- filename = label_text::take (xstrdup (value.c_str ()));
- continue;
- }
- if (key == "serialization")
- {
- static const std::array<std::pair<const char *, enum sarif_serialization_kind>,
- (size_t)sarif_serialization_kind::num_values> value_names
- {{{"json", sarif_serialization_kind::json}}};
-
- if (!parse_enum_value<enum sarif_serialization_kind>
- (ctxt, unparsed_arg,
- key, value,
- value_names,
- serialization_kind))
- return nullptr;
- continue;
- }
- if (key == "version")
- {
- static const std::array<std::pair<const char *, enum sarif_version>,
- (size_t)sarif_version::num_versions> value_names
- {{{"2.1", sarif_version::v2_1_0},
- {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}};
-
- if (!parse_enum_value<enum sarif_version>
- (ctxt, unparsed_arg,
- key, value,
- value_names,
- sarif_gen_opts.m_version))
- return nullptr;
- continue;
- }
- if (key == "state-graphs")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- sarif_gen_opts.m_state_graph))
- return nullptr;
- continue;
- }
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("file");
- known_keys.safe_push ("serialization");
- known_keys.safe_push ("state-graphs");
- known_keys.safe_push ("version");
- ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- known_keys);
- return nullptr;
+ if (!decode_kv (ctxt, key, value, opts))
+ return nullptr;
}
output_file output_file_;
- if (filename.get ())
- output_file_ = ctxt.open_output_file (std::move (filename));
+ if (opts.m_filename.get ())
+ output_file_ = ctxt.open_output_file (std::move (opts.m_filename));
else
// Default filename
{
const char *basename = ctxt.get_base_filename ();
if (!basename)
{
- ctxt.report_missing_key (unparsed_arg,
- "file",
+ ctxt.report_missing_key ("file",
get_scheme_name (),
"FILENAME");
return nullptr;
@@ -503,21 +485,71 @@ sarif_scheme_handler::make_sink (const context &ctxt,
= open_sarif_output_file (dc,
ctxt.get_affected_location_mgr (),
basename,
- serialization_kind);
+ opts.m_serialization_kind);
}
if (!output_file_)
return nullptr;
- auto serialization_obj = make_sarif_serialization_object (serialization_kind);
+ auto serialization_obj
+ = make_sarif_serialization_object (opts.m_serialization_kind);
auto sink = make_sarif_sink (dc,
*ctxt.get_affected_location_mgr (),
std::move (serialization_obj),
- sarif_gen_opts,
+ opts.m_generation_opts,
std::move (output_file_));
+
return sink;
}
+bool
+sarif_scheme_handler::decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &opts_out) const
+{
+ if (key == "file")
+ {
+ opts_out.m_filename = label_text::take (xstrdup (value.c_str ()));
+ return true;
+ }
+ if (key == "serialization")
+ {
+ static const std::array<std::pair<const char *, enum sarif_serialization_kind>,
+ (size_t)sarif_serialization_kind::num_values> value_names
+ {{{"json", sarif_serialization_kind::json}}};
+ return parse_enum_value<enum sarif_serialization_kind>
+ (ctxt,
+ key, value,
+ value_names,
+ opts_out.m_serialization_kind);
+ }
+ if (key == "version")
+ {
+ static const std::array<std::pair<const char *, enum sarif_version>,
+ (size_t)sarif_version::num_versions> value_names
+ {{{"2.1", sarif_version::v2_1_0},
+ {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}};
+ return parse_enum_value<enum sarif_version>
+ (ctxt,
+ key, value,
+ value_names,
+ opts_out.m_generation_opts.m_version);
+ }
+ if (key == "state-graphs")
+ return parse_bool_value (ctxt, key, value,
+ opts_out.m_generation_opts.m_state_graph);
+
+ /* Key not found. */
+ auto_vec<const char *> known_keys;
+ known_keys.safe_push ("file");
+ known_keys.safe_push ("serialization");
+ known_keys.safe_push ("state-graphs");
+ known_keys.safe_push ("version");
+ ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
+ return false;
+}
+
std::unique_ptr<sarif_serialization_format>
sarif_scheme_handler::
make_sarif_serialization_object (enum sarif_serialization_kind kind)
@@ -532,85 +564,33 @@ make_sarif_serialization_object (enum sarif_serialization_kind kind)
}
}
-/* class html_scheme_handler : public output_factory::scheme_handler. */
+/* class html_scheme_handler : public scheme_handler. */
std::unique_ptr<sink>
-html_scheme_handler::make_sink (const context &ctxt,
- diagnostics::context &dc,
- const char *unparsed_arg,
- const scheme_name_and_params &parsed_arg) const
+html_scheme_handler::
+make_sink (const context &ctxt,
+ diagnostics::context &dc,
+ const scheme_name_and_params &scheme_and_kvs) const
{
- label_text filename;
- html_generation_options html_gen_opts;
- for (auto& iter : parsed_arg.m_kvs)
+ decoded_args opts;
+ for (auto& iter : scheme_and_kvs.m_kvs)
{
const std::string &key = iter.first;
const std::string &value = iter.second;
- if (key == "css")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- html_gen_opts.m_css))
- return nullptr;
- continue;
- }
- if (key == "file")
- {
- filename = label_text::take (xstrdup (value.c_str ()));
- continue;
- }
- if (key == "javascript")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- html_gen_opts.m_javascript))
- return nullptr;
- continue;
- }
- if (key == "show-state-diagrams")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- html_gen_opts.m_show_state_diagrams))
- return nullptr;
- continue;
- }
- if (key == "show-state-diagrams-dot-src")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- html_gen_opts.m_show_state_diagrams_dot_src))
- return nullptr;
- continue;
- }
- if (key == "show-state-diagrams-sarif")
- {
- if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- html_gen_opts.m_show_state_diagrams_sarif))
- return nullptr;
- continue;
- }
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("css");
- known_keys.safe_push ("file");
- known_keys.safe_push ("javascript");
- known_keys.safe_push ("show-state-diagrams");
- known_keys.safe_push ("show-state-diagram-dot-src");
- known_keys.safe_push ("show-state-diagram-sarif");
- ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- known_keys);
- return nullptr;
+ if (!decode_kv (ctxt, key, value, opts))
+ return nullptr;
}
output_file output_file_;
- if (filename.get ())
- output_file_ = ctxt.open_output_file (std::move (filename));
+ if (opts.m_filename.get ())
+ output_file_ = ctxt.open_output_file (std::move (opts.m_filename));
else
// Default filename
{
const char *basename = ctxt.get_base_filename ();
if (!basename)
{
- ctxt.report_missing_key (unparsed_arg,
- "file",
+ ctxt.report_missing_key ("file",
get_scheme_name (),
"FILENAME");
return nullptr;
@@ -626,11 +606,51 @@ html_scheme_handler::make_sink (const context &ctxt,
auto sink = make_html_sink (dc,
*ctxt.get_affected_location_mgr (),
- html_gen_opts,
+ opts.m_html_gen_opts,
std::move (output_file_));
return sink;
}
+bool
+html_scheme_handler::decode_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ decoded_args &opts_out) const
+{
+ if (key == "css")
+ return parse_bool_value (ctxt, key, value, opts_out.m_html_gen_opts.m_css);
+ if (key == "file")
+ {
+ opts_out.m_filename = label_text::take (xstrdup (value.c_str ()));
+ return true;
+ }
+ if (key == "javascript")
+ return parse_bool_value (ctxt, key, value,
+ opts_out.m_html_gen_opts.m_javascript);
+ if (key == "show-state-diagrams")
+ return parse_bool_value (ctxt, key, value,
+ opts_out.m_html_gen_opts.m_show_state_diagrams);
+ if (key == "show-state-diagrams-dot-src")
+ return parse_bool_value
+ (ctxt, key, value,
+ opts_out.m_html_gen_opts.m_show_state_diagrams_dot_src);
+ if (key == "show-state-diagrams-sarif")
+ return parse_bool_value
+ (ctxt, key, value,
+ opts_out.m_html_gen_opts.m_show_state_diagrams_sarif);
+
+ /* Key not found. */
+ auto_vec<const char *> known_keys;
+ known_keys.safe_push ("css");
+ known_keys.safe_push ("file");
+ known_keys.safe_push ("javascript");
+ known_keys.safe_push ("show-state-diagrams");
+ known_keys.safe_push ("show-state-diagram-dot-src");
+ known_keys.safe_push ("show-state-diagram-sarif");
+ ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
+ return false;
+}
+
} // namespace output_spec
#if CHECKING_P
@@ -668,12 +688,14 @@ struct parser_test
test_spec_context (diagnostics::context &dc,
line_maps *location_mgr,
location_t loc,
- const char *option_name)
+ const char *option_name,
+ const char *unparsed_arg)
: dc_spec_context (dc,
location_mgr,
location_mgr,
loc,
- option_name)
+ option_name,
+ unparsed_arg)
{
}
@@ -684,18 +706,18 @@ struct parser_test
}
};
- parser_test ()
+ parser_test (const char *unparsed_spec)
: m_dc (),
- m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION="),
+ m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION=", unparsed_spec),
m_fmt (m_dc.get_sink (0))
{
pp_buffer (m_fmt.get_printer ())->m_flush_p = false;
}
std::unique_ptr<diagnostics::output_spec::scheme_name_and_params>
- parse (const char *unparsed_arg)
+ parse ()
{
- return diagnostics::output_spec::parse (m_ctxt, unparsed_arg);
+ return diagnostics::output_spec::parse (m_ctxt);
}
bool execution_failed_p () const
@@ -725,8 +747,8 @@ test_output_arg_parsing ()
/* Minimal correct example. */
{
- parser_test pt;
- auto result = pt.parse ("foo");
+ parser_test pt ("foo");
+ auto result = pt.parse ();
ASSERT_EQ (result->m_scheme_name, "foo");
ASSERT_EQ (result->m_kvs.size (), 0);
ASSERT_FALSE (pt.execution_failed_p ());
@@ -734,8 +756,8 @@ test_output_arg_parsing ()
/* Stray trailing colon with no key/value pairs. */
{
- parser_test pt;
- auto result = pt.parse ("foo:");
+ parser_test pt ("foo:");
+ auto result = pt.parse ();
ASSERT_EQ (result, nullptr);
ASSERT_TRUE (pt.execution_failed_p ());
ASSERT_STREQ (pt.get_diagnostic_text (),
@@ -747,8 +769,8 @@ test_output_arg_parsing ()
/* No key before '='. */
{
- parser_test pt;
- auto result = pt.parse ("foo:=");
+ parser_test pt ("foo:=");
+ auto result = pt.parse ();
ASSERT_EQ (result, nullptr);
ASSERT_TRUE (pt.execution_failed_p ());
ASSERT_STREQ (pt.get_diagnostic_text (),
@@ -760,8 +782,8 @@ test_output_arg_parsing ()
/* No value for key. */
{
- parser_test pt;
- auto result = pt.parse ("foo:key,");
+ parser_test pt ("foo:key,");
+ auto result = pt.parse ();
ASSERT_EQ (result, nullptr);
ASSERT_TRUE (pt.execution_failed_p ());
ASSERT_STREQ (pt.get_diagnostic_text (),
@@ -773,8 +795,8 @@ test_output_arg_parsing ()
/* Correct example, with one key/value pair. */
{
- parser_test pt;
- auto result = pt.parse ("foo:key=value");
+ parser_test pt ("foo:key=value");
+ auto result = pt.parse ();
ASSERT_EQ (result->m_scheme_name, "foo");
ASSERT_EQ (result->m_kvs.size (), 1);
ASSERT_EQ (result->m_kvs[0].first, "key");
@@ -784,8 +806,8 @@ test_output_arg_parsing ()
/* Stray trailing comma. */
{
- parser_test pt;
- auto result = pt.parse ("foo:key=value,");
+ parser_test pt ("foo:key=value,");
+ auto result = pt.parse ();
ASSERT_EQ (result, nullptr);
ASSERT_TRUE (pt.execution_failed_p ());
ASSERT_STREQ (pt.get_diagnostic_text (),
@@ -797,8 +819,8 @@ test_output_arg_parsing ()
/* Correct example, with two key/value pairs. */
{
- parser_test pt;
- auto result = pt.parse ("foo:color=red,shape=circle");
+ parser_test pt ("foo:color=red,shape=circle");
+ auto result = pt.parse ();
ASSERT_EQ (result->m_scheme_name, "foo");
ASSERT_EQ (result->m_kvs.size (), 2);
ASSERT_EQ (result->m_kvs[0].first, "color");