From 8438b3317500d9fff62453e54e8643d063e02282 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 27 Apr 2018 08:34:49 +1000 Subject: [PATCH] Add a debug regex command to dump regex instructions --- src/commands.cc | 10 +++++++++- src/regex_impl.cc | 48 ++++++++++++++++++++++++--------------------- src/regex_impl.hh | 2 ++ src/string_utils.cc | 7 +++++++ src/string_utils.hh | 1 + 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index 54e1a40e..6feb1b2c 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1143,7 +1143,7 @@ const CommandDesc debug_cmd = { [](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos) -> Completions { auto c = {"info", "buffers", "options", "memory", "shared-strings", - "profile-hash-maps", "faces", "mappings"}; + "profile-hash-maps", "faces", "mappings", "regex"}; return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) }; }), [](const ParametersParser& parser, Context& context, const ShellContext&) @@ -1216,6 +1216,14 @@ const CommandDesc debug_cmd = { keymaps.get_mapping(key, m).docstring)); } } + else if (parser[0] == "regex") + { + if (parser.positional_count() != 2) + throw runtime_error("expected a regex"); + + write_to_debug_buffer(format(" * {}:\n{}", + parser[1], dump_regex(compile_regex(parser[1], RegexCompileFlags::None)))); + } else throw runtime_error(format("no such debug command: '{}'", parser[0])); } diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 0202cb85..46ccbae0 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -992,60 +992,63 @@ private: ParsedRegex& m_parsed_regex; }; -void dump_regex(const CompiledRegex& program) +String dump_regex(const CompiledRegex& program) { + String res; int count = 0; for (auto& inst : program.instructions) { - printf(" %03d ", count++); + char buf[10]; + sprintf(buf, " %03d ", count++); + res += buf; switch (inst.op) { case CompiledRegex::Literal: - printf("literal %lc\n", inst.param); + res += format("literal {}\n", inst.param); break; case CompiledRegex::Literal_IgnoreCase: - printf("literal (ignore case) %lc\n", inst.param); + res += format("literal (ignore case) {}\n", inst.param); break; case CompiledRegex::AnyChar: - printf("any char\n"); + res += "any char\n"; break; case CompiledRegex::Jump: - printf("jump %u\n", inst.param); + res += format("jump {}\n", inst.param); break; case CompiledRegex::Split_PrioritizeParent: case CompiledRegex::Split_PrioritizeChild: { - printf("split (prioritize %s) %u\n", - inst.op == CompiledRegex::Split_PrioritizeParent ? "parent" : "child", - inst.param); + res += format("split (prioritize {}) {}\n", + inst.op == CompiledRegex::Split_PrioritizeParent ? "parent" : "child", + inst.param); break; } case CompiledRegex::Save: - printf("save %d\n", inst.param); + res += format("save {}\n", inst.param); break; case CompiledRegex::Class: - printf("class %d\n", inst.param); + res += format("class {}\n", inst.param); break; case CompiledRegex::CharacterType: - printf("character type %d\n", inst.param); + res += format("character type {}\n", inst.param); break; case CompiledRegex::LineStart: - printf("line start\n"); + res += "line start\n"; break; case CompiledRegex::LineEnd: - printf("line end\n"); + res += "line end\n"; break; case CompiledRegex::WordBoundary: - printf("word boundary\n"); + res += "word boundary\n"; break; case CompiledRegex::NotWordBoundary: - printf("not word boundary\n"); + res += "not word boundary\n"; break; case CompiledRegex::SubjectBegin: - printf("subject begin\n"); + res += "subject begin\n"; break; case CompiledRegex::SubjectEnd: - printf("subject end\n"); + res += "subject end\n"; break; case CompiledRegex::LookAhead: case CompiledRegex::NegativeLookAhead: @@ -1078,16 +1081,17 @@ void dump_regex(const CompiledRegex& program) String str; for (auto it = program.lookarounds.begin() + inst.param; *it != -1; ++it) utf8::dump(std::back_inserter(str), *it); - printf("%s (%s)\n", name, str.c_str()); + res += format("{} ({})\n", name, str); break; } case CompiledRegex::FindNextStart: - printf("find next start\n"); + res += "find next start\n"; break; case CompiledRegex::Match: - printf("match\n"); + res += "match\n"; } } + return res; } CompiledRegex compile_regex(StringView re, RegexCompileFlags flags) @@ -1134,7 +1138,7 @@ struct TestVM : CompiledRegex, ThreadedRegexVM : CompiledRegex{compile_regex(re, dir == MatchDirection::Forward ? RegexCompileFlags::None : RegexCompileFlags::Backward)}, VMType{(const CompiledRegex&)*this} - { if (dump) dump_regex(*this); } + { if (dump) printf(dump_regex(*this).c_str()); } bool exec(StringView re, RegexExecFlags flags = RegexExecFlags::AnyMatch) { diff --git a/src/regex_impl.hh b/src/regex_impl.hh index 99160f96..5f522b60 100644 --- a/src/regex_impl.hh +++ b/src/regex_impl.hh @@ -112,6 +112,8 @@ struct CompiledRegex : RefCountable, UseMemoryDomain std::unique_ptr backward_start_desc; }; +String dump_regex(const CompiledRegex& program); + enum class RegexCompileFlags { None = 0, diff --git a/src/string_utils.cc b/src/string_utils.cc index 801cd5a3..a0f74dc6 100644 --- a/src/string_utils.cc +++ b/src/string_utils.cc @@ -125,6 +125,13 @@ InplaceString<15> to_string(int val) return res; } +InplaceString<15> to_string(unsigned val) +{ + InplaceString<15> res; + res.m_length = sprintf(res.m_data, "%u", val); + return res; +} + InplaceString<23> to_string(long int val) { InplaceString<23> res; diff --git a/src/string_utils.hh b/src/string_utils.hh index e8442fc2..1db9da24 100644 --- a/src/string_utils.hh +++ b/src/string_utils.hh @@ -72,6 +72,7 @@ struct Hex { size_t val; }; constexpr Hex hex(size_t val) { return {val}; } InplaceString<15> to_string(int val); +InplaceString<15> to_string(unsigned val); InplaceString<23> to_string(long int val); InplaceString<23> to_string(size_t val); InplaceString<23> to_string(long long int val);