[vte] parser: cat: Refactor and implement lint mode
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] parser: cat: Refactor and implement lint mode
- Date: Sat, 6 Oct 2018 21:09:05 +0000 (UTC)
commit db83de67084387a73031deaf984b21626879d6be
Author: Christian Persch <chpe src gnome org>
Date: Sat Oct 6 23:08:28 2018 +0200
parser: cat: Refactor and implement lint mode
Refactor the parser cat to make it easier plugging in
a linter instead of a pretty printer, and implement a basic
linter.
src/parser-cat.cc | 792 ++++++++++++++++++++++++++++++++----------------------
1 file changed, 466 insertions(+), 326 deletions(-)
---
diff --git a/src/parser-cat.cc b/src/parser-cat.cc
index 8f262a6e..f0b26c54 100644
--- a/src/parser-cat.cc
+++ b/src/parser-cat.cc
@@ -1,5 +1,4 @@
/*
- * Copyright (C) 2001,2002,2003 Red Hat, Inc.
* Copyright © 2017, 2018 Christian Persch
*
* This programme is free software; you can redistribute it and/or
@@ -29,12 +28,16 @@
#include <cstdio>
#include <cstdlib>
+#include <string>
+
#include "debug.h"
#include "parser.hh"
#include "utf8.hh"
-static char const*
-seq_to_str(unsigned int type)
+using namespace std::literals;
+
+static constexpr char const*
+seq_to_str(unsigned int type) noexcept
{
switch (type) {
case VTE_SEQ_NONE: return "NONE";
@@ -54,8 +57,8 @@ seq_to_str(unsigned int type)
}
}
-static char const*
-cmd_to_str(unsigned int command)
+static constexpr char const*
+cmd_to_str(unsigned int command) noexcept
{
switch (command) {
#define _VTE_CMD(cmd) case VTE_CMD_##cmd: return #cmd;
@@ -69,8 +72,8 @@ cmd_to_str(unsigned int command)
}
#if 0
-static char const*
-charset_alias_to_str(unsigned int cs)
+static constexepr char const*
+charset_alias_to_str(unsigned int cs) noexcept
{
switch (cs) {
#define _VTE_CHARSET_PASTE(name)
@@ -87,8 +90,8 @@ charset_alias_to_str(unsigned int cs)
}
}
-static char const*
-charset_to_str(unsigned int cs)
+static constexpr char const*
+charset_to_str(unsigned int cs) noexcept
{
auto alias = charset_alias_to_str(cs);
if (alias)
@@ -112,312 +115,501 @@ charset_to_str(unsigned int cs)
}
#endif
-#define SEQ_START "\e[7m"
-#define SEQ_END "\e[27m"
-
-#define SEQ_START_RED "\e[7;31m"
-#define SEQ_END_RED "\e[27;39m"
-
-class printer {
-public:
- printer(GString* str,
- bool plain,
- char const* intro,
- char const* outro)
- : m_str(str),
- m_plain(plain),
- m_outro(outro) {
- if (!m_plain)
- g_string_append(m_str, intro);
- }
- ~printer() {
- if (!m_plain)
- g_string_append(m_str, m_outro);
- }
+class PrettyPrinter {
private:
- GString* m_str;
+ std::string m_str;
bool m_plain;
- char const* m_outro;
-};
+ bool m_codepoints;
+
+ inline constexpr bool plain() const noexcept { return m_plain; }
+
+ class Attribute {
+ public:
+ Attribute(PrettyPrinter* printer,
+ std::string const& intro,
+ std::string const& outro) noexcept
+ : m_printer{printer}
+ , m_outro{outro} {
+ if (!m_printer->plain())
+ m_printer->m_str.append(intro);
+ }
-static void
-print_params(GString* str,
- struct vte_seq const* seq)
-{
- if (seq->n_args > 0)
- g_string_append_c(str, ' ');
-
- for (unsigned int i = 0; i < seq->n_args; i++) {
- auto arg = seq->args[i];
- if (!vte_seq_arg_default(arg))
- g_string_append_printf(str, "%d", vte_seq_arg_value(arg));
- if (i + 1 < seq->n_args)
- g_string_append_c(str, vte_seq_arg_nonfinal(arg) ? ':' : ';');
- }
-}
+ ~Attribute() noexcept
+ {
+ if (!m_printer->plain())
+ m_printer->m_str.append(m_outro);
+ }
-static void
-print_pintro(GString* str,
- unsigned int type,
- unsigned int intermediates)
-{
- if (type != VTE_SEQ_CSI &&
- type != VTE_SEQ_DCS)
- return;
+ private:
+ PrettyPrinter* m_printer;
+ std::string m_outro;
+ bool m_plain;
+ }; // class Attribute
+
+ class ReverseAttr : private Attribute {
+ public:
+ ReverseAttr(PrettyPrinter* printer)
+ : Attribute(printer, "\e[7m"s, "\e[27m"s)
+ { }
+ };
- unsigned int p = intermediates & 0x7;
- if (p == 0)
- return;
+ class RedAttr : private Attribute {
+ public:
+ RedAttr(PrettyPrinter* printer)
+ : Attribute(printer, "\e[7;31m"s, "\e[27;39m"s)
+ { }
+ };
- g_string_append_c(str, ' ');
- g_string_append_c(str, 0x40 - p);
-}
+ void
+ print_params(struct vte_seq const* seq) noexcept
+ {
+ if (seq->n_args > 0)
+ m_str.push_back(' ');
+
+ for (unsigned int i = 0; i < seq->n_args; i++) {
+ auto arg = seq->args[i];
+ if (!vte_seq_arg_default(arg))
+ print_format("%d", vte_seq_arg_value(arg));
+ if (i + 1 < seq->n_args)
+ m_str.push_back(vte_seq_arg_nonfinal(arg) ? ':' : ';');
+ }
+ }
-static void
-print_intermediates(GString* str,
- unsigned int type,
- unsigned int intermediates)
-{
- if (type == VTE_SEQ_CSI ||
- type == VTE_SEQ_DCS)
- intermediates = intermediates >> 3; /* remove pintro */
+ void
+ print_pintro(unsigned int type,
+ unsigned int intermediates) noexcept
+ {
+ if (type != VTE_SEQ_CSI &&
+ type != VTE_SEQ_DCS)
+ return;
- while (intermediates != 0) {
- unsigned int i = intermediates & 0x1f;
- char c = 0x20 + i - 1;
+ unsigned int p = intermediates & 0x7;
+ if (p == 0)
+ return;
- g_string_append_c(str, ' ');
- if (c == 0x20)
- g_string_append(str, "SP");
- else
- g_string_append_c(str, c);
+ m_str.push_back(' ');
+ m_str.push_back(char(0x40 - p));
+ }
- intermediates = intermediates >> 5;
+ void
+ print_intermediates(unsigned int type,
+ unsigned int intermediates) noexcept
+ {
+ if (type == VTE_SEQ_CSI ||
+ type == VTE_SEQ_DCS)
+ intermediates = intermediates >> 3; /* remove pintro */
+
+ while (intermediates != 0) {
+ unsigned int i = intermediates & 0x1f;
+ char c = 0x20 + i - 1;
+
+ m_str.push_back(' ');
+ if (c == 0x20)
+ m_str.append("SP"s);
+ else
+ m_str.push_back(c);
+
+ intermediates = intermediates >> 5;
+ }
}
-}
-static void
-print_string(GString* str,
- struct vte_seq const* seq)
-{
- size_t len;
- auto buf = vte_seq_string_get(&seq->arg_str, &len);
+ void
+ print_unichar(uint32_t c) noexcept
+ {
+ char buf[7];
+ auto len = g_unichar_to_utf8(c, buf);
+ m_str.append(buf, len);
+ }
- g_string_append_c(str, '\"');
- for (size_t i = 0; i < len; ++i)
- g_string_append_unichar(str, buf[i]);
- g_string_append_c(str, '\"');
-}
+ G_GNUC_PRINTF(2, 3)
+ void
+ print_format(char const* format,
+ ...)
+ {
+ char buf[256];
+ va_list args;
+ va_start(args, format);
+ auto len = g_vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ m_str.append(buf, len);
+ }
-static void
-print_seq_and_params(GString* str,
- const struct vte_seq *seq,
- bool plain)
-{
- printer p(str, plain, SEQ_START, SEQ_END);
+ void
+ print_string(struct vte_seq const* seq) noexcept
+ {
+ size_t len;
+ auto buf = vte_seq_string_get(&seq->arg_str, &len);
+ long u8len;
+ auto u8str = g_ucs4_to_utf8(buf, len, nullptr, &u8len, nullptr);
- if (seq->command != VTE_CMD_NONE) {
- g_string_append_printf(str, "{%s", cmd_to_str(seq->command));
- print_params(str, seq);
- g_string_append_c(str, '}');
- } else {
- g_string_append_printf(str, "{%s", seq_to_str(seq->type));
- print_pintro(str, seq->type, seq->intermediates);
- print_params(str, seq);
- print_intermediates(str, seq->type, seq->intermediates);
- g_string_append_printf(str, " %c}", seq->terminator);
- }
-}
+ m_str.push_back('\"');
+ m_str.append(u8str, size_t(u8len));
+ m_str.push_back('\"');
-static void
-print_seq(GString* str,
- struct vte_seq const* seq,
- bool codepoints,
- bool plain)
-{
- switch (seq->type) {
- case VTE_SEQ_NONE: {
- printer p(str, plain, SEQ_START_RED, SEQ_END_RED);
- g_string_append(str, "{NONE}");
- break;
+ g_free(u8str);
}
- case VTE_SEQ_IGNORE: {
- printer p(str, plain, SEQ_START_RED, SEQ_END_RED);
- g_string_append(str, "{IGN}");
- break;
+ void
+ print_seq_and_params(const struct vte_seq *seq) noexcept
+ {
+ ReverseAttr attr(this);
+
+ if (seq->command != VTE_CMD_NONE) {
+ m_str.push_back('{');
+ m_str.append(cmd_to_str(seq->command));
+ print_params(seq);
+ m_str.push_back('}');
+ } else {
+ m_str.push_back('{');
+ m_str.append(seq_to_str(seq->type));
+ print_pintro(seq->type, seq->intermediates);
+ print_params(seq);
+ print_intermediates(seq->type, seq->intermediates);
+ m_str.push_back(seq->terminator);
+ m_str.push_back('}');
+ }
}
- case VTE_SEQ_GRAPHIC: {
- bool printable = g_unichar_isprint(seq->terminator);
- if (codepoints || !printable) {
- if (printable) {
- char ubuf[7];
- ubuf[g_unichar_to_utf8(seq->terminator, ubuf)] = 0;
- g_string_append_printf(str, "[%04X %s]",
- seq->terminator, ubuf);
+ void
+ print_seq(struct vte_seq const* seq) noexcept
+ {
+ switch (seq->type) {
+ case VTE_SEQ_NONE: {
+ RedAttr attr(this);
+ m_str.append("{NONE}"s);
+ break;
+ }
+
+ case VTE_SEQ_IGNORE: {
+ RedAttr attr(this);
+ m_str.append("{IGNORE}"s);
+ break;
+ }
+
+ case VTE_SEQ_GRAPHIC: {
+ bool const printable = g_unichar_isprint(seq->terminator);
+ if (m_codepoints || !printable) {
+ if (printable) {
+ char ubuf[7];
+ ubuf[g_unichar_to_utf8(seq->terminator, ubuf)] = 0;
+ print_format("[%04X %s]", seq->terminator, ubuf);
+ } else {
+ print_format("[%04X]", seq->terminator);
+ }
} else {
- g_string_append_printf(str, "[%04X]",
- seq->terminator);
+ print_unichar(seq->terminator);
}
- } else {
- g_string_append_unichar(str, seq->terminator);
+ break;
}
- break;
- }
- case VTE_SEQ_CONTROL:
- case VTE_SEQ_ESCAPE: {
- printer p(str, plain, SEQ_START, SEQ_END);
- g_string_append_printf(str, "{%s}", cmd_to_str(seq->command));
- break;
- }
+ case VTE_SEQ_CONTROL:
+ case VTE_SEQ_ESCAPE: {
+ ReverseAttr attr(this);
+ print_format("{%s}", cmd_to_str(seq->command));
+ break;
+ }
- case VTE_SEQ_CSI:
- case VTE_SEQ_DCS: {
- print_seq_and_params(str, seq, plain);
- break;
- }
+ case VTE_SEQ_CSI:
+ case VTE_SEQ_DCS: {
+ print_seq_and_params(seq);
+ break;
+ }
+
+ case VTE_SEQ_OSC: {
+ ReverseAttr attr(this);
+ m_str.append("{OSC "s);
+ print_string(seq);
+ m_str.push_back('}');
+ break;
+ }
+
+ case VTE_SEQ_SCI: {
+ if (seq->terminator <= 0x20)
+ print_format("{SCI %d/%d}",
+ seq->terminator / 16,
+ seq->terminator % 16);
+ else
+ print_format("{SCI %c}", seq->terminator);
+ break;
+ }
- case VTE_SEQ_OSC: {
- printer p(str, plain, SEQ_START, SEQ_END);
- g_string_append(str, "{OSC ");
- print_string(str, seq);
- g_string_append_c(str, '}');
- break;
+ default:
+ assert(false);
+ }
}
- case VTE_SEQ_SCI: {
- if (seq->terminator <= 0x20)
- g_string_append_printf(str, "{SCI %d/%d}",
- seq->terminator / 16,
- seq->terminator % 16);
- else
- g_string_append_printf(str, "{SCI %c}", seq->terminator);
- break;
+ void
+ printout() noexcept
+ {
+ g_print("%s\n", m_str.c_str());
+ m_str.clear();
}
- default:
- assert(false);
+public:
+
+ PrettyPrinter(bool plain,
+ bool codepoints) noexcept
+ : m_plain{plain}
+ , m_codepoints{codepoints}
+ {
}
-}
-static void
-printout(GString* str)
-{
- g_print("%s\n", str->str);
- g_string_truncate(str, 0);
-}
+ ~PrettyPrinter() noexcept
+ {
+ printout();
+ }
-static gsize seq_stats[VTE_SEQ_N];
-static gsize cmd_stats[VTE_CMD_N];
-static GArray* bench_times;
+ void operator()(struct vte_seq const* seq) noexcept
+ {
+ print_seq(seq);
+ if (seq->command == VTE_CMD_LF)
+ printout();
+ }
-static void
-process_file_utf8(int fd,
- bool codepoints,
- bool plain,
- bool quiet)
-{
- struct vte_parser parser;
- vte_parser_init(&parser);
+}; // class PrettyPrinter
- gsize const buf_size = 16384;
- guchar* buf = g_new0(guchar, buf_size);
- auto outbuf = g_string_sized_new(buf_size);
+class Linter {
+private:
+ void
+ warn(char const* str) const noexcept
+ {
+ g_printerr("WARNING: %s\n", str);
+ }
- auto start_time = g_get_monotonic_time();
+ void
+ warn_deprecated(int cmd,
+ int replacement_cmd) const noexcept
+ {
+ g_printerr("WARNING: %s is deprecated; use %s instead.\n",
+ cmd_to_str(cmd),
+ cmd_to_str(replacement_cmd));
+ }
- vte::base::UTF8Decoder decoder;
+public:
+ constexpr Linter() noexcept = default;
+ ~Linter() noexcept = default;
+
+ void operator()(struct vte_seq const* seq) noexcept
+ {
+ auto const cmd = seq->command;
+ switch (cmd) {
+ case VTE_CMD_OSC:
+ if (seq->terminator == 7 /* BEL */)
+ warn("OSC terminated by BEL may be ignored; use ST (ESC \\) instead.");
+ break;
- gsize buf_start = 0;
- for (;;) {
- auto len = read(fd, buf + buf_start, buf_size - buf_start);
- if (!len)
+ case VTE_CMD_DECSLRM_OR_SCOSC:
+ case VTE_CMD_SCOSC:
+ warn_deprecated(VTE_CMD_SCOSC, VTE_CMD_DECSC);
break;
- if (len == -1) {
- if (errno == EAGAIN)
- continue;
+
+ case VTE_CMD_SCORC:
+ warn_deprecated(cmd, VTE_CMD_DECRC);
break;
}
+ }
- auto const bufend = buf + len;
-
- struct vte_seq *seq = &parser.seq;
-
- for (auto sptr = buf; sptr < bufend; ++sptr) {
- switch (decoder.decode(*sptr)) {
- case vte::base::UTF8Decoder::REJECT_REWIND:
- /* Rewind the stream.
- * Note that this will never lead to a loop, since in the
- * next round this byte *will* be consumed.
- */
- --sptr;
- [[fallthrough]];
- case vte::base::UTF8Decoder::REJECT:
- decoder.reset();
- /* Fall through to insert the U+FFFD replacement character. */
- [[fallthrough]];
- case vte::base::UTF8Decoder::ACCEPT: {
- auto ret = vte_parser_feed(&parser, decoder.codepoint());
- if (G_UNLIKELY(ret < 0)) {
- g_printerr("Parser error!\n");
- goto out;
- }
+}; // class Linter
+
+class Sink {
+public:
+ void operator()(struct vte_seq const* seq) noexcept { }
+
+}; // class Sink
+
+class Processor {
+private:
+ gsize m_seq_stats[VTE_SEQ_N];
+ gsize m_cmd_stats[VTE_CMD_N];
+ GArray* m_bench_times;
+
+ template <class Functor>
+ void
+ process_file_utf8(int fd,
+ Functor& func)
+ {
+ struct vte_parser parser;
+ vte_parser_init(&parser);
+
+ gsize const buf_size = 16384;
+ guchar* buf = g_new0(guchar, buf_size);
+
+ auto start_time = g_get_monotonic_time();
+
+ vte::base::UTF8Decoder decoder;
+
+ gsize buf_start = 0;
+ for (;;) {
+ auto len = read(fd, buf + buf_start, buf_size - buf_start);
+ if (!len)
+ break;
+ if (len == -1) {
+ if (errno == EAGAIN)
+ continue;
+ break;
+ }
+
+ auto const bufend = buf + len;
+
+ struct vte_seq *seq = &parser.seq;
+
+ for (auto sptr = buf; sptr < bufend; ++sptr) {
+ switch (decoder.decode(*sptr)) {
+ case vte::base::UTF8Decoder::REJECT_REWIND:
+ /* Rewind the stream.
+ * Note that this will never lead to a loop, since in the
+ * next round this byte *will* be consumed.
+ */
+ --sptr;
+ [[fallthrough]];
+ case vte::base::UTF8Decoder::REJECT:
+ decoder.reset();
+ /* Fall through to insert the U+FFFD replacement character. */
+ [[fallthrough]];
+ case vte::base::UTF8Decoder::ACCEPT: {
+ auto ret = vte_parser_feed(&parser, decoder.codepoint());
+ if (G_UNLIKELY(ret < 0)) {
+ g_printerr("Parser error!\n");
+ goto out;
+ }
- seq_stats[ret]++;
- if (ret != VTE_SEQ_NONE) {
- cmd_stats[seq->command]++;
- if (!quiet) {
- print_seq(outbuf, seq, codepoints, plain);
- if (seq->command == VTE_CMD_LF)
- printout(outbuf);
+ m_seq_stats[ret]++;
+ if (ret != VTE_SEQ_NONE) {
+ m_cmd_stats[seq->command]++;
+ func(seq);
}
+ break;
+ }
+
+ default:
+ break;
}
- break;
}
+ }
- default:
- break;
+ out:
+
+ int64_t time_spent = g_get_monotonic_time() - start_time;
+ g_array_append_val(m_bench_times, time_spent);
+
+ g_free(buf);
+ vte_parser_deinit(&parser);
+ }
+
+ template <class Functor>
+ bool
+ process_file(int fd,
+ int repeat,
+ Functor& func)
+ {
+ if (fd == STDIN_FILENO && repeat != 1) {
+ g_printerr("Cannot consume STDIN more than once\n");
+ return false;
+ }
+
+ for (auto i = 0; i < repeat; ++i) {
+ if (i > 0 && lseek(fd, 0, SEEK_SET) != 0) {
+ g_printerr("Failed to seek: %m\n");
+ return false;
}
+
+ process_file_utf8(fd, func);
}
+
+ return true;
}
- out:
- if (!quiet)
- printout(outbuf);
+public:
- int64_t time_spent = g_get_monotonic_time() - start_time;
- g_array_append_val(bench_times, time_spent);
+ Processor() noexcept
+ {
+ memset(&m_seq_stats, 0, sizeof(m_seq_stats));
+ memset(&m_cmd_stats, 0, sizeof(m_cmd_stats));
+ m_bench_times = g_array_new(false, true, sizeof(int64_t));
+ }
- g_string_free(outbuf, TRUE);
- g_free(buf);
- vte_parser_deinit(&parser);
-}
+ ~Processor() noexcept
+ {
+ g_array_free(m_bench_times, true);
+ }
-static bool
-process_file(int fd,
- bool codepoints,
- bool plain,
- bool quiet,
- int repeat)
-{
- if (fd == STDIN_FILENO && repeat != 1) {
- g_printerr("Cannot consume STDIN more than once\n");
- return false;
+ template <class Functor>
+ bool
+ process_files(char const* const* filenames,
+ int repeat,
+ Functor& func)
+ {
+ bool r = true;
+ if (filenames != nullptr) {
+ for (auto i = 0; filenames[i] != nullptr; i++) {
+ char const* filename = filenames[i];
+
+ int fd = -1;
+ if (g_str_equal(filename, "-")) {
+ fd = STDIN_FILENO;
+ } else {
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ g_printerr("Error opening file %s: %m\n", filename);
+ }
+ }
+ if (fd != -1) {
+ r = process_file(fd, repeat, func);
+ close(fd);
+ if (!r)
+ break;
+ }
+ }
+ } else {
+ r = process_file(STDIN_FILENO, repeat, func);
+ }
+
+ return r;
}
- for (auto i = 0; i < repeat; ++i) {
- if (i > 0 && lseek(fd, 0, SEEK_SET) != 0) {
- g_printerr("Failed to seek: %m\n");
- return false;
+ void print_statistics() const noexcept
+ {
+ for (unsigned int s = VTE_SEQ_NONE + 1; s < VTE_SEQ_N; s++) {
+ g_printerr("%\'16" G_GSIZE_FORMAT " %s\n", m_seq_stats[s], seq_to_str(s));
}
- process_file_utf8(fd, codepoints, plain, quiet);
+ g_printerr("\n");
+ for (unsigned int s = 0; s < VTE_CMD_N; s++) {
+ if (m_cmd_stats[s] > 0) {
+ g_printerr("%\'16" G_GSIZE_FORMAT " %s%s\n",
+ m_cmd_stats[s],
+ cmd_to_str(s),
+ s >= VTE_CMD_NOP_FIRST ? " [NOP]" : "");
+ }
+ }
}
- return true;
-}
+ void print_benchmark() const noexcept
+ {
+ g_array_sort(m_bench_times,
+ [](void const* p1, void const* p2) -> int {
+ int64_t const t1 = *(int64_t const*)p1;
+ int64_t const t2 = *(int64_t const*)p2;
+ return t1 == t2 ? 0 : (t1 < t2 ? -1 : 1);
+ });
+
+ int64_t total_time = 0;
+ for (unsigned int i = 0; i < m_bench_times->len; ++i)
+ total_time += g_array_index(m_bench_times, int64_t, i);
+
+ g_printerr("\nTimes: best %\'" G_GINT64_FORMAT "µs "
+ "worst %\'" G_GINT64_FORMAT "µs "
+ "average %\'" G_GINT64_FORMAT "µs\n",
+ g_array_index(m_bench_times, int64_t, 0),
+ g_array_index(m_bench_times, int64_t, m_bench_times->len - 1),
+ total_time / (int64_t)m_bench_times->len);
+ for (unsigned int i = 0; i < m_bench_times->len; ++i)
+ g_printerr(" %\'" G_GINT64_FORMAT "µs\n",
+ g_array_index(m_bench_times, int64_t, i));
+ }
+
+}; // class Processor
int
main(int argc,
@@ -425,6 +617,7 @@ main(int argc,
{
gboolean benchmark = false;
gboolean codepoints = false;
+ gboolean lint = false;
gboolean plain = false;
gboolean quiet = false;
gboolean statistics = false;
@@ -435,6 +628,8 @@ main(int argc,
"Measure time spent parsing each file", nullptr },
{ "codepoints", 'u', 0, G_OPTION_ARG_NONE, &codepoints,
"Output unicode code points by number", nullptr },
+ { "lint", 'l', 0, G_OPTION_ARG_NONE, &lint,
+ "Check input", nullptr },
{ "plain", 'p', 0, G_OPTION_ARG_NONE, &plain,
"Output plain text without attributes", nullptr },
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
@@ -465,80 +660,25 @@ main(int argc,
return EXIT_FAILURE;
}
- int exit_status = EXIT_FAILURE;
-
- memset(&seq_stats, 0, sizeof(seq_stats));
- memset(&cmd_stats, 0, sizeof(cmd_stats));
- bench_times = g_array_new(false, true, sizeof(int64_t));
-
- if (filenames != nullptr) {
- for (auto i = 0; filenames[i] != nullptr; i++) {
- char const* filename = filenames[i];
-
- int fd = -1;
- if (g_str_equal(filename, "-")) {
- fd = STDIN_FILENO;
- } else {
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- g_printerr("Error opening file %s: %m\n", filename);
- }
- }
- if (fd != -1) {
- bool r = process_file(fd, codepoints, plain, quiet, repeat);
- close(fd);
- if (!r)
- break;
- }
- }
-
- g_strfreev(filenames);
- exit_status = EXIT_SUCCESS;
+ Processor proc{};
+ if (lint) {
+ Linter linter{};
+ rv = proc.process_files(filenames, 1, linter);
+ } else if (quiet) {
+ Sink sink{};
+ rv = proc.process_files(filenames, repeat, sink);
} else {
- if (process_file(STDIN_FILENO, codepoints, plain, quiet, repeat))
- exit_status = EXIT_SUCCESS;
- }
-
- if (statistics) {
- for (unsigned int s = VTE_SEQ_NONE + 1; s < VTE_SEQ_N; s++) {
- g_printerr("%\'16" G_GSIZE_FORMAT " %s\n", seq_stats[s], seq_to_str(s));
- }
-
- g_printerr("\n");
- for (unsigned int s = 0; s < VTE_CMD_N; s++) {
- if (cmd_stats[s] > 0) {
- g_printerr("%\'16" G_GSIZE_FORMAT " %s%s\n",
- cmd_stats[s],
- cmd_to_str(s),
- s >= VTE_CMD_NOP_FIRST ? " [NOP]" : "");
- }
- }
+ PrettyPrinter pp{plain, codepoints};
+ rv = proc.process_files(filenames, repeat, pp);
}
- if (benchmark) {
- g_array_sort(bench_times,
- [](void const* p1, void const* p2) -> int {
- int64_t const t1 = *(int64_t const*)p1;
- int64_t const t2 = *(int64_t const*)p2;
- return t1 == t2 ? 0 : (t1 < t2 ? -1 : 1);
- });
-
- int64_t total_time = 0;
- for (unsigned int i = 0; i < bench_times->len; ++i)
- total_time += g_array_index(bench_times, int64_t, i);
+ if (statistics)
+ proc.print_statistics();
+ if (benchmark)
+ proc.print_benchmark();
- g_printerr("\nTimes: best %\'" G_GINT64_FORMAT "µs "
- "worst %\'" G_GINT64_FORMAT "µs "
- "average %\'" G_GINT64_FORMAT "µs\n",
- g_array_index(bench_times, int64_t, 0),
- g_array_index(bench_times, int64_t, bench_times->len - 1),
- total_time / (int64_t)bench_times->len);
- for (unsigned int i = 0; i < bench_times->len; ++i)
- g_printerr(" %\'" G_GINT64_FORMAT "µs\n",
- g_array_index(bench_times, int64_t, i));
- }
-
- g_array_free(bench_times,true);
+ if (filenames != nullptr)
+ g_strfreev(filenames);
- return exit_status;
+ return rv ? EXIT_SUCCESS : EXIT_FAILURE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]