6060#include " llvm/Support/Regex.h"
6161#include " llvm/TargetParser/Triple.h"
6262
63+ #include < cassert>
6364#include < cctype>
6465#include < cinttypes>
6566#include < cstdio>
@@ -281,31 +282,53 @@ constexpr Definition g_top_level_entries[] = {
281282constexpr Definition g_root = Entry::DefinitionWithChildren(
282283 " <root>" , EntryType::Root, g_top_level_entries);
283284
285+ FormatEntity::Entry::Entry (Type t, const char *s, const char *f)
286+ : string(s ? s : " " ), printf_format(f ? f : " " ), children_stack({{}}),
287+ type(t) {}
288+
284289FormatEntity::Entry::Entry (llvm::StringRef s)
285- : string(s.data(), s.size()), printf_format(), children(),
286- type(Type::String) {}
290+ : string(s.data(), s.size()), children_stack({{}}), type(Type::String) {}
287291
288292FormatEntity::Entry::Entry (char ch)
289- : string(1 , ch), printf_format(), children(), type(Type::String) {}
293+ : string(1 , ch), printf_format(), children_stack({{}}), type(Type::String) {
294+ }
295+
296+ std::vector<Entry> &FormatEntity::Entry::GetChildren () {
297+ assert (level < children_stack.size ());
298+ return children_stack[level];
299+ }
290300
291301void FormatEntity::Entry::AppendChar (char ch) {
292- if (children.empty () || children.back ().type != Entry::Type::String)
293- children.push_back (Entry (ch));
302+ auto &entries = GetChildren ();
303+ if (entries.empty () || entries.back ().type != Entry::Type::String)
304+ entries.push_back (Entry (ch));
294305 else
295- children .back ().string .append (1 , ch);
306+ entries .back ().string .append (1 , ch);
296307}
297308
298309void FormatEntity::Entry::AppendText (const llvm::StringRef &s) {
299- if (children.empty () || children.back ().type != Entry::Type::String)
300- children.push_back (Entry (s));
310+ auto &entries = GetChildren ();
311+ if (entries.empty () || entries.back ().type != Entry::Type::String)
312+ entries.push_back (Entry (s));
301313 else
302- children .back ().string .append (s.data (), s.size ());
314+ entries .back ().string .append (s.data (), s.size ());
303315}
304316
305317void FormatEntity::Entry::AppendText (const char *cstr) {
306318 return AppendText (llvm::StringRef (cstr));
307319}
308320
321+ void FormatEntity::Entry::AppendEntry (const Entry &&entry) {
322+ auto &entries = GetChildren ();
323+ entries.push_back (entry);
324+ }
325+
326+ void FormatEntity::Entry::StartAlternative () {
327+ assert (type == Entry::Type::Scope);
328+ children_stack.emplace_back ();
329+ level++;
330+ }
331+
309332#define ENUM_TO_CSTR (eee ) \
310333 case FormatEntity::Entry::Type::eee: \
311334 return #eee
@@ -405,8 +428,9 @@ void FormatEntity::Entry::Dump(Stream &s, int depth) const {
405428 if (deref)
406429 s.Printf (" deref = true, " );
407430 s.EOL ();
408- for (const auto &child : children) {
409- child.Dump (s, depth + 1 );
431+ for (const auto &children : children_stack) {
432+ for (const auto &child : children)
433+ child.Dump (s, depth + 1 );
410434 }
411435}
412436
@@ -1308,7 +1332,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
13081332 return true ;
13091333
13101334 case Entry::Type::Root:
1311- for (const auto &child : entry.children ) {
1335+ for (const auto &child : entry.children_stack [ 0 ] ) {
13121336 if (!Format (child, s, sc, exe_ctx, addr, valobj, function_changed,
13131337 initial_function)) {
13141338 return false ; // If any item of root fails, then the formatting fails
@@ -1322,19 +1346,26 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
13221346
13231347 case Entry::Type::Scope: {
13241348 StreamString scope_stream;
1325- bool success = false ;
1326- for (const auto &child : entry.children ) {
1327- success = Format (child, scope_stream, sc, exe_ctx, addr, valobj,
1328- function_changed, initial_function);
1329- if (!success)
1330- break ;
1349+ auto format_children = [&](const std::vector<Entry> &children) {
1350+ scope_stream.Clear ();
1351+ for (const auto &child : children) {
1352+ if (!Format (child, scope_stream, sc, exe_ctx, addr, valobj,
1353+ function_changed, initial_function))
1354+ return false ;
1355+ }
1356+ return true ;
1357+ };
1358+
1359+ for (auto &children : entry.children_stack ) {
1360+ if (format_children (children)) {
1361+ s.Write (scope_stream.GetString ().data (),
1362+ scope_stream.GetString ().size ());
1363+ return true ;
1364+ }
13311365 }
1332- // Only if all items in a scope succeed, then do we print the output into
1333- // the main stream
1334- if (success)
1335- s.Write (scope_stream.GetString ().data (), scope_stream.GetString ().size ());
1336- }
1366+
13371367 return true ; // Scopes always successfully print themselves
1368+ }
13381369
13391370 case Entry::Type::Variable:
13401371 case Entry::Type::VariableSynthetic:
@@ -2132,7 +2163,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
21322163 uint32_t depth) {
21332164 Status error;
21342165 while (!format.empty () && error.Success ()) {
2135- const size_t non_special_chars = format.find_first_of (" ${}\\ " );
2166+ const size_t non_special_chars = format.find_first_of (" ${}\\ | " );
21362167
21372168 if (non_special_chars == llvm::StringRef::npos) {
21382169 // No special characters, just string bytes so add them and we are done
@@ -2169,6 +2200,14 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
21692200 .drop_front (); // Skip the '}' as we are at the end of the scope
21702201 return error;
21712202
2203+ case ' |' :
2204+ format = format.drop_front (); // Skip the '|'
2205+ if (parent_entry.type == Entry::Type::Scope)
2206+ parent_entry.StartAlternative ();
2207+ else
2208+ parent_entry.AppendChar (' |' );
2209+ break ;
2210+
21722211 case ' \\ ' : {
21732212 format = format.drop_front (); // Skip the '\' character
21742213 if (format.empty ()) {
0 commit comments