Skip to content

Commit

Permalink
Add methods to enable using formatv syntax in LLDB.
Browse files Browse the repository at this point in the history
This adds formatv-backed formatting functions in various
places in LLDB such as StreamString, logging, constructing
error messages, etc.  A couple of callsites are changed
from Printf style syntax to formatv style syntax to
illustrate its usage.  Additionally, a FileSpec formatter
is introduced so that FileSpecs can be formatted natively.

Differential Revision: https://reviews.llvm.org/D27632

llvm-svn: 289922
  • Loading branch information
Zachary Turner committed Dec 16, 2016
1 parent db4c86f commit 827d5d7
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 100 deletions.
7 changes: 7 additions & 0 deletions lldb/include/lldb/Core/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "lldb/lldb-private.h"

#include "llvm/Support/FormatVariadic.h"

namespace lldb_private {

class Log;
Expand Down Expand Up @@ -258,6 +260,11 @@ class Error {

int SetErrorStringWithVarArg(const char *format, va_list args);

template <typename... Args>
void SetErrorStringWithFormatv(const char *format, Args &&... args) {
SetErrorString(llvm::formatv(format, std::forward<Args>(args)...).str());
}

//------------------------------------------------------------------
/// Test for success condition.
///
Expand Down
44 changes: 18 additions & 26 deletions lldb/include/lldb/Core/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "lldb/Core/PluginInterface.h"
#include "lldb/lldb-private.h"

#include "llvm/Support/FormatVariadic.h"

//----------------------------------------------------------------------
// Logging Options
//----------------------------------------------------------------------
Expand All @@ -43,7 +45,7 @@
//----------------------------------------------------------------------
namespace lldb_private {

class Log {
class Log final {
public:
//------------------------------------------------------------------
// Callback definitions for abstracted plug-in log access.
Expand Down Expand Up @@ -102,42 +104,32 @@ class Log {

Log(const lldb::StreamSP &stream_sp);

virtual ~Log();
~Log();

void PutCString(const char *cstr);
void PutString(llvm::StringRef str);

virtual void PutCString(const char *cstr);
virtual void PutString(llvm::StringRef str);
template <typename... Args> void Format(const char *fmt, Args &&... args) {
PutString(llvm::formatv(fmt, std::forward<Args>(args)...).str());
}

// CLEANUP: Add llvm::raw_ostream &Stream() function.
virtual void Printf(const char *format, ...)
__attribute__((format(printf, 2, 3)));
void Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));

virtual void VAPrintf(const char *format, va_list args);
void VAPrintf(const char *format, va_list args);

virtual void LogIf(uint32_t mask, const char *fmt, ...)
void LogIf(uint32_t mask, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));

virtual void Debug(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));

virtual void DebugVerbose(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
void Debug(const char *fmt, ...) __attribute__((format(printf, 2, 3)));

virtual void Error(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));

virtual void VAError(const char *format, va_list args);

virtual void FatalError(int err, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
void Error(const char *fmt, ...) __attribute__((format(printf, 2, 3)));

virtual void Verbose(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
void VAError(const char *format, va_list args);

virtual void Warning(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
void Verbose(const char *fmt, ...) __attribute__((format(printf, 2, 3)));

virtual void WarningVerbose(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
void Warning(const char *fmt, ...) __attribute__((format(printf, 2, 3)));

Flags &GetOptions();

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Core/ModuleSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class ModuleSpec {
if (m_object_mod_time != llvm::sys::TimePoint<>()) {
if (dumped_something)
strm.PutCString(", ");
strm.Printf("object_mod_time = 0x%" PRIx64,
strm.Format("object_mod_time = {0:x+}",
uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
}
}
Expand Down
6 changes: 6 additions & 0 deletions lldb/include/lldb/Core/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "lldb/Core/Flags.h"
#include "lldb/lldb-private.h"

#include "llvm/Support/FormatVariadic.h"

namespace lldb_private {

//----------------------------------------------------------------------
Expand Down Expand Up @@ -485,6 +487,10 @@ class Stream {

size_t PrintfVarArg(const char *format, va_list args);

template <typename... Args> void Format(const char *format, Args &&... args) {
PutCString(llvm::formatv(format, std::forward<Args>(args)...).str());
}

//------------------------------------------------------------------
/// Output a quoted C string value to the stream.
///
Expand Down
28 changes: 28 additions & 0 deletions lldb/include/lldb/Host/FileSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "lldb/Host/PosixApi.h"
#include "lldb/lldb-private.h"

#include "llvm/Support/FormatVariadic.h"

namespace lldb_private {

//----------------------------------------------------------------------
Expand Down Expand Up @@ -759,4 +761,30 @@ Stream &operator<<(Stream &s, const FileSpec &f);

} // namespace lldb_private

namespace llvm {

/// Implementation of format_provider<T> for FileSpec.
///
/// The options string of a FileSpec has the grammar:
///
/// file_spec_options :: (empty) | F | D
///
/// =======================================================
/// | style | Meaning | Example |
/// -------------------------------------------------------
/// | | | Input | Output |
/// =======================================================
/// | F | Only print filename | /foo/bar | bar |
/// | D | Only print directory | /foo/bar | /foo/ |
/// | (empty) | Print file and dir | | |
/// =======================================================
///
/// Any other value is considered an invalid format string.
///
template <> struct format_provider<lldb_private::FileSpec> {
static void format(const lldb_private::FileSpec &F, llvm::raw_ostream &Stream,
StringRef Style);
};
}

#endif // liblldb_FileSpec_h_
16 changes: 16 additions & 0 deletions lldb/include/lldb/Interpreter/CommandReturnObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "lldb/lldb-private.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatVariadic.h"

#include <memory>

Expand Down Expand Up @@ -113,6 +114,21 @@ class CommandReturnObject {
void AppendErrorWithFormat(const char *format, ...)
__attribute__((format(printf, 2, 3)));

template <typename... Args>
void AppendMessageWithFormatv(const char *format, Args &&... args) {
AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str());
}

template <typename... Args>
void AppendWarningWithFormatv(const char *format, Args &&... args) {
AppendWarning(llvm::formatv(format, std::forward<Args>(args)...).str());
}

template <typename... Args>
void AppendErrorWithFormatv(const char *format, Args &&... args) {
AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
}

void SetError(const Error &error, const char *fallback_error_cstr = nullptr);

void SetError(llvm::StringRef error_cstr);
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Breakpoint/BreakpointOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ BreakpointOptions::CommandData::CreateFromStructuredData(
found_something = true;
interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
if (interp_language == eScriptLanguageUnknown) {
error.SetErrorStringWithFormat("Unknown breakpoint command language: %s.",
interpreter_str.c_str());
error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
interpreter_str);
return data_up;
}
data_up->interpreter = interp_language;
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Commands/CommandObjectApropos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) {
m_interpreter.GetDebugger().Apropos(search_word, properties);
if (num_properties) {
const bool dump_qualified_name = true;
result.AppendMessageWithFormat(
"\nThe following settings variables may relate to '%s': \n\n",
args[0].c_str());
result.AppendMessageWithFormatv(
"\nThe following settings variables may relate to '{0}': \n\n",
args[0].ref);
for (size_t i = 0; i < num_properties; ++i)
properties[i]->DumpDescription(
m_interpreter, result.GetOutputStream(), 0, dump_qualified_name);
Expand Down
53 changes: 0 additions & 53 deletions lldb/source/Core/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,6 @@ void Log::Debug(const char *format, ...) {
va_end(args);
}

//----------------------------------------------------------------------
// Print debug strings if and only if the global debug option is set to
// a non-zero value.
//----------------------------------------------------------------------
void Log::DebugVerbose(const char *format, ...) {
if (!GetOptions().AllSet(LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
return;

va_list args;
va_start(args, format);
VAPrintf(format, args);
va_end(args);
}

//----------------------------------------------------------------------
// Log only if all of the bits are set
//----------------------------------------------------------------------
Expand Down Expand Up @@ -185,24 +171,6 @@ void Log::VAError(const char *format, va_list args) {
free(arg_msg);
}

//----------------------------------------------------------------------
// Printing of errors that ARE fatal. Exit with ERR exit code
// immediately.
//----------------------------------------------------------------------
void Log::FatalError(int err, const char *format, ...) {
char *arg_msg = nullptr;
va_list args;
va_start(args, format);
::vasprintf(&arg_msg, format, args);
va_end(args);

if (arg_msg != nullptr) {
Printf("error: %s", arg_msg);
::free(arg_msg);
}
::exit(err);
}

//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
Expand All @@ -217,27 +185,6 @@ void Log::Verbose(const char *format, ...) {
va_end(args);
}

//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
//----------------------------------------------------------------------
void Log::WarningVerbose(const char *format, ...) {
if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
return;

char *arg_msg = nullptr;
va_list args;
va_start(args, format);
::vasprintf(&arg_msg, format, args);
va_end(args);

if (arg_msg == nullptr)
return;

Printf("warning: %s", arg_msg);
free(arg_msg);
}

//----------------------------------------------------------------------
// Printing of warnings that are not fatal.
//----------------------------------------------------------------------
Expand Down
51 changes: 47 additions & 4 deletions lldb/source/Host/common/FileSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,10 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve,
m_is_resolved = true;
}

Normalize(resolved, syntax);
Normalize(resolved, m_syntax);

llvm::StringRef resolve_path_ref(resolved.c_str());
size_t dir_end = ParentPathEnd(resolve_path_ref, syntax);
size_t dir_end = ParentPathEnd(resolve_path_ref, m_syntax);
if (dir_end == 0) {
m_filename.SetString(resolve_path_ref);
return;
Expand All @@ -366,11 +366,11 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve,
m_directory.SetString(resolve_path_ref.substr(0, dir_end));

size_t filename_begin = dir_end;
size_t root_dir_start = RootDirStart(resolve_path_ref, syntax);
size_t root_dir_start = RootDirStart(resolve_path_ref, m_syntax);
while (filename_begin != llvm::StringRef::npos &&
filename_begin < resolve_path_ref.size() &&
filename_begin != root_dir_start &&
IsPathSeparator(resolve_path_ref[filename_begin], syntax))
IsPathSeparator(resolve_path_ref[filename_begin], m_syntax))
++filename_begin;
m_filename.SetString((filename_begin == llvm::StringRef::npos ||
filename_begin >= resolve_path_ref.size())
Expand Down Expand Up @@ -1386,3 +1386,46 @@ bool FileSpec::IsRelative() const {
}

bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); }

void llvm::format_provider<FileSpec>::format(const FileSpec &F,
raw_ostream &Stream,
StringRef Style) {
assert(
(Style.empty() || Style.equals_lower("F") || Style.equals_lower("D")) &&
"Invalid FileSpec style!");

StringRef dir = F.GetDirectory().GetStringRef();
StringRef file = F.GetFilename().GetStringRef();

if (dir.empty() && file.empty()) {
Stream << "(empty)";
return;
}

if (Style.equals_lower("F")) {
Stream << (file.empty() ? "(empty)" : file);
return;
}

// Style is either D or empty, either way we need to print the directory.
if (!dir.empty()) {
// Directory is stored in normalized form, which might be different
// than preferred form. In order to handle this, we need to cut off
// the filename, then denormalize, then write the entire denorm'ed
// directory.
llvm::SmallString<64> denormalized_dir = dir;
Denormalize(denormalized_dir, F.GetPathSyntax());
Stream << denormalized_dir;
Stream << GetPreferredPathSeparator(F.GetPathSyntax());
}

if (Style.equals_lower("D")) {
// We only want to print the directory, so now just exit.
if (dir.empty())
Stream << "(empty)";
return;
}

if (!file.empty())
Stream << file;
}
Loading

0 comments on commit 827d5d7

Please sign in to comment.