From 04b878f078283c1042dc6975d63b9ebc38570c99 Mon Sep 17 00:00:00 2001 From: Alexander Kobjolke Date: Sat, 26 Feb 2022 00:23:43 +0100 Subject: [PATCH] Initial version --- .gitignore | 1 + Makefile | 33 ++ app/Main.hs | 6 + example/defects.err | 5 + example/include/health/ui/plugin_registry.hpp | 144 +++++++ example/include/process/command_receiver.hpp | 37 ++ .../include/process/default_controller.hpp | 36 ++ .../process/default_controller_topics.hpp | 21 ++ .../include/process/definition_receiver.hpp | 24 ++ example/include/process/filesystem.hpp | 28 ++ example/include/process/libprocess_export.hpp | 42 +++ example/include/process/node_checker.hpp | 31 ++ example/include/process/predicate.hpp | 76 ++++ example/include/process/process.hpp | 97 +++++ example/include/process/process_checker.hpp | 31 ++ .../include/process/process_collection.hpp | 80 ++++ .../include/process/process_exceptions.hpp | 114 ++++++ example/include/process/process_factory.hpp | 46 +++ .../process/process_state_extensions.hpp | 15 + example/include/process/service_wrapper.hpp | 22 ++ .../process/service_wrapper_factory.hpp | 23 ++ .../process/service_wrapper_listener.hpp | 38 ++ example/include/process/watchdog.hpp | 89 +++++ example/process-defects.err | 336 +++++++++++++++++ script/makedist | 15 + src/Annotator.hs | 357 ++++++++++++++++++ src/Annotator/Annotation.hs | 14 + src/Annotator/Rule.hs | 10 + 28 files changed, 1771 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 app/Main.hs create mode 100644 example/defects.err create mode 100644 example/include/health/ui/plugin_registry.hpp create mode 100644 example/include/process/command_receiver.hpp create mode 100644 example/include/process/default_controller.hpp create mode 100644 example/include/process/default_controller_topics.hpp create mode 100644 example/include/process/definition_receiver.hpp create mode 100644 example/include/process/filesystem.hpp create mode 100644 example/include/process/libprocess_export.hpp create mode 100644 example/include/process/node_checker.hpp create mode 100644 example/include/process/predicate.hpp create mode 100644 example/include/process/process.hpp create mode 100644 example/include/process/process_checker.hpp create mode 100644 example/include/process/process_collection.hpp create mode 100644 example/include/process/process_exceptions.hpp create mode 100644 example/include/process/process_factory.hpp create mode 100644 example/include/process/process_state_extensions.hpp create mode 100644 example/include/process/service_wrapper.hpp create mode 100644 example/include/process/service_wrapper_factory.hpp create mode 100644 example/include/process/service_wrapper_listener.hpp create mode 100644 example/include/process/watchdog.hpp create mode 100644 example/process-defects.err create mode 100755 script/makedist create mode 100644 src/Annotator.hs create mode 100644 src/Annotator/Annotation.hs create mode 100644 src/Annotator/Rule.hs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..74fc338 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +.PHONY: default all install watch clean build dist distclean +default: all + +all: build + +build: builddir build/annotator + +GHCFLAGS = -iapp -isrc -Wall -outputdir build +DESTDIR = ~/.local +BINDIR = ${DESTDIR}/bin + +builddir: + mkdir -p build + +build/annotator: app/Main.hs src/*.hs + ghc --make $(GHCFLAGS) $< -o $@ + +watch: + @git ls-files src app Makefile | entr make -s build install + +clean: + @find . -name "*.hi" -delete + @find . -name "*.fix" -delete + +distclean: clean + @rm -rf build + @rm -rf dist + +install: build/annotator + @install -D -t ${BINDIR} $< + +dist: script/makedist + @$< diff --git a/app/Main.hs b/app/Main.hs new file mode 100644 index 0000000..5ac1405 --- /dev/null +++ b/app/Main.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import qualified Annotator + +main :: IO () +main = Annotator.defaultMain diff --git a/example/defects.err b/example/defects.err new file mode 100644 index 0000000..b7a58c9 --- /dev/null +++ b/example/defects.err @@ -0,0 +1,5 @@ +include/health/ui/plugin_registry.hpp:1:ERROR: Newest, autosar_cpp14_a18_9_1_violation: Using "std::move" on object "this->file", which is declared "const" or "const&". +include/health/ui/plugin_registry.hpp:130:ERROR: Newest, autosar_cpp14_a18_9_1_violation: Using "std::move" on object "this->file", which is declared "const" or "const&". +include/health/ui/plugin_registry.hpp:140:ERROR: New, autosar_cpp14_a18_9_2_violation: Using "std::move" on object "this->file", which is declared "const" or "const&". +include/health/ui/plugin_registry.hpp:100:ERROR: Newest, autosar_cpp14_a18_9_3_violation: Using "std::move" on object "this->file", which is declared "const" or "const&". +include/health/ui/foo.hpp:100:ERROR: Newest, autosar_cpp14_a18_9_4_violation: Using "std::move" on object "this->file", which is declared "const" or "const&". diff --git a/example/include/health/ui/plugin_registry.hpp b/example/include/health/ui/plugin_registry.hpp new file mode 100644 index 0000000..3fcf659 --- /dev/null +++ b/example/include/health/ui/plugin_registry.hpp @@ -0,0 +1,144 @@ +#ifndef HEALTH_UI_PLUGIN_REGISTRY_HPP +#define HEALTH_UI_PLUGIN_REGISTRY_HPP + +#include + +#include + +#include + +#include +#include + +namespace health::ui { +// coverity[autosar_cpp14_a11_0_1_violation] we do not need a class +struct LoadedPlugin { + // coverity[autosar_cpp14_m11_0_1_violation] we do not need a class + std::string name; + // coverity[autosar_cpp14_m11_0_1_violation] we do not need a class + std::filesystem::path file; + // coverity[autosar_cpp14_m11_0_1_violation] we do not need a class + std::unique_ptr library; + // coverity[autosar_cpp14_m11_0_1_violation] we do not need a class + std::unique_ptr api; + // coverity[autosar_cpp14_m11_0_1_violation] we do not need a class + std::unique_ptr adapter; +}; + +class PluginRegistry : public Adapter { +public: + // coverity[autosar_cpp14_a8_4_7_violation : FALSE] parameter gets moved + PluginRegistry(const util::shared::Loader& loader, infra::log::LoggerPtr logger, std::shared_ptr participant) + : m_loader { loader } + , m_logger { std::move(logger) } + , m_participant { std::move(participant) } + , m_plugins {} + { + } + + [[nodiscard]] bool is_compatible(const Version our, const Version their) const + { + return is_compatible_impl(our, their); + } + + // load plugin(s) from the given path + // + // NB: we currently do not support loading plugins from a directory + util::ErrorOr load(const std::filesystem::path& path) + { + // coverity[autosar_cpp14_a5_1_4_violation : FALSE] objects get moved + return load_impl(path).and_then([this](LoadedPlugin& p) -> util::ErrorOr { + const auto plugin_name { p.name }; + m_logger->info("Loaded plugin '{}' from '{}'", p.name, p.file); + m_plugins.push_back(std::move(p)); + return { plugin_name }; + }); + } + +private: + // coverity[autosar_cpp14_a7_1_8_violation : FALSE] nodiscard ignored + [[nodiscard]] virtual bool is_compatible_impl(const Version our, const Version their) const + { + return our == their; // be conservative right now + } + + virtual util::ErrorOr load_impl(const std::filesystem::path& path) const + { + // we currently do not support loading directories, so just delegate to load_file for now + return load_file(path); + } + + std::unique_ptr create_api(const std::string& name) const + { + class PluginApiImpl : public PluginApi { + public: + // coverity[autosar_cpp14_a8_4_7_violation : FALSE] parameter gets moved + PluginApiImpl(std::shared_ptr participant, infra::log::LoggerPtr logger) + : m_participant { std::move(participant) } + , m_logger { std::move(logger) } + { + } + + [[nodiscard]] std::shared_ptr get_participant() const override + { + return m_participant; + } + + [[nodiscard]] ::infra::log::LoggerPtr get_logger() const override + { + return m_logger; + } + + private: + std::shared_ptr m_participant; + infra::log::LoggerPtr m_logger; + }; + + return std::make_unique(m_participant, m_logger->get_child(name)); + } + + /** + * Main functionality for our class + */ + virtual util::ErrorOr load_file(const std::filesystem::path& file) const + { + auto lib { m_loader.load(file) }; + if (const auto version { lib->get("health_ui_version") }; !is_compatible(health::ui::PLUGIN_API_VERSION, version)) { + return { std::make_error_code(std::errc::protocol_not_supported), "plugin has an incompatible version" }; + } else { + return load_plugin(file, std::move(lib)); + } + } + + // coverity[autosar_cpp14_a8_4_7_violation : FALSE] move semantics + virtual util::ErrorOr load_plugin(const std::filesystem::path& file, std::unique_ptr lib) const + { + m_logger->debug("Trying to load compatible plugin from '{}'", file); + const auto plugin_info { lib->get("health_ui_info") }; + std::string name { plugin_info->name }; + + auto api { create_api(name) }; + + // coverity[autosar_cpp14_a5_1_4_violation : FALSE] objects get moved + return plugin_info->create(*api).and_then([&name, &file, &lib, &api](AdapterPtr& adapter) -> util::ErrorOr { + return LoadedPlugin { std::move(name), file, std::move(lib), std::move(api), std::move(adapter) }; + }); + } + + void update_internal(const ::health::Snapshot& system_state, const ::health::monitoring::HealthData& health_data) override + { + m_logger->debug("Updating {} ui-adapters...", m_plugins.size()); + for (const auto& plugin : m_plugins) { + m_logger->trace("Updating '{}'...", plugin.name); + plugin.adapter->update(system_state, health_data); + } + } + + const util::shared::Loader& m_loader; + infra::log::LoggerPtr m_logger; + std::shared_ptr m_participant; + std::list m_plugins; +}; +} + +#endif /* HEALTH_UI_PLUGIN_REGISTRY_HPP */ diff --git a/example/include/process/command_receiver.hpp b/example/include/process/command_receiver.hpp new file mode 100644 index 0000000..a40099a --- /dev/null +++ b/example/include/process/command_receiver.hpp @@ -0,0 +1,37 @@ +#ifndef PROCESS_COMMAND_RECEIVER_HPP +#define PROCESS_COMMAND_RECEIVER_HPP + +#include + +#include "process/process_collection.hpp" + +#include "process_command.hpp" + +namespace process::controller { +class CommandListener; + +class CommandReceiver { +public: + CommandReceiver(const std::shared_ptr& collection, + const std::shared_ptr& participant, + const std::string& topic_name); + CommandReceiver(const std::shared_ptr& collection, + const std::shared_ptr& participant, + const std::string& topic_name, + const std::function& validator); + virtual ~CommandReceiver() = default; + + CommandReceiver(CommandReceiver&&) = delete; + CommandReceiver& operator=(CommandReceiver&&) & = delete; + CommandReceiver(const CommandReceiver&) = delete; + CommandReceiver& operator=(const CommandReceiver&) & = delete; + +private: + const std::string m_participant_topic; + std::shared_ptr m_cmd_listener; + std::shared_ptr participant; + std::shared_ptr> subscriber; +}; +} + +#endif //PROCESS_COMMAND_RECEIVER_HPP diff --git a/example/include/process/default_controller.hpp b/example/include/process/default_controller.hpp new file mode 100644 index 0000000..1da7584 --- /dev/null +++ b/example/include/process/default_controller.hpp @@ -0,0 +1,36 @@ +#ifndef PROCESS_DEFAULT_CONTROLLER_HPP +#define PROCESS_DEFAULT_CONTROLLER_HPP + +#include +#include +#include +#include + +namespace process::controller { +class ProcessCollection; + +class CommandReceiver; +class DefinitionReceiver; + +class DefaultProcessController { +public: + DefaultProcessController(std::shared_ptr collection, const std::string& node_name, + const std::string& transport, const std::string& ctrl_prefix, const std::string& info_prefix); + + virtual ~DefaultProcessController() = default; + + void start(); + + void stop(); + +private: + std::shared_ptr m_cfg; + std::shared_ptr m_participant; + std::shared_ptr m_collection; + std::shared_ptr m_definition_receiver; + std::shared_ptr m_command_receiver; + Watchdog m_watchdog; +}; +} + +#endif diff --git a/example/include/process/default_controller_topics.hpp b/example/include/process/default_controller_topics.hpp new file mode 100644 index 0000000..6ace459 --- /dev/null +++ b/example/include/process/default_controller_topics.hpp @@ -0,0 +1,21 @@ +#ifndef PROCESS_DEFAULT_CONTROLLER_TOPICS_HPP +#define PROCESS_DEFAULT_CONTROLLER_TOPICS_HPP + +#include + +namespace process::controller { +struct DefaultTopics { + static const std::string TOPIC; + static const std::string TOPIC_COMMAND; + static const std::string TOPIC_DEFINITIONS; + + static const std::string TOPIC_NODE; + static const std::string TOPIC_NODE_STATS; + + static const std::string TOPIC_PROC; + static const std::string TOPIC_PROC_STATE; + static const std::string TOPIC_PROC_STATS; +}; +} + +#endif /* PROCESS_DEFAULT_CONTROLLER_TOPICS_HPP */ diff --git a/example/include/process/definition_receiver.hpp b/example/include/process/definition_receiver.hpp new file mode 100644 index 0000000..a4ee945 --- /dev/null +++ b/example/include/process/definition_receiver.hpp @@ -0,0 +1,24 @@ +#ifndef PROCESS_LIBPROCESS_EXT_INCLUDE_DEFINITION_RECEIVER_HPP +#define PROCESS_LIBPROCESS_EXT_INCLUDE_DEFINITION_RECEIVER_HPP + +#include + +#include +#include "process_definition.hpp" // TODO generate to + +namespace process::controller { +class DefinitionListener; + +class DefinitionReceiver { +public: + DefinitionReceiver(std::shared_ptr collection, std::shared_ptr participant, const std::string& topic_name); + virtual ~DefinitionReceiver() = default; + +protected: //for testing purposes + std::shared_ptr m_def_listener; + std::shared_ptr m_participant; + std::shared_ptr> m_subscriber; +}; +} + +#endif //PROCESS_LIBPROCESS_EXT_INCLUDE_DEFINITION_RECEIVER_HPP diff --git a/example/include/process/filesystem.hpp b/example/include/process/filesystem.hpp new file mode 100644 index 0000000..0b86d8f --- /dev/null +++ b/example/include/process/filesystem.hpp @@ -0,0 +1,28 @@ +#ifndef PROCESS_FILESYSTEM_HPP +#define PROCESS_FILESYSTEM_HPP + +#include +#include + +namespace process { +class Filesystem { +public: + Filesystem() = default; + + Filesystem(const Filesystem&) = default; + + virtual ~Filesystem() noexcept = default; + + Filesystem& operator=(const Filesystem&) & = default; + + Filesystem& operator=(Filesystem&&) & = default; + + Filesystem(Filesystem&&) = default; + + [[nodiscard]] virtual std::shared_ptr open_read(const std::string& path) const; + + [[nodiscard]] virtual uint32_t get_folder_size(const std::string& path) const; +}; +} + +#endif diff --git a/example/include/process/libprocess_export.hpp b/example/include/process/libprocess_export.hpp new file mode 100644 index 0000000..cfedb24 --- /dev/null +++ b/example/include/process/libprocess_export.hpp @@ -0,0 +1,42 @@ + +#ifndef LIBPROCESS_EXPORT_H +#define LIBPROCESS_EXPORT_H + +#ifdef LIBPROCESS_STATIC_DEFINE +# define LIBPROCESS_EXPORT +# define LIBPROCESS_NO_EXPORT +#else +# ifndef LIBPROCESS_EXPORT +# ifdef libprocess_EXPORTS + /* We are building this library */ +# define LIBPROCESS_EXPORT +# else + /* We are using this library */ +# define LIBPROCESS_EXPORT +# endif +# endif + +# ifndef LIBPROCESS_NO_EXPORT +# define LIBPROCESS_NO_EXPORT +# endif +#endif + +#ifndef LIBPROCESS_DEPRECATED +# define LIBPROCESS_DEPRECATED +#endif + +#ifndef LIBPROCESS_DEPRECATED_EXPORT +# define LIBPROCESS_DEPRECATED_EXPORT LIBPROCESS_EXPORT LIBPROCESS_DEPRECATED +#endif + +#ifndef LIBPROCESS_DEPRECATED_NO_EXPORT +# define LIBPROCESS_DEPRECATED_NO_EXPORT LIBPROCESS_NO_EXPORT LIBPROCESS_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef LIBPROCESS_NO_DEPRECATED +# define LIBPROCESS_NO_DEPRECATED +# endif +#endif + +#endif /* LIBPROCESS_EXPORT_H */ diff --git a/example/include/process/node_checker.hpp b/example/include/process/node_checker.hpp new file mode 100644 index 0000000..6f2b30a --- /dev/null +++ b/example/include/process/node_checker.hpp @@ -0,0 +1,31 @@ +#ifndef PROCESS_LIBPROCESS_EXT_INCLUDE_NODE_CHECKER_HPP +#define PROCESS_LIBPROCESS_EXT_INCLUDE_NODE_CHECKER_HPP + +#include + +#include "node_statistic.hpp" +#include + +namespace process::controller { +class NodeOSInterface; + +class NodeCheckerCallback { +public: + virtual void on_node_statistic_changed(const ::process::controller::NodeStatistic& ps) = 0; +}; + +class NodeChecker : public WatchdogChecker { +public: + //TODO default OSInterface in constructor, here should be nullptr if there are include problems/forward declare? + NodeChecker(std::shared_ptr cb, + std::shared_ptr interface = nullptr); + + void check() override; + +protected: + std::shared_ptr m_interface; + ::process::controller::NodeStatistic m_stat; +}; +} + +#endif diff --git a/example/include/process/predicate.hpp b/example/include/process/predicate.hpp new file mode 100644 index 0000000..eefc8df --- /dev/null +++ b/example/include/process/predicate.hpp @@ -0,0 +1,76 @@ +#ifndef PROCESS_CONTROLLER_PREDICATE_HPP +#define PROCESS_CONTROLLER_PREDICATE_HPP + +#include "process_definition.hpp" // TODO: generate to /idl/process/process_definition.hpp + +#include +#include +#include + +namespace process::controller { +namespace predicate { + /** + * combines two predicates into one using a given binary operation + */ + template + [[nodiscard]] inline auto combine(const P1& p1, const P2& p2, const Op op) noexcept -> std::function + { + static_assert(std::is_invocable_r_v); + static_assert(std::is_invocable_r_v); + static_assert(std::is_invocable_r_v); + return [p1, p2, op](const ProcessDefinition& arg) noexcept -> bool { + static_assert(std::is_invocable_r_v); + static_assert(std::is_invocable_r_v); + static_assert(std::is_invocable_r_v); + return op(p1(arg), p2(arg)); + }; + } + + /** + * combines two predicates using logical or + * + * returns a function operating on the same argument as p1 and p2 + */ + template + [[nodiscard]] inline auto Or(const P1& p1, const P2& p2) noexcept -> std::function + { + return combine(p1, p2, std::logical_or {}); + } + + /** + * equivalent to `const true` + */ + [[nodiscard]] constexpr bool allow_all(const ProcessDefinition&) noexcept { return true; } + + /** + * returns a function that checks whether the node of a ProcessDefinition equals a given string + */ + [[nodiscard]] inline std::function node_equals(const std::string& node) noexcept + { + return [node](const ProcessDefinition& pd) noexcept -> bool { + return pd.node() == node; + }; + } + + /** + * returns true iff the node specifies "any node", i.e. '*' + */ + [[nodiscard]] inline std::function is_any_node() noexcept + { + return node_equals("*"); + } + + /** + * returns a function that checks whether the node of a ProcessDefinition matches a given pattern + * + * TODO implement more sophisticated glob matching, we currently support '*' and exact match + */ + [[nodiscard]] inline std::function node_matches(const std::string& pattern) noexcept + { + return Or(is_any_node(), node_equals(pattern)); + } + +} +} + +#endif /* PROCESS_CONTROLLER_PREDICATE_HPP */ diff --git a/example/include/process/process.hpp b/example/include/process/process.hpp new file mode 100644 index 0000000..aafc6ea --- /dev/null +++ b/example/include/process/process.hpp @@ -0,0 +1,97 @@ +#ifndef PROCESS_LIBPROCESS_INCLUDE_PROCESS_HPP +#define PROCESS_LIBPROCESS_INCLUDE_PROCESS_HPP + +#include + +#include "process/libprocess_export.hpp" + +#include "process_status.hpp" +#include "process_statistic.hpp" + +namespace process::controller { +class ProcessDefinition; +} + +namespace process { +/** + Process interface expected to be used by library user. + + This interface represents a process, be it for a console application, + a window application or a services. + + Processes can be started, stopped or terminated using this interfaces. + + Instances of this interface are created through the factory method + create_process_for() declared in process_factory. + + This file is a public header, that is, one that a user of libprocess is + expected to see and use. +*/ +class LIBPROCESS_EXPORT Process { +public: + virtual ~Process() = default; + Process(Process const&) = delete; + Process& operator=(Process const&) & = delete; + Process(Process&&) = delete; + Process& operator=(Process&&) & = delete; + /** + Start this process. + + Attempts to start process. + @throws ProcessAlreadyStartedException if process is already running + @throws ProcessStartException if start failed for some reason + @throws ProcessUpdateException if updating the process (essentially calling Process::update()) failed + */ + virtual void start() = 0; + /** + Stop this process. + + Attempts to stop process. + @throws ProcessAlreadyStoppedException if process is already stopped + @throws ProcessStopException if stop failed for some reason + @throws ProcessUpdateException if updating the process (essentially calling Process::update()) failed + */ + virtual void stop() = 0; + /** + Terminates this process. + + Attempts to terminate this process. THIS IS ONLY A LAST RESORT WAY TO STOP A PROCESS! + @throws ProcessAlreadyStoppedException if process is already stopped + @throws ProcessTerminationException if terminate failed for some reason + @throws ProcessUpdateException if updating the process (essentially calling Process::update()) failed + */ + virtual void terminate() = 0; + /** + Update the process, that is, its state. + + Attempts to update the state of the process (currently just whether or not it is running and its PID). + May at a later time also update resource consumption. + @throws ProcessUpdateException if updating the process (essentially calling Process::update()) failed + */ + virtual void update() = 0; + /** + Check whether or not the process is running. + */ + virtual bool is_running() const = 0; + /** + Retrieve the process definition used to create this process. + + @returns process definition + */ + virtual const controller::ProcessDefinition& get_definition() const = 0; + + /** + Retrieve the process status. + + The process status is updated on every call to @ref Process::update(). + + @param status Struct contains all available status information + */ + virtual std::pair get_status() const = 0; + +protected: + Process() = default; +}; +} + +#endif diff --git a/example/include/process/process_checker.hpp b/example/include/process/process_checker.hpp new file mode 100644 index 0000000..c144fd4 --- /dev/null +++ b/example/include/process/process_checker.hpp @@ -0,0 +1,31 @@ +#ifndef PROCESS_LIBPROCESS_EXT_INCLUDE_PROCESS_CHECKER_HPP +#define PROCESS_LIBPROCESS_EXT_INCLUDE_PROCESS_CHECKER_HPP + +#include +#include "process_statistic.hpp" +#include "process_status.hpp" + +namespace process::controller { +class ProcessCheckerCallback { +public: + virtual void on_process_status_changed(const ProcessStatus& ps) = 0; + + virtual void on_process_statistic_changed(const ProcessStatistic& ps) = 0; +}; + +class ProcessChecker : public WatchdogChecker { +public: + ProcessChecker(std::shared_ptr collection, std::shared_ptr cb); + + void check() override; + +private: + void check_process(const std::shared_ptr& process); + + using ProcessDataMap = std::map>; + ProcessDataMap m_process_data; + const std::shared_ptr m_collection; +}; +} + +#endif diff --git a/example/include/process/process_collection.hpp b/example/include/process/process_collection.hpp new file mode 100644 index 0000000..456e4c8 --- /dev/null +++ b/example/include/process/process_collection.hpp @@ -0,0 +1,80 @@ +#ifndef PROCESS_PROCESS_COLLECTION_HPP +#define PROCESS_PROCESS_COLLECTION_HPP + +#include +#include + +#include +#include + +namespace process::controller { +class ProcessDefinition; +/** + @TODO This collection holds up to N ProcessDefinitions with 0 or 1 Process created. + Each of N definition is unique by definition. + Todo: Check uniqueness of added definition! + Currently there is a scope lock inside for_each() function (because of maybe invalidated iter). + This blocks all concurrent action in all other threads. + ToDo: Reduce lock contention. + Proposal: Change vector to list. Do not remove an element from that list + in case the corresponding process has been stopped. Only insert at end of list. + Unless any element is deleted the collection is thread safe. + Use lock to get valid begin() and end() iterator only. Release lock afterwards + and iter through collection without lock. +*/ +class ProcessCollection { + using create_process_fn = std::function( + const process::controller::ProcessDefinition& pd)>; + +public: + /// Initialize the create_process_for function with an own implementation + explicit ProcessCollection(create_process_fn create_process_for_f) noexcept(false); + + ProcessCollection(create_process_fn create_process_for_f, + std::function predicate) noexcept(false); + + /** + * Add a process using its definition. + * + * The definition gets passed to a predicate function deciding whether to + * accept it or not. + * + * @return true iff it was added to the collection, false otherwise + */ + void add(const process::controller::ProcessDefinition& definition); + + /** + * Lookup a single process by its id. + * + * @return the process or null if it wasn't found + */ + std::shared_ptr get(const std::string& pd_id) const; + + /** + * Iterate over all processes while holding the monitor lock. + */ + void for_each(const std::function)>& pred) const; + + /** + * + * @return the number of registered processes + */ + size_t size() const noexcept; + +private: + /** + @return Searches and returns process with a given process definition ID. Nullptr if not found. + @param pd_id ID of process definition + @note Does not lock any mutex. + */ + std::shared_ptr lookup(const std::string& pd_id) const; + + mutable std::shared_mutex m_mutex; + std::vector> m_processes; + create_process_fn m_create_process; + + std::function m_predicate; +}; +} + +#endif diff --git a/example/include/process/process_exceptions.hpp b/example/include/process/process_exceptions.hpp new file mode 100644 index 0000000..0d6da29 --- /dev/null +++ b/example/include/process/process_exceptions.hpp @@ -0,0 +1,114 @@ +#ifndef PROCESS_LIBPROCESS_INCLUDE_PROCESS_EXCEPTIONS_HPP +#define PROCESS_LIBPROCESS_INCLUDE_PROCESS_EXCEPTIONS_HPP +#include + +namespace process { +/** + Base class for all libprocess exceptions +*/ +class ProcessException : public std::runtime_error { +public: + explicit ProcessException(const std::basic_string& what) noexcept + : std::runtime_error(what) + { + } + + ~ProcessException() override = default; + ProcessException(ProcessException const&) = delete; + ProcessException& operator=(ProcessException const&) & = delete; + ProcessException(ProcessException&&) = delete; + ProcessException& operator=(ProcessException&&) & = delete; +}; + +/** + Thrown if something goes wrong during process creation +*/ +class ProcessCreationException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessCreationException() override = default; + ProcessCreationException(ProcessCreationException const&) = delete; + ProcessCreationException& operator=(ProcessCreationException const&) & = delete; + ProcessCreationException(ProcessCreationException&&) = delete; + ProcessCreationException& operator=(ProcessCreationException&&) & = delete; +}; + +/** + Thrown if something goes wrong while attempting to start a process +*/ +class ProcessStartException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessStartException() override = default; + ProcessStartException(ProcessStartException const&) = delete; + ProcessStartException& operator=(ProcessStartException const&) & = delete; + ProcessStartException(ProcessStartException&&) = delete; + ProcessStartException& operator=(ProcessStartException&&) & = delete; +}; + +/** + Thrown if something goes wrong while attempting to stop a process +*/ +class ProcessStopException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessStopException() override = default; + ProcessStopException(ProcessStopException const&) = delete; + ProcessStopException& operator=(ProcessStopException const&) & = delete; + ProcessStopException(ProcessStopException&&) = delete; + ProcessStopException& operator=(ProcessStopException&&) & = delete; +}; + +/** + Thrown if Process::start() is called but the process is already running +*/ +class ProcessAlreadyStartedException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessAlreadyStartedException() override = default; + ProcessAlreadyStartedException(ProcessAlreadyStartedException const&) = delete; + ProcessAlreadyStartedException& operator=(ProcessAlreadyStartedException const&) & = delete; + ProcessAlreadyStartedException(ProcessAlreadyStartedException&&) = delete; + ProcessAlreadyStartedException& operator=(ProcessAlreadyStartedException&&) & = delete; +}; + +/** + Thrown if Process::stop() is called but the process is already stopped +*/ +class ProcessAlreadyStoppedException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessAlreadyStoppedException() override = default; + ProcessAlreadyStoppedException(ProcessAlreadyStoppedException const&) = delete; + ProcessAlreadyStoppedException& operator=(ProcessAlreadyStoppedException const&) & = delete; + ProcessAlreadyStoppedException(ProcessAlreadyStoppedException&&) = delete; + ProcessAlreadyStoppedException& operator=(ProcessAlreadyStoppedException&&) & = delete; +}; + +/** + Thrown if the state of a process cannot be updated +*/ +class ProcessUpdateException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessUpdateException() override = default; + ProcessUpdateException(ProcessUpdateException const&) = delete; + ProcessUpdateException& operator=(ProcessUpdateException const&) & = delete; + ProcessUpdateException(ProcessUpdateException&&) = delete; + ProcessUpdateException& operator=(ProcessUpdateException&&) & = delete; +}; + +/** + Thrown if the termination of a process fails +*/ +class ProcessTerminationException : public ProcessException { +public: + using ProcessException::ProcessException; + ~ProcessTerminationException() override = default; + ProcessTerminationException(ProcessTerminationException const&) = delete; + ProcessTerminationException& operator=(ProcessTerminationException const&) & = delete; + ProcessTerminationException(ProcessTerminationException&&) = delete; + ProcessTerminationException& operator=(ProcessTerminationException&&) & = delete; +}; +} +#endif \ No newline at end of file diff --git a/example/include/process/process_factory.hpp b/example/include/process/process_factory.hpp new file mode 100644 index 0000000..a54e727 --- /dev/null +++ b/example/include/process/process_factory.hpp @@ -0,0 +1,46 @@ +#ifndef PROCESS_LIBPROCESS_INCLUDE_PROCESS_FACTORY_HPP +#define PROCESS_LIBPROCESS_INCLUDE_PROCESS_FACTORY_HPP + +#include +#include +#include "process/process.hpp" +#include "process/libprocess_export.hpp" + +namespace process::controller { +class ProcessDefinition; +enum class ProcessType : uint32_t; +} + +namespace process { +/** + @brief Factory method that creates Process instances for specific process definitions. + + In order to control a process, you need an instance of Process controlling a process + based on a process description. + + Given a valid process definition, create_process_for will create an appropriate + instance of Process for you. + + Note that multiple calls to create_process_for with the same process definition + will create separate instances of Process for this definition. + + This file is a public header, that is, one that a user of libprocess is + expected to see and use. + @param pd ProcessDefinition to use for the process object + @param user optional parameter if using this library in an application; Required if running as a service. if specified will try to run the process under that user. + Note that this (at least if using windows) only works if that specific user is logged in. + + @note In case function is invoked by multipe threads they must be serialized. +*/ +LIBPROCESS_EXPORT extern std::shared_ptr create_process(const process::controller::ProcessDefinition& pd, const std::string& default_user = ""); + +/** + * @brief creates a Process instance for an already existing process id + + * @param pt Type of process, necessary to order to stop the process correctly + * @return Instance of process for the given process id +*/ +LIBPROCESS_EXPORT extern std::shared_ptr attach_process(const process::controller::ProcessType pt, const os_pid_t os_pid); +} + +#endif diff --git a/example/include/process/process_state_extensions.hpp b/example/include/process/process_state_extensions.hpp new file mode 100644 index 0000000..ab1fa86 --- /dev/null +++ b/example/include/process/process_state_extensions.hpp @@ -0,0 +1,15 @@ +#ifndef PROCESS_LIBPROCESS_INCLUDE_STATE_EXTENSIONS_HPP +#define PROCESS_LIBPROCESS_INCLUDE_STATE_EXTENSIONS_HPP + +#include + +namespace process::controller::extensions { + +inline static bool is_running(const ProcessState state) +{ + return ((state == ProcessState::RUNNING) || (state == ProcessState::RESTARTED)); +} + +} + +#endif //PROCESS_LIBPROCESS_INCLUDE_STATE_EXTENSIONS_HPP diff --git a/example/include/process/service_wrapper.hpp b/example/include/process/service_wrapper.hpp new file mode 100644 index 0000000..c836e88 --- /dev/null +++ b/example/include/process/service_wrapper.hpp @@ -0,0 +1,22 @@ +#ifndef PROCESS_SERVICE_WRAPPER_HPP +#define PROCESS_SERVICE_WRAPPER_HPP + +#include + +namespace process::servicewrapper { + +class ServiceWrapper { +public: + /** + * Tells the wrapper to run the service for execution. + * This will start the service run and will block until + * the service is done or died + * @returns exit code of service implementation; return value for service main + */ + virtual uint32_t run() const = 0; + virtual ~ServiceWrapper() = default; +}; + +} + +#endif //!< PROCESS_SERVICE_WRAPPER_HPP \ No newline at end of file diff --git a/example/include/process/service_wrapper_factory.hpp b/example/include/process/service_wrapper_factory.hpp new file mode 100644 index 0000000..95a5846 --- /dev/null +++ b/example/include/process/service_wrapper_factory.hpp @@ -0,0 +1,23 @@ +#ifndef PROCESS_SERVICE_WRAPPER_FACTORY_HPP +#define PROCESS_SERVICE_WRAPPER_FACTORY_HPP + +#include + +#include +#include + +namespace process::servicewrapper { + +/** +@briefFactory method that creates a service wrapper for a ServicewrapperListener. + +@note THIS METHOD CAN BE USED ONCE AND ONLY ONCE PER EXECUTABLE + +@param listener the actual service implementation. Since this might do other stuff in other threads, we use a shared_ptr +@returns the service wrapper ready to run the service. Call ServiceWrapper::run() to actually execute +*/ +std::unique_ptr make_wrapper(std::shared_ptr listener); + +} + +#endif // !PROCESS_SERVICE_WRAPPER_FACTORY_HPP diff --git a/example/include/process/service_wrapper_listener.hpp b/example/include/process/service_wrapper_listener.hpp new file mode 100644 index 0000000..b163398 --- /dev/null +++ b/example/include/process/service_wrapper_listener.hpp @@ -0,0 +1,38 @@ +#ifndef PROCESS_SERVICE_WRAPPER_LISTENER_HPP +#define PROCESS_SERVICE_WRAPPER_LISTENER_HPP + +#include +#include + +namespace process::servicewrapper { + +/** + * @brief class that houses the actual implementation of a service +*/ +class ServiceWrapperListener { +public: + /* + * Starts the wrapped service. + * + * This is supposed to be a blocking function. Block until your service has a reason to stop, + * either because it is done, because it encountered a fatal error or because it received a + * call to on_stop and is closing down gracefully. + * + * @returns the exit code you want the service to return. + * Note that this may differ from the actual exit code in case the service wrapper encounters + * some platform specific errors + */ + virtual uint32_t on_start() = 0; + /** + * Indicates to the wrapped service that is shall stop, that is, leave the on_start() method + */ + virtual void on_stop() = 0; + /** + Retrieves the internal name of the service + */ + virtual std::string get_name() = 0; + virtual ~ServiceWrapperListener() = default; +}; +} + +#endif diff --git a/example/include/process/watchdog.hpp b/example/include/process/watchdog.hpp new file mode 100644 index 0000000..9e9e293 --- /dev/null +++ b/example/include/process/watchdog.hpp @@ -0,0 +1,89 @@ +#ifndef PROCESS_PROCESS_EXT_INCLUDE_WATCHDOG_HPP +#define PROCESS_PROCESS_EXT_INCLUDE_WATCHDOG_HPP + +#include +#include +#include +#include + +#include // note: Public include from libprocess +#include "process_status.hpp" // note: Though in different folder this is also a public +// include from libprocess. Generated from IDL +#include "process_statistic.hpp" +#include "process/process_collection.hpp" + +namespace process::controller { +class WatchdogCheckerBase { +public: + virtual void check() = 0; +}; + +template +class WatchdogChecker : public WatchdogCheckerBase { + // Add assert to satisfy A14-1-1 + static_assert(std::is_class::value); + +public: + WatchdogChecker(std::shared_ptr cb) + : m_callback(std::move(cb)) + { + if (m_callback.get() == nullptr) { + throw std::runtime_error("invalid callback"); + } + } + +protected: + std::shared_ptr m_callback; +}; + +/** +@brief Periodically updates all provided processes. +@note + - Callback is used to keep class Watchdog free of specific dependencies and user types (No linkage to ASAP) + - Watchdog may be moved into libprocess as well as ProcessCollection + - API of Watchdog itself is not thread safe +*/ +class Watchdog { +public: + /** + @brief Constructs the Watchdog. + @param collection List of all processes which shall be monitored + @param interval_ms All processes are checked periodically using the given interval + @param cb Callback object which will be invoked whenever a status change has been detected + */ + explicit Watchdog(const std::chrono::milliseconds interval_ms); + + Watchdog(const Watchdog& other) = delete; + + Watchdog(Watchdog&& other) = delete; + + Watchdog& operator=(const Watchdog& other) & = delete; + + Watchdog& operator=(Watchdog&& other) & = delete; + + /** This class is not intended to be derived */ + virtual ~Watchdog(); + + /**/ + virtual void add_checker(std::shared_ptr checker); + + /** Watchdog starts processing */ + virtual void start(); + + /** Stops the watchdog worker thread */ + virtual void stop(); + + /** @return true if watchdog has been started and monitors the collection periodically */ + virtual bool is_running() const; + +protected: + virtual void loop(); + + std::chrono::milliseconds m_interval_ms; + std::atomic m_stop_loop; + std::thread m_thread; + std::vector> m_checker; +}; +} + +#endif diff --git a/example/process-defects.err b/example/process-defects.err new file mode 100644 index 0000000..e3a621f --- /dev/null +++ b/example/process-defects.err @@ -0,0 +1,336 @@ +src/software_mc/process_state_collector.hpp:120:ERROR: Newest, autosar_cpp14_a5_1_1_violation: Using literal "1U" other than type initialization, where symbolic names shall be used instead. +src/software_mc/process_state_collector.hpp:100:ERROR: Newest, autosar_cpp14_m8_4_4_violation: Function identifier "is_running" is not used to call the function or preceded by &. +src/software_mc/process_state_collector.hpp:100:ERROR: Newest, autosar_cpp14_m5_0_4_violation: "0" is implicitly converted from a signed value to an unsigned value. +src/software_mc/process_state_collector.hpp:95:ERROR: Newest, autosar_cpp14_a0_1_2_violation: The return value of function "this->m_state.erase(id)" is not used. +src/software_mc/process_state_collector.hpp:90:ERROR: Newest, autosar_cpp14_a0_1_2_violation: The return value of function "this->m_state[id]->erase(ps->_ZNK7process10controller13ProcessStatus5pd_idB5cxx11Ev())" is not used. +src/software_mc/process_state_collector.hpp:23:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::software_mc::ProcessStateCollector" does not declare all five special member functions. +src/software_mc/process_command_distributor.hpp:16:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::software_mc::ProcessCommandDistributor" does not declare all five special member functions. +src/software_mc/main.cpp:46:ERROR: Newest, autosar_cpp14_m8_4_4_violation: Function identifier "endl" is not used to call the function or preceded by &. +src/software_mc/command_acceptance_publisher.hpp:11:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::software_mc::CommandAcceptancePublisher" does not declare all five special member functions. +src/process_controller_svc/process_controller_svc.hpp:56:ERROR: Newest, autosar_cpp14_a7_3_1_violation: member function declaration hides overloaded members in base class +src/process_controller_svc/process_controller_svc.cpp:115:ERROR: Newest, autosar_cpp14_m7_1_2_violation: The virtual function "_ZN7process10controller3svc7Service8get_nameB5cxx11Ev()" or any of its overriding functions do not modify the object pointed to by the this pointer. Consider marking the function const. +src/process_controller_svc/process_controller_ctl.hpp:114:ERROR: Newest, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:243:ERROR: Newest, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:259:ERROR: Newest, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:172:ERROR: Newest, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:78:ERROR: Newest, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/libprocess_controller/node_os_interface.hpp:7:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::NodeOSInterface::operator =(process::controller::NodeOSInterface const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +src/libprocess_controller/node_os_interface.hpp:7:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::NodeOSInterface::NodeOSInterface(process::controller::NodeOSInterface const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +src/libprocess_controller/node_os_interface.hpp:7:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::controller::NodeOSInterface" does not declare all five special member functions. +src/libprocess_controller/default_controller.cpp:63:ERROR: Newest, autosar_cpp14_m8_4_2_violation: Declaration uses a different parameter name than "void process::controller::NodeCheckerCallback::on_node_statistic_changed(const process::controller::NodeStatistic &)". +src/libprocess_controller/default_controller.cpp:48:ERROR: Newest, autosar_cpp14_m8_4_2_violation: Declaration uses a different parameter name than "void process::controller::ProcessCheckerCallback::on_process_status_changed(const process::controller::ProcessStatus &)". +src/libprocess_controller/default_controller.cpp:40:ERROR: Newest, autosar_cpp14_a8_4_7_violation: Passing parameter "node_name" of expensive-to-copy type "std::__cxx11::string" by value. +src/libprocess_controller/default_controller.cpp:25:ERROR: Newest, autosar_cpp14_a8_4_7_violation: Passing parameter "participant" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/default_controller.cpp:25:ERROR: Newest, autosar_cpp14_a7_1_5_violation: Using "auto" as return type specifier to declare template function "::make_publisher(std::shared_ptr, std::__cxx11::string const &)" without trailing return type syntax. +src/libprocess_controller/default_controller.cpp:21:ERROR: Newest, autosar_cpp14_m7_3_4_violation: Using a using-directive for namespace "process::controller". +src/libprocess_controller/default_controller.cpp:20:ERROR: Newest, autosar_cpp14_m7_3_4_violation: Using a using-directive for namespace "std::literals::chrono_literals". +src/libprocess/linux/statistic_api_impl.cpp:213:ERROR: Newest, autosar_cpp14_a13_5_3_violation: Using user-defined conversion operator "stat_file.operator bool()". +src/libprocess/linux/statistic_api_impl.cpp:163:ERROR: Newest, autosar_cpp14_a13_5_3_violation: Using user-defined conversion operator "matches[0UL]->operator std::__cxx11::sub_match<__gnu_cxx::__normal_iterator, std::allocator > > >::string_type()". +src/libprocess/linux/statistic_api_impl.cpp:143:ERROR: Newest, autosar_cpp14_a13_5_3_violation: Using user-defined conversion operator "stat_file.operator bool()". +src/libprocess/linux/statistic_api_factory.cpp:9:ERROR: Newest, autosar_cpp14_m7_1_2_violation: The virtual function "process::statistic::StatisticApiFactory::create()" or any of its overriding functions do not modify the object pointed to by the this pointer. Consider marking the function const. +src/libprocess/linux/service_process.cpp:19:ERROR: Newest, autosar_cpp14_a8_5_2_violation: Initializing variable "unit_name" without using braced-initialization {}. +src/libprocess/linux/process_factory.cpp:19:ERROR: Newest, autosar_cpp14_a7_1_1_violation: The variable "filesystem" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/process_factory.cpp:19:ERROR: Newest, autosar_cpp14_a20_8_4_violation: The ownership of object "filesystem" is not shared. Consider using "std::unique_ptr" instead. +include/process/watchdog.hpp:22:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::WatchdogChecker::WatchdogChecker(process::controller::WatchdogChecker const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/watchdog.hpp:22:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::WatchdogChecker::operator =(process::controller::WatchdogChecker const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/watchdog.hpp:16:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::WatchdogCheckerBase::WatchdogCheckerBase(process::controller::WatchdogCheckerBase const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/service_wrapper_listener.hpp:12:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::servicewrapper::ServiceWrapperListener::operator =(process::servicewrapper::ServiceWrapperListener const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/service_wrapper_listener.hpp:12:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::servicewrapper::ServiceWrapperListener::ServiceWrapperListener(process::servicewrapper::ServiceWrapperListener const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/service_wrapper_listener.hpp:12:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::servicewrapper::ServiceWrapperListener" does not declare all five special member functions. +include/process/service_wrapper.hpp:8:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::servicewrapper::ServiceWrapper::operator =(process::servicewrapper::ServiceWrapper const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/service_wrapper.hpp:8:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::servicewrapper::ServiceWrapper::ServiceWrapper(process::servicewrapper::ServiceWrapper const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/service_wrapper.hpp:8:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::servicewrapper::ServiceWrapper" does not declare all five special member functions. +include/process/process_checker.hpp:13:ERROR: Newest, autosar_cpp14_m7_1_2_violation: The virtual function "process::controller::ProcessCheckerCallback::on_process_statistic_changed(process::controller::ProcessStatistic const &)" or any of its overriding functions do not modify the object pointed to by the this pointer. Consider marking the function const. +include/process/process_checker.hpp:11:ERROR: Newest, autosar_cpp14_m7_1_2_violation: The virtual function "process::controller::ProcessCheckerCallback::on_process_status_changed(process::controller::ProcessStatus const &)" or any of its overriding functions do not modify the object pointed to by the this pointer. Consider marking the function const. +include/process/process_checker.hpp:9:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::ProcessCheckerCallback::operator =(process::controller::ProcessCheckerCallback const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/process_checker.hpp:9:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::ProcessCheckerCallback::ProcessCheckerCallback(process::controller::ProcessCheckerCallback const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/node_checker.hpp:14:ERROR: Newest, autosar_cpp14_m7_1_2_violation: The virtual function "process::controller::NodeCheckerCallback::on_node_statistic_changed(process::controller::NodeStatistic const &)" or any of its overriding functions do not modify the object pointed to by the this pointer. Consider marking the function const. +include/process/node_checker.hpp:12:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::NodeCheckerCallback::operator =(process::controller::NodeCheckerCallback const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/node_checker.hpp:12:ERROR: Newest, autosar_cpp14_a12_8_6_violation: Declaring member function "process::controller::NodeCheckerCallback::NodeCheckerCallback(process::controller::NodeCheckerCallback const &) /*implicit =default*/" without "protected" or "=delete" in the base class. +include/process/definition_receiver.hpp:12:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::controller::DefinitionReceiver" does not declare all five special member functions. +include/process/default_controller.hpp:24:ERROR: Newest, autosar_cpp14_m3_2_4_violation: Function "stop" is declared but never defined. +include/process/default_controller.hpp:24:ERROR: Newest, autosar_cpp14_m3_2_2_violation: Function "stop" is declared but never defined. +include/process/default_controller.hpp:15:ERROR: Newest, autosar_cpp14_a12_0_1_violation: Class "process::controller::DefaultProcessController" does not declare all five special member functions. +src/libprocess_controller/process_checker.cpp:28:INFO: na, autosar_cpp14_a8_5_2_violation: Initializing variable "status" without using braced-initialization {}. +src/libprocess_controller/process_checker.cpp:28:INFO: na, autosar_cpp14_a8_5_2_violation: Initializing variable "stats" without using braced-initialization {}. +src/libprocess_controller/process_checker.cpp:35:INFO: na, autosar_cpp14_a8_5_2_violation: Initializing variable "prev_stats" without using braced-initialization {}. +src/libprocess_controller/process_checker.cpp:35:INFO: na, autosar_cpp14_a8_5_2_violation: Initializing variable "prev_status" without using braced-initialization {}. +src/libprocess_controller/process_checker.cpp:39:ERROR: New, autosar_cpp14_a18_9_2_violation: Forwarding rvalue reference "status" without using "std::move". +src/libprocess_controller/process_checker.cpp:44:ERROR: New, autosar_cpp14_a18_9_2_violation: Forwarding rvalue reference "stats" without using "std::move". +src/libprocess_controller/process_checker.cpp:23:INFO: na, autosar_cpp14_a8_4_13_violation: The parameter "process" of type "std::shared_ptr const &" is not copied in any code path. Considering passing a const lvalue reference to the underlying object instead. +src/libprocess_controller/process_collection.cpp:10:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "create_process_for_f" of expensive-to-copy type "process::controller::ProcessCollection::create_process_fn" by value. +src/libprocess_controller/process_collection.cpp:16:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "create_process_for_f" of expensive-to-copy type "process::controller::ProcessCollection::create_process_fn" by value. +src/libprocess_controller/process_collection.cpp:60:INFO: na, autosar_cpp14_a8_4_13_violation: The parameter "p" of type "process::controller::ProcessCollection::lookup(std::__cxx11::basic_string, std::allocator > const &) const::ProcessPtr const &" is not copied in any code path. Considering passing a const lvalue reference to the underlying object instead. +src/libprocess_controller/node_os_interface_linux.cpp:152:ERROR: New, autosar_cpp14_m5_0_7_violation: There is an explicit floating-integral conversion of cvalue expression "static_cast(user_time_ms) / static_cast(total_time_ms) * 100.". +src/libprocess_controller/node_os_interface_linux.cpp:146:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "v.user - this->m_last_stat.user" may wrap. +src/libprocess_controller/process_collection.cpp:17:INFO: Int, autosar_cpp14_a8_4_7_violation: Passing parameter "predicate" of expensive-to-copy type "std::function" by value. +src/libprocess_controller/node_os_interface_linux.cpp:116:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.guest_nice - last.guest_nice" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:147:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "this->total_time(v, this->m_last_stat) * 10U" may wrap. +src/libprocess_controller/process_checker.cpp:7:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "cb" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user" may wrap. +src/libprocess_controller/process_checker.cpp:7:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "collection" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/watchdog.cpp:16:ERROR: New, autosar_cpp14_a15_5_2_violation: Calling "std::thread::~thread()" which calls function to abruptly terminate the program. +src/libprocess_controller/node_checker.cpp:9:ERROR: New, autosar_cpp14_m16_0_1_violation: #include directive preceded by code. +src/libprocess_controller/node_os_interface_linux.cpp:119:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "fs" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.cpp:108:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.nice - last.nice" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:114:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.steal - last.steal" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:150:ERROR: New, autosar_cpp14_a5_1_1_violation: Using literal "0U" other than type initialization, where symbolic names shall be used instead. +src/libprocess_controller/node_checker.cpp:13:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "interface" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.hpp:77:ERROR: New, autosar_cpp14_a12_0_1_violation: Class "process::controller::impl::NodeOSInterfaceLinux" does not declare all five special member functions. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice)" may wrap. +src/libprocess_controller/process_collection.cpp:16:INFO: Int, autosar_cpp14_a12_1_5_violation: Initializing non-constant members without using delegating constructor. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait) + (actual.irq - last.irq) + (actual.softirq - last.softirq)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait) + (actual.irq - last.irq) + (actual.softirq - last.softirq) + (actual.steal - last.steal) + (actual.guest - last.guest)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:110:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.idle - last.idle" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:115:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.guest - last.guest" may wrap. +src/libprocess_controller/node_checker.cpp:13:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "cb" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.cpp:113:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.softirq - last.softirq" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait) + (actual.irq - last.irq)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle)" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait) + (actual.irq - last.irq) + (actual.softirq - last.softirq) + (actual.steal - last.steal) + (actual.guest - last.guest) + (actual.guest_nice - last.guest_nice)" may wrap. +src/libservicewrapper/linux/linux_service_wrapper.cpp:15:INFO: Int, autosar_cpp14_a8_4_7_violation: Passing parameter "listener" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.cpp:107:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.user - last.user + (actual.nice - last.nice) + (actual.system - last.system) + (actual.idle - last.idle) + (actual.iowait - last.iowait) + (actual.irq - last.irq) + (actual.softirq - last.softirq) + (actual.steal - last.steal)" may wrap. +src/libprocess_controller/watchdog.cpp:18:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "checker" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_os_interface_linux.cpp:112:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.irq - last.irq" may wrap. +src/libprocess_controller/node_os_interface_linux.cpp:111:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.iowait - last.iowait" may wrap. +src/libprocess_controller/watchdog.cpp:15:ERROR: New, autosar_cpp14_m12_1_1_violation: Calling function "process::controller::Watchdog::stop()" which calls virtual function in the constructor or destructor. +src/libprocess_controller/node_os_interface_linux.cpp:109:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "actual.system - last.system" may wrap. +src/process_controller_svc/process_controller_svc_main.cpp:19:ERROR: New, autosar_cpp14_m5_2_9_violation: CastOperator "(__sighandler_t)1" is the cast from an integral type "int" to a pointer type "void (*)(int)". +src/process_controller_svc/process_controller_svc.cpp:71:INFO: Int, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_svc_main.cpp:27:INFO: na, autosar_cpp14_a8_5_2_violation: Initializing variable "create" without using braced-initialization {}. +src/process_controller_svc/process_controller_svc_main.cpp:19:ERROR: New, autosar_cpp14_m0_3_2_violation: Calling "signal(2, (__sighandler_t)0x1)" without checking return value. This function returns error information that should be checked. +src/process_controller_svc/util.cpp:25:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process10controller13generate_uuidB5cxx11Ev". +src/process_controller_svc/process_controller_ctl.cpp:171:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:171:ERROR: New, autosar_cpp14_a14_1_1_violation: function template "lambda [](const auto &)->int" does not use static_assert declarations to ensure template arguments satisfy the required interface +src/process_controller_svc/process_controller_ctl.cpp:27:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/process_controller_svc/process_controller_ctl.cpp:168:INFO: Int, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:24:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/process_controller_svc/process_controller_ctl.cpp:21:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/process_controller_svc/process_controller_ctl.cpp:159:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "std::ostream &" in function "process::controller::ctl::ClientImpl::ClientImpl(process::controller::ctl::Config const &, process::controller::ProcessControllerService &, std::ostream &, std::ostream &)". +src/process_controller_svc/process_controller_ctl.cpp:32:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_ctl.cpp:137:ERROR: New, autosar_cpp14_a5_1_1_violation: Using literal ""stress"" other than type initialization, where symbolic names shall be used instead. +src/libprocess_controller/definition_receiver_listener.hpp:25:INFO: Int, autosar_cpp14_a15_3_4_violation: Using catch-all handler in function "process::controller::DefinitionListener::on_data_available(process::controller::ProcessDefinition const &, asap::SampleInfo const &)", which is not a main function, a task main function, a function of isolating independent components or a function calling third-party code. +src/libprocess_controller/default_controller.cpp:71:INFO: Int, autosar_cpp14_a2_5_2_violation: Using digraphs "<:". +include/process/libprocess_export.hpp:38:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/software_mc/main.cpp:69:INFO: na, autosar_cpp14_a7_1_1_violation: The variable "cmd_acceptance_publisher" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/software_mc/process_command_distributor.cpp:67:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "++this->m_subscriber_seq_nr" may wrap. +src/software_mc/main.cpp:70:ERROR: New, autosar_cpp14_a18_9_1_violation: Using "std::bind". +src/software_mc/main.cpp:65:INFO: Int, autosar_cpp14_a20_8_6_violation: Object "std::unique_ptr >(asap::Configuration::read_configuration(asap_transport))" is not constructed using "std::make_shared". +src/software_mc/process_state_collector.hpp:120:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "matches += 1UL" may wrap. +src/software_mc/process_command_distributor.hpp:27:ERROR: New, autosar_cpp14_m11_0_1_violation: Member "process_state_collector" is not private but "process::software_mc::ProcessCommandDistributor::Configuration" is a non-POD type. +src/software_mc/process_command_distributor.hpp:29:ERROR: New, autosar_cpp14_a12_0_1_violation: Class "process::software_mc::ProcessCommandDistributor::Listener" does not declare all five special member functions. +src/software_mc/process_command_distributor.hpp:33:ERROR: New, autosar_cpp14_m8_4_2_violation: Declaration uses a different parameter name than "void asap::DataAvailableListener::on_data_available(const SAMPLE_T &, const asap::SampleInfo &) [with SAMPLE_T=process::software_mc::CommandRequestPayload]". +src/software_mc/process_state_collector.hpp:114:ERROR: New, autosar_cpp14_a8_4_10_violation: The parameter "pred", which can't be "NULL", shall be passed by reference. +src/software_mc/process_state_collector.hpp:107:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal "" process(es) stopped"" other than type initialization, where symbolic names shall be used instead. +src/software_mc/process_command_distributor.hpp:43:INFO: Int, autosar_cpp14_a11_3_1_violation: Using "friend" declaration. +src/software_mc/command_acceptance_publisher.cpp:22:ERROR: New, autosar_cpp14_a2_7_2_violation: The comment resembles a code snippet. +src/software_mc/command_acceptance_publisher.cpp:37:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""no data"" other than type initialization, where symbolic names shall be used instead. +src/software_mc/command_acceptance_publisher.cpp:19:ERROR: New, autosar_cpp14_a12_7_1_violation: Defining a special member function "process::software_mc::CommandAcceptancePublisher::~CommandAcceptancePublisher()" which is identical to implicitly defined one. +include/process/predicate.hpp:68:INFO: na, autosar_cpp14_a7_1_8_violation: "inline" is placed after type specifier. +src/libprocess_controller/definition_receiver_listener.hpp:14:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "collection" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/definition_receiver.cpp:9:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "participant" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/definition_receiver.cpp:9:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "collection" of expensive-to-copy type "std::shared_ptr" by value. +include/process/predicate.hpp:43:INFO: na, autosar_cpp14_a7_1_8_violation: "constexpr" is placed after type specifier. +src/process_ender/main.cpp:17:INFO: na, autosar_cpp14_m3_2_2_violation: Symbol "main" is defined more than once. +src/process_ender/main.cpp:17:INFO: na, autosar_cpp14_m3_2_4_violation: Symbol "main" is defined more than once. +src/libprocess_controller/command_receiver.cpp:12:INFO: Int, autosar_cpp14_a8_4_8_violation: Using output parameter "process::Process &" in function "::idempotent_start(process::Process &)". +src/process_controller_svc/process_controller_svc.cpp:74:INFO: Int, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/process_controller_svc/process_controller_svc.cpp:92:WARNING: Fix, autosar_cpp14_m12_1_1_violation: Calling function "process::controller::svc::Service::stop()" which calls virtual function in the constructor or destructor. +src/process_controller_svc/process_controller_asap_config.hpp:13:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "prefix_info" is not private but "process::controller::AsapConfig" is a non-POD type. +src/process_controller_svc/process_controller_svc.cpp:76:INFO: Int, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/libprocess_controller/default_controller_topics.cpp:12:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""_state"" other than type initialization, where symbolic names shall be used instead. +src/software_mc/main.cpp:96:ERROR: New, autosar_cpp14_a5_1_1_violation: Using literal "1" other than type initialization, where symbolic names shall be used instead. +src/process_controller_svc/process_controller_asap_client.hpp:19:INFO: Int, autosar_cpp14_a20_8_6_violation: Object "std::unique_ptr >(asap::Configuration::read_configuration(cfg.uri))" is not constructed using "std::make_shared". +src/process_controller_svc/process_controller_ctl.cpp:78:ERROR: New, autosar_cpp14_a4_7_1_violation: Converting "static_cast(argv.size())" from "64-bit unsigned long" to "32-bit signed int" may lead to data loss. +src/libprocess_controller/command_receiver.cpp:33:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "process" is not private but "process::controller::CommandListener::Start" is a non-POD type. +src/process_controller_svc/util.hpp:116:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process10controller13generate_uuidB5cxx11Ev". +src/libprocess_controller/command_receiver.cpp:19:INFO: Int, autosar_cpp14_a8_4_8_violation: Using output parameter "process::Process &" in function "::idempotent_stop(process::Process &)". +include/process/filesystem.hpp:24:INFO: na, autosar_cpp14_a7_1_8_violation: "virtual" is placed after type specifier. +src/process_controller_svc/process_controller_ctl.cpp:171:ERROR: New, autosar_cpp14_a5_1_4_violation: Returning lambda object "process::controller::ctl::ClientImpl::run(std::vector, std::allocator >, std::allocator, std::allocator > > > const &)::[lambda(T1 const &) (instance 1)](this)" which captures object by reference directly by return statement. +src/libprocess_controller/command_receiver.cpp:40:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "process" is not private but "process::controller::CommandListener::Stop" is a non-POD type. +src/process_controller_svc/process_controller_ctl.hpp:92:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "std::ostream &" in function "process::controller::ctl::ClientImpl::ClientImpl(process::controller::ctl::Config const &, process::controller::ProcessControllerService &, std::ostream &, std::ostream &)". +src/process_controller_svc/process_controller_svc.cpp:58:INFO: Int, autosar_cpp14_a4_7_1_violation: Converting "static_cast(argv.size())" from "64-bit unsigned long" to "32-bit signed int" may lead to data loss. +src/libservicewrapper/service_wrapper_factory.cpp:16:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/libprocess_controller/node_os_interface_linux.cpp:4:ERROR: New, autosar_cpp14_a16_2_2_violation: Include /usr/include/unistd.h is unused. +include/process/definition_receiver.hpp:20:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "m_subscriber" is not private but "process::controller::DefinitionReceiver" is a non-POD type. +src/libprocess_controller/node_checker.cpp:11:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/libservicewrapper/service_wrapper_factory.cpp:10:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "listener" of expensive-to-copy type "std::shared_ptr" by value. +src/libprocess_controller/node_checker.cpp:8:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +include/process/node_checker.hpp:27:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "m_stat" is not private but "process::controller::NodeChecker" is a non-POD type. +src/libprocess_controller/node_checker.cpp:5:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/libservicewrapper/service_wrapper_factory.cpp:14:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/libprocess_controller/node_os_interface_linux.cpp:5:ERROR: New, autosar_cpp14_a16_2_2_violation: Include /usr/include/sys/types.h is unused. +include/process/watchdog.hpp:36:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "m_callback" is not private but "process::controller::WatchdogChecker" is a non-POD type. +include/process/watchdog.hpp:85:INFO: Int, autosar_cpp14_m11_0_1_violation: Member "m_checker" is not private but "process::controller::Watchdog" is a non-POD type. +src/libservicewrapper/service_wrapper_factory.cpp:12:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/libprocess_controller/node_os_interface_linux.cpp:6:ERROR: New, autosar_cpp14_a16_2_2_violation: Include /usr/include/sys/param.h is unused. +include/process/libprocess_export.hpp:13:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +include/process/libprocess_export.hpp:10:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +include/process/libprocess_export.hpp:32:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +include/process/libprocess_export.hpp:39:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +include/process/libprocess_export.hpp:36:ERROR: New, autosar_cpp14_a16_0_1_violation: Using preprocessor features for something other than include guards or file inclusion. +src/software_mc/main.cpp:21:INFO: Int, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "main(int32_t, char **)". +src/libprocess/linux/service_process.cpp:19:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "unit_name" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/process_controller_svc/util.hpp:26:ERROR: New, autosar_cpp14_m3_4_1_violation: Symbol "ConfigurationReaderException" should be defined at block scope. +src/libprocess/process_base.cpp:19:ERROR: New, autosar_cpp14_m12_1_1_violation: Calling virtual function "process::ProcessBase::get_definition() const" in the constructor or destructor. +src/libprocess/process_base.cpp:23:ERROR: New, autosar_cpp14_m12_1_1_violation: Calling function "process::ProcessBase::change_state(process::os_pid_t, process::detail::UpdateReason, std::optional)" which calls virtual function in the constructor or destructor. +src/libprocess/linux/console_process.cpp:18:ERROR: New, autosar_cpp14_m12_1_1_violation: Calling function "process::ProcessBase::change_state(process::os_pid_t, process::detail::UpdateReason, std::optional)" which calls virtual function in the constructor or destructor. +src/process_controller_svc/process_controller_mon.cpp:29:ERROR: New, autosar_cpp14_a3_3_1_violation: Declaration of symbols with external linkage outside of headers. +src/libprocess/statistic_api_factory.hpp:19:INFO: na, autosar_cpp14_a7_1_8_violation: "virtual" is placed after type specifier. +src/libprocess/process_base.cpp:168:ERROR: New, autosar_cpp14_m5_0_2_violation: "exit_code.value() == 0" should be parenthesized. +src/libprocess/process_base.cpp:168:ERROR: New, autosar_cpp14_a5_2_6_violation: Operand "exit_code.value() == 0" is not a postfix expression. +src/process_ender/process_ender.cpp:47:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZZN7process7utility5ender12stop_processB5cxx11ERKSt10shared_ptrINS_7ProcessEEEUlRS3_E_". +src/process_ender/process_ender.cpp:22:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender11_GLOBAL__N_17kill_process_withIZNS1_12stop_processB5cxx11ERKSt10shared_ptrINS_7ProcessEEEUlRS5_E_EESt5tupleIJiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEES8_T_". +src/process_ender/process_ender.cpp:22:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender11_GLOBAL__N_17kill_process_withIZNS1_17terminate_processB5cxx11ERKSt10shared_ptrINS_7ProcessEEEUlRS5_E_EESt5tupleIJiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEES8_T_". +src/process_ender/process_ender.cpp:53:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZZN7process7utility5ender17terminate_processB5cxx11ERKSt10shared_ptrINS_7ProcessEEEUlRS3_E_". +src/process_controller_svc/process_controller_mon.cpp:80:ERROR: New, autosar_cpp14_m5_0_11_violation: Object "'q'" with plain char type is used with its non-character values. +src/libprocess/process_base.cpp:246:INFO: Int, autosar_cpp14_a20_8_6_violation: Object "std::move(this->m_cpu_usage)" is not constructed using "std::make_shared". +src/libprocess/linux/linux_os_api_impl.hpp:58:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:38:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.hpp:35:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:59:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait + stat.irq + stat.softirq + stat.steal" may wrap. +src/libprocess/linux/linux_os_api_impl.cpp:207:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_s(sd_bus_message *, char const **) const". +src/libprocess/linux/linux_os_api_impl.hpp:20:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:136:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "_ZN7process14LinuxOsApiImpl6to_setB5cxx11EPPc(char **)". +src/libprocess/linux/linux_os_api_impl.cpp:26:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:139:ERROR: New, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZZN7process14LinuxOsApiImpl6to_setB5cxx11EPPcEUlPKcE_". +src/libprocess/linux/statistic_api_impl.hpp:112:ERROR: New, autosar_cpp14_a8_4_9_violation: The in-out parameter "s" is not modified. +src/libprocess/linux/linux_os_api_impl.hpp:60:ERROR: New, autosar_cpp14_a7_1_8_violation: "static" is placed after type specifier. +src/libprocess/linux/linux_os_api_impl.hpp:41:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_o(sd_bus_message *, char const **) const". +src/libprocess/linux/linux_os_api_impl.hpp:19:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:21:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char *". +src/libprocess/linux/linux_os_api.hpp:58:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/service_process.cpp:40:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""Received this SdBusException message: "" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api.hpp:42:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/service_process.cpp:106:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""Received this SdBusException message: "" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api_impl.hpp:35:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApiImpl::sd_bus_call_method_s(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *) const". +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait + stat.irq + stat.softirq" may wrap. +src/libprocess/linux/linux_os_api_impl.hpp:23:ERROR: New, autosar_cpp14_m3_9_1_violation: Redeclaration of object/function is typename incompatible with "int32_t process::LinuxOsApi::execvpe(const char *, char *const *, char *const *) const". +src/libprocess/linux/linux_os_api.hpp:65:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:110:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:139:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:148:ERROR: New, autosar_cpp14_a5_0_3_violation: The fourth parameter of the function "sd_uid_get_sessions" is declared with a type that has more than two levels of pointer nesting. +src/libprocess/linux/linux_os_api_impl.hpp:68:ERROR: New, autosar_cpp14_a18_9_2_violation: Forwarding rvalue reference "fun" without using "std::move". +src/libprocess/linux/linux_os_api_impl.hpp:35:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.hpp:58:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "process::LinuxOsApiImpl::destroy_sessions(char **)". +src/libprocess/linux/linux_os_api_impl.hpp:41:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api.hpp:64:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApi::sd_bus_message_read_o(sd_bus_message *, char const **) const". +src/libprocess/process_base.cpp:224:ERROR: New, autosar_cpp14_a5_1_1_violation: Using literal "0U" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api_impl.cpp:230:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait" may wrap. +src/libprocess/linux/linux_os_api.hpp:74:ERROR: New, autosar_cpp14_a7_1_8_violation: "virtual" is placed after type specifier. +src/libprocess/linux/linux_os_api.hpp:42:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char *". +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "process::LinuxOsApiImpl::for_each_session(char **, process::LinuxOsApiImpl::destroy_sessions(char **)::[lambda(char *) (instance 1)] const &&)". +src/libprocess/linux/linux_os_api_impl.cpp:148:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "sessions" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "_ZN7process14LinuxOsApiImpl16for_each_sessionIZNS0_6to_setB5cxx11EPPcEUlPKcE_S3_EEvT0_OKT_(char **, _ZZN7process14LinuxOsApiImpl6to_setB5cxx11EPPcEUlPKcE_ const &&)". +src/libprocess/linux/linux_os_api_impl.cpp:153:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:62:ERROR: New, autosar_cpp14_a7_1_8_violation: "virtual" is placed after type specifier. +src/libprocess/linux/linux_os_api_impl.hpp:42:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:139:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:32:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "this->read_statm(pid).resident * page_size" may wrap. +src/libprocess/linux/linux_os_api_impl.hpp:62:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:26:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:191:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApiImpl::sd_bus_call_method_ss(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *, char const *) const". +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait + stat.irq + stat.softirq + stat.steal + stat.guest + stat.guest_nice" may wrap. +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait + stat.irq + stat.softirq + stat.steal + stat.guest" may wrap. +src/libprocess/linux/linux_os_api_impl.cpp:132:ERROR: New, autosar_cpp14_a18_5_1_violation: Invoking "free". +src/libprocess/linux/linux_os_api_impl.hpp:67:ERROR: New, autosar_cpp14_m5_0_15_violation: Using arithmetic on pointer "session". +src/libprocess/linux/linux_os_api_impl.cpp:42:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.hpp:67:ERROR: New, autosar_cpp14_m5_0_15_violation: Using arithmetic on pointer "session". +src/libprocess/linux/console_process.cpp:39:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""setuid"" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api_impl.cpp:153:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api.hpp:46:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:42:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "argv" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/linux_os_api_impl.hpp:8:ERROR: New, autosar_cpp14_m3_2_2_violation: Symbol "LinuxOsApiImpl" is defined more than once and the definitions violate the one definition rule. +src/libprocess/linux/linux_os_api_impl.cpp:42:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:138:ERROR: New, autosar_cpp14_m8_5_2_violation: "ret" is not completely initialized. +src/libprocess/linux/linux_os_api_impl.cpp:153:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "display" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice" may wrap. +src/libprocess/linux/linux_os_api_impl.cpp:120:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api.hpp:58:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApi::sd_bus_call_method_s(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *) const". +src/libprocess/linux/linux_os_api_impl.cpp:111:ERROR: New, autosar_cpp14_a20_8_5_violation: Object "sessions, std::remove_reference::type(&destroy_sessions)" is not constructed using "std::make_unique". +src/libprocess/linux/linux_os_api_impl.cpp:73:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "int32_t *" in function "process::LinuxOsApiImpl::waitpid(process::os_pid_t, int32_t *, int32_t) const". +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle" may wrap. +src/libprocess/linux/linux_os_api_impl.cpp:230:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api.hpp:46:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:214:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_u(sd_bus_message *, process::os_pid_t *) const". +src/libprocess/linux/linux_os_api_impl.cpp:131:ERROR: New, autosar_cpp14_a18_5_1_violation: Invoking "free". +src/libprocess/linux/linux_os_api.hpp:61:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApi::sd_bus_call_method_ss(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *, char const *) const". +src/libprocess/linux/linux_os_api_impl.cpp:148:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:207:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:42:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_s(sd_bus_message *, char const **) const". +src/libprocess/linux/linux_os_api_impl.cpp:21:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:47:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:121:ERROR: New, autosar_cpp14_a18_5_1_violation: Invoking "free". +src/libprocess/linux/linux_os_api_impl.cpp:199:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_o(sd_bus_message *, char const **) const". +src/libprocess/linux/linux_os_api_impl.cpp:128:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:199:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:23:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_m7_1_2_violation: The pointer variable "sessions" points to a non-constant type but does not modify the object it points to. Consider adding const qualifier to the points-to type. +src/libprocess/linux/linux_os_api_impl.cpp:230:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_enter_container(sd_bus_message *, char, char const *) const". +src/libprocess/linux/linux_os_api_impl.cpp:183:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApiImpl::sd_bus_call_method_s(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *) const". +src/libprocess/linux/linux_os_api_impl.cpp:120:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char *". +src/libprocess/linux/service_process.cpp:53:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""Received this SdBusException message: "" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_a8_4_7_violation: Passing parameter "fun" of cheap-to-copy type "_ZZN7process14LinuxOsApiImpl6to_setB5cxx11EPPcEUlPKcE_ const &&" by reference. +src/libprocess/linux/linux_os_api_impl.hpp:59:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "_ZN7process14LinuxOsApiImpl6to_setB5cxx11EPPc(char **)". +src/libprocess/linux/linux_os_api_impl.cpp:42:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "envv" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/linux_os_api_impl.cpp:128:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "char **" in function "process::LinuxOsApiImpl::destroy_sessions(char **)". +src/libprocess/linux/linux_os_api.hpp:58:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:136:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api.hpp:65:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApi::sd_bus_message_read_s(sd_bus_message *, char const **) const". +src/libprocess/linux/linux_os_api.hpp:61:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:38:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:38:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message **" in function "process::LinuxOsApiImpl::sd_bus_call_method_ss(sd_bus *, char const *, char const *, char const *, char const *, sd_bus_error *, sd_bus_message **, char const *, char const *) const". +src/libprocess/linux/linux_os_api_impl.hpp:20:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/statistic_api_impl.cpp:140:INFO: Int, autosar_cpp14_a5_1_1_violation: Using literal ""/stat"" other than type initialization, where symbolic names shall be used instead. +src/libprocess/linux/linux_os_api_impl.cpp:153:ERROR: New, autosar_cpp14_a7_1_1_violation: The variable "session" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess/linux/linux_os_api_impl.hpp:61:ERROR: New, autosar_cpp14_a5_0_3_violation: The fourth parameter of the function "sd_uid_get_sessions" is declared with a type that has more than two levels of pointer nesting. +src/libprocess/linux/linux_os_api_impl.hpp:55:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "int32_t *" in function "process::LinuxOsApiImpl::waitpid(process::os_pid_t, int32_t *, int32_t) const". +src/libprocess/linux/linux_os_api.hpp:64:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api.hpp:61:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.hpp:61:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:62:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api.hpp:66:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApi::sd_bus_message_read_u(sd_bus_message *, process::os_pid_t *) const". +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_m7_1_2_violation: The pointer variable "sessions" points to a non-constant type but does not modify the object it points to. Consider adding const qualifier to the points-to type. +src/libprocess/linux/linux_os_api_impl.cpp:183:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.hpp:65:ERROR: New, autosar_cpp14_a8_4_7_violation: Passing parameter "fun" of cheap-to-copy type "process::LinuxOsApiImpl::destroy_sessions(char **)::[lambda(char *) (instance 1)] const &&" by reference. +src/libprocess/linux/linux_os_api.hpp:43:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/console_process.cpp:27:INFO: Int, autosar_cpp14_m19_3_1_violation: The error indicator "errno" used here. +src/libprocess/linux/linux_os_api_impl.hpp:19:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char *". +src/libprocess/linux/linux_os_api_impl.hpp:43:ERROR: New, autosar_cpp14_a8_4_8_violation: Using output parameter "sd_bus_message *" in function "process::LinuxOsApiImpl::sd_bus_message_read_u(sd_bus_message *, process::os_pid_t *) const". +src/libprocess/linux/linux_os_api_impl.cpp:131:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system + stat.idle + stat.iowait + stat.irq" may wrap. +src/libprocess/linux/linux_os_api.hpp:70:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api.hpp:43:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:131:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char *". +src/libprocess/linux/linux_os_api_impl.cpp:191:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/linux_os_api_impl.cpp:109:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:191:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.cpp:121:ERROR: New, autosar_cpp14_a20_8_5_violation: Object "display, std::remove_reference::type(&free)" is not constructed using "std::make_unique". +src/libprocess/linux/linux_os_api_impl.cpp:100:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "int" rather than a typedef that includes size and signedness information. +src/libprocess/linux/linux_os_api_impl.hpp:23:ERROR: New, autosar_cpp14_a27_0_4_violation: Using C-style string type "char const *". +src/libprocess/linux/statistic_api_impl.cpp:226:ERROR: New, autosar_cpp14_a4_7_1_violation: Unsigned integer operation "stat.user + stat.nice + stat.system" may wrap. +src/libprocess/linux/linux_os_api_impl.cpp:183:ERROR: New, autosar_cpp14_a3_9_1_violation: Using basic numerical type "char" rather than a typedef that includes size and signedness information. +src/process_ender/process_ender.cpp:45:INFO: na, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender12stop_processB5cxx11ERKSt10shared_ptrINS_7ProcessEE". +src/process_ender/process_ender.cpp:51:INFO: na, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender17terminate_processB5cxx11ERKSt10shared_ptrINS_7ProcessEE". +src/process_ender/process_ender.hpp:28:INFO: na, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender12stop_processB5cxx11ERKSt10shared_ptrINS_7ProcessEE". +src/process_ender/process_ender.hpp:34:INFO: na, autosar_cpp14_m7_3_1_violation: Global namespace contains "_ZN7process7utility5ender17terminate_processB5cxx11ERKSt10shared_ptrINS_7ProcessEE". +src/software_mc/main.cpp:21:INFO: Int, autosar_cpp14_a7_1_1_violation: The variable "argv" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/software_mc/main.cpp:21:INFO: Int, autosar_cpp14_a7_1_1_violation: The variable "argc" has a non-const type, however its value is never changed. Consider adding a const qualifier to the variable type. +src/libprocess_controller/default_controller.cpp:76:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "collection" of expensive-to-copy type "std::shared_ptr" by value. +src/process_controller_svc/process_controller_svc_main.cpp:16:ERROR: New, autosar_cpp14_m5_0_3_violation: Cvalue expression "argc" with underlying type "32-bit signed int" is implicitly converted to a different underlying type "64-bit signed long". +src/software_mc/main.cpp:37:INFO: Int, autosar_cpp14_a0_1_2_violation: The return value of function "std::copy(std::next(all_args.begin(), 1L), all_args.end(), std::ostream_iterator, std::allocator >, char, std::char_traits >(args, " "))" is not used. +src/software_mc/command_acceptance_publisher.cpp:5:INFO: Int, autosar_cpp14_a8_4_7_violation: Passing parameter "logger" of expensive-to-copy type "std::shared_ptr" by value. +src/software_mc/process_state_collector.hpp:31:INFO: na, autosar_cpp14_a12_1_5_violation: Initializing non-constant members without using delegating constructor. +src/software_mc/process_command_distributor.cpp:36:INFO: Int, autosar_cpp14_a8_4_7_violation: Passing parameter "logger" of expensive-to-copy type "std::shared_ptr" by value. +src/software_mc/command_acceptance_publisher.cpp:5:INFO: na, autosar_cpp14_a8_4_13_violation: The parameter "participant" of type "std::shared_ptr const &" is not copied in any code path. Considering passing a const lvalue reference to the underlying object instead. +src/software_mc/process_state_collector.hpp:31:INFO: na, autosar_cpp14_a8_4_7_violation: Passing parameter "on_command_state_changed" of expensive-to-copy type "std::_Bind_helper, std::allocator > const &), process::software_mc::CommandAcceptancePublisher *, std::_Placeholder<1> const &, std::_Placeholder<2> const &, std::_Placeholder<3> const &>::type" by value. +src/software_mc/command_acceptance_publisher.cpp:15:INFO: Int, autosar_cpp14_a0_1_2_violation: The return value of function "this->m_command_acceptance_states.emplace(process::software_mc::Command(process::software_mc::Command::CMD_STOP_ALL_PROCESSES), process::software_mc::CommandAcceptanceInfo(process::software_mc::CommandAcceptanceState::STATE_REFUSE, std::__cxx11::string("no data", std::allocator())))" is not used. +src/software_mc/main.cpp:35:INFO: Int, autosar_cpp14_m5_0_15_violation: Using arithmetic on pointer "argv". +src/software_mc/process_state_collector.hpp:31:INFO: Int, autosar_cpp14_a8_4_7_violation: Passing parameter "logger" of expensive-to-copy type "std::shared_ptr" by value. +src/process_controller_svc/process_controller_mon.cpp:29:INFO: na, autosar_cpp14_a8_4_8_violation: Using output parameter "std::ostream &" in function "process::controller::monitor::operator << (std::ostream &, /*class template specialization*/)". +src/process_controller_svc/process_controller_mon.cpp:9:ERROR: New, autosar_cpp14_a14_1_1_violation: class template "process::controller::monitor::Dumper" does not use static_assert declarations to ensure template arguments satisfy the required interface diff --git a/script/makedist b/script/makedist new file mode 100755 index 0000000..7efd3b9 --- /dev/null +++ b/script/makedist @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# -*- mode: sh -*- + +set -e +base=$(readlink -f $(dirname "$0")/..) +make -C "${base}" build >/dev/null +version=$(${base}/build/annotator --short-version) +release=annotator-${version} +out=${base}/dist/${release} +pkg=${out}.tar.gz +make -C "${base}" install DESTDIR=${out} >/dev/null +pushd ${base}/dist >/dev/null +tar cfz ${pkg}.tar.gz ${release} +popd >/dev/null +echo created release for version ${version}: ${pkg} diff --git a/src/Annotator.hs b/src/Annotator.hs new file mode 100644 index 0000000..1e93752 --- /dev/null +++ b/src/Annotator.hs @@ -0,0 +1,357 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE BangPatterns #-} + +module Annotator (defaultMain) where + +import System.Environment (getArgs) +import System.IO +import System.Exit +import System.Console.GetOpt +import System.Directory (doesFileExist) +import System.Posix.Files +import Control.Monad +import Control.Monad.IO.Class +import Control.Monad.Trans.Reader +import Data.Function (on) +import Data.List (delete, intercalate, foldl', nub) +import Data.Foldable (foldlM) +import Data.Char (isSpace) +import Data.Ord +import Data.Monoid +import Data.Maybe (fromMaybe) +import qualified Data.Version as Vsn +import qualified Data.List.NonEmpty as NE +import Data.List.NonEmpty (NonEmpty(..)) + +import Annotator.Rule +import Annotator.Annotation + +version :: Vsn.Version +version = Vsn.makeVersion [0,0,2,0] + +type App a = ReaderT Options IO a + +data Verbosity = Silent | Low | Chatty + deriving (Show, Enum, Eq, Ord, Bounded) + +data ShowVersion = FullVersion | ShortVersion + deriving (Show, Eq) + +increaseVerbosity :: Verbosity -> Verbosity +increaseVerbosity v + | v == maxBound = v + | otherwise = succ v + +data Options = Options + { inplace :: Bool + , verbosity :: Verbosity + , showVersion :: Maybe ShowVersion + , showHelp :: Bool + , contextLines :: Int + , onlyNewest :: Bool + , annotationFiles :: [FilePath] + } + deriving (Show, Eq) + +defaultOptions :: Options +defaultOptions = Options + { inplace = False + , verbosity = Silent + , showVersion = Nothing + , showHelp = False + , contextLines = 0 + , onlyNewest = True + , annotationFiles = [] + } + +options :: [OptDescr (Options -> Options)] +options = + [ Option ['v'] ["verbose"] + (NoArg (\opts -> opts { verbosity = increaseVerbosity (verbosity opts)})) + "be more verbose, pass multiple times to increase verbosity" + , Option ['i'] ["inplace"] + (NoArg (\opts -> opts { inplace = True})) + "replace source-file after inserting annotations" + , Option ['V'] ["version"] + (NoArg (\opts -> opts { showVersion = Just FullVersion })) + "show version" + , Option [] ["short-version"] + (NoArg (\opts -> opts { showVersion = Just ShortVersion })) + "show version" + , Option ['h'] ["help"] + (NoArg (\opts -> opts { showHelp = True })) + "show usage information" + , Option ['a'] ["all"] + (NoArg (\opts -> opts { onlyNewest = False})) + "handle all defects not just Newest" + , Option ['C'] ["context"] + (OptArg ((\f opts -> opts { contextLines = fromMaybe 0 $ readMaybe f }) . fromMaybe "0") "NUM") + "specify how much context should be shown around a violation" + , Option ['A'] ["annotations"] + (ReqArg (\f opts -> opts { annotationFiles = (nub $ annotationFiles opts ++ [f]) }) "FILE") + "load automatic annotation rules" + ] + +readMaybe :: (Read a) => String -> Maybe a +readMaybe s = case reads s of + [(n,[])] -> Just n + _ -> Nothing + +parseOptions :: [String] -> IO (Options, [String]) +parseOptions argv = + case getOpt Permute options argv of + (o, n, []) -> pure (foldl' (flip id) defaultOptions o, n) + (_, _, errs) -> ioError (userError (concat errs ++ usageInfo header options)) + where + header = "Usage: annotator [OPTIONS] files..." + +verbose :: Verbosity -> String -> App () +verbose v s = do + opts <- ask + liftIO $ when (verbosity opts >= v) $ hPutStrLn stderr s + +defaultMain :: IO () +defaultMain = do + (opts, defects) <- getArgs >>= parseOptions + let fn = case defects of + [f] -> f + _ -> "defects.err" + + case showVersion opts of + Just FullVersion -> do + putStrLn $ unlines + [ + "Annotator v" <> (Vsn.showVersion version) + , "Copyright (c) 2022 Alexander Kobjolke " + ] + exitWith ExitSuccess + Just ShortVersion -> do + putStrLn $ Vsn.showVersion version + exitWith ExitSuccess + Nothing -> pure () + + when (showHelp opts) $ do + putStrLn $ usageInfo header options + exitWith ExitSuccess + + runReaderT (genericMain fn) opts + + where + header = unlines $ + [ + "Usage: annotator [OPTIONS] files..." + , "" + , "A tool to semi-automatically add Coverity source-code annotations based on found defects." + , "" + ] + +data Age = Old | New | Newest + deriving (Show, Eq) + +data Violation = Violation { + filename :: !FilePath, + line :: !Int, + age :: !Age, + rule :: !Rule, + description :: !String + } + deriving (Show, Eq) + +split :: Int -> (a -> Bool) -> [a] -> [[a]] +split _ _ [] = [] +split n p xs + | n > 0 = case break p xs of + (match, []) -> [match] + (match, (_ : rest)) -> match : split (n-1) p rest + | otherwise = [xs] + +parseViolations :: String -> [Violation] +parseViolations = map parseViolation . lines + +removeSuffix :: String -> String -> String +removeSuffix suffix text = stripped + where + (p, s) = splitAt (length text - length suffix) text + stripped = if s == suffix then p else text + +parseViolation :: String -> Violation +parseViolation s = case split 4 (== ':') s of + (file:line:_error:rule':desc) -> violation + where + violation = Violation file (read line) a (Rule (removeSuffix "_violation" r)) (dropWhile isSpace $ concat desc) + (_:age':r:_) = split 2 (== ' ') rule' + a = case (delete ',' age') of + "Newest" -> Newest + "New" -> New + _ -> Old + _ -> error "incorrectly formatted defect line" + +genericMain :: FilePath -> App () +genericMain file = do + opts <- ask + verbose Chatty $ show opts + liftIO $ hSetBuffering stdin NoBuffering + violations' <- liftIO $ filter (isRelevant (onlyNewest opts)) . parseViolations <$> readFile file + + let mviolations = NE.nonEmpty violations' + + case mviolations of + Just violations -> do + let sortedViolations = NE.sortBy reverseOccurrences violations + groupedViolations = NE.groupBy ((==) `on` filename) sortedViolations + verbose Chatty $ "all violations: " <> show sortedViolations + forM_ groupedViolations handleViolations + + Nothing -> do + liftIO $ hPutStrLn stderr "Defects file is empty" + + where + reverseOccurrences :: Violation -> Violation -> Ordering + reverseOccurrences = comparing filename <> flip (comparing line) + + isRelevant :: Bool -> Violation -> Bool + isRelevant newestOnly v + | newestOnly = age v == Newest + | otherwise = True + +-- | handle violations within a single file +handleViolations :: NonEmpty Violation -> App () +handleViolations violations = do + opts <- ask + let fname = filename $ NE.head violations + fname' = fname <> ".fix" + header' = "Processing " <> (show $ NE.length violations) <> " violation(s) in file " <> fname + header = unlines + [ header' + , take (length header') $ repeat '=' + , "" + ] + + fileExists <- liftIO $ doesFileExist fname + + if fileExists + then do + liftIO $ hPutStrLn stderr header + contents' <- liftIO $ readFile fname + let !contents = id contents' + + newContent <- foldlM handleViolation contents violations + + liftIO $ writeFile fname' newContent + + liftIO $ when (inplace opts) $ rename fname' fname + else do + verbose Low $ "skipping non-existent file " <> fname + + +data UserChoice = Abort + | Annotate Annotation + | Skip + | Help + deriving (Show, Eq) + +-- | let the user decide what to do with a violation +getUserChoice :: Violation -> App UserChoice +getUserChoice Violation{..} = do + liftIO $ queryUser + where queryUser = do + putStr $ "> What shall we do [s/t/i/f/q/?]: " + hFlush stdout + c <- getChar + putStrLn "" + case c of + 's' -> do + pure Skip + 't' -> do + pure $ Annotate (ToDo rule) + 'i' -> do + excuse <- getExcuse + pure $ Annotate (FalsePositive rule excuse) + 'f' -> do + excuse <- getExcuse + pure $ Annotate (Intentional rule excuse) + 'q' -> pure Abort + '?' -> do + putStrLn $ unlines [ "t - add TODO marker to fix this issue" + , "s - skip this violation" + , "f - false positive" + , "i - intentional" + , "q - quit without changing the current file" + , "? - show this help" + ] + queryUser + + _ -> queryUser + + getExcuse = do + putStr $ "What's your excuse? " + hFlush stdout + mode <- hGetBuffering stdin + hSetBuffering stdin LineBuffering + excuse <- getLine + hSetBuffering stdin mode + pure excuse + +type Content = String +type NumberedLine = (Int, String) + +-- | merge lines together +-- +-- It is assumed that both lists are sorted according to their line number +-- @ +-- mergeLines [(1, "blah"), (2,"foo"), (2, "baz"), (3, "bam")] [(2,"bar")] +-- [(1,"blah"),(2,"foo"),(2,"baz"),(2,"bar"),(3,"bam")] +-- @ +mergeLines :: [NumberedLine] -> [NumberedLine] -> [NumberedLine] +mergeLines [] r = r +mergeLines l [] = l +mergeLines !lhs@(left@(nl,_):ls) !rhs@(right@(nr,_):rs) + | nl <= nr = left : mergeLines ls rhs + | nl > nr = right : mergeLines lhs rs + +-- | handle a single violation +-- +-- The function gets the current content of the file and should result in the +-- new content of the file +handleViolation :: Content -> Violation -> App Content +handleViolation content v@Violation{..} = do + verbose Low $ show v + opts <- ask + + let (before, after) = splitAt (line-1) . zip [1..] . lines $ content + context = getContext (contextLines opts) before after + !indent = takeWhile isSpace (snd . head $ after) + + -- print some context + liftIO $ forM_ context (\(n, code) -> do + let marker = '>' <$ indent + when (n == line) $ putStrLn (intercalate " " [ marker + , show age + , "violation of rule" + , show rule + , "in line" + , show line <> ":" + , description + ]) + putStrLn (code)) + + + choice <- getUserChoice v + case choice of + Abort -> liftIO $ exitSuccess + Annotate annotation -> do + let !comment = showAnnotation annotation description + !newContent = unlines . map snd $ (before ++ ((0, indent ++ comment) : after)) + pure newContent + Skip -> pure content + Help -> handleViolation content v + +-- | Get some context around some line +-- +-- the function receives the number of lines to show before and after a given line and the whole content split into lines before +getContext :: Int -> [(Int, String)] -> [(Int, String)] -> [(Int, String)] +getContext n before after = before' ++ after' + where before' = reverse . take n . reverse $ before + after' = take (n+1) after diff --git a/src/Annotator/Annotation.hs b/src/Annotator/Annotation.hs new file mode 100644 index 0000000..bc9b8a4 --- /dev/null +++ b/src/Annotator/Annotation.hs @@ -0,0 +1,14 @@ +module Annotator.Annotation (Annotation(..), showAnnotation) where + +import Annotator.Rule +import Data.Monoid + +data Annotation = Intentional !Rule !String + | FalsePositive !Rule !String + | ToDo !Rule + deriving (Show, Read, Eq) + +showAnnotation :: Annotation -> String -> String +showAnnotation (Intentional (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", "] ", reason] +showAnnotation (FalsePositive (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", " : FALSE", "] ", reason] +showAnnotation (ToDo (Rule rule)) description = "// FIXME violation " <> rule <> ": " <> description diff --git a/src/Annotator/Rule.hs b/src/Annotator/Rule.hs new file mode 100644 index 0000000..4deff92 --- /dev/null +++ b/src/Annotator/Rule.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE InstanceSigs #-} + +module Annotator.Rule where + +newtype Rule = Rule String + deriving (Eq, Read) + +instance Show Rule where + show :: Rule -> String + show (Rule r) = r