[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/ConnectionFileDescriptorPosix.cpp Tue Sep 6 15:57:50 2016
@@ -17,16 +17,16 @@
#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/IOObject.h"
-#include "lldb/Host/SocketAddress.h"
#include "lldb/Host/Socket.h"
+#include "lldb/Host/SocketAddress.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/SelectHelper.h"
// C Includes
#include <errno.h>
#include <fcntl.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#ifndef LLDB_DISABLE_POSIX
@@ -54,526 +54,491 @@
using namespace lldb;
using namespace lldb_private;
-const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen";
-const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept";
-const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept";
-const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect";
-const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect";
-const char* ConnectionFileDescriptor::UDP_SCHEME = "udp";
-const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect";
-const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect";
-const char* ConnectionFileDescriptor::FD_SCHEME = "fd";
-const char* ConnectionFileDescriptor::FILE_SCHEME = "file";
+const char *ConnectionFileDescriptor::LISTEN_SCHEME = "listen";
+const char *ConnectionFileDescriptor::ACCEPT_SCHEME = "accept";
+const char *ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept";
+const char *ConnectionFileDescriptor::CONNECT_SCHEME = "connect";
+const char *ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect";
+const char *ConnectionFileDescriptor::UDP_SCHEME = "udp";
+const char *ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect";
+const char *ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME =
+ "unix-abstract-connect";
+const char *ConnectionFileDescriptor::FD_SCHEME = "fd";
+const char *ConnectionFileDescriptor::FILE_SCHEME = "file";
namespace {
-const char*
-GetURLAddress(const char *url, const char *scheme)
-{
- const auto prefix = std::string(scheme) + "://";
- if (strstr(url, prefix.c_str()) != url)
- return nullptr;
+const char *GetURLAddress(const char *url, const char *scheme) {
+ const auto prefix = std::string(scheme) + "://";
+ if (strstr(url, prefix.c_str()) != url)
+ return nullptr;
- return url + prefix.size();
+ return url + prefix.size();
}
-
}
ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit)
- : Connection(),
- m_pipe(),
- m_mutex(),
- m_shutting_down(false),
+ : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
m_waiting_for_accept(false),
- m_child_processes_inherit(child_processes_inherit)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast<void *>(this));
+ m_child_processes_inherit(child_processes_inherit) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
+ LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
+ static_cast<void *>(this));
}
ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd)
- : Connection(),
- m_pipe(),
- m_mutex(),
- m_shutting_down(false),
- m_waiting_for_accept(false),
- m_child_processes_inherit(false)
-{
- m_write_sp.reset(new File(fd, owns_fd));
- m_read_sp.reset(new File(fd, false));
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
- static_cast<void *>(this), fd, owns_fd);
- OpenCommandPipe();
+ : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
+ m_waiting_for_accept(false), m_child_processes_inherit(false) {
+ m_write_sp.reset(new File(fd, owns_fd));
+ m_read_sp.reset(new File(fd, false));
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
+ LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = "
+ "%i, owns_fd = %i)",
+ static_cast<void *>(this), fd, owns_fd);
+ OpenCommandPipe();
}
ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket)
- : Connection(),
- m_pipe(),
- m_mutex(),
- m_shutting_down(false),
- m_waiting_for_accept(false),
- m_child_processes_inherit(false)
-{
- InitializeSocket(socket);
-}
-
-ConnectionFileDescriptor::~ConnectionFileDescriptor()
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT));
+ : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
+ m_waiting_for_accept(false), m_child_processes_inherit(false) {
+ InitializeSocket(socket);
+}
+
+ConnectionFileDescriptor::~ConnectionFileDescriptor() {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
+ LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
+ static_cast<void *>(this));
+ Disconnect(NULL);
+ CloseCommandPipe();
+}
+
+void ConnectionFileDescriptor::OpenCommandPipe() {
+ CloseCommandPipe();
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ // Make the command file descriptor here:
+ Error result = m_pipe.CreateNew(m_child_processes_inherit);
+ if (!result.Success()) {
if (log)
- log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this));
- Disconnect(NULL);
- CloseCommandPipe();
-}
-
-void
-ConnectionFileDescriptor::OpenCommandPipe()
-{
- CloseCommandPipe();
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- // Make the command file descriptor here:
- Error result = m_pipe.CreateNew(m_child_processes_inherit);
- if (!result.Success())
- {
- if (log)
- log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this),
- result.AsCString());
- }
- else
- {
- if (log)
- log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this),
- m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor());
- }
-}
-
-void
-ConnectionFileDescriptor::CloseCommandPipe()
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast<void *>(this));
-
- m_pipe.Close();
-}
-
-bool
-ConnectionFileDescriptor::IsConnected() const
-{
- return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid());
-}
-
-ConnectionStatus
-ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not "
+ "make pipe: %s",
+ static_cast<void *>(this), result.AsCString());
+ } else {
if (log)
- log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast<void *>(this), s);
-
- OpenCommandPipe();
-
- if (s && s[0])
- {
- const char *addr = nullptr;
- if ((addr = GetURLAddress(s, LISTEN_SCHEME)))
- {
- // listen://HOST:PORT
- return SocketListenAndAccept(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, ACCEPT_SCHEME)))
- {
- // unix://SOCKNAME
- return NamedSocketAccept(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME)))
- {
- // unix://SOCKNAME
- return NamedSocketAccept(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, CONNECT_SCHEME)))
- {
- return ConnectTCP(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME)))
- {
- return ConnectTCP(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, UDP_SCHEME)))
- {
- return ConnectUDP(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME)))
- {
- // unix-connect://SOCKNAME
- return NamedSocketConnect(addr, error_ptr);
- }
- else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME)))
- {
- // unix-abstract-connect://SOCKNAME
- return UnixAbstractSocketConnect(addr, error_ptr);
- }
+ log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success "
+ "readfd=%d writefd=%d",
+ static_cast<void *>(this), m_pipe.GetReadFileDescriptor(),
+ m_pipe.GetWriteFileDescriptor());
+ }
+}
+
+void ConnectionFileDescriptor::CloseCommandPipe() {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()",
+ static_cast<void *>(this));
+
+ m_pipe.Close();
+}
+
+bool ConnectionFileDescriptor::IsConnected() const {
+ return (m_read_sp && m_read_sp->IsValid()) ||
+ (m_write_sp && m_write_sp->IsValid());
+}
+
+ConnectionStatus ConnectionFileDescriptor::Connect(const char *s,
+ Error *error_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')",
+ static_cast<void *>(this), s);
+
+ OpenCommandPipe();
+
+ if (s && s[0]) {
+ const char *addr = nullptr;
+ if ((addr = GetURLAddress(s, LISTEN_SCHEME))) {
+ // listen://HOST:PORT
+ return SocketListenAndAccept(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) {
+ // unix://SOCKNAME
+ return NamedSocketAccept(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) {
+ // unix://SOCKNAME
+ return NamedSocketAccept(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) {
+ return ConnectTCP(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) {
+ return ConnectTCP(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, UDP_SCHEME))) {
+ return ConnectUDP(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) {
+ // unix-connect://SOCKNAME
+ return NamedSocketConnect(addr, error_ptr);
+ } else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) {
+ // unix-abstract-connect://SOCKNAME
+ return UnixAbstractSocketConnect(addr, error_ptr);
+ }
#ifndef LLDB_DISABLE_POSIX
- else if ((addr = GetURLAddress(s, FD_SCHEME)))
- {
- // Just passing a native file descriptor within this current process
- // that is already opened (possibly from a service or other source).
- bool success = false;
- int fd = StringConvert::ToSInt32(addr, -1, 0, &success);
-
- if (success)
- {
- // We have what looks to be a valid file descriptor, but we
- // should make sure it is. We currently are doing this by trying to
- // get the flags from the file descriptor and making sure it
- // isn't a bad fd.
- errno = 0;
- int flags = ::fcntl(fd, F_GETFL, 0);
- if (flags == -1 || errno == EBADF)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s);
- m_read_sp.reset();
- m_write_sp.reset();
- return eConnectionStatusError;
- }
- else
- {
- // Don't take ownership of a file descriptor that gets passed
- // to us since someone else opened the file descriptor and
- // handed it to us.
- // TODO: Since are using a URL to open connection we should
- // eventually parse options using the web standard where we
- // have "fd://123?opt1=value;opt2=value" and we can have an
- // option be "owns=1" or "owns=0" or something like this to
- // allow us to specify this. For now, we assume we must
- // assume we don't own it.
-
- std::unique_ptr<TCPSocket> tcp_socket;
- tcp_socket.reset(new TCPSocket(fd, false));
- // Try and get a socket option from this file descriptor to
- // see if this is a socket and set m_is_socket accordingly.
- int resuse;
- bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse);
- if (is_socket)
- {
- m_read_sp = std::move(tcp_socket);
- m_write_sp = m_read_sp;
- }
- else
- {
- m_read_sp.reset(new File(fd, false));
- m_write_sp.reset(new File(fd, false));
- }
- m_uri.assign(addr);
- return eConnectionStatusSuccess;
- }
- }
-
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s);
- m_read_sp.reset();
- m_write_sp.reset();
- return eConnectionStatusError;
- }
- else if ((addr = GetURLAddress(s, FILE_SCHEME)))
- {
- // file:///PATH
- const char *path = addr;
- int fd = -1;
- do
- {
- fd = ::open(path, O_RDWR);
- } while (fd == -1 && errno == EINTR);
-
- if (fd == -1)
- {
- if (error_ptr)
- error_ptr->SetErrorToErrno();
- return eConnectionStatusError;
- }
-
- if (::isatty(fd))
- {
- // Set up serial terminal emulation
- struct termios options;
- ::tcgetattr(fd, &options);
-
- // Set port speed to maximum
- ::cfsetospeed(&options, B115200);
- ::cfsetispeed(&options, B115200);
-
- // Raw input, disable echo and signals
- options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
-
- // Make sure only one character is needed to return from a read
- options.c_cc[VMIN] = 1;
- options.c_cc[VTIME] = 0;
-
- ::tcsetattr(fd, TCSANOW, &options);
- }
-
- int flags = ::fcntl(fd, F_GETFL, 0);
- if (flags >= 0)
- {
- if ((flags & O_NONBLOCK) == 0)
- {
- flags |= O_NONBLOCK;
- ::fcntl(fd, F_SETFL, flags);
- }
- }
- m_read_sp.reset(new File(fd, true));
+ else if ((addr = GetURLAddress(s, FD_SCHEME))) {
+ // Just passing a native file descriptor within this current process
+ // that is already opened (possibly from a service or other source).
+ bool success = false;
+ int fd = StringConvert::ToSInt32(addr, -1, 0, &success);
+
+ if (success) {
+ // We have what looks to be a valid file descriptor, but we
+ // should make sure it is. We currently are doing this by trying to
+ // get the flags from the file descriptor and making sure it
+ // isn't a bad fd.
+ errno = 0;
+ int flags = ::fcntl(fd, F_GETFL, 0);
+ if (flags == -1 || errno == EBADF) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s);
+ m_read_sp.reset();
+ m_write_sp.reset();
+ return eConnectionStatusError;
+ } else {
+ // Don't take ownership of a file descriptor that gets passed
+ // to us since someone else opened the file descriptor and
+ // handed it to us.
+ // TODO: Since are using a URL to open connection we should
+ // eventually parse options using the web standard where we
+ // have "fd://123?opt1=value;opt2=value" and we can have an
+ // option be "owns=1" or "owns=0" or something like this to
+ // allow us to specify this. For now, we assume we must
+ // assume we don't own it.
+
+ std::unique_ptr<TCPSocket> tcp_socket;
+ tcp_socket.reset(new TCPSocket(fd, false));
+ // Try and get a socket option from this file descriptor to
+ // see if this is a socket and set m_is_socket accordingly.
+ int resuse;
+ bool is_socket =
+ !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse);
+ if (is_socket) {
+ m_read_sp = std::move(tcp_socket);
+ m_write_sp = m_read_sp;
+ } else {
+ m_read_sp.reset(new File(fd, false));
m_write_sp.reset(new File(fd, false));
- return eConnectionStatusSuccess;
- }
-#endif
+ }
+ m_uri.assign(addr);
+ return eConnectionStatusSuccess;
+ }
+ }
+
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"",
+ s);
+ m_read_sp.reset();
+ m_write_sp.reset();
+ return eConnectionStatusError;
+ } else if ((addr = GetURLAddress(s, FILE_SCHEME))) {
+ // file:///PATH
+ const char *path = addr;
+ int fd = -1;
+ do {
+ fd = ::open(path, O_RDWR);
+ } while (fd == -1 && errno == EINTR);
+
+ if (fd == -1) {
if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s);
+ error_ptr->SetErrorToErrno();
return eConnectionStatusError;
+ }
+
+ if (::isatty(fd)) {
+ // Set up serial terminal emulation
+ struct termios options;
+ ::tcgetattr(fd, &options);
+
+ // Set port speed to maximum
+ ::cfsetospeed(&options, B115200);
+ ::cfsetispeed(&options, B115200);
+
+ // Raw input, disable echo and signals
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+
+ // Make sure only one character is needed to return from a read
+ options.c_cc[VMIN] = 1;
+ options.c_cc[VTIME] = 0;
+
+ ::tcsetattr(fd, TCSANOW, &options);
+ }
+
+ int flags = ::fcntl(fd, F_GETFL, 0);
+ if (flags >= 0) {
+ if ((flags & O_NONBLOCK) == 0) {
+ flags |= O_NONBLOCK;
+ ::fcntl(fd, F_SETFL, flags);
+ }
+ }
+ m_read_sp.reset(new File(fd, true));
+ m_write_sp.reset(new File(fd, false));
+ return eConnectionStatusSuccess;
}
+#endif
if (error_ptr)
- error_ptr->SetErrorString("invalid connect arguments");
+ error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'",
+ s);
return eConnectionStatusError;
+ }
+ if (error_ptr)
+ error_ptr->SetErrorString("invalid connect arguments");
+ return eConnectionStatusError;
}
-bool
-ConnectionFileDescriptor::InterruptRead()
-{
- size_t bytes_written = 0;
- Error result = m_pipe.Write("i", 1, bytes_written);
- return result.Success();
+bool ConnectionFileDescriptor::InterruptRead() {
+ size_t bytes_written = 0;
+ Error result = m_pipe.Write("i", 1, bytes_written);
+ return result.Success();
}
-ConnectionStatus
-ConnectionFileDescriptor::Disconnect(Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void *>(this));
-
- ConnectionStatus status = eConnectionStatusSuccess;
+ConnectionStatus ConnectionFileDescriptor::Disconnect(Error *error_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::Disconnect ()",
+ static_cast<void *>(this));
- if (!IsConnected())
- {
- if (log)
- log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void *>(this));
- return eConnectionStatusSuccess;
- }
-
- if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
- static_cast<Socket &>(*m_read_sp).PreDisconnect();
+ ConnectionStatus status = eConnectionStatusSuccess;
- // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely
- // because somebody is doing a blocking read on our file descriptor. If that's the case,
- // then send the "q" char to the command file channel so the read will wake up and the connection
- // will then know to shut down.
-
- m_shutting_down = true;
-
- std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock);
- if (!locker.try_lock())
- {
- if (m_pipe.CanWrite())
- {
- size_t bytes_written = 0;
- Error result = m_pipe.Write("q", 1, bytes_written);
- if (log)
- log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, error = '%s'.",
- static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), result.AsCString());
- }
- else if (log)
- {
- log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.",
- static_cast<void *>(this));
- }
- locker.lock();
- }
-
- Error error = m_read_sp->Close();
- Error error2 = m_write_sp->Close();
- if (error.Fail() || error2.Fail())
- status = eConnectionStatusError;
- if (error_ptr)
- *error_ptr = error.Fail() ? error : error2;
-
- // Close any pipes we were using for async interrupts
- m_pipe.Close();
-
- m_uri.clear();
- m_shutting_down = false;
- return status;
-}
-
-size_t
-ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
-
- std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock);
- if (!locker.try_lock())
- {
- if (log)
- log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast<void *>(this));
- if (error_ptr)
- error_ptr->SetErrorString("failed to get the connection lock for read.");
-
- status = eConnectionStatusTimedOut;
- return 0;
- }
-
- if (m_shutting_down)
- {
- status = eConnectionStatusError;
- return 0;
- }
-
- status = BytesAvailable(timeout_usec, error_ptr);
- if (status != eConnectionStatusSuccess)
- return 0;
-
- Error error;
- size_t bytes_read = dst_len;
- error = m_read_sp->Read(dst, bytes_read);
-
- if (log)
- {
- log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s",
- static_cast<void *>(this), static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), static_cast<void *>(dst),
- static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read), error.AsCString());
- }
-
- if (bytes_read == 0)
- {
- error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers.
- status = eConnectionStatusEndOfFile;
- }
-
- if (error_ptr)
- *error_ptr = error;
-
- if (error.Fail())
- {
- uint32_t error_value = error.GetError();
- switch (error_value)
- {
- case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read.
- if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
- status = eConnectionStatusTimedOut;
- else
- status = eConnectionStatusSuccess;
- return 0;
-
- case EFAULT: // Buf points outside the allocated address space.
- case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal.
- case EINVAL: // The pointer associated with fildes was negative.
- case EIO: // An I/O error occurred while reading from the file system.
- // The process group is orphaned.
- // The file is a regular file, nbyte is greater than 0,
- // the starting position is before the end-of-file, and
- // the starting position is greater than or equal to the
- // offset maximum established for the open file
- // descriptor associated with fildes.
- case EISDIR: // An attempt is made to read a directory.
- case ENOBUFS: // An attempt to allocate a memory buffer fails.
- case ENOMEM: // Insufficient memory is available.
- status = eConnectionStatusError;
- break; // Break to close....
-
- case ENOENT: // no such file or directory
- case EBADF: // fildes is not a valid file or socket descriptor open for reading.
- case ENXIO: // An action is requested of a device that does not exist..
- // A requested action cannot be performed by the device.
- case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket.
- case ENOTCONN: // A read is attempted on an unconnected socket.
- status = eConnectionStatusLostConnection;
- break; // Break to close....
-
- case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket.
- status = eConnectionStatusTimedOut;
- return 0;
-
- default:
- if (log)
- log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast<void *>(this),
- strerror(error_value));
- status = eConnectionStatusError;
- break; // Break to close....
- }
-
- return 0;
- }
- return bytes_read;
-}
-
-size_t
-ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (!IsConnected()) {
if (log)
- log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast<void *>(this),
- static_cast<const void *>(src), static_cast<uint64_t>(src_len));
-
- if (!IsConnected())
- {
- if (error_ptr)
- error_ptr->SetErrorString("not connected");
- status = eConnectionStatusNoConnection;
- return 0;
- }
-
- Error error;
+ log->Printf(
+ "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
+ static_cast<void *>(this));
+ return eConnectionStatusSuccess;
+ }
- size_t bytes_sent = src_len;
- error = m_write_sp->Write(src, bytes_sent);
+ if (m_read_sp && m_read_sp->IsValid() &&
+ m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
+ static_cast<Socket &>(*m_read_sp).PreDisconnect();
+
+ // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite
+ // likely
+ // because somebody is doing a blocking read on our file descriptor. If
+ // that's the case,
+ // then send the "q" char to the command file channel so the read will wake up
+ // and the connection
+ // will then know to shut down.
+
+ m_shutting_down = true;
+
+ std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock);
+ if (!locker.try_lock()) {
+ if (m_pipe.CanWrite()) {
+ size_t bytes_written = 0;
+ Error result = m_pipe.Write("q", 1, bytes_written);
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get "
+ "the lock, sent 'q' to %d, error = '%s'.",
+ static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(),
+ result.AsCString());
+ } else if (log) {
+ log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the "
+ "lock, but no command pipe is available.",
+ static_cast<void *>(this));
+ }
+ locker.lock();
+ }
+
+ Error error = m_read_sp->Close();
+ Error error2 = m_write_sp->Close();
+ if (error.Fail() || error2.Fail())
+ status = eConnectionStatusError;
+ if (error_ptr)
+ *error_ptr = error.Fail() ? error : error2;
+
+ // Close any pipes we were using for async interrupts
+ m_pipe.Close();
+
+ m_uri.clear();
+ m_shutting_down = false;
+ return status;
+}
+
+size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len,
+ uint32_t timeout_usec,
+ ConnectionStatus &status,
+ Error *error_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock);
+ if (!locker.try_lock()) {
if (log)
- {
- log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)",
- static_cast<void *>(this), static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), static_cast<const void *>(src),
- static_cast<uint64_t>(src_len), static_cast<uint64_t>(bytes_sent), error.AsCString());
- }
-
- if (error_ptr)
- *error_ptr = error;
-
- if (error.Fail())
- {
- switch (error.GetError())
- {
- case EAGAIN:
- case EINTR:
- status = eConnectionStatusSuccess;
- return 0;
-
- case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket.
- case ENOTCONN: // A read is attempted on an unconnected socket.
- status = eConnectionStatusLostConnection;
- break; // Break to close....
-
- default:
- status = eConnectionStatusError;
- break; // Break to close....
- }
-
- return 0;
- }
+ log->Printf("%p ConnectionFileDescriptor::Read () failed to get the "
+ "connection lock.",
+ static_cast<void *>(this));
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to get the connection lock for read.");
+
+ status = eConnectionStatusTimedOut;
+ return 0;
+ }
+
+ if (m_shutting_down) {
+ status = eConnectionStatusError;
+ return 0;
+ }
+
+ status = BytesAvailable(timeout_usec, error_ptr);
+ if (status != eConnectionStatusSuccess)
+ return 0;
+
+ Error error;
+ size_t bytes_read = dst_len;
+ error = m_read_sp->Read(dst, bytes_read);
+
+ if (log) {
+ log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64
+ ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s",
+ static_cast<void *>(this),
+ static_cast<uint64_t>(m_read_sp->GetWaitableHandle()),
+ static_cast<void *>(dst), static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(bytes_read), error.AsCString());
+ }
+
+ if (bytes_read == 0) {
+ error.Clear(); // End-of-file. Do not automatically close; pass along for
+ // the end-of-file handlers.
+ status = eConnectionStatusEndOfFile;
+ }
+
+ if (error_ptr)
+ *error_ptr = error;
+
+ if (error.Fail()) {
+ uint32_t error_value = error.GetError();
+ switch (error_value) {
+ case EAGAIN: // The file was marked for non-blocking I/O, and no data were
+ // ready to be read.
+ if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket)
+ status = eConnectionStatusTimedOut;
+ else
+ status = eConnectionStatusSuccess;
+ return 0;
+
+ case EFAULT: // Buf points outside the allocated address space.
+ case EINTR: // A read from a slow device was interrupted before any data
+ // arrived by the delivery of a signal.
+ case EINVAL: // The pointer associated with fildes was negative.
+ case EIO: // An I/O error occurred while reading from the file system.
+ // The process group is orphaned.
+ // The file is a regular file, nbyte is greater than 0,
+ // the starting position is before the end-of-file, and
+ // the starting position is greater than or equal to the
+ // offset maximum established for the open file
+ // descriptor associated with fildes.
+ case EISDIR: // An attempt is made to read a directory.
+ case ENOBUFS: // An attempt to allocate a memory buffer fails.
+ case ENOMEM: // Insufficient memory is available.
+ status = eConnectionStatusError;
+ break; // Break to close....
+
+ case ENOENT: // no such file or directory
+ case EBADF: // fildes is not a valid file or socket descriptor open for
+ // reading.
+ case ENXIO: // An action is requested of a device that does not exist..
+ // A requested action cannot be performed by the device.
+ case ECONNRESET: // The connection is closed by the peer during a read
+ // attempt on a socket.
+ case ENOTCONN: // A read is attempted on an unconnected socket.
+ status = eConnectionStatusLostConnection;
+ break; // Break to close....
+
+ case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a
+ // socket.
+ status = eConnectionStatusTimedOut;
+ return 0;
+
+ default:
+ if (log)
+ log->Printf(
+ "%p ConnectionFileDescriptor::Read (), unexpected error: %s",
+ static_cast<void *>(this), strerror(error_value));
+ status = eConnectionStatusError;
+ break; // Break to close....
+ }
+
+ return 0;
+ }
+ return bytes_read;
+}
+
+size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len,
+ ConnectionStatus &status,
+ Error *error_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf(
+ "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")",
+ static_cast<void *>(this), static_cast<const void *>(src),
+ static_cast<uint64_t>(src_len));
+
+ if (!IsConnected()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("not connected");
+ status = eConnectionStatusNoConnection;
+ return 0;
+ }
+
+ Error error;
+
+ size_t bytes_sent = src_len;
+ error = m_write_sp->Write(src, bytes_sent);
+
+ if (log) {
+ log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64
+ ", src = %p, src_len = %" PRIu64 ") => %" PRIu64
+ " (error = %s)",
+ static_cast<void *>(this),
+ static_cast<uint64_t>(m_write_sp->GetWaitableHandle()),
+ static_cast<const void *>(src), static_cast<uint64_t>(src_len),
+ static_cast<uint64_t>(bytes_sent), error.AsCString());
+ }
+
+ if (error_ptr)
+ *error_ptr = error;
+
+ if (error.Fail()) {
+ switch (error.GetError()) {
+ case EAGAIN:
+ case EINTR:
+ status = eConnectionStatusSuccess;
+ return 0;
+
+ case ECONNRESET: // The connection is closed by the peer during a read
+ // attempt on a socket.
+ case ENOTCONN: // A read is attempted on an unconnected socket.
+ status = eConnectionStatusLostConnection;
+ break; // Break to close....
+
+ default:
+ status = eConnectionStatusError;
+ break; // Break to close....
+ }
+
+ return 0;
+ }
- status = eConnectionStatusSuccess;
- return bytes_sent;
+ status = eConnectionStatusSuccess;
+ return bytes_sent;
}
-std::string
-ConnectionFileDescriptor::GetURI()
-{
- return m_uri;
-}
+std::string ConnectionFileDescriptor::GetURI() { return m_uri; }
-// This ConnectionFileDescriptor::BytesAvailable() uses select() via SelectHelper
+// This ConnectionFileDescriptor::BytesAvailable() uses select() via
+// SelectHelper
//
// PROS:
// - select is consistent across most unix platforms
@@ -587,260 +552,247 @@ ConnectionFileDescriptor::GetURI()
// be used or a new version of ConnectionFileDescriptor::BytesAvailable()
// should be written for the system that is running into the limitations.
+ConnectionStatus ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec,
+ Error *error_ptr) {
+ // Don't need to take the mutex here separately since we are only called from
+ // Read. If we
+ // ever get used more generally we will need to lock here as well.
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf(
+ "%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)",
+ static_cast<void *>(this), timeout_usec);
+
+ // Make a copy of the file descriptors to make sure we don't
+ // have another thread change these values out from under us
+ // and cause problems in the loop below where like in FS_SET()
+ const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
+ const int pipe_fd = m_pipe.GetReadFileDescriptor();
+
+ if (handle != IOObject::kInvalidHandleValue) {
+ SelectHelper select_helper;
+ if (timeout_usec != UINT32_MAX)
+ select_helper.SetTimeout(std::chrono::microseconds(timeout_usec));
-ConnectionStatus
-ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr)
-{
- // Don't need to take the mutex here separately since we are only called from Read. If we
- // ever get used more generally we will need to lock here as well.
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec);
-
-
- // Make a copy of the file descriptors to make sure we don't
- // have another thread change these values out from under us
- // and cause problems in the loop below where like in FS_SET()
- const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle();
- const int pipe_fd = m_pipe.GetReadFileDescriptor();
-
-
- if (handle != IOObject::kInvalidHandleValue)
- {
- SelectHelper select_helper;
- if (timeout_usec != UINT32_MAX)
- select_helper.SetTimeout(std::chrono::microseconds(timeout_usec));
-
- select_helper.FDSetRead(handle);
+ select_helper.FDSetRead(handle);
#if defined(_MSC_VER)
- // select() won't accept pipes on Windows. The entire Windows codepath needs to be
- // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least
- // this will allow ::select() to not return an error.
- const bool have_pipe_fd = false;
+ // select() won't accept pipes on Windows. The entire Windows codepath
+ // needs to be
+ // converted over to using WaitForMultipleObjects and event HANDLEs, but for
+ // now at least
+ // this will allow ::select() to not return an error.
+ const bool have_pipe_fd = false;
#else
- const bool have_pipe_fd = pipe_fd >= 0;
+ const bool have_pipe_fd = pipe_fd >= 0;
#endif
- if (have_pipe_fd)
- select_helper.FDSetRead(pipe_fd);
+ if (have_pipe_fd)
+ select_helper.FDSetRead(pipe_fd);
- while (handle == m_read_sp->GetWaitableHandle())
- {
+ while (handle == m_read_sp->GetWaitableHandle()) {
- Error error = select_helper.Select();
+ Error error = select_helper.Select();
- if (error_ptr)
- *error_ptr = error;
-
- if (error.Fail())
- {
- switch (error.GetError())
- {
- case EBADF: // One of the descriptor sets specified an invalid descriptor.
- return eConnectionStatusLostConnection;
-
- case EINVAL: // The specified time limit is invalid. One of its components is negative or too large.
- default: // Other unknown error
- return eConnectionStatusError;
-
- case ETIMEDOUT:
- return eConnectionStatusTimedOut;
-
- case EAGAIN: // The kernel was (perhaps temporarily) unable to
- // allocate the requested number of file descriptors,
- // or we have non-blocking IO
- case EINTR: // A signal was delivered before the time limit
- // expired and before any of the selected events
- // occurred.
- break; // Lets keep reading to until we timeout
- }
- }
- else
- {
- if (select_helper.FDIsSetRead(handle))
- return eConnectionStatusSuccess;
-
- if (select_helper.FDIsSetRead(pipe_fd))
- {
- // There is an interrupt or exit command in the command pipe
- // Read the data from that pipe:
- char buffer[1];
-
- ssize_t bytes_read;
-
- do
- {
- bytes_read = ::read(pipe_fd, buffer, sizeof(buffer));
- } while (bytes_read < 0 && errno == EINTR);
-
- switch (buffer[0])
- {
- case 'q':
- if (log)
- log->Printf("%p ConnectionFileDescriptor::BytesAvailable() "
- "got data: %c from the command channel.",
- static_cast<void *>(this), buffer[0]);
- return eConnectionStatusEndOfFile;
- case 'i':
- // Interrupt the current read
- return eConnectionStatusInterrupted;
- }
- }
- }
- }
- }
+ if (error_ptr)
+ *error_ptr = error;
- if (error_ptr)
- error_ptr->SetErrorString("not connected");
- return eConnectionStatusLostConnection;
+ if (error.Fail()) {
+ switch (error.GetError()) {
+ case EBADF: // One of the descriptor sets specified an invalid
+ // descriptor.
+ return eConnectionStatusLostConnection;
+
+ case EINVAL: // The specified time limit is invalid. One of its
+ // components is negative or too large.
+ default: // Other unknown error
+ return eConnectionStatusError;
+
+ case ETIMEDOUT:
+ return eConnectionStatusTimedOut;
+
+ case EAGAIN: // The kernel was (perhaps temporarily) unable to
+ // allocate the requested number of file descriptors,
+ // or we have non-blocking IO
+ case EINTR: // A signal was delivered before the time limit
+ // expired and before any of the selected events
+ // occurred.
+ break; // Lets keep reading to until we timeout
+ }
+ } else {
+ if (select_helper.FDIsSetRead(handle))
+ return eConnectionStatusSuccess;
+
+ if (select_helper.FDIsSetRead(pipe_fd)) {
+ // There is an interrupt or exit command in the command pipe
+ // Read the data from that pipe:
+ char buffer[1];
+
+ ssize_t bytes_read;
+
+ do {
+ bytes_read = ::read(pipe_fd, buffer, sizeof(buffer));
+ } while (bytes_read < 0 && errno == EINTR);
+
+ switch (buffer[0]) {
+ case 'q':
+ if (log)
+ log->Printf("%p ConnectionFileDescriptor::BytesAvailable() "
+ "got data: %c from the command channel.",
+ static_cast<void *>(this), buffer[0]);
+ return eConnectionStatusEndOfFile;
+ case 'i':
+ // Interrupt the current read
+ return eConnectionStatusInterrupted;
+ }
+ }
+ }
+ }
+ }
+
+ if (error_ptr)
+ error_ptr->SetErrorString("not connected");
+ return eConnectionStatusLostConnection;
}
ConnectionStatus
-ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr)
-{
- Socket *socket = nullptr;
- Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket);
- if (error_ptr)
- *error_ptr = error;
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- m_uri.assign(socket_name);
- return eConnectionStatusSuccess;
+ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name,
+ Error *error_ptr) {
+ Socket *socket = nullptr;
+ Error error =
+ Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ if (error.Fail()) {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(socket_name);
+ return eConnectionStatusSuccess;
}
ConnectionStatus
-ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr)
-{
- Socket *socket = nullptr;
- Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket);
- if (error_ptr)
- *error_ptr = error;
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- m_uri.assign(socket_name);
- return eConnectionStatusSuccess;
+ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name,
+ Error *error_ptr) {
+ Socket *socket = nullptr;
+ Error error =
+ Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ if (error.Fail()) {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(socket_name);
+ return eConnectionStatusSuccess;
}
lldb::ConnectionStatus
-ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr)
-{
- Socket *socket = nullptr;
- Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket);
- if (error_ptr)
- *error_ptr = error;
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- m_uri.assign(socket_name);
- return eConnectionStatusSuccess;
+ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name,
+ Error *error_ptr) {
+ Socket *socket = nullptr;
+ Error error = Socket::UnixAbstractConnect(socket_name,
+ m_child_processes_inherit, socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ if (error.Fail()) {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(socket_name);
+ return eConnectionStatusSuccess;
}
ConnectionStatus
-ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr)
-{
- m_port_predicate.SetValue(0, eBroadcastNever);
-
- Socket *socket = nullptr;
- m_waiting_for_accept = true;
- Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate);
- if (error_ptr)
- *error_ptr = error;
- if (error.Fail())
- return eConnectionStatusError;
+ConnectionFileDescriptor::SocketListenAndAccept(const char *s,
+ Error *error_ptr) {
+ m_port_predicate.SetValue(0, eBroadcastNever);
+
+ Socket *socket = nullptr;
+ m_waiting_for_accept = true;
+ Error error = Socket::TcpListen(s, m_child_processes_inherit, socket,
+ &m_port_predicate);
+ if (error_ptr)
+ *error_ptr = error;
+ if (error.Fail())
+ return eConnectionStatusError;
- std::unique_ptr<Socket> listening_socket_up;
+ std::unique_ptr<Socket> listening_socket_up;
- listening_socket_up.reset(socket);
- socket = nullptr;
- error = listening_socket_up->Accept(s, m_child_processes_inherit, socket);
- listening_socket_up.reset();
- if (error_ptr)
- *error_ptr = error;
- if (error.Fail())
- return eConnectionStatusError;
+ listening_socket_up.reset(socket);
+ socket = nullptr;
+ error = listening_socket_up->Accept(s, m_child_processes_inherit, socket);
+ listening_socket_up.reset();
+ if (error_ptr)
+ *error_ptr = error;
+ if (error.Fail())
+ return eConnectionStatusError;
- InitializeSocket(socket);
- return eConnectionStatusSuccess;
+ InitializeSocket(socket);
+ return eConnectionStatusSuccess;
}
-ConnectionStatus
-ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr)
-{
- Socket *socket = nullptr;
- Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket);
- if (error_ptr)
- *error_ptr = error;
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- m_uri.assign(s);
- return eConnectionStatusSuccess;
+ConnectionStatus ConnectionFileDescriptor::ConnectTCP(const char *s,
+ Error *error_ptr) {
+ Socket *socket = nullptr;
+ Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ if (error.Fail()) {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(s);
+ return eConnectionStatusSuccess;
+}
+
+ConnectionStatus ConnectionFileDescriptor::ConnectUDP(const char *s,
+ Error *error_ptr) {
+ Socket *send_socket = nullptr;
+ Socket *recv_socket = nullptr;
+ Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket,
+ recv_socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(send_socket);
+ m_read_sp.reset(recv_socket);
+ if (error.Fail()) {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(s);
+ return eConnectionStatusSuccess;
}
-ConnectionStatus
-ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr)
-{
- Socket *send_socket = nullptr;
- Socket *recv_socket = nullptr;
- Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket);
- if (error_ptr)
- *error_ptr = error;
- m_write_sp.reset(send_socket);
- m_read_sp.reset(recv_socket);
- if (error.Fail())
- {
- return eConnectionStatusError;
- }
- m_uri.assign(s);
- return eConnectionStatusSuccess;
+uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) {
+ uint16_t bound_port = 0;
+ if (timeout_sec == UINT32_MAX)
+ m_port_predicate.WaitForValueNotEqualTo(0, bound_port);
+ else
+ m_port_predicate.WaitForValueNotEqualTo(0, bound_port,
+ std::chrono::seconds(timeout_sec));
+ return bound_port;
}
-uint16_t
-ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec)
-{
- uint16_t bound_port = 0;
- if (timeout_sec == UINT32_MAX)
- m_port_predicate.WaitForValueNotEqualTo(0, bound_port);
- else
- m_port_predicate.WaitForValueNotEqualTo(0, bound_port, std::chrono::seconds(timeout_sec));
- return bound_port;
-}
-
-bool
-ConnectionFileDescriptor::GetChildProcessesInherit() const
-{
- return m_child_processes_inherit;
-}
-
-void
-ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit)
-{
- m_child_processes_inherit = child_processes_inherit;
-}
-
-void
-ConnectionFileDescriptor::InitializeSocket(Socket* socket)
-{
- assert(socket->GetSocketProtocol() == Socket::ProtocolTcp);
- TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
-
- m_write_sp.reset(socket);
- m_read_sp = m_write_sp;
- StreamString strm;
- strm.Printf("connect://%s:%u",tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber());
- m_uri.swap(strm.GetString());
+bool ConnectionFileDescriptor::GetChildProcessesInherit() const {
+ return m_child_processes_inherit;
+}
+
+void ConnectionFileDescriptor::SetChildProcessesInherit(
+ bool child_processes_inherit) {
+ m_child_processes_inherit = child_processes_inherit;
+}
+
+void ConnectionFileDescriptor::InitializeSocket(Socket *socket) {
+ assert(socket->GetSocketProtocol() == Socket::ProtocolTcp);
+ TCPSocket *tcp_socket = static_cast<TCPSocket *>(socket);
+
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ StreamString strm;
+ strm.Printf("connect://%s:%u", tcp_socket->GetRemoteIPAddress().c_str(),
+ tcp_socket->GetRemotePortNumber());
+ m_uri.swap(strm.GetString());
}
Modified: lldb/trunk/source/Host/posix/DomainSocket.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/DomainSocket.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/DomainSocket.cpp (original)
+++ lldb/trunk/source/Host/posix/DomainSocket.cpp Tue Sep 6 15:57:50 2016
@@ -21,113 +21,100 @@ using namespace lldb_private;
#ifdef __ANDROID__
// Android does not have SUN_LEN
#ifndef SUN_LEN
-#define SUN_LEN(ptr) (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))
+#define SUN_LEN(ptr) \
+ (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path))
#endif
#endif // #ifdef __ANDROID__
namespace {
const int kDomain = AF_UNIX;
-const int kType = SOCK_STREAM;
+const int kType = SOCK_STREAM;
-bool SetSockAddr(llvm::StringRef name,
- const size_t name_offset,
- sockaddr_un* saddr_un,
- socklen_t& saddr_un_len)
-{
- if (name.size() + name_offset > sizeof(saddr_un->sun_path))
- return false;
-
- memset(saddr_un, 0, sizeof(*saddr_un));
- saddr_un->sun_family = kDomain;
-
- memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
-
- // For domain sockets we can use SUN_LEN in order to calculate size of
- // sockaddr_un, but for abstract sockets we have to calculate size manually
- // because of leading null symbol.
- if (name_offset == 0)
- saddr_un_len = SUN_LEN(saddr_un);
- else
- saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
+bool SetSockAddr(llvm::StringRef name, const size_t name_offset,
+ sockaddr_un *saddr_un, socklen_t &saddr_un_len) {
+ if (name.size() + name_offset > sizeof(saddr_un->sun_path))
+ return false;
+
+ memset(saddr_un, 0, sizeof(*saddr_un));
+ saddr_un->sun_family = kDomain;
+
+ memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
+
+ // For domain sockets we can use SUN_LEN in order to calculate size of
+ // sockaddr_un, but for abstract sockets we have to calculate size manually
+ // because of leading null symbol.
+ if (name_offset == 0)
+ saddr_un_len = SUN_LEN(saddr_un);
+ else
+ saddr_un_len =
+ offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un->sun_len = saddr_un_len;
+ saddr_un->sun_len = saddr_un_len;
#endif
- return true;
+ return true;
}
-
}
DomainSocket::DomainSocket(NativeSocket socket)
- : Socket(socket, ProtocolUnixDomain, true)
-{
-}
+ : Socket(socket, ProtocolUnixDomain, true) {}
DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
- : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
-{
-}
-
-DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error)
- : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true)
-{
-}
+ : DomainSocket(
+ CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {}
-Error
-DomainSocket::Connect(llvm::StringRef name)
-{
- sockaddr_un saddr_un;
- socklen_t saddr_un_len;
- if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
- return Error("Failed to set socket address");
-
- Error error;
- if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
- SetLastError (error);
+DomainSocket::DomainSocket(SocketProtocol protocol,
+ bool child_processes_inherit, Error &error)
+ : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error),
+ protocol, true) {}
+
+Error DomainSocket::Connect(llvm::StringRef name) {
+ sockaddr_un saddr_un;
+ socklen_t saddr_un_len;
+ if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+ return Error("Failed to set socket address");
+
+ Error error;
+ if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) <
+ 0)
+ SetLastError(error);
- return error;
+ return error;
}
-Error
-DomainSocket::Listen(llvm::StringRef name, int backlog)
-{
- sockaddr_un saddr_un;
- socklen_t saddr_un_len;
- if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
- return Error("Failed to set socket address");
+Error DomainSocket::Listen(llvm::StringRef name, int backlog) {
+ sockaddr_un saddr_un;
+ socklen_t saddr_un_len;
+ if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+ return Error("Failed to set socket address");
- DeleteSocketFile(name);
+ DeleteSocketFile(name);
- Error error;
- if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0)
- if (::listen(GetNativeSocket(), backlog) == 0)
- return error;
+ Error error;
+ if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==
+ 0)
+ if (::listen(GetNativeSocket(), backlog) == 0)
+ return error;
- SetLastError(error);
- return error;
+ SetLastError(error);
+ return error;
}
-Error
-DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
-{
- Error error;
- auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error);
- if (error.Success())
- socket = new DomainSocket(conn_fd);
+Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
+ Socket *&socket) {
+ Error error;
+ auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,
+ child_processes_inherit, error);
+ if (error.Success())
+ socket = new DomainSocket(conn_fd);
- return error;
+ return error;
}
-size_t
-DomainSocket::GetNameOffset() const
-{
- return 0;
-}
+size_t DomainSocket::GetNameOffset() const { return 0; }
-void
-DomainSocket::DeleteSocketFile(llvm::StringRef name)
-{
- FileSystem::Unlink(FileSpec{name, true});
+void DomainSocket::DeleteSocketFile(llvm::StringRef name) {
+ FileSystem::Unlink(FileSpec{name, true});
}
Modified: lldb/trunk/source/Host/posix/FileSystem.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/FileSystem.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/FileSystem.cpp (original)
+++ lldb/trunk/source/Host/posix/FileSystem.cpp Tue Sep 6 15:57:50 2016
@@ -16,9 +16,9 @@
#include <sys/stat.h>
#include <sys/types.h>
#ifdef __linux__
-#include <sys/statfs.h>
-#include <sys/mount.h>
#include <linux/magic.h>
+#include <sys/mount.h>
+#include <sys/statfs.h>
#endif
#if defined(__NetBSD__)
#include <sys/statvfs.h>
@@ -32,282 +32,231 @@
using namespace lldb;
using namespace lldb_private;
-const char *
-FileSystem::DEV_NULL = "/dev/null";
+const char *FileSystem::DEV_NULL = "/dev/null";
-FileSpec::PathSyntax
-FileSystem::GetNativePathSyntax()
-{
- return FileSpec::ePathSyntaxPosix;
-}
-
-Error
-FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions)
-{
- if (file_spec)
- {
- Error error;
- if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
- {
- error.SetErrorToErrno();
- errno = 0;
- switch (error.GetError())
- {
- case ENOENT:
- {
- // Parent directory doesn't exist, so lets make it if we can
- // Make the parent directory and try again
- FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false};
- error = MakeDirectory(parent_file_spec, file_permissions);
- if (error.Fail())
- return error;
- // Try and make the directory again now that the parent directory was made successfully
- if (::mkdir(file_spec.GetCString(), file_permissions) == -1)
- {
- error.SetErrorToErrno();
- }
- return error;
- }
- break;
- case EEXIST:
- {
- if (file_spec.IsDirectory())
- return Error(); // It is a directory and it already exists
- }
- break;
- }
- }
- return error;
- }
- return Error("empty path");
+FileSpec::PathSyntax FileSystem::GetNativePathSyntax() {
+ return FileSpec::ePathSyntaxPosix;
}
-Error
-FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
-{
- Error error;
- if (file_spec)
- {
- if (recurse)
- {
- // Save all sub directories in a list so we don't recursively call this function
- // and possibly run out of file descriptors if the directory is too deep.
- std::vector<FileSpec> sub_directories;
-
- FileSpec::ForEachItemInDirectory (file_spec.GetCString(), [&error, &sub_directories](FileSpec::FileType file_type, const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult {
- if (file_type == FileSpec::eFileTypeDirectory)
- {
- // Save all directorires and process them after iterating through this directory
- sub_directories.push_back(spec);
- }
- else
- {
- // Update sub_spec to point to the current file and delete it
- error = FileSystem::Unlink(spec);
- }
- // If anything went wrong, stop iterating, else process the next file
- if (error.Fail())
- return FileSpec::eEnumerateDirectoryResultQuit;
- else
- return FileSpec::eEnumerateDirectoryResultNext;
- });
-
- if (error.Success())
- {
- // Now delete all sub directories with separate calls that aren't
- // recursively calling into this function _while_ this function is
- // iterating through the current directory.
- for (const auto &sub_directory : sub_directories)
- {
- error = DeleteDirectory(sub_directory, recurse);
- if (error.Fail())
- break;
- }
- }
+Error FileSystem::MakeDirectory(const FileSpec &file_spec,
+ uint32_t file_permissions) {
+ if (file_spec) {
+ Error error;
+ if (::mkdir(file_spec.GetCString(), file_permissions) == -1) {
+ error.SetErrorToErrno();
+ errno = 0;
+ switch (error.GetError()) {
+ case ENOENT: {
+ // Parent directory doesn't exist, so lets make it if we can
+ // Make the parent directory and try again
+ FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false};
+ error = MakeDirectory(parent_file_spec, file_permissions);
+ if (error.Fail())
+ return error;
+ // Try and make the directory again now that the parent directory was
+ // made successfully
+ if (::mkdir(file_spec.GetCString(), file_permissions) == -1) {
+ error.SetErrorToErrno();
}
-
- if (error.Success())
- {
- if (::rmdir(file_spec.GetCString()) != 0)
- error.SetErrorToErrno();
+ return error;
+ } break;
+ case EEXIST: {
+ if (file_spec.IsDirectory())
+ return Error(); // It is a directory and it already exists
+ } break;
+ }
+ }
+ return error;
+ }
+ return Error("empty path");
+}
+
+Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) {
+ Error error;
+ if (file_spec) {
+ if (recurse) {
+ // Save all sub directories in a list so we don't recursively call this
+ // function
+ // and possibly run out of file descriptors if the directory is too deep.
+ std::vector<FileSpec> sub_directories;
+
+ FileSpec::ForEachItemInDirectory(
+ file_spec.GetCString(),
+ [&error, &sub_directories](
+ FileSpec::FileType file_type,
+ const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult {
+ if (file_type == FileSpec::eFileTypeDirectory) {
+ // Save all directorires and process them after iterating through
+ // this directory
+ sub_directories.push_back(spec);
+ } else {
+ // Update sub_spec to point to the current file and delete it
+ error = FileSystem::Unlink(spec);
+ }
+ // If anything went wrong, stop iterating, else process the next
+ // file
+ if (error.Fail())
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ else
+ return FileSpec::eEnumerateDirectoryResultNext;
+ });
+
+ if (error.Success()) {
+ // Now delete all sub directories with separate calls that aren't
+ // recursively calling into this function _while_ this function is
+ // iterating through the current directory.
+ for (const auto &sub_directory : sub_directories) {
+ error = DeleteDirectory(sub_directory, recurse);
+ if (error.Fail())
+ break;
}
+ }
}
- else
- {
- error.SetErrorString("empty path");
- }
- return error;
-}
-Error
-FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
-{
- Error error;
- struct stat file_stats;
- if (::stat(file_spec.GetCString(), &file_stats) == 0)
- {
- // The bits in "st_mode" currently match the definitions
- // for the file mode bits in unix.
- file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- }
- else
- {
+ if (error.Success()) {
+ if (::rmdir(file_spec.GetCString()) != 0)
error.SetErrorToErrno();
}
- return error;
+ } else {
+ error.SetErrorString("empty path");
+ }
+ return error;
}
-Error
-FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
-{
- Error error;
- if (::chmod(file_spec.GetCString(), file_permissions) != 0)
- error.SetErrorToErrno();
- return error;
+Error FileSystem::GetFilePermissions(const FileSpec &file_spec,
+ uint32_t &file_permissions) {
+ Error error;
+ struct stat file_stats;
+ if (::stat(file_spec.GetCString(), &file_stats) == 0) {
+ // The bits in "st_mode" currently match the definitions
+ // for the file mode bits in unix.
+ file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ } else {
+ error.SetErrorToErrno();
+ }
+ return error;
}
-lldb::user_id_t
-FileSystem::GetFileSize(const FileSpec &file_spec)
-{
- return file_spec.GetByteSize();
+Error FileSystem::SetFilePermissions(const FileSpec &file_spec,
+ uint32_t file_permissions) {
+ Error error;
+ if (::chmod(file_spec.GetCString(), file_permissions) != 0)
+ error.SetErrorToErrno();
+ return error;
}
-bool
-FileSystem::GetFileExists(const FileSpec &file_spec)
-{
- return file_spec.Exists();
+lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) {
+ return file_spec.GetByteSize();
}
-Error
-FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
-{
- Error error;
- if (::link(dst.GetCString(), src.GetCString()) == -1)
- error.SetErrorToErrno();
- return error;
+bool FileSystem::GetFileExists(const FileSpec &file_spec) {
+ return file_spec.Exists();
}
-int
-FileSystem::GetHardlinkCount(const FileSpec &file_spec)
-{
- struct stat file_stat;
- if (::stat(file_spec.GetCString(), &file_stat) == 0)
- return file_stat.st_nlink;
-
- return -1;
+Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) {
+ Error error;
+ if (::link(dst.GetCString(), src.GetCString()) == -1)
+ error.SetErrorToErrno();
+ return error;
}
-Error
-FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
-{
- Error error;
- if (::symlink(dst.GetCString(), src.GetCString()) == -1)
- error.SetErrorToErrno();
- return error;
+int FileSystem::GetHardlinkCount(const FileSpec &file_spec) {
+ struct stat file_stat;
+ if (::stat(file_spec.GetCString(), &file_stat) == 0)
+ return file_stat.st_nlink;
+
+ return -1;
}
-Error
-FileSystem::Unlink(const FileSpec &file_spec)
-{
- Error error;
- if (::unlink(file_spec.GetCString()) == -1)
- error.SetErrorToErrno();
- return error;
+Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {
+ Error error;
+ if (::symlink(dst.GetCString(), src.GetCString()) == -1)
+ error.SetErrorToErrno();
+ return error;
}
-Error
-FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
-{
- Error error;
- char buf[PATH_MAX];
- ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1);
- if (count < 0)
- error.SetErrorToErrno();
- else
- {
- buf[count] = '\0'; // Success
- dst.SetFile(buf, false);
- }
- return error;
+Error FileSystem::Unlink(const FileSpec &file_spec) {
+ Error error;
+ if (::unlink(file_spec.GetCString()) == -1)
+ error.SetErrorToErrno();
+ return error;
}
-Error
-FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
-{
- char resolved_path[PATH_MAX];
- if (!src.GetPath (resolved_path, sizeof (resolved_path)))
- {
- return Error("Couldn't get the canonical path for %s", src.GetCString());
- }
-
- char real_path[PATH_MAX + 1];
- if (realpath(resolved_path, real_path) == nullptr)
- {
- Error err;
- err.SetErrorToErrno();
- return err;
- }
-
- dst = FileSpec(real_path, false);
-
- return Error();
+Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
+ Error error;
+ char buf[PATH_MAX];
+ ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1);
+ if (count < 0)
+ error.SetErrorToErrno();
+ else {
+ buf[count] = '\0'; // Success
+ dst.SetFile(buf, false);
+ }
+ return error;
+}
+
+Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {
+ char resolved_path[PATH_MAX];
+ if (!src.GetPath(resolved_path, sizeof(resolved_path))) {
+ return Error("Couldn't get the canonical path for %s", src.GetCString());
+ }
+
+ char real_path[PATH_MAX + 1];
+ if (realpath(resolved_path, real_path) == nullptr) {
+ Error err;
+ err.SetErrorToErrno();
+ return err;
+ }
+
+ dst = FileSpec(real_path, false);
+
+ return Error();
}
#if defined(__NetBSD__)
-static bool IsLocal(const struct statvfs& info)
-{
- return (info.f_flag & MNT_LOCAL) != 0;
+static bool IsLocal(const struct statvfs &info) {
+ return (info.f_flag & MNT_LOCAL) != 0;
}
#else
-static bool IsLocal(const struct statfs& info)
-{
+static bool IsLocal(const struct statfs &info) {
#ifdef __linux__
- #define CIFS_MAGIC_NUMBER 0xFF534D42
- switch ((uint32_t)info.f_type)
- {
- case NFS_SUPER_MAGIC:
- case SMB_SUPER_MAGIC:
- case CIFS_MAGIC_NUMBER:
- return false;
- default:
- return true;
- }
+#define CIFS_MAGIC_NUMBER 0xFF534D42
+ switch ((uint32_t)info.f_type) {
+ case NFS_SUPER_MAGIC:
+ case SMB_SUPER_MAGIC:
+ case CIFS_MAGIC_NUMBER:
+ return false;
+ default:
+ return true;
+ }
#else
- return (info.f_flags & MNT_LOCAL) != 0;
+ return (info.f_flags & MNT_LOCAL) != 0;
#endif
}
#endif
#if defined(__NetBSD__)
-bool
-FileSystem::IsLocal(const FileSpec &spec)
-{
- struct statvfs statfs_info;
- std::string path (spec.GetPath());
- if (statvfs(path.c_str(), &statfs_info) == 0)
- return ::IsLocal(statfs_info);
- return false;
+bool FileSystem::IsLocal(const FileSpec &spec) {
+ struct statvfs statfs_info;
+ std::string path(spec.GetPath());
+ if (statvfs(path.c_str(), &statfs_info) == 0)
+ return ::IsLocal(statfs_info);
+ return false;
}
#else
-bool
-FileSystem::IsLocal(const FileSpec &spec)
-{
- struct statfs statfs_info;
- std::string path (spec.GetPath());
- if (statfs(path.c_str(), &statfs_info) == 0)
- return ::IsLocal(statfs_info);
- return false;
+bool FileSystem::IsLocal(const FileSpec &spec) {
+ struct statfs statfs_info;
+ std::string path(spec.GetPath());
+ if (statfs(path.c_str(), &statfs_info) == 0)
+ return ::IsLocal(statfs_info);
+ return false;
}
#endif
-FILE *
-FileSystem::Fopen(const char *path, const char *mode)
-{
- return ::fopen(path, mode);
+FILE *FileSystem::Fopen(const char *path, const char *mode) {
+ return ::fopen(path, mode);
}
-int
-FileSystem::Stat(const char *path, struct stat *stats)
-{
- return ::stat(path, stats);
+int FileSystem::Stat(const char *path, struct stat *stats) {
+ return ::stat(path, stats);
}
Modified: lldb/trunk/source/Host/posix/HostInfoPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/HostInfoPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/HostInfoPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/HostInfoPosix.cpp Tue Sep 6 15:57:50 2016
@@ -28,27 +28,20 @@
using namespace lldb_private;
-size_t
-HostInfoPosix::GetPageSize()
-{
- return ::getpagesize();
-}
-
-bool
-HostInfoPosix::GetHostname(std::string &s)
-{
- char hostname[PATH_MAX];
- hostname[sizeof(hostname) - 1] = '\0';
- if (::gethostname(hostname, sizeof(hostname) - 1) == 0)
- {
- struct hostent *h = ::gethostbyname(hostname);
- if (h)
- s.assign(h->h_name);
- else
- s.assign(hostname);
- return true;
- }
- return false;
+size_t HostInfoPosix::GetPageSize() { return ::getpagesize(); }
+
+bool HostInfoPosix::GetHostname(std::string &s) {
+ char hostname[PATH_MAX];
+ hostname[sizeof(hostname) - 1] = '\0';
+ if (::gethostname(hostname, sizeof(hostname) - 1) == 0) {
+ struct hostent *h = ::gethostbyname(hostname);
+ if (h)
+ s.assign(h->h_name);
+ else
+ s.assign(hostname);
+ return true;
+ }
+ return false;
}
#ifdef __ANDROID_NDK__
@@ -62,194 +55,164 @@ HostInfoPosix::GetHostname(std::string &
static std::mutex s_getpwuid_lock;
#endif
-const char *
-HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name)
-{
+const char *HostInfoPosix::LookupUserName(uint32_t uid,
+ std::string &user_name) {
#ifdef USE_GETPWUID
- // getpwuid_r is missing from android-9
- // make getpwuid thread safe with a mutex
- std::lock_guard<std::mutex> lock(s_getpwuid_lock);
- struct passwd *user_info_ptr = ::getpwuid(uid);
- if (user_info_ptr)
- {
- user_name.assign(user_info_ptr->pw_name);
- return user_name.c_str();
- }
+ // getpwuid_r is missing from android-9
+ // make getpwuid thread safe with a mutex
+ std::lock_guard<std::mutex> lock(s_getpwuid_lock);
+ struct passwd *user_info_ptr = ::getpwuid(uid);
+ if (user_info_ptr) {
+ user_name.assign(user_info_ptr->pw_name);
+ return user_name.c_str();
+ }
#else
- struct passwd user_info;
- struct passwd *user_info_ptr = &user_info;
- char user_buffer[PATH_MAX];
- size_t user_buffer_size = sizeof(user_buffer);
- if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0)
- {
- if (user_info_ptr)
- {
- user_name.assign(user_info_ptr->pw_name);
- return user_name.c_str();
- }
+ struct passwd user_info;
+ struct passwd *user_info_ptr = &user_info;
+ char user_buffer[PATH_MAX];
+ size_t user_buffer_size = sizeof(user_buffer);
+ if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size,
+ &user_info_ptr) == 0) {
+ if (user_info_ptr) {
+ user_name.assign(user_info_ptr->pw_name);
+ return user_name.c_str();
}
+ }
#endif
- user_name.clear();
- return nullptr;
+ user_name.clear();
+ return nullptr;
}
-const char *
-HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name)
-{
+const char *HostInfoPosix::LookupGroupName(uint32_t gid,
+ std::string &group_name) {
#ifndef __ANDROID__
- char group_buffer[PATH_MAX];
- size_t group_buffer_size = sizeof(group_buffer);
- struct group group_info;
- struct group *group_info_ptr = &group_info;
- // Try the threadsafe version first
- if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0)
- {
- if (group_info_ptr)
- {
- group_name.assign(group_info_ptr->gr_name);
- return group_name.c_str();
- }
- }
- else
- {
- // The threadsafe version isn't currently working for me on darwin, but the non-threadsafe version
- // is, so I am calling it below.
- group_info_ptr = ::getgrgid(gid);
- if (group_info_ptr)
- {
- group_name.assign(group_info_ptr->gr_name);
- return group_name.c_str();
- }
+ char group_buffer[PATH_MAX];
+ size_t group_buffer_size = sizeof(group_buffer);
+ struct group group_info;
+ struct group *group_info_ptr = &group_info;
+ // Try the threadsafe version first
+ if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size,
+ &group_info_ptr) == 0) {
+ if (group_info_ptr) {
+ group_name.assign(group_info_ptr->gr_name);
+ return group_name.c_str();
+ }
+ } else {
+ // The threadsafe version isn't currently working for me on darwin, but the
+ // non-threadsafe version
+ // is, so I am calling it below.
+ group_info_ptr = ::getgrgid(gid);
+ if (group_info_ptr) {
+ group_name.assign(group_info_ptr->gr_name);
+ return group_name.c_str();
}
- group_name.clear();
+ }
+ group_name.clear();
#else
- assert(false && "getgrgid_r() not supported on Android");
+ assert(false && "getgrgid_r() not supported on Android");
#endif
- return NULL;
+ return NULL;
}
-uint32_t
-HostInfoPosix::GetUserID()
-{
- return getuid();
-}
+uint32_t HostInfoPosix::GetUserID() { return getuid(); }
-uint32_t
-HostInfoPosix::GetGroupID()
-{
- return getgid();
-}
+uint32_t HostInfoPosix::GetGroupID() { return getgid(); }
-uint32_t
-HostInfoPosix::GetEffectiveUserID()
-{
- return geteuid();
-}
+uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); }
-uint32_t
-HostInfoPosix::GetEffectiveGroupID()
-{
- return getegid();
-}
+uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); }
-FileSpec
-HostInfoPosix::GetDefaultShell()
-{
- return FileSpec("/bin/sh", false);
-}
+FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh", false); }
-bool
-HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec)
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- FileSpec lldb_file_spec;
- if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
- return false;
+ FileSpec lldb_file_spec;
+ if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ return false;
- char raw_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+ char raw_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
- // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with */bin as the base
- // directory for helper exe programs. This will fail if the /lib and /bin directories are
- // rooted in entirely different trees.
- if (log)
- log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from "
- "this path: %s",
- raw_path);
- char *lib_pos = ::strstr(raw_path, "/lib");
- if (lib_pos != nullptr)
- {
- // Now write in bin in place of lib.
- ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin");
+ // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with
+ // */bin as the base
+ // directory for helper exe programs. This will fail if the /lib and /bin
+ // directories are
+ // rooted in entirely different trees.
+ if (log)
+ log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to "
+ "derive the bin path (ePathTypeSupportExecutableDir) from "
+ "this path: %s",
+ raw_path);
+ char *lib_pos = ::strstr(raw_path, "/lib");
+ if (lib_pos != nullptr) {
+ // Now write in bin in place of lib.
+ ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin");
- if (log)
- log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
- }
- else
- {
- if (log)
- log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction",
- __FUNCTION__);
- }
- file_spec.GetDirectory().SetCString(raw_path);
- return (bool)file_spec.GetDirectory();
+ if (log)
+ log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__,
+ raw_path);
+ } else {
+ if (log)
+ log->Printf("Host::%s() failed to find /lib/liblldb within the shared "
+ "lib path, bailing on bin path construction",
+ __FUNCTION__);
+ }
+ file_spec.GetDirectory().SetCString(raw_path);
+ return (bool)file_spec.GetDirectory();
}
-bool
-HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec)
-{
- FileSpec temp_file("/opt/local/include/lldb", false);
- file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
- return true;
+bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) {
+ FileSpec temp_file("/opt/local/include/lldb", false);
+ file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
+ return true;
}
-bool
-HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec)
-{
+bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) {
#ifndef LLDB_DISABLE_PYTHON
- FileSpec lldb_file_spec;
- if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
- return false;
+ FileSpec lldb_file_spec;
+ if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ return false;
- char raw_path[PATH_MAX];
- lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+ char raw_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
- // Build the path by backing out of the lib dir, then building
- // with whatever the real python interpreter uses. (e.g. lib
- // for most, lib64 on RHEL x86_64).
- char python_path[PATH_MAX];
- ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, LLDB_PYTHON_RELATIVE_LIBDIR);
-
- char final_path[PATH_MAX];
- realpath(python_path, final_path);
- file_spec.GetDirectory().SetCString(final_path);
+ // Build the path by backing out of the lib dir, then building
+ // with whatever the real python interpreter uses. (e.g. lib
+ // for most, lib64 on RHEL x86_64).
+ char python_path[PATH_MAX];
+ ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path,
+ LLDB_PYTHON_RELATIVE_LIBDIR);
+
+ char final_path[PATH_MAX];
+ realpath(python_path, final_path);
+ file_spec.GetDirectory().SetCString(final_path);
- return true;
+ return true;
#else
- llvm::SmallString<256> python_version_dir;
- llvm::raw_svector_ostream os(python_version_dir);
- os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
-
- // We may get our string truncated. Should we protect this with an assert?
- ::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1);
+ llvm::SmallString<256> python_version_dir;
+ llvm::raw_svector_ostream os(python_version_dir);
+ os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION
+ << "/site-packages";
+
+ // We may get our string truncated. Should we protect this with an assert?
+ ::strncat(raw_path, python_version_dir.c_str(),
+ sizeof(raw_path) - strlen(raw_path) - 1);
- file_spec.GetDirectory().SetCString(raw_path);
- return true;
+ file_spec.GetDirectory().SetCString(raw_path);
+ return true;
#endif
#else
- return false;
+ return false;
#endif
}
-bool
-HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var)
-{
- if (const char *pvar = ::getenv(var_name.c_str()))
- {
- var = std::string(pvar);
- return true;
- }
- return false;
+bool HostInfoPosix::GetEnvironmentVar(const std::string &var_name,
+ std::string &var) {
+ if (const char *pvar = ::getenv(var_name.c_str())) {
+ var = std::string(pvar);
+ return true;
+ }
+ return false;
}
Modified: lldb/trunk/source/Host/posix/HostProcessPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/HostProcessPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/HostProcessPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/HostProcessPosix.cpp Tue Sep 6 15:57:50 2016
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Host.h"
-#include "lldb/Host/posix/HostProcessPosix.h"
#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/posix/HostProcessPosix.h"
#include "llvm/ADT/STLExtras.h"
@@ -17,97 +17,77 @@
using namespace lldb_private;
-namespace
-{
- const int kInvalidPosixProcess = 0;
+namespace {
+const int kInvalidPosixProcess = 0;
}
HostProcessPosix::HostProcessPosix()
- : HostNativeProcessBase(kInvalidPosixProcess)
-{
-}
+ : HostNativeProcessBase(kInvalidPosixProcess) {}
HostProcessPosix::HostProcessPosix(lldb::process_t process)
- : HostNativeProcessBase(process)
-{
-}
+ : HostNativeProcessBase(process) {}
-HostProcessPosix::~HostProcessPosix()
-{
-}
+HostProcessPosix::~HostProcessPosix() {}
-Error HostProcessPosix::Signal(int signo) const
-{
- if (m_process == kInvalidPosixProcess)
- {
- Error error;
- error.SetErrorString("HostProcessPosix refers to an invalid process");
- return error;
- }
+Error HostProcessPosix::Signal(int signo) const {
+ if (m_process == kInvalidPosixProcess) {
+ Error error;
+ error.SetErrorString("HostProcessPosix refers to an invalid process");
+ return error;
+ }
- return HostProcessPosix::Signal(m_process, signo);
+ return HostProcessPosix::Signal(m_process, signo);
}
-Error HostProcessPosix::Signal(lldb::process_t process, int signo)
-{
- Error error;
+Error HostProcessPosix::Signal(lldb::process_t process, int signo) {
+ Error error;
- if (-1 == ::kill(process, signo))
- error.SetErrorToErrno();
+ if (-1 == ::kill(process, signo))
+ error.SetErrorToErrno();
- return error;
+ return error;
}
-Error HostProcessPosix::Terminate()
-{
- return Signal(SIGKILL);
-}
+Error HostProcessPosix::Terminate() { return Signal(SIGKILL); }
-Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const
-{
- Error error;
+Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const {
+ Error error;
- // Use special code here because proc/[pid]/exe is a symbolic link.
- char link_path[PATH_MAX];
- if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1)
- {
- error.SetErrorString("Unable to build /proc/<pid>/exe string");
- return error;
- }
-
- error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec);
- if (!error.Success())
- return error;
-
- // If the binary has been deleted, the link name has " (deleted)" appended.
- // Remove if there.
- if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)"))
- {
- const char *filename = file_spec.GetFilename().GetCString();
- static const size_t deleted_len = strlen(" (deleted)");
- const size_t len = file_spec.GetFilename().GetLength();
- file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len);
- }
+ // Use special code here because proc/[pid]/exe is a symbolic link.
+ char link_path[PATH_MAX];
+ if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1) {
+ error.SetErrorString("Unable to build /proc/<pid>/exe string");
return error;
-}
-
-lldb::pid_t HostProcessPosix::GetProcessId() const
-{
- return m_process;
-}
-
-bool HostProcessPosix::IsRunning() const
-{
- if (m_process == kInvalidPosixProcess)
- return false;
+ }
- // Send this process the null signal. If it succeeds the process is running.
- Error error = Signal(0);
- return error.Success();
-}
+ error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec);
+ if (!error.Success())
+ return error;
-HostThread
-HostProcessPosix::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals)
-{
- return Host::StartMonitoringChildProcess(callback, m_process, monitor_signals);
+ // If the binary has been deleted, the link name has " (deleted)" appended.
+ // Remove if there.
+ if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)")) {
+ const char *filename = file_spec.GetFilename().GetCString();
+ static const size_t deleted_len = strlen(" (deleted)");
+ const size_t len = file_spec.GetFilename().GetLength();
+ file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len);
+ }
+ return error;
+}
+
+lldb::pid_t HostProcessPosix::GetProcessId() const { return m_process; }
+
+bool HostProcessPosix::IsRunning() const {
+ if (m_process == kInvalidPosixProcess)
+ return false;
+
+ // Send this process the null signal. If it succeeds the process is running.
+ Error error = Signal(0);
+ return error.Success();
+}
+
+HostThread HostProcessPosix::StartMonitoring(
+ const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
+ return Host::StartMonitoringChildProcess(callback, m_process,
+ monitor_signals);
}
Modified: lldb/trunk/source/Host/posix/HostThreadPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/HostThreadPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/HostThreadPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/HostThreadPosix.cpp Tue Sep 6 15:57:50 2016
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Error.h"
#include "lldb/Host/posix/HostThreadPosix.h"
+#include "lldb/Core/Error.h"
#include <errno.h>
#include <pthread.h>
@@ -16,67 +16,50 @@
using namespace lldb;
using namespace lldb_private;
-HostThreadPosix::HostThreadPosix()
-{
-}
+HostThreadPosix::HostThreadPosix() {}
HostThreadPosix::HostThreadPosix(lldb::thread_t thread)
- : HostNativeThreadBase(thread)
-{
-}
+ : HostNativeThreadBase(thread) {}
-HostThreadPosix::~HostThreadPosix()
-{
-}
-
-Error
-HostThreadPosix::Join(lldb::thread_result_t *result)
-{
- Error error;
- if (IsJoinable())
- {
- int err = ::pthread_join(m_thread, result);
- error.SetError(err, lldb::eErrorTypePOSIX);
- }
- else
- {
- if (result)
- *result = NULL;
- error.SetError(EINVAL, eErrorTypePOSIX);
- }
-
- Reset();
- return error;
-}
+HostThreadPosix::~HostThreadPosix() {}
-Error
-HostThreadPosix::Cancel()
-{
- Error error;
- if (IsJoinable())
- {
+Error HostThreadPosix::Join(lldb::thread_result_t *result) {
+ Error error;
+ if (IsJoinable()) {
+ int err = ::pthread_join(m_thread, result);
+ error.SetError(err, lldb::eErrorTypePOSIX);
+ } else {
+ if (result)
+ *result = NULL;
+ error.SetError(EINVAL, eErrorTypePOSIX);
+ }
+
+ Reset();
+ return error;
+}
+
+Error HostThreadPosix::Cancel() {
+ Error error;
+ if (IsJoinable()) {
#ifndef __ANDROID__
#ifndef __FreeBSD__
- assert(false && "someone is calling HostThread::Cancel()");
+ assert(false && "someone is calling HostThread::Cancel()");
#endif
- int err = ::pthread_cancel(m_thread);
- error.SetError(err, eErrorTypePOSIX);
+ int err = ::pthread_cancel(m_thread);
+ error.SetError(err, eErrorTypePOSIX);
#else
- error.SetErrorString("HostThreadPosix::Cancel() not supported on Android");
+ error.SetErrorString("HostThreadPosix::Cancel() not supported on Android");
#endif
- }
- return error;
+ }
+ return error;
}
-Error
-HostThreadPosix::Detach()
-{
- Error error;
- if (IsJoinable())
- {
- int err = ::pthread_detach(m_thread);
- error.SetError(err, eErrorTypePOSIX);
- }
- Reset();
- return error;
+Error HostThreadPosix::Detach() {
+ Error error;
+ if (IsJoinable()) {
+ int err = ::pthread_detach(m_thread);
+ error.SetError(err, eErrorTypePOSIX);
+ }
+ Reset();
+ return error;
}
Modified: lldb/trunk/source/Host/posix/LockFilePosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/LockFilePosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/LockFilePosix.cpp (original)
+++ lldb/trunk/source/Host/posix/LockFilePosix.cpp Tue Sep 6 15:57:50 2016
@@ -14,64 +14,47 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
+namespace {
-Error fileLock (int fd, int cmd, int lock_type, const uint64_t start, const uint64_t len)
-{
- struct flock fl;
+Error fileLock(int fd, int cmd, int lock_type, const uint64_t start,
+ const uint64_t len) {
+ struct flock fl;
- fl.l_type = lock_type;
- fl.l_whence = SEEK_SET;
- fl.l_start = start;
- fl.l_len = len;
- fl.l_pid = ::getpid ();
+ fl.l_type = lock_type;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = start;
+ fl.l_len = len;
+ fl.l_pid = ::getpid();
- Error error;
- if (::fcntl (fd, cmd, &fl) == -1)
- error.SetErrorToErrno ();
+ Error error;
+ if (::fcntl(fd, cmd, &fl) == -1)
+ error.SetErrorToErrno();
- return error;
+ return error;
}
-} // namespace
+} // namespace
-LockFilePosix::LockFilePosix (int fd)
- : LockFileBase (fd)
-{
-}
+LockFilePosix::LockFilePosix(int fd) : LockFileBase(fd) {}
-LockFilePosix::~LockFilePosix ()
-{
- Unlock ();
-}
+LockFilePosix::~LockFilePosix() { Unlock(); }
-Error
-LockFilePosix::DoWriteLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_fd, F_SETLKW, F_WRLCK, start, len);
+Error LockFilePosix::DoWriteLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_fd, F_SETLKW, F_WRLCK, start, len);
}
-Error
-LockFilePosix::DoTryWriteLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_fd, F_SETLK, F_WRLCK, start, len);
+Error LockFilePosix::DoTryWriteLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_fd, F_SETLK, F_WRLCK, start, len);
}
-Error
-LockFilePosix::DoReadLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_fd, F_SETLKW, F_RDLCK, start, len);
+Error LockFilePosix::DoReadLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_fd, F_SETLKW, F_RDLCK, start, len);
}
-Error
-LockFilePosix::DoTryReadLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_fd, F_SETLK, F_RDLCK, start, len);
+Error LockFilePosix::DoTryReadLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_fd, F_SETLK, F_RDLCK, start, len);
}
-Error
-LockFilePosix::DoUnlock ()
-{
- return fileLock (m_fd, F_SETLK, F_UNLCK, m_start, m_len);
+Error LockFilePosix::DoUnlock() {
+ return fileLock(m_fd, F_SETLK, F_UNLCK, m_start, m_len);
}
Modified: lldb/trunk/source/Host/posix/MainLoopPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/MainLoopPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/MainLoopPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/MainLoopPosix.cpp Tue Sep 6 15:57:50 2016
@@ -18,176 +18,162 @@ using namespace lldb_private;
static sig_atomic_t g_signal_flags[NSIG];
-static void
-SignalHandler(int signo, siginfo_t *info, void *)
-{
- assert(signo < NSIG);
- g_signal_flags[signo] = 1;
+static void SignalHandler(int signo, siginfo_t *info, void *) {
+ assert(signo < NSIG);
+ g_signal_flags[signo] = 1;
}
-
-MainLoopPosix::~MainLoopPosix()
-{
- assert(m_read_fds.size() == 0);
- assert(m_signals.size() == 0);
+MainLoopPosix::~MainLoopPosix() {
+ assert(m_read_fds.size() == 0);
+ assert(m_signals.size() == 0);
}
MainLoopPosix::ReadHandleUP
-MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Error &error)
-{
- if (!object_sp || !object_sp->IsValid())
- {
- error.SetErrorString("IO object is not valid.");
- return nullptr;
- }
-
- const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
- if (! inserted)
- {
- error.SetErrorStringWithFormat("File descriptor %d already monitored.",
- object_sp->GetWaitableHandle());
- return nullptr;
- }
+MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp,
+ const Callback &callback, Error &error) {
+ if (!object_sp || !object_sp->IsValid()) {
+ error.SetErrorString("IO object is not valid.");
+ return nullptr;
+ }
+
+ const bool inserted =
+ m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
+ if (!inserted) {
+ error.SetErrorStringWithFormat("File descriptor %d already monitored.",
+ object_sp->GetWaitableHandle());
+ return nullptr;
+ }
- return CreateReadHandle(object_sp);
+ return CreateReadHandle(object_sp);
}
-// We shall block the signal, then install the signal handler. The signal will be unblocked in
+// We shall block the signal, then install the signal handler. The signal will
+// be unblocked in
// the Run() function to check for signal delivery.
MainLoopPosix::SignalHandleUP
-MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error)
-{
- if (m_signals.find(signo) != m_signals.end())
- {
- error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
- return nullptr;
- }
+MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
+ Error &error) {
+ if (m_signals.find(signo) != m_signals.end()) {
+ error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
+ return nullptr;
+ }
+
+ SignalInfo info;
+ info.callback = callback;
+ struct sigaction new_action;
+ new_action.sa_sigaction = &SignalHandler;
+ new_action.sa_flags = SA_SIGINFO;
+ sigemptyset(&new_action.sa_mask);
+ sigaddset(&new_action.sa_mask, signo);
+
+ sigset_t old_set;
+ if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) {
+ error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n",
+ ret);
+ return nullptr;
+ }
+
+ info.was_blocked = sigismember(&old_set, signo);
+ if (sigaction(signo, &new_action, &info.old_action) == -1) {
+ error.SetErrorToErrno();
+ if (!info.was_blocked)
+ pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
+ return nullptr;
+ }
+
+ m_signals.insert({signo, info});
+ g_signal_flags[signo] = 0;
+
+ return SignalHandleUP(new SignalHandle(*this, signo));
+}
+
+void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) {
+ bool erased = m_read_fds.erase(handle);
+ UNUSED_IF_ASSERT_DISABLED(erased);
+ assert(erased);
+}
+
+void MainLoopPosix::UnregisterSignal(int signo) {
+ // We undo the actions of RegisterSignal on a best-effort basis.
+ auto it = m_signals.find(signo);
+ assert(it != m_signals.end());
+
+ sigaction(signo, &it->second.old_action, nullptr);
+
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, signo);
+ pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set,
+ nullptr);
+
+ m_signals.erase(it);
+}
+
+Error MainLoopPosix::Run() {
+ std::vector<int> signals;
+ sigset_t sigmask;
+ std::vector<int> read_fds;
+ fd_set read_fd_set;
+ m_terminate_request = false;
+
+ // run until termination or until we run out of things to listen to
+ while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
+ // To avoid problems with callbacks changing the things we're supposed to
+ // listen to, we
+ // will store the *real* list of events separately.
+ signals.clear();
+ read_fds.clear();
+ FD_ZERO(&read_fd_set);
+ int nfds = 0;
+
+ if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
+ return Error("pthread_sigmask failed with error %d\n", ret);
+
+ for (const auto &fd : m_read_fds) {
+ read_fds.push_back(fd.first);
+ FD_SET(fd.first, &read_fd_set);
+ nfds = std::max(nfds, fd.first + 1);
+ }
+
+ for (const auto &sig : m_signals) {
+ signals.push_back(sig.first);
+ sigdelset(&sigmask, sig.first);
+ }
+
+ if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) ==
+ -1 &&
+ errno != EINTR)
+ return Error(errno, eErrorTypePOSIX);
+
+ for (int sig : signals) {
+ if (g_signal_flags[sig] == 0)
+ continue; // No signal
+ g_signal_flags[sig] = 0;
+
+ auto it = m_signals.find(sig);
+ if (it == m_signals.end())
+ continue; // Signal must have gotten unregistered in the meantime
+
+ it->second.callback(*this); // Do the work
+
+ if (m_terminate_request)
+ return Error();
+ }
+
+ for (int fd : read_fds) {
+ if (!FD_ISSET(fd, &read_fd_set))
+ continue; // Not ready
+
+ auto it = m_read_fds.find(fd);
+ if (it == m_read_fds.end())
+ continue; // File descriptor must have gotten unregistered in the
+ // meantime
- SignalInfo info;
- info.callback = callback;
- struct sigaction new_action;
- new_action.sa_sigaction = &SignalHandler;
- new_action.sa_flags = SA_SIGINFO;
- sigemptyset(&new_action.sa_mask);
- sigaddset(&new_action.sa_mask, signo);
-
- sigset_t old_set;
- if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set))
- {
- error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", ret);
- return nullptr;
- }
+ it->second(*this); // Do the work
- info.was_blocked = sigismember(&old_set, signo);
- if (sigaction(signo, &new_action, &info.old_action) == -1)
- {
- error.SetErrorToErrno();
- if (!info.was_blocked)
- pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
- return nullptr;
+ if (m_terminate_request)
+ return Error();
}
-
- m_signals.insert({signo, info});
- g_signal_flags[signo] = 0;
-
- return SignalHandleUP(new SignalHandle(*this, signo));
-}
-
-void
-MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle)
-{
- bool erased = m_read_fds.erase(handle);
- UNUSED_IF_ASSERT_DISABLED(erased);
- assert(erased);
-}
-
-void
-MainLoopPosix::UnregisterSignal(int signo)
-{
- // We undo the actions of RegisterSignal on a best-effort basis.
- auto it = m_signals.find(signo);
- assert(it != m_signals.end());
-
- sigaction(signo, &it->second.old_action, nullptr);
-
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, signo);
- pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr);
-
- m_signals.erase(it);
-}
-
-Error
-MainLoopPosix::Run()
-{
- std::vector<int> signals;
- sigset_t sigmask;
- std::vector<int> read_fds;
- fd_set read_fd_set;
- m_terminate_request = false;
-
- // run until termination or until we run out of things to listen to
- while (! m_terminate_request && (!m_read_fds.empty() || !m_signals.empty()))
- {
- // To avoid problems with callbacks changing the things we're supposed to listen to, we
- // will store the *real* list of events separately.
- signals.clear();
- read_fds.clear();
- FD_ZERO(&read_fd_set);
- int nfds = 0;
-
- if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
- return Error("pthread_sigmask failed with error %d\n", ret);
-
- for (const auto &fd: m_read_fds)
- {
- read_fds.push_back(fd.first);
- FD_SET(fd.first, &read_fd_set);
- nfds = std::max(nfds, fd.first+1);
- }
-
- for (const auto &sig: m_signals)
- {
- signals.push_back(sig.first);
- sigdelset(&sigmask, sig.first);
- }
-
- if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR)
- return Error(errno, eErrorTypePOSIX);
-
- for (int sig: signals)
- {
- if (g_signal_flags[sig] == 0)
- continue; // No signal
- g_signal_flags[sig] = 0;
-
- auto it = m_signals.find(sig);
- if (it == m_signals.end())
- continue; // Signal must have gotten unregistered in the meantime
-
- it->second.callback(*this); // Do the work
-
- if (m_terminate_request)
- return Error();
- }
-
- for (int fd: read_fds)
- {
- if (!FD_ISSET(fd, &read_fd_set))
- continue; // Not ready
-
- auto it = m_read_fds.find(fd);
- if (it == m_read_fds.end())
- continue; // File descriptor must have gotten unregistered in the meantime
-
- it->second(*this); // Do the work
-
- if (m_terminate_request)
- return Error();
- }
- }
- return Error();
+ }
+ return Error();
}
-
-
Modified: lldb/trunk/source/Host/posix/PipePosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/PipePosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/PipePosix.cpp (original)
+++ lldb/trunk/source/Host/posix/PipePosix.cpp Tue Sep 6 15:57:50 2016
@@ -26,9 +26,9 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
using namespace lldb;
using namespace lldb_private;
@@ -39,343 +39,280 @@ enum PIPES { READ, WRITE }; // Constants
// pipe2 is supported by a limited set of platforms
// TODO: Add more platforms that support pipe2.
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
+ defined(__NetBSD__)
#define PIPE2_SUPPORTED 1
#else
#define PIPE2_SUPPORTED 0
#endif
-namespace
-{
+namespace {
constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100;
#if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED
-bool SetCloexecFlag(int fd)
-{
- int flags = ::fcntl(fd, F_GETFD);
- if (flags == -1)
- return false;
- return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
+bool SetCloexecFlag(int fd) {
+ int flags = ::fcntl(fd, F_GETFD);
+ if (flags == -1)
+ return false;
+ return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
}
#endif
-std::chrono::time_point<std::chrono::steady_clock>
-Now()
-{
- return std::chrono::steady_clock::now();
+std::chrono::time_point<std::chrono::steady_clock> Now() {
+ return std::chrono::steady_clock::now();
}
-
}
PipePosix::PipePosix()
- : m_fds{
- PipePosix::kInvalidDescriptor,
- PipePosix::kInvalidDescriptor
- } {}
+ : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {}
-PipePosix::PipePosix(int read_fd, int write_fd)
- : m_fds{read_fd, write_fd} {}
+PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {}
PipePosix::PipePosix(PipePosix &&pipe_posix)
: PipeBase{std::move(pipe_posix)},
- m_fds{
- pipe_posix.ReleaseReadFileDescriptor(),
- pipe_posix.ReleaseWriteFileDescriptor()
- } {}
-
-PipePosix &PipePosix::operator=(PipePosix &&pipe_posix)
-{
- PipeBase::operator=(std::move(pipe_posix));
- m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor();
- m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor();
- return *this;
-}
-
-PipePosix::~PipePosix()
-{
- Close();
-}
-
-Error
-PipePosix::CreateNew(bool child_processes_inherit)
-{
- if (CanRead() || CanWrite())
- return Error(EINVAL, eErrorTypePOSIX);
+ m_fds{pipe_posix.ReleaseReadFileDescriptor(),
+ pipe_posix.ReleaseWriteFileDescriptor()} {}
+
+PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) {
+ PipeBase::operator=(std::move(pipe_posix));
+ m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor();
+ m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor();
+ return *this;
+}
+
+PipePosix::~PipePosix() { Close(); }
+
+Error PipePosix::CreateNew(bool child_processes_inherit) {
+ if (CanRead() || CanWrite())
+ return Error(EINVAL, eErrorTypePOSIX);
- Error error;
+ Error error;
#if PIPE2_SUPPORTED
- if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0)
- return error;
+ if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0)
+ return error;
#else
- if (::pipe(m_fds) == 0)
- {
+ if (::pipe(m_fds) == 0) {
#ifdef FD_CLOEXEC
- if (!child_processes_inherit)
- {
- if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1]))
- {
- error.SetErrorToErrno();
- Close();
- return error;
- }
- }
-#endif
+ if (!child_processes_inherit) {
+ if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) {
+ error.SetErrorToErrno();
+ Close();
return error;
+ }
}
#endif
-
- error.SetErrorToErrno();
- m_fds[READ] = PipePosix::kInvalidDescriptor;
- m_fds[WRITE] = PipePosix::kInvalidDescriptor;
return error;
+ }
+#endif
+
+ error.SetErrorToErrno();
+ m_fds[READ] = PipePosix::kInvalidDescriptor;
+ m_fds[WRITE] = PipePosix::kInvalidDescriptor;
+ return error;
}
-Error
-PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit)
-{
- if (CanRead() || CanWrite())
- return Error("Pipe is already opened");
+Error PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) {
+ if (CanRead() || CanWrite())
+ return Error("Pipe is already opened");
- Error error;
- if (::mkfifo(name.data(), 0660) != 0)
- error.SetErrorToErrno();
+ Error error;
+ if (::mkfifo(name.data(), 0660) != 0)
+ error.SetErrorToErrno();
- return error;
+ return error;
}
-Error
-PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name)
-{
- llvm::SmallString<PATH_MAX> named_pipe_path;
- llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str());
- FileSpec tmpdir_file_spec;
- tmpdir_file_spec.Clear();
- if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
- {
- tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
- }
- else
- {
- tmpdir_file_spec.AppendPathComponent("/tmp");
- tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
- }
-
- // It's possible that another process creates the target path after we've
- // verified it's available but before we create it, in which case we
- // should try again.
- Error error;
- do {
- llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), named_pipe_path);
- error = CreateNew(named_pipe_path, child_process_inherit);
- } while (error.GetError() == EEXIST);
+Error PipePosix::CreateWithUniqueName(llvm::StringRef prefix,
+ bool child_process_inherit,
+ llvm::SmallVectorImpl<char> &name) {
+ llvm::SmallString<PATH_MAX> named_pipe_path;
+ llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str());
+ FileSpec tmpdir_file_spec;
+ tmpdir_file_spec.Clear();
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) {
+ tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
+ } else {
+ tmpdir_file_spec.AppendPathComponent("/tmp");
+ tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str());
+ }
+
+ // It's possible that another process creates the target path after we've
+ // verified it's available but before we create it, in which case we
+ // should try again.
+ Error error;
+ do {
+ llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(),
+ named_pipe_path);
+ error = CreateNew(named_pipe_path, child_process_inherit);
+ } while (error.GetError() == EEXIST);
+
+ if (error.Success())
+ name = named_pipe_path;
+ return error;
+}
+
+Error PipePosix::OpenAsReader(llvm::StringRef name,
+ bool child_process_inherit) {
+ if (CanRead() || CanWrite())
+ return Error("Pipe is already opened");
+
+ int flags = O_RDONLY | O_NONBLOCK;
+ if (!child_process_inherit)
+ flags |= O_CLOEXEC;
+
+ Error error;
+ int fd = ::open(name.data(), flags);
+ if (fd != -1)
+ m_fds[READ] = fd;
+ else
+ error.SetErrorToErrno();
- if (error.Success())
- name = named_pipe_path;
- return error;
+ return error;
}
-Error
-PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
-{
- if (CanRead() || CanWrite())
- return Error("Pipe is already opened");
-
- int flags = O_RDONLY | O_NONBLOCK;
- if (!child_process_inherit)
- flags |= O_CLOEXEC;
+Error PipePosix::OpenAsWriterWithTimeout(
+ llvm::StringRef name, bool child_process_inherit,
+ const std::chrono::microseconds &timeout) {
+ if (CanRead() || CanWrite())
+ return Error("Pipe is already opened");
+
+ int flags = O_WRONLY | O_NONBLOCK;
+ if (!child_process_inherit)
+ flags |= O_CLOEXEC;
+
+ using namespace std::chrono;
+ const auto finish_time = Now() + timeout;
+
+ while (!CanWrite()) {
+ if (timeout != microseconds::zero()) {
+ const auto dur = duration_cast<microseconds>(finish_time - Now()).count();
+ if (dur <= 0)
+ return Error("timeout exceeded - reader hasn't opened so far");
+ }
- Error error;
+ errno = 0;
int fd = ::open(name.data(), flags);
- if (fd != -1)
- m_fds[READ] = fd;
- else
- error.SetErrorToErrno();
-
- return error;
-}
-
-Error
-PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
-{
- if (CanRead() || CanWrite())
- return Error("Pipe is already opened");
-
- int flags = O_WRONLY | O_NONBLOCK;
- if (!child_process_inherit)
- flags |= O_CLOEXEC;
-
- using namespace std::chrono;
- const auto finish_time = Now() + timeout;
-
- while (!CanWrite())
- {
- if (timeout != microseconds::zero())
- {
- const auto dur = duration_cast<microseconds>(finish_time - Now()).count();
- if (dur <= 0)
- return Error("timeout exceeded - reader hasn't opened so far");
- }
-
- errno = 0;
- int fd = ::open(name.data(), flags);
- if (fd == -1)
- {
- const auto errno_copy = errno;
- // We may get ENXIO if a reader side of the pipe hasn't opened yet.
- if (errno_copy != ENXIO)
- return Error(errno_copy, eErrorTypePOSIX);
-
- std::this_thread::sleep_for(milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS));
- }
- else
- {
- m_fds[WRITE] = fd;
- }
+ if (fd == -1) {
+ const auto errno_copy = errno;
+ // We may get ENXIO if a reader side of the pipe hasn't opened yet.
+ if (errno_copy != ENXIO)
+ return Error(errno_copy, eErrorTypePOSIX);
+
+ std::this_thread::sleep_for(
+ milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS));
+ } else {
+ m_fds[WRITE] = fd;
}
+ }
- return Error();
+ return Error();
}
-int
-PipePosix::GetReadFileDescriptor() const
-{
- return m_fds[READ];
-}
+int PipePosix::GetReadFileDescriptor() const { return m_fds[READ]; }
-int
-PipePosix::GetWriteFileDescriptor() const
-{
- return m_fds[WRITE];
-}
+int PipePosix::GetWriteFileDescriptor() const { return m_fds[WRITE]; }
-int
-PipePosix::ReleaseReadFileDescriptor()
-{
- const int fd = m_fds[READ];
- m_fds[READ] = PipePosix::kInvalidDescriptor;
- return fd;
+int PipePosix::ReleaseReadFileDescriptor() {
+ const int fd = m_fds[READ];
+ m_fds[READ] = PipePosix::kInvalidDescriptor;
+ return fd;
}
-int
-PipePosix::ReleaseWriteFileDescriptor()
-{
- const int fd = m_fds[WRITE];
- m_fds[WRITE] = PipePosix::kInvalidDescriptor;
- return fd;
+int PipePosix::ReleaseWriteFileDescriptor() {
+ const int fd = m_fds[WRITE];
+ m_fds[WRITE] = PipePosix::kInvalidDescriptor;
+ return fd;
}
-void
-PipePosix::Close()
-{
- CloseReadFileDescriptor();
- CloseWriteFileDescriptor();
+void PipePosix::Close() {
+ CloseReadFileDescriptor();
+ CloseWriteFileDescriptor();
}
-Error
-PipePosix::Delete(llvm::StringRef name)
-{
- return FileSystem::Unlink(FileSpec{name.data(), true});
+Error PipePosix::Delete(llvm::StringRef name) {
+ return FileSystem::Unlink(FileSpec{name.data(), true});
}
-bool
-PipePosix::CanRead() const
-{
- return m_fds[READ] != PipePosix::kInvalidDescriptor;
+bool PipePosix::CanRead() const {
+ return m_fds[READ] != PipePosix::kInvalidDescriptor;
}
-bool
-PipePosix::CanWrite() const
-{
- return m_fds[WRITE] != PipePosix::kInvalidDescriptor;
+bool PipePosix::CanWrite() const {
+ return m_fds[WRITE] != PipePosix::kInvalidDescriptor;
}
-void
-PipePosix::CloseReadFileDescriptor()
-{
- if (CanRead())
- {
- close(m_fds[READ]);
- m_fds[READ] = PipePosix::kInvalidDescriptor;
- }
+void PipePosix::CloseReadFileDescriptor() {
+ if (CanRead()) {
+ close(m_fds[READ]);
+ m_fds[READ] = PipePosix::kInvalidDescriptor;
+ }
}
-void
-PipePosix::CloseWriteFileDescriptor()
-{
- if (CanWrite())
- {
- close(m_fds[WRITE]);
- m_fds[WRITE] = PipePosix::kInvalidDescriptor;
- }
+void PipePosix::CloseWriteFileDescriptor() {
+ if (CanWrite()) {
+ close(m_fds[WRITE]);
+ m_fds[WRITE] = PipePosix::kInvalidDescriptor;
+ }
}
-Error
-PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read)
-{
- bytes_read = 0;
- if (!CanRead())
- return Error(EINVAL, eErrorTypePOSIX);
-
- const int fd = GetReadFileDescriptor();
-
- SelectHelper select_helper;
- select_helper.SetTimeout(timeout);
- select_helper.FDSetRead(fd);
-
- Error error;
- while (error.Success())
- {
- error = select_helper.Select();
- if (error.Success())
- {
- auto result = ::read(fd, reinterpret_cast<char*>(buf) + bytes_read, size - bytes_read);
- if (result != -1)
- {
- bytes_read += result;
- if (bytes_read == size || result == 0)
- break;
- }
- else
- {
- error.SetErrorToErrno();
- break;
- }
- }
+Error PipePosix::ReadWithTimeout(void *buf, size_t size,
+ const std::chrono::microseconds &timeout,
+ size_t &bytes_read) {
+ bytes_read = 0;
+ if (!CanRead())
+ return Error(EINVAL, eErrorTypePOSIX);
+
+ const int fd = GetReadFileDescriptor();
+
+ SelectHelper select_helper;
+ select_helper.SetTimeout(timeout);
+ select_helper.FDSetRead(fd);
+
+ Error error;
+ while (error.Success()) {
+ error = select_helper.Select();
+ if (error.Success()) {
+ auto result = ::read(fd, reinterpret_cast<char *>(buf) + bytes_read,
+ size - bytes_read);
+ if (result != -1) {
+ bytes_read += result;
+ if (bytes_read == size || result == 0)
+ break;
+ } else {
+ error.SetErrorToErrno();
+ break;
+ }
}
- return error;
+ }
+ return error;
}
-Error
-PipePosix::Write(const void *buf, size_t size, size_t &bytes_written)
-{
- bytes_written = 0;
- if (!CanWrite())
- return Error(EINVAL, eErrorTypePOSIX);
-
- const int fd = GetWriteFileDescriptor();
- SelectHelper select_helper;
- select_helper.SetTimeout(std::chrono::seconds(0));
- select_helper.FDSetWrite(fd);
-
- Error error;
- while (error.Success())
- {
- error = select_helper.Select();
- if (error.Success())
- {
- auto result = ::write(fd, reinterpret_cast<const char*>(buf) + bytes_written, size - bytes_written);
- if (result != -1)
- {
- bytes_written += result;
- if (bytes_written == size)
- break;
- }
- else
- {
- error.SetErrorToErrno();
- }
- }
+Error PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) {
+ bytes_written = 0;
+ if (!CanWrite())
+ return Error(EINVAL, eErrorTypePOSIX);
+
+ const int fd = GetWriteFileDescriptor();
+ SelectHelper select_helper;
+ select_helper.SetTimeout(std::chrono::seconds(0));
+ select_helper.FDSetWrite(fd);
+
+ Error error;
+ while (error.Success()) {
+ error = select_helper.Select();
+ if (error.Success()) {
+ auto result =
+ ::write(fd, reinterpret_cast<const char *>(buf) + bytes_written,
+ size - bytes_written);
+ if (result != -1) {
+ bytes_written += result;
+ if (bytes_written == size)
+ break;
+ } else {
+ error.SetErrorToErrno();
+ }
}
- return error;
+ }
+ return error;
}
Modified: lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp (original)
+++ lldb/trunk/source/Host/posix/ProcessLauncherPosix.cpp Tue Sep 6 15:57:50 2016
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/posix/ProcessLauncherPosix.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
-#include "lldb/Host/posix/ProcessLauncherPosix.h"
#include "lldb/Target/ProcessLaunchInfo.h"
@@ -19,15 +19,16 @@ using namespace lldb;
using namespace lldb_private;
HostProcess
-ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
-{
- lldb::pid_t pid;
- char exe_path[PATH_MAX];
-
- launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
-
- // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this
- // ProcessLauncher when it wants a posix_spawn launch.
- error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid);
- return HostProcess(pid);
+ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info,
+ Error &error) {
+ lldb::pid_t pid;
+ char exe_path[PATH_MAX];
+
+ launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
+
+ // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make
+ // MacOSX re-use this
+ // ProcessLauncher when it wants a posix_spawn launch.
+ error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid);
+ return HostProcess(pid);
}
Modified: lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp Tue Sep 6 15:57:50 2016
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Host/TimeValue.h"
-#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -19,345 +19,319 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
-// This is a simple helper class to package up the information needed to return from a Read/Write
-// operation function. Since there is a lot of code to be run before exit regardless of whether the
-// operation succeeded or failed, combined with many possible return paths, this is the cleanest
+namespace {
+// This is a simple helper class to package up the information needed to return
+// from a Read/Write
+// operation function. Since there is a lot of code to be run before exit
+// regardless of whether the
+// operation succeeded or failed, combined with many possible return paths, this
+// is the cleanest
// way to represent it.
-class ReturnInfo
-{
- public:
- void
- Set(size_t bytes, ConnectionStatus status, DWORD error_code)
- {
- m_error.SetError(error_code, eErrorTypeWin32);
- m_bytes = bytes;
- m_status = status;
- }
-
- void
- Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg)
- {
- m_error.SetErrorString(error_msg.data());
- m_bytes = bytes;
- m_status = status;
- }
-
- size_t
- GetBytes() const
- {
- return m_bytes;
- }
- ConnectionStatus
- GetStatus() const
- {
- return m_status;
- }
- const Error &
- GetError() const
- {
- return m_error;
- }
-
- private:
- Error m_error;
- size_t m_bytes;
- ConnectionStatus m_status;
+class ReturnInfo {
+public:
+ void Set(size_t bytes, ConnectionStatus status, DWORD error_code) {
+ m_error.SetError(error_code, eErrorTypeWin32);
+ m_bytes = bytes;
+ m_status = status;
+ }
+
+ void Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) {
+ m_error.SetErrorString(error_msg.data());
+ m_bytes = bytes;
+ m_status = status;
+ }
+
+ size_t GetBytes() const { return m_bytes; }
+ ConnectionStatus GetStatus() const { return m_status; }
+ const Error &GetError() const { return m_error; }
+
+private:
+ Error m_error;
+ size_t m_bytes;
+ ConnectionStatus m_status;
};
}
ConnectionGenericFile::ConnectionGenericFile()
- : m_file(INVALID_HANDLE_VALUE)
- , m_owns_file(false)
-{
- ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
- ::ZeroMemory(&m_file_position, sizeof(m_file_position));
- InitializeEventHandles();
+ : m_file(INVALID_HANDLE_VALUE), m_owns_file(false) {
+ ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+ ::ZeroMemory(&m_file_position, sizeof(m_file_position));
+ InitializeEventHandles();
}
ConnectionGenericFile::ConnectionGenericFile(lldb::file_t file, bool owns_file)
- : m_file(file)
- , m_owns_file(owns_file)
-{
- ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
- ::ZeroMemory(&m_file_position, sizeof(m_file_position));
- InitializeEventHandles();
-}
-
-ConnectionGenericFile::~ConnectionGenericFile()
-{
- if (m_owns_file && IsConnected())
- ::CloseHandle(m_file);
-
- ::CloseHandle(m_event_handles[kBytesAvailableEvent]);
- ::CloseHandle(m_event_handles[kInterruptEvent]);
-}
-
-void
-ConnectionGenericFile::InitializeEventHandles()
-{
- m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL);
-
- // Note, we should use a manual reset event for the hEvent argument of the OVERLAPPED. This
- // is because both WaitForMultipleObjects and GetOverlappedResult (if you set the bWait
- // argument to TRUE) will wait for the event to be signalled. If we use an auto-reset event,
- // WaitForMultipleObjects will reset the event, return successfully, and then
- // GetOverlappedResult will block since the event is no longer signalled.
- m_event_handles[kBytesAvailableEvent] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
-}
-
-bool
-ConnectionGenericFile::IsConnected() const
-{
- return m_file && (m_file != INVALID_HANDLE_VALUE);
-}
-
-lldb::ConnectionStatus
-ConnectionGenericFile::Connect(const char *s, Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionGenericFile::Connect (url = '%s')", static_cast<void *>(this), s);
-
- if (strstr(s, "file://") != s)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s);
- return eConnectionStatusError;
- }
+ : m_file(file), m_owns_file(owns_file) {
+ ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+ ::ZeroMemory(&m_file_position, sizeof(m_file_position));
+ InitializeEventHandles();
+}
- if (IsConnected())
- {
- ConnectionStatus status = Disconnect(error_ptr);
- if (status != eConnectionStatusSuccess)
- return status;
- }
+ConnectionGenericFile::~ConnectionGenericFile() {
+ if (m_owns_file && IsConnected())
+ ::CloseHandle(m_file);
- // file://PATH
- const char *path = s + strlen("file://");
- // Open the file for overlapped access. If it does not exist, create it. We open it overlapped
- // so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read
- // to be interrupted by an event object.
- std::wstring wpath;
- if (!llvm::ConvertUTF8toWide(path, wpath))
- {
- if (error_ptr)
- error_ptr->SetError(1, eErrorTypeGeneric);
- return eConnectionStatusError;
- }
- m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS,
- FILE_FLAG_OVERLAPPED, NULL);
- if (m_file == INVALID_HANDLE_VALUE)
- {
- if (error_ptr)
- error_ptr->SetError(::GetLastError(), eErrorTypeWin32);
- return eConnectionStatusError;
- }
+ ::CloseHandle(m_event_handles[kBytesAvailableEvent]);
+ ::CloseHandle(m_event_handles[kInterruptEvent]);
+}
- m_owns_file = true;
- m_uri.assign(s);
- return eConnectionStatusSuccess;
+void ConnectionGenericFile::InitializeEventHandles() {
+ m_event_handles[kInterruptEvent] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Note, we should use a manual reset event for the hEvent argument of the
+ // OVERLAPPED. This
+ // is because both WaitForMultipleObjects and GetOverlappedResult (if you set
+ // the bWait
+ // argument to TRUE) will wait for the event to be signalled. If we use an
+ // auto-reset event,
+ // WaitForMultipleObjects will reset the event, return successfully, and then
+ // GetOverlappedResult will block since the event is no longer signalled.
+ m_event_handles[kBytesAvailableEvent] =
+ ::CreateEvent(NULL, TRUE, FALSE, NULL);
}
-lldb::ConnectionStatus
-ConnectionGenericFile::Disconnect(Error *error_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- log->Printf("%p ConnectionGenericFile::Disconnect ()", static_cast<void *>(this));
-
- if (!IsConnected())
- return eConnectionStatusSuccess;
-
- // Reset the handle so that after we unblock any pending reads, subsequent calls to Read() will
- // see a disconnected state.
- HANDLE old_file = m_file;
- m_file = INVALID_HANDLE_VALUE;
-
- // Set the disconnect event so that any blocking reads unblock, then cancel any pending IO operations.
- ::CancelIoEx(old_file, &m_overlapped);
-
- // Close the file handle if we owned it, but don't close the event handles. We could always
- // reconnect with the same Connection instance.
- if (m_owns_file)
- ::CloseHandle(old_file);
-
- ::ZeroMemory(&m_file_position, sizeof(m_file_position));
- m_owns_file = false;
- m_uri.clear();
- return eConnectionStatusSuccess;
+bool ConnectionGenericFile::IsConnected() const {
+ return m_file && (m_file != INVALID_HANDLE_VALUE);
}
-size_t
-ConnectionGenericFile::Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr)
-{
- ReturnInfo return_info;
- BOOL result = 0;
- DWORD bytes_read = 0;
+lldb::ConnectionStatus ConnectionGenericFile::Connect(const char *s,
+ Error *error_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf("%p ConnectionGenericFile::Connect (url = '%s')",
+ static_cast<void *>(this), s);
+ if (strstr(s, "file://") != s) {
if (error_ptr)
- error_ptr->Clear();
+ error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'",
+ s);
+ return eConnectionStatusError;
+ }
+
+ if (IsConnected()) {
+ ConnectionStatus status = Disconnect(error_ptr);
+ if (status != eConnectionStatusSuccess)
+ return status;
+ }
+
+ // file://PATH
+ const char *path = s + strlen("file://");
+ // Open the file for overlapped access. If it does not exist, create it. We
+ // open it overlapped
+ // so that we can issue asynchronous reads and then use WaitForMultipleObjects
+ // to allow the read
+ // to be interrupted by an event object.
+ std::wstring wpath;
+ if (!llvm::ConvertUTF8toWide(path, wpath)) {
+ if (error_ptr)
+ error_ptr->SetError(1, eErrorTypeGeneric);
+ return eConnectionStatusError;
+ }
+ m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, OPEN_ALWAYS,
+ FILE_FLAG_OVERLAPPED, NULL);
+ if (m_file == INVALID_HANDLE_VALUE) {
+ if (error_ptr)
+ error_ptr->SetError(::GetLastError(), eErrorTypeWin32);
+ return eConnectionStatusError;
+ }
+
+ m_owns_file = true;
+ m_uri.assign(s);
+ return eConnectionStatusSuccess;
+}
+
+lldb::ConnectionStatus ConnectionGenericFile::Disconnect(Error *error_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf("%p ConnectionGenericFile::Disconnect ()",
+ static_cast<void *>(this));
- if (!IsConnected())
- {
- return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
- goto finish;
- }
+ if (!IsConnected())
+ return eConnectionStatusSuccess;
- m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent];
+ // Reset the handle so that after we unblock any pending reads, subsequent
+ // calls to Read() will
+ // see a disconnected state.
+ HANDLE old_file = m_file;
+ m_file = INVALID_HANDLE_VALUE;
+
+ // Set the disconnect event so that any blocking reads unblock, then cancel
+ // any pending IO operations.
+ ::CancelIoEx(old_file, &m_overlapped);
+
+ // Close the file handle if we owned it, but don't close the event handles.
+ // We could always
+ // reconnect with the same Connection instance.
+ if (m_owns_file)
+ ::CloseHandle(old_file);
+
+ ::ZeroMemory(&m_file_position, sizeof(m_file_position));
+ m_owns_file = false;
+ m_uri.clear();
+ return eConnectionStatusSuccess;
+}
+
+size_t ConnectionGenericFile::Read(void *dst, size_t dst_len,
+ uint32_t timeout_usec,
+ lldb::ConnectionStatus &status,
+ Error *error_ptr) {
+ ReturnInfo return_info;
+ BOOL result = 0;
+ DWORD bytes_read = 0;
- result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped);
- if (result || ::GetLastError() == ERROR_IO_PENDING)
- {
- if (!result)
- {
- // The expected return path. The operation is pending. Wait for the operation to complete
- // or be interrupted.
- TimeValue time_value;
- time_value.OffsetWithMicroSeconds(timeout_usec);
- DWORD milliseconds = time_value.milliseconds();
- DWORD wait_result = ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles), m_event_handles, FALSE, milliseconds);
- // All of the events are manual reset events, so make sure we reset them to non-signalled.
- switch (wait_result)
- {
- case WAIT_OBJECT_0 + kBytesAvailableEvent:
- break;
- case WAIT_OBJECT_0 + kInterruptEvent:
- return_info.Set(0, eConnectionStatusInterrupted, 0);
- goto finish;
- case WAIT_TIMEOUT:
- return_info.Set(0, eConnectionStatusTimedOut, 0);
- goto finish;
- case WAIT_FAILED:
- return_info.Set(0, eConnectionStatusError, ::GetLastError());
- goto finish;
- }
- }
- // The data is ready. Figure out how much was read and return;
- if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE))
- {
- DWORD result_error = ::GetLastError();
- // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a blocking read.
- // This triggers a call to CancelIoEx, which causes the operation to complete and the
- // result to be ERROR_OPERATION_ABORTED.
- if (result_error == ERROR_HANDLE_EOF || result_error == ERROR_OPERATION_ABORTED || result_error == ERROR_BROKEN_PIPE)
- return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
- else
- return_info.Set(bytes_read, eConnectionStatusError, result_error);
- }
- else if (bytes_read == 0)
- return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
- else
- return_info.Set(bytes_read, eConnectionStatusSuccess, 0);
+ if (error_ptr)
+ error_ptr->Clear();
- goto finish;
- }
- else if (::GetLastError() == ERROR_BROKEN_PIPE)
- {
- // The write end of a pipe was closed. This is equivalent to EOF.
- return_info.Set(0, eConnectionStatusEndOfFile, 0);
- }
- else
- {
- // An unknown error occurred. Fail out.
- return_info.Set(0, eConnectionStatusError, ::GetLastError());
- }
+ if (!IsConnected()) {
+ return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
goto finish;
+ }
-finish:
- status = return_info.GetStatus();
- if (error_ptr)
- *error_ptr = return_info.GetError();
+ m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent];
- // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here so that any
- // subsequent operations don't immediately see bytes available.
- ResetEvent(m_event_handles[kBytesAvailableEvent]);
-
- IncrementFilePointer(return_info.GetBytes());
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- {
- log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR ", dst = %" PRIxPTR ", dst_len = %" PRIu64
- ") => %" PRIu64 ", error = %s",
- this, m_file, dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(return_info.GetBytes()),
- return_info.GetError().AsCString());
+ result = ::ReadFile(m_file, dst, dst_len, NULL, &m_overlapped);
+ if (result || ::GetLastError() == ERROR_IO_PENDING) {
+ if (!result) {
+ // The expected return path. The operation is pending. Wait for the
+ // operation to complete
+ // or be interrupted.
+ TimeValue time_value;
+ time_value.OffsetWithMicroSeconds(timeout_usec);
+ DWORD milliseconds = time_value.milliseconds();
+ DWORD wait_result =
+ ::WaitForMultipleObjects(llvm::array_lengthof(m_event_handles),
+ m_event_handles, FALSE, milliseconds);
+ // All of the events are manual reset events, so make sure we reset them
+ // to non-signalled.
+ switch (wait_result) {
+ case WAIT_OBJECT_0 + kBytesAvailableEvent:
+ break;
+ case WAIT_OBJECT_0 + kInterruptEvent:
+ return_info.Set(0, eConnectionStatusInterrupted, 0);
+ goto finish;
+ case WAIT_TIMEOUT:
+ return_info.Set(0, eConnectionStatusTimedOut, 0);
+ goto finish;
+ case WAIT_FAILED:
+ return_info.Set(0, eConnectionStatusError, ::GetLastError());
+ goto finish;
+ }
}
+ // The data is ready. Figure out how much was read and return;
+ if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_read, FALSE)) {
+ DWORD result_error = ::GetLastError();
+ // ERROR_OPERATION_ABORTED occurs when someone calls Disconnect() during a
+ // blocking read.
+ // This triggers a call to CancelIoEx, which causes the operation to
+ // complete and the
+ // result to be ERROR_OPERATION_ABORTED.
+ if (result_error == ERROR_HANDLE_EOF ||
+ result_error == ERROR_OPERATION_ABORTED ||
+ result_error == ERROR_BROKEN_PIPE)
+ return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
+ else
+ return_info.Set(bytes_read, eConnectionStatusError, result_error);
+ } else if (bytes_read == 0)
+ return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
+ else
+ return_info.Set(bytes_read, eConnectionStatusSuccess, 0);
- return return_info.GetBytes();
-}
-
-size_t
-ConnectionGenericFile::Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr)
-{
- ReturnInfo return_info;
- DWORD bytes_written = 0;
- BOOL result = 0;
-
- if (error_ptr)
- error_ptr->Clear();
+ goto finish;
+ } else if (::GetLastError() == ERROR_BROKEN_PIPE) {
+ // The write end of a pipe was closed. This is equivalent to EOF.
+ return_info.Set(0, eConnectionStatusEndOfFile, 0);
+ } else {
+ // An unknown error occurred. Fail out.
+ return_info.Set(0, eConnectionStatusError, ::GetLastError());
+ }
+ goto finish;
- if (!IsConnected())
- {
- return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
- goto finish;
- }
+finish:
+ status = return_info.GetStatus();
+ if (error_ptr)
+ *error_ptr = return_info.GetError();
+
+ // kBytesAvailableEvent is a manual reset event. Make sure it gets reset here
+ // so that any
+ // subsequent operations don't immediately see bytes available.
+ ResetEvent(m_event_handles[kBytesAvailableEvent]);
+
+ IncrementFilePointer(return_info.GetBytes());
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log) {
+ log->Printf("%" PRIxPTR " ConnectionGenericFile::Read() handle = %" PRIxPTR
+ ", dst = %" PRIxPTR ", dst_len = %" PRIu64 ") => %" PRIu64
+ ", error = %s",
+ this, m_file, dst, static_cast<uint64_t>(dst_len),
+ static_cast<uint64_t>(return_info.GetBytes()),
+ return_info.GetError().AsCString());
+ }
+
+ return return_info.GetBytes();
+}
+
+size_t ConnectionGenericFile::Write(const void *src, size_t src_len,
+ lldb::ConnectionStatus &status,
+ Error *error_ptr) {
+ ReturnInfo return_info;
+ DWORD bytes_written = 0;
+ BOOL result = 0;
- m_overlapped.hEvent = NULL;
+ if (error_ptr)
+ error_ptr->Clear();
- // Writes are not interruptible like reads are, so just block until it's done.
- result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped);
- if (!result && ::GetLastError() != ERROR_IO_PENDING)
- {
- return_info.Set(0, eConnectionStatusError, ::GetLastError());
- goto finish;
- }
+ if (!IsConnected()) {
+ return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
+ goto finish;
+ }
- if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE))
- {
- return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError());
- goto finish;
- }
+ m_overlapped.hEvent = NULL;
- return_info.Set(bytes_written, eConnectionStatusSuccess, 0);
+ // Writes are not interruptible like reads are, so just block until it's done.
+ result = ::WriteFile(m_file, src, src_len, NULL, &m_overlapped);
+ if (!result && ::GetLastError() != ERROR_IO_PENDING) {
+ return_info.Set(0, eConnectionStatusError, ::GetLastError());
goto finish;
+ }
-finish:
- status = return_info.GetStatus();
- if (error_ptr)
- *error_ptr = return_info.GetError();
+ if (!::GetOverlappedResult(m_file, &m_overlapped, &bytes_written, TRUE)) {
+ return_info.Set(bytes_written, eConnectionStatusError, ::GetLastError());
+ goto finish;
+ }
- IncrementFilePointer(return_info.GetBytes());
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
- if (log)
- {
- log->Printf("%" PRIxPTR " ConnectionGenericFile::Write() handle = %" PRIxPTR ", src = %" PRIxPTR ", src_len = %" PRIu64
- ") => %" PRIu64 ", error = %s",
- this, m_file, src, static_cast<uint64_t>(src_len), static_cast<uint64_t>(return_info.GetBytes()),
- return_info.GetError().AsCString());
- }
- return return_info.GetBytes();
-}
+ return_info.Set(bytes_written, eConnectionStatusSuccess, 0);
+ goto finish;
-std::string
-ConnectionGenericFile::GetURI()
-{
- return m_uri;
-}
-
-bool
-ConnectionGenericFile::InterruptRead()
-{
- return ::SetEvent(m_event_handles[kInterruptEvent]);
-}
-
-void
-ConnectionGenericFile::IncrementFilePointer(DWORD amount)
-{
- LARGE_INTEGER old_pos;
- old_pos.HighPart = m_overlapped.OffsetHigh;
- old_pos.LowPart = m_overlapped.Offset;
- old_pos.QuadPart += amount;
- m_overlapped.Offset = old_pos.LowPart;
- m_overlapped.OffsetHigh = old_pos.HighPart;
+finish:
+ status = return_info.GetStatus();
+ if (error_ptr)
+ *error_ptr = return_info.GetError();
+
+ IncrementFilePointer(return_info.GetBytes());
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
+ if (log) {
+ log->Printf("%" PRIxPTR
+ " ConnectionGenericFile::Write() handle = %" PRIxPTR
+ ", src = %" PRIxPTR ", src_len = %" PRIu64 ") => %" PRIu64
+ ", error = %s",
+ this, m_file, src, static_cast<uint64_t>(src_len),
+ static_cast<uint64_t>(return_info.GetBytes()),
+ return_info.GetError().AsCString());
+ }
+ return return_info.GetBytes();
+}
+
+std::string ConnectionGenericFile::GetURI() { return m_uri; }
+
+bool ConnectionGenericFile::InterruptRead() {
+ return ::SetEvent(m_event_handles[kInterruptEvent]);
+}
+
+void ConnectionGenericFile::IncrementFilePointer(DWORD amount) {
+ LARGE_INTEGER old_pos;
+ old_pos.HighPart = m_overlapped.OffsetHigh;
+ old_pos.LowPart = m_overlapped.Offset;
+ old_pos.QuadPart += amount;
+ m_overlapped.Offset = old_pos.LowPart;
+ m_overlapped.OffsetHigh = old_pos.HighPart;
}
Modified: lldb/trunk/source/Host/windows/EditLineWin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/EditLineWin.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/EditLineWin.cpp (original)
+++ lldb/trunk/source/Host/windows/EditLineWin.cpp Tue Sep 6 15:57:50 2016
@@ -8,428 +8,345 @@
//===----------------------------------------------------------------------===//
// this file is only relevant for Visual C++
-#if defined( _WIN32 )
+#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include "lldb/Host/windows/editlinewin.h"
-#include <vector>
#include <assert.h>
+#include <vector>
// edit line EL_ADDFN function pointer type
-typedef unsigned char(*el_addfn_func)(EditLine *e, int ch);
-typedef const char* (*el_prompt_func)(EditLine *);
+typedef unsigned char (*el_addfn_func)(EditLine *e, int ch);
+typedef const char *(*el_prompt_func)(EditLine *);
// edit line wrapper binding container
-struct el_binding
-{
- //
- const char *name;
- const char *help;
- // function pointer to callback routine
- el_addfn_func func;
- // ascii key this function is bound to
- const char *key;
+struct el_binding {
+ //
+ const char *name;
+ const char *help;
+ // function pointer to callback routine
+ el_addfn_func func;
+ // ascii key this function is bound to
+ const char *key;
};
// stored key bindings
-static std::vector<el_binding*> _bindings;
+static std::vector<el_binding *> _bindings;
-//TODO: this should in fact be related to the exact edit line context we create
+// TODO: this should in fact be related to the exact edit line context we create
static void *clientData = NULL;
// store the current prompt string
// default to what we expect to receive anyway
static const char *_prompt = "(lldb) ";
-#if !defined( _WIP_INPUT_METHOD )
+#if !defined(_WIP_INPUT_METHOD)
-static char *
-el_get_s (char *buffer, int chars)
-{
- return gets_s(buffer, chars);
-}
+static char *el_get_s(char *buffer, int chars) { return gets_s(buffer, chars); }
#else
-static void
-con_output (char _in)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get the cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // output this char
- WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written );
- // advance cursor position
- info.dwCursorPosition.X++;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
-}
-
-static void
-con_backspace (void)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // nudge cursor backwards
- info.dwCursorPosition.X--;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
- // blank out the last character
- WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written );
-}
-
-static void
-con_return (void)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // move onto the new line
- info.dwCursorPosition.X = 0;
- info.dwCursorPosition.Y++;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
-}
-
-static bool
-runBind (char _key)
-{
- for ( int i=0; i<_bindings.size(); i++ )
- {
- el_binding *bind = _bindings[i];
- if ( bind->key[0] == _key )
- {
- bind->func( (EditLine*) -1, _key );
- return true;
- }
+static void con_output(char _in) {
+ HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD written = 0;
+ // get the cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo(hout, &info);
+ // output this char
+ WriteConsoleOutputCharacterA(hout, &_in, 1, info.dwCursorPosition, &written);
+ // advance cursor position
+ info.dwCursorPosition.X++;
+ SetConsoleCursorPosition(hout, info.dwCursorPosition);
+}
+
+static void con_backspace(void) {
+ HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo(hout, &info);
+ // nudge cursor backwards
+ info.dwCursorPosition.X--;
+ SetConsoleCursorPosition(hout, info.dwCursorPosition);
+ // blank out the last character
+ WriteConsoleOutputCharacterA(hout, " ", 1, info.dwCursorPosition, &written);
+}
+
+static void con_return(void) {
+ HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo(hout, &info);
+ // move onto the new line
+ info.dwCursorPosition.X = 0;
+ info.dwCursorPosition.Y++;
+ SetConsoleCursorPosition(hout, info.dwCursorPosition);
+}
+
+static bool runBind(char _key) {
+ for (int i = 0; i < _bindings.size(); i++) {
+ el_binding *bind = _bindings[i];
+ if (bind->key[0] == _key) {
+ bind->func((EditLine *)-1, _key);
+ return true;
}
- return false;
+ }
+ return false;
}
// replacement get_s which is EL_BIND aware
-static char *
-el_get_s (char *buffer, int chars)
-{
+static char *el_get_s(char *buffer, int chars) {
+ //
+ char *head = buffer;
+ //
+ for (;; Sleep(10)) {
//
- char *head = buffer;
+ INPUT_RECORD _record;
//
- for ( ;; Sleep( 10 ) )
- {
- //
- INPUT_RECORD _record;
- //
- DWORD _read = 0;
- if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE )
- break;
- // if we didn't read a key
- if ( _read == 0 )
- continue;
- // only interested in key events
- if ( _record.EventType != KEY_EVENT )
- continue;
- // is the key down
- if (! _record.Event.KeyEvent.bKeyDown )
- continue;
- // read the ascii key character
- char _key = _record.Event.KeyEvent.uChar.AsciiChar;
- // non ascii conformant key press
- if ( _key == 0 )
- {
- // check the scan code
- // if VK_UP scroll back through history
- // if VK_DOWN scroll forward through history
- continue;
- }
- // try to execute any bind this key may have
- if ( runBind( _key ) )
- continue;
- // if we read a return key
- if ( _key == '\n' || _key == '\r' )
- {
- con_return( );
- break;
- }
- // key is backspace
- if ( _key == 0x8 )
- {
- // avoid deleting past beginning
- if ( head > buffer )
- {
- con_backspace( );
- head--;
- }
- continue;
- }
-
- // add this key to the input buffer
- if ( (head-buffer) < (chars-1) )
- {
- con_output( _key );
- *(head++) = _key;
- }
+ DWORD _read = 0;
+ if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE), &_record, 1,
+ &_read) == FALSE)
+ break;
+ // if we didn't read a key
+ if (_read == 0)
+ continue;
+ // only interested in key events
+ if (_record.EventType != KEY_EVENT)
+ continue;
+ // is the key down
+ if (!_record.Event.KeyEvent.bKeyDown)
+ continue;
+ // read the ascii key character
+ char _key = _record.Event.KeyEvent.uChar.AsciiChar;
+ // non ascii conformant key press
+ if (_key == 0) {
+ // check the scan code
+ // if VK_UP scroll back through history
+ // if VK_DOWN scroll forward through history
+ continue;
}
- // insert end of line character
- *head = '\0';
-
- return buffer;
-}
-#endif
-
-// edit line initialize
-EditLine *
-el_init (const char *, FILE *, FILE *, FILE *)
-{
- //
- SetConsoleTitleA( "lldb" );
- // return dummy handle
- return (EditLine*) -1;
-}
-
-const char *
-el_gets (EditLine *el, int *length)
-{
- // print the prompt if we have one
- if ( _prompt != NULL )
- printf("%s", _prompt);
- // create a buffer for the user input
- char *buffer = new char[ MAX_PATH ];
- // try to get user input string
- if ( el_get_s( buffer, MAX_PATH ) )
- {
- // get the string length in 'length'
- while ( buffer[ *length ] != '\0' )
- (*length)++;
- // return the input buffer
- // remember that this memory has the be free'd somewhere
- return buffer;
+ // try to execute any bind this key may have
+ if (runBind(_key))
+ continue;
+ // if we read a return key
+ if (_key == '\n' || _key == '\r') {
+ con_return();
+ break;
}
- else
- {
- // on error
- delete [] buffer;
- return NULL;
+ // key is backspace
+ if (_key == 0x8) {
+ // avoid deleting past beginning
+ if (head > buffer) {
+ con_backspace();
+ head--;
+ }
+ continue;
}
-}
-
-int
-el_set (EditLine *el, int code, ...)
-{
- va_list vl;
- va_start(vl, code);
- //
- switch ( code )
- {
- // edit line set prompt message
- case ( EL_PROMPT ):
- {
- // EL_PROMPT, char *(*f)( EditLine *)
- // define a prompt printing function as 'f', which is to return a string that
- // contains the prompt.
-
- // get the function pointer from the arg list
- void *func_vp = (void*)va_arg(vl, el_prompt_func);
- // cast to suitable prototype
- el_prompt_func func_fp = (el_prompt_func)func_vp;
- // call to get the prompt as a string
- _prompt = func_fp( el );
- }
- break;
- case (EL_PROMPT_ESC) :
- {
- // EL_PROMPT, char *(*f)( EditLine *)
- // define a prompt printing function as 'f', which is to return a string that
- // contains the prompt.
-
- // get the function pointer from the arg list
- void *func_vp = (void*)va_arg(vl, el_prompt_func);
- va_arg(vl, int);
- // call to get the prompt as a string
- el_prompt_func func_fp = (el_prompt_func)func_vp;
- _prompt = func_fp(el);
- }
- break;
+ // add this key to the input buffer
+ if ((head - buffer) < (chars - 1)) {
+ con_output(_key);
+ *(head++) = _key;
+ }
+ }
+ // insert end of line character
+ *head = '\0';
- case ( EL_EDITOR ):
- {
- // EL_EDITOR, const char *mode
- // set editing mode to "emacs" or "vi"
- }
- break;
- case ( EL_HIST ):
- {
- // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr
- // defines which history function to use, which is usually history(). Ptr should be the
- // value returned by history_init().
- }
- break;
- case ( EL_ADDFN ):
- {
- // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch)
- // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is
- // entered. 'help' is a description of 'name'. at invocation time, 'ch' is the key which caused the invocation. the
- // return value of 'func()' should be one of:
- // CC_NORM add a normal character
- // CC_NEWLINE end of line was entered
- // CC_EOF EOF was entered
- // CC_ARGHACK expecting further command input as arguments, do nothing visually.
- // CC_REFRESH refresh display.
- // CC_REFRESH_BEEP refresh display and beep.
- // CC_CURSOR cursor moved so update and perform CC_REFRESH
- // CC_REDISPLAY redisplay entire input line. this is useful if a key binding outputs extra information.
- // CC_ERROR an error occurred. beep and flush tty.
- // CC_FATAL fatal error, reset tty to known state.
-
- el_binding *binding = new el_binding;
- binding->name = va_arg( vl, const char *);
- binding->help = va_arg( vl, const char *);
- binding->func = va_arg( vl, el_addfn_func );
- binding->key = 0;
- // add this to the bindings list
- _bindings.push_back( binding );
- }
- break;
- case ( EL_BIND ):
- {
- // EL_BIND, const char *, ..., NULL
- // perform the BIND built-in command. Refer to editrc(5) for more information.
-
- const char *name = va_arg( vl, const char* );
-
- for ( int i=0; i<_bindings.size(); i++ )
- {
- el_binding *bind = _bindings[i];
- if ( strcmp( bind->name, name ) == 0 )
- {
- bind->key = va_arg( vl, const char * );
- break;
- }
- }
+ return buffer;
+}
+#endif
- }
- break;
- case ( EL_CLIENTDATA ):
- {
- clientData = va_arg(vl, void*);
- }
+// edit line initialize
+EditLine *el_init(const char *, FILE *, FILE *, FILE *) {
+ //
+ SetConsoleTitleA("lldb");
+ // return dummy handle
+ return (EditLine *)-1;
+}
+
+const char *el_gets(EditLine *el, int *length) {
+ // print the prompt if we have one
+ if (_prompt != NULL)
+ printf("%s", _prompt);
+ // create a buffer for the user input
+ char *buffer = new char[MAX_PATH];
+ // try to get user input string
+ if (el_get_s(buffer, MAX_PATH)) {
+ // get the string length in 'length'
+ while (buffer[*length] != '\0')
+ (*length)++;
+ // return the input buffer
+ // remember that this memory has the be free'd somewhere
+ return buffer;
+ } else {
+ // on error
+ delete[] buffer;
+ return NULL;
+ }
+}
+
+int el_set(EditLine *el, int code, ...) {
+ va_list vl;
+ va_start(vl, code);
+ //
+ switch (code) {
+ // edit line set prompt message
+ case (EL_PROMPT): {
+ // EL_PROMPT, char *(*f)( EditLine *)
+ // define a prompt printing function as 'f', which is to return a
+ // string that
+ // contains the prompt.
+
+ // get the function pointer from the arg list
+ void *func_vp = (void *)va_arg(vl, el_prompt_func);
+ // cast to suitable prototype
+ el_prompt_func func_fp = (el_prompt_func)func_vp;
+ // call to get the prompt as a string
+ _prompt = func_fp(el);
+ } break;
+
+ case (EL_PROMPT_ESC): {
+ // EL_PROMPT, char *(*f)( EditLine *)
+ // define a prompt printing function as 'f', which is to return a
+ // string that
+ // contains the prompt.
+
+ // get the function pointer from the arg list
+ void *func_vp = (void *)va_arg(vl, el_prompt_func);
+ va_arg(vl, int);
+ // call to get the prompt as a string
+ el_prompt_func func_fp = (el_prompt_func)func_vp;
+ _prompt = func_fp(el);
+ } break;
+
+ case (EL_EDITOR): {
+ // EL_EDITOR, const char *mode
+ // set editing mode to "emacs" or "vi"
+ } break;
+ case (EL_HIST): {
+ // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr
+ // defines which history function to use, which is usually history().
+ // Ptr should be the
+ // value returned by history_init().
+ } break;
+ case (EL_ADDFN): {
+ // EL_ADDFN, const char *name, const char *help, unsigned char
+ // (*func)(EditLine *e, int ch)
+ // add a user defined function, func), referred to as 'name' which is
+ // invoked when a key which is bound to 'name' is
+ // entered. 'help' is a description of 'name'. at invocation time, 'ch'
+ // is the key which caused the invocation. the
+ // return value of 'func()' should be one of:
+ // CC_NORM add a normal character
+ // CC_NEWLINE end of line was entered
+ // CC_EOF EOF was entered
+ // CC_ARGHACK expecting further command input as arguments, do
+ // nothing visually.
+ // CC_REFRESH refresh display.
+ // CC_REFRESH_BEEP refresh display and beep.
+ // CC_CURSOR cursor moved so update and perform CC_REFRESH
+ // CC_REDISPLAY redisplay entire input line. this is useful
+ // if a key binding outputs extra information.
+ // CC_ERROR an error occurred. beep and flush tty.
+ // CC_FATAL fatal error, reset tty to known state.
+
+ el_binding *binding = new el_binding;
+ binding->name = va_arg(vl, const char *);
+ binding->help = va_arg(vl, const char *);
+ binding->func = va_arg(vl, el_addfn_func);
+ binding->key = 0;
+ // add this to the bindings list
+ _bindings.push_back(binding);
+ } break;
+ case (EL_BIND): {
+ // EL_BIND, const char *, ..., NULL
+ // perform the BIND built-in command. Refer to editrc(5) for more
+ // information.
+
+ const char *name = va_arg(vl, const char *);
+
+ for (int i = 0; i < _bindings.size(); i++) {
+ el_binding *bind = _bindings[i];
+ if (strcmp(bind->name, name) == 0) {
+ bind->key = va_arg(vl, const char *);
break;
+ }
}
- return 0;
-}
-void
-el_end (EditLine *el)
-{
- //assert( !"Not implemented!" );
+ } break;
+ case (EL_CLIENTDATA): {
+ clientData = va_arg(vl, void *);
+ } break;
+ }
+ return 0;
}
-void
-el_reset (EditLine *)
-{
- assert( !"Not implemented!" );
+void el_end(EditLine *el) {
+ // assert( !"Not implemented!" );
}
-int
-el_getc (EditLine *, char *)
-{
- assert( !"Not implemented!" );
- return 0;
-}
+void el_reset(EditLine *) { assert(!"Not implemented!"); }
-void
-el_push (EditLine *, const char *)
-{
+int el_getc(EditLine *, char *) {
+ assert(!"Not implemented!");
+ return 0;
}
-void
-el_beep (EditLine *)
-{
- Beep( 1000, 500 );
-}
+void el_push(EditLine *, const char *) {}
-int
-el_parse (EditLine *, int, const char **)
-{
- assert( !"Not implemented!" );
- return 0;
+void el_beep(EditLine *) { Beep(1000, 500); }
+
+int el_parse(EditLine *, int, const char **) {
+ assert(!"Not implemented!");
+ return 0;
}
-int
-el_get (EditLine *el, int code, ...)
-{
- va_list vl;
- va_start( vl, code );
+int el_get(EditLine *el, int code, ...) {
+ va_list vl;
+ va_start(vl, code);
- switch ( code )
- {
- case ( EL_CLIENTDATA ):
- {
- void **dout = va_arg( vl, void** );
- *dout = clientData;
- }
- break;
- default:
- assert( !"Not implemented!" );
- }
- return 0;
+ switch (code) {
+ case (EL_CLIENTDATA): {
+ void **dout = va_arg(vl, void **);
+ *dout = clientData;
+ } break;
+ default:
+ assert(!"Not implemented!");
+ }
+ return 0;
}
-int
-el_source (EditLine *el, const char *file)
-{
- // init edit line by reading the contents of 'file'
- // nothing to do here on windows...
- return 0;
+int el_source(EditLine *el, const char *file) {
+ // init edit line by reading the contents of 'file'
+ // nothing to do here on windows...
+ return 0;
}
-void
-el_resize (EditLine *)
-{
- assert( !"Not implemented!" );
-}
+void el_resize(EditLine *) { assert(!"Not implemented!"); }
-const LineInfo *
-el_line (EditLine *el)
-{
- return 0;
-}
+const LineInfo *el_line(EditLine *el) { return 0; }
-int
-el_insertstr (EditLine *, const char *)
-{
-// assert( !"Not implemented!" );
- return 0;
+int el_insertstr(EditLine *, const char *) {
+ // assert( !"Not implemented!" );
+ return 0;
}
-void
-el_deletestr (EditLine *, int)
-{
- assert( !"Not implemented!" );
-}
+void el_deletestr(EditLine *, int) { assert(!"Not implemented!"); }
-History *
-history_init (void)
-{
- // return dummy handle
- return (History*) -1;
+History *history_init(void) {
+ // return dummy handle
+ return (History *)-1;
}
-void
-history_end (History *)
-{
-// assert( !"Not implemented!" );
+void history_end(History *) {
+ // assert( !"Not implemented!" );
}
-int
-history (History *, HistEvent *, int op, ...)
-{
- // perform operation 'op' on the history list with
- // optional arguments as needed by the operation.
- return 0;
+int history(History *, HistEvent *, int op, ...) {
+ // perform operation 'op' on the history list with
+ // optional arguments as needed by the operation.
+ return 0;
}
#endif
Modified: lldb/trunk/source/Host/windows/FileSystem.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/FileSystem.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/FileSystem.cpp (original)
+++ lldb/trunk/source/Host/windows/FileSystem.cpp Tue Sep 6 15:57:50 2016
@@ -21,273 +21,241 @@
using namespace lldb_private;
-const char *
-FileSystem::DEV_NULL = "nul";
+const char *FileSystem::DEV_NULL = "nul";
-const char *FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding";
+const char *FileSystem::PATH_CONVERSION_ERROR =
+ "Error converting path between UTF-8 and native encoding";
-FileSpec::PathSyntax
-FileSystem::GetNativePathSyntax()
-{
- return FileSpec::ePathSyntaxWindows;
-}
-
-Error
-FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions)
-{
- // On Win32, the mode parameter is ignored, as Windows files and directories support a
- // different permission model than POSIX.
- Error error;
- const auto err_code = llvm::sys::fs::create_directories(file_spec.GetPath(), true);
- if (err_code)
- {
- error.SetErrorString(err_code.message().c_str());
- }
-
- return error;
-}
-
-Error
-FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
-{
- Error error;
- std::wstring path_buffer;
- if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer))
- {
- error.SetErrorString(PATH_CONVERSION_ERROR);
- return error;
- }
- if (!recurse)
- {
- BOOL result = ::RemoveDirectoryW(path_buffer.c_str());
- if (!result)
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- }
- else
- {
- // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
- // indicate the end of the list. The first null terminator is there only in the backing
- // store but not the actual vector contents, and so we need to push twice.
- path_buffer.push_back(0);
- path_buffer.push_back(0);
-
- SHFILEOPSTRUCTW shfos = {0};
- shfos.wFunc = FO_DELETE;
- shfos.pFrom = (LPCWSTR)path_buffer.data();
- shfos.fFlags = FOF_NO_UI;
-
- int result = ::SHFileOperationW(&shfos);
- // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
- if (result != 0)
- error.SetErrorStringWithFormat("SHFileOperation failed");
- }
- return error;
-}
-
-Error
-FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
-{
- Error error;
- // Beware that Windows's permission model is different from Unix's, and it's
- // not clear if this API is supposed to check ACLs. To match the caller's
- // expectations as closely as possible, we'll use Microsoft's _stat, which
- // attempts to emulate POSIX stat. This should be good enough for basic
- // checks like FileSpec::Readable.
- struct _stat file_stats;
- if (::_stat(file_spec.GetCString(), &file_stats) == 0)
- {
- // The owner permission bits in "st_mode" currently match the definitions
- // for the owner file mode bits.
- file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC);
- }
- else
- {
- error.SetErrorToErrno();
- }
-
- return error;
-}
-
-Error
-FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
-{
- Error error;
- error.SetErrorStringWithFormat("%s is not supported on this host", LLVM_PRETTY_FUNCTION);
- return error;
-}
-
-lldb::user_id_t
-FileSystem::GetFileSize(const FileSpec &file_spec)
-{
- return file_spec.GetByteSize();
-}
-
-bool
-FileSystem::GetFileExists(const FileSpec &file_spec)
-{
- return file_spec.Exists();
-}
-
-Error
-FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
-{
- Error error;
- std::wstring wsrc, wdst;
- if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
- error.SetErrorString(PATH_CONVERSION_ERROR);
- else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr))
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
+FileSpec::PathSyntax FileSystem::GetNativePathSyntax() {
+ return FileSpec::ePathSyntaxWindows;
}
-int
-FileSystem::GetHardlinkCount(const FileSpec &file_spec)
-{
- std::wstring path;
- if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
- return -1;
-
- HANDLE file_handle = ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, nullptr);
-
- if (file_handle == INVALID_HANDLE_VALUE)
- return -1;
-
- AutoHandle auto_file_handle(file_handle);
- BY_HANDLE_FILE_INFORMATION file_info;
- if (::GetFileInformationByHandle(file_handle, &file_info))
- return file_info.nNumberOfLinks;
-
- return -1;
-}
-
-Error
-FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
-{
- Error error;
- std::wstring wsrc, wdst;
- if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
- error.SetErrorString(PATH_CONVERSION_ERROR);
- if (error.Fail())
- return error;
- DWORD attrib = ::GetFileAttributesW(wdst.c_str());
- if (attrib == INVALID_FILE_ATTRIBUTES)
- {
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
- }
- bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
- DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
- BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag);
- if (!result)
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
-}
-
-Error
-FileSystem::Unlink(const FileSpec &file_spec)
-{
- Error error;
- std::wstring path;
- if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
- {
- error.SetErrorString(PATH_CONVERSION_ERROR);
- return error;
- }
- BOOL result = ::DeleteFileW(path.c_str());
+Error FileSystem::MakeDirectory(const FileSpec &file_spec,
+ uint32_t file_permissions) {
+ // On Win32, the mode parameter is ignored, as Windows files and directories
+ // support a
+ // different permission model than POSIX.
+ Error error;
+ const auto err_code =
+ llvm::sys::fs::create_directories(file_spec.GetPath(), true);
+ if (err_code) {
+ error.SetErrorString(err_code.message().c_str());
+ }
+
+ return error;
+}
+
+Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) {
+ Error error;
+ std::wstring path_buffer;
+ if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) {
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ return error;
+ }
+ if (!recurse) {
+ BOOL result = ::RemoveDirectoryW(path_buffer.c_str());
if (!result)
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
-}
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ } else {
+ // SHFileOperation() accepts a list of paths, and so must be
+ // double-null-terminated to
+ // indicate the end of the list. The first null terminator is there only in
+ // the backing
+ // store but not the actual vector contents, and so we need to push twice.
+ path_buffer.push_back(0);
+ path_buffer.push_back(0);
+
+ SHFILEOPSTRUCTW shfos = {0};
+ shfos.wFunc = FO_DELETE;
+ shfos.pFrom = (LPCWSTR)path_buffer.data();
+ shfos.fFlags = FOF_NO_UI;
+
+ int result = ::SHFileOperationW(&shfos);
+ // TODO(zturner): Correctly handle the intricacies of SHFileOperation return
+ // values.
+ if (result != 0)
+ error.SetErrorStringWithFormat("SHFileOperation failed");
+ }
+ return error;
+}
+
+Error FileSystem::GetFilePermissions(const FileSpec &file_spec,
+ uint32_t &file_permissions) {
+ Error error;
+ // Beware that Windows's permission model is different from Unix's, and it's
+ // not clear if this API is supposed to check ACLs. To match the caller's
+ // expectations as closely as possible, we'll use Microsoft's _stat, which
+ // attempts to emulate POSIX stat. This should be good enough for basic
+ // checks like FileSpec::Readable.
+ struct _stat file_stats;
+ if (::_stat(file_spec.GetCString(), &file_stats) == 0) {
+ // The owner permission bits in "st_mode" currently match the definitions
+ // for the owner file mode bits.
+ file_permissions = file_stats.st_mode & (_S_IREAD | _S_IWRITE | _S_IEXEC);
+ } else {
+ error.SetErrorToErrno();
+ }
+
+ return error;
+}
+
+Error FileSystem::SetFilePermissions(const FileSpec &file_spec,
+ uint32_t file_permissions) {
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host",
+ LLVM_PRETTY_FUNCTION);
+ return error;
+}
+
+lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) {
+ return file_spec.GetByteSize();
+}
+
+bool FileSystem::GetFileExists(const FileSpec &file_spec) {
+ return file_spec.Exists();
+}
+
+Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) {
+ Error error;
+ std::wstring wsrc, wdst;
+ if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) ||
+ !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr))
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ return error;
+}
+
+int FileSystem::GetHardlinkCount(const FileSpec &file_spec) {
+ std::wstring path;
+ if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
+ return -1;
-Error
-FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
-{
- Error error;
- std::wstring wsrc;
- if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc))
- {
- error.SetErrorString(PATH_CONVERSION_ERROR);
- return error;
- }
-
- HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT, NULL);
- if (h == INVALID_HANDLE_VALUE)
- {
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
- }
-
- std::vector<wchar_t> buf(PATH_MAX + 1);
- // Subtract 1 from the path length since this function does not add a null terminator.
- DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
- std::string path;
- if (result == 0)
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- else if (!llvm::convertWideToUTF8(buf.data(), path))
- error.SetErrorString(PATH_CONVERSION_ERROR);
- else
- dst.SetFile(path, false);
+ HANDLE file_handle =
+ ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(h);
- return error;
-}
+ if (file_handle == INVALID_HANDLE_VALUE)
+ return -1;
-Error
-FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
-{
- return Error("ResolveSymbolicLink() isn't implemented on Windows");
-}
-
-bool
-FileSystem::IsLocal(const FileSpec &spec)
-{
- if (spec)
- {
- // TODO: return true if the file is on a locally mounted file system
- return true;
- }
-
- return false;
-}
-
-FILE *
-FileSystem::Fopen(const char *path, const char *mode)
-{
- std::wstring wpath, wmode;
- if (!llvm::ConvertUTF8toWide(path, wpath))
- return nullptr;
- if (!llvm::ConvertUTF8toWide(mode, wmode))
- return nullptr;
- FILE *file;
- if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0)
- return nullptr;
- return file;
-}
-
-int
-FileSystem::Stat(const char *path, struct stat *stats)
-{
- std::wstring wpath;
- if (!llvm::ConvertUTF8toWide(path, wpath))
- {
- errno = EINVAL;
- return -EINVAL;
- }
- int stat_result;
+ AutoHandle auto_file_handle(file_handle);
+ BY_HANDLE_FILE_INFORMATION file_info;
+ if (::GetFileInformationByHandle(file_handle, &file_info))
+ return file_info.nNumberOfLinks;
+
+ return -1;
+}
+
+Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {
+ Error error;
+ std::wstring wsrc, wdst;
+ if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) ||
+ !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ if (error.Fail())
+ return error;
+ DWORD attrib = ::GetFileAttributesW(wdst.c_str());
+ if (attrib == INVALID_FILE_ATTRIBUTES) {
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ return error;
+ }
+ bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
+ DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
+ BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag);
+ if (!result)
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ return error;
+}
+
+Error FileSystem::Unlink(const FileSpec &file_spec) {
+ Error error;
+ std::wstring path;
+ if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) {
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ return error;
+ }
+ BOOL result = ::DeleteFileW(path.c_str());
+ if (!result)
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ return error;
+}
+
+Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
+ Error error;
+ std::wstring wsrc;
+ if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) {
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ return error;
+ }
+
+ HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ return error;
+ }
+
+ std::vector<wchar_t> buf(PATH_MAX + 1);
+ // Subtract 1 from the path length since this function does not add a null
+ // terminator.
+ DWORD result = ::GetFinalPathNameByHandleW(
+ h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+ std::string path;
+ if (result == 0)
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ else if (!llvm::convertWideToUTF8(buf.data(), path))
+ error.SetErrorString(PATH_CONVERSION_ERROR);
+ else
+ dst.SetFile(path, false);
+
+ ::CloseHandle(h);
+ return error;
+}
+
+Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {
+ return Error("ResolveSymbolicLink() isn't implemented on Windows");
+}
+
+bool FileSystem::IsLocal(const FileSpec &spec) {
+ if (spec) {
+ // TODO: return true if the file is on a locally mounted file system
+ return true;
+ }
+
+ return false;
+}
+
+FILE *FileSystem::Fopen(const char *path, const char *mode) {
+ std::wstring wpath, wmode;
+ if (!llvm::ConvertUTF8toWide(path, wpath))
+ return nullptr;
+ if (!llvm::ConvertUTF8toWide(mode, wmode))
+ return nullptr;
+ FILE *file;
+ if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0)
+ return nullptr;
+ return file;
+}
+
+int FileSystem::Stat(const char *path, struct stat *stats) {
+ std::wstring wpath;
+ if (!llvm::ConvertUTF8toWide(path, wpath)) {
+ errno = EINVAL;
+ return -EINVAL;
+ }
+ int stat_result;
#ifdef _USE_32BIT_TIME_T
- struct _stat32 file_stats;
- stat_result = ::_wstat32(wpath.c_str(), &file_stats);
+ struct _stat32 file_stats;
+ stat_result = ::_wstat32(wpath.c_str(), &file_stats);
#else
- struct _stat64i32 file_stats;
- stat_result = ::_wstat64i32(wpath.c_str(), &file_stats);
+ struct _stat64i32 file_stats;
+ stat_result = ::_wstat64i32(wpath.c_str(), &file_stats);
#endif
- if (stat_result == 0)
- {
- static_assert(sizeof(struct stat) == sizeof(file_stats),
- "stat and _stat32/_stat64i32 must have the same layout");
- *stats = *reinterpret_cast<struct stat *>(&file_stats);
- }
- return stat_result;
+ if (stat_result == 0) {
+ static_assert(sizeof(struct stat) == sizeof(file_stats),
+ "stat and _stat32/_stat64i32 must have the same layout");
+ *stats = *reinterpret_cast<struct stat *>(&file_stats);
+ }
+ return stat_result;
}
Modified: lldb/trunk/source/Host/windows/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/Host.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/Host.cpp (original)
+++ lldb/trunk/source/Host/windows/Host.cpp Tue Sep 6 15:57:50 2016
@@ -8,9 +8,9 @@
//===----------------------------------------------------------------------===//
// C Includes
-#include <stdio.h>
-#include "lldb/Host/windows/windows.h"
#include "lldb/Host/windows/AutoHandle.h"
+#include "lldb/Host/windows/windows.h"
+#include <stdio.h>
// C++ Includes
// Other libraries and framework includes
@@ -19,12 +19,12 @@
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "llvm/Support/ConvertUTF.h"
@@ -34,305 +34,270 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
- bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple)
- {
- // Open the PE File as a binary file, and parse just enough information to determine the
- // machine type.
- File imageBinary(
- executable.GetPath().c_str(),
- File::eOpenOptionRead,
- lldb::eFilePermissionsUserRead);
- imageBinary.SeekFromStart(0x3c);
- int32_t peOffset = 0;
- uint32_t peHead = 0;
- uint16_t machineType = 0;
- size_t readSize = sizeof(peOffset);
- imageBinary.Read(&peOffset, readSize);
- imageBinary.SeekFromStart(peOffset);
- imageBinary.Read(&peHead, readSize);
- if (peHead != 0x00004550) // "PE\0\0", little-endian
- return false; // Error: Can't find PE header
- readSize = 2;
- imageBinary.Read(&machineType, readSize);
- triple.setVendor(llvm::Triple::PC);
- triple.setOS(llvm::Triple::Win32);
- triple.setArch(llvm::Triple::UnknownArch);
- if (machineType == 0x8664)
- triple.setArch(llvm::Triple::x86_64);
- else if (machineType == 0x14c)
- triple.setArch(llvm::Triple::x86);
-
- return true;
- }
-
- bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
- {
- // Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB.
- std::vector<wchar_t> buffer(PATH_MAX);
- DWORD dwSize = buffer.size();
- if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
- return false;
- return llvm::convertWideToUTF8(buffer.data(), path);
- }
-
- void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
- {
- // We may not have permissions to read the path from the process. So start off by
- // setting the executable file to whatever Toolhelp32 gives us, and then try to
- // enhance this with more detailed information, but fail gracefully.
- std::string executable;
- llvm::Triple triple;
- triple.setVendor(llvm::Triple::PC);
- triple.setOS(llvm::Triple::Win32);
- triple.setArch(llvm::Triple::UnknownArch);
- if (GetExecutableForProcess(handle, executable))
- {
- FileSpec executableFile(executable.c_str(), false);
- process.SetExecutableFile(executableFile, true);
- GetTripleForProcess(executableFile, triple);
- }
- process.SetArchitecture(ArchSpec(triple));
-
- // TODO(zturner): Add the ability to get the process user name.
- }
-}
-
-lldb::DataBufferSP
-Host::GetAuxvData(lldb_private::Process *process)
-{
- return 0;
+namespace {
+bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) {
+ // Open the PE File as a binary file, and parse just enough information to
+ // determine the
+ // machine type.
+ File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead,
+ lldb::eFilePermissionsUserRead);
+ imageBinary.SeekFromStart(0x3c);
+ int32_t peOffset = 0;
+ uint32_t peHead = 0;
+ uint16_t machineType = 0;
+ size_t readSize = sizeof(peOffset);
+ imageBinary.Read(&peOffset, readSize);
+ imageBinary.SeekFromStart(peOffset);
+ imageBinary.Read(&peHead, readSize);
+ if (peHead != 0x00004550) // "PE\0\0", little-endian
+ return false; // Error: Can't find PE header
+ readSize = 2;
+ imageBinary.Read(&machineType, readSize);
+ triple.setVendor(llvm::Triple::PC);
+ triple.setOS(llvm::Triple::Win32);
+ triple.setArch(llvm::Triple::UnknownArch);
+ if (machineType == 0x8664)
+ triple.setArch(llvm::Triple::x86_64);
+ else if (machineType == 0x14c)
+ triple.setArch(llvm::Triple::x86);
+
+ return true;
+}
+
+bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) {
+ // Get the process image path. MAX_PATH isn't long enough, paths can actually
+ // be up to 32KB.
+ std::vector<wchar_t> buffer(PATH_MAX);
+ DWORD dwSize = buffer.size();
+ if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
+ return false;
+ return llvm::convertWideToUTF8(buffer.data(), path);
+}
+
+void GetProcessExecutableAndTriple(const AutoHandle &handle,
+ ProcessInstanceInfo &process) {
+ // We may not have permissions to read the path from the process. So start
+ // off by
+ // setting the executable file to whatever Toolhelp32 gives us, and then try
+ // to
+ // enhance this with more detailed information, but fail gracefully.
+ std::string executable;
+ llvm::Triple triple;
+ triple.setVendor(llvm::Triple::PC);
+ triple.setOS(llvm::Triple::Win32);
+ triple.setArch(llvm::Triple::UnknownArch);
+ if (GetExecutableForProcess(handle, executable)) {
+ FileSpec executableFile(executable.c_str(), false);
+ process.SetExecutableFile(executableFile, true);
+ GetTripleForProcess(executableFile, triple);
+ }
+ process.SetArchitecture(ArchSpec(triple));
+
+ // TODO(zturner): Add the ability to get the process user name.
+}
+}
+
+lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) {
+ return 0;
}
-lldb::tid_t
-Host::GetCurrentThreadID()
-{
- return lldb::tid_t(::GetCurrentThreadId());
+lldb::tid_t Host::GetCurrentThreadID() {
+ return lldb::tid_t(::GetCurrentThreadId());
}
-lldb::thread_t
-Host::GetCurrentThread ()
-{
- return lldb::thread_t(::GetCurrentThread());
+lldb::thread_t Host::GetCurrentThread() {
+ return lldb::thread_t(::GetCurrentThread());
}
lldb::thread_key_t
-Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
-{
- return TlsAlloc();
+Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) {
+ return TlsAlloc();
}
-void*
-Host::ThreadLocalStorageGet(lldb::thread_key_t key)
-{
- return ::TlsGetValue (key);
+void *Host::ThreadLocalStorageGet(lldb::thread_key_t key) {
+ return ::TlsGetValue(key);
}
-void
-Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
-{
- ::TlsSetValue (key, value);
+void Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) {
+ ::TlsSetValue(key, value);
}
-void
-Host::Kill(lldb::pid_t pid, int signo)
-{
- TerminateProcess((HANDLE) pid, 1);
+void Host::Kill(lldb::pid_t pid, int signo) {
+ TerminateProcess((HANDLE)pid, 1);
}
+const char *Host::GetSignalAsCString(int signo) { return NULL; }
+
+FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
+ FileSpec module_filespec;
+
+ HMODULE hmodule = NULL;
+ if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (LPCTSTR)host_addr, &hmodule))
+ return module_filespec;
-const char *
-Host::GetSignalAsCString(int signo)
-{
- return NULL;
+ std::vector<wchar_t> buffer(PATH_MAX);
+ DWORD chars_copied = 0;
+ do {
+ chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
+ if (chars_copied == buffer.size() &&
+ ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ buffer.resize(buffer.size() * 2);
+ } while (chars_copied >= buffer.size());
+ std::string path;
+ if (!llvm::convertWideToUTF8(buffer.data(), path))
+ return module_filespec;
+ module_filespec.SetFile(path, false);
+ return module_filespec;
}
-FileSpec
-Host::GetModuleFileSpecForHostAddress (const void *host_addr)
-{
- FileSpec module_filespec;
+uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos) {
+ process_infos.Clear();
- HMODULE hmodule = NULL;
- if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
- return module_filespec;
+ AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
+ if (!snapshot.IsValid())
+ return 0;
- std::vector<wchar_t> buffer(PATH_MAX);
- DWORD chars_copied = 0;
+ PROCESSENTRY32W pe = {0};
+ pe.dwSize = sizeof(PROCESSENTRY32W);
+ if (Process32FirstW(snapshot.get(), &pe)) {
do {
- chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
- if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- buffer.resize(buffer.size() * 2);
- } while (chars_copied >= buffer.size());
- std::string path;
- if (!llvm::convertWideToUTF8(buffer.data(), path))
- return module_filespec;
- module_filespec.SetFile(path, false);
- return module_filespec;
-}
+ AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
+ pe.th32ProcessID),
+ nullptr);
+
+ ProcessInstanceInfo process;
+ std::string exeFile;
+ llvm::convertWideToUTF8(pe.szExeFile, exeFile);
+ process.SetExecutableFile(FileSpec(exeFile, false), true);
+ process.SetProcessID(pe.th32ProcessID);
+ process.SetParentProcessID(pe.th32ParentProcessID);
+ GetProcessExecutableAndTriple(handle, process);
+
+ if (match_info.MatchAllProcesses() || match_info.Matches(process))
+ process_infos.Append(process);
+ } while (Process32NextW(snapshot.get(), &pe));
+ }
+ return process_infos.GetSize();
+}
+
+bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
+ process_info.Clear();
+
+ AutoHandle handle(
+ ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
+ nullptr);
+ if (!handle.IsValid())
+ return false;
+
+ process_info.SetProcessID(pid);
+ GetProcessExecutableAndTriple(handle, process_info);
+
+ // Need to read the PEB to get parent process and command line arguments.
+ return true;
+}
+
+HostThread Host::StartMonitoringChildProcess(
+ const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid,
+ bool monitor_signals) {
+ return HostThread();
+}
+
+Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
+ Error error;
+ if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
+ FileSpec expand_tool_spec;
+ if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir,
+ expand_tool_spec)) {
+ error.SetErrorString("could not find support executable directory for "
+ "the lldb-argdumper tool");
+ return error;
+ }
+ expand_tool_spec.AppendPathComponent("lldb-argdumper.exe");
+ if (!expand_tool_spec.Exists()) {
+ error.SetErrorString("could not find the lldb-argdumper tool");
+ return error;
+ }
-uint32_t
-Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
-{
- process_infos.Clear();
-
- AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
- if (!snapshot.IsValid())
- return 0;
-
- PROCESSENTRY32W pe = {0};
- pe.dwSize = sizeof(PROCESSENTRY32W);
- if (Process32FirstW(snapshot.get(), &pe))
- {
- do
- {
- AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
-
- ProcessInstanceInfo process;
- std::string exeFile;
- llvm::convertWideToUTF8(pe.szExeFile, exeFile);
- process.SetExecutableFile(FileSpec(exeFile, false), true);
- process.SetProcessID(pe.th32ProcessID);
- process.SetParentProcessID(pe.th32ParentProcessID);
- GetProcessExecutableAndTriple(handle, process);
-
- if (match_info.MatchAllProcesses() || match_info.Matches(process))
- process_infos.Append(process);
- } while (Process32NextW(snapshot.get(), &pe));
+ std::string quoted_cmd_string;
+ launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string);
+ std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/');
+ StreamString expand_command;
+
+ expand_command.Printf("\"%s\" %s", expand_tool_spec.GetPath().c_str(),
+ quoted_cmd_string.c_str());
+
+ int status;
+ std::string output;
+ RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(),
+ &status, nullptr, &output, 10);
+
+ if (status != 0) {
+ error.SetErrorStringWithFormat("lldb-argdumper exited with error %d",
+ status);
+ return error;
}
- return process_infos.GetSize();
-}
-bool
-Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
- process_info.Clear();
-
- AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
- nullptr);
- if (!handle.IsValid())
- return false;
-
- process_info.SetProcessID(pid);
- GetProcessExecutableAndTriple(handle, process_info);
-
- // Need to read the PEB to get parent process and command line arguments.
- return true;
-}
-
-HostThread
-Host::StartMonitoringChildProcess(const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid,
- bool monitor_signals)
-{
- return HostThread();
-}
-
-Error
-Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
-{
- Error error;
- if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments))
- {
- FileSpec expand_tool_spec;
- if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec))
- {
- error.SetErrorString("could not find support executable directory for the lldb-argdumper tool");
- return error;
- }
- expand_tool_spec.AppendPathComponent("lldb-argdumper.exe");
- if (!expand_tool_spec.Exists())
- {
- error.SetErrorString("could not find the lldb-argdumper tool");
- return error;
- }
-
- std::string quoted_cmd_string;
- launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string);
- std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/');
- StreamString expand_command;
-
- expand_command.Printf("\"%s\" %s",
- expand_tool_spec.GetPath().c_str(),
- quoted_cmd_string.c_str());
-
- int status;
- std::string output;
- RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), &status, nullptr, &output, 10);
-
- if (status != 0)
- {
- error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", status);
- return error;
- }
-
- auto data_sp = StructuredData::ParseJSON(output);
- if (!data_sp)
- {
- error.SetErrorString("invalid JSON");
- return error;
- }
-
- auto dict_sp = data_sp->GetAsDictionary();
- if (!data_sp)
- {
- error.SetErrorString("invalid JSON");
- return error;
- }
-
- auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments");
- if (!args_sp)
- {
- error.SetErrorString("invalid JSON");
- return error;
- }
-
- auto args_array_sp = args_sp->GetAsArray();
- if (!args_array_sp)
- {
- error.SetErrorString("invalid JSON");
- return error;
- }
-
- launch_info.GetArguments().Clear();
-
- for (size_t i = 0;
- i < args_array_sp->GetSize();
- i++)
- {
- auto item_sp = args_array_sp->GetItemAtIndex(i);
- if (!item_sp)
- continue;
- auto str_sp = item_sp->GetAsString();
- if (!str_sp)
- continue;
-
- launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str());
- }
+ auto data_sp = StructuredData::ParseJSON(output);
+ if (!data_sp) {
+ error.SetErrorString("invalid JSON");
+ return error;
+ }
+
+ auto dict_sp = data_sp->GetAsDictionary();
+ if (!data_sp) {
+ error.SetErrorString("invalid JSON");
+ return error;
}
-
- return error;
-}
-size_t
-Host::GetEnvironment(StringList &env)
-{
- // The environment block on Windows is a contiguous buffer of NULL terminated strings,
- // where the end of the environment block is indicated by two consecutive NULLs.
- LPWCH environment_block = ::GetEnvironmentStringsW();
- env.Clear();
- while (*environment_block != L'\0')
- {
- std::string current_var;
- auto current_var_size = wcslen(environment_block) + 1;
- if (!llvm::convertWideToUTF8(environment_block, current_var))
- {
- environment_block += current_var_size;
- continue;
- }
- if (current_var[0] != '=')
- env.AppendString(current_var);
+ auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments");
+ if (!args_sp) {
+ error.SetErrorString("invalid JSON");
+ return error;
+ }
+
+ auto args_array_sp = args_sp->GetAsArray();
+ if (!args_array_sp) {
+ error.SetErrorString("invalid JSON");
+ return error;
+ }
+
+ launch_info.GetArguments().Clear();
+
+ for (size_t i = 0; i < args_array_sp->GetSize(); i++) {
+ auto item_sp = args_array_sp->GetItemAtIndex(i);
+ if (!item_sp)
+ continue;
+ auto str_sp = item_sp->GetAsString();
+ if (!str_sp)
+ continue;
- environment_block += current_var_size;
+ launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str());
}
- return env.GetSize();
+ }
+
+ return error;
+}
+
+size_t Host::GetEnvironment(StringList &env) {
+ // The environment block on Windows is a contiguous buffer of NULL terminated
+ // strings,
+ // where the end of the environment block is indicated by two consecutive
+ // NULLs.
+ LPWCH environment_block = ::GetEnvironmentStringsW();
+ env.Clear();
+ while (*environment_block != L'\0') {
+ std::string current_var;
+ auto current_var_size = wcslen(environment_block) + 1;
+ if (!llvm::convertWideToUTF8(environment_block, current_var)) {
+ environment_block += current_var_size;
+ continue;
+ }
+ if (current_var[0] != '=')
+ env.AppendString(current_var);
+
+ environment_block += current_var_size;
+ }
+ return env.GetSize();
}
Modified: lldb/trunk/source/Host/windows/HostInfoWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/HostInfoWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/HostInfoWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/HostInfoWindows.cpp Tue Sep 6 15:57:50 2016
@@ -24,127 +24,108 @@ using namespace lldb_private;
FileSpec HostInfoWindows::m_program_filespec;
-void
-HostInfoWindows::Initialize()
-{
- ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
- HostInfoBase::Initialize();
-}
-
-void
-HostInfoWindows::Terminate()
-{
- HostInfoBase::Terminate();
- ::CoUninitialize();
-}
-
-size_t
-HostInfoWindows::GetPageSize()
-{
- SYSTEM_INFO systemInfo;
- GetNativeSystemInfo(&systemInfo);
- return systemInfo.dwPageSize;
-}
-
-bool
-HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update)
-{
- OSVERSIONINFOEX info;
+void HostInfoWindows::Initialize() {
+ ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ HostInfoBase::Initialize();
+}
+
+void HostInfoWindows::Terminate() {
+ HostInfoBase::Terminate();
+ ::CoUninitialize();
+}
+
+size_t HostInfoWindows::GetPageSize() {
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo(&systemInfo);
+ return systemInfo.dwPageSize;
+}
+
+bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor,
+ uint32_t &update) {
+ OSVERSIONINFOEX info;
- ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
- info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
+ info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
#pragma warning(push)
#pragma warning(disable : 4996)
- // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in favor of the
- // new Windows Version Helper APIs. Since we don't specify a minimum SDK version, it's easier
- // to simply disable the warning rather than try to support both APIs.
- if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
- {
- return false;
- }
+ // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in
+ // favor of the
+ // new Windows Version Helper APIs. Since we don't specify a minimum SDK
+ // version, it's easier
+ // to simply disable the warning rather than try to support both APIs.
+ if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) {
+ return false;
+ }
#pragma warning(pop)
- major = info.dwMajorVersion;
- minor = info.dwMinorVersion;
- update = info.wServicePackMajor;
-
- return true;
-}
-
-bool
-HostInfoWindows::GetOSBuildString(std::string &s)
-{
- s.clear();
- uint32_t major, minor, update;
- if (!GetOSVersion(major, minor, update))
- return false;
-
- llvm::raw_string_ostream stream(s);
- stream << "Windows NT " << major << "." << minor << "." << update;
- return true;
-}
-
-bool
-HostInfoWindows::GetOSKernelDescription(std::string &s)
-{
- return GetOSBuildString(s);
-}
-
-bool
-HostInfoWindows::GetHostname(std::string &s)
-{
- wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
- DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
- if (!::GetComputerNameW(buffer, &dwSize))
- return false;
-
- return llvm::convertWideToUTF8(buffer, s);
-}
-
-FileSpec
-HostInfoWindows::GetProgramFileSpec()
-{
- static std::once_flag g_once_flag;
- std::call_once(g_once_flag, []() {
- std::vector<wchar_t> buffer(PATH_MAX);
- ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
- std::string path;
- llvm::convertWideToUTF8(buffer.data(), path);
- m_program_filespec.SetFile(path, false);
- });
- return m_program_filespec;
-}
-
-FileSpec
-HostInfoWindows::GetDefaultShell()
-{
- std::string shell;
- GetEnvironmentVar("ComSpec", shell);
- return FileSpec(shell, false);
-}
-
-bool
-HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec)
-{
- FileSpec lldb_file_spec;
- if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
- return false;
- llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString());
- llvm::sys::path::remove_filename(path);
- llvm::sys::path::append(path, "lib", "site-packages");
- std::replace(path.begin(), path.end(), '\\', '/');
- file_spec.GetDirectory().SetString(path.c_str());
- return true;
-}
-
-bool
-HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var)
-{
- std::wstring wvar_name;
- if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
- return false;
+ major = info.dwMajorVersion;
+ minor = info.dwMinorVersion;
+ update = info.wServicePackMajor;
+
+ return true;
+}
- if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
- return llvm::convertWideToUTF8(wvar, var);
+bool HostInfoWindows::GetOSBuildString(std::string &s) {
+ s.clear();
+ uint32_t major, minor, update;
+ if (!GetOSVersion(major, minor, update))
return false;
+
+ llvm::raw_string_ostream stream(s);
+ stream << "Windows NT " << major << "." << minor << "." << update;
+ return true;
+}
+
+bool HostInfoWindows::GetOSKernelDescription(std::string &s) {
+ return GetOSBuildString(s);
+}
+
+bool HostInfoWindows::GetHostname(std::string &s) {
+ wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
+ if (!::GetComputerNameW(buffer, &dwSize))
+ return false;
+
+ return llvm::convertWideToUTF8(buffer, s);
+}
+
+FileSpec HostInfoWindows::GetProgramFileSpec() {
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, []() {
+ std::vector<wchar_t> buffer(PATH_MAX);
+ ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
+ std::string path;
+ llvm::convertWideToUTF8(buffer.data(), path);
+ m_program_filespec.SetFile(path, false);
+ });
+ return m_program_filespec;
+}
+
+FileSpec HostInfoWindows::GetDefaultShell() {
+ std::string shell;
+ GetEnvironmentVar("ComSpec", shell);
+ return FileSpec(shell, false);
+}
+
+bool HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec) {
+ FileSpec lldb_file_spec;
+ if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
+ return false;
+ llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString());
+ llvm::sys::path::remove_filename(path);
+ llvm::sys::path::append(path, "lib", "site-packages");
+ std::replace(path.begin(), path.end(), '\\', '/');
+ file_spec.GetDirectory().SetString(path.c_str());
+ return true;
+}
+
+bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name,
+ std::string &var) {
+ std::wstring wvar_name;
+ if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
+ return false;
+
+ if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
+ return llvm::convertWideToUTF8(wvar, var);
+ return false;
}
Modified: lldb/trunk/source/Host/windows/HostProcessWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/HostProcessWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/HostProcessWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/HostProcessWindows.cpp Tue Sep 6 15:57:50 2016
@@ -7,11 +7,11 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/windows/HostProcessWindows.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/windows/windows.h"
-#include "lldb/Host/windows/HostProcessWindows.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ConvertUTF.h"
@@ -20,123 +20,101 @@
using namespace lldb_private;
-namespace
-{
-struct MonitorInfo
-{
- Host::MonitorChildProcessCallback callback;
- HANDLE process_handle;
+namespace {
+struct MonitorInfo {
+ Host::MonitorChildProcessCallback callback;
+ HANDLE process_handle;
};
}
HostProcessWindows::HostProcessWindows()
- : HostNativeProcessBase()
- , m_owns_handle(true)
-{
-}
+ : HostNativeProcessBase(), m_owns_handle(true) {}
HostProcessWindows::HostProcessWindows(lldb::process_t process)
- : HostNativeProcessBase(process)
- , m_owns_handle(true)
-{
-}
+ : HostNativeProcessBase(process), m_owns_handle(true) {}
-HostProcessWindows::~HostProcessWindows()
-{
- Close();
-}
+HostProcessWindows::~HostProcessWindows() { Close(); }
-void
-HostProcessWindows::SetOwnsHandle(bool owns)
-{
- m_owns_handle = owns;
-}
+void HostProcessWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; }
-Error HostProcessWindows::Terminate()
-{
- Error error;
- if (m_process == nullptr)
- error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
+Error HostProcessWindows::Terminate() {
+ Error error;
+ if (m_process == nullptr)
+ error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
- if (!::TerminateProcess(m_process, 0))
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ if (!::TerminateProcess(m_process, 0))
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
+ return error;
}
-Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const
-{
- Error error;
- if (m_process == nullptr)
- error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
+Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const {
+ Error error;
+ if (m_process == nullptr)
+ error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
- std::vector<wchar_t> wpath(PATH_MAX);
- if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size()))
- {
- std::string path;
- if (llvm::convertWideToUTF8(wpath.data(), path))
- file_spec.SetFile(path, false);
- else
- error.SetErrorString("Error converting path to UTF-8");
- }
+ std::vector<wchar_t> wpath(PATH_MAX);
+ if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) {
+ std::string path;
+ if (llvm::convertWideToUTF8(wpath.data(), path))
+ file_spec.SetFile(path, false);
else
- error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+ error.SetErrorString("Error converting path to UTF-8");
+ } else
+ error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
- return error;
+ return error;
}
-lldb::pid_t HostProcessWindows::GetProcessId() const
-{
- return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
+lldb::pid_t HostProcessWindows::GetProcessId() const {
+ return (m_process == LLDB_INVALID_PROCESS) ? -1 : ::GetProcessId(m_process);
}
-bool HostProcessWindows::IsRunning() const
-{
- if (m_process == nullptr)
- return false;
+bool HostProcessWindows::IsRunning() const {
+ if (m_process == nullptr)
+ return false;
- DWORD code = 0;
- if (!::GetExitCodeProcess(m_process, &code))
- return false;
+ DWORD code = 0;
+ if (!::GetExitCodeProcess(m_process, &code))
+ return false;
- return (code == STILL_ACTIVE);
+ return (code == STILL_ACTIVE);
}
-HostThread
-HostProcessWindows::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals)
-{
- HostThread monitor_thread;
- MonitorInfo *info = new MonitorInfo;
- info->callback = callback;
+HostThread HostProcessWindows::StartMonitoring(
+ const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
+ HostThread monitor_thread;
+ MonitorInfo *info = new MonitorInfo;
+ info->callback = callback;
- // Since the life of this HostProcessWindows instance and the life of the process may be different, duplicate the handle so that
- // the monitor thread can have ownership over its own copy of the handle.
- HostThread result;
- if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(), &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
- result = ThreadLauncher::LaunchThread("ChildProcessMonitor", HostProcessWindows::MonitorThread, info, nullptr);
- return result;
+ // Since the life of this HostProcessWindows instance and the life of the
+ // process may be different, duplicate the handle so that
+ // the monitor thread can have ownership over its own copy of the handle.
+ HostThread result;
+ if (::DuplicateHandle(GetCurrentProcess(), m_process, GetCurrentProcess(),
+ &info->process_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ result = ThreadLauncher::LaunchThread("ChildProcessMonitor",
+ HostProcessWindows::MonitorThread,
+ info, nullptr);
+ return result;
}
-lldb::thread_result_t
-HostProcessWindows::MonitorThread(void *thread_arg)
-{
- DWORD exit_code;
+lldb::thread_result_t HostProcessWindows::MonitorThread(void *thread_arg) {
+ DWORD exit_code;
- MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg);
- if (info)
- {
- ::WaitForSingleObject(info->process_handle, INFINITE);
- ::GetExitCodeProcess(info->process_handle, &exit_code);
- info->callback(::GetProcessId(info->process_handle), true, 0, exit_code);
- ::CloseHandle(info->process_handle);
- delete (info);
- }
- return 0;
+ MonitorInfo *info = static_cast<MonitorInfo *>(thread_arg);
+ if (info) {
+ ::WaitForSingleObject(info->process_handle, INFINITE);
+ ::GetExitCodeProcess(info->process_handle, &exit_code);
+ info->callback(::GetProcessId(info->process_handle), true, 0, exit_code);
+ ::CloseHandle(info->process_handle);
+ delete (info);
+ }
+ return 0;
}
-void HostProcessWindows::Close()
-{
- if (m_owns_handle && m_process != LLDB_INVALID_PROCESS)
- ::CloseHandle(m_process);
- m_process = nullptr;
+void HostProcessWindows::Close() {
+ if (m_owns_handle && m_process != LLDB_INVALID_PROCESS)
+ ::CloseHandle(m_process);
+ m_process = nullptr;
}
Modified: lldb/trunk/source/Host/windows/HostThreadWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/HostThreadWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/HostThreadWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/HostThreadWindows.cpp Tue Sep 6 15:57:50 2016
@@ -9,90 +9,63 @@
#include "lldb/Core/Error.h"
-#include "lldb/Host/windows/windows.h"
#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
-namespace
-{
-void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode)
-{
- ::ExitThread(dwExitCode);
+namespace {
+void __stdcall ExitThreadProxy(ULONG_PTR dwExitCode) {
+ ::ExitThread(dwExitCode);
}
}
HostThreadWindows::HostThreadWindows()
- : HostNativeThreadBase()
- , m_owns_handle(true)
-{
-}
+ : HostNativeThreadBase(), m_owns_handle(true) {}
HostThreadWindows::HostThreadWindows(lldb::thread_t thread)
- : HostNativeThreadBase(thread)
- , m_owns_handle(true)
-{
-}
-
-HostThreadWindows::~HostThreadWindows()
-{
- Reset();
-}
-
-void
-HostThreadWindows::SetOwnsHandle(bool owns)
-{
- m_owns_handle = owns;
-}
-
-Error
-HostThreadWindows::Join(lldb::thread_result_t *result)
-{
- Error error;
- if (IsJoinable())
- {
- DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE);
- if (WAIT_OBJECT_0 == wait_result && result)
- {
- DWORD exit_code = 0;
- if (!::GetExitCodeThread(m_thread, &exit_code))
- *result = 0;
- *result = exit_code;
- }
- else if (WAIT_OBJECT_0 != wait_result)
- error.SetError(::GetLastError(), eErrorTypeWin32);
- }
- else
- error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32);
-
- Reset ();
- return error;
-}
-
-Error
-HostThreadWindows::Cancel()
-{
- Error error;
-
- DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0);
- error.SetError(result, eErrorTypeWin32);
- return error;
-}
-
-lldb::tid_t
-HostThreadWindows::GetThreadId() const
-{
- return ::GetThreadId(m_thread);
-}
-
-void
-HostThreadWindows::Reset()
-{
- if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD)
- ::CloseHandle(m_thread);
+ : HostNativeThreadBase(thread), m_owns_handle(true) {}
+
+HostThreadWindows::~HostThreadWindows() { Reset(); }
+
+void HostThreadWindows::SetOwnsHandle(bool owns) { m_owns_handle = owns; }
+
+Error HostThreadWindows::Join(lldb::thread_result_t *result) {
+ Error error;
+ if (IsJoinable()) {
+ DWORD wait_result = ::WaitForSingleObject(m_thread, INFINITE);
+ if (WAIT_OBJECT_0 == wait_result && result) {
+ DWORD exit_code = 0;
+ if (!::GetExitCodeThread(m_thread, &exit_code))
+ *result = 0;
+ *result = exit_code;
+ } else if (WAIT_OBJECT_0 != wait_result)
+ error.SetError(::GetLastError(), eErrorTypeWin32);
+ } else
+ error.SetError(ERROR_INVALID_HANDLE, eErrorTypeWin32);
+
+ Reset();
+ return error;
+}
+
+Error HostThreadWindows::Cancel() {
+ Error error;
+
+ DWORD result = ::QueueUserAPC(::ExitThreadProxy, m_thread, 0);
+ error.SetError(result, eErrorTypeWin32);
+ return error;
+}
+
+lldb::tid_t HostThreadWindows::GetThreadId() const {
+ return ::GetThreadId(m_thread);
+}
+
+void HostThreadWindows::Reset() {
+ if (m_owns_handle && m_thread != LLDB_INVALID_HOST_THREAD)
+ ::CloseHandle(m_thread);
- HostNativeThreadBase::Reset();
+ HostNativeThreadBase::Reset();
}
Modified: lldb/trunk/source/Host/windows/LockFileWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/LockFileWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/LockFileWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/LockFileWindows.cpp Tue Sep 6 15:57:50 2016
@@ -14,80 +14,65 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
+namespace {
-Error fileLock (HANDLE file_handle, DWORD flags, const uint64_t start, const uint64_t len)
-{
- if (start != 0)
- return Error ("Non-zero start lock regions are not supported");
+Error fileLock(HANDLE file_handle, DWORD flags, const uint64_t start,
+ const uint64_t len) {
+ if (start != 0)
+ return Error("Non-zero start lock regions are not supported");
- OVERLAPPED overlapped = {0};
+ OVERLAPPED overlapped = {0};
- if (!::LockFileEx (file_handle, flags, 0, len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING)
- return Error (::GetLastError (), eErrorTypeWin32);
+ if (!::LockFileEx(file_handle, flags, 0, len, 0, &overlapped) &&
+ ::GetLastError() != ERROR_IO_PENDING)
+ return Error(::GetLastError(), eErrorTypeWin32);
- DWORD bytes;
- if (!::GetOverlappedResult (file_handle, &overlapped, &bytes, TRUE))
- return Error (::GetLastError (), eErrorTypeWin32);
+ DWORD bytes;
+ if (!::GetOverlappedResult(file_handle, &overlapped, &bytes, TRUE))
+ return Error(::GetLastError(), eErrorTypeWin32);
- return Error ();
+ return Error();
}
-} // namespace
+} // namespace
-LockFileWindows::LockFileWindows (int fd)
- : LockFileBase (fd),
- m_file (reinterpret_cast<HANDLE> (_get_osfhandle (fd)))
-{
-}
+LockFileWindows::LockFileWindows(int fd)
+ : LockFileBase(fd), m_file(reinterpret_cast<HANDLE>(_get_osfhandle(fd))) {}
-LockFileWindows::~LockFileWindows ()
-{
- Unlock ();
-}
+LockFileWindows::~LockFileWindows() { Unlock(); }
-bool
-LockFileWindows::IsValidFile () const
-{
- return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE;
+bool LockFileWindows::IsValidFile() const {
+ return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE;
}
-Error
-LockFileWindows::DoWriteLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len);
+Error LockFileWindows::DoWriteLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len);
}
-Error
-LockFileWindows::DoTryWriteLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, start, len);
+Error LockFileWindows::DoTryWriteLock(const uint64_t start,
+ const uint64_t len) {
+ return fileLock(m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
+ start, len);
}
-Error
-LockFileWindows::DoReadLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_file, 0, start, len);
+Error LockFileWindows::DoReadLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_file, 0, start, len);
}
-Error
-LockFileWindows::DoTryReadLock (const uint64_t start, const uint64_t len)
-{
- return fileLock (m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len);
+Error LockFileWindows::DoTryReadLock(const uint64_t start, const uint64_t len) {
+ return fileLock(m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len);
}
-Error
-LockFileWindows::DoUnlock ()
-{
- OVERLAPPED overlapped = {0};
+Error LockFileWindows::DoUnlock() {
+ OVERLAPPED overlapped = {0};
- if (!::UnlockFileEx (m_file, 0, m_len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING)
- return Error (::GetLastError (), eErrorTypeWin32);
+ if (!::UnlockFileEx(m_file, 0, m_len, 0, &overlapped) &&
+ ::GetLastError() != ERROR_IO_PENDING)
+ return Error(::GetLastError(), eErrorTypeWin32);
- DWORD bytes;
- if (!::GetOverlappedResult (m_file, &overlapped, &bytes, TRUE))
- return Error (::GetLastError (), eErrorTypeWin32);
+ DWORD bytes;
+ if (!::GetOverlappedResult(m_file, &overlapped, &bytes, TRUE))
+ return Error(::GetLastError(), eErrorTypeWin32);
- return Error ();
+ return Error();
}
Modified: lldb/trunk/source/Host/windows/PipeWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/PipeWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/PipeWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/PipeWindows.cpp Tue Sep 6 15:57:50 2016
@@ -23,316 +23,273 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
+namespace {
std::atomic<uint32_t> g_pipe_serial(0);
}
-PipeWindows::PipeWindows()
-{
- m_read = INVALID_HANDLE_VALUE;
- m_write = INVALID_HANDLE_VALUE;
+PipeWindows::PipeWindows() {
+ m_read = INVALID_HANDLE_VALUE;
+ m_write = INVALID_HANDLE_VALUE;
+
+ m_read_fd = -1;
+ m_write_fd = -1;
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+}
+
+PipeWindows::~PipeWindows() { Close(); }
+
+Error PipeWindows::CreateNew(bool child_process_inherit) {
+ // Even for anonymous pipes, we open a named pipe. This is because you cannot
+ // get
+ // overlapped i/o on Windows without using a named pipe. So we synthesize a
+ // unique
+ // name.
+ uint32_t serial = g_pipe_serial.fetch_add(1);
+ std::string pipe_name;
+ llvm::raw_string_ostream pipe_name_stream(pipe_name);
+ pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial;
+ pipe_name_stream.flush();
+
+ return CreateNew(pipe_name.c_str(), child_process_inherit);
+}
+
+Error PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit) {
+ if (name.empty())
+ return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
+
+ if (CanRead() || CanWrite())
+ return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
+
+ std::string pipe_path = "\\\\.\\Pipe\\";
+ pipe_path.append(name);
+
+ // Always open for overlapped i/o. We implement blocking manually in Read and
+ // Write.
+ DWORD read_mode = FILE_FLAG_OVERLAPPED;
+ m_read = ::CreateNamedPipeA(
+ pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode,
+ PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
+ if (INVALID_HANDLE_VALUE == m_read)
+ return Error(::GetLastError(), eErrorTypeWin32);
+ m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+ m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ // Open the write end of the pipe.
+ Error result = OpenNamedPipe(name, child_process_inherit, false);
+ if (!result.Success()) {
+ CloseReadFileDescriptor();
+ return result;
+ }
- m_read_fd = -1;
- m_write_fd = -1;
- ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
- ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+ return result;
}
-PipeWindows::~PipeWindows()
-{
- Close();
-}
-
-Error
-PipeWindows::CreateNew(bool child_process_inherit)
-{
- // Even for anonymous pipes, we open a named pipe. This is because you cannot get
- // overlapped i/o on Windows without using a named pipe. So we synthesize a unique
- // name.
- uint32_t serial = g_pipe_serial.fetch_add(1);
- std::string pipe_name;
- llvm::raw_string_ostream pipe_name_stream(pipe_name);
- pipe_name_stream << "lldb.pipe." << ::GetCurrentProcessId() << "." << serial;
- pipe_name_stream.flush();
-
- return CreateNew(pipe_name.c_str(), child_process_inherit);
-}
-
-Error
-PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit)
-{
- if (name.empty())
- return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
-
- if (CanRead() || CanWrite())
- return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
-
- std::string pipe_path = "\\\\.\\Pipe\\";
- pipe_path.append(name);
-
- // Always open for overlapped i/o. We implement blocking manually in Read and Write.
- DWORD read_mode = FILE_FLAG_OVERLAPPED;
- m_read = ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024,
- 1024, 120 * 1000, NULL);
+Error PipeWindows::CreateWithUniqueName(llvm::StringRef prefix,
+ bool child_process_inherit,
+ llvm::SmallVectorImpl<char> &name) {
+ llvm::SmallString<128> pipe_name;
+ Error error;
+ ::UUID unique_id;
+ RPC_CSTR unique_string;
+ RPC_STATUS status = ::UuidCreate(&unique_id);
+ if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY)
+ status = ::UuidToStringA(&unique_id, &unique_string);
+ if (status == RPC_S_OK) {
+ pipe_name = prefix;
+ pipe_name += "-";
+ pipe_name += reinterpret_cast<char *>(unique_string);
+ ::RpcStringFreeA(&unique_string);
+ error = CreateNew(pipe_name, child_process_inherit);
+ } else {
+ error.SetError(status, eErrorTypeWin32);
+ }
+ if (error.Success())
+ name = pipe_name;
+ return error;
+}
+
+Error PipeWindows::OpenAsReader(llvm::StringRef name,
+ bool child_process_inherit) {
+ if (CanRead() || CanWrite())
+ return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
+
+ return OpenNamedPipe(name, child_process_inherit, true);
+}
+
+Error PipeWindows::OpenAsWriterWithTimeout(
+ llvm::StringRef name, bool child_process_inherit,
+ const std::chrono::microseconds &timeout) {
+ if (CanRead() || CanWrite())
+ return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
+
+ return OpenNamedPipe(name, child_process_inherit, false);
+}
+
+Error PipeWindows::OpenNamedPipe(llvm::StringRef name,
+ bool child_process_inherit, bool is_read) {
+ if (name.empty())
+ return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
+
+ assert(is_read ? !CanRead() : !CanWrite());
+
+ SECURITY_ATTRIBUTES attributes = {0};
+ attributes.bInheritHandle = child_process_inherit;
+
+ std::string pipe_path = "\\\\.\\Pipe\\";
+ pipe_path.append(name);
+
+ if (is_read) {
+ m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == m_read)
- return Error(::GetLastError(), eErrorTypeWin32);
+ return Error(::GetLastError(), eErrorTypeWin32);
+
m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
+
ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ } else {
+ m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (INVALID_HANDLE_VALUE == m_write)
+ return Error(::GetLastError(), eErrorTypeWin32);
- // Open the write end of the pipe.
- Error result = OpenNamedPipe(name, child_process_inherit, false);
- if (!result.Success())
- {
- CloseReadFileDescriptor();
- return result;
- }
+ m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
- return result;
-}
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+ }
-Error
-PipeWindows::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name)
-{
- llvm::SmallString<128> pipe_name;
- Error error;
- ::UUID unique_id;
- RPC_CSTR unique_string;
- RPC_STATUS status = ::UuidCreate(&unique_id);
- if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY)
- status = ::UuidToStringA(&unique_id, &unique_string);
- if (status == RPC_S_OK)
- {
- pipe_name = prefix;
- pipe_name += "-";
- pipe_name += reinterpret_cast<char *>(unique_string);
- ::RpcStringFreeA(&unique_string);
- error = CreateNew(pipe_name, child_process_inherit);
- }
- else
- {
- error.SetError(status, eErrorTypeWin32);
- }
- if (error.Success())
- name = pipe_name;
- return error;
+ return Error();
}
-Error
-PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
-{
- if (CanRead() || CanWrite())
- return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
+int PipeWindows::GetReadFileDescriptor() const { return m_read_fd; }
- return OpenNamedPipe(name, child_process_inherit, true);
-}
+int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; }
-Error
-PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
-{
- if (CanRead() || CanWrite())
- return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
-
- return OpenNamedPipe(name, child_process_inherit, false);
+int PipeWindows::ReleaseReadFileDescriptor() {
+ if (!CanRead())
+ return -1;
+ int result = m_read_fd;
+ m_read_fd = -1;
+ if (m_read_overlapped.hEvent)
+ ::CloseHandle(m_read_overlapped.hEvent);
+ m_read = INVALID_HANDLE_VALUE;
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+ return result;
}
-Error
-PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, bool is_read)
-{
- if (name.empty())
- return Error(ERROR_INVALID_PARAMETER, eErrorTypeWin32);
-
- assert(is_read ? !CanRead() : !CanWrite());
-
- SECURITY_ATTRIBUTES attributes = {0};
- attributes.bInheritHandle = child_process_inherit;
-
- std::string pipe_path = "\\\\.\\Pipe\\";
- pipe_path.append(name);
-
- if (is_read)
- {
- m_read =
- ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (INVALID_HANDLE_VALUE == m_read)
- return Error(::GetLastError(), eErrorTypeWin32);
-
- m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
-
- ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
- m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
- }
- else
- {
- m_write =
- ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (INVALID_HANDLE_VALUE == m_write)
- return Error(::GetLastError(), eErrorTypeWin32);
-
- m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
-
- ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
- }
-
- return Error();
+int PipeWindows::ReleaseWriteFileDescriptor() {
+ if (!CanWrite())
+ return -1;
+ int result = m_write_fd;
+ m_write_fd = -1;
+ m_write = INVALID_HANDLE_VALUE;
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+ return result;
}
-int
-PipeWindows::GetReadFileDescriptor() const
-{
- return m_read_fd;
-}
-
-int
-PipeWindows::GetWriteFileDescriptor() const
-{
- return m_write_fd;
-}
-
-int
-PipeWindows::ReleaseReadFileDescriptor()
-{
- if (!CanRead())
- return -1;
- int result = m_read_fd;
- m_read_fd = -1;
- if (m_read_overlapped.hEvent)
- ::CloseHandle(m_read_overlapped.hEvent);
- m_read = INVALID_HANDLE_VALUE;
- ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
- return result;
-}
+void PipeWindows::CloseReadFileDescriptor() {
+ if (!CanRead())
+ return;
-int
-PipeWindows::ReleaseWriteFileDescriptor()
-{
- if (!CanWrite())
- return -1;
- int result = m_write_fd;
- m_write_fd = -1;
- m_write = INVALID_HANDLE_VALUE;
- ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
- return result;
+ if (m_read_overlapped.hEvent)
+ ::CloseHandle(m_read_overlapped.hEvent);
+ _close(m_read_fd);
+ m_read = INVALID_HANDLE_VALUE;
+ m_read_fd = -1;
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
}
-void
-PipeWindows::CloseReadFileDescriptor()
-{
- if (!CanRead())
- return;
-
- if (m_read_overlapped.hEvent)
- ::CloseHandle(m_read_overlapped.hEvent);
- _close(m_read_fd);
- m_read = INVALID_HANDLE_VALUE;
- m_read_fd = -1;
- ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
-}
+void PipeWindows::CloseWriteFileDescriptor() {
+ if (!CanWrite())
+ return;
-void
-PipeWindows::CloseWriteFileDescriptor()
-{
- if (!CanWrite())
- return;
-
- _close(m_write_fd);
- m_write = INVALID_HANDLE_VALUE;
- m_write_fd = -1;
- ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+ _close(m_write_fd);
+ m_write = INVALID_HANDLE_VALUE;
+ m_write_fd = -1;
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
}
-void
-PipeWindows::Close()
-{
- CloseReadFileDescriptor();
- CloseWriteFileDescriptor();
+void PipeWindows::Close() {
+ CloseReadFileDescriptor();
+ CloseWriteFileDescriptor();
}
-Error
-PipeWindows::Delete(llvm::StringRef name)
-{
- return Error();
-}
+Error PipeWindows::Delete(llvm::StringRef name) { return Error(); }
-bool
-PipeWindows::CanRead() const
-{
- return (m_read != INVALID_HANDLE_VALUE);
-}
+bool PipeWindows::CanRead() const { return (m_read != INVALID_HANDLE_VALUE); }
-bool
-PipeWindows::CanWrite() const
-{
- return (m_write != INVALID_HANDLE_VALUE);
-}
+bool PipeWindows::CanWrite() const { return (m_write != INVALID_HANDLE_VALUE); }
HANDLE
-PipeWindows::GetReadNativeHandle()
-{
- return m_read;
-}
+PipeWindows::GetReadNativeHandle() { return m_read; }
HANDLE
-PipeWindows::GetWriteNativeHandle()
-{
- return m_write;
-}
-
-Error
-PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read)
-{
- if (!CanRead())
- return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
-
- bytes_read = 0;
- DWORD sys_bytes_read = size;
- BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read, &m_read_overlapped);
- if (!result && GetLastError() != ERROR_IO_PENDING)
- return Error(::GetLastError(), eErrorTypeWin32);
-
- DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000;
- DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout);
- if (wait_result != WAIT_OBJECT_0)
- {
- // The operation probably failed. However, if it timed out, we need to cancel the I/O.
- // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx,
- // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND.
- // If that happens, the original operation should be considered to have been successful.
- bool failed = true;
- DWORD failure_error = ::GetLastError();
- if (wait_result == WAIT_TIMEOUT)
- {
- BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped);
- if (!cancel_result && GetLastError() == ERROR_NOT_FOUND)
- failed = false;
- }
- if (failed)
- return Error(failure_error, eErrorTypeWin32);
- }
+PipeWindows::GetWriteNativeHandle() { return m_write; }
- // Now we call GetOverlappedResult setting bWait to false, since we've already waited
- // as long as we're willing to.
- if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE))
- return Error(::GetLastError(), eErrorTypeWin32);
-
- bytes_read = sys_bytes_read;
- return Error();
-}
-
-Error
-PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written)
-{
- if (!CanWrite())
- return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
-
- DWORD sys_bytes_written = 0;
- BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written, &m_write_overlapped);
- if (!write_result && GetLastError() != ERROR_IO_PENDING)
- return Error(::GetLastError(), eErrorTypeWin32);
-
- BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE);
- if (!result)
- return Error(::GetLastError(), eErrorTypeWin32);
- return Error();
+Error PipeWindows::ReadWithTimeout(void *buf, size_t size,
+ const std::chrono::microseconds &duration,
+ size_t &bytes_read) {
+ if (!CanRead())
+ return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
+
+ bytes_read = 0;
+ DWORD sys_bytes_read = size;
+ BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read,
+ &m_read_overlapped);
+ if (!result && GetLastError() != ERROR_IO_PENDING)
+ return Error(::GetLastError(), eErrorTypeWin32);
+
+ DWORD timeout = (duration == std::chrono::microseconds::zero())
+ ? INFINITE
+ : duration.count() * 1000;
+ DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout);
+ if (wait_result != WAIT_OBJECT_0) {
+ // The operation probably failed. However, if it timed out, we need to
+ // cancel the I/O.
+ // Between the time we returned from WaitForSingleObject and the time we
+ // call CancelIoEx,
+ // the operation may complete. If that hapens, CancelIoEx will fail and
+ // return ERROR_NOT_FOUND.
+ // If that happens, the original operation should be considered to have been
+ // successful.
+ bool failed = true;
+ DWORD failure_error = ::GetLastError();
+ if (wait_result == WAIT_TIMEOUT) {
+ BOOL cancel_result = CancelIoEx(m_read, &m_read_overlapped);
+ if (!cancel_result && GetLastError() == ERROR_NOT_FOUND)
+ failed = false;
+ }
+ if (failed)
+ return Error(failure_error, eErrorTypeWin32);
+ }
+
+ // Now we call GetOverlappedResult setting bWait to false, since we've already
+ // waited
+ // as long as we're willing to.
+ if (!GetOverlappedResult(m_read, &m_read_overlapped, &sys_bytes_read, FALSE))
+ return Error(::GetLastError(), eErrorTypeWin32);
+
+ bytes_read = sys_bytes_read;
+ return Error();
+}
+
+Error PipeWindows::Write(const void *buf, size_t num_bytes,
+ size_t &bytes_written) {
+ if (!CanWrite())
+ return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
+
+ DWORD sys_bytes_written = 0;
+ BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written,
+ &m_write_overlapped);
+ if (!write_result && GetLastError() != ERROR_IO_PENDING)
+ return Error(::GetLastError(), eErrorTypeWin32);
+
+ BOOL result = GetOverlappedResult(m_write, &m_write_overlapped,
+ &sys_bytes_written, TRUE);
+ if (!result)
+ return Error(::GetLastError(), eErrorTypeWin32);
+ return Error();
}
Modified: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp Tue Sep 6 15:57:50 2016
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Host/HostProcess.h"
#include "lldb/Host/windows/ProcessLauncherWindows.h"
+#include "lldb/Host/HostProcess.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "llvm/ADT/SmallVector.h"
@@ -20,127 +20,130 @@
using namespace lldb;
using namespace lldb_private;
-namespace
-{
-void
-CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer)
-{
- if (env.GetArgumentCount() == 0)
- return;
-
- // Environment buffer is a null terminated list of null terminated strings
- for (int i = 0; i < env.GetArgumentCount(); ++i)
- {
- std::wstring warg;
- if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg))
- {
- buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1));
- }
+namespace {
+void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) {
+ if (env.GetArgumentCount() == 0)
+ return;
+
+ // Environment buffer is a null terminated list of null terminated strings
+ for (int i = 0; i < env.GetArgumentCount(); ++i) {
+ std::wstring warg;
+ if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) {
+ buffer.insert(buffer.end(), (char *)warg.c_str(),
+ (char *)(warg.c_str() + warg.size() + 1));
}
- // One null wchar_t (to end the block) is two null bytes
- buffer.push_back(0);
- buffer.push_back(0);
+ }
+ // One null wchar_t (to end the block) is two null bytes
+ buffer.push_back(0);
+ buffer.push_back(0);
}
}
HostProcess
-ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
-{
- error.Clear();
-
- std::string executable;
- std::string commandLine;
- std::vector<char> environment;
- STARTUPINFO startupinfo = {0};
- PROCESS_INFORMATION pi = {0};
-
- HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
- HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
- HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
-
- startupinfo.cb = sizeof(startupinfo);
- startupinfo.dwFlags |= STARTF_USESTDHANDLES;
- startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
- startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
- startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
-
- const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
- if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true"))
- {
- startupinfo.dwFlags |= STARTF_USESHOWWINDOW;
- startupinfo.wShowWindow = SW_HIDE;
- }
-
- DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
- if (launch_info.GetFlags().Test(eLaunchFlagDebug))
- flags |= DEBUG_ONLY_THIS_PROCESS;
-
- auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries());
- LPVOID env_block = nullptr;
- ::CreateEnvironmentBuffer(env, environment);
- if (!environment.empty())
- env_block = environment.data();
-
- executable = launch_info.GetExecutableFile().GetPath();
- launch_info.GetArguments().GetQuotedCommandString(commandLine);
-
- std::wstring wexecutable, wcommandLine, wworkingDirectory;
- llvm::ConvertUTF8toWide(executable, wexecutable);
- llvm::ConvertUTF8toWide(commandLine, wcommandLine);
- llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory);
-
- wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it
- BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block,
- wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi);
- if (result)
- {
- // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
- ::CloseHandle(pi.hThread);
- }
-
- if (stdin_handle)
- ::CloseHandle(stdin_handle);
- if (stdout_handle)
- ::CloseHandle(stdout_handle);
- if (stderr_handle)
- ::CloseHandle(stderr_handle);
-
- if (!result)
- error.SetError(::GetLastError(), eErrorTypeWin32);
- return HostProcess(pi.hProcess);
+ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
+ Error &error) {
+ error.Clear();
+
+ std::string executable;
+ std::string commandLine;
+ std::vector<char> environment;
+ STARTUPINFO startupinfo = {0};
+ PROCESS_INFORMATION pi = {0};
+
+ HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
+ HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
+ HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
+
+ startupinfo.cb = sizeof(startupinfo);
+ startupinfo.dwFlags |= STARTF_USESTDHANDLES;
+ startupinfo.hStdError =
+ stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
+ startupinfo.hStdInput =
+ stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
+ startupinfo.hStdOutput =
+ stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
+
+ const char *hide_console_var =
+ getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
+ if (hide_console_var &&
+ llvm::StringRef(hide_console_var).equals_lower("true")) {
+ startupinfo.dwFlags |= STARTF_USESHOWWINDOW;
+ startupinfo.wShowWindow = SW_HIDE;
+ }
+
+ DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
+ if (launch_info.GetFlags().Test(eLaunchFlagDebug))
+ flags |= DEBUG_ONLY_THIS_PROCESS;
+
+ auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries());
+ LPVOID env_block = nullptr;
+ ::CreateEnvironmentBuffer(env, environment);
+ if (!environment.empty())
+ env_block = environment.data();
+
+ executable = launch_info.GetExecutableFile().GetPath();
+ launch_info.GetArguments().GetQuotedCommandString(commandLine);
+
+ std::wstring wexecutable, wcommandLine, wworkingDirectory;
+ llvm::ConvertUTF8toWide(executable, wexecutable);
+ llvm::ConvertUTF8toWide(commandLine, wcommandLine);
+ llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(),
+ wworkingDirectory);
+
+ wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because
+ // CreateProcessW can modify it
+ BOOL result = ::CreateProcessW(
+ wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block,
+ wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
+ &startupinfo, &pi);
+ if (result) {
+ // Do not call CloseHandle on pi.hProcess, since we want to pass that back
+ // through the HostProcess.
+ ::CloseHandle(pi.hThread);
+ }
+
+ if (stdin_handle)
+ ::CloseHandle(stdin_handle);
+ if (stdout_handle)
+ ::CloseHandle(stdout_handle);
+ if (stderr_handle)
+ ::CloseHandle(stderr_handle);
+
+ if (!result)
+ error.SetError(::GetLastError(), eErrorTypeWin32);
+ return HostProcess(pi.hProcess);
}
HANDLE
-ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd)
-{
- const FileAction *action = launch_info.GetFileActionForFD(fd);
- if (action == nullptr)
- return NULL;
- SECURITY_ATTRIBUTES secattr = {0};
- secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
- secattr.bInheritHandle = TRUE;
-
- const char *path = action->GetPath();
- DWORD access = 0;
- DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- DWORD create = 0;
- DWORD flags = 0;
- if (fd == STDIN_FILENO)
- {
- access = GENERIC_READ;
- create = OPEN_EXISTING;
- flags = FILE_ATTRIBUTE_READONLY;
- }
- if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
- {
- access = GENERIC_WRITE;
- create = CREATE_ALWAYS;
- if (fd == STDERR_FILENO)
- flags = FILE_FLAG_WRITE_THROUGH;
- }
-
- std::wstring wpath;
- llvm::ConvertUTF8toWide(path, wpath);
- HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL);
- return (result == INVALID_HANDLE_VALUE) ? NULL : result;
+ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
+ int fd) {
+ const FileAction *action = launch_info.GetFileActionForFD(fd);
+ if (action == nullptr)
+ return NULL;
+ SECURITY_ATTRIBUTES secattr = {0};
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secattr.bInheritHandle = TRUE;
+
+ const char *path = action->GetPath();
+ DWORD access = 0;
+ DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ DWORD create = 0;
+ DWORD flags = 0;
+ if (fd == STDIN_FILENO) {
+ access = GENERIC_READ;
+ create = OPEN_EXISTING;
+ flags = FILE_ATTRIBUTE_READONLY;
+ }
+ if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
+ access = GENERIC_WRITE;
+ create = CREATE_ALWAYS;
+ if (fd == STDERR_FILENO)
+ flags = FILE_FLAG_WRITE_THROUGH;
+ }
+
+ std::wstring wpath;
+ llvm::ConvertUTF8toWide(path, wpath);
+ HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
+ flags, NULL);
+ return (result == INVALID_HANDLE_VALUE) ? NULL : result;
}
Modified: lldb/trunk/source/Host/windows/ProcessRunLock.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/ProcessRunLock.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/ProcessRunLock.cpp (original)
+++ lldb/trunk/source/Host/windows/ProcessRunLock.cpp Tue Sep 6 15:57:50 2016
@@ -1,106 +1,83 @@
#include "lldb/Host/ProcessRunLock.h"
#include "lldb/Host/windows/windows.h"
-namespace
-{
+namespace {
#if defined(__MINGW32__)
// Taken from WinNT.h
-typedef struct _RTL_SRWLOCK {
- PVOID Ptr;
-} RTL_SRWLOCK, *PRTL_SRWLOCK;
+typedef struct _RTL_SRWLOCK { PVOID Ptr; } RTL_SRWLOCK, *PRTL_SRWLOCK;
// Taken from WinBase.h
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
#endif
}
-
-static PSRWLOCK GetLock(lldb::rwlock_t lock)
-{
- return static_cast<PSRWLOCK>(lock);
+static PSRWLOCK GetLock(lldb::rwlock_t lock) {
+ return static_cast<PSRWLOCK>(lock);
}
-static bool ReadLock(lldb::rwlock_t rwlock)
-{
- ::AcquireSRWLockShared(GetLock(rwlock));
- return true;
+static bool ReadLock(lldb::rwlock_t rwlock) {
+ ::AcquireSRWLockShared(GetLock(rwlock));
+ return true;
}
-static bool ReadUnlock(lldb::rwlock_t rwlock)
-{
- ::ReleaseSRWLockShared(GetLock(rwlock));
- return true;
+static bool ReadUnlock(lldb::rwlock_t rwlock) {
+ ::ReleaseSRWLockShared(GetLock(rwlock));
+ return true;
}
-static bool WriteLock(lldb::rwlock_t rwlock)
-{
- ::AcquireSRWLockExclusive(GetLock(rwlock));
- return true;
+static bool WriteLock(lldb::rwlock_t rwlock) {
+ ::AcquireSRWLockExclusive(GetLock(rwlock));
+ return true;
}
-static bool WriteTryLock(lldb::rwlock_t rwlock)
-{
- return !!::TryAcquireSRWLockExclusive(GetLock(rwlock));
+static bool WriteTryLock(lldb::rwlock_t rwlock) {
+ return !!::TryAcquireSRWLockExclusive(GetLock(rwlock));
}
-static bool WriteUnlock(lldb::rwlock_t rwlock)
-{
- ::ReleaseSRWLockExclusive(GetLock(rwlock));
- return true;
+static bool WriteUnlock(lldb::rwlock_t rwlock) {
+ ::ReleaseSRWLockExclusive(GetLock(rwlock));
+ return true;
}
using namespace lldb_private;
-ProcessRunLock::ProcessRunLock()
- : m_running(false)
-{
- m_rwlock = new SRWLOCK;
- InitializeSRWLock(GetLock(m_rwlock));
+ProcessRunLock::ProcessRunLock() : m_running(false) {
+ m_rwlock = new SRWLOCK;
+ InitializeSRWLock(GetLock(m_rwlock));
}
-ProcessRunLock::~ProcessRunLock()
-{
- delete m_rwlock;
-}
+ProcessRunLock::~ProcessRunLock() { delete m_rwlock; }
-bool ProcessRunLock::ReadTryLock()
-{
- ::ReadLock(m_rwlock);
- if (m_running == false)
- return true;
- ::ReadUnlock(m_rwlock);
- return false;
+bool ProcessRunLock::ReadTryLock() {
+ ::ReadLock(m_rwlock);
+ if (m_running == false)
+ return true;
+ ::ReadUnlock(m_rwlock);
+ return false;
}
-bool ProcessRunLock::ReadUnlock()
-{
- return ::ReadUnlock(m_rwlock);
+bool ProcessRunLock::ReadUnlock() { return ::ReadUnlock(m_rwlock); }
+
+bool ProcessRunLock::SetRunning() {
+ WriteLock(m_rwlock);
+ m_running = true;
+ WriteUnlock(m_rwlock);
+ return true;
}
-bool ProcessRunLock::SetRunning ()
-{
- WriteLock(m_rwlock);
+bool ProcessRunLock::TrySetRunning() {
+ if (WriteTryLock(m_rwlock)) {
+ bool was_running = m_running;
m_running = true;
WriteUnlock(m_rwlock);
- return true;
+ return !was_running;
+ }
+ return false;
}
-bool ProcessRunLock::TrySetRunning ()
-{
- if (WriteTryLock(m_rwlock))
- {
- bool was_running = m_running;
- m_running = true;
- WriteUnlock(m_rwlock);
- return !was_running;
- }
- return false;
-}
-
-bool ProcessRunLock::SetStopped ()
-{
- WriteLock(m_rwlock);
- m_running = false;
- WriteUnlock(m_rwlock);
- return true;
+bool ProcessRunLock::SetStopped() {
+ WriteLock(m_rwlock);
+ m_running = false;
+ WriteUnlock(m_rwlock);
+ return true;
}
Modified: lldb/trunk/source/Host/windows/ThisThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/ThisThread.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/ThisThread.cpp (original)
+++ lldb/trunk/source/Host/windows/ThisThread.cpp Tue Sep 6 15:57:50 2016
@@ -9,8 +9,8 @@
#include "lldb/Core/Error.h"
-#include "lldb/Host/windows/windows.h"
#include "lldb/Host/ThisThread.h"
+#include "lldb/Host/windows/windows.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -20,47 +20,44 @@ using namespace lldb_private;
#if defined(_MSC_VER) && !defined(__clang__)
-namespace
-{
+namespace {
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
-struct THREADNAME_INFO
-{
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to thread name
- DWORD dwThreadId; // Thread ID (-1 == current thread)
- DWORD dwFlags; // Reserved. Do not use.
+struct THREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to thread name
+ DWORD dwThreadId; // Thread ID (-1 == current thread)
+ DWORD dwFlags; // Reserved. Do not use.
};
#pragma pack(pop)
}
#endif
-void
-ThisThread::SetName(llvm::StringRef name)
-{
-// Other compilers don't yet support SEH, so we can only set the thread if compiling with MSVC.
+void ThisThread::SetName(llvm::StringRef name) {
+// Other compilers don't yet support SEH, so we can only set the thread if
+// compiling with MSVC.
// TODO(zturner): Once clang-cl supports SEH, relax this conditional.
#if defined(_MSC_VER) && !defined(__clang__)
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = name.data();
- info.dwThreadId = ::GetCurrentThreadId();
- info.dwFlags = 0;
-
- __try {
- ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {}
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = name.data();
+ info.dwThreadId = ::GetCurrentThreadId();
+ info.dwFlags = 0;
+
+ __try {
+ ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
+ (ULONG_PTR *)&info);
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ }
#endif
}
-void
-ThisThread::GetName(llvm::SmallVectorImpl<char> &name)
-{
- // Getting the thread name is not supported on Windows.
- // TODO(zturner): In SetName(), make a TLS entry that contains the thread's name, and in this function
- // try to extract that TLS entry.
- name.clear();
+void ThisThread::GetName(llvm::SmallVectorImpl<char> &name) {
+ // Getting the thread name is not supported on Windows.
+ // TODO(zturner): In SetName(), make a TLS entry that contains the thread's
+ // name, and in this function
+ // try to extract that TLS entry.
+ name.clear();
}
Modified: lldb/trunk/source/Host/windows/Windows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/Windows.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/Windows.cpp (original)
+++ lldb/trunk/source/Host/windows/Windows.cpp Tue Sep 6 15:57:50 2016
@@ -9,276 +9,253 @@
// This file provides Windows support functions
-#include "lldb/Host/windows/windows.h"
#include "lldb/Host/PosixApi.h"
+#include "lldb/Host/windows/windows.h"
#include "llvm/Support/ConvertUTF.h"
#include <assert.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-#include <io.h>
#include <cerrno>
#include <ctype.h>
+#include <io.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors
-extern "C"
-{
- char *_getcwd(char *buffer, int maxlen);
- int _chdir(const char *path);
-}
-
-namespace
-{
-bool
-utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize)
-{
- const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8);
- size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
- UTF16 *target = reinterpret_cast<UTF16 *>(buf);
- ConversionFlags flags = strictConversion;
- return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
-}
-
-bool
-wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize)
-{
- const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide);
- size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
- UTF8 *target = reinterpret_cast<UTF8 *>(buf);
- ConversionFlags flags = strictConversion;
- return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
+// These prototypes are defined in <direct.h>, but it also defines chdir() and
+// getcwd(), giving multiply defined errors
+extern "C" {
+char *_getcwd(char *buffer, int maxlen);
+int _chdir(const char *path);
+}
+
+namespace {
+bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) {
+ const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8);
+ size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
+ UTF16 *target = reinterpret_cast<UTF16 *>(buf);
+ ConversionFlags flags = strictConversion;
+ return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target,
+ target + bufSize, flags) == conversionOK;
+}
+
+bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) {
+ const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide);
+ size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
+ UTF8 *target = reinterpret_cast<UTF8 *>(buf);
+ ConversionFlags flags = strictConversion;
+ return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target,
+ target + bufSize, flags) == conversionOK;
}
}
-int vasprintf(char **ret, const char *fmt, va_list ap)
-{
- char *buf;
- int len;
- size_t buflen;
- va_list ap2;
+int vasprintf(char **ret, const char *fmt, va_list ap) {
+ char *buf;
+ int len;
+ size_t buflen;
+ va_list ap2;
#if defined(_MSC_VER) || defined(__MINGW64)
- ap2 = ap;
- len = _vscprintf(fmt, ap2);
+ ap2 = ap;
+ len = _vscprintf(fmt, ap2);
#else
- va_copy(ap2, ap);
- len = vsnprintf(NULL, 0, fmt, ap2);
+ va_copy(ap2, ap);
+ len = vsnprintf(NULL, 0, fmt, ap2);
#endif
- if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) {
- len = vsnprintf(buf, buflen, fmt, ap);
- *ret = buf;
- } else {
- *ret = NULL;
- len = -1;
- }
-
- va_end(ap2);
- return len;
-}
-
-char* strcasestr(const char *s, const char* find)
-{
- char c, sc;
- size_t len;
-
- if ((c = *find++) != 0) {
- c = tolower((unsigned char) c);
- len = strlen(find);
- do {
- do {
- if ((sc = *s++) == 0)
- return 0;
- } while ((char) tolower((unsigned char) sc) != c);
- } while (strncasecmp(s, find, len) != 0);
- s--;
- }
- return ((char *) s);
-}
-
-char* realpath(const char * name, char * resolved)
-{
- char *retname = NULL;
-
- /* SUSv3 says we must set `errno = EINVAL', and return NULL,
- * if `name' is passed as a NULL pointer.
- */
- if (name == NULL)
- {
- errno = EINVAL;
- return NULL;
- }
+ if (len >= 0 &&
+ (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) {
+ len = vsnprintf(buf, buflen, fmt, ap);
+ *ret = buf;
+ } else {
+ *ret = NULL;
+ len = -1;
+ }
+
+ va_end(ap2);
+ return len;
+}
+
+char *strcasestr(const char *s, const char *find) {
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ c = tolower((unsigned char)c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return 0;
+ } while ((char)tolower((unsigned char)sc) != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+char *realpath(const char *name, char *resolved) {
+ char *retname = NULL;
+
+ /* SUSv3 says we must set `errno = EINVAL', and return NULL,
+ * if `name' is passed as a NULL pointer.
+ */
+ if (name == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
- /* Otherwise, `name' must refer to a readable filesystem object,
- * if we are going to resolve its absolute path name.
- */
- wchar_t wideNameBuffer[PATH_MAX];
- wchar_t *wideName = wideNameBuffer;
- if (!utf8ToWide(name, wideName, PATH_MAX))
- {
- errno = EINVAL;
- return NULL;
- }
+ /* Otherwise, `name' must refer to a readable filesystem object,
+ * if we are going to resolve its absolute path name.
+ */
+ wchar_t wideNameBuffer[PATH_MAX];
+ wchar_t *wideName = wideNameBuffer;
+ if (!utf8ToWide(name, wideName, PATH_MAX)) {
+ errno = EINVAL;
+ return NULL;
+ }
- if (_waccess(wideName, 4) != 0)
- return NULL;
+ if (_waccess(wideName, 4) != 0)
+ return NULL;
- /* If `name' didn't point to an existing entity,
- * then we don't get to here; we simply fall past this block,
- * returning NULL, with `errno' appropriately set by `access'.
+ /* If `name' didn't point to an existing entity,
+ * then we don't get to here; we simply fall past this block,
+ * returning NULL, with `errno' appropriately set by `access'.
+ *
+ * When we _do_ get to here, then we can use `_fullpath' to
+ * resolve the full path for `name' into `resolved', but first,
+ * check that we have a suitable buffer, in which to return it.
+ */
+
+ if ((retname = resolved) == NULL) {
+ /* Caller didn't give us a buffer, so we'll exercise the
+ * option granted by SUSv3, and allocate one.
*
- * When we _do_ get to here, then we can use `_fullpath' to
- * resolve the full path for `name' into `resolved', but first,
- * check that we have a suitable buffer, in which to return it.
- */
-
- if ((retname = resolved) == NULL)
- {
- /* Caller didn't give us a buffer, so we'll exercise the
- * option granted by SUSv3, and allocate one.
- *
- * `_fullpath' would do this for us, but it uses `malloc', and
- * Microsoft's implementation doesn't set `errno' on failure.
- * If we don't do this explicitly ourselves, then we will not
- * know if `_fullpath' fails on `malloc' failure, or for some
- * other reason, and we want to set `errno = ENOMEM' for the
- * `malloc' failure case.
- */
-
- retname = (char *)malloc(PATH_MAX);
- if (retname == NULL)
- {
- errno = ENOMEM;
- return NULL;
- }
- }
-
- /* Otherwise, when we do have a valid buffer,
- * `_fullpath' should only fail if the path name is too long.
+ * `_fullpath' would do this for us, but it uses `malloc', and
+ * Microsoft's implementation doesn't set `errno' on failure.
+ * If we don't do this explicitly ourselves, then we will not
+ * know if `_fullpath' fails on `malloc' failure, or for some
+ * other reason, and we want to set `errno = ENOMEM' for the
+ * `malloc' failure case.
*/
- wchar_t wideFullPathBuffer[PATH_MAX];
- wchar_t *wideFullPath;
- if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
- {
- errno = ENAMETOOLONG;
- return NULL;
- }
+ retname = (char *)malloc(PATH_MAX);
+ if (retname == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+
+ /* Otherwise, when we do have a valid buffer,
+ * `_fullpath' should only fail if the path name is too long.
+ */
+
+ wchar_t wideFullPathBuffer[PATH_MAX];
+ wchar_t *wideFullPath;
+ if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) ==
+ NULL) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
- // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
- // FIXME: Check for failure
- size_t initialLength = wcslen(wideFullPath);
- GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
- GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
-
- // Convert back to UTF-8
- if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
- {
- errno = EINVAL;
- return NULL;
- }
+ // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
+ // FIXME: Check for failure
+ size_t initialLength = wcslen(wideFullPath);
+ GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
+ GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
+
+ // Convert back to UTF-8
+ if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) {
+ errno = EINVAL;
+ return NULL;
+ }
- // Force drive to be upper case
- if (retname[1] == ':')
- retname[0] = toupper(retname[0]);
+ // Force drive to be upper case
+ if (retname[1] == ':')
+ retname[0] = toupper(retname[0]);
- return retname;
+ return retname;
}
#ifdef _MSC_VER
-char* basename(char *path)
-{
- char* l1 = strrchr(path, '\\');
- char* l2 = strrchr(path, '/');
- if (l2 > l1) l1 = l2;
- if (!l1) return path; // no base name
- return &l1[1];
+char *basename(char *path) {
+ char *l1 = strrchr(path, '\\');
+ char *l2 = strrchr(path, '/');
+ if (l2 > l1)
+ l1 = l2;
+ if (!l1)
+ return path; // no base name
+ return &l1[1];
}
// use _getcwd() instead of GetCurrentDirectory() because it updates errno
-char* getcwd(char* path, int max)
-{
- assert(path == NULL || max <= PATH_MAX);
- wchar_t wpath[PATH_MAX];
- if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX))
- {
- // Caller is allowed to pass in NULL for `path`.
- // In that case, we're supposed to allocate a
- // buffer on the caller's behalf.
- if (path == NULL)
- {
- max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
- path = (char *)malloc(max);
- if (path == NULL)
- {
- errno = ENOMEM;
- return NULL;
- }
- }
- if (wideToUtf8(wresult, path, max))
- return path;
+char *getcwd(char *path, int max) {
+ assert(path == NULL || max <= PATH_MAX);
+ wchar_t wpath[PATH_MAX];
+ if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX)) {
+ // Caller is allowed to pass in NULL for `path`.
+ // In that case, we're supposed to allocate a
+ // buffer on the caller's behalf.
+ if (path == NULL) {
+ max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
+ path = (char *)malloc(max);
+ if (path == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
}
- return NULL;
+ if (wideToUtf8(wresult, path, max))
+ return path;
+ }
+ return NULL;
}
// use _chdir() instead of SetCurrentDirectory() because it updates errno
-int chdir(const char* path)
-{
- return _chdir(path);
-}
+int chdir(const char *path) { return _chdir(path); }
-char *dirname(char *path)
-{
- char* l1 = strrchr(path, '\\');
- char* l2 = strrchr(path, '/');
- if (l2 > l1) l1 = l2;
- if (!l1) return NULL; // no dir name
- *l1 = 0;
- return path;
+char *dirname(char *path) {
+ char *l1 = strrchr(path, '\\');
+ char *l2 = strrchr(path, '/');
+ if (l2 > l1)
+ l1 = l2;
+ if (!l1)
+ return NULL; // no dir name
+ *l1 = 0;
+ return path;
}
-int strcasecmp(const char* s1, const char* s2)
-{
- return stricmp(s1, s2);
-}
+int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
-int strncasecmp(const char* s1, const char* s2, size_t n)
-{
- return strnicmp(s1, s2, n);
+int strncasecmp(const char *s1, const char *s2, size_t n) {
+ return strnicmp(s1, s2, n);
}
-int usleep(uint32_t useconds)
-{
- Sleep(useconds / 1000);
- return 0;
+int usleep(uint32_t useconds) {
+ Sleep(useconds / 1000);
+ return 0;
}
#if _MSC_VER < 1900
namespace lldb_private {
-int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
-{
- int old_errno = errno;
- int r = ::vsnprintf(buffer, count, format, argptr);
- int new_errno = errno;
- buffer[count-1] = '\0';
- if (r == -1 || r == count)
- {
- FILE *nul = fopen("nul", "w");
- int bytes_written = ::vfprintf(nul, format, argptr);
- fclose(nul);
- if (bytes_written < count)
- errno = new_errno;
- else
- {
- errno = old_errno;
- r = bytes_written;
- }
+int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) {
+ int old_errno = errno;
+ int r = ::vsnprintf(buffer, count, format, argptr);
+ int new_errno = errno;
+ buffer[count - 1] = '\0';
+ if (r == -1 || r == count) {
+ FILE *nul = fopen("nul", "w");
+ int bytes_written = ::vfprintf(nul, format, argptr);
+ fclose(nul);
+ if (bytes_written < count)
+ errno = new_errno;
+ else {
+ errno = old_errno;
+ r = bytes_written;
}
- return r;
+ }
+ return r;
}
} // namespace lldb_private
#endif
Modified: lldb/trunk/source/Initialization/SystemInitializer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializer.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Initialization/SystemInitializer.cpp (original)
+++ lldb/trunk/source/Initialization/SystemInitializer.cpp Tue Sep 6 15:57:50 2016
@@ -11,10 +11,6 @@
using namespace lldb_private;
-SystemInitializer::SystemInitializer()
-{
-}
+SystemInitializer::SystemInitializer() {}
-SystemInitializer::~SystemInitializer()
-{
-}
+SystemInitializer::~SystemInitializer() {}
Modified: lldb/trunk/source/Initialization/SystemInitializerCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializerCommon.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Initialization/SystemInitializerCommon.cpp (original)
+++ lldb/trunk/source/Initialization/SystemInitializerCommon.cpp Tue Sep 6 15:57:50 2016
@@ -9,10 +9,6 @@
#include "lldb/Initialization/SystemInitializerCommon.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Timer.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h"
#include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h"
@@ -21,6 +17,10 @@
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#if defined(__APPLE__)
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
@@ -41,98 +41,92 @@
using namespace lldb_private;
-static void
-fatal_error_handler(void *user_data, const std::string &reason, bool gen_crash_diag)
-{
- Host::SetCrashDescription(reason.c_str());
- ::abort();
+static void fatal_error_handler(void *user_data, const std::string &reason,
+ bool gen_crash_diag) {
+ Host::SetCrashDescription(reason.c_str());
+ ::abort();
}
-SystemInitializerCommon::SystemInitializerCommon()
-{
-}
+SystemInitializerCommon::SystemInitializerCommon() {}
-SystemInitializerCommon::~SystemInitializerCommon()
-{
-}
+SystemInitializerCommon::~SystemInitializerCommon() {}
-void
-SystemInitializerCommon::Initialize()
-{
+void SystemInitializerCommon::Initialize() {
#if defined(_MSC_VER)
- const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
- if (disable_crash_dialog_var && llvm::StringRef(disable_crash_dialog_var).equals_lower("true"))
- {
- // This will prevent Windows from displaying a dialog box requiring user interaction when
- // LLDB crashes. This is mostly useful when automating LLDB, for example via the test
- // suite, so that a crash in LLDB does not prevent completion of the test suite.
- ::SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
-
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- }
-#endif
-
- Log::Initialize();
- HostInfo::Initialize();
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-
- llvm::install_fatal_error_handler(fatal_error_handler, 0);
-
- process_gdb_remote::ProcessGDBRemoteLog::Initialize();
-
- // Initialize plug-ins
- ObjectContainerBSDArchive::Initialize();
- ObjectFileELF::Initialize();
- ObjectFilePECOFF::Initialize();
-
- EmulateInstructionARM::Initialize();
- EmulateInstructionMIPS::Initialize();
- EmulateInstructionMIPS64::Initialize();
-
- //----------------------------------------------------------------------
- // Apple/Darwin hosted plugins
- //----------------------------------------------------------------------
- ObjectContainerUniversalMachO::Initialize();
-
+ const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
+ if (disable_crash_dialog_var &&
+ llvm::StringRef(disable_crash_dialog_var).equals_lower("true")) {
+ // This will prevent Windows from displaying a dialog box requiring user
+ // interaction when
+ // LLDB crashes. This is mostly useful when automating LLDB, for example
+ // via the test
+ // suite, so that a crash in LLDB does not prevent completion of the test
+ // suite.
+ ::SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX);
+
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+ }
+#endif
+
+ Log::Initialize();
+ HostInfo::Initialize();
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ llvm::install_fatal_error_handler(fatal_error_handler, 0);
+
+ process_gdb_remote::ProcessGDBRemoteLog::Initialize();
+
+ // Initialize plug-ins
+ ObjectContainerBSDArchive::Initialize();
+ ObjectFileELF::Initialize();
+ ObjectFilePECOFF::Initialize();
+
+ EmulateInstructionARM::Initialize();
+ EmulateInstructionMIPS::Initialize();
+ EmulateInstructionMIPS64::Initialize();
+
+ //----------------------------------------------------------------------
+ // Apple/Darwin hosted plugins
+ //----------------------------------------------------------------------
+ ObjectContainerUniversalMachO::Initialize();
#if defined(__APPLE__)
- ObjectFileMachO::Initialize();
+ ObjectFileMachO::Initialize();
#endif
#if defined(__linux__)
- static ConstString g_linux_log_name("linux");
- ProcessPOSIXLog::Initialize(g_linux_log_name);
+ static ConstString g_linux_log_name("linux");
+ ProcessPOSIXLog::Initialize(g_linux_log_name);
#endif
#if defined(_MSC_VER)
- ProcessWindowsLog::Initialize();
+ ProcessWindowsLog::Initialize();
#endif
}
-void
-SystemInitializerCommon::Terminate()
-{
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
- ObjectContainerBSDArchive::Terminate();
- ObjectFileELF::Terminate();
- ObjectFilePECOFF::Terminate();
-
- EmulateInstructionARM::Terminate();
- EmulateInstructionMIPS::Terminate();
- EmulateInstructionMIPS64::Terminate();
+void SystemInitializerCommon::Terminate() {
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ ObjectContainerBSDArchive::Terminate();
+ ObjectFileELF::Terminate();
+ ObjectFilePECOFF::Terminate();
+
+ EmulateInstructionARM::Terminate();
+ EmulateInstructionMIPS::Terminate();
+ EmulateInstructionMIPS64::Terminate();
- ObjectContainerUniversalMachO::Terminate();
+ ObjectContainerUniversalMachO::Terminate();
#if defined(__APPLE__)
- ObjectFileMachO::Terminate();
+ ObjectFileMachO::Terminate();
#endif
#if defined(_MSC_VER)
- ProcessWindowsLog::Terminate();
+ ProcessWindowsLog::Terminate();
#endif
- HostInfo::Terminate();
- Log::Terminate();
+ HostInfo::Terminate();
+ Log::Terminate();
}
Modified: lldb/trunk/source/Initialization/SystemLifetimeManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemLifetimeManager.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Initialization/SystemLifetimeManager.cpp (original)
+++ lldb/trunk/source/Initialization/SystemLifetimeManager.cpp Tue Sep 6 15:57:50 2016
@@ -16,43 +16,38 @@
using namespace lldb_private;
-SystemLifetimeManager::SystemLifetimeManager() : m_mutex(), m_initialized(false)
-{
-}
+SystemLifetimeManager::SystemLifetimeManager()
+ : m_mutex(), m_initialized(false) {}
-SystemLifetimeManager::~SystemLifetimeManager()
-{
- assert(!m_initialized && "SystemLifetimeManager destroyed without calling Terminate!");
+SystemLifetimeManager::~SystemLifetimeManager() {
+ assert(!m_initialized &&
+ "SystemLifetimeManager destroyed without calling Terminate!");
}
-void
-SystemLifetimeManager::Initialize(std::unique_ptr<SystemInitializer> initializer,
- LoadPluginCallbackType plugin_callback)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (!m_initialized)
- {
- assert(!m_initializer &&
- "Attempting to call SystemLifetimeManager::Initialize() when it is already initialized");
- m_initialized = true;
- m_initializer = std::move(initializer);
-
- m_initializer->Initialize();
- Debugger::Initialize(plugin_callback);
- }
+void SystemLifetimeManager::Initialize(
+ std::unique_ptr<SystemInitializer> initializer,
+ LoadPluginCallbackType plugin_callback) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (!m_initialized) {
+ assert(!m_initializer && "Attempting to call "
+ "SystemLifetimeManager::Initialize() when it is "
+ "already initialized");
+ m_initialized = true;
+ m_initializer = std::move(initializer);
+
+ m_initializer->Initialize();
+ Debugger::Initialize(plugin_callback);
+ }
}
-void
-SystemLifetimeManager::Terminate()
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- if (m_initialized)
- {
- Debugger::Terminate();
- m_initializer->Terminate();
-
- m_initializer.reset();
- m_initialized = false;
- }
+void SystemLifetimeManager::Terminate() {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+ if (m_initialized) {
+ Debugger::Terminate();
+ m_initializer->Terminate();
+
+ m_initializer.reset();
+ m_initialized = false;
+ }
}
Modified: lldb/trunk/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Args.cpp (original)
+++ lldb/trunk/source/Interpreter/Args.cpp Tue Sep 6 15:57:50 2016
@@ -12,15 +12,15 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
@@ -33,1822 +33,1635 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// Args constructor
//----------------------------------------------------------------------
-Args::Args (llvm::StringRef command) :
- m_args(),
- m_argv(),
- m_args_quote_char()
-{
- SetCommandString (command);
+Args::Args(llvm::StringRef command) : m_args(), m_argv(), m_args_quote_char() {
+ SetCommandString(command);
}
-
//----------------------------------------------------------------------
// We have to be very careful on the copy constructor of this class
// to make sure we copy all of the string values, but we can't copy the
-// rhs.m_argv into m_argv since it will point to the "const char *" c
+// rhs.m_argv into m_argv since it will point to the "const char *" c
// strings in rhs.m_args. We need to copy the string list and update our
-// own m_argv appropriately.
+// own m_argv appropriately.
//----------------------------------------------------------------------
-Args::Args (const Args &rhs) :
- m_args (rhs.m_args),
- m_argv (),
- m_args_quote_char(rhs.m_args_quote_char)
-{
- UpdateArgvFromArgs();
+Args::Args(const Args &rhs)
+ : m_args(rhs.m_args), m_argv(), m_args_quote_char(rhs.m_args_quote_char) {
+ UpdateArgvFromArgs();
}
//----------------------------------------------------------------------
// We have to be very careful on the copy constructor of this class
// to make sure we copy all of the string values, but we can't copy the
-// rhs.m_argv into m_argv since it will point to the "const char *" c
+// rhs.m_argv into m_argv since it will point to the "const char *" c
// strings in rhs.m_args. We need to copy the string list and update our
-// own m_argv appropriately.
+// own m_argv appropriately.
//----------------------------------------------------------------------
-const Args &
-Args::operator= (const Args &rhs)
-{
- // Make sure we aren't assigning to self
- if (this != &rhs)
- {
- m_args = rhs.m_args;
- m_args_quote_char = rhs.m_args_quote_char;
- UpdateArgvFromArgs();
- }
- return *this;
+const Args &Args::operator=(const Args &rhs) {
+ // Make sure we aren't assigning to self
+ if (this != &rhs) {
+ m_args = rhs.m_args;
+ m_args_quote_char = rhs.m_args_quote_char;
+ UpdateArgvFromArgs();
+ }
+ return *this;
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-Args::~Args ()
-{
-}
+Args::~Args() {}
-void
-Args::Dump (Stream &s, const char *label_name) const
-{
- if (!label_name)
- return;
-
- const size_t argc = m_argv.size();
- for (size_t i=0; i<argc; ++i)
- {
- s.Indent();
- const char *arg_cstr = m_argv[i];
- if (arg_cstr)
- s.Printf("%s[%zi]=\"%s\"\n", label_name, i, arg_cstr);
- else
- s.Printf("%s[%zi]=NULL\n", label_name, i);
- }
- s.EOL();
-}
-
-bool
-Args::GetCommandString (std::string &command) const
-{
- command.clear();
- const size_t argc = GetArgumentCount();
- for (size_t i=0; i<argc; ++i)
- {
- if (i > 0)
- command += ' ';
- command += m_argv[i];
- }
- return argc > 0;
-}
-
-bool
-Args::GetQuotedCommandString (std::string &command) const
-{
- command.clear ();
- const size_t argc = GetArgumentCount();
- for (size_t i = 0; i < argc; ++i)
- {
- if (i > 0)
- command.append (1, ' ');
- char quote_char = GetArgumentQuoteCharAtIndex(i);
- if (quote_char)
- {
- command.append (1, quote_char);
- command.append (m_argv[i]);
- command.append (1, quote_char);
- }
- else
- command.append (m_argv[i]);
- }
- return argc > 0;
+void Args::Dump(Stream &s, const char *label_name) const {
+ if (!label_name)
+ return;
+
+ const size_t argc = m_argv.size();
+ for (size_t i = 0; i < argc; ++i) {
+ s.Indent();
+ const char *arg_cstr = m_argv[i];
+ if (arg_cstr)
+ s.Printf("%s[%zi]=\"%s\"\n", label_name, i, arg_cstr);
+ else
+ s.Printf("%s[%zi]=NULL\n", label_name, i);
+ }
+ s.EOL();
+}
+
+bool Args::GetCommandString(std::string &command) const {
+ command.clear();
+ const size_t argc = GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i) {
+ if (i > 0)
+ command += ' ';
+ command += m_argv[i];
+ }
+ return argc > 0;
+}
+
+bool Args::GetQuotedCommandString(std::string &command) const {
+ command.clear();
+ const size_t argc = GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i) {
+ if (i > 0)
+ command.append(1, ' ');
+ char quote_char = GetArgumentQuoteCharAtIndex(i);
+ if (quote_char) {
+ command.append(1, quote_char);
+ command.append(m_argv[i]);
+ command.append(1, quote_char);
+ } else
+ command.append(m_argv[i]);
+ }
+ return argc > 0;
}
// A helper function for argument parsing.
-// Parses the initial part of the first argument using normal double quote rules:
-// backslash escapes the double quote and itself. The parsed string is appended to the second
-// argument. The function returns the unparsed portion of the string, starting at the closing
+// Parses the initial part of the first argument using normal double quote
+// rules:
+// backslash escapes the double quote and itself. The parsed string is appended
+// to the second
+// argument. The function returns the unparsed portion of the string, starting
+// at the closing
// quote.
-static llvm::StringRef
-ParseDoubleQuotes(llvm::StringRef quoted, std::string &result)
-{
- // Inside double quotes, '\' and '"' are special.
- static const char *k_escapable_characters = "\"\\";
- while (true)
- {
- // Skip over over regular characters and append them.
- size_t regular = quoted.find_first_of(k_escapable_characters);
- result += quoted.substr(0, regular);
- quoted = quoted.substr(regular);
-
- // If we have reached the end of string or the closing quote, we're done.
- if (quoted.empty() || quoted.front() == '"')
- break;
-
- // We have found a backslash.
- quoted = quoted.drop_front();
-
- if (quoted.empty())
- {
- // A lone backslash at the end of string, let's just append it.
- result += '\\';
- break;
- }
-
- // If the character after the backslash is not a whitelisted escapable character, we
- // leave the character sequence untouched.
- if (strchr(k_escapable_characters, quoted.front()) == nullptr)
- result += '\\';
+static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
+ std::string &result) {
+ // Inside double quotes, '\' and '"' are special.
+ static const char *k_escapable_characters = "\"\\";
+ while (true) {
+ // Skip over over regular characters and append them.
+ size_t regular = quoted.find_first_of(k_escapable_characters);
+ result += quoted.substr(0, regular);
+ quoted = quoted.substr(regular);
+
+ // If we have reached the end of string or the closing quote, we're done.
+ if (quoted.empty() || quoted.front() == '"')
+ break;
+
+ // We have found a backslash.
+ quoted = quoted.drop_front();
+
+ if (quoted.empty()) {
+ // A lone backslash at the end of string, let's just append it.
+ result += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we
+ // leave the character sequence untouched.
+ if (strchr(k_escapable_characters, quoted.front()) == nullptr)
+ result += '\\';
+
+ result += quoted.front();
+ quoted = quoted.drop_front();
+ }
- result += quoted.front();
- quoted = quoted.drop_front();
- }
-
- return quoted;
+ return quoted;
}
// A helper function for SetCommandString.
-// Parses a single argument from the command string, processing quotes and backslashes in a
-// shell-like manner. The parsed argument is appended to the m_args array. The function returns
-// the unparsed portion of the string, starting at the first unqouted, unescaped whitespace
+// Parses a single argument from the command string, processing quotes and
+// backslashes in a
+// shell-like manner. The parsed argument is appended to the m_args array. The
+// function returns
+// the unparsed portion of the string, starting at the first unqouted, unescaped
+// whitespace
// character.
-llvm::StringRef
-Args::ParseSingleArgument(llvm::StringRef command)
-{
- // Argument can be split into multiple discontiguous pieces,
- // for example:
- // "Hello ""World"
- // this would result in a single argument "Hello World" (without/
- // the quotes) since the quotes would be removed and there is
- // not space between the strings.
-
- std::string arg;
-
- // Since we can have multiple quotes that form a single command
- // in a command like: "Hello "world'!' (which will make a single
- // argument "Hello world!") we remember the first quote character
- // we encounter and use that for the quote character.
- char first_quote_char = '\0';
-
- bool arg_complete = false;
- do
- {
- // Skip over over regular characters and append them.
- size_t regular = command.find_first_of(" \t\"'`\\");
- arg += command.substr(0, regular);
- command = command.substr(regular);
+llvm::StringRef Args::ParseSingleArgument(llvm::StringRef command) {
+ // Argument can be split into multiple discontiguous pieces,
+ // for example:
+ // "Hello ""World"
+ // this would result in a single argument "Hello World" (without/
+ // the quotes) since the quotes would be removed and there is
+ // not space between the strings.
+
+ std::string arg;
+
+ // Since we can have multiple quotes that form a single command
+ // in a command like: "Hello "world'!' (which will make a single
+ // argument "Hello world!") we remember the first quote character
+ // we encounter and use that for the quote character.
+ char first_quote_char = '\0';
+
+ bool arg_complete = false;
+ do {
+ // Skip over over regular characters and append them.
+ size_t regular = command.find_first_of(" \t\"'`\\");
+ arg += command.substr(0, regular);
+ command = command.substr(regular);
+
+ if (command.empty())
+ break;
+
+ char special = command.front();
+ command = command.drop_front();
+ switch (special) {
+ case '\\':
+ if (command.empty()) {
+ arg += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we
+ // leave the character sequence untouched.
+ if (strchr(" \t\\'\"`", command.front()) == nullptr)
+ arg += '\\';
+
+ arg += command.front();
+ command = command.drop_front();
+
+ break;
+
+ case ' ':
+ case '\t':
+ // We are not inside any quotes, we just found a space after an
+ // argument. We are done.
+ arg_complete = true;
+ break;
+
+ case '"':
+ case '\'':
+ case '`':
+ // We found the start of a quote scope.
+ if (first_quote_char == '\0')
+ first_quote_char = special;
+
+ if (special == '"')
+ command = ParseDoubleQuotes(command, arg);
+ else {
+ // For single quotes, we simply skip ahead to the matching quote
+ // character
+ // (or the end of the string).
+ size_t quoted = command.find(special);
+ arg += command.substr(0, quoted);
+ command = command.substr(quoted);
+ }
- if (command.empty())
- break;
-
- char special = command.front();
+ // If we found a closing quote, skip it.
+ if (!command.empty())
command = command.drop_front();
- switch (special)
- {
- case '\\':
- if (command.empty())
- {
- arg += '\\';
- break;
- }
-
- // If the character after the backslash is not a whitelisted escapable character, we
- // leave the character sequence untouched.
- if (strchr(" \t\\'\"`", command.front()) == nullptr)
- arg += '\\';
-
- arg += command.front();
- command = command.drop_front();
- break;
-
- case ' ':
- case '\t':
- // We are not inside any quotes, we just found a space after an
- // argument. We are done.
- arg_complete = true;
- break;
-
- case '"':
- case '\'':
- case '`':
- // We found the start of a quote scope.
- if (first_quote_char == '\0')
- first_quote_char = special;
-
- if (special == '"')
- command = ParseDoubleQuotes(command, arg);
- else
- {
- // For single quotes, we simply skip ahead to the matching quote character
- // (or the end of the string).
- size_t quoted = command.find(special);
- arg += command.substr(0, quoted);
- command = command.substr(quoted);
- }
-
- // If we found a closing quote, skip it.
- if (! command.empty())
- command = command.drop_front();
-
- break;
- }
- } while (!arg_complete);
-
- m_args.push_back(arg);
- m_args_quote_char.push_back (first_quote_char);
- return command;
-}
-
-void
-Args::SetCommandString (llvm::StringRef command)
-{
- m_args.clear();
- m_argv.clear();
- m_args_quote_char.clear();
-
- static const char *k_space_separators = " \t";
- command = command.ltrim(k_space_separators);
- while (!command.empty())
- {
- command = ParseSingleArgument(command);
- command = command.ltrim(k_space_separators);
+ break;
}
+ } while (!arg_complete);
- UpdateArgvFromArgs();
+ m_args.push_back(arg);
+ m_args_quote_char.push_back(first_quote_char);
+ return command;
}
-void
-Args::UpdateArgsAfterOptionParsing()
-{
- // Now m_argv might be out of date with m_args, so we need to fix that
- arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
- arg_sstr_collection::iterator args_pos;
- arg_quote_char_collection::iterator quotes_pos;
-
- for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
- argv_pos != argv_end && args_pos != m_args.end();
- ++argv_pos)
- {
- const char *argv_cstr = *argv_pos;
- if (argv_cstr == nullptr)
- break;
-
- while (args_pos != m_args.end())
- {
- const char *args_cstr = args_pos->c_str();
- if (args_cstr == argv_cstr)
- {
- // We found the argument that matches the C string in the
- // vector, so we can now look for the next one
- ++args_pos;
- ++quotes_pos;
- break;
- }
- else
- {
- quotes_pos = m_args_quote_char.erase (quotes_pos);
- args_pos = m_args.erase (args_pos);
- }
- }
- }
+void Args::SetCommandString(llvm::StringRef command) {
+ m_args.clear();
+ m_argv.clear();
+ m_args_quote_char.clear();
- if (args_pos != m_args.end())
- m_args.erase (args_pos, m_args.end());
+ static const char *k_space_separators = " \t";
+ command = command.ltrim(k_space_separators);
+ while (!command.empty()) {
+ command = ParseSingleArgument(command);
+ command = command.ltrim(k_space_separators);
+ }
- if (quotes_pos != m_args_quote_char.end())
- m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
+ UpdateArgvFromArgs();
}
-void
-Args::UpdateArgvFromArgs()
-{
- m_argv.clear();
- arg_sstr_collection::const_iterator pos, end = m_args.end();
- for (pos = m_args.begin(); pos != end; ++pos)
- m_argv.push_back(pos->c_str());
- m_argv.push_back(nullptr);
- // Make sure we have enough arg quote chars in the array
- if (m_args_quote_char.size() < m_args.size())
- m_args_quote_char.resize (m_argv.size());
-}
-
-size_t
-Args::GetArgumentCount() const
-{
- if (m_argv.empty())
- return 0;
- return m_argv.size() - 1;
-}
-
-const char *
-Args::GetArgumentAtIndex (size_t idx) const
-{
- if (idx < m_argv.size())
- return m_argv[idx];
- return nullptr;
+void Args::UpdateArgsAfterOptionParsing() {
+ // Now m_argv might be out of date with m_args, so we need to fix that
+ arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
+ arg_sstr_collection::iterator args_pos;
+ arg_quote_char_collection::iterator quotes_pos;
+
+ for (argv_pos = m_argv.begin(), args_pos = m_args.begin(),
+ quotes_pos = m_args_quote_char.begin();
+ argv_pos != argv_end && args_pos != m_args.end(); ++argv_pos) {
+ const char *argv_cstr = *argv_pos;
+ if (argv_cstr == nullptr)
+ break;
+
+ while (args_pos != m_args.end()) {
+ const char *args_cstr = args_pos->c_str();
+ if (args_cstr == argv_cstr) {
+ // We found the argument that matches the C string in the
+ // vector, so we can now look for the next one
+ ++args_pos;
+ ++quotes_pos;
+ break;
+ } else {
+ quotes_pos = m_args_quote_char.erase(quotes_pos);
+ args_pos = m_args.erase(args_pos);
+ }
+ }
+ }
+
+ if (args_pos != m_args.end())
+ m_args.erase(args_pos, m_args.end());
+
+ if (quotes_pos != m_args_quote_char.end())
+ m_args_quote_char.erase(quotes_pos, m_args_quote_char.end());
+}
+
+void Args::UpdateArgvFromArgs() {
+ m_argv.clear();
+ arg_sstr_collection::const_iterator pos, end = m_args.end();
+ for (pos = m_args.begin(); pos != end; ++pos)
+ m_argv.push_back(pos->c_str());
+ m_argv.push_back(nullptr);
+ // Make sure we have enough arg quote chars in the array
+ if (m_args_quote_char.size() < m_args.size())
+ m_args_quote_char.resize(m_argv.size());
+}
+
+size_t Args::GetArgumentCount() const {
+ if (m_argv.empty())
+ return 0;
+ return m_argv.size() - 1;
+}
+
+const char *Args::GetArgumentAtIndex(size_t idx) const {
+ if (idx < m_argv.size())
+ return m_argv[idx];
+ return nullptr;
+}
+
+char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
+ if (idx < m_args_quote_char.size())
+ return m_args_quote_char[idx];
+ return '\0';
+}
+
+char **Args::GetArgumentVector() {
+ if (!m_argv.empty())
+ return const_cast<char **>(&m_argv[0]);
+ return nullptr;
+}
+
+const char **Args::GetConstArgumentVector() const {
+ if (!m_argv.empty())
+ return const_cast<const char **>(&m_argv[0]);
+ return nullptr;
+}
+
+void Args::Shift() {
+ // Don't pop the last NULL terminator from the argv array
+ if (m_argv.size() > 1) {
+ m_argv.erase(m_argv.begin());
+ m_args.pop_front();
+ if (!m_args_quote_char.empty())
+ m_args_quote_char.erase(m_args_quote_char.begin());
+ }
+}
+
+const char *Args::Unshift(const char *arg_cstr, char quote_char) {
+ m_args.push_front(arg_cstr);
+ m_argv.insert(m_argv.begin(), m_args.front().c_str());
+ m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
+ return GetArgumentAtIndex(0);
+}
+
+void Args::AppendArguments(const Args &rhs) {
+ const size_t rhs_argc = rhs.GetArgumentCount();
+ for (size_t i = 0; i < rhs_argc; ++i)
+ AppendArgument(rhs.GetArgumentAtIndex(i),
+ rhs.GetArgumentQuoteCharAtIndex(i));
+}
+
+void Args::AppendArguments(const char **argv) {
+ if (argv) {
+ for (uint32_t i = 0; argv[i]; ++i)
+ AppendArgument(argv[i]);
+ }
+}
+
+const char *Args::AppendArgument(const char *arg_cstr, char quote_char) {
+ return InsertArgumentAtIndex(GetArgumentCount(), arg_cstr, quote_char);
+}
+
+const char *Args::InsertArgumentAtIndex(size_t idx, const char *arg_cstr,
+ char quote_char) {
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ pos = m_args.insert(pos, arg_cstr);
+
+ if (idx >= m_args_quote_char.size()) {
+ m_args_quote_char.resize(idx + 1);
+ m_args_quote_char[idx] = quote_char;
+ } else
+ m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
+
+ UpdateArgvFromArgs();
+ return GetArgumentAtIndex(idx);
+}
+
+const char *Args::ReplaceArgumentAtIndex(size_t idx, const char *arg_cstr,
+ char quote_char) {
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ if (pos != end) {
+ pos->assign(arg_cstr);
+ assert(idx < m_argv.size() - 1);
+ m_argv[idx] = pos->c_str();
+ if (idx >= m_args_quote_char.size())
+ m_args_quote_char.resize(idx + 1);
+ m_args_quote_char[idx] = quote_char;
+ return GetArgumentAtIndex(idx);
+ }
+ return nullptr;
}
-char
-Args::GetArgumentQuoteCharAtIndex (size_t idx) const
-{
+void Args::DeleteArgumentAtIndex(size_t idx) {
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ if (pos != end) {
+ m_args.erase(pos);
+ assert(idx < m_argv.size() - 1);
+ m_argv.erase(m_argv.begin() + idx);
if (idx < m_args_quote_char.size())
- return m_args_quote_char[idx];
- return '\0';
-}
-
-char **
-Args::GetArgumentVector()
-{
- if (!m_argv.empty())
- return const_cast<char **>(&m_argv[0]);
- return nullptr;
-}
-
-const char **
-Args::GetConstArgumentVector() const
-{
- if (!m_argv.empty())
- return const_cast<const char **>(&m_argv[0]);
- return nullptr;
-}
-
-void
-Args::Shift ()
-{
- // Don't pop the last NULL terminator from the argv array
- if (m_argv.size() > 1)
- {
- m_argv.erase(m_argv.begin());
- m_args.pop_front();
- if (!m_args_quote_char.empty())
- m_args_quote_char.erase(m_args_quote_char.begin());
- }
+ m_args_quote_char.erase(m_args_quote_char.begin() + idx);
+ }
}
-const char *
-Args::Unshift (const char *arg_cstr, char quote_char)
-{
- m_args.push_front(arg_cstr);
- m_argv.insert(m_argv.begin(), m_args.front().c_str());
- m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
- return GetArgumentAtIndex (0);
-}
-
-void
-Args::AppendArguments (const Args &rhs)
-{
- const size_t rhs_argc = rhs.GetArgumentCount();
- for (size_t i=0; i<rhs_argc; ++i)
- AppendArgument(rhs.GetArgumentAtIndex(i),
- rhs.GetArgumentQuoteCharAtIndex(i));
-}
-
-void
-Args::AppendArguments (const char **argv)
-{
- if (argv)
- {
- for (uint32_t i=0; argv[i]; ++i)
- AppendArgument(argv[i]);
- }
-}
-
-const char *
-Args::AppendArgument (const char *arg_cstr, char quote_char)
-{
- return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
-}
-
-const char *
-Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
-{
- // Since we are using a std::list to hold onto the copied C string and
- // we don't have direct access to the elements, we have to iterate to
- // find the value.
- arg_sstr_collection::iterator pos, end = m_args.end();
- size_t i = idx;
- for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
- --i;
-
- pos = m_args.insert(pos, arg_cstr);
-
- if (idx >= m_args_quote_char.size())
- {
- m_args_quote_char.resize(idx + 1);
- m_args_quote_char[idx] = quote_char;
- }
+void Args::SetArguments(size_t argc, const char **argv) {
+ // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
+ // no need to clear it here.
+ m_args.clear();
+ m_args_quote_char.clear();
+
+ // First copy each string
+ for (size_t i = 0; i < argc; ++i) {
+ m_args.push_back(argv[i]);
+ if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
+ m_args_quote_char.push_back(argv[i][0]);
else
- m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
-
- UpdateArgvFromArgs();
- return GetArgumentAtIndex(idx);
-}
-
-const char *
-Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
-{
- // Since we are using a std::list to hold onto the copied C string and
- // we don't have direct access to the elements, we have to iterate to
- // find the value.
- arg_sstr_collection::iterator pos, end = m_args.end();
- size_t i = idx;
- for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
- --i;
-
- if (pos != end)
- {
- pos->assign(arg_cstr);
- assert(idx < m_argv.size() - 1);
- m_argv[idx] = pos->c_str();
- if (idx >= m_args_quote_char.size())
- m_args_quote_char.resize(idx + 1);
- m_args_quote_char[idx] = quote_char;
- return GetArgumentAtIndex(idx);
- }
- return nullptr;
-}
+ m_args_quote_char.push_back('\0');
+ }
-void
-Args::DeleteArgumentAtIndex (size_t idx)
-{
- // Since we are using a std::list to hold onto the copied C string and
- // we don't have direct access to the elements, we have to iterate to
- // find the value.
- arg_sstr_collection::iterator pos, end = m_args.end();
- size_t i = idx;
- for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
- --i;
-
- if (pos != end)
- {
- m_args.erase (pos);
- assert(idx < m_argv.size() - 1);
- m_argv.erase(m_argv.begin() + idx);
- if (idx < m_args_quote_char.size())
- m_args_quote_char.erase(m_args_quote_char.begin() + idx);
- }
+ UpdateArgvFromArgs();
}
-void
-Args::SetArguments (size_t argc, const char **argv)
-{
- // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
- // no need to clear it here.
- m_args.clear();
- m_args_quote_char.clear();
+void Args::SetArguments(const char **argv) {
+ // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
+ // no need to clear it here.
+ m_args.clear();
+ m_args_quote_char.clear();
+ if (argv) {
// First copy each string
- for (size_t i=0; i<argc; ++i)
- {
- m_args.push_back (argv[i]);
- if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
- m_args_quote_char.push_back (argv[i][0]);
- else
- m_args_quote_char.push_back ('\0');
- }
-
- UpdateArgvFromArgs();
-}
-
-void
-Args::SetArguments (const char **argv)
-{
- // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
- // no need to clear it here.
- m_args.clear();
- m_args_quote_char.clear();
-
- if (argv)
- {
- // First copy each string
- for (size_t i=0; argv[i]; ++i)
- {
- m_args.push_back (argv[i]);
- if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
- m_args_quote_char.push_back (argv[i][0]);
- else
- m_args_quote_char.push_back ('\0');
- }
- }
-
- UpdateArgvFromArgs();
-}
-
+ for (size_t i = 0; argv[i]; ++i) {
+ m_args.push_back(argv[i]);
+ if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
+ m_args_quote_char.push_back(argv[i][0]);
+ else
+ m_args_quote_char.push_back('\0');
+ }
+ }
+
+ UpdateArgvFromArgs();
+}
+
+Error Args::ParseOptions(Options &options, ExecutionContext *execution_context,
+ PlatformSP platform_sp, bool require_validation) {
+ StreamString sstr;
+ Error error;
+ Option *long_options = options.GetLongOptions();
+ if (long_options == nullptr) {
+ error.SetErrorStringWithFormat("invalid long options");
+ return error;
+ }
-Error
-Args::ParseOptions (Options &options, ExecutionContext *execution_context,
- PlatformSP platform_sp, bool require_validation)
-{
- StreamString sstr;
- Error error;
- Option *long_options = options.GetLongOptions();
- if (long_options == nullptr)
- {
- error.SetErrorStringWithFormat("invalid long options");
+ for (int i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ if (isprint8(long_options[i].val)) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ':';
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+ }
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ int val;
+ while (1) {
+ int long_options_index = -1;
+ val =
+ OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
+ sstr.GetData(), long_options, &long_options_index);
+ if (val == -1)
+ break;
+
+ // Did we get an error?
+ if (val == '?') {
+ error.SetErrorStringWithFormat("unknown or ambiguous option");
+ break;
+ }
+ // The option auto-set itself
+ if (val == 0)
+ continue;
+
+ ((Options *)&options)->OptionSeen(val);
+
+ // Lookup the long option index
+ if (long_options_index == -1) {
+ for (int i = 0; long_options[i].definition || long_options[i].flag ||
+ long_options[i].val;
+ ++i) {
+ if (long_options[i].val == val) {
+ long_options_index = i;
+ break;
+ }
+ }
+ }
+ // Call the callback with the option
+ if (long_options_index >= 0 &&
+ long_options[long_options_index].definition) {
+ const OptionDefinition *def = long_options[long_options_index].definition;
+
+ if (!platform_sp) {
+ // User did not pass in an explicit platform. Try to grab
+ // from the execution context.
+ TargetSP target_sp =
+ execution_context ? execution_context->GetTargetSP() : TargetSP();
+ platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
+ }
+ OptionValidator *validator = def->validator;
+
+ if (!platform_sp && require_validation) {
+ // Caller requires validation but we cannot validate as we
+ // don't have the mandatory platform against which to
+ // validate.
+ error.SetErrorString("cannot validate options: "
+ "no platform available");
return error;
- }
+ }
- for (int i=0; long_options[i].definition != nullptr; ++i)
- {
- if (long_options[i].flag == nullptr)
- {
- if (isprint8(long_options[i].val))
- {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg)
- {
- default:
- case OptionParser::eNoArgument: break;
- case OptionParser::eRequiredArgument: sstr << ':'; break;
- case OptionParser::eOptionalArgument: sstr << "::"; break;
- }
- }
- }
- }
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- int val;
- while (1)
- {
- int long_options_index = -1;
- val = OptionParser::Parse(GetArgumentCount(),
- GetArgumentVector(),
- sstr.GetData(),
- long_options,
- &long_options_index);
- if (val == -1)
- break;
-
- // Did we get an error?
- if (val == '?')
- {
- error.SetErrorStringWithFormat("unknown or ambiguous option");
- break;
- }
- // The option auto-set itself
- if (val == 0)
- continue;
-
- ((Options *) &options)->OptionSeen (val);
-
- // Lookup the long option index
- if (long_options_index == -1)
- {
- for (int i=0;
- long_options[i].definition || long_options[i].flag || long_options[i].val;
- ++i)
- {
- if (long_options[i].val == val)
- {
- long_options_index = i;
- break;
- }
- }
- }
- // Call the callback with the option
- if (long_options_index >= 0 && long_options[long_options_index].definition)
- {
- const OptionDefinition *def = long_options[long_options_index].definition;
-
- if (!platform_sp)
- {
- // User did not pass in an explicit platform. Try to grab
- // from the execution context.
- TargetSP target_sp = execution_context ?
- execution_context->GetTargetSP() : TargetSP();
- platform_sp = target_sp ?
- target_sp->GetPlatform() : PlatformSP();
- }
- OptionValidator *validator = def->validator;
-
- if (!platform_sp && require_validation)
- {
- // Caller requires validation but we cannot validate as we
- // don't have the mandatory platform against which to
- // validate.
- error.SetErrorString("cannot validate options: "
- "no platform available");
- return error;
- }
-
- bool validation_failed = false;
- if (platform_sp)
- {
- // Ensure we have an execution context, empty or not.
- ExecutionContext dummy_context;
- ExecutionContext *exe_ctx_p =
- execution_context ? execution_context : &dummy_context;
- if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p))
- {
- validation_failed = true;
- error.SetErrorStringWithFormat("Option \"%s\" invalid. %s", def->long_option, def->validator->LongConditionString());
- }
- }
-
- // As long as validation didn't fail, we set the option value.
- if (!validation_failed)
- error = options.SetOptionValue(long_options_index,
- (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument(),
- execution_context);
- }
- else
- {
- error.SetErrorStringWithFormat("invalid option with value '%i'", val);
- }
- if (error.Fail())
- break;
- }
-
- // Update our ARGV now that get options has consumed all the options
- m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
- UpdateArgsAfterOptionParsing ();
- return error;
-}
-
-void
-Args::Clear ()
-{
- m_args.clear ();
- m_argv.clear ();
- m_args_quote_char.clear();
-}
-
-lldb::addr_t
-Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
-{
- bool error_set = false;
- if (s && s[0])
- {
- char *end = nullptr;
- lldb::addr_t addr = ::strtoull (s, &end, 0);
- if (*end == '\0')
- {
- if (error_ptr)
- error_ptr->Clear();
- return addr; // All characters were used, return the result
- }
- // Try base 16 with no prefix...
- addr = ::strtoull (s, &end, 16);
- if (*end == '\0')
- {
+ bool validation_failed = false;
+ if (platform_sp) {
+ // Ensure we have an execution context, empty or not.
+ ExecutionContext dummy_context;
+ ExecutionContext *exe_ctx_p =
+ execution_context ? execution_context : &dummy_context;
+ if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
+ validation_failed = true;
+ error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
+ def->long_option,
+ def->validator->LongConditionString());
+ }
+ }
+
+ // As long as validation didn't fail, we set the option value.
+ if (!validation_failed)
+ error = options.SetOptionValue(
+ long_options_index,
+ (def->option_has_arg == OptionParser::eNoArgument)
+ ? nullptr
+ : OptionParser::GetOptionArgument(),
+ execution_context);
+ } else {
+ error.SetErrorStringWithFormat("invalid option with value '%i'", val);
+ }
+ if (error.Fail())
+ break;
+ }
+
+ // Update our ARGV now that get options has consumed all the options
+ m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
+ UpdateArgsAfterOptionParsing();
+ return error;
+}
+
+void Args::Clear() {
+ m_args.clear();
+ m_argv.clear();
+ m_args_quote_char.clear();
+}
+
+lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx,
+ const char *s, lldb::addr_t fail_value,
+ Error *error_ptr) {
+ bool error_set = false;
+ if (s && s[0]) {
+ char *end = nullptr;
+ lldb::addr_t addr = ::strtoull(s, &end, 0);
+ if (*end == '\0') {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr; // All characters were used, return the result
+ }
+ // Try base 16 with no prefix...
+ addr = ::strtoull(s, &end, 16);
+ if (*end == '\0') {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr; // All characters were used, return the result
+ }
+
+ if (exe_ctx) {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target) {
+ lldb::ValueObjectSP valobj_sp;
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+
+ ExpressionResults expr_result = target->EvaluateExpression(
+ s, exe_ctx->GetFramePtr(), valobj_sp, options);
+
+ bool success = false;
+ if (expr_result == eExpressionCompleted) {
+ if (valobj_sp)
+ valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
+ valobj_sp->GetDynamicValueType(), true);
+ // Get the address to watch.
+ if (valobj_sp)
+ addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
+ if (success) {
if (error_ptr)
- error_ptr->Clear();
- return addr; // All characters were used, return the result
- }
-
- if (exe_ctx)
- {
- Target *target = exe_ctx->GetTargetPtr();
- if (target)
- {
- lldb::ValueObjectSP valobj_sp;
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(false);
- options.SetTryAllThreads(true);
-
- ExpressionResults expr_result = target->EvaluateExpression(s,
- exe_ctx->GetFramePtr(),
- valobj_sp,
- options);
-
- bool success = false;
- if (expr_result == eExpressionCompleted)
- {
- if (valobj_sp)
- valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(valobj_sp->GetDynamicValueType(), true);
- // Get the address to watch.
- if (valobj_sp)
- addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
- if (success)
- {
- if (error_ptr)
- error_ptr->Clear();
- return addr;
- }
- else
- {
- if (error_ptr)
- {
- error_set = true;
- error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString());
- }
- }
-
- }
- else
- {
- // Since the compiler can't handle things like "main + 12" we should
- // try to do this for now. The compiler doesn't like adding offsets
- // to function pointer types.
- static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
- RegularExpression::Match regex_match(3);
- if (g_symbol_plus_offset_regex.Execute(s, ®ex_match))
- {
- uint64_t offset = 0;
- bool add = true;
- std::string name;
- std::string str;
- if (regex_match.GetMatchAtIndex(s, 1, name))
- {
- if (regex_match.GetMatchAtIndex(s, 2, str))
- {
- add = str[0] == '+';
-
- if (regex_match.GetMatchAtIndex(s, 3, str))
- {
- offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success);
-
- if (success)
- {
- Error error;
- addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
- if (addr != LLDB_INVALID_ADDRESS)
- {
- if (add)
- return addr + offset;
- else
- return addr - offset;
- }
- }
- }
- }
- }
- }
-
- if (error_ptr)
- {
- error_set = true;
- error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
+ error_ptr->Clear();
+ return addr;
+ } else {
+ if (error_ptr) {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat(
+ "address expression \"%s\" resulted in a value whose type "
+ "can't be converted to an address: %s",
+ s, valobj_sp->GetTypeName().GetCString());
+ }
+ }
+
+ } else {
+ // Since the compiler can't handle things like "main + 12" we should
+ // try to do this for now. The compiler doesn't like adding offsets
+ // to function pointer types.
+ static RegularExpression g_symbol_plus_offset_regex(
+ "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
+ RegularExpression::Match regex_match(3);
+ if (g_symbol_plus_offset_regex.Execute(s, ®ex_match)) {
+ uint64_t offset = 0;
+ bool add = true;
+ std::string name;
+ std::string str;
+ if (regex_match.GetMatchAtIndex(s, 1, name)) {
+ if (regex_match.GetMatchAtIndex(s, 2, str)) {
+ add = str[0] == '+';
+
+ if (regex_match.GetMatchAtIndex(s, 3, str)) {
+ offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success);
+
+ if (success) {
+ Error error;
+ addr = StringToAddress(exe_ctx, name.c_str(),
+ LLDB_INVALID_ADDRESS, &error);
+ if (addr != LLDB_INVALID_ADDRESS) {
+ if (add)
+ return addr + offset;
+ else
+ return addr - offset;
}
+ }
}
+ }
}
- }
- }
- if (error_ptr)
- {
- if (!error_set)
- error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
- }
- return fail_value;
-}
-
-const char *
-Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
-{
- static const char *k_white_space = " \t\v";
- if (!s.empty())
- {
- if (leading)
- {
- size_t pos = s.find_first_not_of (k_white_space);
- if (pos == std::string::npos)
- s.clear();
- else if (pos > 0)
- s.erase(0, pos);
- }
-
- if (trailing)
- {
- size_t rpos = s.find_last_not_of(k_white_space);
- if (rpos != std::string::npos && rpos + 1 < s.size())
- s.erase(rpos + 1);
- }
- }
- if (return_null_if_empty && s.empty())
- return nullptr;
- return s.c_str();
-}
-
-bool
-Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
-{
- if (!s)
- return fail_value;
- return Args::StringToBoolean(llvm::StringRef(s), fail_value, success_ptr);
-}
-
-bool
-Args::StringToBoolean(llvm::StringRef ref, bool fail_value, bool *success_ptr)
-{
- ref = ref.trim();
- if (ref.equals_lower("false") ||
- ref.equals_lower("off") ||
- ref.equals_lower("no") ||
- ref.equals_lower("0"))
- {
- if (success_ptr)
- *success_ptr = true;
- return false;
- }
- else if (ref.equals_lower("true") || ref.equals_lower("on") || ref.equals_lower("yes") || ref.equals_lower("1"))
- {
- if (success_ptr)
- *success_ptr = true;
- return true;
- }
- if (success_ptr) *success_ptr = false;
- return fail_value;
-}
+ }
-char
-Args::StringToChar(const char *s, char fail_value, bool *success_ptr)
-{
- bool success = false;
- char result = fail_value;
-
- if (s)
- {
- size_t length = strlen(s);
- if (length == 1)
- {
- success = true;
- result = s[0];
- }
- }
- if (success_ptr)
- *success_ptr = success;
- return result;
-}
-
-const char *
-Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
-{
- major = UINT32_MAX;
- minor = UINT32_MAX;
- update = UINT32_MAX;
-
- if (s && s[0])
- {
- char *pos = nullptr;
- unsigned long uval32 = ::strtoul (s, &pos, 0);
- if (pos == s)
- return s;
- major = uval32;
- if (*pos == '\0')
- {
- return pos; // Decoded major and got end of string
- }
- else if (*pos == '.')
- {
- const char *minor_cstr = pos + 1;
- uval32 = ::strtoul (minor_cstr, &pos, 0);
- if (pos == minor_cstr)
- return pos; // Didn't get any digits for the minor version...
- minor = uval32;
- if (*pos == '.')
- {
- const char *update_cstr = pos + 1;
- uval32 = ::strtoul (update_cstr, &pos, 0);
- if (pos == update_cstr)
- return pos;
- update = uval32;
- }
- return pos;
- }
+ if (error_ptr) {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat(
+ "address expression \"%s\" evaluation failed", s);
+ }
+ }
+ }
+ }
+ }
+ if (error_ptr) {
+ if (!error_set)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
+ s);
+ }
+ return fail_value;
+}
+
+const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
+ bool return_null_if_empty) {
+ static const char *k_white_space = " \t\v";
+ if (!s.empty()) {
+ if (leading) {
+ size_t pos = s.find_first_not_of(k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos > 0)
+ s.erase(0, pos);
+ }
+
+ if (trailing) {
+ size_t rpos = s.find_last_not_of(k_white_space);
+ if (rpos != std::string::npos && rpos + 1 < s.size())
+ s.erase(rpos + 1);
}
+ }
+ if (return_null_if_empty && s.empty())
return nullptr;
+ return s.c_str();
}
-const char *
-Args::GetShellSafeArgument (const FileSpec& shell,
- const char *unsafe_arg,
- std::string &safe_arg)
-{
- struct ShellDescriptor
- {
- ConstString m_basename;
- const char* m_escapables;
- };
-
- static ShellDescriptor g_Shells[] = {
- {ConstString("bash")," '\"<>()&"},
- {ConstString("tcsh")," '\"<>()&$"},
- {ConstString("sh")," '\"<>()&"}
- };
-
- // safe minimal set
- const char* escapables = " '\"";
-
- if (auto basename = shell.GetFilename())
- {
- for (const auto& Shell : g_Shells)
- {
- if (Shell.m_basename == basename)
- {
- escapables = Shell.m_escapables;
- break;
- }
- }
- }
-
- safe_arg.assign (unsafe_arg);
- size_t prev_pos = 0;
- while (prev_pos < safe_arg.size())
- {
- // Escape spaces and quotes
- size_t pos = safe_arg.find_first_of(escapables, prev_pos);
- if (pos != std::string::npos)
- {
- safe_arg.insert (pos, 1, '\\');
- prev_pos = pos + 2;
- }
- else
- break;
- }
- return safe_arg.c_str();
-}
-
-int64_t
-Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
-{
- if (enum_values)
- {
- if (s && s[0])
- {
- for (int i = 0; enum_values[i].string_value != nullptr ; i++)
- {
- if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
- {
- error.Clear();
- return enum_values[i].value;
- }
- }
- }
-
- StreamString strm;
- strm.PutCString ("invalid enumeration value, valid values are: ");
- for (int i = 0; enum_values[i].string_value != nullptr; i++)
- {
- strm.Printf ("%s\"%s\"",
- i > 0 ? ", " : "",
- enum_values[i].string_value);
- }
- error.SetErrorString(strm.GetData());
- }
- else
- {
- error.SetErrorString ("invalid enumeration argument");
- }
+bool Args::StringToBoolean(const char *s, bool fail_value, bool *success_ptr) {
+ if (!s)
return fail_value;
+ return Args::StringToBoolean(llvm::StringRef(s), fail_value, success_ptr);
}
-ScriptLanguage
-Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
-{
- if (s && s[0])
- {
- if ((::strcasecmp (s, "python") == 0) ||
- (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
- {
- if (success_ptr) *success_ptr = true;
- return eScriptLanguagePython;
- }
- if (::strcasecmp (s, "none"))
- {
- if (success_ptr) *success_ptr = true;
- return eScriptLanguageNone;
- }
- }
- if (success_ptr) *success_ptr = false;
+bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value,
+ bool *success_ptr) {
+ ref = ref.trim();
+ if (ref.equals_lower("false") || ref.equals_lower("off") ||
+ ref.equals_lower("no") || ref.equals_lower("0")) {
+ if (success_ptr)
+ *success_ptr = true;
+ return false;
+ } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
+ ref.equals_lower("yes") || ref.equals_lower("1")) {
+ if (success_ptr)
+ *success_ptr = true;
+ return true;
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+char Args::StringToChar(const char *s, char fail_value, bool *success_ptr) {
+ bool success = false;
+ char result = fail_value;
+
+ if (s) {
+ size_t length = strlen(s);
+ if (length == 1) {
+ success = true;
+ result = s[0];
+ }
+ }
+ if (success_ptr)
+ *success_ptr = success;
+ return result;
+}
+
+const char *Args::StringToVersion(const char *s, uint32_t &major,
+ uint32_t &minor, uint32_t &update) {
+ major = UINT32_MAX;
+ minor = UINT32_MAX;
+ update = UINT32_MAX;
+
+ if (s && s[0]) {
+ char *pos = nullptr;
+ unsigned long uval32 = ::strtoul(s, &pos, 0);
+ if (pos == s)
+ return s;
+ major = uval32;
+ if (*pos == '\0') {
+ return pos; // Decoded major and got end of string
+ } else if (*pos == '.') {
+ const char *minor_cstr = pos + 1;
+ uval32 = ::strtoul(minor_cstr, &pos, 0);
+ if (pos == minor_cstr)
+ return pos; // Didn't get any digits for the minor version...
+ minor = uval32;
+ if (*pos == '.') {
+ const char *update_cstr = pos + 1;
+ uval32 = ::strtoul(update_cstr, &pos, 0);
+ if (pos == update_cstr)
+ return pos;
+ update = uval32;
+ }
+ return pos;
+ }
+ }
+ return nullptr;
+}
+
+const char *Args::GetShellSafeArgument(const FileSpec &shell,
+ const char *unsafe_arg,
+ std::string &safe_arg) {
+ struct ShellDescriptor {
+ ConstString m_basename;
+ const char *m_escapables;
+ };
+
+ static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
+ {ConstString("tcsh"), " '\"<>()&$"},
+ {ConstString("sh"), " '\"<>()&"}};
+
+ // safe minimal set
+ const char *escapables = " '\"";
+
+ if (auto basename = shell.GetFilename()) {
+ for (const auto &Shell : g_Shells) {
+ if (Shell.m_basename == basename) {
+ escapables = Shell.m_escapables;
+ break;
+ }
+ }
+ }
+
+ safe_arg.assign(unsafe_arg);
+ size_t prev_pos = 0;
+ while (prev_pos < safe_arg.size()) {
+ // Escape spaces and quotes
+ size_t pos = safe_arg.find_first_of(escapables, prev_pos);
+ if (pos != std::string::npos) {
+ safe_arg.insert(pos, 1, '\\');
+ prev_pos = pos + 2;
+ } else
+ break;
+ }
+ return safe_arg.c_str();
+}
+
+int64_t Args::StringToOptionEnum(const char *s,
+ OptionEnumValueElement *enum_values,
+ int32_t fail_value, Error &error) {
+ if (enum_values) {
+ if (s && s[0]) {
+ for (int i = 0; enum_values[i].string_value != nullptr; i++) {
+ if (strstr(enum_values[i].string_value, s) ==
+ enum_values[i].string_value) {
+ error.Clear();
+ return enum_values[i].value;
+ }
+ }
+ }
+
+ StreamString strm;
+ strm.PutCString("invalid enumeration value, valid values are: ");
+ for (int i = 0; enum_values[i].string_value != nullptr; i++) {
+ strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
+ }
+ error.SetErrorString(strm.GetData());
+ } else {
+ error.SetErrorString("invalid enumeration argument");
+ }
+ return fail_value;
+}
+
+ScriptLanguage Args::StringToScriptLanguage(const char *s,
+ ScriptLanguage fail_value,
+ bool *success_ptr) {
+ if (s && s[0]) {
+ if ((::strcasecmp(s, "python") == 0) ||
+ (::strcasecmp(s, "default") == 0 &&
+ eScriptLanguagePython == eScriptLanguageDefault)) {
+ if (success_ptr)
+ *success_ptr = true;
+ return eScriptLanguagePython;
+ }
+ if (::strcasecmp(s, "none")) {
+ if (success_ptr)
+ *success_ptr = true;
+ return eScriptLanguageNone;
+ }
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+Error Args::StringToFormat(const char *s, lldb::Format &format,
+ size_t *byte_size_ptr) {
+ format = eFormatInvalid;
+ Error error;
+
+ if (s && s[0]) {
+ if (byte_size_ptr) {
+ if (isdigit(s[0])) {
+ char *format_char = nullptr;
+ unsigned long byte_size = ::strtoul(s, &format_char, 0);
+ if (byte_size != ULONG_MAX)
+ *byte_size_ptr = byte_size;
+ s = format_char;
+ } else
+ *byte_size_ptr = 0;
+ }
+
+ const bool partial_match_ok = true;
+ if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
+ StreamString error_strm;
+ error_strm.Printf(
+ "Invalid format character or name '%s'. Valid values are:\n", s);
+ for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
+ char format_char = FormatManager::GetFormatAsFormatChar(f);
+ if (format_char)
+ error_strm.Printf("'%c' or ", format_char);
+
+ error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
+ error_strm.EOL();
+ }
+
+ if (byte_size_ptr)
+ error_strm.PutCString(
+ "An optional byte size can precede the format character.\n");
+ error.SetErrorString(error_strm.GetString().c_str());
+ }
+
+ if (error.Fail())
+ return error;
+ } else {
+ error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
+ }
+ return error;
+}
+
+lldb::Encoding Args::StringToEncoding(const char *s,
+ lldb::Encoding fail_value) {
+ if (!s)
return fail_value;
+ return StringToEncoding(llvm::StringRef(s), fail_value);
}
-Error
-Args::StringToFormat
-(
- const char *s,
- lldb::Format &format,
- size_t *byte_size_ptr
-)
-{
- format = eFormatInvalid;
- Error error;
-
- if (s && s[0])
- {
- if (byte_size_ptr)
- {
- if (isdigit (s[0]))
- {
- char *format_char = nullptr;
- unsigned long byte_size = ::strtoul (s, &format_char, 0);
- if (byte_size != ULONG_MAX)
- *byte_size_ptr = byte_size;
- s = format_char;
- }
- else
- *byte_size_ptr = 0;
- }
-
- const bool partial_match_ok = true;
- if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
- {
- StreamString error_strm;
- error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
- for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
- {
- char format_char = FormatManager::GetFormatAsFormatChar(f);
- if (format_char)
- error_strm.Printf ("'%c' or ", format_char);
-
- error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
- error_strm.EOL();
- }
-
- if (byte_size_ptr)
- error_strm.PutCString ("An optional byte size can precede the format character.\n");
- error.SetErrorString(error_strm.GetString().c_str());
- }
-
- if (error.Fail())
- return error;
- }
- else
- {
- error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
- }
- return error;
-}
-
-lldb::Encoding
-Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
-{
- if (!s)
- return fail_value;
- return StringToEncoding(llvm::StringRef(s), fail_value);
-}
-
-lldb::Encoding
-Args::StringToEncoding(llvm::StringRef s, lldb::Encoding fail_value)
-{
- return llvm::StringSwitch<lldb::Encoding>(s)
- .Case("uint", eEncodingUint)
- .Case("sint", eEncodingSint)
- .Case("ieee754", eEncodingIEEE754)
- .Case("vector", eEncodingVector)
- .Default(fail_value);
-}
-
-uint32_t
-Args::StringToGenericRegister (const char *s)
-{
- if (!s)
- return LLDB_INVALID_REGNUM;
- return StringToGenericRegister(llvm::StringRef(s));
-}
-
-uint32_t
-Args::StringToGenericRegister(llvm::StringRef s)
-{
- if (s.empty())
- return LLDB_INVALID_REGNUM;
- uint32_t result = llvm::StringSwitch<uint32_t>(s)
- .Case("pc", LLDB_REGNUM_GENERIC_PC)
- .Case("sp", LLDB_REGNUM_GENERIC_SP)
- .Case("fp", LLDB_REGNUM_GENERIC_FP)
- .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
- .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
- .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
- .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
- .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
- .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
- .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
- .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
- .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
- .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
- .Default(LLDB_INVALID_REGNUM);
- return result;
-}
-
-
-void
-Args::LongestCommonPrefix (std::string &common_prefix)
-{
- arg_sstr_collection::iterator pos, end = m_args.end();
- pos = m_args.begin();
- if (pos == end)
- common_prefix.clear();
- else
- common_prefix = (*pos);
-
- for (++pos; pos != end; ++pos)
- {
- size_t new_size = (*pos).size();
-
- // First trim common_prefix if it is longer than the current element:
- if (common_prefix.size() > new_size)
- common_prefix.erase (new_size);
-
- // Then trim it at the first disparity:
-
- for (size_t i = 0; i < common_prefix.size(); i++)
- {
- if ((*pos)[i] != common_prefix[i])
- {
- common_prefix.erase(i);
- break;
- }
- }
-
- // If we've emptied the common prefix, we're done.
- if (common_prefix.empty())
- break;
- }
-}
-
-void
-Args::AddOrReplaceEnvironmentVariable(const char *env_var_name,
- const char *new_value)
-{
- if (!env_var_name || !new_value)
- return;
-
- // Build the new entry.
- StreamString stream;
- stream << env_var_name;
- stream << '=';
- stream << new_value;
- stream.Flush();
-
- // Find the environment variable if present and replace it.
- for (size_t i = 0; i < GetArgumentCount(); ++i)
- {
- // Get the env var value.
- const char *arg_value = GetArgumentAtIndex(i);
- if (!arg_value)
- continue;
-
- // Find the name of the env var: before the first =.
- auto equal_p = strchr(arg_value, '=');
- if (!equal_p)
- continue;
-
- // Check if the name matches the given env_var_name.
- if (strncmp(env_var_name, arg_value, equal_p - arg_value) == 0)
- {
- ReplaceArgumentAtIndex(i, stream.GetString().c_str());
- return;
- }
- }
-
- // We didn't find it. Append it instead.
- AppendArgument(stream.GetString().c_str());
-}
-
-bool
-Args::ContainsEnvironmentVariable(const char *env_var_name,
- size_t *argument_index) const
-{
- // Validate args.
- if (!env_var_name)
- return false;
-
- // Check each arg to see if it matches the env var name.
- for (size_t i = 0; i < GetArgumentCount(); ++i)
- {
- // Get the arg value.
- const char *argument_value = GetArgumentAtIndex(i);
- if (!argument_value)
- continue;
-
- // Check if we are the "{env_var_name}={env_var_value}" style.
- const char *equal_p = strchr(argument_value, '=');
- if (equal_p)
- {
- if (strncmp(env_var_name, argument_value,
- equal_p - argument_value) == 0)
- {
- // We matched.
- if (argument_index)
- *argument_index = i;
- return true;
- }
- }
- else
- {
- // We're a simple {env_var_name}-style entry.
- if (strcmp(argument_value, env_var_name) == 0)
- {
- // We matched.
- if (argument_index)
- *argument_index = i;
- return true;
- }
- }
- }
-
- // We didn't find a match.
+lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
+ lldb::Encoding fail_value) {
+ return llvm::StringSwitch<lldb::Encoding>(s)
+ .Case("uint", eEncodingUint)
+ .Case("sint", eEncodingSint)
+ .Case("ieee754", eEncodingIEEE754)
+ .Case("vector", eEncodingVector)
+ .Default(fail_value);
+}
+
+uint32_t Args::StringToGenericRegister(const char *s) {
+ if (!s)
+ return LLDB_INVALID_REGNUM;
+ return StringToGenericRegister(llvm::StringRef(s));
+}
+
+uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
+ if (s.empty())
+ return LLDB_INVALID_REGNUM;
+ uint32_t result = llvm::StringSwitch<uint32_t>(s)
+ .Case("pc", LLDB_REGNUM_GENERIC_PC)
+ .Case("sp", LLDB_REGNUM_GENERIC_SP)
+ .Case("fp", LLDB_REGNUM_GENERIC_FP)
+ .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
+ .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
+ .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
+ .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
+ .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
+ .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
+ .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
+ .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
+ .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
+ .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
+ .Default(LLDB_INVALID_REGNUM);
+ return result;
+}
+
+void Args::LongestCommonPrefix(std::string &common_prefix) {
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ pos = m_args.begin();
+ if (pos == end)
+ common_prefix.clear();
+ else
+ common_prefix = (*pos);
+
+ for (++pos; pos != end; ++pos) {
+ size_t new_size = (*pos).size();
+
+ // First trim common_prefix if it is longer than the current element:
+ if (common_prefix.size() > new_size)
+ common_prefix.erase(new_size);
+
+ // Then trim it at the first disparity:
+
+ for (size_t i = 0; i < common_prefix.size(); i++) {
+ if ((*pos)[i] != common_prefix[i]) {
+ common_prefix.erase(i);
+ break;
+ }
+ }
+
+ // If we've emptied the common prefix, we're done.
+ if (common_prefix.empty())
+ break;
+ }
+}
+
+void Args::AddOrReplaceEnvironmentVariable(const char *env_var_name,
+ const char *new_value) {
+ if (!env_var_name || !new_value)
+ return;
+
+ // Build the new entry.
+ StreamString stream;
+ stream << env_var_name;
+ stream << '=';
+ stream << new_value;
+ stream.Flush();
+
+ // Find the environment variable if present and replace it.
+ for (size_t i = 0; i < GetArgumentCount(); ++i) {
+ // Get the env var value.
+ const char *arg_value = GetArgumentAtIndex(i);
+ if (!arg_value)
+ continue;
+
+ // Find the name of the env var: before the first =.
+ auto equal_p = strchr(arg_value, '=');
+ if (!equal_p)
+ continue;
+
+ // Check if the name matches the given env_var_name.
+ if (strncmp(env_var_name, arg_value, equal_p - arg_value) == 0) {
+ ReplaceArgumentAtIndex(i, stream.GetString().c_str());
+ return;
+ }
+ }
+
+ // We didn't find it. Append it instead.
+ AppendArgument(stream.GetString().c_str());
+}
+
+bool Args::ContainsEnvironmentVariable(const char *env_var_name,
+ size_t *argument_index) const {
+ // Validate args.
+ if (!env_var_name)
return false;
-}
-size_t
-Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
-{
- char short_buffer[3];
- char long_buffer[255];
- ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
- ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].definition->long_option);
- size_t end = GetArgumentCount ();
- size_t idx = 0;
- while (idx < end)
- {
- if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
- || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
- {
- return idx;
- }
- ++idx;
+ // Check each arg to see if it matches the env var name.
+ for (size_t i = 0; i < GetArgumentCount(); ++i) {
+ // Get the arg value.
+ const char *argument_value = GetArgumentAtIndex(i);
+ if (!argument_value)
+ continue;
+
+ // Check if we are the "{env_var_name}={env_var_value}" style.
+ const char *equal_p = strchr(argument_value, '=');
+ if (equal_p) {
+ if (strncmp(env_var_name, argument_value, equal_p - argument_value) ==
+ 0) {
+ // We matched.
+ if (argument_index)
+ *argument_index = i;
+ return true;
+ }
+ } else {
+ // We're a simple {env_var_name}-style entry.
+ if (strcmp(argument_value, env_var_name) == 0) {
+ // We matched.
+ if (argument_index)
+ *argument_index = i;
+ return true;
+ }
}
+ }
- return end;
+ // We didn't find a match.
+ return false;
}
-bool
-Args::IsPositionalArgument (const char *arg)
-{
- if (arg == nullptr)
- return false;
-
- bool is_positional = true;
- const char *cptr = arg;
-
- if (cptr[0] == '%')
- {
- ++cptr;
- while (isdigit (cptr[0]))
- ++cptr;
- if (cptr[0] != '\0')
- is_positional = false;
+size_t Args::FindArgumentIndexForOption(Option *long_options,
+ int long_options_index) {
+ char short_buffer[3];
+ char long_buffer[255];
+ ::snprintf(short_buffer, sizeof(short_buffer), "-%c",
+ long_options[long_options_index].val);
+ ::snprintf(long_buffer, sizeof(long_buffer), "--%s",
+ long_options[long_options_index].definition->long_option);
+ size_t end = GetArgumentCount();
+ size_t idx = 0;
+ while (idx < end) {
+ if ((::strncmp(GetArgumentAtIndex(idx), short_buffer,
+ strlen(short_buffer)) == 0) ||
+ (::strncmp(GetArgumentAtIndex(idx), long_buffer, strlen(long_buffer)) ==
+ 0)) {
+ return idx;
}
- else
- is_positional = false;
+ ++idx;
+ }
- return is_positional;
+ return end;
}
-void
-Args::ParseAliasOptions (Options &options,
- CommandReturnObject &result,
- OptionArgVector *option_arg_vector,
- std::string &raw_input_string)
-{
- StreamString sstr;
- int i;
- Option *long_options = options.GetLongOptions();
-
- if (long_options == nullptr)
- {
- result.AppendError ("invalid long options");
- result.SetStatus (eReturnStatusFailed);
- return;
- }
-
- for (i = 0; long_options[i].definition != nullptr; ++i)
- {
- if (long_options[i].flag == nullptr)
- {
- sstr << (char) long_options[i].val;
- switch (long_options[i].definition->option_has_arg)
- {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ":";
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
-
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- int val;
- while (1)
- {
- int long_options_index = -1;
- val = OptionParser::Parse (GetArgumentCount(),
- GetArgumentVector(),
- sstr.GetData(),
- long_options,
- &long_options_index);
-
- if (val == -1)
- break;
-
- if (val == '?')
- {
- result.AppendError ("unknown or ambiguous option");
- result.SetStatus (eReturnStatusFailed);
- break;
- }
-
- if (val == 0)
- continue;
-
- options.OptionSeen (val);
-
- // Look up the long option index
- if (long_options_index == -1)
- {
- for (int j = 0;
- long_options[j].definition || long_options[j].flag || long_options[j].val;
- ++j)
- {
- if (long_options[j].val == val)
- {
- long_options_index = j;
- break;
- }
- }
- }
-
- // See if the option takes an argument, and see if one was supplied.
- if (long_options_index >= 0)
- {
- StreamString option_str;
- option_str.Printf ("-%c", val);
- const OptionDefinition *def = long_options[long_options_index].definition;
- int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
-
- switch (has_arg)
- {
- case OptionParser::eNoArgument:
- option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (OptionParser::eNoArgument, "<no-argument>")));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- break;
- case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() != nullptr)
- {
- option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (OptionParser::eRequiredArgument,
- std::string (OptionParser::GetOptionArgument()))));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
- option_str.GetData());
- result.SetStatus (eReturnStatusFailed);
- }
- break;
- case OptionParser::eOptionalArgument:
- if (OptionParser::GetOptionArgument() != nullptr)
- {
- option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (OptionParser::eOptionalArgument,
- std::string (OptionParser::GetOptionArgument()))));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
- OptionArgValue (OptionParser::eOptionalArgument, "<no-argument>")));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- break;
- default:
- result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
- result.SetStatus (eReturnStatusFailed);
- break;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
- result.SetStatus (eReturnStatusFailed);
- }
-
- if (long_options_index >= 0)
- {
- // Find option in the argument list; also see if it was supposed to take an argument and if one was
- // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
- // the raw_input_string, if one was passed in.
- size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
- if (idx < GetArgumentCount())
- {
- if (raw_input_string.size() > 0)
- {
- const char *tmp_arg = GetArgumentAtIndex (idx);
- size_t pos = raw_input_string.find (tmp_arg);
- if (pos != std::string::npos)
- raw_input_string.erase (pos, strlen (tmp_arg));
- }
- ReplaceArgumentAtIndex (idx, "");
- if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
- && (OptionParser::GetOptionArgument() != nullptr)
- && (idx+1 < GetArgumentCount())
- && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
- {
- if (raw_input_string.size() > 0)
- {
- const char *tmp_arg = GetArgumentAtIndex (idx+1);
- size_t pos = raw_input_string.find (tmp_arg);
- if (pos != std::string::npos)
- raw_input_string.erase (pos, strlen (tmp_arg));
- }
- ReplaceArgumentAtIndex (idx+1, "");
- }
- }
- }
-
- if (!result.Succeeded())
- break;
- }
-}
-
-void
-Args::ParseArgsForCompletion
-(
- Options &options,
- OptionElementVector &option_element_vector,
- uint32_t cursor_index
-)
-{
- StreamString sstr;
- Option *long_options = options.GetLongOptions();
- option_element_vector.clear();
-
- if (long_options == nullptr)
- {
- return;
- }
-
- // Leading : tells getopt to return a : for a missing option argument AND
- // to suppress error messages.
-
- sstr << ":";
- for (int i = 0; long_options[i].definition != nullptr; ++i)
- {
- if (long_options[i].flag == nullptr)
- {
- sstr << (char) long_options[i].val;
- switch (long_options[i].definition->option_has_arg)
- {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ":";
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
-
- std::unique_lock<std::mutex> lock;
- OptionParser::Prepare(lock);
- OptionParser::EnableError(false);
-
- int val;
- const OptionDefinition *opt_defs = options.GetDefinitions();
-
- // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front.
- // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't
- // change the one we have.
-
- std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
-
- bool failed_once = false;
- uint32_t dash_dash_pos = -1;
-
- while (1)
- {
- bool missing_argument = false;
- int long_options_index = -1;
-
- val = OptionParser::Parse (dummy_vec.size() - 1,
- const_cast<char *const *>(&dummy_vec.front()),
- sstr.GetData(),
- long_options,
- &long_options_index);
-
- if (val == -1)
- {
- // When we're completing a "--" which is the last option on line,
- if (failed_once)
- break;
-
- failed_once = true;
-
- // If this is a bare "--" we mark it as such so we can complete it successfully later.
- // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
- // user might want to complete options by long name. I make this work by checking whether the
- // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
- // I let it pass to OptionParser::Parse which will terminate the option parsing.
- // Note, in either case we continue parsing the line so we can figure out what other options
- // were passed. This will be useful when we come to restricting completions based on what other
- // options we've seen on the line.
-
- if (static_cast<size_t>(OptionParser::GetOptionIndex()) < dummy_vec.size() - 1
- && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
- {
- dash_dash_pos = OptionParser::GetOptionIndex() - 1;
- if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) == cursor_index)
- {
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eBareDoubleDash));
- continue;
- }
- else
- break;
- }
- else
- break;
- }
- else if (val == '?')
- {
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- continue;
- }
- else if (val == 0)
- {
- continue;
- }
- else if (val == ':')
- {
- // This is a missing argument.
- val = OptionParser::GetOptionErrorCause();
- missing_argument = true;
- }
-
- ((Options *) &options)->OptionSeen (val);
-
- // Look up the long option index
- if (long_options_index == -1)
- {
- for (int j = 0;
- long_options[j].definition || long_options[j].flag || long_options[j].val;
- ++j)
- {
- if (long_options[j].val == val)
- {
- long_options_index = j;
- break;
- }
- }
- }
-
- // See if the option takes an argument, and see if one was supplied.
- if (long_options_index >= 0)
- {
- int opt_defs_index = -1;
- for (int i = 0; ; i++)
- {
- if (opt_defs[i].short_option == 0)
- break;
- else if (opt_defs[i].short_option == val)
- {
- opt_defs_index = i;
- break;
- }
- }
-
- const OptionDefinition *def = long_options[long_options_index].definition;
- int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
- switch (has_arg)
- {
- case OptionParser::eNoArgument:
- option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
- break;
- case OptionParser::eRequiredArgument:
- if (OptionParser::GetOptionArgument() != nullptr)
- {
- int arg_index;
- if (missing_argument)
- arg_index = -1;
- else
- arg_index = OptionParser::GetOptionIndex() - 1;
-
- option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
- }
- else
- {
- option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
- }
- break;
- case OptionParser::eOptionalArgument:
- if (OptionParser::GetOptionArgument() != nullptr)
- {
- option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
- }
- else
- {
- option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
- }
- break;
- default:
- // The options table is messed up. Here we'll just continue
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- break;
- }
- }
- else
- {
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
- OptionArgElement::eUnrecognizedArg));
- }
- }
-
- // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
- // the option_element_vector, but only if it is not after the "--". But it turns out that OptionParser::Parse just ignores
- // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
- // Note, a single quoted dash is not the same as a single dash...
-
- if ((static_cast<int32_t>(dash_dash_pos) == -1 || cursor_index < dash_dash_pos)
- && m_args_quote_char[cursor_index] == '\0'
- && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
- {
- option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
- OptionArgElement::eBareDash));
-
- }
-}
-
-void
-Args::EncodeEscapeSequences (const char *src, std::string &dst)
-{
- dst.clear();
- if (src)
- {
- for (const char *p = src; *p != '\0'; ++p)
- {
- size_t non_special_chars = ::strcspn (p, "\\");
- if (non_special_chars > 0)
- {
- dst.append(p, non_special_chars);
- p += non_special_chars;
- if (*p == '\0')
- break;
- }
-
- if (*p == '\\')
- {
- ++p; // skip the slash
- switch (*p)
- {
- case 'a' : dst.append(1, '\a'); break;
- case 'b' : dst.append(1, '\b'); break;
- case 'f' : dst.append(1, '\f'); break;
- case 'n' : dst.append(1, '\n'); break;
- case 'r' : dst.append(1, '\r'); break;
- case 't' : dst.append(1, '\t'); break;
- case 'v' : dst.append(1, '\v'); break;
- case '\\': dst.append(1, '\\'); break;
- case '\'': dst.append(1, '\''); break;
- case '"' : dst.append(1, '"'); break;
- case '0' :
- // 1 to 3 octal chars
- {
- // Make a string that can hold onto the initial zero char,
- // up to 3 octal digits, and a terminating NULL.
- char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
-
- int i;
- for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
- oct_str[i] = p[i];
-
- // We don't want to consume the last octal character since
- // the main for loop will do this for us, so we advance p by
- // one less than i (even if i is zero)
- p += i - 1;
- unsigned long octal_value = ::strtoul (oct_str, nullptr, 8);
- if (octal_value <= UINT8_MAX)
- {
- dst.append(1, (char)octal_value);
- }
- }
- break;
-
- case 'x':
- // hex number in the format
- if (isxdigit(p[1]))
- {
- ++p; // Skip the 'x'
-
- // Make a string that can hold onto two hex chars plus a
- // NULL terminator
- char hex_str[3] = { *p, '\0', '\0' };
- if (isxdigit(p[1]))
- {
- ++p; // Skip the first of the two hex chars
- hex_str[1] = *p;
- }
-
- unsigned long hex_value = strtoul (hex_str, nullptr, 16);
- if (hex_value <= UINT8_MAX)
- dst.append (1, (char)hex_value);
- }
- else
- {
- dst.append(1, 'x');
- }
- break;
-
- default:
- // Just desensitize any other character by just printing what
- // came after the '\'
- dst.append(1, *p);
- break;
-
- }
- }
- }
- }
-}
+bool Args::IsPositionalArgument(const char *arg) {
+ if (arg == nullptr)
+ return false;
+ bool is_positional = true;
+ const char *cptr = arg;
-void
-Args::ExpandEscapedCharacters (const char *src, std::string &dst)
-{
- dst.clear();
- if (src)
- {
- for (const char *p = src; *p != '\0'; ++p)
- {
- if (isprint8(*p))
- dst.append(1, *p);
- else
- {
- switch (*p)
- {
- case '\a': dst.append("\\a"); break;
- case '\b': dst.append("\\b"); break;
- case '\f': dst.append("\\f"); break;
- case '\n': dst.append("\\n"); break;
- case '\r': dst.append("\\r"); break;
- case '\t': dst.append("\\t"); break;
- case '\v': dst.append("\\v"); break;
- case '\'': dst.append("\\'"); break;
- case '"': dst.append("\\\""); break;
- case '\\': dst.append("\\\\"); break;
- default:
- {
- // Just encode as octal
- dst.append("\\0");
- char octal_str[32];
- snprintf(octal_str, sizeof(octal_str), "%o", *p);
- dst.append(octal_str);
- }
- break;
- }
- }
- }
- }
-}
-
-std::string
-Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char)
-{
- const char* chars_to_escape = nullptr;
- switch (quote_char)
- {
- case '\0':
- chars_to_escape = " \t\\'\"`";
- break;
+ if (cptr[0] == '%') {
+ ++cptr;
+ while (isdigit(cptr[0]))
+ ++cptr;
+ if (cptr[0] != '\0')
+ is_positional = false;
+ } else
+ is_positional = false;
+
+ return is_positional;
+}
+
+void Args::ParseAliasOptions(Options &options, CommandReturnObject &result,
+ OptionArgVector *option_arg_vector,
+ std::string &raw_input_string) {
+ StreamString sstr;
+ int i;
+ Option *long_options = options.GetLongOptions();
+
+ if (long_options == nullptr) {
+ result.AppendError("invalid long options");
+ result.SetStatus(eReturnStatusFailed);
+ return;
+ }
+
+ for (i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ":";
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ int val;
+ while (1) {
+ int long_options_index = -1;
+ val =
+ OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
+ sstr.GetData(), long_options, &long_options_index);
+
+ if (val == -1)
+ break;
+
+ if (val == '?') {
+ result.AppendError("unknown or ambiguous option");
+ result.SetStatus(eReturnStatusFailed);
+ break;
+ }
+
+ if (val == 0)
+ continue;
+
+ options.OptionSeen(val);
+
+ // Look up the long option index
+ if (long_options_index == -1) {
+ for (int j = 0; long_options[j].definition || long_options[j].flag ||
+ long_options[j].val;
+ ++j) {
+ if (long_options[j].val == val) {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index >= 0) {
+ StreamString option_str;
+ option_str.Printf("-%c", val);
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg =
+ (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+
+ switch (has_arg) {
+ case OptionParser::eNoArgument:
+ option_arg_vector->push_back(OptionArgPair(
+ std::string(option_str.GetData()),
+ OptionArgValue(OptionParser::eNoArgument, "<no-argument>")));
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ break;
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ option_arg_vector->push_back(OptionArgPair(
+ std::string(option_str.GetData()),
+ OptionArgValue(OptionParser::eRequiredArgument,
+ std::string(OptionParser::GetOptionArgument()))));
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ } else {
+ result.AppendErrorWithFormat(
+ "Option '%s' is missing argument specifier.\n",
+ option_str.GetData());
+ result.SetStatus(eReturnStatusFailed);
+ }
+ break;
+ case OptionParser::eOptionalArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ option_arg_vector->push_back(OptionArgPair(
+ std::string(option_str.GetData()),
+ OptionArgValue(OptionParser::eOptionalArgument,
+ std::string(OptionParser::GetOptionArgument()))));
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ } else {
+ option_arg_vector->push_back(
+ OptionArgPair(std::string(option_str.GetData()),
+ OptionArgValue(OptionParser::eOptionalArgument,
+ "<no-argument>")));
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ break;
+ default:
+ result.AppendErrorWithFormat("error with options table; invalid value "
+ "in has_arg field for option '%c'.\n",
+ val);
+ result.SetStatus(eReturnStatusFailed);
+ break;
+ }
+ } else {
+ result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val);
+ result.SetStatus(eReturnStatusFailed);
+ }
+
+ if (long_options_index >= 0) {
+ // Find option in the argument list; also see if it was supposed to take
+ // an argument and if one was
+ // supplied. Remove option (and argument, if given) from the argument
+ // list. Also remove them from
+ // the raw_input_string, if one was passed in.
+ size_t idx = FindArgumentIndexForOption(long_options, long_options_index);
+ if (idx < GetArgumentCount()) {
+ if (raw_input_string.size() > 0) {
+ const char *tmp_arg = GetArgumentAtIndex(idx);
+ size_t pos = raw_input_string.find(tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase(pos, strlen(tmp_arg));
+ }
+ ReplaceArgumentAtIndex(idx, "");
+ if ((long_options[long_options_index].definition->option_has_arg !=
+ OptionParser::eNoArgument) &&
+ (OptionParser::GetOptionArgument() != nullptr) &&
+ (idx + 1 < GetArgumentCount()) &&
+ (strcmp(OptionParser::GetOptionArgument(),
+ GetArgumentAtIndex(idx + 1)) == 0)) {
+ if (raw_input_string.size() > 0) {
+ const char *tmp_arg = GetArgumentAtIndex(idx + 1);
+ size_t pos = raw_input_string.find(tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase(pos, strlen(tmp_arg));
+ }
+ ReplaceArgumentAtIndex(idx + 1, "");
+ }
+ }
+ }
+
+ if (!result.Succeeded())
+ break;
+ }
+}
+
+void Args::ParseArgsForCompletion(Options &options,
+ OptionElementVector &option_element_vector,
+ uint32_t cursor_index) {
+ StreamString sstr;
+ Option *long_options = options.GetLongOptions();
+ option_element_vector.clear();
+
+ if (long_options == nullptr) {
+ return;
+ }
+
+ // Leading : tells getopt to return a : for a missing option argument AND
+ // to suppress error messages.
+
+ sstr << ":";
+ for (int i = 0; long_options[i].definition != nullptr; ++i) {
+ if (long_options[i].flag == nullptr) {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].definition->option_has_arg) {
+ default:
+ case OptionParser::eNoArgument:
+ break;
+ case OptionParser::eRequiredArgument:
+ sstr << ":";
+ break;
+ case OptionParser::eOptionalArgument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
+ OptionParser::EnableError(false);
+
+ int val;
+ const OptionDefinition *opt_defs = options.GetDefinitions();
+
+ // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the
+ // options to the front.
+ // So we have to build another Arg and pass that to OptionParser::Parse so it
+ // doesn't
+ // change the one we have.
+
+ std::vector<const char *> dummy_vec(
+ GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
+
+ bool failed_once = false;
+ uint32_t dash_dash_pos = -1;
+
+ while (1) {
+ bool missing_argument = false;
+ int long_options_index = -1;
+
+ val = OptionParser::Parse(
+ dummy_vec.size() - 1, const_cast<char *const *>(&dummy_vec.front()),
+ sstr.GetData(), long_options, &long_options_index);
+
+ if (val == -1) {
+ // When we're completing a "--" which is the last option on line,
+ if (failed_once)
+ break;
+
+ failed_once = true;
+
+ // If this is a bare "--" we mark it as such so we can complete it
+ // successfully later.
+ // Handling the "--" is a little tricky, since that may mean end of
+ // options or arguments, or the
+ // user might want to complete options by long name. I make this work by
+ // checking whether the
+ // cursor is in the "--" argument, and if so I assume we're completing the
+ // long option, otherwise
+ // I let it pass to OptionParser::Parse which will terminate the option
+ // parsing.
+ // Note, in either case we continue parsing the line so we can figure out
+ // what other options
+ // were passed. This will be useful when we come to restricting
+ // completions based on what other
+ // options we've seen on the line.
+
+ if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
+ dummy_vec.size() - 1 &&
+ (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
+ dash_dash_pos = OptionParser::GetOptionIndex() - 1;
+ if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) ==
+ cursor_index) {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eBareDoubleDash,
+ OptionParser::GetOptionIndex() - 1,
+ OptionArgElement::eBareDoubleDash));
+ continue;
+ } else
+ break;
+ } else
+ break;
+ } else if (val == '?') {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eUnrecognizedArg,
+ OptionParser::GetOptionIndex() - 1,
+ OptionArgElement::eUnrecognizedArg));
+ continue;
+ } else if (val == 0) {
+ continue;
+ } else if (val == ':') {
+ // This is a missing argument.
+ val = OptionParser::GetOptionErrorCause();
+ missing_argument = true;
+ }
+
+ ((Options *)&options)->OptionSeen(val);
+
+ // Look up the long option index
+ if (long_options_index == -1) {
+ for (int j = 0; long_options[j].definition || long_options[j].flag ||
+ long_options[j].val;
+ ++j) {
+ if (long_options[j].val == val) {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index >= 0) {
+ int opt_defs_index = -1;
+ for (int i = 0;; i++) {
+ if (opt_defs[i].short_option == 0)
+ break;
+ else if (opt_defs[i].short_option == val) {
+ opt_defs_index = i;
+ break;
+ }
+ }
+
+ const OptionDefinition *def = long_options[long_options_index].definition;
+ int has_arg =
+ (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
+ switch (has_arg) {
+ case OptionParser::eNoArgument:
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
+ break;
+ case OptionParser::eRequiredArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ int arg_index;
+ if (missing_argument)
+ arg_index = -1;
+ else
+ arg_index = OptionParser::GetOptionIndex() - 1;
+
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
+ } else {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
+ }
+ break;
+ case OptionParser::eOptionalArgument:
+ if (OptionParser::GetOptionArgument() != nullptr) {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index, OptionParser::GetOptionIndex() - 2,
+ OptionParser::GetOptionIndex() - 1));
+ } else {
+ option_element_vector.push_back(OptionArgElement(
+ opt_defs_index, OptionParser::GetOptionIndex() - 2,
+ OptionParser::GetOptionIndex() - 1));
+ }
+ break;
+ default:
+ // The options table is messed up. Here we'll just continue
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eUnrecognizedArg,
+ OptionParser::GetOptionIndex() - 1,
+ OptionArgElement::eUnrecognizedArg));
+ break;
+ }
+ } else {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eUnrecognizedArg,
+ OptionParser::GetOptionIndex() - 1,
+ OptionArgElement::eUnrecognizedArg));
+ }
+ }
+
+ // Finally we have to handle the case where the cursor index points at a
+ // single "-". We want to mark that in
+ // the option_element_vector, but only if it is not after the "--". But it
+ // turns out that OptionParser::Parse just ignores
+ // an isolated "-". So we have to look it up by hand here. We only care if
+ // it is AT the cursor position.
+ // Note, a single quoted dash is not the same as a single dash...
+
+ if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
+ cursor_index < dash_dash_pos) &&
+ m_args_quote_char[cursor_index] == '\0' &&
+ strcmp(GetArgumentAtIndex(cursor_index), "-") == 0) {
+ option_element_vector.push_back(
+ OptionArgElement(OptionArgElement::eBareDash, cursor_index,
+ OptionArgElement::eBareDash));
+ }
+}
+
+void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ size_t non_special_chars = ::strcspn(p, "\\");
+ if (non_special_chars > 0) {
+ dst.append(p, non_special_chars);
+ p += non_special_chars;
+ if (*p == '\0')
+ break;
+ }
+
+ if (*p == '\\') {
+ ++p; // skip the slash
+ switch (*p) {
+ case 'a':
+ dst.append(1, '\a');
+ break;
+ case 'b':
+ dst.append(1, '\b');
+ break;
+ case 'f':
+ dst.append(1, '\f');
+ break;
+ case 'n':
+ dst.append(1, '\n');
+ break;
+ case 'r':
+ dst.append(1, '\r');
+ break;
+ case 't':
+ dst.append(1, '\t');
+ break;
+ case 'v':
+ dst.append(1, '\v');
+ break;
+ case '\\':
+ dst.append(1, '\\');
+ break;
case '\'':
- chars_to_escape = "";
- break;
+ dst.append(1, '\'');
+ break;
case '"':
- chars_to_escape = "$\"`\\";
- break;
- default:
- assert(false && "Unhandled quote character");
- }
+ dst.append(1, '"');
+ break;
+ case '0':
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char,
+ // up to 3 octal digits, and a terminating NULL.
+ char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
+
+ int i;
+ for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
+ oct_str[i] = p[i];
+
+ // We don't want to consume the last octal character since
+ // the main for loop will do this for us, so we advance p by
+ // one less than i (even if i is zero)
+ p += i - 1;
+ unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
+ if (octal_value <= UINT8_MAX) {
+ dst.append(1, (char)octal_value);
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(p[1])) {
+ ++p; // Skip the 'x'
+
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = {*p, '\0', '\0'};
+ if (isxdigit(p[1])) {
+ ++p; // Skip the first of the two hex chars
+ hex_str[1] = *p;
+ }
+
+ unsigned long hex_value = strtoul(hex_str, nullptr, 16);
+ if (hex_value <= UINT8_MAX)
+ dst.append(1, (char)hex_value);
+ } else {
+ dst.append(1, 'x');
+ }
+ break;
- std::string res;
- res.reserve(arg.size());
- for (char c : arg)
- {
- if (::strchr(chars_to_escape, c))
- res.push_back('\\');
- res.push_back(c);
- }
- return res;
+ default:
+ // Just desensitize any other character by just printing what
+ // came after the '\'
+ dst.append(1, *p);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ if (isprint8(*p))
+ dst.append(1, *p);
+ else {
+ switch (*p) {
+ case '\a':
+ dst.append("\\a");
+ break;
+ case '\b':
+ dst.append("\\b");
+ break;
+ case '\f':
+ dst.append("\\f");
+ break;
+ case '\n':
+ dst.append("\\n");
+ break;
+ case '\r':
+ dst.append("\\r");
+ break;
+ case '\t':
+ dst.append("\\t");
+ break;
+ case '\v':
+ dst.append("\\v");
+ break;
+ case '\'':
+ dst.append("\\'");
+ break;
+ case '"':
+ dst.append("\\\"");
+ break;
+ case '\\':
+ dst.append("\\\\");
+ break;
+ default: {
+ // Just encode as octal
+ dst.append("\\0");
+ char octal_str[32];
+ snprintf(octal_str, sizeof(octal_str), "%o", *p);
+ dst.append(octal_str);
+ } break;
+ }
+ }
+ }
+ }
+}
+
+std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
+ char quote_char) {
+ const char *chars_to_escape = nullptr;
+ switch (quote_char) {
+ case '\0':
+ chars_to_escape = " \t\\'\"`";
+ break;
+ case '\'':
+ chars_to_escape = "";
+ break;
+ case '"':
+ chars_to_escape = "$\"`\\";
+ break;
+ default:
+ assert(false && "Unhandled quote character");
+ }
+
+ std::string res;
+ res.reserve(arg.size());
+ for (char c : arg) {
+ if (::strchr(chars_to_escape, c))
+ res.push_back('\\');
+ res.push_back(c);
+ }
+ return res;
}
-
Modified: lldb/trunk/source/Interpreter/CommandAlias.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandAlias.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandAlias.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandAlias.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- CommandAlias.cpp ------------------------------------------*- C++ -*-===//
+//===-- CommandAlias.cpp ------------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,291 +21,225 @@
using namespace lldb;
using namespace lldb_private;
-static bool
-ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
- const char *options_args,
- OptionArgVectorSP &option_arg_vector_sp)
-{
- bool success = true;
- OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
-
- if (!options_args || (strlen (options_args) < 1))
- return true;
-
- std::string options_string (options_args);
- Args args (options_args);
- CommandReturnObject result;
- // Check to see if the command being aliased can take any command options.
- Options *options = cmd_obj_sp->GetOptions ();
- if (options)
- {
- // See if any options were specified as part of the alias; if so, handle them appropriately.
- ExecutionContext exe_ctx =
- cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
- options->NotifyOptionParsingStarting(&exe_ctx);
- args.Unshift ("dummy_arg");
- args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
- args.Shift ();
- if (result.Succeeded())
- options->VerifyPartialOptions (result);
- if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
- {
- result.AppendError ("Unable to create requested alias.\n");
- return false;
- }
- }
-
- if (!options_string.empty())
- {
- if (cmd_obj_sp->WantsRawCommandString ())
- option_arg_vector->push_back (OptionArgPair ("<argument>",
- OptionArgValue (-1,
- options_string)));
- else
- {
- const size_t argc = args.GetArgumentCount();
- for (size_t i = 0; i < argc; ++i)
- if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
- option_arg_vector->push_back
- (OptionArgPair ("<argument>",
- OptionArgValue (-1,
- std::string (args.GetArgumentAtIndex (i)))));
- }
- }
-
- return success;
-}
-
-CommandAlias::CommandAlias (CommandInterpreter &interpreter,
- lldb::CommandObjectSP cmd_sp,
- const char *options_args,
- const char *name,
- const char *help,
- const char *syntax,
- uint32_t flags) :
- CommandObject(interpreter,
- name,
- help,
- syntax,
- flags),
-m_underlying_command_sp(),
-m_option_string(options_args ? options_args : ""),
-m_option_args_sp(new OptionArgVector),
-m_is_dashdash_alias(eLazyBoolCalculate),
-m_did_set_help(false),
-m_did_set_help_long(false)
-{
- if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp))
- {
- m_underlying_command_sp = cmd_sp;
- for (int i = 0;
- auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
- i++)
- {
- m_arguments.push_back(*cmd_entry);
- }
- if (!help || !help[0])
- {
- StreamString sstr;
- StreamString translation_and_help;
- GetAliasExpansion(sstr);
-
- translation_and_help.Printf ("(%s) %s", sstr.GetData(), GetUnderlyingCommand()->GetHelp());
- SetHelp(translation_and_help.GetData());
- }
- }
-}
-
-bool
-CommandAlias::WantsRawCommandString()
-{
- if (IsValid())
- return m_underlying_command_sp->WantsRawCommandString();
- return false;
-}
-
-bool
-CommandAlias::WantsCompletion()
-{
- if (IsValid())
- return m_underlying_command_sp->WantsCompletion();
- return false;
-}
-
-int
-CommandAlias::HandleCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- if (IsValid())
- return m_underlying_command_sp->HandleCompletion(input,
- cursor_index,
- cursor_char_position,
- match_start_point,
- max_return_elements,
- word_complete,
- matches);
- return -1;
-}
-
-int
-CommandAlias::HandleArgumentCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- if (IsValid())
- return m_underlying_command_sp->HandleArgumentCompletion(input,
- cursor_index,
- cursor_char_position,
- opt_element_vector,
- match_start_point,
- max_return_elements,
- word_complete,
- matches);
- return -1;
-}
-
-Options*
-CommandAlias::GetOptions()
-{
- if (IsValid())
- return m_underlying_command_sp->GetOptions();
- return nullptr;
-}
-
-bool
-CommandAlias::Execute(const char *args_string, CommandReturnObject &result)
-{
- llvm_unreachable("CommandAlias::Execute is not to be called");
-}
-
-void
-CommandAlias::GetAliasExpansion (StreamString &help_string)
-{
- const char* command_name = m_underlying_command_sp->GetCommandName();
- help_string.Printf ("'%s", command_name);
-
- if (m_option_args_sp)
- {
- OptionArgVector *options = m_option_args_sp.get();
- for (size_t i = 0; i < options->size(); ++i)
- {
- OptionArgPair cur_option = (*options)[i];
- std::string opt = cur_option.first;
- OptionArgValue value_pair = cur_option.second;
- std::string value = value_pair.second;
- if (opt.compare("<argument>") == 0)
- {
- help_string.Printf (" %s", value.c_str());
- }
- else
- {
- help_string.Printf (" %s", opt.c_str());
- if ((value.compare ("<no-argument>") != 0)
- && (value.compare ("<need-argument") != 0))
- {
- help_string.Printf (" %s", value.c_str());
- }
- }
- }
- }
-
- help_string.Printf ("'");
-}
-
-bool
-CommandAlias::IsDashDashCommand ()
-{
- if (m_is_dashdash_alias == eLazyBoolCalculate)
- {
- m_is_dashdash_alias = eLazyBoolNo;
- if (IsValid())
- {
- for (const OptionArgPair& opt_arg : *GetOptionArguments())
- {
- if (opt_arg.first == "<argument>" &&
- !opt_arg.second.second.empty() &&
- llvm::StringRef(opt_arg.second.second).endswith("--"))
- {
- m_is_dashdash_alias = eLazyBoolYes;
- break;
- }
- }
- // if this is a nested alias, it may be adding arguments on top of an already dash-dash alias
- if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
- m_is_dashdash_alias = (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes : eLazyBoolNo);
- }
- }
- return (m_is_dashdash_alias == eLazyBoolYes);
-}
-
-bool
-CommandAlias::IsNestedAlias ()
-{
- if (GetUnderlyingCommand())
- return GetUnderlyingCommand()->IsAlias();
- return false;
-}
-
-std::pair<lldb::CommandObjectSP, OptionArgVectorSP>
-CommandAlias::Desugar ()
-{
- auto underlying = GetUnderlyingCommand();
- if (!underlying)
- return {nullptr,nullptr};
-
- if (underlying->IsAlias())
- {
- auto desugared = ((CommandAlias*)underlying.get())->Desugar();
- auto options = GetOptionArguments();
- options->insert(options->begin(), desugared.second->begin(), desugared.second->end());
- return {desugared.first,options};
- }
+static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
+ const char *options_args,
+ OptionArgVectorSP &option_arg_vector_sp) {
+ bool success = true;
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ if (!options_args || (strlen(options_args) < 1))
+ return true;
+
+ std::string options_string(options_args);
+ Args args(options_args);
+ CommandReturnObject result;
+ // Check to see if the command being aliased can take any command options.
+ Options *options = cmd_obj_sp->GetOptions();
+ if (options) {
+ // See if any options were specified as part of the alias; if so, handle
+ // them appropriately.
+ ExecutionContext exe_ctx =
+ cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
+ options->NotifyOptionParsingStarting(&exe_ctx);
+ args.Unshift("dummy_arg");
+ args.ParseAliasOptions(*options, result, option_arg_vector, options_string);
+ args.Shift();
+ if (result.Succeeded())
+ options->VerifyPartialOptions(result);
+ if (!result.Succeeded() &&
+ result.GetStatus() != lldb::eReturnStatusStarted) {
+ result.AppendError("Unable to create requested alias.\n");
+ return false;
+ }
+ }
+
+ if (!options_string.empty()) {
+ if (cmd_obj_sp->WantsRawCommandString())
+ option_arg_vector->push_back(
+ OptionArgPair("<argument>", OptionArgValue(-1, options_string)));
+ else {
+ const size_t argc = args.GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i)
+ if (strcmp(args.GetArgumentAtIndex(i), "") != 0)
+ option_arg_vector->push_back(OptionArgPair(
+ "<argument>",
+ OptionArgValue(-1, std::string(args.GetArgumentAtIndex(i)))));
+ }
+ }
+
+ return success;
+}
+
+CommandAlias::CommandAlias(CommandInterpreter &interpreter,
+ lldb::CommandObjectSP cmd_sp,
+ const char *options_args, const char *name,
+ const char *help, const char *syntax, uint32_t flags)
+ : CommandObject(interpreter, name, help, syntax, flags),
+ m_underlying_command_sp(),
+ m_option_string(options_args ? options_args : ""),
+ m_option_args_sp(new OptionArgVector),
+ m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
+ m_did_set_help_long(false) {
+ if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
+ m_underlying_command_sp = cmd_sp;
+ for (int i = 0;
+ auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
+ i++) {
+ m_arguments.push_back(*cmd_entry);
+ }
+ if (!help || !help[0]) {
+ StreamString sstr;
+ StreamString translation_and_help;
+ GetAliasExpansion(sstr);
+
+ translation_and_help.Printf("(%s) %s", sstr.GetData(),
+ GetUnderlyingCommand()->GetHelp());
+ SetHelp(translation_and_help.GetData());
+ }
+ }
+}
+
+bool CommandAlias::WantsRawCommandString() {
+ if (IsValid())
+ return m_underlying_command_sp->WantsRawCommandString();
+ return false;
+}
+
+bool CommandAlias::WantsCompletion() {
+ if (IsValid())
+ return m_underlying_command_sp->WantsCompletion();
+ return false;
+}
+
+int CommandAlias::HandleCompletion(Args &input, int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements, bool &word_complete,
+ StringList &matches) {
+ if (IsValid())
+ return m_underlying_command_sp->HandleCompletion(
+ input, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, word_complete, matches);
+ return -1;
+}
+
+int CommandAlias::HandleArgumentCompletion(
+ Args &input, int &cursor_index, int &cursor_char_position,
+ OptionElementVector &opt_element_vector, int match_start_point,
+ int max_return_elements, bool &word_complete, StringList &matches) {
+ if (IsValid())
+ return m_underlying_command_sp->HandleArgumentCompletion(
+ input, cursor_index, cursor_char_position, opt_element_vector,
+ match_start_point, max_return_elements, word_complete, matches);
+ return -1;
+}
+
+Options *CommandAlias::GetOptions() {
+ if (IsValid())
+ return m_underlying_command_sp->GetOptions();
+ return nullptr;
+}
+
+bool CommandAlias::Execute(const char *args_string,
+ CommandReturnObject &result) {
+ llvm_unreachable("CommandAlias::Execute is not to be called");
+}
+
+void CommandAlias::GetAliasExpansion(StreamString &help_string) {
+ const char *command_name = m_underlying_command_sp->GetCommandName();
+ help_string.Printf("'%s", command_name);
+
+ if (m_option_args_sp) {
+ OptionArgVector *options = m_option_args_sp.get();
+ for (size_t i = 0; i < options->size(); ++i) {
+ OptionArgPair cur_option = (*options)[i];
+ std::string opt = cur_option.first;
+ OptionArgValue value_pair = cur_option.second;
+ std::string value = value_pair.second;
+ if (opt.compare("<argument>") == 0) {
+ help_string.Printf(" %s", value.c_str());
+ } else {
+ help_string.Printf(" %s", opt.c_str());
+ if ((value.compare("<no-argument>") != 0) &&
+ (value.compare("<need-argument") != 0)) {
+ help_string.Printf(" %s", value.c_str());
+ }
+ }
+ }
+ }
+
+ help_string.Printf("'");
+}
+
+bool CommandAlias::IsDashDashCommand() {
+ if (m_is_dashdash_alias == eLazyBoolCalculate) {
+ m_is_dashdash_alias = eLazyBoolNo;
+ if (IsValid()) {
+ for (const OptionArgPair &opt_arg : *GetOptionArguments()) {
+ if (opt_arg.first == "<argument>" && !opt_arg.second.second.empty() &&
+ llvm::StringRef(opt_arg.second.second).endswith("--")) {
+ m_is_dashdash_alias = eLazyBoolYes;
+ break;
+ }
+ }
+ // if this is a nested alias, it may be adding arguments on top of an
+ // already dash-dash alias
+ if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
+ m_is_dashdash_alias =
+ (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
+ : eLazyBoolNo);
+ }
+ }
+ return (m_is_dashdash_alias == eLazyBoolYes);
+}
+
+bool CommandAlias::IsNestedAlias() {
+ if (GetUnderlyingCommand())
+ return GetUnderlyingCommand()->IsAlias();
+ return false;
+}
+
+std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {
+ auto underlying = GetUnderlyingCommand();
+ if (!underlying)
+ return {nullptr, nullptr};
+
+ if (underlying->IsAlias()) {
+ auto desugared = ((CommandAlias *)underlying.get())->Desugar();
+ auto options = GetOptionArguments();
+ options->insert(options->begin(), desugared.second->begin(),
+ desugared.second->end());
+ return {desugared.first, options};
+ }
- return {underlying,GetOptionArguments()};
+ return {underlying, GetOptionArguments()};
}
-// allow CommandAlias objects to provide their own help, but fallback to the info
+// allow CommandAlias objects to provide their own help, but fallback to the
+// info
// for the underlying command if no customization has been provided
-void
-CommandAlias::SetHelp (const char * str)
-{
- this->CommandObject::SetHelp(str);
- m_did_set_help = true;
-}
-
-void
-CommandAlias::SetHelpLong (const char * str)
-{
- this->CommandObject::SetHelpLong(str);
- m_did_set_help_long = true;
-}
-
-const char*
-CommandAlias::GetHelp ()
-{
- if (!m_cmd_help_short.empty() || m_did_set_help)
- return m_cmd_help_short.c_str();
- if (IsValid())
- return m_underlying_command_sp->GetHelp();
- return nullptr;
-}
-
-const char*
-CommandAlias::GetHelpLong ()
-{
- if (!m_cmd_help_long.empty() || m_did_set_help_long)
- return m_cmd_help_long.c_str();
- if (IsValid())
- return m_underlying_command_sp->GetHelpLong();
- return nullptr;
+void CommandAlias::SetHelp(const char *str) {
+ this->CommandObject::SetHelp(str);
+ m_did_set_help = true;
+}
+
+void CommandAlias::SetHelpLong(const char *str) {
+ this->CommandObject::SetHelpLong(str);
+ m_did_set_help_long = true;
+}
+
+const char *CommandAlias::GetHelp() {
+ if (!m_cmd_help_short.empty() || m_did_set_help)
+ return m_cmd_help_short.c_str();
+ if (IsValid())
+ return m_underlying_command_sp->GetHelp();
+ return nullptr;
+}
+
+const char *CommandAlias::GetHelpLong() {
+ if (!m_cmd_help_long.empty() || m_did_set_help_long)
+ return m_cmd_help_long.c_str();
+ if (IsValid())
+ return m_underlying_command_sp->GetHelpLong();
+ return nullptr;
}
Modified: lldb/trunk/source/Interpreter/CommandHistory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandHistory.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandHistory.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandHistory.cpp Tue Sep 6 15:57:50 2016
@@ -9,134 +9,101 @@
#include <inttypes.h>
-#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Host/StringConvert.h"
+#include "lldb/Interpreter/CommandHistory.h"
using namespace lldb;
using namespace lldb_private;
-CommandHistory::CommandHistory() : m_mutex(), m_history()
-{}
+CommandHistory::CommandHistory() : m_mutex(), m_history() {}
-CommandHistory::~CommandHistory ()
-{}
+CommandHistory::~CommandHistory() {}
-size_t
-CommandHistory::GetSize () const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_history.size();
-}
-
-bool
-CommandHistory::IsEmpty () const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_history.empty();
-}
-
-const char*
-CommandHistory::FindString (const char* input_str) const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (!input_str)
- return nullptr;
- if (input_str[0] != g_repeat_char)
- return nullptr;
- if (input_str[1] == '-')
- {
- bool success;
- size_t idx = StringConvert::ToUInt32 (input_str+2, 0, 0, &success);
- if (!success)
- return nullptr;
- if (idx > m_history.size())
- return nullptr;
- idx = m_history.size() - idx;
- return m_history[idx].c_str();
-
- }
- else if (input_str[1] == g_repeat_char)
- {
- if (m_history.empty())
- return nullptr;
- else
- return m_history.back().c_str();
- }
- else
- {
- bool success;
- uint32_t idx = StringConvert::ToUInt32 (input_str+1, 0, 0, &success);
- if (!success)
- return nullptr;
- if (idx >= m_history.size())
- return nullptr;
- return m_history[idx].c_str();
- }
+size_t CommandHistory::GetSize() const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ return m_history.size();
}
-const char*
-CommandHistory::GetStringAtIndex (size_t idx) const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (idx < m_history.size())
- return m_history[idx].c_str();
- return nullptr;
+bool CommandHistory::IsEmpty() const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ return m_history.empty();
}
-const char*
-CommandHistory::operator [] (size_t idx) const
-{
- return GetStringAtIndex(idx);
-}
+const char *CommandHistory::FindString(const char *input_str) const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (!input_str)
+ return nullptr;
+ if (input_str[0] != g_repeat_char)
+ return nullptr;
+ if (input_str[1] == '-') {
+ bool success;
+ size_t idx = StringConvert::ToUInt32(input_str + 2, 0, 0, &success);
+ if (!success)
+ return nullptr;
+ if (idx > m_history.size())
+ return nullptr;
+ idx = m_history.size() - idx;
+ return m_history[idx].c_str();
-const char*
-CommandHistory::GetRecentmostString () const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ } else if (input_str[1] == g_repeat_char) {
if (m_history.empty())
- return nullptr;
- return m_history.back().c_str();
+ return nullptr;
+ else
+ return m_history.back().c_str();
+ } else {
+ bool success;
+ uint32_t idx = StringConvert::ToUInt32(input_str + 1, 0, 0, &success);
+ if (!success)
+ return nullptr;
+ if (idx >= m_history.size())
+ return nullptr;
+ return m_history[idx].c_str();
+ }
+}
+
+const char *CommandHistory::GetStringAtIndex(size_t idx) const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (idx < m_history.size())
+ return m_history[idx].c_str();
+ return nullptr;
+}
+
+const char *CommandHistory::operator[](size_t idx) const {
+ return GetStringAtIndex(idx);
+}
+
+const char *CommandHistory::GetRecentmostString() const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (m_history.empty())
+ return nullptr;
+ return m_history.back().c_str();
}
-void
-CommandHistory::AppendString (const std::string& str,
- bool reject_if_dupe)
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (reject_if_dupe)
- {
- if (!m_history.empty())
- {
- if (str == m_history.back())
- return;
- }
+void CommandHistory::AppendString(const std::string &str, bool reject_if_dupe) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (reject_if_dupe) {
+ if (!m_history.empty()) {
+ if (str == m_history.back())
+ return;
}
- m_history.push_back(std::string(str));
+ }
+ m_history.push_back(std::string(str));
}
-void
-CommandHistory::Clear ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- m_history.clear();
-}
-
-void
-CommandHistory::Dump (Stream& stream,
- size_t start_idx,
- size_t stop_idx) const
-{
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- stop_idx = std::min(stop_idx + 1, m_history.size());
- for (size_t counter = start_idx;
- counter < stop_idx;
- counter++)
- {
- const std::string hist_item = m_history[counter];
- if (!hist_item.empty())
- {
- stream.Indent();
- stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str());
- }
+void CommandHistory::Clear() {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ m_history.clear();
+}
+
+void CommandHistory::Dump(Stream &stream, size_t start_idx,
+ size_t stop_idx) const {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ stop_idx = std::min(stop_idx + 1, m_history.size());
+ for (size_t counter = start_idx; counter < stop_idx; counter++) {
+ const std::string hist_item = m_history[counter];
+ if (!hist_item.empty()) {
+ stream.Indent();
+ stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str());
}
+ }
}
Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Tue Sep 6 15:57:50 2016
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
+#include <stdlib.h>
#include <string>
#include <vector>
-#include <stdlib.h>
#include "CommandObjectScript.h"
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
@@ -18,11 +18,13 @@
#include "../Commands/CommandObjectArgs.h"
#include "../Commands/CommandObjectBreakpoint.h"
#include "../Commands/CommandObjectBugreport.h"
+#include "../Commands/CommandObjectCommands.h"
#include "../Commands/CommandObjectDisassemble.h"
#include "../Commands/CommandObjectExpression.h"
#include "../Commands/CommandObjectFrame.h"
#include "../Commands/CommandObjectGUI.h"
#include "../Commands/CommandObjectHelp.h"
+#include "../Commands/CommandObjectLanguage.h"
#include "../Commands/CommandObjectLog.h"
#include "../Commands/CommandObjectMemory.h"
#include "../Commands/CommandObjectPlatform.h"
@@ -32,14 +34,12 @@
#include "../Commands/CommandObjectRegister.h"
#include "../Commands/CommandObjectSettings.h"
#include "../Commands/CommandObjectSource.h"
-#include "../Commands/CommandObjectCommands.h"
#include "../Commands/CommandObjectSyntax.h"
#include "../Commands/CommandObjectTarget.h"
#include "../Commands/CommandObjectThread.h"
#include "../Commands/CommandObjectType.h"
#include "../Commands/CommandObjectVersion.h"
#include "../Commands/CommandObjectWatchpoint.h"
-#include "../Commands/CommandObjectLanguage.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
@@ -59,19 +59,18 @@
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
-
#include "lldb/Target/Process.h"
-#include "lldb/Target/Thread.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Target/Thread.h"
#include "lldb/Utility/CleanUp.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
using namespace lldb;
@@ -79,3235 +78,3020 @@ using namespace lldb_private;
static const char *k_white_space = " \t\v";
-static PropertyDefinition
-g_properties[] =
-{
- { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
- { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
- { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
- { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." },
- { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr }
-};
+static PropertyDefinition g_properties[] = {
+ {"expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr,
+ nullptr, "If true, regular expression alias commands will show the "
+ "expanded command that will be executed. This can be used to "
+ "debug new regular expression alias commands."},
+ {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ "If true, LLDB will prompt you before quitting if there are any live "
+ "processes being debugged. If false, LLDB will quit without asking in any "
+ "case."},
+ {"stop-command-source-on-error", OptionValue::eTypeBoolean, true, true,
+ nullptr, nullptr, "If true, LLDB will stop running a 'command source' "
+ "script upon encountering an error."},
+ {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr,
+ nullptr,
+ "If true, blank lines will be printed between between REPL submissions."},
+ {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
-enum
-{
- ePropertyExpandRegexAliases = 0,
- ePropertyPromptOnQuit = 1,
- ePropertyStopCmdSourceOnError = 2,
- eSpaceReplPrompts = 3
+enum {
+ ePropertyExpandRegexAliases = 0,
+ ePropertyPromptOnQuit = 1,
+ ePropertyStopCmdSourceOnError = 2,
+ eSpaceReplPrompts = 3
};
-ConstString &
-CommandInterpreter::GetStaticBroadcasterClass ()
-{
- static ConstString class_name ("lldb.commandInterpreter");
- return class_name;
+ConstString &CommandInterpreter::GetStaticBroadcasterClass() {
+ static ConstString class_name("lldb.commandInterpreter");
+ return class_name;
}
-CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution)
- : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
- Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
+CommandInterpreter::CommandInterpreter(Debugger &debugger,
+ ScriptLanguage script_language,
+ bool synchronous_execution)
+ : Broadcaster(debugger.GetBroadcasterManager(),
+ CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
+ Properties(OptionValuePropertiesSP(
+ new OptionValueProperties(ConstString("interpreter")))),
IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
- m_debugger(debugger),
- m_synchronous_execution(synchronous_execution),
- m_skip_lldbinit_files(false),
- m_skip_app_init_files(false),
- m_script_interpreter_sp(),
- m_command_io_handler_sp(),
- m_comment_char('#'),
- m_batch_command_mode(false),
- m_truncation_warning(eNoTruncation),
- m_command_source_depth(0),
- m_num_errors(0),
- m_quit_requested(false),
- m_stopped_for_crash(false)
-{
- debugger.SetScriptLanguage (script_language);
- SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
- SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
- SetEventName (eBroadcastBitQuitCommandReceived, "quit");
- CheckInWithManager ();
- m_collection_sp->Initialize (g_properties);
-}
+ m_debugger(debugger), m_synchronous_execution(synchronous_execution),
+ m_skip_lldbinit_files(false), m_skip_app_init_files(false),
+ m_script_interpreter_sp(), m_command_io_handler_sp(), m_comment_char('#'),
+ m_batch_command_mode(false), m_truncation_warning(eNoTruncation),
+ m_command_source_depth(0), m_num_errors(0), m_quit_requested(false),
+ m_stopped_for_crash(false) {
+ debugger.SetScriptLanguage(script_language);
+ SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
+ SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
+ SetEventName(eBroadcastBitQuitCommandReceived, "quit");
+ CheckInWithManager();
+ m_collection_sp->Initialize(g_properties);
+}
+
+bool CommandInterpreter::GetExpandRegexAliases() const {
+ const uint32_t idx = ePropertyExpandRegexAliases;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool CommandInterpreter::GetPromptOnQuit() const {
+ const uint32_t idx = ePropertyPromptOnQuit;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void CommandInterpreter::SetPromptOnQuit(bool b) {
+ const uint32_t idx = ePropertyPromptOnQuit;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
+void CommandInterpreter::ResolveCommand(const char *command_line,
+ CommandReturnObject &result) {
+ std::string command = command_line;
+ if (ResolveCommandImpl(command, result) != nullptr) {
+ result.AppendMessageWithFormat("%s", command.c_str());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+}
+
+bool CommandInterpreter::GetStopCmdSourceOnError() const {
+ const uint32_t idx = ePropertyStopCmdSourceOnError;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool CommandInterpreter::GetSpaceReplPrompts() const {
+ const uint32_t idx = eSpaceReplPrompts;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void CommandInterpreter::Initialize() {
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ CommandReturnObject result;
+
+ LoadCommandDictionary();
+
+ // An alias arguments vector to reuse - reset it before use...
+ OptionArgVectorSP alias_arguments_vector_sp(new OptionArgVector);
+
+ // Set up some initial aliases.
+ CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit", false);
+ if (cmd_obj_sp) {
+ AddAlias("q", cmd_obj_sp);
+ AddAlias("exit", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-attach", false);
+ if (cmd_obj_sp)
+ AddAlias("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("process detach", false);
+ if (cmd_obj_sp) {
+ AddAlias("detach", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("process continue", false);
+ if (cmd_obj_sp) {
+ AddAlias("c", cmd_obj_sp);
+ AddAlias("continue", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-break", false);
+ if (cmd_obj_sp)
+ AddAlias("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-tbreak", false);
+ if (cmd_obj_sp)
+ AddAlias("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("thread step-inst", false);
+ if (cmd_obj_sp) {
+ AddAlias("stepi", cmd_obj_sp);
+ AddAlias("si", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("thread step-inst-over", false);
+ if (cmd_obj_sp) {
+ AddAlias("nexti", cmd_obj_sp);
+ AddAlias("ni", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("thread step-in", false);
+ if (cmd_obj_sp) {
+ AddAlias("s", cmd_obj_sp);
+ AddAlias("step", cmd_obj_sp);
+ CommandAlias *sif_alias = AddAlias(
+ "sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
+ if (sif_alias) {
+ sif_alias->SetHelp("Step through the current block, stopping if you step "
+ "directly into a function whose name matches the "
+ "TargetFunctionName.");
+ sif_alias->SetSyntax("sif <TargetFunctionName>");
+ }
+ }
+
+ cmd_obj_sp = GetCommandSPExact("thread step-over", false);
+ if (cmd_obj_sp) {
+ AddAlias("n", cmd_obj_sp);
+ AddAlias("next", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("thread step-out", false);
+ if (cmd_obj_sp) {
+ AddAlias("finish", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("frame select", false);
+ if (cmd_obj_sp) {
+ AddAlias("f", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("thread select", false);
+ if (cmd_obj_sp) {
+ AddAlias("t", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-jump", false);
+ if (cmd_obj_sp) {
+ AddAlias("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ AddAlias("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ }
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-list", false);
+ if (cmd_obj_sp) {
+ AddAlias("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ AddAlias("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ }
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-env", false);
+ if (cmd_obj_sp)
+ AddAlias("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("memory read", false);
+ if (cmd_obj_sp)
+ AddAlias("x", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-up", false);
+ if (cmd_obj_sp)
+ AddAlias("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-down", false);
+ if (cmd_obj_sp)
+ AddAlias("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-display", false);
+ if (cmd_obj_sp)
+ AddAlias("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("disassemble", false);
+ if (cmd_obj_sp)
+ AddAlias("dis", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact("disassemble", false);
+ if (cmd_obj_sp)
+ AddAlias("di", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-undisplay", false);
+ if (cmd_obj_sp)
+ AddAlias("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("_regexp-bt", false);
+ if (cmd_obj_sp)
+ AddAlias("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+
+ cmd_obj_sp = GetCommandSPExact("target create", false);
+ if (cmd_obj_sp)
+ AddAlias("file", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact("target modules", false);
+ if (cmd_obj_sp)
+ AddAlias("image", cmd_obj_sp);
+
+ alias_arguments_vector_sp.reset(new OptionArgVector);
+
+ cmd_obj_sp = GetCommandSPExact("expression", false);
+ if (cmd_obj_sp) {
+ AddAlias("p", cmd_obj_sp, "--")->SetHelpLong("");
+ AddAlias("print", cmd_obj_sp, "--")->SetHelpLong("");
+ AddAlias("call", cmd_obj_sp, "--")->SetHelpLong("");
+ if (auto po = AddAlias("po", cmd_obj_sp, "-O --")) {
+ po->SetHelp("Evaluate an expression on the current thread. Displays any "
+ "returned value with formatting "
+ "controlled by the type's author.");
+ po->SetHelpLong("");
+ }
+ AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
+ AddAlias("poarray", cmd_obj_sp,
+ "--object-description --element-count %1 --")
+ ->SetHelpLong("");
+ }
+
+ cmd_obj_sp = GetCommandSPExact("process kill", false);
+ if (cmd_obj_sp) {
+ AddAlias("kill", cmd_obj_sp);
+ }
-bool
-CommandInterpreter::GetExpandRegexAliases () const
-{
- const uint32_t idx = ePropertyExpandRegexAliases;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
-}
-
-bool
-CommandInterpreter::GetPromptOnQuit () const
-{
- const uint32_t idx = ePropertyPromptOnQuit;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
-}
+ cmd_obj_sp = GetCommandSPExact("process launch", false);
+ if (cmd_obj_sp) {
+ alias_arguments_vector_sp.reset(new OptionArgVector);
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ AddAlias("r", cmd_obj_sp, "--");
+ AddAlias("run", cmd_obj_sp, "--");
+#else
+#if defined(__APPLE__)
+ std::string shell_option;
+ shell_option.append("--shell-expand-args");
+ shell_option.append(" true");
+ shell_option.append(" --");
+ AddAlias("r", cmd_obj_sp, "--shell-expand-args true --");
+ AddAlias("run", cmd_obj_sp, "--shell-expand-args true --");
+#else
+ StreamString defaultshell;
+ defaultshell.Printf("--shell=%s --",
+ HostInfo::GetDefaultShell().GetPath().c_str());
+ AddAlias("r", cmd_obj_sp, defaultshell.GetData());
+ AddAlias("run", cmd_obj_sp, defaultshell.GetData());
+#endif
+#endif
+ }
-void
-CommandInterpreter::SetPromptOnQuit (bool b)
-{
- const uint32_t idx = ePropertyPromptOnQuit;
- m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, idx, b);
-}
+ cmd_obj_sp = GetCommandSPExact("target symbols add", false);
+ if (cmd_obj_sp) {
+ AddAlias("add-dsym", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact("breakpoint set", false);
+ if (cmd_obj_sp) {
+ AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
+ }
+}
+
+void CommandInterpreter::Clear() {
+ m_command_io_handler_sp.reset();
+
+ if (m_script_interpreter_sp)
+ m_script_interpreter_sp->Clear();
+}
+
+const char *CommandInterpreter::ProcessEmbeddedScriptCommands(const char *arg) {
+ // This function has not yet been implemented.
+
+ // Look for any embedded script command
+ // If found,
+ // get interpreter object from the command dictionary,
+ // call execute_one_command on it,
+ // get the results as a string,
+ // substitute that string for current stuff.
+
+ return arg;
+}
+
+void CommandInterpreter::LoadCommandDictionary() {
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
+
+ m_command_dict["apropos"] = CommandObjectSP(new CommandObjectApropos(*this));
+ m_command_dict["breakpoint"] =
+ CommandObjectSP(new CommandObjectMultiwordBreakpoint(*this));
+ m_command_dict["bugreport"] =
+ CommandObjectSP(new CommandObjectMultiwordBugreport(*this));
+ m_command_dict["command"] =
+ CommandObjectSP(new CommandObjectMultiwordCommands(*this));
+ m_command_dict["disassemble"] =
+ CommandObjectSP(new CommandObjectDisassemble(*this));
+ m_command_dict["expression"] =
+ CommandObjectSP(new CommandObjectExpression(*this));
+ m_command_dict["frame"] =
+ CommandObjectSP(new CommandObjectMultiwordFrame(*this));
+ m_command_dict["gui"] = CommandObjectSP(new CommandObjectGUI(*this));
+ m_command_dict["help"] = CommandObjectSP(new CommandObjectHelp(*this));
+ m_command_dict["log"] = CommandObjectSP(new CommandObjectLog(*this));
+ m_command_dict["memory"] = CommandObjectSP(new CommandObjectMemory(*this));
+ m_command_dict["platform"] =
+ CommandObjectSP(new CommandObjectPlatform(*this));
+ m_command_dict["plugin"] = CommandObjectSP(new CommandObjectPlugin(*this));
+ m_command_dict["process"] =
+ CommandObjectSP(new CommandObjectMultiwordProcess(*this));
+ m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this));
+ m_command_dict["register"] =
+ CommandObjectSP(new CommandObjectRegister(*this));
+ m_command_dict["script"] =
+ CommandObjectSP(new CommandObjectScript(*this, script_language));
+ m_command_dict["settings"] =
+ CommandObjectSP(new CommandObjectMultiwordSettings(*this));
+ m_command_dict["source"] =
+ CommandObjectSP(new CommandObjectMultiwordSource(*this));
+ m_command_dict["target"] =
+ CommandObjectSP(new CommandObjectMultiwordTarget(*this));
+ m_command_dict["thread"] =
+ CommandObjectSP(new CommandObjectMultiwordThread(*this));
+ m_command_dict["type"] = CommandObjectSP(new CommandObjectType(*this));
+ m_command_dict["version"] = CommandObjectSP(new CommandObjectVersion(*this));
+ m_command_dict["watchpoint"] =
+ CommandObjectSP(new CommandObjectMultiwordWatchpoint(*this));
+ m_command_dict["language"] =
+ CommandObjectSP(new CommandObjectLanguage(*this));
+
+ const char *break_regexes[][2] = {
+ {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
+ "breakpoint set --file '%1' --line %2"},
+ {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
+ {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
+ {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
+ {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
+ "breakpoint set --name '%1'"},
+ {"^(-.*)$", "breakpoint set %1"},
+ {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
+ "breakpoint set --name '%2' --shlib '%1'"},
+ {"^\\&(.*[^[:space:]])[[:space:]]*$",
+ "breakpoint set --name '%1' --skip-prologue=0"},
+ {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
+ "breakpoint set --name '%1'"}};
+
+ size_t num_regexes = llvm::array_lengthof(break_regexes);
+
+ std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-break",
+ "Set a breakpoint using one of several shorthand formats.\n",
+ "\n"
+ "_regexp-break <filename>:<linenum>\n"
+ " main.c:12 // Break at line 12 of "
+ "main.c\n\n"
+ "_regexp-break <linenum>\n"
+ " 12 // Break at line 12 of current "
+ "file\n\n"
+ "_regexp-break 0x<address>\n"
+ " 0x1234000 // Break at address "
+ "0x1234000\n\n"
+ "_regexp-break <name>\n"
+ " main // Break in 'main' after the "
+ "prologue\n\n"
+ "_regexp-break &<name>\n"
+ " &main // Break at first instruction "
+ "in 'main'\n\n"
+ "_regexp-break <module>`<name>\n"
+ " libc.so`malloc // Break in 'malloc' from "
+ "'libc.so'\n\n"
+ "_regexp-break /<source-regex>/\n"
+ " /break here/ // Break on source lines in "
+ "current file\n"
+ " // containing text 'break "
+ "here'.\n",
+ 2, CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion,
+ false));
+
+ if (break_regex_cmd_ap.get()) {
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++) {
+ success = break_regex_cmd_ap->AddRegexCommand(break_regexes[i][0],
+ break_regexes[i][1]);
+ if (!success)
+ break;
+ }
+ success =
+ break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success) {
+ CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
+ m_command_dict[break_regex_cmd_sp->GetCommandName()] = break_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-tbreak",
+ "Set a one-shot breakpoint using one of several shorthand formats.\n",
+ "\n"
+ "_regexp-break <filename>:<linenum>\n"
+ " main.c:12 // Break at line 12 of "
+ "main.c\n\n"
+ "_regexp-break <linenum>\n"
+ " 12 // Break at line 12 of current "
+ "file\n\n"
+ "_regexp-break 0x<address>\n"
+ " 0x1234000 // Break at address "
+ "0x1234000\n\n"
+ "_regexp-break <name>\n"
+ " main // Break in 'main' after the "
+ "prologue\n\n"
+ "_regexp-break &<name>\n"
+ " &main // Break at first instruction "
+ "in 'main'\n\n"
+ "_regexp-break <module>`<name>\n"
+ " libc.so`malloc // Break in 'malloc' from "
+ "'libc.so'\n\n"
+ "_regexp-break /<source-regex>/\n"
+ " /break here/ // Break on source lines in "
+ "current file\n"
+ " // containing text 'break "
+ "here'.\n",
+ 2, CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion,
+ false));
+
+ if (tbreak_regex_cmd_ap.get()) {
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++) {
+ // If you add a resultant command string longer than 1024 characters be
+ // sure to increase the size of this buffer.
+ char buffer[1024];
+ int num_printed =
+ snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
+ assert(num_printed < 1024);
+ UNUSED_IF_ASSERT_DISABLED(num_printed);
+ success =
+ tbreak_regex_cmd_ap->AddRegexCommand(break_regexes[i][0], buffer);
+ if (!success)
+ break;
+ }
+ success =
+ tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success) {
+ CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
+ m_command_dict[tbreak_regex_cmd_sp->GetCommandName()] =
+ tbreak_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-attach", "Attach to process by ID or name.",
+ "_regexp-attach <pid> | <process-name>", 2, 0, false));
+ if (attach_regex_cmd_ap.get()) {
+ if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$",
+ "process attach --pid %1") &&
+ attach_regex_cmd_ap->AddRegexCommand(
+ "^(-.*|.* -.*)$", "process attach %1") && // Any options that are
+ // specified get passed to
+ // 'process attach'
+ attach_regex_cmd_ap->AddRegexCommand("^(.+)$",
+ "process attach --name '%1'") &&
+ attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) {
+ CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
+ m_command_dict[attach_regex_cmd_sp->GetCommandName()] =
+ attach_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_ap(
+ new CommandObjectRegexCommand(*this, "_regexp-down",
+ "Select a newer stack frame. Defaults to "
+ "moving one frame, a numeric argument can "
+ "specify an arbitrary number.",
+ "_regexp-down [<count>]", 2, 0, false));
+ if (down_regex_cmd_ap.get()) {
+ if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
+ down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$",
+ "frame select -r -%1")) {
+ CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
+ m_command_dict[down_regex_cmd_sp->GetCommandName()] = down_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-up",
+ "Select an older stack frame. Defaults to moving one "
+ "frame, a numeric argument can specify an arbitrary number.",
+ "_regexp-up [<count>]", 2, 0, false));
+ if (up_regex_cmd_ap.get()) {
+ if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
+ up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) {
+ CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
+ m_command_dict[up_regex_cmd_sp->GetCommandName()] = up_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-display",
+ "Evaluate an expression at every stop (see 'help target stop-hook'.)",
+ "_regexp-display expression", 2, 0, false));
+ if (display_regex_cmd_ap.get()) {
+ if (display_regex_cmd_ap->AddRegexCommand(
+ "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) {
+ CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
+ m_command_dict[display_regex_cmd_sp->GetCommandName()] =
+ display_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-undisplay", "Stop displaying expression at every "
+ "stop (specified by stop-hook index.)",
+ "_regexp-undisplay stop-hook-number", 2, 0, false));
+ if (undisplay_regex_cmd_ap.get()) {
+ if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$",
+ "target stop-hook delete %1")) {
+ CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
+ m_command_dict[undisplay_regex_cmd_sp->GetCommandName()] =
+ undisplay_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "gdb-remote", "Connect to a process via remote GDB server. "
+ "If no host is specifed, localhost is assumed.",
+ "gdb-remote [<hostname>:]<portnum>", 2, 0, false));
+ if (connect_gdb_remote_cmd_ap.get()) {
+ if (connect_gdb_remote_cmd_ap->AddRegexCommand(
+ "^([^:]+:[[:digit:]]+)$",
+ "process connect --plugin gdb-remote connect://%1") &&
+ connect_gdb_remote_cmd_ap->AddRegexCommand(
+ "^([[:digit:]]+)$",
+ "process connect --plugin gdb-remote connect://localhost:%1")) {
+ CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "kdp-remote", "Connect to a process via remote KDP server. "
+ "If no UDP port is specified, port 41139 is "
+ "assumed.",
+ "kdp-remote <hostname>[:<portnum>]", 2, 0, false));
+ if (connect_kdp_remote_cmd_ap.get()) {
+ if (connect_kdp_remote_cmd_ap->AddRegexCommand(
+ "^([^:]+:[[:digit:]]+)$",
+ "process connect --plugin kdp-remote udp://%1") &&
+ connect_kdp_remote_cmd_ap->AddRegexCommand(
+ "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) {
+ CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-bt",
+ "Show the current thread's call stack. Any numeric argument "
+ "displays at most that many "
+ "frames. The argument 'all' displays all threads.",
+ "bt [<digit> | all]", 2, 0, false));
+ if (bt_regex_cmd_ap.get()) {
+ // accept but don't document "bt -c <number>" -- before bt was a regex
+ // command if you wanted to backtrace
+ // three frames you would do "bt -c 3" but the intention is to have this
+ // emulate the gdb "bt" command and
+ // so now "bt 3" is the preferred form, in line with gdb.
+ if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$",
+ "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$",
+ "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
+ bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) {
+ CommandObjectSP command_sp(bt_regex_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-list",
+ "List relevant source code using one of several shorthand formats.",
+ "\n"
+ "_regexp-list <file>:<line> // List around specific file/line\n"
+ "_regexp-list <line> // List current file around specified "
+ "line\n"
+ "_regexp-list <function-name> // List specified function\n"
+ "_regexp-list 0x<address> // List around specified address\n"
+ "_regexp-list -[<count>] // List previous <count> lines\n"
+ "_regexp-list // List subsequent lines",
+ 2, CommandCompletions::eSourceFileCompletion, false));
+ if (list_regex_cmd_ap.get()) {
+ if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$",
+ "source list --line %1") &&
+ list_regex_cmd_ap->AddRegexCommand(
+ "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
+ "]*$",
+ "source list --file '%1' --line %2") &&
+ list_regex_cmd_ap->AddRegexCommand(
+ "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
+ "source list --address %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$",
+ "source list --reverse") &&
+ list_regex_cmd_ap->AddRegexCommand(
+ "^-([[:digit:]]+)[[:space:]]*$",
+ "source list --reverse --count %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^(.+)$",
+ "source list --name \"%1\"") &&
+ list_regex_cmd_ap->AddRegexCommand("^$", "source list")) {
+ CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
+ m_command_dict[list_regex_cmd_sp->GetCommandName()] = list_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-env",
+ "Shorthand for viewing and setting environment variables.",
+ "\n"
+ "_regexp-env // Show enrivonment\n"
+ "_regexp-env <name>=<value> // Set an environment variable",
+ 2, 0, false));
+ if (env_regex_cmd_ap.get()) {
+ if (env_regex_cmd_ap->AddRegexCommand("^$",
+ "settings show target.env-vars") &&
+ env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$",
+ "settings set target.env-vars %1")) {
+ CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
+ m_command_dict[env_regex_cmd_sp->GetCommandName()] = env_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_ap(
+ new CommandObjectRegexCommand(
+ *this, "_regexp-jump", "Set the program counter to a new address.",
+ "\n"
+ "_regexp-jump <line>\n"
+ "_regexp-jump +<line-offset> | -<line-offset>\n"
+ "_regexp-jump <file>:<line>\n"
+ "_regexp-jump *<addr>\n",
+ 2, 0, false));
+ if (jump_regex_cmd_ap.get()) {
+ if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$",
+ "thread jump --addr %1") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$",
+ "thread jump --line %1") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$",
+ "thread jump --file %1 --line %2") &&
+ jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$",
+ "thread jump --by %1")) {
+ CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
+ m_command_dict[jump_regex_cmd_sp->GetCommandName()] = jump_regex_cmd_sp;
+ }
+ }
+}
+
+int CommandInterpreter::GetCommandNamesMatchingPartialString(
+ const char *cmd_str, bool include_aliases, StringList &matches) {
+ AddNamesMatchingPartialString(m_command_dict, cmd_str, matches);
+
+ if (include_aliases) {
+ AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches);
+ }
+
+ return matches.GetSize();
+}
+
+CommandObjectSP CommandInterpreter::GetCommandSP(const char *cmd_cstr,
+ bool include_aliases,
+ bool exact,
+ StringList *matches) {
+ CommandObject::CommandMap::iterator pos;
+ CommandObjectSP command_sp;
-void
-CommandInterpreter::ResolveCommand(const char *command_line, CommandReturnObject &result)
-{
- std::string command = command_line;
- if (ResolveCommandImpl(command, result) != nullptr) {
- result.AppendMessageWithFormat("%s", command.c_str());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- }
-}
+ std::string cmd(cmd_cstr);
+ if (HasCommands()) {
+ pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end())
+ command_sp = pos->second;
+ }
-bool
-CommandInterpreter::GetStopCmdSourceOnError () const
-{
- const uint32_t idx = ePropertyStopCmdSourceOnError;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
-}
+ if (include_aliases && HasAliases()) {
+ auto alias_pos = m_alias_dict.find(cmd);
+ if (alias_pos != m_alias_dict.end())
+ command_sp = alias_pos->second;
+ }
-bool
-CommandInterpreter::GetSpaceReplPrompts () const
-{
- const uint32_t idx = eSpaceReplPrompts;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
-}
+ if (HasUserCommands()) {
+ pos = m_user_dict.find(cmd);
+ if (pos != m_user_dict.end())
+ command_sp = pos->second;
+ }
-void
-CommandInterpreter::Initialize ()
-{
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ if (!exact && !command_sp) {
+ // We will only get into here if we didn't find any exact matches.
- CommandReturnObject result;
+ CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
- LoadCommandDictionary ();
+ StringList local_matches;
+ if (matches == nullptr)
+ matches = &local_matches;
- // An alias arguments vector to reuse - reset it before use...
- OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
-
- // Set up some initial aliases.
- CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
- if (cmd_obj_sp)
- {
- AddAlias ("q", cmd_obj_sp);
- AddAlias ("exit", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
- if (cmd_obj_sp)
- AddAlias ("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("process detach",false);
- if (cmd_obj_sp)
- {
- AddAlias ("detach", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("process continue", false);
- if (cmd_obj_sp)
- {
- AddAlias ("c", cmd_obj_sp);
- AddAlias ("continue", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
- if (cmd_obj_sp)
- AddAlias ("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
- if (cmd_obj_sp)
- AddAlias ("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
- if (cmd_obj_sp)
- {
- AddAlias ("stepi", cmd_obj_sp);
- AddAlias ("si", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
- if (cmd_obj_sp)
- {
- AddAlias ("nexti", cmd_obj_sp);
- AddAlias ("ni", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
- if (cmd_obj_sp)
- {
- AddAlias ("s", cmd_obj_sp);
- AddAlias ("step", cmd_obj_sp);
- CommandAlias *sif_alias = AddAlias ("sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
- if (sif_alias)
- {
- sif_alias->SetHelp("Step through the current block, stopping if you step "
- "directly into a function whose name matches the TargetFunctionName.");
- sif_alias->SetSyntax("sif <TargetFunctionName>");
- }
- }
+ unsigned int num_cmd_matches = 0;
+ unsigned int num_alias_matches = 0;
+ unsigned int num_user_matches = 0;
- cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
- if (cmd_obj_sp)
- {
- AddAlias ("n", cmd_obj_sp);
- AddAlias ("next", cmd_obj_sp);
- }
+ // Look through the command dictionaries one by one, and if we get only one
+ // match from any of
+ // them in toto, then return that, otherwise return an empty CommandObjectSP
+ // and the list of matches.
- cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
- if (cmd_obj_sp)
- {
- AddAlias ("finish", cmd_obj_sp);
+ if (HasCommands()) {
+ num_cmd_matches =
+ AddNamesMatchingPartialString(m_command_dict, cmd_cstr, *matches);
}
- cmd_obj_sp = GetCommandSPExact ("frame select", false);
- if (cmd_obj_sp)
- {
- AddAlias ("f", cmd_obj_sp);
+ if (num_cmd_matches == 1) {
+ cmd.assign(matches->GetStringAtIndex(0));
+ pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end())
+ real_match_sp = pos->second;
}
- cmd_obj_sp = GetCommandSPExact ("thread select", false);
- if (cmd_obj_sp)
- {
- AddAlias ("t", cmd_obj_sp);
+ if (include_aliases && HasAliases()) {
+ num_alias_matches =
+ AddNamesMatchingPartialString(m_alias_dict, cmd_cstr, *matches);
}
- cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
- if (cmd_obj_sp)
- {
- AddAlias ("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- AddAlias ("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ if (num_alias_matches == 1) {
+ cmd.assign(matches->GetStringAtIndex(num_cmd_matches));
+ auto alias_pos = m_alias_dict.find(cmd);
+ if (alias_pos != m_alias_dict.end())
+ alias_match_sp = alias_pos->second;
}
- cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
- if (cmd_obj_sp)
- {
- AddAlias ("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- AddAlias ("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ if (HasUserCommands()) {
+ num_user_matches =
+ AddNamesMatchingPartialString(m_user_dict, cmd_cstr, *matches);
}
- cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
- if (cmd_obj_sp)
- AddAlias ("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("memory read", false);
- if (cmd_obj_sp)
- AddAlias ("x", cmd_obj_sp);
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
- if (cmd_obj_sp)
- AddAlias ("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
- if (cmd_obj_sp)
- AddAlias ("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ if (num_user_matches == 1) {
+ cmd.assign(
+ matches->GetStringAtIndex(num_cmd_matches + num_alias_matches));
- cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
- if (cmd_obj_sp)
- AddAlias ("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("disassemble", false);
- if (cmd_obj_sp)
- AddAlias ("dis", cmd_obj_sp);
-
- cmd_obj_sp = GetCommandSPExact ("disassemble", false);
- if (cmd_obj_sp)
- AddAlias ("di", cmd_obj_sp);
-
-
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
- if (cmd_obj_sp)
- AddAlias ("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
- if (cmd_obj_sp)
- AddAlias ("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
-
- cmd_obj_sp = GetCommandSPExact ("target create", false);
- if (cmd_obj_sp)
- AddAlias ("file", cmd_obj_sp);
+ pos = m_user_dict.find(cmd);
+ if (pos != m_user_dict.end())
+ user_match_sp = pos->second;
+ }
- cmd_obj_sp = GetCommandSPExact ("target modules", false);
- if (cmd_obj_sp)
- AddAlias ("image", cmd_obj_sp);
+ // If we got exactly one match, return that, otherwise return the match
+ // list.
+ if (num_user_matches + num_cmd_matches + num_alias_matches == 1) {
+ if (num_cmd_matches)
+ return real_match_sp;
+ else if (num_alias_matches)
+ return alias_match_sp;
+ else
+ return user_match_sp;
+ }
+ } else if (matches && command_sp) {
+ matches->AppendString(cmd_cstr);
+ }
- alias_arguments_vector_sp.reset(new OptionArgVector);
+ return command_sp;
+}
- cmd_obj_sp = GetCommandSPExact ("expression", false);
- if (cmd_obj_sp)
- {
- AddAlias ("p", cmd_obj_sp, "--")->SetHelpLong("");
- AddAlias ("print", cmd_obj_sp, "--")->SetHelpLong("");
- AddAlias ("call", cmd_obj_sp, "--")->SetHelpLong("");
- if (auto po = AddAlias ("po", cmd_obj_sp, "-O --"))
- {
- po->SetHelp("Evaluate an expression on the current thread. Displays any returned value with formatting "
- "controlled by the type's author.");
- po->SetHelpLong("");
- }
- AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
- AddAlias("poarray", cmd_obj_sp, "--object-description --element-count %1 --")->SetHelpLong("");
- }
-
- cmd_obj_sp = GetCommandSPExact ("process kill", false);
- if (cmd_obj_sp)
- {
- AddAlias ("kill", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("process launch", false);
- if (cmd_obj_sp)
- {
- alias_arguments_vector_sp.reset (new OptionArgVector);
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- AddAlias ("r", cmd_obj_sp, "--");
- AddAlias ("run", cmd_obj_sp, "--");
-#else
- #if defined(__APPLE__)
- std::string shell_option;
- shell_option.append("--shell-expand-args");
- shell_option.append(" true");
- shell_option.append(" --");
- AddAlias ("r", cmd_obj_sp, "--shell-expand-args true --");
- AddAlias ("run", cmd_obj_sp, "--shell-expand-args true --");
- #else
- StreamString defaultshell;
- defaultshell.Printf("--shell=%s --", HostInfo::GetDefaultShell().GetPath().c_str());
- AddAlias ("r", cmd_obj_sp, defaultshell.GetData());
- AddAlias ("run", cmd_obj_sp, defaultshell.GetData());
- #endif
-#endif
- }
-
- cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
- if (cmd_obj_sp)
- {
- AddAlias ("add-dsym", cmd_obj_sp);
- }
-
- cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
- if (cmd_obj_sp)
- {
- AddAlias ("rbreak", cmd_obj_sp, "--func-regex %1");
+bool CommandInterpreter::AddCommand(const char *name,
+ const lldb::CommandObjectSP &cmd_sp,
+ bool can_replace) {
+ if (cmd_sp.get())
+ assert((this == &cmd_sp->GetCommandInterpreter()) &&
+ "tried to add a CommandObject from a different interpreter");
+
+ if (name && name[0]) {
+ std::string name_sstr(name);
+ bool found = (m_command_dict.find(name_sstr) != m_command_dict.end());
+ if (found && !can_replace)
+ return false;
+ if (found && m_command_dict[name_sstr]->IsRemovable() == false)
+ return false;
+ m_command_dict[name_sstr] = cmd_sp;
+ return true;
+ }
+ return false;
+}
+
+bool CommandInterpreter::AddUserCommand(std::string name,
+ const lldb::CommandObjectSP &cmd_sp,
+ bool can_replace) {
+ if (cmd_sp.get())
+ assert((this == &cmd_sp->GetCommandInterpreter()) &&
+ "tried to add a CommandObject from a different interpreter");
+
+ if (!name.empty()) {
+ const char *name_cstr = name.c_str();
+
+ // do not allow replacement of internal commands
+ if (CommandExists(name_cstr)) {
+ if (can_replace == false)
+ return false;
+ if (m_command_dict[name]->IsRemovable() == false)
+ return false;
}
-}
-void
-CommandInterpreter::Clear()
-{
- m_command_io_handler_sp.reset();
+ if (UserCommandExists(name_cstr)) {
+ if (can_replace == false)
+ return false;
+ if (m_user_dict[name]->IsRemovable() == false)
+ return false;
+ }
- if (m_script_interpreter_sp)
- m_script_interpreter_sp->Clear();
+ m_user_dict[name] = cmd_sp;
+ return true;
+ }
+ return false;
}
-const char *
-CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
-{
- // This function has not yet been implemented.
+CommandObjectSP CommandInterpreter::GetCommandSPExact(const char *cmd_cstr,
+ bool include_aliases) {
+ Args cmd_words(cmd_cstr); // Break up the command string into words, in case
+ // it's a multi-word command.
+ CommandObjectSP ret_val; // Possibly empty return value.
- // Look for any embedded script command
- // If found,
- // get interpreter object from the command dictionary,
- // call execute_one_command on it,
- // get the results as a string,
- // substitute that string for current stuff.
+ if (cmd_cstr == nullptr)
+ return ret_val;
- return arg;
+ if (cmd_words.GetArgumentCount() == 1)
+ return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);
+ else {
+ // We have a multi-word command (seemingly), so we need to do more work.
+ // First, get the cmd_obj_sp for the first word in the command.
+ CommandObjectSP cmd_obj_sp = GetCommandSP(cmd_words.GetArgumentAtIndex(0),
+ include_aliases, true, nullptr);
+ if (cmd_obj_sp.get() != nullptr) {
+ // Loop through the rest of the words in the command (everything passed in
+ // was supposed to be part of a
+ // command name), and find the appropriate sub-command SP for each command
+ // word....
+ size_t end = cmd_words.GetArgumentCount();
+ for (size_t j = 1; j < end; ++j) {
+ if (cmd_obj_sp->IsMultiwordObject()) {
+ cmd_obj_sp =
+ cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(j));
+ if (cmd_obj_sp.get() == nullptr)
+ // The sub-command name was invalid. Fail and return the empty
+ // 'ret_val'.
+ return ret_val;
+ } else
+ // We have more words in the command name, but we don't have a
+ // multiword object. Fail and return
+ // empty 'ret_val'.
+ return ret_val;
+ }
+ // We successfully looped through all the command words and got valid
+ // command objects for them. Assign the
+ // last object retrieved to 'ret_val'.
+ ret_val = cmd_obj_sp;
+ }
+ }
+ return ret_val;
+}
+
+CommandObject *CommandInterpreter::GetCommandObjectExact(const char *cmd_cstr,
+ bool include_aliases) {
+ return GetCommandSPExact(cmd_cstr, include_aliases).get();
+}
+
+CommandObject *CommandInterpreter::GetCommandObject(const char *cmd_cstr,
+ StringList *matches) {
+ CommandObject *command_obj =
+ GetCommandSP(cmd_cstr, false, true, matches).get();
+
+ // If we didn't find an exact match to the command string in the commands,
+ // look in
+ // the aliases.
+
+ if (command_obj)
+ return command_obj;
+
+ command_obj = GetCommandSP(cmd_cstr, true, true, matches).get();
+
+ if (command_obj)
+ return command_obj;
+
+ // If there wasn't an exact match then look for an inexact one in just the
+ // commands
+ command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();
+
+ // Finally, if there wasn't an inexact match among the commands, look for an
+ // inexact
+ // match in both the commands and aliases.
+
+ if (command_obj) {
+ if (matches)
+ matches->AppendString(command_obj->GetCommandName());
+ return command_obj;
+ }
+
+ return GetCommandSP(cmd_cstr, true, false, matches).get();
+}
+
+bool CommandInterpreter::CommandExists(const char *cmd) {
+ return m_command_dict.find(cmd) != m_command_dict.end();
+}
+
+bool CommandInterpreter::GetAliasFullName(const char *cmd,
+ std::string &full_name) {
+ bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
+ if (exact_match) {
+ full_name.assign(cmd);
+ return exact_match;
+ } else {
+ StringList matches;
+ size_t num_alias_matches;
+ num_alias_matches =
+ AddNamesMatchingPartialString(m_alias_dict, cmd, matches);
+ if (num_alias_matches == 1) {
+ // Make sure this isn't shadowing a command in the regular command space:
+ StringList regular_matches;
+ const bool include_aliases = false;
+ const bool exact = false;
+ CommandObjectSP cmd_obj_sp(
+ GetCommandSP(cmd, include_aliases, exact, ®ular_matches));
+ if (cmd_obj_sp || regular_matches.GetSize() > 0)
+ return false;
+ else {
+ full_name.assign(matches.GetStringAtIndex(0));
+ return true;
+ }
+ } else
+ return false;
+ }
+}
+
+bool CommandInterpreter::AliasExists(const char *cmd) {
+ return m_alias_dict.find(cmd) != m_alias_dict.end();
+}
+
+bool CommandInterpreter::UserCommandExists(const char *cmd) {
+ return m_user_dict.find(cmd) != m_user_dict.end();
+}
+
+CommandAlias *
+CommandInterpreter::AddAlias(const char *alias_name,
+ lldb::CommandObjectSP &command_obj_sp,
+ const char *args_string) {
+ if (command_obj_sp.get())
+ assert((this == &command_obj_sp->GetCommandInterpreter()) &&
+ "tried to add a CommandObject from a different interpreter");
+
+ std::unique_ptr<CommandAlias> command_alias_up(
+ new CommandAlias(*this, command_obj_sp, args_string, alias_name));
+
+ if (command_alias_up && command_alias_up->IsValid()) {
+ m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get());
+ return command_alias_up.release();
+ }
+
+ return nullptr;
+}
+
+bool CommandInterpreter::RemoveAlias(const char *alias_name) {
+ auto pos = m_alias_dict.find(alias_name);
+ if (pos != m_alias_dict.end()) {
+ m_alias_dict.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+bool CommandInterpreter::RemoveCommand(const char *cmd) {
+ auto pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end()) {
+ if (pos->second->IsRemovable()) {
+ // Only regular expression objects or python commands are removable
+ m_command_dict.erase(pos);
+ return true;
+ }
+ }
+ return false;
+}
+bool CommandInterpreter::RemoveUser(const char *alias_name) {
+ CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
+ if (pos != m_user_dict.end()) {
+ m_user_dict.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+void CommandInterpreter::GetHelp(CommandReturnObject &result,
+ uint32_t cmd_types) {
+ const char *help_prologue = GetDebugger().GetIOHandlerHelpPrologue();
+ if (help_prologue != NULL) {
+ OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue);
+ }
+
+ CommandObject::CommandMap::const_iterator pos;
+ size_t max_len = FindLongestCommandWord(m_command_dict);
+
+ if ((cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin) {
+ result.AppendMessage("Debugger commands:");
+ result.AppendMessage("");
+
+ for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) {
+ if (!(cmd_types & eCommandTypesHidden) &&
+ (pos->first.compare(0, 1, "_") == 0))
+ continue;
+
+ OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(),
+ "--", pos->second->GetHelp(), max_len);
+ }
+ result.AppendMessage("");
+ }
+
+ if (!m_alias_dict.empty() &&
+ ((cmd_types & eCommandTypesAliases) == eCommandTypesAliases)) {
+ result.AppendMessageWithFormat(
+ "Current command abbreviations "
+ "(type '%shelp command alias' for more info):\n",
+ GetCommandPrefix());
+ result.AppendMessage("");
+ max_len = FindLongestCommandWord(m_alias_dict);
+
+ for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end();
+ ++alias_pos) {
+ OutputFormattedHelpText(result.GetOutputStream(),
+ alias_pos->first.c_str(), "--",
+ alias_pos->second->GetHelp(), max_len);
+ }
+ result.AppendMessage("");
+ }
+
+ if (!m_user_dict.empty() &&
+ ((cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef)) {
+ result.AppendMessage("Current user-defined commands:");
+ result.AppendMessage("");
+ max_len = FindLongestCommandWord(m_user_dict);
+ for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) {
+ OutputFormattedHelpText(result.GetOutputStream(), pos->first.c_str(),
+ "--", pos->second->GetHelp(), max_len);
+ }
+ result.AppendMessage("");
+ }
+
+ result.AppendMessageWithFormat(
+ "For more information on any command, type '%shelp <command-name>'.\n",
+ GetCommandPrefix());
}
+CommandObject *
+CommandInterpreter::GetCommandObjectForCommand(std::string &command_string) {
+ // This function finds the final, lowest-level, alias-resolved command object
+ // whose 'Execute' function will
+ // eventually be invoked by the given command line.
+
+ CommandObject *cmd_obj = nullptr;
+ size_t start = command_string.find_first_not_of(k_white_space);
+ size_t end = 0;
+ bool done = false;
+ while (!done) {
+ if (start != std::string::npos) {
+ // Get the next word from command_string.
+ end = command_string.find_first_of(k_white_space, start);
+ if (end == std::string::npos)
+ end = command_string.size();
+ std::string cmd_word = command_string.substr(start, end - start);
+
+ if (cmd_obj == nullptr)
+ // Since cmd_obj is NULL we are on our first time through this loop.
+ // Check to see if cmd_word is a valid
+ // command or alias.
+ cmd_obj = GetCommandObject(cmd_word.c_str());
+ else if (cmd_obj->IsMultiwordObject()) {
+ // Our current object is a multi-word object; see if the cmd_word is a
+ // valid sub-command for our object.
+ CommandObject *sub_cmd_obj =
+ cmd_obj->GetSubcommandObject(cmd_word.c_str());
+ if (sub_cmd_obj)
+ cmd_obj = sub_cmd_obj;
+ else // cmd_word was not a valid sub-command word, so we are done
+ done = true;
+ } else
+ // We have a cmd_obj and it is not a multi-word object, so we are done.
+ done = true;
+
+ // If we didn't find a valid command object, or our command object is not
+ // a multi-word object, or
+ // we are at the end of the command_string, then we are done. Otherwise,
+ // find the start of the
+ // next word.
+
+ if (!cmd_obj || !cmd_obj->IsMultiwordObject() ||
+ end >= command_string.size())
+ done = true;
+ else
+ start = command_string.find_first_not_of(k_white_space, end);
+ } else
+ // Unable to find any more words.
+ done = true;
+ }
+
+ if (end == command_string.size())
+ command_string.clear();
+ else
+ command_string = command_string.substr(end);
+
+ return cmd_obj;
+}
+
+static const char *k_valid_command_chars =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
+static void StripLeadingSpaces(std::string &s) {
+ if (!s.empty()) {
+ size_t pos = s.find_first_not_of(k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos == 0)
+ return;
+ s.erase(0, pos);
+ }
+}
+
+static size_t FindArgumentTerminator(const std::string &s) {
+ const size_t s_len = s.size();
+ size_t offset = 0;
+ while (offset < s_len) {
+ size_t pos = s.find("--", offset);
+ if (pos == std::string::npos)
+ break;
+ if (pos > 0) {
+ if (isspace(s[pos - 1])) {
+ // Check if the string ends "\s--" (where \s is a space character)
+ // or if we have "\s--\s".
+ if ((pos + 2 >= s_len) || isspace(s[pos + 2])) {
+ return pos;
+ }
+ }
+ }
+ offset = pos + 2;
+ }
+ return std::string::npos;
+}
+
+static bool ExtractCommand(std::string &command_string, std::string &command,
+ std::string &suffix, char "e_char) {
+ command.clear();
+ suffix.clear();
+ StripLeadingSpaces(command_string);
+
+ bool result = false;
+ quote_char = '\0';
+
+ if (!command_string.empty()) {
+ const char first_char = command_string[0];
+ if (first_char == '\'' || first_char == '"') {
+ quote_char = first_char;
+ const size_t end_quote_pos = command_string.find(quote_char, 1);
+ if (end_quote_pos == std::string::npos) {
+ command.swap(command_string);
+ command_string.erase();
+ } else {
+ command.assign(command_string, 1, end_quote_pos - 1);
+ if (end_quote_pos + 1 < command_string.size())
+ command_string.erase(0, command_string.find_first_not_of(
+ k_white_space, end_quote_pos + 1));
+ else
+ command_string.erase();
+ }
+ } else {
+ const size_t first_space_pos =
+ command_string.find_first_of(k_white_space);
+ if (first_space_pos == std::string::npos) {
+ command.swap(command_string);
+ command_string.erase();
+ } else {
+ command.assign(command_string, 0, first_space_pos);
+ command_string.erase(0, command_string.find_first_not_of(
+ k_white_space, first_space_pos));
+ }
+ }
+ result = true;
+ }
+
+ if (!command.empty()) {
+ // actual commands can't start with '-' or '_'
+ if (command[0] != '-' && command[0] != '_') {
+ size_t pos = command.find_first_not_of(k_valid_command_chars);
+ if (pos > 0 && pos != std::string::npos) {
+ suffix.assign(command.begin() + pos, command.end());
+ command.erase(pos);
+ }
+ }
+ }
+
+ return result;
+}
+
+CommandObject *CommandInterpreter::BuildAliasResult(
+ const char *alias_name, std::string &raw_input_string,
+ std::string &alias_result, CommandReturnObject &result) {
+ CommandObject *alias_cmd_obj = nullptr;
+ Args cmd_args(raw_input_string);
+ alias_cmd_obj = GetCommandObject(alias_name);
+ StreamString result_str;
+
+ if (alias_cmd_obj && alias_cmd_obj->IsAlias()) {
+ std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
+ ((CommandAlias *)alias_cmd_obj)->Desugar();
+ OptionArgVectorSP option_arg_vector_sp = desugared.second;
+ alias_cmd_obj = desugared.first.get();
+ std::string alias_name_str = alias_name;
+ if ((cmd_args.GetArgumentCount() == 0) ||
+ (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0))
+ cmd_args.Unshift(alias_name);
+
+ result_str.Printf("%s", alias_cmd_obj->GetCommandName());
+
+ if (option_arg_vector_sp.get()) {
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ for (size_t i = 0; i < option_arg_vector->size(); ++i) {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ OptionArgValue value_pair = option_pair.second;
+ int value_type = value_pair.first;
+ std::string option = option_pair.first;
+ std::string value = value_pair.second;
+ if (option.compare("<argument>") == 0)
+ result_str.Printf(" %s", value.c_str());
+ else {
+ result_str.Printf(" %s", option.c_str());
+ if (value_type != OptionParser::eNoArgument) {
+ if (value_type != OptionParser::eOptionalArgument)
+ result_str.Printf(" ");
+ int index = GetOptionArgumentPosition(value.c_str());
+ if (index == 0)
+ result_str.Printf("%s", value.c_str());
+ else if (static_cast<size_t>(index) >=
+ cmd_args.GetArgumentCount()) {
+
+ result.AppendErrorWithFormat("Not enough arguments provided; you "
+ "need at least %d arguments to use "
+ "this alias.\n",
+ index);
+ result.SetStatus(eReturnStatusFailed);
+ return nullptr;
+ } else {
+ size_t strpos =
+ raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
+ if (strpos != std::string::npos)
+ raw_input_string = raw_input_string.erase(
+ strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
+ result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index));
+ }
+ }
+ }
+ }
+ }
+
+ alias_result = result_str.GetData();
+ }
+ return alias_cmd_obj;
+}
+
+Error CommandInterpreter::PreprocessCommand(std::string &command) {
+ // The command preprocessor needs to do things to the command
+ // line before any parsing of arguments or anything else is done.
+ // The only current stuff that gets preprocessed is anything enclosed
+ // in backtick ('`') characters is evaluated as an expression and
+ // the result of the expression must be a scalar that can be substituted
+ // into the command. An example would be:
+ // (lldb) memory read `$rsp + 20`
+ Error error; // Error for any expressions that might not evaluate
+ size_t start_backtick;
+ size_t pos = 0;
+ while ((start_backtick = command.find('`', pos)) != std::string::npos) {
+ if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
+ // The backtick was preceded by a '\' character, remove the slash
+ // and don't treat the backtick as the start of an expression
+ command.erase(start_backtick - 1, 1);
+ // No need to add one to start_backtick since we just deleted a char
+ pos = start_backtick;
+ } else {
+ const size_t expr_content_start = start_backtick + 1;
+ const size_t end_backtick = command.find('`', expr_content_start);
+ if (end_backtick == std::string::npos)
+ return error;
+ else if (end_backtick == expr_content_start) {
+ // Empty expression (two backticks in a row)
+ command.erase(start_backtick, 2);
+ } else {
+ std::string expr_str(command, expr_content_start,
+ end_backtick - expr_content_start);
-void
-CommandInterpreter::LoadCommandDictionary ()
-{
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-
- lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
-
- m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
- m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
- m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this));
- m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
- m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
- m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
- m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
- m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this));
- m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
- m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
- m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
- m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
- m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
- m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
- m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
- m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
- m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
- m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
- m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
- m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
- m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
- m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
- m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
- m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
- m_command_dict["language"] = CommandObjectSP (new CommandObjectLanguage(*this));
-
- const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
- {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
- {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
- {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
- {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
- {"^(-.*)$", "breakpoint set %1"},
- {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
- {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
- {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}};
-
- size_t num_regexes = llvm::array_lengthof(break_regexes);
-
- std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-break", "Set a breakpoint using one of several shorthand formats.\n",
- "\n"
- "_regexp-break <filename>:<linenum>\n"
- " main.c:12 // Break at line 12 of main.c\n\n"
- "_regexp-break <linenum>\n"
- " 12 // Break at line 12 of current file\n\n"
- "_regexp-break 0x<address>\n"
- " 0x1234000 // Break at address 0x1234000\n\n"
- "_regexp-break <name>\n"
- " main // Break in 'main' after the prologue\n\n"
- "_regexp-break &<name>\n"
- " &main // Break at first instruction in 'main'\n\n"
- "_regexp-break <module>`<name>\n"
- " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n"
- "_regexp-break /<source-regex>/\n"
- " /break here/ // Break on source lines in current file\n"
- " // containing text 'break here'.\n",
- 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));
-
- if (break_regex_cmd_ap.get())
- {
- bool success = true;
- for (size_t i = 0; i < num_regexes; i++)
- {
- success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
- if (!success)
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ // Get a dummy target to allow for calculator mode while processing
+ // backticks.
+ // This also helps break the infinite loop caused when target is null.
+ if (!target)
+ target = m_debugger.GetDummyTarget();
+ if (target) {
+ ValueObjectSP expr_result_valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+ options.SetTimeoutUsec(0);
+
+ ExpressionResults expr_result = target->EvaluateExpression(
+ expr_str.c_str(), exe_ctx.GetFramePtr(), expr_result_valobj_sp,
+ options);
+
+ if (expr_result == eExpressionCompleted) {
+ Scalar scalar;
+ if (expr_result_valobj_sp)
+ expr_result_valobj_sp =
+ expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
+ expr_result_valobj_sp->GetDynamicValueType(), true);
+ if (expr_result_valobj_sp->ResolveValue(scalar)) {
+ command.erase(start_backtick, end_backtick - start_backtick + 1);
+ StreamString value_strm;
+ const bool show_type = false;
+ scalar.GetValue(&value_strm, show_type);
+ size_t value_string_size = value_strm.GetSize();
+ if (value_string_size) {
+ command.insert(start_backtick, value_strm.GetData(),
+ value_string_size);
+ pos = start_backtick + value_string_size;
+ continue;
+ } else {
+ error.SetErrorStringWithFormat("expression value didn't result "
+ "in a scalar value for the "
+ "expression '%s'",
+ expr_str.c_str());
+ }
+ } else {
+ error.SetErrorStringWithFormat("expression value didn't result "
+ "in a scalar value for the "
+ "expression '%s'",
+ expr_str.c_str());
+ }
+ } else {
+ if (expr_result_valobj_sp)
+ error = expr_result_valobj_sp->GetError();
+ if (error.Success()) {
+
+ switch (expr_result) {
+ case eExpressionSetupError:
+ error.SetErrorStringWithFormat(
+ "expression setup error for the expression '%s'",
+ expr_str.c_str());
break;
- }
- success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
-
- if (success)
- {
- CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
- m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-tbreak", "Set a one-shot breakpoint using one of several shorthand formats.\n",
- "\n"
- "_regexp-break <filename>:<linenum>\n"
- " main.c:12 // Break at line 12 of main.c\n\n"
- "_regexp-break <linenum>\n"
- " 12 // Break at line 12 of current file\n\n"
- "_regexp-break 0x<address>\n"
- " 0x1234000 // Break at address 0x1234000\n\n"
- "_regexp-break <name>\n"
- " main // Break in 'main' after the prologue\n\n"
- "_regexp-break &<name>\n"
- " &main // Break at first instruction in 'main'\n\n"
- "_regexp-break <module>`<name>\n"
- " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n"
- "_regexp-break /<source-regex>/\n"
- " /break here/ // Break on source lines in current file\n"
- " // containing text 'break here'.\n",
- 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));
-
- if (tbreak_regex_cmd_ap.get())
- {
- bool success = true;
- for (size_t i = 0; i < num_regexes; i++)
- {
- // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
- char buffer[1024];
- int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
- assert (num_printed < 1024);
- UNUSED_IF_ASSERT_DISABLED(num_printed);
- success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
- if (!success)
+ case eExpressionParseError:
+ error.SetErrorStringWithFormat(
+ "expression parse error for the expression '%s'",
+ expr_str.c_str());
break;
+ case eExpressionResultUnavailable:
+ error.SetErrorStringWithFormat(
+ "expression error fetching result for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionCompleted:
+ break;
+ case eExpressionDiscarded:
+ error.SetErrorStringWithFormat(
+ "expression discarded for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionInterrupted:
+ error.SetErrorStringWithFormat(
+ "expression interrupted for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionHitBreakpoint:
+ error.SetErrorStringWithFormat(
+ "expression hit breakpoint for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionTimedOut:
+ error.SetErrorStringWithFormat(
+ "expression timed out for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionStoppedForDebug:
+ error.SetErrorStringWithFormat("expression stop at entry point "
+ "for debugging for the "
+ "expression '%s'",
+ expr_str.c_str());
+ break;
+ }
+ }
+ }
}
- success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
-
- if (success)
- {
- CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
- m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_ap(
- new CommandObjectRegexCommand(*this, "_regexp-attach", "Attach to process by ID or name.",
- "_regexp-attach <pid> | <process-name>", 2, 0, false));
- if (attach_regex_cmd_ap.get())
- {
- if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
- attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
- attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
- attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
- {
- CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
- m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-down", "Select a newer stack frame. Defaults to moving one frame, a numeric argument can "
- "specify an arbitrary number.",
- "_regexp-down [<count>]", 2, 0, false));
- if (down_regex_cmd_ap.get())
- {
- if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
- down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
- {
- CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
- m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_ap(
- new CommandObjectRegexCommand(*this, "_regexp-up", "Select an older stack frame. Defaults to moving one "
- "frame, a numeric argument can specify an arbitrary number.",
- "_regexp-up [<count>]", 2, 0, false));
- if (up_regex_cmd_ap.get())
- {
- if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
- up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
- {
- CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
- m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-display", "Evaluate an expression at every stop (see 'help target stop-hook'.)",
- "_regexp-display expression", 2, 0, false));
- if (display_regex_cmd_ap.get())
- {
- if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
- {
- CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
- m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-undisplay", "Stop displaying expression at every stop (specified by stop-hook index.)",
- "_regexp-undisplay stop-hook-number", 2, 0, false));
- if (undisplay_regex_cmd_ap.get())
- {
- if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
- {
- CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
- m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand(
- *this, "gdb-remote",
- "Connect to a process via remote GDB server. If no host is specifed, localhost is assumed.",
- "gdb-remote [<hostname>:]<portnum>", 2, 0, false));
- if (connect_gdb_remote_cmd_ap.get())
- {
- if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
- connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
- {
- CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
- m_command_dict[command_sp->GetCommandName ()] = command_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand(
- *this, "kdp-remote",
- "Connect to a process via remote KDP server. If no UDP port is specified, port 41139 is assumed.",
- "kdp-remote <hostname>[:<portnum>]", 2, 0, false));
- if (connect_kdp_remote_cmd_ap.get())
- {
- if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
- connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
- {
- CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
- m_command_dict[command_sp->GetCommandName ()] = command_sp;
- }
- }
-
- std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-bt", "Show the current thread's call stack. Any numeric argument displays at most that many "
- "frames. The argument 'all' displays all threads.",
- "bt [<digit> | all]", 2, 0, false));
- if (bt_regex_cmd_ap.get())
- {
- // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
- // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
- // so now "bt 3" is the preferred form, in line with gdb.
- if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
- bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
- bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
- bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
- {
- CommandObjectSP command_sp(bt_regex_cmd_ap.release());
- m_command_dict[command_sp->GetCommandName ()] = command_sp;
- }
- }
+ }
+ if (error.Fail())
+ break;
+ }
+ }
+ return error;
+}
+
+bool CommandInterpreter::HandleCommand(const char *command_line,
+ LazyBool lazy_add_to_history,
+ CommandReturnObject &result,
+ ExecutionContext *override_context,
+ bool repeat_on_empty_command,
+ bool no_context_switching)
+
+{
+
+ std::string command_string(command_line);
+ std::string original_command_string(command_line);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS));
+ Host::SetCrashDescriptionWithFormat("HandleCommand(command = \"%s\")",
+ command_line);
+
+ // Make a scoped cleanup object that will clear the crash description string
+ // on exit of this function.
+ lldb_utility::CleanUp<const char *> crash_description_cleanup(
+ nullptr, Host::SetCrashDescription);
+
+ if (log)
+ log->Printf("Processing command: %s", command_line);
+
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, "Handling command: %s.",
+ command_line);
+
+ if (!no_context_switching)
+ UpdateExecutionContext(override_context);
+
+ bool add_to_history;
+ if (lazy_add_to_history == eLazyBoolCalculate)
+ add_to_history = (m_command_source_depth == 0);
+ else
+ add_to_history = (lazy_add_to_history == eLazyBoolYes);
+
+ bool empty_command = false;
+ bool comment_command = false;
+ if (command_string.empty())
+ empty_command = true;
+ else {
+ const char *k_space_characters = "\t\n\v\f\r ";
+
+ size_t non_space = command_string.find_first_not_of(k_space_characters);
+ // Check for empty line or comment line (lines whose first
+ // non-space character is the comment character for this interpreter)
+ if (non_space == std::string::npos)
+ empty_command = true;
+ else if (command_string[non_space] == m_comment_char)
+ comment_command = true;
+ else if (command_string[non_space] == CommandHistory::g_repeat_char) {
+ const char *history_string =
+ m_command_history.FindString(command_string.c_str() + non_space);
+ if (history_string == nullptr) {
+ result.AppendErrorWithFormat("Could not find entry: %s in history",
+ command_string.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ add_to_history = false;
+ command_string = history_string;
+ original_command_string = history_string;
+ }
+ }
+
+ if (empty_command) {
+ if (repeat_on_empty_command) {
+ if (m_command_history.IsEmpty()) {
+ result.AppendError("empty command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ } else {
+ command_line = m_repeat_command.c_str();
+ command_string = command_line;
+ original_command_string = command_line;
+ if (m_repeat_command.empty()) {
+ result.AppendErrorWithFormat("No auto repeat.\n");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ add_to_history = false;
+ } else {
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ } else if (comment_command) {
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ Error error(PreprocessCommand(command_string));
+
+ if (error.Fail()) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_ap(new CommandObjectRegexCommand(
- *this, "_regexp-list", "List relevant source code using one of several shorthand formats.",
- "\n"
- "_regexp-list <file>:<line> // List around specific file/line\n"
- "_regexp-list <line> // List current file around specified line\n"
- "_regexp-list <function-name> // List specified function\n"
- "_regexp-list 0x<address> // List around specified address\n"
- "_regexp-list -[<count>] // List previous <count> lines\n"
- "_regexp-list // List subsequent lines",
- 2, CommandCompletions::eSourceFileCompletion, false));
- if (list_regex_cmd_ap.get())
- {
- if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
- list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
- list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
- list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
- list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
- list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
- list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
- {
- CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
- m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
- }
- }
+ // Phase 1.
- std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_ap(
- new CommandObjectRegexCommand(*this, "_regexp-env", "Shorthand for viewing and setting environment variables.",
- "\n"
- "_regexp-env // Show enrivonment\n"
- "_regexp-env <name>=<value> // Set an environment variable",
- 2, 0, false));
- if (env_regex_cmd_ap.get())
- {
- if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
- env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
- {
- CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
- m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
- }
- }
+ // Before we do ANY kind of argument processing, we need to figure out what
+ // the real/final command object is for the specified command. This gets
+ // complicated by the fact that the user could have specified an alias, and,
+ // in translating the alias, there may also be command options and/or even
+ // data (including raw text strings) that need to be found and inserted into
+ // the command line as part of the translation. So this first step is plain
+ // look-up and replacement, resulting in:
+ // 1. the command object whose Execute method will actually be called
+ // 2. a revised command string, with all substitutions and replacements
+ // taken care of
+ // From 1 above, we can determine whether the Execute function wants raw
+ // input or not.
+
+ CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
+
+ // Although the user may have abbreviated the command, the command_string now
+ // has the command expanded to the full name. For example, if the input
+ // was "br s -n main", command_string is now "breakpoint set -n main".
+
+ if (log) {
+ log->Printf("HandleCommand, cmd_obj : '%s'",
+ cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
+ log->Printf("HandleCommand, (revised) command_string: '%s'",
+ command_string.c_str());
+ const bool wants_raw_input =
+ (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false;
+ log->Printf("HandleCommand, wants_raw_input:'%s'",
+ wants_raw_input ? "True" : "False");
+ }
+
+ // Phase 2.
+ // Take care of things like setting up the history command & calling the
+ // appropriate Execute method on the
+ // CommandObject, with the appropriate arguments.
+
+ if (cmd_obj != nullptr) {
+ if (add_to_history) {
+ Args command_args(command_string);
+ const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
+ if (repeat_command != nullptr)
+ m_repeat_command.assign(repeat_command);
+ else
+ m_repeat_command.assign(original_command_string.c_str());
+
+ m_command_history.AppendString(original_command_string);
+ }
+
+ std::string remainder;
+ const std::size_t actual_cmd_name_len = strlen(cmd_obj->GetCommandName());
+ if (actual_cmd_name_len < command_string.length())
+ remainder = command_string.substr(actual_cmd_name_len);
+
+ // Remove any initial spaces
+ size_t pos = remainder.find_first_not_of(k_white_space);
+ if (pos != 0 && pos != std::string::npos)
+ remainder.erase(0, pos);
- std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_ap(
- new CommandObjectRegexCommand(*this, "_regexp-jump", "Set the program counter to a new address.",
- "\n"
- "_regexp-jump <line>\n"
- "_regexp-jump +<line-offset> | -<line-offset>\n"
- "_regexp-jump <file>:<line>\n"
- "_regexp-jump *<addr>\n",
- 2, 0, false));
- if (jump_regex_cmd_ap.get())
- {
- if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
- jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
- jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
- jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
- {
- CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
- m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
- }
+ if (log)
+ log->Printf(
+ "HandleCommand, command line after removing command name(s): '%s'",
+ remainder.c_str());
+
+ cmd_obj->Execute(remainder.c_str(), result);
+ } else {
+ // We didn't find the first command object, so complete the first argument.
+ Args command_args(command_string);
+ StringList matches;
+ int num_matches;
+ int cursor_index = 0;
+ int cursor_char_position = strlen(command_args.GetArgumentAtIndex(0));
+ bool word_complete;
+ num_matches = HandleCompletionMatches(command_args, cursor_index,
+ cursor_char_position, 0, -1,
+ word_complete, matches);
+
+ if (num_matches > 0) {
+ std::string error_msg;
+ error_msg.assign("ambiguous command '");
+ error_msg.append(command_args.GetArgumentAtIndex(0));
+ error_msg.append("'.");
+
+ error_msg.append(" Possible completions:");
+ for (int i = 0; i < num_matches; i++) {
+ error_msg.append("\n\t");
+ error_msg.append(matches.GetStringAtIndex(i));
+ }
+ error_msg.append("\n");
+ result.AppendRawError(error_msg.c_str());
+ } else
+ result.AppendErrorWithFormat("Unrecognized command '%s'.\n",
+ command_args.GetArgumentAtIndex(0));
+
+ result.SetStatus(eReturnStatusFailed);
+ }
+
+ if (log)
+ log->Printf("HandleCommand, command %s",
+ (result.Succeeded() ? "succeeded" : "did not succeed"));
+
+ return result.Succeeded();
+}
+
+int CommandInterpreter::HandleCompletionMatches(
+ Args &parsed_line, int &cursor_index, int &cursor_char_position,
+ int match_start_point, int max_return_elements, bool &word_complete,
+ StringList &matches) {
+ int num_command_matches = 0;
+ bool look_for_subcommand = false;
+
+ // For any of the command completions a unique match will be a complete word.
+ word_complete = true;
+
+ if (cursor_index == -1) {
+ // We got nothing on the command line, so return the list of commands
+ bool include_aliases = true;
+ num_command_matches =
+ GetCommandNamesMatchingPartialString("", include_aliases, matches);
+ } else if (cursor_index == 0) {
+ // The cursor is in the first argument, so just do a lookup in the
+ // dictionary.
+ CommandObject *cmd_obj =
+ GetCommandObject(parsed_line.GetArgumentAtIndex(0), &matches);
+ num_command_matches = matches.GetSize();
+
+ if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() &&
+ matches.GetStringAtIndex(0) != nullptr &&
+ strcmp(parsed_line.GetArgumentAtIndex(0),
+ matches.GetStringAtIndex(0)) == 0) {
+ if (parsed_line.GetArgumentCount() == 1) {
+ word_complete = true;
+ } else {
+ look_for_subcommand = true;
+ num_command_matches = 0;
+ matches.DeleteStringAtIndex(0);
+ parsed_line.AppendArgument("");
+ cursor_index++;
+ cursor_char_position = 0;
+ }
}
+ }
-}
+ if (cursor_index > 0 || look_for_subcommand) {
+ // We are completing further on into a commands arguments, so find the
+ // command and tell it
+ // to complete the command.
+ // First see if there is a matching initial command:
+ CommandObject *command_object =
+ GetCommandObject(parsed_line.GetArgumentAtIndex(0));
+ if (command_object == nullptr) {
+ return 0;
+ } else {
+ parsed_line.Shift();
+ cursor_index--;
+ num_command_matches = command_object->HandleCompletion(
+ parsed_line, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, word_complete, matches);
+ }
+ }
+
+ return num_command_matches;
+}
+
+int CommandInterpreter::HandleCompletion(
+ const char *current_line, const char *cursor, const char *last_char,
+ int match_start_point, int max_return_elements, StringList &matches) {
+ // We parse the argument up to the cursor, so the last argument in parsed_line
+ // is
+ // the one containing the cursor, and the cursor is after the last character.
+
+ Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
+ Args partial_parsed_line(
+ llvm::StringRef(current_line, cursor - current_line));
+
+ // Don't complete comments, and if the line we are completing is just the
+ // history repeat character,
+ // substitute the appropriate history line.
+ const char *first_arg = parsed_line.GetArgumentAtIndex(0);
+ if (first_arg) {
+ if (first_arg[0] == m_comment_char)
+ return 0;
+ else if (first_arg[0] == CommandHistory::g_repeat_char) {
+ const char *history_string = m_command_history.FindString(first_arg);
+ if (history_string != nullptr) {
+ matches.Clear();
+ matches.InsertStringAtIndex(0, history_string);
+ return -2;
+ } else
+ return 0;
+ }
+ }
+
+ int num_args = partial_parsed_line.GetArgumentCount();
+ int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
+ int cursor_char_position;
+
+ if (cursor_index == -1)
+ cursor_char_position = 0;
+ else
+ cursor_char_position =
+ strlen(partial_parsed_line.GetArgumentAtIndex(cursor_index));
+
+ if (cursor > current_line && cursor[-1] == ' ') {
+ // We are just after a space. If we are in an argument, then we will
+ // continue
+ // parsing, but if we are between arguments, then we have to complete
+ // whatever the next
+ // element would be.
+ // We can distinguish the two cases because if we are in an argument (e.g.
+ // because the space is
+ // protected by a quote) then the space will also be in the parsed
+ // argument...
+
+ const char *current_elem =
+ partial_parsed_line.GetArgumentAtIndex(cursor_index);
+ if (cursor_char_position == 0 ||
+ current_elem[cursor_char_position - 1] != ' ') {
+ parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
+ cursor_index++;
+ cursor_char_position = 0;
+ }
+ }
+
+ int num_command_matches;
+
+ matches.Clear();
+
+ // Only max_return_elements == -1 is supported at present:
+ assert(max_return_elements == -1);
+ bool word_complete;
+ num_command_matches = HandleCompletionMatches(
+ parsed_line, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, word_complete, matches);
-int
-CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
- StringList &matches)
-{
- AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
+ if (num_command_matches <= 0)
+ return num_command_matches;
- if (include_aliases)
- {
- AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
+ if (num_args == 0) {
+ // If we got an empty string, insert nothing.
+ matches.InsertStringAtIndex(0, "");
+ } else {
+ // Now figure out if there is a common substring, and if so put that in
+ // element 0, otherwise
+ // put an empty string in element 0.
+ std::string command_partial_str;
+ if (cursor_index >= 0)
+ command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
+ parsed_line.GetArgumentAtIndex(cursor_index) +
+ cursor_char_position);
+
+ std::string common_prefix;
+ matches.LongestCommonPrefix(common_prefix);
+ const size_t partial_name_len = command_partial_str.size();
+ common_prefix.erase(0, partial_name_len);
+
+ // If we matched a unique single command, add a space...
+ // Only do this if the completer told us this was a complete word,
+ // however...
+ if (num_command_matches == 1 && word_complete) {
+ char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
+ common_prefix =
+ Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
+ if (quote_char != '\0')
+ common_prefix.push_back(quote_char);
+ common_prefix.push_back(' ');
+ }
+ matches.InsertStringAtIndex(0, common_prefix.c_str());
+ }
+ return num_command_matches;
+}
+
+CommandInterpreter::~CommandInterpreter() {}
+
+void CommandInterpreter::UpdatePrompt(const char *new_prompt) {
+ EventSP prompt_change_event_sp(
+ new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt)));
+ ;
+ BroadcastEvent(prompt_change_event_sp);
+ if (m_command_io_handler_sp)
+ m_command_io_handler_sp->SetPrompt(new_prompt);
+}
+
+bool CommandInterpreter::Confirm(const char *message, bool default_answer) {
+ // Check AutoConfirm first:
+ if (m_debugger.GetAutoConfirm())
+ return default_answer;
+
+ IOHandlerConfirm *confirm =
+ new IOHandlerConfirm(m_debugger, message, default_answer);
+ IOHandlerSP io_handler_sp(confirm);
+ m_debugger.RunIOHandler(io_handler_sp);
+ return confirm->GetResponse();
+}
+
+CommandAlias *CommandInterpreter::GetAlias(const char *alias_name) {
+ OptionArgVectorSP ret_val;
+
+ std::string alias(alias_name);
+
+ auto pos = m_alias_dict.find(alias);
+ if (pos != m_alias_dict.end())
+ return (CommandAlias *)pos->second.get();
+
+ return nullptr;
+}
+
+bool CommandInterpreter::HasCommands() { return (!m_command_dict.empty()); }
+
+bool CommandInterpreter::HasAliases() { return (!m_alias_dict.empty()); }
+
+bool CommandInterpreter::HasUserCommands() { return (!m_user_dict.empty()); }
+
+bool CommandInterpreter::HasAliasOptions() { return HasAliases(); }
+
+void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
+ const char *alias_name,
+ Args &cmd_args,
+ std::string &raw_input_string,
+ CommandReturnObject &result) {
+ OptionArgVectorSP option_arg_vector_sp =
+ GetAlias(alias_name)->GetOptionArguments();
+
+ bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
+
+ // Make sure that the alias name is the 0th element in cmd_args
+ std::string alias_name_str = alias_name;
+ if (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0)
+ cmd_args.Unshift(alias_name);
+
+ Args new_args(alias_cmd_obj->GetCommandName());
+ if (new_args.GetArgumentCount() == 2)
+ new_args.Shift();
+
+ if (option_arg_vector_sp.get()) {
+ if (wants_raw_input) {
+ // We have a command that both has command options and takes raw input.
+ // Make *sure* it has a
+ // " -- " in the right place in the raw_input_string.
+ size_t pos = raw_input_string.find(" -- ");
+ if (pos == std::string::npos) {
+ // None found; assume it goes at the beginning of the raw input string
+ raw_input_string.insert(0, " -- ");
+ }
+ }
+
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+ const size_t old_size = cmd_args.GetArgumentCount();
+ std::vector<bool> used(old_size + 1, false);
+
+ used[0] = true;
+
+ for (size_t i = 0; i < option_arg_vector->size(); ++i) {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ OptionArgValue value_pair = option_pair.second;
+ int value_type = value_pair.first;
+ std::string option = option_pair.first;
+ std::string value = value_pair.second;
+ if (option.compare("<argument>") == 0) {
+ if (!wants_raw_input || (value.compare("--") != 0)) // Since we inserted
+ // this above, make
+ // sure we don't
+ // insert it twice
+ new_args.AppendArgument(value.c_str());
+ } else {
+ if (value_type != OptionParser::eOptionalArgument)
+ new_args.AppendArgument(option.c_str());
+ if (value.compare("<no-argument>") != 0) {
+ int index = GetOptionArgumentPosition(value.c_str());
+ if (index == 0) {
+ // value was NOT a positional argument; must be a real value
+ if (value_type != OptionParser::eOptionalArgument)
+ new_args.AppendArgument(value.c_str());
+ else {
+ char buffer[255];
+ ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
+ value.c_str());
+ new_args.AppendArgument(buffer);
+ }
+
+ } else if (static_cast<size_t>(index) >=
+ cmd_args.GetArgumentCount()) {
+ result.AppendErrorWithFormat("Not enough arguments provided; you "
+ "need at least %d arguments to use "
+ "this alias.\n",
+ index);
+ result.SetStatus(eReturnStatusFailed);
+ return;
+ } else {
+ // Find and remove cmd_args.GetArgumentAtIndex(i) from
+ // raw_input_string
+ size_t strpos =
+ raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
+ if (strpos != std::string::npos) {
+ raw_input_string = raw_input_string.erase(
+ strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
+ }
+
+ if (value_type != OptionParser::eOptionalArgument)
+ new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index));
+ else {
+ char buffer[255];
+ ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
+ cmd_args.GetArgumentAtIndex(index));
+ new_args.AppendArgument(buffer);
+ }
+ used[index] = true;
+ }
+ }
+ }
+ }
+
+ for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) {
+ if (!used[j] && !wants_raw_input)
+ new_args.AppendArgument(cmd_args.GetArgumentAtIndex(j));
+ }
+
+ cmd_args.Clear();
+ cmd_args.SetArguments(new_args.GetArgumentCount(),
+ new_args.GetConstArgumentVector());
+ } else {
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ // This alias was not created with any options; nothing further needs to be
+ // done, unless it is a command that
+ // wants raw input, in which case we need to clear the rest of the data from
+ // cmd_args, since its in the raw
+ // input string.
+ if (wants_raw_input) {
+ cmd_args.Clear();
+ cmd_args.SetArguments(new_args.GetArgumentCount(),
+ new_args.GetConstArgumentVector());
}
+ return;
+ }
- return matches.GetSize();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return;
}
-CommandObjectSP
-CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
-{
- CommandObject::CommandMap::iterator pos;
- CommandObjectSP command_sp;
-
- std::string cmd(cmd_cstr);
+int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) {
+ int position = 0; // Any string that isn't an argument position, i.e. '%'
+ // followed by an integer, gets a position
+ // of zero.
- if (HasCommands())
- {
- pos = m_command_dict.find(cmd);
- if (pos != m_command_dict.end())
- command_sp = pos->second;
- }
-
- if (include_aliases && HasAliases())
- {
- auto alias_pos = m_alias_dict.find(cmd);
- if (alias_pos != m_alias_dict.end())
- command_sp = alias_pos->second;
- }
-
- if (HasUserCommands())
- {
- pos = m_user_dict.find(cmd);
- if (pos != m_user_dict.end())
- command_sp = pos->second;
- }
-
- if (!exact && !command_sp)
- {
- // We will only get into here if we didn't find any exact matches.
-
- CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
-
- StringList local_matches;
- if (matches == nullptr)
- matches = &local_matches;
-
- unsigned int num_cmd_matches = 0;
- unsigned int num_alias_matches = 0;
- unsigned int num_user_matches = 0;
-
- // Look through the command dictionaries one by one, and if we get only one match from any of
- // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
-
- if (HasCommands())
- {
- num_cmd_matches = AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
- }
+ const char *cptr = in_string;
- if (num_cmd_matches == 1)
- {
- cmd.assign(matches->GetStringAtIndex(0));
- pos = m_command_dict.find(cmd);
- if (pos != m_command_dict.end())
- real_match_sp = pos->second;
- }
+ // Does it start with '%'
+ if (cptr[0] == '%') {
+ ++cptr;
- if (include_aliases && HasAliases())
- {
- num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
+ // Is the rest of it entirely digits?
+ if (isdigit(cptr[0])) {
+ const char *start = cptr;
+ while (isdigit(cptr[0]))
+ ++cptr;
- }
+ // We've gotten to the end of the digits; are we at the end of the string?
+ if (cptr[0] == '\0')
+ position = atoi(start);
+ }
+ }
+
+ return position;
+}
+
+void CommandInterpreter::SourceInitFile(bool in_cwd,
+ CommandReturnObject &result) {
+ FileSpec init_file;
+ if (in_cwd) {
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ // In the current working directory we don't load any program specific
+ // .lldbinit files, we only look for a ".lldbinit" file.
+ if (m_skip_lldbinit_files)
+ return;
- if (num_alias_matches == 1)
- {
- cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
- auto alias_pos = m_alias_dict.find(cmd);
- if (alias_pos != m_alias_dict.end())
- alias_match_sp = alias_pos->second;
- }
+ LoadCWDlldbinitFile should_load =
+ target->TargetProperties::GetLoadCWDlldbinitFile();
+ if (should_load == eLoadCWDlldbinitWarn) {
+ FileSpec dot_lldb(".lldbinit", true);
+ llvm::SmallString<64> home_dir_path;
+ llvm::sys::path::home_directory(home_dir_path);
+ FileSpec homedir_dot_lldb(home_dir_path.c_str(), false);
+ homedir_dot_lldb.AppendPathComponent(".lldbinit");
+ homedir_dot_lldb.ResolvePath();
+ if (dot_lldb.Exists() &&
+ dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) {
+ result.AppendErrorWithFormat(
+ "There is a .lldbinit file in the current directory which is not "
+ "being read.\n"
+ "To silence this warning without sourcing in the local "
+ ".lldbinit,\n"
+ "add the following to the lldbinit file in your home directory:\n"
+ " settings set target.load-cwd-lldbinit false\n"
+ "To allow lldb to source .lldbinit files in the current working "
+ "directory,\n"
+ "set the value of this variable to true. Only do so if you "
+ "understand and\n"
+ "accept the security risk.");
+ result.SetStatus(eReturnStatusFailed);
+ return;
+ }
+ } else if (should_load == eLoadCWDlldbinitTrue) {
+ init_file.SetFile("./.lldbinit", true);
+ }
+ }
+ } else {
+ // If we aren't looking in the current working directory we are looking
+ // in the home directory. We will first see if there is an application
+ // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
+ // "-" and the name of the program. If this file doesn't exist, we fall
+ // back to just the "~/.lldbinit" file. We also obey any requests to not
+ // load the init files.
+ llvm::SmallString<64> home_dir_path;
+ llvm::sys::path::home_directory(home_dir_path);
+ FileSpec profilePath(home_dir_path.c_str(), false);
+ profilePath.AppendPathComponent(".lldbinit");
+ std::string init_file_path = profilePath.GetPath();
+
+ if (m_skip_app_init_files == false) {
+ FileSpec program_file_spec(HostInfo::GetProgramFileSpec());
+ const char *program_name = program_file_spec.GetFilename().AsCString();
+
+ if (program_name) {
+ char program_init_file_name[PATH_MAX];
+ ::snprintf(program_init_file_name, sizeof(program_init_file_name),
+ "%s-%s", init_file_path.c_str(), program_name);
+ init_file.SetFile(program_init_file_name, true);
+ if (!init_file.Exists())
+ init_file.Clear();
+ }
+ }
+
+ if (!init_file && !m_skip_lldbinit_files)
+ init_file.SetFile(init_file_path.c_str(), false);
+ }
+
+ // If the file exists, tell HandleCommand to 'source' it; this will do the
+ // actual broadcasting
+ // of the commands back to any appropriate listener (see
+ // CommandObjectSource::Execute for more details).
+
+ if (init_file.Exists()) {
+ const bool saved_batch = SetBatchCommandMode(true);
+ CommandInterpreterRunOptions options;
+ options.SetSilent(true);
+ options.SetStopOnError(false);
+ options.SetStopOnContinue(true);
+
+ HandleCommandsFromFile(init_file,
+ nullptr, // Execution context
+ options, result);
+ SetBatchCommandMode(saved_batch);
+ } else {
+ // nothing to be done if the file doesn't exist
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+}
+
+const char *CommandInterpreter::GetCommandPrefix() {
+ const char *prefix = GetDebugger().GetIOHandlerCommandPrefix();
+ return prefix == NULL ? "" : prefix;
+}
+
+PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) {
+ PlatformSP platform_sp;
+ if (prefer_target_platform) {
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ platform_sp = target->GetPlatform();
+ }
+
+ if (!platform_sp)
+ platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
+ return platform_sp;
+}
+
+void CommandInterpreter::HandleCommands(const StringList &commands,
+ ExecutionContext *override_context,
+ CommandInterpreterRunOptions &options,
+ CommandReturnObject &result) {
+ size_t num_lines = commands.GetSize();
+
+ // If we are going to continue past a "continue" then we need to run the
+ // commands synchronously.
+ // Make sure you reset this value anywhere you return from the function.
+
+ bool old_async_execution = m_debugger.GetAsyncExecution();
+
+ // If we've been given an execution context, set it at the start, but don't
+ // keep resetting it or we will
+ // cause series of commands that change the context, then do an operation that
+ // relies on that context to fail.
+
+ if (override_context != nullptr)
+ UpdateExecutionContext(override_context);
+
+ if (!options.GetStopOnContinue()) {
+ m_debugger.SetAsyncExecution(false);
+ }
+
+ for (size_t idx = 0; idx < num_lines; idx++) {
+ const char *cmd = commands.GetStringAtIndex(idx);
+ if (cmd[0] == '\0')
+ continue;
+
+ if (options.GetEchoCommands()) {
+ result.AppendMessageWithFormat("%s %s\n", m_debugger.GetPrompt(), cmd);
+ }
+
+ CommandReturnObject tmp_result;
+ // If override_context is not NULL, pass no_context_switching = true for
+ // HandleCommand() since we updated our context already.
+
+ // We might call into a regex or alias command, in which case the
+ // add_to_history will get lost. This
+ // m_command_source_depth dingus is the way we turn off adding to the
+ // history in that case, so set it up here.
+ if (!options.GetAddToHistory())
+ m_command_source_depth++;
+ bool success =
+ HandleCommand(cmd, options.m_add_to_history, tmp_result,
+ nullptr, /* override_context */
+ true, /* repeat_on_empty_command */
+ override_context != nullptr /* no_context_switching */);
+ if (!options.GetAddToHistory())
+ m_command_source_depth--;
+
+ if (options.GetPrintResults()) {
+ if (tmp_result.Succeeded())
+ result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
+ }
+
+ if (!success || !tmp_result.Succeeded()) {
+ const char *error_msg = tmp_result.GetErrorData();
+ if (error_msg == nullptr || error_msg[0] == '\0')
+ error_msg = "<unknown error>.\n";
+ if (options.GetStopOnError()) {
+ result.AppendErrorWithFormat(
+ "Aborting reading of commands after command #%" PRIu64
+ ": '%s' failed with %s",
+ (uint64_t)idx, cmd, error_msg);
+ result.SetStatus(eReturnStatusFailed);
+ m_debugger.SetAsyncExecution(old_async_execution);
+ return;
+ } else if (options.GetPrintResults()) {
+ result.AppendMessageWithFormat("Command #%" PRIu64
+ " '%s' failed with %s",
+ (uint64_t)idx + 1, cmd, error_msg);
+ }
+ }
+
+ if (result.GetImmediateOutputStream())
+ result.GetImmediateOutputStream()->Flush();
+
+ if (result.GetImmediateErrorStream())
+ result.GetImmediateErrorStream()->Flush();
+
+ // N.B. Can't depend on DidChangeProcessState, because the state coming into
+ // the command execution
+ // could be running (for instance in Breakpoint Commands.
+ // So we check the return value to see if it is has running in it.
+ if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
+ (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) {
+ if (options.GetStopOnContinue()) {
+ // If we caused the target to proceed, and we're going to stop in that
+ // case, set the
+ // status in our real result before returning. This is an error if the
+ // continue was not the
+ // last command in the set of commands to be run.
+ if (idx != num_lines - 1)
+ result.AppendErrorWithFormat(
+ "Aborting reading of commands after command #%" PRIu64
+ ": '%s' continued the target.\n",
+ (uint64_t)idx + 1, cmd);
+ else
+ result.AppendMessageWithFormat("Command #%" PRIu64
+ " '%s' continued the target.\n",
+ (uint64_t)idx + 1, cmd);
- if (HasUserCommands())
- {
- num_user_matches = AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
- }
+ result.SetStatus(tmp_result.GetStatus());
+ m_debugger.SetAsyncExecution(old_async_execution);
- if (num_user_matches == 1)
- {
- cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
-
- pos = m_user_dict.find (cmd);
- if (pos != m_user_dict.end())
- user_match_sp = pos->second;
- }
-
- // If we got exactly one match, return that, otherwise return the match list.
-
- if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
- {
- if (num_cmd_matches)
- return real_match_sp;
- else if (num_alias_matches)
- return alias_match_sp;
- else
- return user_match_sp;
- }
- }
- else if (matches && command_sp)
- {
- matches->AppendString (cmd_cstr);
+ return;
+ }
}
+ // Also check for "stop on crash here:
+ bool should_stop = false;
+ if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) {
+ TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
+ if (target_sp) {
+ ProcessSP process_sp(target_sp->GetProcessSP());
+ if (process_sp) {
+ for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) {
+ StopReason reason = thread_sp->GetStopReason();
+ if (reason == eStopReasonSignal || reason == eStopReasonException ||
+ reason == eStopReasonInstrumentation) {
+ should_stop = true;
+ break;
+ }
+ }
+ }
+ }
+ if (should_stop) {
+ if (idx != num_lines - 1)
+ result.AppendErrorWithFormat(
+ "Aborting reading of commands after command #%" PRIu64
+ ": '%s' stopped with a signal or exception.\n",
+ (uint64_t)idx + 1, cmd);
+ else
+ result.AppendMessageWithFormat(
+ "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n",
+ (uint64_t)idx + 1, cmd);
- return command_sp;
-}
-
-bool
-CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
-{
- if (cmd_sp.get())
- assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
+ result.SetStatus(tmp_result.GetStatus());
+ m_debugger.SetAsyncExecution(old_async_execution);
- if (name && name[0])
- {
- std::string name_sstr(name);
- bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
- if (found && !can_replace)
- return false;
- if (found && m_command_dict[name_sstr]->IsRemovable() == false)
- return false;
- m_command_dict[name_sstr] = cmd_sp;
- return true;
+ return;
+ }
}
- return false;
-}
+ }
-bool
-CommandInterpreter::AddUserCommand (std::string name,
- const lldb::CommandObjectSP &cmd_sp,
- bool can_replace)
-{
- if (cmd_sp.get())
- assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ m_debugger.SetAsyncExecution(old_async_execution);
- if (!name.empty())
- {
- const char* name_cstr = name.c_str();
-
- // do not allow replacement of internal commands
- if (CommandExists(name_cstr))
- {
- if (can_replace == false)
- return false;
- if (m_command_dict[name]->IsRemovable() == false)
- return false;
- }
-
- if (UserCommandExists(name_cstr))
- {
- if (can_replace == false)
- return false;
- if (m_user_dict[name]->IsRemovable() == false)
- return false;
- }
-
- m_user_dict[name] = cmd_sp;
- return true;
- }
- return false;
+ return;
}
-CommandObjectSP
-CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
-{
- Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
- CommandObjectSP ret_val; // Possibly empty return value.
-
- if (cmd_cstr == nullptr)
- return ret_val;
-
- if (cmd_words.GetArgumentCount() == 1)
- return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);
- else
- {
- // We have a multi-word command (seemingly), so we need to do more work.
- // First, get the cmd_obj_sp for the first word in the command.
- CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr);
- if (cmd_obj_sp.get() != nullptr)
- {
- // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
- // command name), and find the appropriate sub-command SP for each command word....
- size_t end = cmd_words.GetArgumentCount();
- for (size_t j= 1; j < end; ++j)
- {
- if (cmd_obj_sp->IsMultiwordObject())
- {
- cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
- if (cmd_obj_sp.get() == nullptr)
- // The sub-command name was invalid. Fail and return the empty 'ret_val'.
- return ret_val;
- }
- else
- // We have more words in the command name, but we don't have a multiword object. Fail and return
- // empty 'ret_val'.
- return ret_val;
- }
- // We successfully looped through all the command words and got valid command objects for them. Assign the
- // last object retrieved to 'ret_val'.
- ret_val = cmd_obj_sp;
- }
- }
- return ret_val;
-}
+// Make flags that we can pass into the IOHandler so our delegates can do the
+// right thing
+enum {
+ eHandleCommandFlagStopOnContinue = (1u << 0),
+ eHandleCommandFlagStopOnError = (1u << 1),
+ eHandleCommandFlagEchoCommand = (1u << 2),
+ eHandleCommandFlagPrintResult = (1u << 3),
+ eHandleCommandFlagStopOnCrash = (1u << 4)
+};
-CommandObject *
-CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
-{
- return GetCommandSPExact (cmd_cstr, include_aliases).get();
+void CommandInterpreter::HandleCommandsFromFile(
+ FileSpec &cmd_file, ExecutionContext *context,
+ CommandInterpreterRunOptions &options, CommandReturnObject &result) {
+ if (cmd_file.Exists()) {
+ StreamFileSP input_file_sp(new StreamFile());
+
+ std::string cmd_file_path = cmd_file.GetPath();
+ Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(),
+ File::eOpenOptionRead);
+
+ if (error.Success()) {
+ Debugger &debugger = GetDebugger();
+
+ uint32_t flags = 0;
+
+ if (options.m_stop_on_continue == eLazyBoolCalculate) {
+ if (m_command_source_flags.empty()) {
+ // Stop on continue by default
+ flags |= eHandleCommandFlagStopOnContinue;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagStopOnContinue) {
+ flags |= eHandleCommandFlagStopOnContinue;
+ }
+ } else if (options.m_stop_on_continue == eLazyBoolYes) {
+ flags |= eHandleCommandFlagStopOnContinue;
+ }
+
+ if (options.m_stop_on_error == eLazyBoolCalculate) {
+ if (m_command_source_flags.empty()) {
+ if (GetStopCmdSourceOnError())
+ flags |= eHandleCommandFlagStopOnError;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagStopOnError) {
+ flags |= eHandleCommandFlagStopOnError;
+ }
+ } else if (options.m_stop_on_error == eLazyBoolYes) {
+ flags |= eHandleCommandFlagStopOnError;
+ }
+
+ if (options.GetStopOnCrash()) {
+ if (m_command_source_flags.empty()) {
+ // Echo command by default
+ flags |= eHandleCommandFlagStopOnCrash;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagStopOnCrash) {
+ flags |= eHandleCommandFlagStopOnCrash;
+ }
+ }
+
+ if (options.m_echo_commands == eLazyBoolCalculate) {
+ if (m_command_source_flags.empty()) {
+ // Echo command by default
+ flags |= eHandleCommandFlagEchoCommand;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagEchoCommand) {
+ flags |= eHandleCommandFlagEchoCommand;
+ }
+ } else if (options.m_echo_commands == eLazyBoolYes) {
+ flags |= eHandleCommandFlagEchoCommand;
+ }
+
+ if (options.m_print_results == eLazyBoolCalculate) {
+ if (m_command_source_flags.empty()) {
+ // Print output by default
+ flags |= eHandleCommandFlagPrintResult;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagPrintResult) {
+ flags |= eHandleCommandFlagPrintResult;
+ }
+ } else if (options.m_print_results == eLazyBoolYes) {
+ flags |= eHandleCommandFlagPrintResult;
+ }
+
+ if (flags & eHandleCommandFlagPrintResult) {
+ debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n",
+ cmd_file_path.c_str());
+ }
+
+ // Used for inheriting the right settings when "command source" might have
+ // nested "command source" commands
+ lldb::StreamFileSP empty_stream_sp;
+ m_command_source_flags.push_back(flags);
+ IOHandlerSP io_handler_sp(new IOHandlerEditline(
+ debugger, IOHandler::Type::CommandInterpreter, input_file_sp,
+ empty_stream_sp, // Pass in an empty stream so we inherit the top
+ // input reader output stream
+ empty_stream_sp, // Pass in an empty stream so we inherit the top
+ // input reader error stream
+ flags,
+ nullptr, // Pass in NULL for "editline_name" so no history is saved,
+ // or written
+ debugger.GetPrompt(), NULL,
+ false, // Not multi-line
+ debugger.GetUseColor(), 0, *this));
+ const bool old_async_execution = debugger.GetAsyncExecution();
+
+ // Set synchronous execution if we are not stopping on continue
+ if ((flags & eHandleCommandFlagStopOnContinue) == 0)
+ debugger.SetAsyncExecution(false);
+
+ m_command_source_depth++;
+
+ debugger.RunIOHandler(io_handler_sp);
+ if (!m_command_source_flags.empty())
+ m_command_source_flags.pop_back();
+ m_command_source_depth--;
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ debugger.SetAsyncExecution(old_async_execution);
+ } else {
+ result.AppendErrorWithFormat(
+ "error: an error occurred read file '%s': %s\n",
+ cmd_file_path.c_str(), error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ }
+
+ } else {
+ result.AppendErrorWithFormat(
+ "Error reading commands from file %s - file not found.\n",
+ cmd_file.GetFilename().AsCString("<Unknown>"));
+ result.SetStatus(eReturnStatusFailed);
+ return;
+ }
}
-CommandObject *
-CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
-{
- CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
+ScriptInterpreter *CommandInterpreter::GetScriptInterpreter(bool can_create) {
+ if (m_script_interpreter_sp)
+ return m_script_interpreter_sp.get();
- // If we didn't find an exact match to the command string in the commands, look in
- // the aliases.
-
- if (command_obj)
- return command_obj;
-
- command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
-
- if (command_obj)
- return command_obj;
-
- // If there wasn't an exact match then look for an inexact one in just the commands
- command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();
-
- // Finally, if there wasn't an inexact match among the commands, look for an inexact
- // match in both the commands and aliases.
-
- if (command_obj)
- {
- if (matches)
- matches->AppendString(command_obj->GetCommandName());
- return command_obj;
- }
-
- return GetCommandSP(cmd_cstr, true, false, matches).get();
-}
+ if (!can_create)
+ return nullptr;
-bool
-CommandInterpreter::CommandExists (const char *cmd)
-{
- return m_command_dict.find(cmd) != m_command_dict.end();
-}
+ lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
+ m_script_interpreter_sp =
+ PluginManager::GetScriptInterpreterForLanguage(script_lang, *this);
+ return m_script_interpreter_sp.get();
+}
+
+bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution; }
+
+void CommandInterpreter::SetSynchronous(bool value) {
+ m_synchronous_execution = value;
+}
+
+void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
+ const char *prefix,
+ const char *help_text) {
+ const uint32_t max_columns = m_debugger.GetTerminalWidth();
+ if (prefix == NULL)
+ prefix = "";
+
+ size_t prefix_width = strlen(prefix);
+ size_t line_width_max = max_columns - prefix_width;
+ const char *help_text_end = help_text + strlen(help_text);
+ const char *line_start = help_text;
+ if (line_width_max < 16)
+ line_width_max = help_text_end - help_text + prefix_width;
+
+ strm.IndentMore(prefix_width);
+ while (line_start < help_text_end) {
+ // Break each line at the first newline or last space/tab before
+ // the maximum number of characters that fit on a line. Lines with no
+ // natural break are left unbroken to wrap.
+ const char *line_end = help_text_end;
+ const char *line_scan = line_start;
+ const char *line_scan_end = help_text_end;
+ while (line_scan < line_scan_end) {
+ char next = *line_scan;
+ if (next == '\t' || next == ' ') {
+ line_end = line_scan;
+ line_scan_end = line_start + line_width_max;
+ } else if (next == '\n' || next == '\0') {
+ line_end = line_scan;
+ break;
+ }
+ ++line_scan;
+ }
+
+ // Prefix the first line, indent subsequent lines to line up
+ if (line_start == help_text)
+ strm.Write(prefix, prefix_width);
+ else
+ strm.Indent();
+ strm.Write(line_start, line_end - line_start);
+ strm.EOL();
-bool
-CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
-{
- bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
- if (exact_match)
- {
- full_name.assign(cmd);
- return exact_match;
- }
+ // When a line breaks at whitespace consume it before continuing
+ line_start = line_end;
+ char next = *line_start;
+ if (next == '\n')
+ ++line_start;
else
- {
- StringList matches;
- size_t num_alias_matches;
- num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
- if (num_alias_matches == 1)
- {
- // Make sure this isn't shadowing a command in the regular command space:
- StringList regular_matches;
- const bool include_aliases = false;
- const bool exact = false;
- CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches));
- if (cmd_obj_sp || regular_matches.GetSize() > 0)
- return false;
- else
- {
- full_name.assign (matches.GetStringAtIndex(0));
- return true;
- }
+ while (next == ' ' || next == '\t')
+ next = *(++line_start);
+ }
+ strm.IndentLess(prefix_width);
+}
+
+void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
+ const char *word_text,
+ const char *separator,
+ const char *help_text,
+ size_t max_word_len) {
+ StreamString prefix_stream;
+ prefix_stream.Printf(" %-*s %s ", (int)max_word_len, word_text, separator);
+ OutputFormattedHelpText(strm, prefix_stream.GetData(), help_text);
+}
+
+void CommandInterpreter::OutputHelpText(Stream &strm, const char *word_text,
+ const char *separator,
+ const char *help_text,
+ uint32_t max_word_len) {
+ int indent_size = max_word_len + strlen(separator) + 2;
+
+ strm.IndentMore(indent_size);
+
+ StreamString text_strm;
+ text_strm.Printf("%-*s %s %s", max_word_len, word_text, separator, help_text);
+
+ const uint32_t max_columns = m_debugger.GetTerminalWidth();
+
+ size_t len = text_strm.GetSize();
+ const char *text = text_strm.GetData();
+
+ uint32_t chars_left = max_columns;
+
+ for (uint32_t i = 0; i < len; i++) {
+ if ((text[i] == ' ' && ::strchr((text + i + 1), ' ') &&
+ chars_left < ::strchr((text + i + 1), ' ') - (text + i)) ||
+ text[i] == '\n') {
+ chars_left = max_columns - indent_size;
+ strm.EOL();
+ strm.Indent();
+ } else {
+ strm.PutChar(text[i]);
+ chars_left--;
+ }
+ }
+
+ strm.EOL();
+ strm.IndentLess(indent_size);
+}
+
+void CommandInterpreter::FindCommandsForApropos(
+ const char *search_word, StringList &commands_found,
+ StringList &commands_help, CommandObject::CommandMap &command_map) {
+ CommandObject::CommandMap::const_iterator pos;
+
+ for (pos = command_map.begin(); pos != command_map.end(); ++pos) {
+ const char *command_name = pos->first.c_str();
+ CommandObject *cmd_obj = pos->second.get();
+
+ const bool search_short_help = true;
+ const bool search_long_help = false;
+ const bool search_syntax = false;
+ const bool search_options = false;
+ if (strcasestr(command_name, search_word) ||
+ cmd_obj->HelpTextContainsWord(search_word, search_short_help,
+ search_long_help, search_syntax,
+ search_options)) {
+ commands_found.AppendString(cmd_obj->GetCommandName());
+ commands_help.AppendString(cmd_obj->GetHelp());
+ }
+
+ if (cmd_obj->IsMultiwordObject()) {
+ CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand();
+ FindCommandsForApropos(search_word, commands_found, commands_help,
+ cmd_multiword->GetSubcommandDictionary());
+ }
+ }
+}
+
+void CommandInterpreter::FindCommandsForApropos(const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help,
+ bool search_builtin_commands,
+ bool search_user_commands,
+ bool search_alias_commands) {
+ CommandObject::CommandMap::const_iterator pos;
+
+ if (search_builtin_commands)
+ FindCommandsForApropos(search_word, commands_found, commands_help,
+ m_command_dict);
+
+ if (search_user_commands)
+ FindCommandsForApropos(search_word, commands_found, commands_help,
+ m_user_dict);
+
+ if (search_alias_commands)
+ FindCommandsForApropos(search_word, commands_found, commands_help,
+ m_alias_dict);
+}
+
+void CommandInterpreter::UpdateExecutionContext(
+ ExecutionContext *override_context) {
+ if (override_context != nullptr) {
+ m_exe_ctx_ref = *override_context;
+ } else {
+ const bool adopt_selected = true;
+ m_exe_ctx_ref.SetTargetPtr(m_debugger.GetSelectedTarget().get(),
+ adopt_selected);
+ }
+}
+
+size_t CommandInterpreter::GetProcessOutput() {
+ // The process has stuff waiting for stderr; get it and write it out to the
+ // appropriate place.
+ char stdio_buffer[1024];
+ size_t len;
+ size_t total_bytes = 0;
+ Error error;
+ TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
+ if (target_sp) {
+ ProcessSP process_sp(target_sp->GetProcessSP());
+ if (process_sp) {
+ while ((len = process_sp->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
+ error)) > 0) {
+ size_t bytes_written = len;
+ m_debugger.GetOutputFile()->Write(stdio_buffer, bytes_written);
+ total_bytes += len;
+ }
+ while ((len = process_sp->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
+ error)) > 0) {
+ size_t bytes_written = len;
+ m_debugger.GetErrorFile()->Write(stdio_buffer, bytes_written);
+ total_bytes += len;
+ }
+ }
+ }
+ return total_bytes;
+}
+
+void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &line) {
+ const bool is_interactive = io_handler.GetIsInteractive();
+ if (is_interactive == false) {
+ // When we are not interactive, don't execute blank lines. This will happen
+ // sourcing a commands file. We don't want blank lines to repeat the
+ // previous
+ // command and cause any errors to occur (like redefining an alias, get an
+ // error
+ // and stop parsing the commands file).
+ if (line.empty())
+ return;
+
+ // When using a non-interactive file handle (like when sourcing commands
+ // from a file)
+ // we need to echo the command out so we don't just see the command output
+ // and no
+ // command...
+ if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
+ io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(),
+ line.c_str());
+ }
+
+ lldb_private::CommandReturnObject result;
+ HandleCommand(line.c_str(), eLazyBoolCalculate, result);
+
+ // Now emit the command output text from the command we just executed
+ if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) {
+ // Display any STDOUT/STDERR _prior_ to emitting the command result text
+ GetProcessOutput();
+
+ if (!result.GetImmediateOutputStream()) {
+ const char *output = result.GetOutputData();
+ if (output && output[0])
+ io_handler.GetOutputStreamFile()->PutCString(output);
+ }
+
+ // Now emit the command error text from the command we just executed
+ if (!result.GetImmediateErrorStream()) {
+ const char *error = result.GetErrorData();
+ if (error && error[0])
+ io_handler.GetErrorStreamFile()->PutCString(error);
+ }
+ }
+
+ switch (result.GetStatus()) {
+ case eReturnStatusInvalid:
+ case eReturnStatusSuccessFinishNoResult:
+ case eReturnStatusSuccessFinishResult:
+ case eReturnStatusStarted:
+ break;
+
+ case eReturnStatusSuccessContinuingNoResult:
+ case eReturnStatusSuccessContinuingResult:
+ if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
+ io_handler.SetIsDone(true);
+ break;
+
+ case eReturnStatusFailed:
+ m_num_errors++;
+ if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
+ io_handler.SetIsDone(true);
+ break;
+
+ case eReturnStatusQuit:
+ m_quit_requested = true;
+ io_handler.SetIsDone(true);
+ break;
+ }
+
+ // Finally, if we're going to stop on crash, check that here:
+ if (!m_quit_requested && result.GetDidChangeProcessState() &&
+ io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) {
+ bool should_stop = false;
+ TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
+ if (target_sp) {
+ ProcessSP process_sp(target_sp->GetProcessSP());
+ if (process_sp) {
+ for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) {
+ StopReason reason = thread_sp->GetStopReason();
+ if ((reason == eStopReasonSignal || reason == eStopReasonException ||
+ reason == eStopReasonInstrumentation) &&
+ !result.GetAbnormalStopWasExpected()) {
+ should_stop = true;
+ break;
+ }
}
- else
- return false;
- }
-}
-
-bool
-CommandInterpreter::AliasExists (const char *cmd)
-{
- return m_alias_dict.find(cmd) != m_alias_dict.end();
-}
-
-bool
-CommandInterpreter::UserCommandExists (const char *cmd)
-{
- return m_user_dict.find(cmd) != m_user_dict.end();
-}
-
-CommandAlias*
-CommandInterpreter::AddAlias (const char *alias_name,
- lldb::CommandObjectSP& command_obj_sp,
- const char *args_string)
-{
- if (command_obj_sp.get())
- assert((this == &command_obj_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
-
- std::unique_ptr<CommandAlias> command_alias_up(new CommandAlias(*this,
- command_obj_sp,
- args_string,
- alias_name));
-
- if (command_alias_up && command_alias_up->IsValid())
- {
- m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get());
- return command_alias_up.release();
+ }
}
-
- return nullptr;
+ if (should_stop) {
+ io_handler.SetIsDone(true);
+ m_stopped_for_crash = true;
+ }
+ }
+}
+
+bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) {
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsRunningState(state)) {
+ process->Halt();
+ return true; // Don't do any updating when we are running
+ }
+ }
+
+ ScriptInterpreter *script_interpreter = GetScriptInterpreter(false);
+ if (script_interpreter) {
+ if (script_interpreter->Interrupt())
+ return true;
+ }
+ return false;
+}
+
+void CommandInterpreter::GetLLDBCommandsFromIOHandler(
+ const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
+ void *baton) {
+ Debugger &debugger = GetDebugger();
+ IOHandlerSP io_handler_sp(
+ new IOHandlerEditline(debugger, IOHandler::Type::CommandList,
+ "lldb", // Name of input reader for history
+ prompt, // Prompt
+ NULL, // Continuation prompt
+ true, // Get multiple lines
+ debugger.GetUseColor(),
+ 0, // Don't show line numbers
+ delegate)); // IOHandlerDelegate
+
+ if (io_handler_sp) {
+ io_handler_sp->SetUserData(baton);
+ if (asynchronously)
+ debugger.PushIOHandler(io_handler_sp);
+ else
+ debugger.RunIOHandler(io_handler_sp);
+ }
}
-bool
-CommandInterpreter::RemoveAlias (const char *alias_name)
-{
- auto pos = m_alias_dict.find(alias_name);
- if (pos != m_alias_dict.end())
- {
- m_alias_dict.erase(pos);
- return true;
- }
- return false;
+void CommandInterpreter::GetPythonCommandsFromIOHandler(
+ const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
+ void *baton) {
+ Debugger &debugger = GetDebugger();
+ IOHandlerSP io_handler_sp(
+ new IOHandlerEditline(debugger, IOHandler::Type::PythonCode,
+ "lldb-python", // Name of input reader for history
+ prompt, // Prompt
+ NULL, // Continuation prompt
+ true, // Get multiple lines
+ debugger.GetUseColor(),
+ 0, // Don't show line numbers
+ delegate)); // IOHandlerDelegate
+
+ if (io_handler_sp) {
+ io_handler_sp->SetUserData(baton);
+ if (asynchronously)
+ debugger.PushIOHandler(io_handler_sp);
+ else
+ debugger.RunIOHandler(io_handler_sp);
+ }
}
-bool
-CommandInterpreter::RemoveCommand (const char *cmd)
-{
- auto pos = m_command_dict.find(cmd);
- if (pos != m_command_dict.end())
- {
- if (pos->second->IsRemovable())
- {
- // Only regular expression objects or python commands are removable
- m_command_dict.erase(pos);
- return true;
- }
- }
- return false;
-}
-bool
-CommandInterpreter::RemoveUser (const char *alias_name)
-{
- CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
- if (pos != m_user_dict.end())
- {
- m_user_dict.erase(pos);
- return true;
- }
- return false;
+bool CommandInterpreter::IsActive() {
+ return m_debugger.IsTopIOHandler(m_command_io_handler_sp);
}
-void
-CommandInterpreter::GetHelp (CommandReturnObject &result,
- uint32_t cmd_types)
-{
- const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue();
- if (help_prologue != NULL)
- {
- OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue);
- }
-
- CommandObject::CommandMap::const_iterator pos;
- size_t max_len = FindLongestCommandWord (m_command_dict);
-
- if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
- {
- result.AppendMessage("Debugger commands:");
- result.AppendMessage("");
-
- for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
- {
- if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0))
- continue;
-
- OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
- max_len);
- }
- result.AppendMessage("");
-
- }
-
- if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
- {
- result.AppendMessageWithFormat("Current command abbreviations "
- "(type '%shelp command alias' for more info):\n",
- GetCommandPrefix());
- result.AppendMessage("");
- max_len = FindLongestCommandWord (m_alias_dict);
-
- for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); ++alias_pos)
- {
- OutputFormattedHelpText (result.GetOutputStream(), alias_pos->first.c_str(), "--", alias_pos->second->GetHelp(),
- max_len);
- }
- result.AppendMessage("");
- }
+lldb::IOHandlerSP
+CommandInterpreter::GetIOHandler(bool force_create,
+ CommandInterpreterRunOptions *options) {
+ // Always re-create the IOHandlerEditline in case the input
+ // changed. The old instance might have had a non-interactive
+ // input and now it does or vice versa.
+ if (force_create || !m_command_io_handler_sp) {
+ // Always re-create the IOHandlerEditline in case the input
+ // changed. The old instance might have had a non-interactive
+ // input and now it does or vice versa.
+ uint32_t flags = 0;
- if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
- {
- result.AppendMessage ("Current user-defined commands:");
- result.AppendMessage("");
- max_len = FindLongestCommandWord (m_user_dict);
- for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
- {
- OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
- max_len);
- }
- result.AppendMessage("");
- }
+ if (options) {
+ if (options->m_stop_on_continue == eLazyBoolYes)
+ flags |= eHandleCommandFlagStopOnContinue;
+ if (options->m_stop_on_error == eLazyBoolYes)
+ flags |= eHandleCommandFlagStopOnError;
+ if (options->m_stop_on_crash == eLazyBoolYes)
+ flags |= eHandleCommandFlagStopOnCrash;
+ if (options->m_echo_commands != eLazyBoolNo)
+ flags |= eHandleCommandFlagEchoCommand;
+ if (options->m_print_results != eLazyBoolNo)
+ flags |= eHandleCommandFlagPrintResult;
+ } else {
+ flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult;
+ }
+
+ m_command_io_handler_sp.reset(new IOHandlerEditline(
+ m_debugger, IOHandler::Type::CommandInterpreter,
+ m_debugger.GetInputFile(), m_debugger.GetOutputFile(),
+ m_debugger.GetErrorFile(), flags, "lldb", m_debugger.GetPrompt(),
+ NULL, // Continuation prompt
+ false, // Don't enable multiple line input, just single line commands
+ m_debugger.GetUseColor(),
+ 0, // Don't show line numbers
+ *this));
+ }
+ return m_command_io_handler_sp;
+}
+
+void CommandInterpreter::RunCommandInterpreter(
+ bool auto_handle_events, bool spawn_thread,
+ CommandInterpreterRunOptions &options) {
+ // Always re-create the command interpreter when we run it in case
+ // any file handles have changed.
+ bool force_create = true;
+ m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
+ m_stopped_for_crash = false;
+
+ if (auto_handle_events)
+ m_debugger.StartEventHandlerThread();
+
+ if (spawn_thread) {
+ m_debugger.StartIOHandlerThread();
+ } else {
+ m_debugger.ExecuteIOHandlers();
- result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n",
- GetCommandPrefix());
+ if (auto_handle_events)
+ m_debugger.StopEventHandlerThread();
+ }
}
CommandObject *
-CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
-{
- // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
- // eventually be invoked by the given command line.
-
- CommandObject *cmd_obj = nullptr;
- size_t start = command_string.find_first_not_of (k_white_space);
- size_t end = 0;
- bool done = false;
- while (!done)
- {
- if (start != std::string::npos)
- {
- // Get the next word from command_string.
- end = command_string.find_first_of (k_white_space, start);
- if (end == std::string::npos)
- end = command_string.size();
- std::string cmd_word = command_string.substr (start, end - start);
-
- if (cmd_obj == nullptr)
- // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
- // command or alias.
- cmd_obj = GetCommandObject (cmd_word.c_str());
- else if (cmd_obj->IsMultiwordObject ())
- {
- // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
- CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
- if (sub_cmd_obj)
- cmd_obj = sub_cmd_obj;
- else // cmd_word was not a valid sub-command word, so we are done
- done = true;
- }
- else
- // We have a cmd_obj and it is not a multi-word object, so we are done.
- done = true;
-
- // If we didn't find a valid command object, or our command object is not a multi-word object, or
- // we are at the end of the command_string, then we are done. Otherwise, find the start of the
- // next word.
-
- if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
- done = true;
- else
- start = command_string.find_first_not_of (k_white_space, end);
- }
+CommandInterpreter::ResolveCommandImpl(std::string &command_line,
+ CommandReturnObject &result) {
+ std::string scratch_command(command_line); // working copy so we don't modify
+ // command_line unless we succeed
+ CommandObject *cmd_obj = nullptr;
+ StreamString revised_command_line;
+ bool wants_raw_input = false;
+ size_t actual_cmd_name_len = 0;
+ std::string next_word;
+ StringList matches;
+ bool done = false;
+ while (!done) {
+ char quote_char = '\0';
+ std::string suffix;
+ ExtractCommand(scratch_command, next_word, suffix, quote_char);
+ if (cmd_obj == nullptr) {
+ std::string full_name;
+ bool is_alias = GetAliasFullName(next_word.c_str(), full_name);
+ cmd_obj = GetCommandObject(next_word.c_str(), &matches);
+ bool is_real_command =
+ (is_alias == false) ||
+ (cmd_obj != nullptr && cmd_obj->IsAlias() == false);
+ if (!is_real_command) {
+ matches.Clear();
+ std::string alias_result;
+ cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command,
+ alias_result, result);
+ revised_command_line.Printf("%s", alias_result.c_str());
+ if (cmd_obj) {
+ wants_raw_input = cmd_obj->WantsRawCommandString();
+ actual_cmd_name_len = strlen(cmd_obj->GetCommandName());
+ }
+ } else {
+ if (!cmd_obj)
+ cmd_obj = GetCommandObject(next_word.c_str(), &matches);
+ if (cmd_obj) {
+ actual_cmd_name_len += strlen(cmd_obj->GetCommandName());
+ revised_command_line.Printf("%s", cmd_obj->GetCommandName());
+ wants_raw_input = cmd_obj->WantsRawCommandString();
+ } else {
+ revised_command_line.Printf("%s", next_word.c_str());
+ }
+ }
+ } else {
+ if (cmd_obj->IsMultiwordObject()) {
+ CommandObject *sub_cmd_obj =
+ cmd_obj->GetSubcommandObject(next_word.c_str());
+ if (sub_cmd_obj) {
+ // The subcommand's name includes the parent command's name,
+ // so restart rather than append to the revised_command_line.
+ actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1;
+ revised_command_line.Clear();
+ revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName());
+ cmd_obj = sub_cmd_obj;
+ wants_raw_input = cmd_obj->WantsRawCommandString();
+ } else {
+ if (quote_char)
+ revised_command_line.Printf(" %c%s%s%c", quote_char,
+ next_word.c_str(), suffix.c_str(),
+ quote_char);
+ else
+ revised_command_line.Printf(" %s%s", next_word.c_str(),
+ suffix.c_str());
+ done = true;
+ }
+ } else {
+ if (quote_char)
+ revised_command_line.Printf(" %c%s%s%c", quote_char,
+ next_word.c_str(), suffix.c_str(),
+ quote_char);
else
- // Unable to find any more words.
- done = true;
- }
-
- if (end == command_string.size())
- command_string.clear();
- else
- command_string = command_string.substr(end);
-
- return cmd_obj;
-}
-
-static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
-static void
-StripLeadingSpaces (std::string &s)
-{
- if (!s.empty())
- {
- size_t pos = s.find_first_not_of (k_white_space);
- if (pos == std::string::npos)
- s.clear();
- else if (pos == 0)
- return;
- s.erase (0, pos);
- }
-}
-
-static size_t
-FindArgumentTerminator (const std::string &s)
-{
- const size_t s_len = s.size();
- size_t offset = 0;
- while (offset < s_len)
- {
- size_t pos = s.find ("--", offset);
- if (pos == std::string::npos)
- break;
- if (pos > 0)
- {
- if (isspace(s[pos-1]))
- {
- // Check if the string ends "\s--" (where \s is a space character)
- // or if we have "\s--\s".
- if ((pos + 2 >= s_len) || isspace(s[pos+2]))
- {
- return pos;
- }
- }
- }
- offset = pos + 2;
- }
- return std::string::npos;
-}
-
-static bool
-ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char)
-{
- command.clear();
- suffix.clear();
- StripLeadingSpaces (command_string);
-
- bool result = false;
- quote_char = '\0';
-
- if (!command_string.empty())
- {
- const char first_char = command_string[0];
- if (first_char == '\'' || first_char == '"')
- {
- quote_char = first_char;
- const size_t end_quote_pos = command_string.find (quote_char, 1);
- if (end_quote_pos == std::string::npos)
- {
- command.swap (command_string);
- command_string.erase ();
- }
- else
- {
- command.assign (command_string, 1, end_quote_pos - 1);
- if (end_quote_pos + 1 < command_string.size())
- command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
- else
- command_string.erase ();
- }
- }
- else
- {
- const size_t first_space_pos = command_string.find_first_of (k_white_space);
- if (first_space_pos == std::string::npos)
- {
- command.swap (command_string);
- command_string.erase();
- }
- else
- {
- command.assign (command_string, 0, first_space_pos);
- command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
- }
- }
- result = true;
- }
-
-
- if (!command.empty())
- {
- // actual commands can't start with '-' or '_'
- if (command[0] != '-' && command[0] != '_')
- {
- size_t pos = command.find_first_not_of(k_valid_command_chars);
- if (pos > 0 && pos != std::string::npos)
- {
- suffix.assign (command.begin() + pos, command.end());
- command.erase (pos);
- }
- }
- }
-
- return result;
-}
-
-CommandObject *
-CommandInterpreter::BuildAliasResult (const char *alias_name,
- std::string &raw_input_string,
- std::string &alias_result,
- CommandReturnObject &result)
-{
- CommandObject *alias_cmd_obj = nullptr;
- Args cmd_args (raw_input_string);
- alias_cmd_obj = GetCommandObject (alias_name);
- StreamString result_str;
-
- if (alias_cmd_obj && alias_cmd_obj->IsAlias())
- {
- std::pair<CommandObjectSP, OptionArgVectorSP> desugared = ((CommandAlias*)alias_cmd_obj)->Desugar();
- OptionArgVectorSP option_arg_vector_sp = desugared.second;
- alias_cmd_obj = desugared.first.get();
- std::string alias_name_str = alias_name;
- if ((cmd_args.GetArgumentCount() == 0)
- || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
- cmd_args.Unshift (alias_name);
-
- result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
-
- if (option_arg_vector_sp.get())
- {
- OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
-
- for (size_t i = 0; i < option_arg_vector->size(); ++i)
- {
- OptionArgPair option_pair = (*option_arg_vector)[i];
- OptionArgValue value_pair = option_pair.second;
- int value_type = value_pair.first;
- std::string option = option_pair.first;
- std::string value = value_pair.second;
- if (option.compare ("<argument>") == 0)
- result_str.Printf (" %s", value.c_str());
- else
- {
- result_str.Printf (" %s", option.c_str());
- if (value_type != OptionParser::eNoArgument)
- {
- if (value_type != OptionParser::eOptionalArgument)
- result_str.Printf (" ");
- int index = GetOptionArgumentPosition (value.c_str());
- if (index == 0)
- result_str.Printf ("%s", value.c_str());
- else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
- {
-
- result.AppendErrorWithFormat
- ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
- index);
- result.SetStatus (eReturnStatusFailed);
- return nullptr;
- }
- else
- {
- size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
- if (strpos != std::string::npos)
- raw_input_string = raw_input_string.erase (strpos,
- strlen (cmd_args.GetArgumentAtIndex (index)));
- result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
- }
- }
- }
- }
- }
-
- alias_result = result_str.GetData();
- }
- return alias_cmd_obj;
-}
-
-Error
-CommandInterpreter::PreprocessCommand (std::string &command)
-{
- // The command preprocessor needs to do things to the command
- // line before any parsing of arguments or anything else is done.
- // The only current stuff that gets preprocessed is anything enclosed
- // in backtick ('`') characters is evaluated as an expression and
- // the result of the expression must be a scalar that can be substituted
- // into the command. An example would be:
- // (lldb) memory read `$rsp + 20`
- Error error; // Error for any expressions that might not evaluate
- size_t start_backtick;
- size_t pos = 0;
- while ((start_backtick = command.find ('`', pos)) != std::string::npos)
- {
- if (start_backtick > 0 && command[start_backtick-1] == '\\')
- {
- // The backtick was preceded by a '\' character, remove the slash
- // and don't treat the backtick as the start of an expression
- command.erase(start_backtick-1, 1);
- // No need to add one to start_backtick since we just deleted a char
- pos = start_backtick;
- }
- else
- {
- const size_t expr_content_start = start_backtick + 1;
- const size_t end_backtick = command.find ('`', expr_content_start);
- if (end_backtick == std::string::npos)
- return error;
- else if (end_backtick == expr_content_start)
- {
- // Empty expression (two backticks in a row)
- command.erase (start_backtick, 2);
- }
- else
- {
- std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
-
- ExecutionContext exe_ctx(GetExecutionContext());
- Target *target = exe_ctx.GetTargetPtr();
- // Get a dummy target to allow for calculator mode while processing backticks.
- // This also helps break the infinite loop caused when target is null.
- if (!target)
- target = m_debugger.GetDummyTarget();
- if (target)
- {
- ValueObjectSP expr_result_valobj_sp;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetKeepInMemory(false);
- options.SetTryAllThreads(true);
- options.SetTimeoutUsec(0);
-
- ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
- exe_ctx.GetFramePtr(),
- expr_result_valobj_sp,
- options);
-
- if (expr_result == eExpressionCompleted)
- {
- Scalar scalar;
- if (expr_result_valobj_sp)
- expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true);
- if (expr_result_valobj_sp->ResolveValue (scalar))
- {
- command.erase (start_backtick, end_backtick - start_backtick + 1);
- StreamString value_strm;
- const bool show_type = false;
- scalar.GetValue (&value_strm, show_type);
- size_t value_string_size = value_strm.GetSize();
- if (value_string_size)
- {
- command.insert (start_backtick, value_strm.GetData(), value_string_size);
- pos = start_backtick + value_string_size;
- continue;
- }
- else
- {
- error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
- }
- }
- else
- {
- error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
- }
- }
- else
- {
- if (expr_result_valobj_sp)
- error = expr_result_valobj_sp->GetError();
- if (error.Success())
- {
-
- switch (expr_result)
- {
- case eExpressionSetupError:
- error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionParseError:
- error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionResultUnavailable:
- error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionCompleted:
- break;
- case eExpressionDiscarded:
- error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionInterrupted:
- error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionHitBreakpoint:
- error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionTimedOut:
- error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
- break;
- case eExpressionStoppedForDebug:
- error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
- break;
- }
- }
- }
- }
- }
- if (error.Fail())
- break;
- }
- }
- return error;
-}
-
-
-bool
-CommandInterpreter::HandleCommand (const char *command_line,
- LazyBool lazy_add_to_history,
- CommandReturnObject &result,
- ExecutionContext *override_context,
- bool repeat_on_empty_command,
- bool no_context_switching)
-
-{
-
- std::string command_string (command_line);
- std::string original_command_string (command_line);
-
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
- Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
-
- // Make a scoped cleanup object that will clear the crash description string
- // on exit of this function.
- lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);
-
- if (log)
- log->Printf ("Processing command: %s", command_line);
-
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, "Handling command: %s.", command_line);
-
- if (!no_context_switching)
- UpdateExecutionContext (override_context);
-
- bool add_to_history;
- if (lazy_add_to_history == eLazyBoolCalculate)
- add_to_history = (m_command_source_depth == 0);
- else
- add_to_history = (lazy_add_to_history == eLazyBoolYes);
-
- bool empty_command = false;
- bool comment_command = false;
- if (command_string.empty())
- empty_command = true;
- else
- {
- const char *k_space_characters = "\t\n\v\f\r ";
-
- size_t non_space = command_string.find_first_not_of (k_space_characters);
- // Check for empty line or comment line (lines whose first
- // non-space character is the comment character for this interpreter)
- if (non_space == std::string::npos)
- empty_command = true;
- else if (command_string[non_space] == m_comment_char)
- comment_command = true;
- else if (command_string[non_space] == CommandHistory::g_repeat_char)
- {
- const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
- if (history_string == nullptr)
- {
- result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- add_to_history = false;
- command_string = history_string;
- original_command_string = history_string;
- }
- }
-
- if (empty_command)
- {
- if (repeat_on_empty_command)
- {
- if (m_command_history.IsEmpty())
- {
- result.AppendError ("empty command");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- else
- {
- command_line = m_repeat_command.c_str();
- command_string = command_line;
- original_command_string = command_line;
- if (m_repeat_command.empty())
- {
- result.AppendErrorWithFormat("No auto repeat.\n");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- }
- add_to_history = false;
- }
- else
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return true;
- }
- }
- else if (comment_command)
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return true;
- }
-
-
- Error error (PreprocessCommand (command_string));
-
- if (error.Fail())
- {
- result.AppendError (error.AsCString());
+ revised_command_line.Printf(" %s%s", next_word.c_str(),
+ suffix.c_str());
+ done = true;
+ }
+ }
+
+ if (cmd_obj == nullptr) {
+ const size_t num_matches = matches.GetSize();
+ if (matches.GetSize() > 1) {
+ StreamString error_msg;
+ error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
+ next_word.c_str());
+
+ for (uint32_t i = 0; i < num_matches; ++i) {
+ error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
+ }
+ result.AppendRawError(error_msg.GetString().c_str());
+ } else {
+ // We didn't have only one match, otherwise we wouldn't get here.
+ assert(num_matches == 0);
+ result.AppendErrorWithFormat("'%s' is not a valid command.\n",
+ next_word.c_str());
+ }
+ result.SetStatus(eReturnStatusFailed);
+ return nullptr;
+ }
+
+ if (cmd_obj->IsMultiwordObject()) {
+ if (!suffix.empty()) {
+ result.AppendErrorWithFormat(
+ "command '%s' did not recognize '%s%s%s' as valid (subcommand "
+ "might be invalid).\n",
+ cmd_obj->GetCommandName(),
+ next_word.empty() ? "" : next_word.c_str(),
+ next_word.empty() ? " -- " : " ", suffix.c_str());
result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- // Phase 1.
-
- // Before we do ANY kind of argument processing, we need to figure out what
- // the real/final command object is for the specified command. This gets
- // complicated by the fact that the user could have specified an alias, and,
- // in translating the alias, there may also be command options and/or even
- // data (including raw text strings) that need to be found and inserted into
- // the command line as part of the translation. So this first step is plain
- // look-up and replacement, resulting in:
- // 1. the command object whose Execute method will actually be called
- // 2. a revised command string, with all substitutions and replacements
- // taken care of
- // From 1 above, we can determine whether the Execute function wants raw
- // input or not.
-
- CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
-
- // Although the user may have abbreviated the command, the command_string now
- // has the command expanded to the full name. For example, if the input
- // was "br s -n main", command_string is now "breakpoint set -n main".
-
- if (log)
- {
- log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
- log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str());
- const bool wants_raw_input = (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false;
- log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
- }
-
- // Phase 2.
- // Take care of things like setting up the history command & calling the appropriate Execute method on the
- // CommandObject, with the appropriate arguments.
-
- if (cmd_obj != nullptr)
- {
- if (add_to_history)
- {
- Args command_args (command_string);
- const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
- if (repeat_command != nullptr)
- m_repeat_command.assign(repeat_command);
- else
- m_repeat_command.assign(original_command_string.c_str());
-
- m_command_history.AppendString (original_command_string);
- }
-
- std::string remainder;
- const std::size_t actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
- if (actual_cmd_name_len < command_string.length())
- remainder = command_string.substr (actual_cmd_name_len);
-
- // Remove any initial spaces
- size_t pos = remainder.find_first_not_of (k_white_space);
- if (pos != 0 && pos != std::string::npos)
- remainder.erase(0, pos);
-
- if (log)
- log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
-
- cmd_obj->Execute (remainder.c_str(), result);
- }
- else
- {
- // We didn't find the first command object, so complete the first argument.
- Args command_args (command_string);
- StringList matches;
- int num_matches;
- int cursor_index = 0;
- int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
- bool word_complete;
- num_matches = HandleCompletionMatches (command_args,
- cursor_index,
- cursor_char_position,
- 0,
- -1,
- word_complete,
- matches);
-
- if (num_matches > 0)
- {
- std::string error_msg;
- error_msg.assign ("ambiguous command '");
- error_msg.append(command_args.GetArgumentAtIndex(0));
- error_msg.append ("'.");
-
- error_msg.append (" Possible completions:");
- for (int i = 0; i < num_matches; i++)
- {
- error_msg.append ("\n\t");
- error_msg.append (matches.GetStringAtIndex (i));
- }
- error_msg.append ("\n");
- result.AppendRawError (error_msg.c_str());
- }
- else
- result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
-
- result.SetStatus (eReturnStatusFailed);
- }
-
- if (log)
- log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
-
- return result.Succeeded();
-}
-
-int
-CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- int num_command_matches = 0;
- bool look_for_subcommand = false;
-
- // For any of the command completions a unique match will be a complete word.
- word_complete = true;
-
- if (cursor_index == -1)
- {
- // We got nothing on the command line, so return the list of commands
- bool include_aliases = true;
- num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
- }
- else if (cursor_index == 0)
- {
- // The cursor is in the first argument, so just do a lookup in the dictionary.
- CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
- num_command_matches = matches.GetSize();
-
- if (num_command_matches == 1
- && cmd_obj && cmd_obj->IsMultiwordObject()
- && matches.GetStringAtIndex(0) != nullptr
- && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
- {
- if (parsed_line.GetArgumentCount() == 1)
- {
- word_complete = true;
- }
- else
- {
- look_for_subcommand = true;
- num_command_matches = 0;
- matches.DeleteStringAtIndex(0);
- parsed_line.AppendArgument ("");
- cursor_index++;
- cursor_char_position = 0;
- }
- }
- }
-
- if (cursor_index > 0 || look_for_subcommand)
- {
- // We are completing further on into a commands arguments, so find the command and tell it
- // to complete the command.
- // First see if there is a matching initial command:
- CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
- if (command_object == nullptr)
- {
- return 0;
- }
- else
- {
- parsed_line.Shift();
- cursor_index--;
- num_command_matches = command_object->HandleCompletion (parsed_line,
- cursor_index,
- cursor_char_position,
- match_start_point,
- max_return_elements,
- word_complete,
- matches);
- }
- }
-
- return num_command_matches;
-
-}
-
-int
-CommandInterpreter::HandleCompletion (const char *current_line,
- const char *cursor,
- const char *last_char,
- int match_start_point,
- int max_return_elements,
- StringList &matches)
-{
- // We parse the argument up to the cursor, so the last argument in parsed_line is
- // the one containing the cursor, and the cursor is after the last character.
-
- Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
- Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line));
-
- // Don't complete comments, and if the line we are completing is just the history repeat character,
- // substitute the appropriate history line.
- const char *first_arg = parsed_line.GetArgumentAtIndex(0);
- if (first_arg)
- {
- if (first_arg[0] == m_comment_char)
- return 0;
- else if (first_arg[0] == CommandHistory::g_repeat_char)
- {
- const char *history_string = m_command_history.FindString (first_arg);
- if (history_string != nullptr)
- {
- matches.Clear();
- matches.InsertStringAtIndex(0, history_string);
- return -2;
- }
- else
- return 0;
-
- }
- }
-
-
- int num_args = partial_parsed_line.GetArgumentCount();
- int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
- int cursor_char_position;
-
- if (cursor_index == -1)
- cursor_char_position = 0;
- else
- cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
-
- if (cursor > current_line && cursor[-1] == ' ')
- {
- // We are just after a space. If we are in an argument, then we will continue
- // parsing, but if we are between arguments, then we have to complete whatever the next
- // element would be.
- // We can distinguish the two cases because if we are in an argument (e.g. because the space is
- // protected by a quote) then the space will also be in the parsed argument...
-
- const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
- if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
- {
- parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
- cursor_index++;
- cursor_char_position = 0;
- }
- }
-
- int num_command_matches;
-
- matches.Clear();
-
- // Only max_return_elements == -1 is supported at present:
- assert (max_return_elements == -1);
- bool word_complete;
- num_command_matches = HandleCompletionMatches (parsed_line,
- cursor_index,
- cursor_char_position,
- match_start_point,
- max_return_elements,
- word_complete,
- matches);
-
- if (num_command_matches <= 0)
- return num_command_matches;
-
- if (num_args == 0)
- {
- // If we got an empty string, insert nothing.
- matches.InsertStringAtIndex(0, "");
- }
- else
- {
- // Now figure out if there is a common substring, and if so put that in element 0, otherwise
- // put an empty string in element 0.
- std::string command_partial_str;
- if (cursor_index >= 0)
- command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
- parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
-
- std::string common_prefix;
- matches.LongestCommonPrefix (common_prefix);
- const size_t partial_name_len = command_partial_str.size();
- common_prefix.erase (0, partial_name_len);
-
- // If we matched a unique single command, add a space...
- // Only do this if the completer told us this was a complete word, however...
- if (num_command_matches == 1 && word_complete)
- {
- char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
- common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
- if (quote_char != '\0')
- common_prefix.push_back(quote_char);
- common_prefix.push_back(' ');
- }
- matches.InsertStringAtIndex(0, common_prefix.c_str());
- }
- return num_command_matches;
-}
-
-
-CommandInterpreter::~CommandInterpreter ()
-{
-}
-
-void
-CommandInterpreter::UpdatePrompt (const char *new_prompt)
-{
- EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
- BroadcastEvent (prompt_change_event_sp);
- if (m_command_io_handler_sp)
- m_command_io_handler_sp->SetPrompt(new_prompt);
-}
-
-
-bool
-CommandInterpreter::Confirm (const char *message, bool default_answer)
-{
- // Check AutoConfirm first:
- if (m_debugger.GetAutoConfirm())
- return default_answer;
-
- IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
- message,
- default_answer);
- IOHandlerSP io_handler_sp (confirm);
- m_debugger.RunIOHandler (io_handler_sp);
- return confirm->GetResponse();
-}
-
-CommandAlias*
-CommandInterpreter::GetAlias (const char *alias_name)
-{
- OptionArgVectorSP ret_val;
-
- std::string alias (alias_name);
-
- auto pos = m_alias_dict.find(alias);
- if (pos != m_alias_dict.end())
- return (CommandAlias*)pos->second.get();
-
- return nullptr;
-}
-
-bool
-CommandInterpreter::HasCommands ()
-{
- return (!m_command_dict.empty());
-}
-
-bool
-CommandInterpreter::HasAliases ()
-{
- return (!m_alias_dict.empty());
-}
-
-bool
-CommandInterpreter::HasUserCommands ()
-{
- return (!m_user_dict.empty());
-}
-
-bool
-CommandInterpreter::HasAliasOptions ()
-{
- return HasAliases();
-}
-
-void
-CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
- const char *alias_name,
- Args &cmd_args,
- std::string &raw_input_string,
- CommandReturnObject &result)
-{
- OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments();
-
- bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
-
- // Make sure that the alias name is the 0th element in cmd_args
- std::string alias_name_str = alias_name;
- if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
- cmd_args.Unshift (alias_name);
-
- Args new_args (alias_cmd_obj->GetCommandName());
- if (new_args.GetArgumentCount() == 2)
- new_args.Shift();
-
- if (option_arg_vector_sp.get())
- {
- if (wants_raw_input)
- {
- // We have a command that both has command options and takes raw input. Make *sure* it has a
- // " -- " in the right place in the raw_input_string.
- size_t pos = raw_input_string.find(" -- ");
- if (pos == std::string::npos)
- {
- // None found; assume it goes at the beginning of the raw input string
- raw_input_string.insert (0, " -- ");
- }
- }
-
- OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
- const size_t old_size = cmd_args.GetArgumentCount();
- std::vector<bool> used (old_size + 1, false);
-
- used[0] = true;
-
- for (size_t i = 0; i < option_arg_vector->size(); ++i)
- {
- OptionArgPair option_pair = (*option_arg_vector)[i];
- OptionArgValue value_pair = option_pair.second;
- int value_type = value_pair.first;
- std::string option = option_pair.first;
- std::string value = value_pair.second;
- if (option.compare ("<argument>") == 0)
- {
- if (!wants_raw_input
- || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
- new_args.AppendArgument (value.c_str());
- }
- else
- {
- if (value_type != OptionParser::eOptionalArgument)
- new_args.AppendArgument (option.c_str());
- if (value.compare ("<no-argument>") != 0)
- {
- int index = GetOptionArgumentPosition (value.c_str());
- if (index == 0)
- {
- // value was NOT a positional argument; must be a real value
- if (value_type != OptionParser::eOptionalArgument)
- new_args.AppendArgument (value.c_str());
- else
- {
- char buffer[255];
- ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
- new_args.AppendArgument (buffer);
- }
-
- }
- else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
- {
- result.AppendErrorWithFormat
- ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
- index);
- result.SetStatus (eReturnStatusFailed);
- return;
- }
- else
- {
- // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
- size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
- if (strpos != std::string::npos)
- {
- raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
- }
-
- if (value_type != OptionParser::eOptionalArgument)
- new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
- else
- {
- char buffer[255];
- ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
- cmd_args.GetArgumentAtIndex (index));
- new_args.AppendArgument (buffer);
- }
- used[index] = true;
- }
- }
- }
- }
-
- for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
- {
- if (!used[j] && !wants_raw_input)
- new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
- }
-
- cmd_args.Clear();
- cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector());
- }
- else
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- // This alias was not created with any options; nothing further needs to be done, unless it is a command that
- // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
- // input string.
- if (wants_raw_input)
- {
- cmd_args.Clear();
- cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector());
- }
- return;
- }
-
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return;
-}
-
-
-int
-CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
-{
- int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
- // of zero.
-
- const char *cptr = in_string;
-
- // Does it start with '%'
- if (cptr[0] == '%')
- {
- ++cptr;
-
- // Is the rest of it entirely digits?
- if (isdigit (cptr[0]))
- {
- const char *start = cptr;
- while (isdigit (cptr[0]))
- ++cptr;
-
- // We've gotten to the end of the digits; are we at the end of the string?
- if (cptr[0] == '\0')
- position = atoi (start);
- }
- }
-
- return position;
-}
-
-void
-CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
-{
- FileSpec init_file;
- if (in_cwd)
- {
- ExecutionContext exe_ctx(GetExecutionContext());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- // In the current working directory we don't load any program specific
- // .lldbinit files, we only look for a ".lldbinit" file.
- if (m_skip_lldbinit_files)
- return;
-
- LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile ();
- if (should_load == eLoadCWDlldbinitWarn)
- {
- FileSpec dot_lldb (".lldbinit", true);
- llvm::SmallString<64> home_dir_path;
- llvm::sys::path::home_directory (home_dir_path);
- FileSpec homedir_dot_lldb (home_dir_path.c_str(), false);
- homedir_dot_lldb.AppendPathComponent (".lldbinit");
- homedir_dot_lldb.ResolvePath ();
- if (dot_lldb.Exists ()
- && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory())
- {
- result.AppendErrorWithFormat (
- "There is a .lldbinit file in the current directory which is not being read.\n"
- "To silence this warning without sourcing in the local .lldbinit,\n"
- "add the following to the lldbinit file in your home directory:\n"
- " settings set target.load-cwd-lldbinit false\n"
- "To allow lldb to source .lldbinit files in the current working directory,\n"
- "set the value of this variable to true. Only do so if you understand and\n"
- "accept the security risk.");
- result.SetStatus (eReturnStatusFailed);
- return;
- }
- }
- else if (should_load == eLoadCWDlldbinitTrue)
- {
- init_file.SetFile ("./.lldbinit", true);
- }
- }
- }
- else
- {
- // If we aren't looking in the current working directory we are looking
- // in the home directory. We will first see if there is an application
- // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
- // "-" and the name of the program. If this file doesn't exist, we fall
- // back to just the "~/.lldbinit" file. We also obey any requests to not
- // load the init files.
- llvm::SmallString<64> home_dir_path;
- llvm::sys::path::home_directory(home_dir_path);
- FileSpec profilePath(home_dir_path.c_str(), false);
- profilePath.AppendPathComponent(".lldbinit");
- std::string init_file_path = profilePath.GetPath();
-
- if (m_skip_app_init_files == false)
- {
- FileSpec program_file_spec(HostInfo::GetProgramFileSpec());
- const char *program_name = program_file_spec.GetFilename().AsCString();
-
- if (program_name)
- {
- char program_init_file_name[PATH_MAX];
- ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name);
- init_file.SetFile (program_init_file_name, true);
- if (!init_file.Exists())
- init_file.Clear();
- }
- }
-
- if (!init_file && !m_skip_lldbinit_files)
- init_file.SetFile (init_file_path.c_str(), false);
- }
-
- // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
- // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
-
- if (init_file.Exists())
- {
- const bool saved_batch = SetBatchCommandMode (true);
- CommandInterpreterRunOptions options;
- options.SetSilent (true);
- options.SetStopOnError (false);
- options.SetStopOnContinue (true);
-
- HandleCommandsFromFile (init_file,
- nullptr, // Execution context
- options,
- result);
- SetBatchCommandMode (saved_batch);
- }
- else
- {
- // nothing to be done if the file doesn't exist
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- }
-}
-
-const char *
-CommandInterpreter::GetCommandPrefix()
-{
- const char * prefix = GetDebugger().GetIOHandlerCommandPrefix();
- return prefix == NULL ? "" : prefix;
-}
-
-PlatformSP
-CommandInterpreter::GetPlatform (bool prefer_target_platform)
-{
- PlatformSP platform_sp;
- if (prefer_target_platform)
- {
- ExecutionContext exe_ctx(GetExecutionContext());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- platform_sp = target->GetPlatform();
- }
-
- if (!platform_sp)
- platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
- return platform_sp;
-}
-
-void
-CommandInterpreter::HandleCommands (const StringList &commands,
- ExecutionContext *override_context,
- CommandInterpreterRunOptions &options,
- CommandReturnObject &result)
-{
- size_t num_lines = commands.GetSize();
-
- // If we are going to continue past a "continue" then we need to run the commands synchronously.
- // Make sure you reset this value anywhere you return from the function.
-
- bool old_async_execution = m_debugger.GetAsyncExecution();
-
- // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
- // cause series of commands that change the context, then do an operation that relies on that context to fail.
-
- if (override_context != nullptr)
- UpdateExecutionContext (override_context);
-
- if (!options.GetStopOnContinue())
- {
- m_debugger.SetAsyncExecution (false);
- }
-
- for (size_t idx = 0; idx < num_lines; idx++)
- {
- const char *cmd = commands.GetStringAtIndex(idx);
- if (cmd[0] == '\0')
- continue;
-
- if (options.GetEchoCommands())
- {
- result.AppendMessageWithFormat ("%s %s\n",
- m_debugger.GetPrompt(),
- cmd);
- }
-
- CommandReturnObject tmp_result;
- // If override_context is not NULL, pass no_context_switching = true for
- // HandleCommand() since we updated our context already.
-
- // We might call into a regex or alias command, in which case the add_to_history will get lost. This
- // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
- if (!options.GetAddToHistory())
- m_command_source_depth++;
- bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result,
- nullptr, /* override_context */
- true, /* repeat_on_empty_command */
- override_context != nullptr /* no_context_switching */);
- if (!options.GetAddToHistory())
- m_command_source_depth--;
-
- if (options.GetPrintResults())
- {
- if (tmp_result.Succeeded())
- result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
- }
-
- if (!success || !tmp_result.Succeeded())
- {
- const char *error_msg = tmp_result.GetErrorData();
- if (error_msg == nullptr || error_msg[0] == '\0')
- error_msg = "<unknown error>.\n";
- if (options.GetStopOnError())
- {
- result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s",
- (uint64_t)idx, cmd, error_msg);
- result.SetStatus (eReturnStatusFailed);
- m_debugger.SetAsyncExecution (old_async_execution);
- return;
- }
- else if (options.GetPrintResults())
- {
- result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
- (uint64_t)idx + 1,
- cmd,
- error_msg);
- }
- }
-
- if (result.GetImmediateOutputStream())
- result.GetImmediateOutputStream()->Flush();
-
- if (result.GetImmediateErrorStream())
- result.GetImmediateErrorStream()->Flush();
-
- // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
- // could be running (for instance in Breakpoint Commands.
- // So we check the return value to see if it is has running in it.
- if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
- || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
- {
- if (options.GetStopOnContinue())
- {
- // If we caused the target to proceed, and we're going to stop in that case, set the
- // status in our real result before returning. This is an error if the continue was not the
- // last command in the set of commands to be run.
- if (idx != num_lines - 1)
- result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",
- (uint64_t)idx + 1, cmd);
- else
- result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);
-
- result.SetStatus(tmp_result.GetStatus());
- m_debugger.SetAsyncExecution (old_async_execution);
-
- return;
- }
- }
-
- // Also check for "stop on crash here:
- bool should_stop = false;
- if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash())
- {
- TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
- if (target_sp)
- {
- ProcessSP process_sp (target_sp->GetProcessSP());
- if (process_sp)
- {
- for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
- {
- StopReason reason = thread_sp->GetStopReason();
- if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation)
- {
- should_stop = true;
- break;
- }
- }
- }
- }
- if (should_stop)
- {
- if (idx != num_lines - 1)
- result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n",
- (uint64_t)idx + 1, cmd);
- else
- result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd);
-
- result.SetStatus(tmp_result.GetStatus());
- m_debugger.SetAsyncExecution (old_async_execution);
-
- return;
- }
- }
-
- }
-
- result.SetStatus (eReturnStatusSuccessFinishResult);
- m_debugger.SetAsyncExecution (old_async_execution);
-
- return;
-}
-
-// Make flags that we can pass into the IOHandler so our delegates can do the right thing
-enum {
- eHandleCommandFlagStopOnContinue = (1u << 0),
- eHandleCommandFlagStopOnError = (1u << 1),
- eHandleCommandFlagEchoCommand = (1u << 2),
- eHandleCommandFlagPrintResult = (1u << 3),
- eHandleCommandFlagStopOnCrash = (1u << 4)
-};
-
-void
-CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
- ExecutionContext *context,
- CommandInterpreterRunOptions &options,
- CommandReturnObject &result)
-{
- if (cmd_file.Exists())
- {
- StreamFileSP input_file_sp (new StreamFile());
-
- std::string cmd_file_path = cmd_file.GetPath();
- Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
-
- if (error.Success())
- {
- Debugger &debugger = GetDebugger();
-
- uint32_t flags = 0;
-
- if (options.m_stop_on_continue == eLazyBoolCalculate)
- {
- if (m_command_source_flags.empty())
- {
- // Stop on continue by default
- flags |= eHandleCommandFlagStopOnContinue;
- }
- else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
- {
- flags |= eHandleCommandFlagStopOnContinue;
- }
- }
- else if (options.m_stop_on_continue == eLazyBoolYes)
- {
- flags |= eHandleCommandFlagStopOnContinue;
- }
-
- if (options.m_stop_on_error == eLazyBoolCalculate)
- {
- if (m_command_source_flags.empty())
- {
- if (GetStopCmdSourceOnError())
- flags |= eHandleCommandFlagStopOnError;
- }
- else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
- {
- flags |= eHandleCommandFlagStopOnError;
- }
- }
- else if (options.m_stop_on_error == eLazyBoolYes)
- {
- flags |= eHandleCommandFlagStopOnError;
- }
-
- if (options.GetStopOnCrash())
- {
- if (m_command_source_flags.empty())
- {
- // Echo command by default
- flags |= eHandleCommandFlagStopOnCrash;
- }
- else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash)
- {
- flags |= eHandleCommandFlagStopOnCrash;
- }
- }
-
- if (options.m_echo_commands == eLazyBoolCalculate)
- {
- if (m_command_source_flags.empty())
- {
- // Echo command by default
- flags |= eHandleCommandFlagEchoCommand;
- }
- else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
- {
- flags |= eHandleCommandFlagEchoCommand;
- }
- }
- else if (options.m_echo_commands == eLazyBoolYes)
- {
- flags |= eHandleCommandFlagEchoCommand;
- }
-
- if (options.m_print_results == eLazyBoolCalculate)
- {
- if (m_command_source_flags.empty())
- {
- // Print output by default
- flags |= eHandleCommandFlagPrintResult;
- }
- else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
- {
- flags |= eHandleCommandFlagPrintResult;
- }
- }
- else if (options.m_print_results == eLazyBoolYes)
- {
- flags |= eHandleCommandFlagPrintResult;
- }
-
- if (flags & eHandleCommandFlagPrintResult)
- {
- debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
- }
-
- // Used for inheriting the right settings when "command source" might have
- // nested "command source" commands
- lldb::StreamFileSP empty_stream_sp;
- m_command_source_flags.push_back(flags);
- IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- IOHandler::Type::CommandInterpreter,
- input_file_sp,
- empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
- empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
- flags,
- nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
- debugger.GetPrompt(),
- NULL,
- false, // Not multi-line
- debugger.GetUseColor(),
- 0,
- *this));
- const bool old_async_execution = debugger.GetAsyncExecution();
-
- // Set synchronous execution if we are not stopping on continue
- if ((flags & eHandleCommandFlagStopOnContinue) == 0)
- debugger.SetAsyncExecution (false);
-
- m_command_source_depth++;
-
- debugger.RunIOHandler(io_handler_sp);
- if (!m_command_source_flags.empty())
- m_command_source_flags.pop_back();
- m_command_source_depth--;
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- debugger.SetAsyncExecution (old_async_execution);
- }
- else
- {
- result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
-
-
- }
- else
- {
- result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
- cmd_file.GetFilename().AsCString("<Unknown>"));
- result.SetStatus (eReturnStatusFailed);
- return;
- }
-}
-
-ScriptInterpreter *
-CommandInterpreter::GetScriptInterpreter(bool can_create)
-{
- if (m_script_interpreter_sp)
- return m_script_interpreter_sp.get();
-
- if (!can_create)
return nullptr;
-
- lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
- m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this);
- return m_script_interpreter_sp.get();
-}
-
-bool
-CommandInterpreter::GetSynchronous ()
-{
- return m_synchronous_execution;
-}
-
-void
-CommandInterpreter::SetSynchronous (bool value)
-{
- m_synchronous_execution = value;
-}
-
-void
-CommandInterpreter::OutputFormattedHelpText (Stream &strm,
- const char *prefix,
- const char *help_text)
-{
- const uint32_t max_columns = m_debugger.GetTerminalWidth();
- if (prefix == NULL)
- prefix = "";
-
- size_t prefix_width = strlen(prefix);
- size_t line_width_max = max_columns - prefix_width;
- const char *help_text_end = help_text + strlen(help_text);
- const char *line_start = help_text;
- if (line_width_max < 16)
- line_width_max = help_text_end - help_text + prefix_width;
-
- strm.IndentMore (prefix_width);
- while (line_start < help_text_end)
- {
- // Break each line at the first newline or last space/tab before
- // the maximum number of characters that fit on a line. Lines with no
- // natural break are left unbroken to wrap.
- const char *line_end = help_text_end;
- const char *line_scan = line_start;
- const char *line_scan_end = help_text_end;
- while (line_scan < line_scan_end)
- {
- char next = *line_scan;
- if (next == '\t' || next == ' ')
- {
- line_end = line_scan;
- line_scan_end = line_start + line_width_max;
- }
- else if (next == '\n' || next == '\0')
- {
- line_end = line_scan;
- break;
- }
- ++line_scan;
- }
-
- // Prefix the first line, indent subsequent lines to line up
- if (line_start == help_text)
- strm.Write (prefix, prefix_width);
- else
- strm.Indent();
- strm.Write (line_start, line_end - line_start);
- strm.EOL();
-
- // When a line breaks at whitespace consume it before continuing
- line_start = line_end;
- char next = *line_start;
- if (next == '\n')
- ++line_start;
- else while (next == ' ' || next == '\t')
- next = *(++line_start);
- }
- strm.IndentLess (prefix_width);
-}
-
-void
-CommandInterpreter::OutputFormattedHelpText (Stream &strm,
- const char *word_text,
- const char *separator,
- const char *help_text,
- size_t max_word_len)
-{
- StreamString prefix_stream;
- prefix_stream.Printf (" %-*s %s ", (int)max_word_len, word_text, separator);
- OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text);
-}
-
-void
-CommandInterpreter::OutputHelpText (Stream &strm,
- const char *word_text,
- const char *separator,
- const char *help_text,
- uint32_t max_word_len)
-{
- int indent_size = max_word_len + strlen (separator) + 2;
-
- strm.IndentMore (indent_size);
-
- StreamString text_strm;
- text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
-
- const uint32_t max_columns = m_debugger.GetTerminalWidth();
-
- size_t len = text_strm.GetSize();
- const char *text = text_strm.GetData();
-
- uint32_t chars_left = max_columns;
-
- for (uint32_t i = 0; i < len; i++)
- {
- if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
- {
- chars_left = max_columns - indent_size;
- strm.EOL();
- strm.Indent();
- }
- else
- {
- strm.PutChar(text[i]);
- chars_left--;
- }
-
- }
-
- strm.EOL();
- strm.IndentLess(indent_size);
-}
-
-void
-CommandInterpreter::FindCommandsForApropos (const char *search_word,
- StringList &commands_found,
- StringList &commands_help,
- CommandObject::CommandMap &command_map)
-{
- CommandObject::CommandMap::const_iterator pos;
-
- for (pos = command_map.begin(); pos != command_map.end(); ++pos)
- {
- const char *command_name = pos->first.c_str();
- CommandObject *cmd_obj = pos->second.get();
-
- const bool search_short_help = true;
- const bool search_long_help = false;
- const bool search_syntax = false;
- const bool search_options = false;
- if (strcasestr(command_name, search_word) ||
- cmd_obj->HelpTextContainsWord (search_word,
- search_short_help,
- search_long_help,
- search_syntax,
- search_options))
- {
- commands_found.AppendString (cmd_obj->GetCommandName());
- commands_help.AppendString (cmd_obj->GetHelp());
- }
-
- if (cmd_obj->IsMultiwordObject())
- {
- CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand();
- FindCommandsForApropos(search_word,
- commands_found,
- commands_help,
- cmd_multiword->GetSubcommandDictionary());
- }
- }
-}
-
-
-void
-CommandInterpreter::FindCommandsForApropos (const char *search_word,
- StringList &commands_found,
- StringList &commands_help,
- bool search_builtin_commands,
- bool search_user_commands,
- bool search_alias_commands)
-{
- CommandObject::CommandMap::const_iterator pos;
-
- if (search_builtin_commands)
- FindCommandsForApropos(search_word, commands_found, commands_help, m_command_dict);
-
- if (search_user_commands)
- FindCommandsForApropos(search_word, commands_found, commands_help, m_user_dict);
-
- if (search_alias_commands)
- FindCommandsForApropos(search_word, commands_found, commands_help, m_alias_dict);
-}
-
-void
-CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
-{
- if (override_context != nullptr)
- {
- m_exe_ctx_ref = *override_context;
- }
- else
- {
- const bool adopt_selected = true;
- m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
- }
-}
-
-
-size_t
-CommandInterpreter::GetProcessOutput ()
-{
- // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
- char stdio_buffer[1024];
- size_t len;
- size_t total_bytes = 0;
- Error error;
- TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
- if (target_sp)
- {
- ProcessSP process_sp (target_sp->GetProcessSP());
- if (process_sp)
- {
- while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
- {
- size_t bytes_written = len;
- m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
- total_bytes += len;
- }
- while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
- {
- size_t bytes_written = len;
- m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
- total_bytes += len;
- }
- }
- }
- return total_bytes;
-}
-
-void
-CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
-{
- const bool is_interactive = io_handler.GetIsInteractive();
- if (is_interactive == false)
- {
- // When we are not interactive, don't execute blank lines. This will happen
- // sourcing a commands file. We don't want blank lines to repeat the previous
- // command and cause any errors to occur (like redefining an alias, get an error
- // and stop parsing the commands file).
- if (line.empty())
- return;
-
- // When using a non-interactive file handle (like when sourcing commands from a file)
- // we need to echo the command out so we don't just see the command output and no
- // command...
- if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
- io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
- }
-
- lldb_private::CommandReturnObject result;
- HandleCommand(line.c_str(), eLazyBoolCalculate, result);
-
- // Now emit the command output text from the command we just executed
- if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
- {
- // Display any STDOUT/STDERR _prior_ to emitting the command result text
- GetProcessOutput ();
-
- if (!result.GetImmediateOutputStream())
- {
- const char *output = result.GetOutputData();
- if (output && output[0])
- io_handler.GetOutputStreamFile()->PutCString(output);
- }
-
- // Now emit the command error text from the command we just executed
- if (!result.GetImmediateErrorStream())
- {
- const char *error = result.GetErrorData();
- if (error && error[0])
- io_handler.GetErrorStreamFile()->PutCString(error);
- }
- }
-
- switch (result.GetStatus())
- {
- case eReturnStatusInvalid:
- case eReturnStatusSuccessFinishNoResult:
- case eReturnStatusSuccessFinishResult:
- case eReturnStatusStarted:
- break;
-
- case eReturnStatusSuccessContinuingNoResult:
- case eReturnStatusSuccessContinuingResult:
- if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
- io_handler.SetIsDone(true);
- break;
-
- case eReturnStatusFailed:
- m_num_errors++;
- if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
- io_handler.SetIsDone(true);
- break;
-
- case eReturnStatusQuit:
- m_quit_requested = true;
- io_handler.SetIsDone(true);
- break;
- }
-
- // Finally, if we're going to stop on crash, check that here:
- if (!m_quit_requested
- && result.GetDidChangeProcessState()
- && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash))
- {
- bool should_stop = false;
- TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
- if (target_sp)
- {
- ProcessSP process_sp (target_sp->GetProcessSP());
- if (process_sp)
- {
- for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
- {
- StopReason reason = thread_sp->GetStopReason();
- if ((reason == eStopReasonSignal
- || reason == eStopReasonException
- || reason == eStopReasonInstrumentation)
- && !result.GetAbnormalStopWasExpected())
- {
- should_stop = true;
- break;
- }
- }
- }
- }
- if (should_stop)
- {
- io_handler.SetIsDone(true);
- m_stopped_for_crash = true;
- }
- }
-}
-
-bool
-CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler)
-{
- ExecutionContext exe_ctx (GetExecutionContext());
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process)
- {
- StateType state = process->GetState();
- if (StateIsRunningState(state))
- {
- process->Halt();
- return true; // Don't do any updating when we are running
- }
- }
-
- ScriptInterpreter *script_interpreter = GetScriptInterpreter (false);
- if (script_interpreter)
- {
- if (script_interpreter->Interrupt())
- return true;
- }
- return false;
-}
-
-void
-CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
- IOHandlerDelegate &delegate,
- bool asynchronously,
- void *baton)
-{
- Debugger &debugger = GetDebugger();
- IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- IOHandler::Type::CommandList,
- "lldb", // Name of input reader for history
- prompt, // Prompt
- NULL, // Continuation prompt
- true, // Get multiple lines
- debugger.GetUseColor(),
- 0, // Don't show line numbers
- delegate)); // IOHandlerDelegate
-
- if (io_handler_sp)
- {
- io_handler_sp->SetUserData (baton);
- if (asynchronously)
- debugger.PushIOHandler(io_handler_sp);
- else
- debugger.RunIOHandler(io_handler_sp);
- }
-
-}
-
-
-void
-CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
- IOHandlerDelegate &delegate,
- bool asynchronously,
- void *baton)
-{
- Debugger &debugger = GetDebugger();
- IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- IOHandler::Type::PythonCode,
- "lldb-python", // Name of input reader for history
- prompt, // Prompt
- NULL, // Continuation prompt
- true, // Get multiple lines
- debugger.GetUseColor(),
- 0, // Don't show line numbers
- delegate)); // IOHandlerDelegate
-
- if (io_handler_sp)
- {
- io_handler_sp->SetUserData (baton);
- if (asynchronously)
- debugger.PushIOHandler(io_handler_sp);
- else
- debugger.RunIOHandler(io_handler_sp);
- }
-
-}
-
-bool
-CommandInterpreter::IsActive ()
-{
- return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
-}
-
-lldb::IOHandlerSP
-CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options)
-{
- // Always re-create the IOHandlerEditline in case the input
- // changed. The old instance might have had a non-interactive
- // input and now it does or vice versa.
- if (force_create || !m_command_io_handler_sp)
- {
- // Always re-create the IOHandlerEditline in case the input
- // changed. The old instance might have had a non-interactive
- // input and now it does or vice versa.
- uint32_t flags = 0;
-
- if (options)
- {
- if (options->m_stop_on_continue == eLazyBoolYes)
- flags |= eHandleCommandFlagStopOnContinue;
- if (options->m_stop_on_error == eLazyBoolYes)
- flags |= eHandleCommandFlagStopOnError;
- if (options->m_stop_on_crash == eLazyBoolYes)
- flags |= eHandleCommandFlagStopOnCrash;
- if (options->m_echo_commands != eLazyBoolNo)
- flags |= eHandleCommandFlagEchoCommand;
- if (options->m_print_results != eLazyBoolNo)
- flags |= eHandleCommandFlagPrintResult;
- }
- else
- {
- flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult;
- }
-
- m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
- IOHandler::Type::CommandInterpreter,
- m_debugger.GetInputFile(),
- m_debugger.GetOutputFile(),
- m_debugger.GetErrorFile(),
- flags,
- "lldb",
- m_debugger.GetPrompt(),
- NULL, // Continuation prompt
- false, // Don't enable multiple line input, just single line commands
- m_debugger.GetUseColor(),
- 0, // Don't show line numbers
- *this));
- }
- return m_command_io_handler_sp;
-}
-
-void
-CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
- bool spawn_thread,
- CommandInterpreterRunOptions &options)
-{
- // Always re-create the command interpreter when we run it in case
- // any file handles have changed.
- bool force_create = true;
- m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
- m_stopped_for_crash = false;
-
- if (auto_handle_events)
- m_debugger.StartEventHandlerThread();
-
- if (spawn_thread)
- {
- m_debugger.StartIOHandlerThread();
- }
- else
- {
- m_debugger.ExecuteIOHandlers();
-
- if (auto_handle_events)
- m_debugger.StopEventHandlerThread();
- }
-
-}
-
-CommandObject *
-CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnObject &result)
-{
- std::string scratch_command(command_line); // working copy so we don't modify command_line unless we succeed
- CommandObject *cmd_obj = nullptr;
- StreamString revised_command_line;
- bool wants_raw_input = false;
- size_t actual_cmd_name_len = 0;
- std::string next_word;
- StringList matches;
- bool done = false;
- while (!done)
- {
- char quote_char = '\0';
- std::string suffix;
- ExtractCommand(scratch_command, next_word, suffix, quote_char);
- if (cmd_obj == nullptr)
- {
- std::string full_name;
- bool is_alias = GetAliasFullName(next_word.c_str(), full_name);
- cmd_obj = GetCommandObject(next_word.c_str(), &matches);
- bool is_real_command = (is_alias == false) || (cmd_obj != nullptr && cmd_obj->IsAlias() == false);
- if (!is_real_command)
- {
- matches.Clear();
- std::string alias_result;
- cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result);
- revised_command_line.Printf("%s", alias_result.c_str());
- if (cmd_obj)
- {
- wants_raw_input = cmd_obj->WantsRawCommandString();
- actual_cmd_name_len = strlen(cmd_obj->GetCommandName());
- }
- }
- else
- {
- if (!cmd_obj)
- cmd_obj = GetCommandObject(next_word.c_str(), &matches);
- if (cmd_obj)
- {
- actual_cmd_name_len += strlen(cmd_obj->GetCommandName());
- revised_command_line.Printf("%s", cmd_obj->GetCommandName());
- wants_raw_input = cmd_obj->WantsRawCommandString();
- }
- else
- {
- revised_command_line.Printf ("%s", next_word.c_str());
- }
- }
- }
- else
- {
- if (cmd_obj->IsMultiwordObject ())
- {
- CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject(next_word.c_str());
- if (sub_cmd_obj)
- {
- // The subcommand's name includes the parent command's name,
- // so restart rather than append to the revised_command_line.
- actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1;
- revised_command_line.Clear();
- revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName());
- cmd_obj = sub_cmd_obj;
- wants_raw_input = cmd_obj->WantsRawCommandString();
- }
- else
- {
- if (quote_char)
- revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
- else
- revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str());
- done = true;
- }
- }
- else
- {
- if (quote_char)
- revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
- else
- revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str());
- done = true;
- }
- }
-
- if (cmd_obj == nullptr)
- {
- const size_t num_matches = matches.GetSize();
- if (matches.GetSize() > 1) {
- StreamString error_msg;
- error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
-
- for (uint32_t i = 0; i < num_matches; ++i) {
- error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
- }
- result.AppendRawError(error_msg.GetString().c_str());
+ }
+ } else {
+ // If we found a normal command, we are done
+ done = true;
+ if (!suffix.empty()) {
+ switch (suffix[0]) {
+ case '/':
+ // GDB format suffixes
+ {
+ Options *command_options = cmd_obj->GetOptions();
+ if (command_options &&
+ command_options->SupportsLongOption("gdb-format")) {
+ std::string gdb_format_option("--gdb-format=");
+ gdb_format_option += (suffix.c_str() + 1);
+
+ bool inserted = false;
+ std::string &cmd = revised_command_line.GetString();
+ size_t arg_terminator_idx = FindArgumentTerminator(cmd);
+ if (arg_terminator_idx != std::string::npos) {
+ // Insert the gdb format option before the "--" that terminates
+ // options
+ gdb_format_option.append(1, ' ');
+ cmd.insert(arg_terminator_idx, gdb_format_option);
+ inserted = true;
+ }
+
+ if (!inserted)
+ revised_command_line.Printf(" %s", gdb_format_option.c_str());
+
+ if (wants_raw_input &&
+ FindArgumentTerminator(cmd) == std::string::npos)
+ revised_command_line.PutCString(" --");
} else {
- // We didn't have only one match, otherwise we wouldn't get here.
- assert(num_matches == 0);
- result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str());
- }
- result.SetStatus(eReturnStatusFailed);
- return nullptr;
- }
-
- if (cmd_obj->IsMultiwordObject())
- {
- if (!suffix.empty())
- {
- result.AppendErrorWithFormat("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
- cmd_obj->GetCommandName(),
- next_word.empty() ? "" : next_word.c_str(),
- next_word.empty() ? " -- " : " ",
- suffix.c_str());
- result.SetStatus(eReturnStatusFailed);
- return nullptr;
- }
- }
- else
- {
- // If we found a normal command, we are done
- done = true;
- if (!suffix.empty())
- {
- switch (suffix[0])
- {
- case '/':
- // GDB format suffixes
- {
- Options *command_options = cmd_obj->GetOptions();
- if (command_options && command_options->SupportsLongOption("gdb-format"))
- {
- std::string gdb_format_option("--gdb-format=");
- gdb_format_option += (suffix.c_str() + 1);
-
- bool inserted = false;
- std::string &cmd = revised_command_line.GetString();
- size_t arg_terminator_idx = FindArgumentTerminator(cmd);
- if (arg_terminator_idx != std::string::npos)
- {
- // Insert the gdb format option before the "--" that terminates options
- gdb_format_option.append(1,' ');
- cmd.insert(arg_terminator_idx, gdb_format_option);
- inserted = true;
- }
-
- if (!inserted)
- revised_command_line.Printf(" %s", gdb_format_option.c_str());
-
- if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
- revised_command_line.PutCString(" --");
- }
- else
- {
- result.AppendErrorWithFormat("the '%s' command doesn't support the --gdb-format option\n",
- cmd_obj->GetCommandName());
- result.SetStatus(eReturnStatusFailed);
- return nullptr;
- }
- }
- break;
-
- default:
- result.AppendErrorWithFormat("unknown command shorthand suffix: '%s'\n",
- suffix.c_str());
- result.SetStatus(eReturnStatusFailed);
- return nullptr;
- }
- }
- }
- if (scratch_command.empty())
- done = true;
- }
+ result.AppendErrorWithFormat(
+ "the '%s' command doesn't support the --gdb-format option\n",
+ cmd_obj->GetCommandName());
+ result.SetStatus(eReturnStatusFailed);
+ return nullptr;
+ }
+ }
+ break;
+
+ default:
+ result.AppendErrorWithFormat(
+ "unknown command shorthand suffix: '%s'\n", suffix.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return nullptr;
+ }
+ }
+ }
+ if (scratch_command.empty())
+ done = true;
+ }
- if (!scratch_command.empty())
- revised_command_line.Printf(" %s", scratch_command.c_str());
+ if (!scratch_command.empty())
+ revised_command_line.Printf(" %s", scratch_command.c_str());
- if (cmd_obj != NULL)
- command_line = revised_command_line.GetData();
+ if (cmd_obj != NULL)
+ command_line = revised_command_line.GetData();
- return cmd_obj;
+ return cmd_obj;
}
Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Tue Sep 6 15:57:50 2016
@@ -9,12 +9,12 @@
#include "lldb/Interpreter/CommandObject.h"
-#include <string>
-#include <sstream>
#include <map>
+#include <sstream>
+#include <string>
-#include <stdlib.h>
#include <ctype.h>
+#include <stdlib.h>
#include "lldb/Core/Address.h"
#include "lldb/Core/ArchSpec.h"
@@ -22,9 +22,9 @@
// These are for the Sourcename completers.
// FIXME: Make a separate file for the completers.
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -40,1079 +40,1012 @@ using namespace lldb_private;
// CommandObject
//-------------------------------------------------------------------------
-CommandObject::CommandObject
-(
- CommandInterpreter &interpreter,
- const char *name,
- const char *help,
- const char *syntax,
- uint32_t flags
-) :
- m_interpreter (interpreter),
- m_cmd_name (name ? name : ""),
- m_cmd_help_short (),
- m_cmd_help_long (),
- m_cmd_syntax (),
- m_flags (flags),
- m_arguments(),
- m_deprecated_command_override_callback (nullptr),
- m_command_override_callback (nullptr),
- m_command_override_baton (nullptr)
-{
- if (help && help[0])
- m_cmd_help_short = help;
- if (syntax && syntax[0])
- m_cmd_syntax = syntax;
-}
-
-CommandObject::~CommandObject ()
-{
-}
-
-const char *
-CommandObject::GetHelp ()
-{
- return m_cmd_help_short.c_str();
-}
-
-const char *
-CommandObject::GetHelpLong ()
-{
- return m_cmd_help_long.c_str();
-}
-
-const char *
-CommandObject::GetSyntax ()
-{
- if (m_cmd_syntax.length() == 0)
- {
- StreamString syntax_str;
- syntax_str.Printf ("%s", GetCommandName());
- if (!IsDashDashCommand() && GetOptions() != nullptr)
- syntax_str.Printf (" <cmd-options>");
- if (m_arguments.size() > 0)
- {
- syntax_str.Printf (" ");
- if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
- syntax_str.Printf("-- ");
- GetFormattedCommandArguments (syntax_str);
- }
- m_cmd_syntax = syntax_str.GetData ();
- }
-
- return m_cmd_syntax.c_str();
+CommandObject::CommandObject(CommandInterpreter &interpreter, const char *name,
+ const char *help, const char *syntax,
+ uint32_t flags)
+ : m_interpreter(interpreter), m_cmd_name(name ? name : ""),
+ m_cmd_help_short(), m_cmd_help_long(), m_cmd_syntax(), m_flags(flags),
+ m_arguments(), m_deprecated_command_override_callback(nullptr),
+ m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
+ if (help && help[0])
+ m_cmd_help_short = help;
+ if (syntax && syntax[0])
+ m_cmd_syntax = syntax;
}
-const char *
-CommandObject::GetCommandName ()
-{
- return m_cmd_name.c_str();
-}
+CommandObject::~CommandObject() {}
-void
-CommandObject::SetCommandName (const char *name)
-{
- m_cmd_name = name;
-}
+const char *CommandObject::GetHelp() { return m_cmd_help_short.c_str(); }
-void
-CommandObject::SetHelp (const char *cstr)
-{
- if (cstr)
- m_cmd_help_short = cstr;
- else
- m_cmd_help_short.assign("");
-}
+const char *CommandObject::GetHelpLong() { return m_cmd_help_long.c_str(); }
-void
-CommandObject::SetHelpLong (const char *cstr)
-{
- if (cstr)
- m_cmd_help_long = cstr;
- else
- m_cmd_help_long.assign("");
-}
+const char *CommandObject::GetSyntax() {
+ if (m_cmd_syntax.length() == 0) {
+ StreamString syntax_str;
+ syntax_str.Printf("%s", GetCommandName());
+ if (!IsDashDashCommand() && GetOptions() != nullptr)
+ syntax_str.Printf(" <cmd-options>");
+ if (m_arguments.size() > 0) {
+ syntax_str.Printf(" ");
+ if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
+ GetOptions()->NumCommandOptions())
+ syntax_str.Printf("-- ");
+ GetFormattedCommandArguments(syntax_str);
+ }
+ m_cmd_syntax = syntax_str.GetData();
+ }
-void
-CommandObject::SetSyntax (const char *cstr)
-{
- m_cmd_syntax = cstr;
+ return m_cmd_syntax.c_str();
}
-Options *
-CommandObject::GetOptions ()
-{
- // By default commands don't have options unless this virtual function
- // is overridden by base classes.
- return nullptr;
-}
+const char *CommandObject::GetCommandName() { return m_cmd_name.c_str(); }
-bool
-CommandObject::ParseOptions
-(
- Args& args,
- CommandReturnObject &result
-)
-{
- // See if the subclass has options?
- Options *options = GetOptions();
- if (options != nullptr)
- {
- Error error;
-
- auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
- options->NotifyOptionParsingStarting(&exe_ctx);
-
- // ParseOptions calls getopt_long_only, which always skips the zero'th item in the array and starts at position 1,
- // so we need to push a dummy value into position zero.
- args.Unshift("dummy_string");
- const bool require_validation = true;
- error = args.ParseOptions(*options, &exe_ctx,
- GetCommandInterpreter().GetPlatform(true),
- require_validation);
-
- // The "dummy_string" will have already been removed by ParseOptions,
- // so no need to remove it.
-
- if (error.Success())
- error = options->NotifyOptionParsingFinished(&exe_ctx);
-
- if (error.Success())
- {
- if (options->VerifyOptions (result))
- return true;
- }
- else
- {
- const char *error_cstr = error.AsCString();
- if (error_cstr)
- {
- // We got an error string, lets use that
- result.AppendError(error_cstr);
- }
- else
- {
- // No error string, output the usage information into result
- options->GenerateOptionUsage(result.GetErrorStream(), this,
- GetCommandInterpreter()
- .GetDebugger()
- .GetTerminalWidth());
- }
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- return true;
+void CommandObject::SetCommandName(const char *name) { m_cmd_name = name; }
+
+void CommandObject::SetHelp(const char *cstr) {
+ if (cstr)
+ m_cmd_help_short = cstr;
+ else
+ m_cmd_help_short.assign("");
}
+void CommandObject::SetHelpLong(const char *cstr) {
+ if (cstr)
+ m_cmd_help_long = cstr;
+ else
+ m_cmd_help_long.assign("");
+}
+void CommandObject::SetSyntax(const char *cstr) { m_cmd_syntax = cstr; }
-bool
-CommandObject::CheckRequirements (CommandReturnObject &result)
-{
-#ifdef LLDB_CONFIGURATION_DEBUG
- // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
- // has shared pointers to the target, process, thread and frame and we don't
- // want any CommandObject instances to keep any of these objects around
- // longer than for a single command. Every command should call
- // CommandObject::Cleanup() after it has completed
- assert (m_exe_ctx.GetTargetPtr() == NULL);
- assert (m_exe_ctx.GetProcessPtr() == NULL);
- assert (m_exe_ctx.GetThreadPtr() == NULL);
- assert (m_exe_ctx.GetFramePtr() == NULL);
-#endif
+Options *CommandObject::GetOptions() {
+ // By default commands don't have options unless this virtual function
+ // is overridden by base classes.
+ return nullptr;
+}
- // Lock down the interpreter's execution context prior to running the
- // command so we guarantee the selected target, process, thread and frame
- // can't go away during the execution
- m_exe_ctx = m_interpreter.GetExecutionContext();
-
- const uint32_t flags = GetFlags().Get();
- if (flags & (eCommandRequiresTarget |
- eCommandRequiresProcess |
- eCommandRequiresThread |
- eCommandRequiresFrame |
- eCommandTryTargetAPILock ))
- {
-
- if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope())
- {
- result.AppendError (GetInvalidTargetDescription());
- return false;
- }
+bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
+ // See if the subclass has options?
+ Options *options = GetOptions();
+ if (options != nullptr) {
+ Error error;
- if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope())
- {
- if (!m_exe_ctx.HasTargetScope())
- result.AppendError (GetInvalidTargetDescription());
- else
- result.AppendError (GetInvalidProcessDescription());
- return false;
- }
-
- if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope())
- {
- if (!m_exe_ctx.HasTargetScope())
- result.AppendError (GetInvalidTargetDescription());
- else if (!m_exe_ctx.HasProcessScope())
- result.AppendError (GetInvalidProcessDescription());
- else
- result.AppendError (GetInvalidThreadDescription());
- return false;
- }
-
- if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope())
- {
- if (!m_exe_ctx.HasTargetScope())
- result.AppendError (GetInvalidTargetDescription());
- else if (!m_exe_ctx.HasProcessScope())
- result.AppendError (GetInvalidProcessDescription());
- else if (!m_exe_ctx.HasThreadScope())
- result.AppendError (GetInvalidThreadDescription());
- else
- result.AppendError (GetInvalidFrameDescription());
- return false;
- }
-
- if ((flags & eCommandRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr))
- {
- result.AppendError (GetInvalidRegContextDescription());
- return false;
- }
+ auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
+ options->NotifyOptionParsingStarting(&exe_ctx);
- if (flags & eCommandTryTargetAPILock)
- {
- Target *target = m_exe_ctx.GetTargetPtr();
- if (target)
- m_api_locker = std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
- }
- }
+ // ParseOptions calls getopt_long_only, which always skips the zero'th item
+ // in the array and starts at position 1,
+ // so we need to push a dummy value into position zero.
+ args.Unshift("dummy_string");
+ const bool require_validation = true;
+ error = args.ParseOptions(*options, &exe_ctx,
+ GetCommandInterpreter().GetPlatform(true),
+ require_validation);
- if (GetFlags().AnySet (eCommandProcessMustBeLaunched | eCommandProcessMustBePaused))
- {
- Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process == nullptr)
- {
- // A process that is not running is considered paused.
- if (GetFlags().Test(eCommandProcessMustBeLaunched))
- {
- result.AppendError ("Process must exist.");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- }
- else
- {
- StateType state = process->GetState();
- switch (state)
- {
- case eStateInvalid:
- case eStateSuspended:
- case eStateCrashed:
- case eStateStopped:
- break;
-
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateDetached:
- case eStateExited:
- case eStateUnloaded:
- if (GetFlags().Test(eCommandProcessMustBeLaunched))
- {
- result.AppendError ("Process must be launched.");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- break;
-
- case eStateRunning:
- case eStateStepping:
- if (GetFlags().Test(eCommandProcessMustBePaused))
- {
- result.AppendError ("Process is running. Use 'process interrupt' to pause execution.");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- }
- }
- }
- return true;
-}
+ // The "dummy_string" will have already been removed by ParseOptions,
+ // so no need to remove it.
-void
-CommandObject::Cleanup ()
-{
- m_exe_ctx.Clear();
- if (m_api_locker.owns_lock())
- m_api_locker.unlock();
-}
-
-int
-CommandObject::HandleCompletion
-(
- Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches
-)
-{
- // Default implementation of WantsCompletion() is !WantsRawCommandString().
- // Subclasses who want raw command string but desire, for example,
- // argument completion should override WantsCompletion() to return true,
- // instead.
- if (WantsRawCommandString() && !WantsCompletion())
- {
- // FIXME: Abstract telling the completion to insert the completion character.
- matches.Clear();
- return -1;
- }
- else
- {
- // Can we do anything generic with the options?
- Options *cur_options = GetOptions();
- CommandReturnObject result;
- OptionElementVector opt_element_vector;
-
- if (cur_options != nullptr)
- {
- // Re-insert the dummy command name string which will have been
- // stripped off:
- input.Unshift ("dummy-string");
- cursor_index++;
-
-
- // I stick an element on the end of the input, because if the last element is
- // option that requires an argument, getopt_long_only will freak out.
-
- input.AppendArgument ("<FAKE-VALUE>");
-
- input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
-
- input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
-
- bool handled_by_options;
- handled_by_options = cur_options->HandleOptionCompletion (input,
- opt_element_vector,
- cursor_index,
- cursor_char_position,
- match_start_point,
- max_return_elements,
- GetCommandInterpreter(),
- word_complete,
- matches);
- if (handled_by_options)
- return matches.GetSize();
- }
+ if (error.Success())
+ error = options->NotifyOptionParsingFinished(&exe_ctx);
- // If we got here, the last word is not an option or an option argument.
- return HandleArgumentCompletion (input,
- cursor_index,
- cursor_char_position,
- opt_element_vector,
- match_start_point,
- max_return_elements,
- word_complete,
- matches);
+ if (error.Success()) {
+ if (options->VerifyOptions(result))
+ return true;
+ } else {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr) {
+ // We got an error string, lets use that
+ result.AppendError(error_cstr);
+ } else {
+ // No error string, output the usage information into result
+ options->GenerateOptionUsage(
+ result.GetErrorStream(), this,
+ GetCommandInterpreter().GetDebugger().GetTerminalWidth());
+ }
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ return true;
}
-bool
-CommandObject::HelpTextContainsWord (const char *search_word,
- bool search_short_help,
- bool search_long_help,
- bool search_syntax,
- bool search_options)
-{
- std::string options_usage_help;
-
- bool found_word = false;
-
- const char *short_help = GetHelp();
- const char *long_help = GetHelpLong();
- const char *syntax_help = GetSyntax();
-
- if (search_short_help && short_help && strcasestr (short_help, search_word))
- found_word = true;
- else if (search_long_help && long_help && strcasestr (long_help, search_word))
- found_word = true;
- else if (search_syntax && syntax_help && strcasestr (syntax_help, search_word))
- found_word = true;
+bool CommandObject::CheckRequirements(CommandReturnObject &result) {
+#ifdef LLDB_CONFIGURATION_DEBUG
+ // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
+ // has shared pointers to the target, process, thread and frame and we don't
+ // want any CommandObject instances to keep any of these objects around
+ // longer than for a single command. Every command should call
+ // CommandObject::Cleanup() after it has completed
+ assert(m_exe_ctx.GetTargetPtr() == NULL);
+ assert(m_exe_ctx.GetProcessPtr() == NULL);
+ assert(m_exe_ctx.GetThreadPtr() == NULL);
+ assert(m_exe_ctx.GetFramePtr() == NULL);
+#endif
- if (!found_word
- && search_options
- && GetOptions() != nullptr)
- {
- StreamString usage_help;
- GetOptions()->GenerateOptionUsage(usage_help, this,
- GetCommandInterpreter()
- .GetDebugger().GetTerminalWidth());
- if (usage_help.GetSize() > 0)
- {
- const char *usage_text = usage_help.GetData();
- if (strcasestr (usage_text, search_word))
- found_word = true;
- }
+ // Lock down the interpreter's execution context prior to running the
+ // command so we guarantee the selected target, process, thread and frame
+ // can't go away during the execution
+ m_exe_ctx = m_interpreter.GetExecutionContext();
+
+ const uint32_t flags = GetFlags().Get();
+ if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
+ eCommandRequiresThread | eCommandRequiresFrame |
+ eCommandTryTargetAPILock)) {
+
+ if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
+ result.AppendError(GetInvalidTargetDescription());
+ return false;
+ }
+
+ if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
+ if (!m_exe_ctx.HasTargetScope())
+ result.AppendError(GetInvalidTargetDescription());
+ else
+ result.AppendError(GetInvalidProcessDescription());
+ return false;
+ }
+
+ if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
+ if (!m_exe_ctx.HasTargetScope())
+ result.AppendError(GetInvalidTargetDescription());
+ else if (!m_exe_ctx.HasProcessScope())
+ result.AppendError(GetInvalidProcessDescription());
+ else
+ result.AppendError(GetInvalidThreadDescription());
+ return false;
+ }
+
+ if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
+ if (!m_exe_ctx.HasTargetScope())
+ result.AppendError(GetInvalidTargetDescription());
+ else if (!m_exe_ctx.HasProcessScope())
+ result.AppendError(GetInvalidProcessDescription());
+ else if (!m_exe_ctx.HasThreadScope())
+ result.AppendError(GetInvalidThreadDescription());
+ else
+ result.AppendError(GetInvalidFrameDescription());
+ return false;
+ }
+
+ if ((flags & eCommandRequiresRegContext) &&
+ (m_exe_ctx.GetRegisterContext() == nullptr)) {
+ result.AppendError(GetInvalidRegContextDescription());
+ return false;
+ }
+
+ if (flags & eCommandTryTargetAPILock) {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (target)
+ m_api_locker =
+ std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
+ }
+ }
+
+ if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused)) {
+ Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process == nullptr) {
+ // A process that is not running is considered paused.
+ if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
+ result.AppendError("Process must exist.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ } else {
+ StateType state = process->GetState();
+ switch (state) {
+ case eStateInvalid:
+ case eStateSuspended:
+ case eStateCrashed:
+ case eStateStopped:
+ break;
+
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateDetached:
+ case eStateExited:
+ case eStateUnloaded:
+ if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
+ result.AppendError("Process must be launched.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ break;
+
+ case eStateRunning:
+ case eStateStepping:
+ if (GetFlags().Test(eCommandProcessMustBePaused)) {
+ result.AppendError("Process is running. Use 'process interrupt' to "
+ "pause execution.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void CommandObject::Cleanup() {
+ m_exe_ctx.Clear();
+ if (m_api_locker.owns_lock())
+ m_api_locker.unlock();
+}
+
+int CommandObject::HandleCompletion(Args &input, int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete, StringList &matches) {
+ // Default implementation of WantsCompletion() is !WantsRawCommandString().
+ // Subclasses who want raw command string but desire, for example,
+ // argument completion should override WantsCompletion() to return true,
+ // instead.
+ if (WantsRawCommandString() && !WantsCompletion()) {
+ // FIXME: Abstract telling the completion to insert the completion
+ // character.
+ matches.Clear();
+ return -1;
+ } else {
+ // Can we do anything generic with the options?
+ Options *cur_options = GetOptions();
+ CommandReturnObject result;
+ OptionElementVector opt_element_vector;
+
+ if (cur_options != nullptr) {
+ // Re-insert the dummy command name string which will have been
+ // stripped off:
+ input.Unshift("dummy-string");
+ cursor_index++;
+
+ // I stick an element on the end of the input, because if the last element
+ // is
+ // option that requires an argument, getopt_long_only will freak out.
+
+ input.AppendArgument("<FAKE-VALUE>");
+
+ input.ParseArgsForCompletion(*cur_options, opt_element_vector,
+ cursor_index);
+
+ input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
+
+ bool handled_by_options;
+ handled_by_options = cur_options->HandleOptionCompletion(
+ input, opt_element_vector, cursor_index, cursor_char_position,
+ match_start_point, max_return_elements, GetCommandInterpreter(),
+ word_complete, matches);
+ if (handled_by_options)
+ return matches.GetSize();
+ }
+
+ // If we got here, the last word is not an option or an option argument.
+ return HandleArgumentCompletion(
+ input, cursor_index, cursor_char_position, opt_element_vector,
+ match_start_point, max_return_elements, word_complete, matches);
+ }
+}
+
+bool CommandObject::HelpTextContainsWord(const char *search_word,
+ bool search_short_help,
+ bool search_long_help,
+ bool search_syntax,
+ bool search_options) {
+ std::string options_usage_help;
+
+ bool found_word = false;
+
+ const char *short_help = GetHelp();
+ const char *long_help = GetHelpLong();
+ const char *syntax_help = GetSyntax();
+
+ if (search_short_help && short_help && strcasestr(short_help, search_word))
+ found_word = true;
+ else if (search_long_help && long_help && strcasestr(long_help, search_word))
+ found_word = true;
+ else if (search_syntax && syntax_help && strcasestr(syntax_help, search_word))
+ found_word = true;
+
+ if (!found_word && search_options && GetOptions() != nullptr) {
+ StreamString usage_help;
+ GetOptions()->GenerateOptionUsage(
+ usage_help, this,
+ GetCommandInterpreter().GetDebugger().GetTerminalWidth());
+ if (usage_help.GetSize() > 0) {
+ const char *usage_text = usage_help.GetData();
+ if (strcasestr(usage_text, search_word))
+ found_word = true;
}
+ }
- return found_word;
+ return found_word;
}
-int
-CommandObject::GetNumArgumentEntries ()
-{
- return m_arguments.size();
-}
+int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
CommandObject::CommandArgumentEntry *
-CommandObject::GetArgumentEntryAtIndex (int idx)
-{
- if (static_cast<size_t>(idx) < m_arguments.size())
- return &(m_arguments[idx]);
+CommandObject::GetArgumentEntryAtIndex(int idx) {
+ if (static_cast<size_t>(idx) < m_arguments.size())
+ return &(m_arguments[idx]);
- return nullptr;
+ return nullptr;
}
const CommandObject::ArgumentTableEntry *
-CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
-{
- const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
-
- for (int i = 0; i < eArgTypeLastArg; ++i)
- if (table[i].arg_type == arg_type)
- return &(table[i]);
+CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
+ const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
- return nullptr;
+ for (int i = 0; i < eArgTypeLastArg; ++i)
+ if (table[i].arg_type == arg_type)
+ return &(table[i]);
+
+ return nullptr;
}
-void
-CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
-{
- const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
- const ArgumentTableEntry *entry = &(table[arg_type]);
-
- // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
-
- if (entry->arg_type != arg_type)
- entry = CommandObject::FindArgumentDataByType (arg_type);
-
- if (!entry)
- return;
-
- StreamString name_str;
- name_str.Printf ("<%s>", entry->arg_name);
-
- if (entry->help_function)
- {
- const char* help_text = entry->help_function();
- if (!entry->help_function.self_formatting)
- {
- interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
- name_str.GetSize());
- }
- else
- {
- interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
- name_str.GetSize());
- }
+void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
+ CommandInterpreter &interpreter) {
+ const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
+ const ArgumentTableEntry *entry = &(table[arg_type]);
+
+ // The table is *supposed* to be kept in arg_type order, but someone *could*
+ // have messed it up...
+
+ if (entry->arg_type != arg_type)
+ entry = CommandObject::FindArgumentDataByType(arg_type);
+
+ if (!entry)
+ return;
+
+ StreamString name_str;
+ name_str.Printf("<%s>", entry->arg_name);
+
+ if (entry->help_function) {
+ const char *help_text = entry->help_function();
+ if (!entry->help_function.self_formatting) {
+ interpreter.OutputFormattedHelpText(str, name_str.GetData(), "--",
+ help_text, name_str.GetSize());
+ } else {
+ interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
+ name_str.GetSize());
}
- else
- interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
+ } else
+ interpreter.OutputFormattedHelpText(str, name_str.GetData(), "--",
+ entry->help_text, name_str.GetSize());
}
-const char *
-CommandObject::GetArgumentName (CommandArgumentType arg_type)
-{
- const ArgumentTableEntry *entry = &(CommandObject::GetArgumentTable()[arg_type]);
+const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
+ const ArgumentTableEntry *entry =
+ &(CommandObject::GetArgumentTable()[arg_type]);
- // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
+ // The table is *supposed* to be kept in arg_type order, but someone *could*
+ // have messed it up...
- if (entry->arg_type != arg_type)
- entry = CommandObject::FindArgumentDataByType (arg_type);
+ if (entry->arg_type != arg_type)
+ entry = CommandObject::FindArgumentDataByType(arg_type);
- if (entry)
- return entry->arg_name;
+ if (entry)
+ return entry->arg_name;
- StreamString str;
- str << "Arg name for type (" << arg_type << ") not in arg table!";
- return str.GetData();
+ StreamString str;
+ str << "Arg name for type (" << arg_type << ") not in arg table!";
+ return str.GetData();
}
-bool
-CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type)
-{
- if ((arg_repeat_type == eArgRepeatPairPlain)
- || (arg_repeat_type == eArgRepeatPairOptional)
- || (arg_repeat_type == eArgRepeatPairPlus)
- || (arg_repeat_type == eArgRepeatPairStar)
- || (arg_repeat_type == eArgRepeatPairRange)
- || (arg_repeat_type == eArgRepeatPairRangeOptional))
- return true;
+bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
+ if ((arg_repeat_type == eArgRepeatPairPlain) ||
+ (arg_repeat_type == eArgRepeatPairOptional) ||
+ (arg_repeat_type == eArgRepeatPairPlus) ||
+ (arg_repeat_type == eArgRepeatPairStar) ||
+ (arg_repeat_type == eArgRepeatPairRange) ||
+ (arg_repeat_type == eArgRepeatPairRangeOptional))
+ return true;
- return false;
+ return false;
}
static CommandObject::CommandArgumentEntry
-OptSetFiltered(uint32_t opt_set_mask, CommandObject::CommandArgumentEntry &cmd_arg_entry)
-{
- CommandObject::CommandArgumentEntry ret_val;
- for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
- if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
- ret_val.push_back(cmd_arg_entry[i]);
- return ret_val;
+OptSetFiltered(uint32_t opt_set_mask,
+ CommandObject::CommandArgumentEntry &cmd_arg_entry) {
+ CommandObject::CommandArgumentEntry ret_val;
+ for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
+ if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
+ ret_val.push_back(cmd_arg_entry[i]);
+ return ret_val;
}
// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take
// all the argument data into account. On rare cases where some argument sticks
// with certain option sets, this function returns the option set filtered args.
-void
-CommandObject::GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask)
-{
- int num_args = m_arguments.size();
- for (int i = 0; i < num_args; ++i)
- {
- if (i > 0)
- str.Printf (" ");
- CommandArgumentEntry arg_entry =
- opt_set_mask == LLDB_OPT_SET_ALL ? m_arguments[i]
- : OptSetFiltered(opt_set_mask, m_arguments[i]);
- int num_alternatives = arg_entry.size();
-
- if ((num_alternatives == 2)
- && IsPairType (arg_entry[0].arg_repetition))
- {
- const char *first_name = GetArgumentName (arg_entry[0].arg_type);
- const char *second_name = GetArgumentName (arg_entry[1].arg_type);
- switch (arg_entry[0].arg_repetition)
- {
- case eArgRepeatPairPlain:
- str.Printf ("<%s> <%s>", first_name, second_name);
- break;
- case eArgRepeatPairOptional:
- str.Printf ("[<%s> <%s>]", first_name, second_name);
- break;
- case eArgRepeatPairPlus:
- str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
- break;
- case eArgRepeatPairStar:
- str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
- break;
- case eArgRepeatPairRange:
- str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
- break;
- case eArgRepeatPairRangeOptional:
- str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
- break;
- // Explicitly test for all the rest of the cases, so if new types get added we will notice the
- // missing case statement(s).
- case eArgRepeatPlain:
- case eArgRepeatOptional:
- case eArgRepeatPlus:
- case eArgRepeatStar:
- case eArgRepeatRange:
- // These should not be reached, as they should fail the IsPairType test above.
- break;
- }
- }
- else
- {
- StreamString names;
- for (int j = 0; j < num_alternatives; ++j)
- {
- if (j > 0)
- names.Printf (" | ");
- names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
- }
- switch (arg_entry[0].arg_repetition)
- {
- case eArgRepeatPlain:
- str.Printf ("<%s>", names.GetData());
- break;
- case eArgRepeatPlus:
- str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
- break;
- case eArgRepeatStar:
- str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
- break;
- case eArgRepeatOptional:
- str.Printf ("[<%s>]", names.GetData());
- break;
- case eArgRepeatRange:
- str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData());
- break;
- // Explicitly test for all the rest of the cases, so if new types get added we will notice the
- // missing case statement(s).
- case eArgRepeatPairPlain:
- case eArgRepeatPairOptional:
- case eArgRepeatPairPlus:
- case eArgRepeatPairStar:
- case eArgRepeatPairRange:
- case eArgRepeatPairRangeOptional:
- // These should not be hit, as they should pass the IsPairType test above, and control should
- // have gone into the other branch of the if statement.
- break;
- }
- }
- }
+void CommandObject::GetFormattedCommandArguments(Stream &str,
+ uint32_t opt_set_mask) {
+ int num_args = m_arguments.size();
+ for (int i = 0; i < num_args; ++i) {
+ if (i > 0)
+ str.Printf(" ");
+ CommandArgumentEntry arg_entry =
+ opt_set_mask == LLDB_OPT_SET_ALL
+ ? m_arguments[i]
+ : OptSetFiltered(opt_set_mask, m_arguments[i]);
+ int num_alternatives = arg_entry.size();
+
+ if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
+ const char *first_name = GetArgumentName(arg_entry[0].arg_type);
+ const char *second_name = GetArgumentName(arg_entry[1].arg_type);
+ switch (arg_entry[0].arg_repetition) {
+ case eArgRepeatPairPlain:
+ str.Printf("<%s> <%s>", first_name, second_name);
+ break;
+ case eArgRepeatPairOptional:
+ str.Printf("[<%s> <%s>]", first_name, second_name);
+ break;
+ case eArgRepeatPairPlus:
+ str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
+ first_name, second_name);
+ break;
+ case eArgRepeatPairStar:
+ str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
+ first_name, second_name);
+ break;
+ case eArgRepeatPairRange:
+ str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
+ first_name, second_name);
+ break;
+ case eArgRepeatPairRangeOptional:
+ str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
+ first_name, second_name);
+ break;
+ // Explicitly test for all the rest of the cases, so if new types get
+ // added we will notice the
+ // missing case statement(s).
+ case eArgRepeatPlain:
+ case eArgRepeatOptional:
+ case eArgRepeatPlus:
+ case eArgRepeatStar:
+ case eArgRepeatRange:
+ // These should not be reached, as they should fail the IsPairType test
+ // above.
+ break;
+ }
+ } else {
+ StreamString names;
+ for (int j = 0; j < num_alternatives; ++j) {
+ if (j > 0)
+ names.Printf(" | ");
+ names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
+ }
+ switch (arg_entry[0].arg_repetition) {
+ case eArgRepeatPlain:
+ str.Printf("<%s>", names.GetData());
+ break;
+ case eArgRepeatPlus:
+ str.Printf("<%s> [<%s> [...]]", names.GetData(), names.GetData());
+ break;
+ case eArgRepeatStar:
+ str.Printf("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
+ break;
+ case eArgRepeatOptional:
+ str.Printf("[<%s>]", names.GetData());
+ break;
+ case eArgRepeatRange:
+ str.Printf("<%s_1> .. <%s_n>", names.GetData(), names.GetData());
+ break;
+ // Explicitly test for all the rest of the cases, so if new types get
+ // added we will notice the
+ // missing case statement(s).
+ case eArgRepeatPairPlain:
+ case eArgRepeatPairOptional:
+ case eArgRepeatPairPlus:
+ case eArgRepeatPairStar:
+ case eArgRepeatPairRange:
+ case eArgRepeatPairRangeOptional:
+ // These should not be hit, as they should pass the IsPairType test
+ // above, and control should
+ // have gone into the other branch of the if statement.
+ break;
+ }
+ }
+ }
+}
+
+CommandArgumentType CommandObject::LookupArgumentName(const char *arg_name) {
+ CommandArgumentType return_type = eArgTypeLastArg;
+
+ std::string arg_name_str(arg_name);
+ size_t len = arg_name_str.length();
+ if (arg_name[0] == '<' && arg_name[len - 1] == '>')
+ arg_name_str = arg_name_str.substr(1, len - 2);
+
+ const ArgumentTableEntry *table = GetArgumentTable();
+ for (int i = 0; i < eArgTypeLastArg; ++i)
+ if (arg_name_str.compare(table[i].arg_name) == 0)
+ return_type = g_arguments_data[i].arg_type;
+
+ return return_type;
+}
+
+static const char *RegisterNameHelpTextCallback() {
+ return "Register names can be specified using the architecture specific "
+ "names. "
+ "They can also be specified using generic names. Not all generic "
+ "entities have "
+ "registers backing them on all architectures. When they don't the "
+ "generic name "
+ "will return an error.\n"
+ "The generic names defined in lldb are:\n"
+ "\n"
+ "pc - program counter register\n"
+ "ra - return address register\n"
+ "fp - frame pointer register\n"
+ "sp - stack pointer register\n"
+ "flags - the flags register\n"
+ "arg{1-6} - integer argument passing registers.\n";
+}
+
+static const char *BreakpointIDHelpTextCallback() {
+ return "Breakpoints are identified using major and minor numbers; the major "
+ "number corresponds to the single entity that was created with a "
+ "'breakpoint "
+ "set' command; the minor numbers correspond to all the locations that "
+ "were "
+ "actually found/set based on the major breakpoint. A full breakpoint "
+ "ID might "
+ "look like 3.14, meaning the 14th location set for the 3rd "
+ "breakpoint. You "
+ "can specify all the locations of a breakpoint by just indicating the "
+ "major "
+ "breakpoint number. A valid breakpoint ID consists either of just the "
+ "major "
+ "number, or the major number followed by a dot and the location "
+ "number (e.g. "
+ "3 or 3.2 could both be valid breakpoint IDs.)";
+}
+
+static const char *BreakpointIDRangeHelpTextCallback() {
+ return "A 'breakpoint ID list' is a manner of specifying multiple "
+ "breakpoints. "
+ "This can be done through several mechanisms. The easiest way is to "
+ "just "
+ "enter a space-separated list of breakpoint IDs. To specify all the "
+ "breakpoint locations under a major breakpoint, you can use the major "
+ "breakpoint number followed by '.*', eg. '5.*' means all the "
+ "locations under "
+ "breakpoint 5. You can also indicate a range of breakpoints by using "
+ "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a "
+ "range can "
+ "be any valid breakpoint IDs. It is not legal, however, to specify a "
+ "range "
+ "using specific locations that cross major breakpoint numbers. I.e. "
+ "3.2 - 3.7"
+ " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
+}
+
+static const char *BreakpointNameHelpTextCallback() {
+ return "A name that can be added to a breakpoint when it is created, or "
+ "later "
+ "on with the \"breakpoint name add\" command. "
+ "Breakpoint names can be used to specify breakpoints in all the "
+ "places breakpoint IDs "
+ "and breakpoint ID ranges can be used. As such they provide a "
+ "convenient way to group breakpoints, "
+ "and to operate on breakpoints you create without having to track the "
+ "breakpoint number. "
+ "Note, the attributes you set when using a breakpoint name in a "
+ "breakpoint command don't "
+ "adhere to the name, but instead are set individually on all the "
+ "breakpoints currently tagged with that "
+ "name. Future breakpoints "
+ "tagged with that name will not pick up the attributes previously "
+ "given using that name. "
+ "In order to distinguish breakpoint names from breakpoint IDs and "
+ "ranges, "
+ "names must start with a letter from a-z or A-Z and cannot contain "
+ "spaces, \".\" or \"-\". "
+ "Also, breakpoint names can only be applied to breakpoints, not to "
+ "breakpoint locations.";
+}
+
+static const char *GDBFormatHelpTextCallback() {
+ return "A GDB format consists of a repeat count, a format letter and a size "
+ "letter. "
+ "The repeat count is optional and defaults to 1. The format letter is "
+ "optional "
+ "and defaults to the previous format that was used. The size letter "
+ "is optional "
+ "and defaults to the previous size that was used.\n"
+ "\n"
+ "Format letters include:\n"
+ "o - octal\n"
+ "x - hexadecimal\n"
+ "d - decimal\n"
+ "u - unsigned decimal\n"
+ "t - binary\n"
+ "f - float\n"
+ "a - address\n"
+ "i - instruction\n"
+ "c - char\n"
+ "s - string\n"
+ "T - OSType\n"
+ "A - float as hex\n"
+ "\n"
+ "Size letters include:\n"
+ "b - 1 byte (byte)\n"
+ "h - 2 bytes (halfword)\n"
+ "w - 4 bytes (word)\n"
+ "g - 8 bytes (giant)\n"
+ "\n"
+ "Example formats:\n"
+ "32xb - show 32 1 byte hexadecimal integer values\n"
+ "16xh - show 16 2 byte hexadecimal integer values\n"
+ "64 - show 64 2 byte hexadecimal integer values (format and size "
+ "from the last format)\n"
+ "dw - show 1 4 byte decimal integer value\n";
}
-CommandArgumentType
-CommandObject::LookupArgumentName (const char *arg_name)
-{
- CommandArgumentType return_type = eArgTypeLastArg;
-
- std::string arg_name_str (arg_name);
- size_t len = arg_name_str.length();
- if (arg_name[0] == '<'
- && arg_name[len-1] == '>')
- arg_name_str = arg_name_str.substr (1, len-2);
-
- const ArgumentTableEntry *table = GetArgumentTable();
- for (int i = 0; i < eArgTypeLastArg; ++i)
- if (arg_name_str.compare (table[i].arg_name) == 0)
- return_type = g_arguments_data[i].arg_type;
-
- return return_type;
-}
-
-static const char *
-RegisterNameHelpTextCallback ()
-{
- return "Register names can be specified using the architecture specific names. "
- "They can also be specified using generic names. Not all generic entities have "
- "registers backing them on all architectures. When they don't the generic name "
- "will return an error.\n"
- "The generic names defined in lldb are:\n"
- "\n"
- "pc - program counter register\n"
- "ra - return address register\n"
- "fp - frame pointer register\n"
- "sp - stack pointer register\n"
- "flags - the flags register\n"
- "arg{1-6} - integer argument passing registers.\n";
-}
-
-static const char *
-BreakpointIDHelpTextCallback ()
-{
- return "Breakpoints are identified using major and minor numbers; the major "
- "number corresponds to the single entity that was created with a 'breakpoint "
- "set' command; the minor numbers correspond to all the locations that were "
- "actually found/set based on the major breakpoint. A full breakpoint ID might "
- "look like 3.14, meaning the 14th location set for the 3rd breakpoint. You "
- "can specify all the locations of a breakpoint by just indicating the major "
- "breakpoint number. A valid breakpoint ID consists either of just the major "
- "number, or the major number followed by a dot and the location number (e.g. "
- "3 or 3.2 could both be valid breakpoint IDs.)";
-}
-
-static const char *
-BreakpointIDRangeHelpTextCallback ()
-{
- return "A 'breakpoint ID list' is a manner of specifying multiple breakpoints. "
- "This can be done through several mechanisms. The easiest way is to just "
- "enter a space-separated list of breakpoint IDs. To specify all the "
- "breakpoint locations under a major breakpoint, you can use the major "
- "breakpoint number followed by '.*', eg. '5.*' means all the locations under "
- "breakpoint 5. You can also indicate a range of breakpoints by using "
- "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a range can "
- "be any valid breakpoint IDs. It is not legal, however, to specify a range "
- "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7"
- " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
-}
-
-static const char *
-BreakpointNameHelpTextCallback ()
-{
- return "A name that can be added to a breakpoint when it is created, or later "
- "on with the \"breakpoint name add\" command. "
- "Breakpoint names can be used to specify breakpoints in all the places breakpoint IDs "
- "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, "
- "and to operate on breakpoints you create without having to track the breakpoint number. "
- "Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
- "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that "
- "name. Future breakpoints "
- "tagged with that name will not pick up the attributes previously given using that name. "
- "In order to distinguish breakpoint names from breakpoint IDs and ranges, "
- "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". "
- "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
-}
-
-static const char *
-GDBFormatHelpTextCallback ()
-{
- return "A GDB format consists of a repeat count, a format letter and a size letter. "
- "The repeat count is optional and defaults to 1. The format letter is optional "
- "and defaults to the previous format that was used. The size letter is optional "
- "and defaults to the previous size that was used.\n"
- "\n"
- "Format letters include:\n"
- "o - octal\n"
- "x - hexadecimal\n"
- "d - decimal\n"
- "u - unsigned decimal\n"
- "t - binary\n"
- "f - float\n"
- "a - address\n"
- "i - instruction\n"
- "c - char\n"
- "s - string\n"
- "T - OSType\n"
- "A - float as hex\n"
- "\n"
- "Size letters include:\n"
- "b - 1 byte (byte)\n"
- "h - 2 bytes (halfword)\n"
- "w - 4 bytes (word)\n"
- "g - 8 bytes (giant)\n"
- "\n"
- "Example formats:\n"
- "32xb - show 32 1 byte hexadecimal integer values\n"
- "16xh - show 16 2 byte hexadecimal integer values\n"
- "64 - show 64 2 byte hexadecimal integer values (format and size from the last format)\n"
- "dw - show 1 4 byte decimal integer value\n"
- ;
-}
-
-static const char *
-FormatHelpTextCallback ()
-{
-
- static char* help_text_ptr = nullptr;
-
- if (help_text_ptr)
- return help_text_ptr;
-
- StreamString sstr;
- sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n";
- for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
- {
- if (f != eFormatDefault)
- sstr.PutChar('\n');
-
- char format_char = FormatManager::GetFormatAsFormatChar(f);
- if (format_char)
- sstr.Printf("'%c' or ", format_char);
-
- sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
- }
-
- sstr.Flush();
-
- std::string data = sstr.GetString();
-
- help_text_ptr = new char[data.length()+1];
-
- data.copy(help_text_ptr, data.length());
-
- return help_text_ptr;
-}
+static const char *FormatHelpTextCallback() {
+
+ static char *help_text_ptr = nullptr;
-static const char *
-LanguageTypeHelpTextCallback ()
-{
- static char* help_text_ptr = nullptr;
-
- if (help_text_ptr)
- return help_text_ptr;
-
- StreamString sstr;
- sstr << "One of the following languages:\n";
-
- Language::PrintAllLanguages(sstr, " ", "\n");
-
- sstr.Flush();
-
- std::string data = sstr.GetString();
-
- help_text_ptr = new char[data.length()+1];
-
- data.copy(help_text_ptr, data.length());
-
+ if (help_text_ptr)
return help_text_ptr;
-}
-static const char *
-SummaryStringHelpTextCallback()
-{
- return
- "A summary string is a way to extract information from variables in order to present them using a summary.\n"
- "Summary strings contain static text, variables, scopes and control sequences:\n"
- " - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n"
- " - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n"
- " - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n"
- " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n"
- "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n"
- "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n"
- "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type"
- " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be"
- " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed."
- " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n"
- "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed."
- "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression"
- " path refers to:\n"
- " - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number"
- " and displayed as an individual variable\n"
- " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are"
- " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n"
- "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n"
- "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the"
- " special symbols only allowed as part of a variable:\n"
- " %V: show the value of the object by default\n"
- " %S: show the summary of the object by default\n"
- " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n"
- " %L: show the location of the object (memory address or a register name)\n"
- " %#: show the number of children of the object\n"
- " %T: show the type of the object\n"
- "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses"
- " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would"
- " count the number of actual elements stored in an std::list:\n"
- "type summary add -s \"${svar%#}\" -x \"std::list<\"";
-}
-
-static const char *
-ExprPathHelpTextCallback()
-{
- return
- "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n"
- "For instance, given a class:\n"
- " class foo {\n"
- " int a;\n"
- " int b; .\n"
- " foo* next;\n"
- " };\n"
- "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n"
- "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n"
- "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n"
- "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n"
- "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n"
- "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract"
- " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index"
- " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the"
- " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
-}
-
-void
-CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
-{
- CommandInterpreter& interpreter = GetCommandInterpreter();
- std::stringstream lineStream (long_help);
- std::string line;
- while (std::getline (lineStream, line)) {
- if (line.empty()) {
- output_strm << "\n";
- continue;
- }
- size_t result = line.find_first_not_of (" \t");
- if (result == std::string::npos) {
- result = 0;
- }
- std::string whitespace_prefix = line.substr (0, result);
- std::string remainder = line.substr (result);
- interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
- }
-}
+ StreamString sstr;
+ sstr << "One of the format names (or one-character names) that can be used "
+ "to show a variable's value:\n";
+ for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
+ if (f != eFormatDefault)
+ sstr.PutChar('\n');
-void
-CommandObject::GenerateHelpText (CommandReturnObject &result)
-{
- GenerateHelpText(result.GetOutputStream());
-
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
-}
-
-void
-CommandObject::GenerateHelpText (Stream &output_strm)
-{
- CommandInterpreter& interpreter = GetCommandInterpreter();
- if (WantsRawCommandString())
- {
- std::string help_text(GetHelp());
- help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
- interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(), 1);
- }
- else
- interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1);
- output_strm.Printf("\nSyntax: %s\n", GetSyntax());
- Options *options = GetOptions();
- if (options != nullptr)
- {
- options->GenerateOptionUsage(output_strm, this,
- GetCommandInterpreter()
- .GetDebugger().GetTerminalWidth());
- }
- const char *long_help = GetHelpLong();
- if ((long_help != nullptr) && (strlen(long_help) > 0))
- {
- FormatLongHelpText(output_strm, long_help);
- }
- if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0)
- {
- if (WantsRawCommandString() && !WantsCompletion())
- {
- // Emit the message about using ' -- ' between the end of the command options and the raw input
- // conditionally, i.e., only if the command object does not want completion.
- interpreter.OutputFormattedHelpText(
- output_strm, "", "",
- "\nImportant Note: Because this command takes 'raw' input, if you use any command options"
- " you must use ' -- ' between the end of the command options and the beginning of the raw input.",
- 1);
- }
- else if (GetNumArgumentEntries() > 0)
- {
- // Also emit a warning about using "--" in case you are using a command that takes options and arguments.
- interpreter.OutputFormattedHelpText(
- output_strm, "", "", "\nThis command takes options and free-form arguments. If your arguments resemble"
- " option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
- " the end of the command options and the beginning of the arguments.",
- 1);
- }
- }
-}
+ char format_char = FormatManager::GetFormatAsFormatChar(f);
+ if (format_char)
+ sstr.Printf("'%c' or ", format_char);
-void
-CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange)
-{
- CommandArgumentData id_arg;
- CommandArgumentData id_range_arg;
-
- // Create the first variant for the first (and only) argument for this command.
- id_arg.arg_type = ID;
- id_arg.arg_repetition = eArgRepeatOptional;
-
- // Create the second variant for the first (and only) argument for this command.
- id_range_arg.arg_type = IDRange;
- id_range_arg.arg_repetition = eArgRepeatOptional;
-
- // The first (and only) argument for this command could be either an id or an id_range.
- // Push both variants into the entry for the first argument for this command.
- arg.push_back(id_arg);
- arg.push_back(id_range_arg);
-}
-
-const char *
-CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
-{
- assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentTypeAsCString");
- return g_arguments_data[arg_type].arg_name;
-}
-
-const char *
-CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
-{
- assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentDescriptionAsCString");
- return g_arguments_data[arg_type].help_text;
-}
-
-Target *
-CommandObject::GetDummyTarget()
-{
- return m_interpreter.GetDebugger().GetDummyTarget();
-}
-
-Target *
-CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy)
-{
- return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
-}
-
-Thread *
-CommandObject::GetDefaultThread()
-{
- Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
- if (thread_to_use)
- return thread_to_use;
-
- Process *process = m_exe_ctx.GetProcessPtr();
- if (!process)
- {
- Target *target = m_exe_ctx.GetTargetPtr();
- if (!target)
- {
- target = m_interpreter.GetDebugger().GetSelectedTarget().get();
- }
- if (target)
- process = target->GetProcessSP().get();
- }
+ sstr.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
+ }
- if (process)
- return process->GetThreadList().GetSelectedThread().get();
- else
- return nullptr;
-}
-
-bool
-CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result)
-{
- bool handled = false;
- Args cmd_args (args_string);
- if (HasOverrideCallback())
- {
- Args full_args (GetCommandName ());
- full_args.AppendArguments(cmd_args);
- handled = InvokeOverrideCallback (full_args.GetConstArgumentVector(), result);
- }
- if (!handled)
- {
- for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i)
- {
- const char *tmp_str = cmd_args.GetArgumentAtIndex (i);
- if (tmp_str[0] == '`') // back-quote
- cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
- }
+ sstr.Flush();
- if (CheckRequirements(result))
- {
- if (ParseOptions (cmd_args, result))
- {
- // Call the command-specific version of 'Execute', passing it the already processed arguments.
- handled = DoExecute (cmd_args, result);
- }
- }
+ std::string data = sstr.GetString();
- Cleanup();
- }
- return handled;
+ help_text_ptr = new char[data.length() + 1];
+
+ data.copy(help_text_ptr, data.length());
+
+ return help_text_ptr;
}
-bool
-CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
-{
- bool handled = false;
- if (HasOverrideCallback())
- {
- std::string full_command (GetCommandName ());
- full_command += ' ';
- full_command += args_string;
- const char *argv[2] = { nullptr, nullptr };
- argv[0] = full_command.c_str();
- handled = InvokeOverrideCallback (argv, result);
- }
- if (!handled)
- {
- if (CheckRequirements(result))
- handled = DoExecute (args_string, result);
-
- Cleanup();
- }
- return handled;
+static const char *LanguageTypeHelpTextCallback() {
+ static char *help_text_ptr = nullptr;
+
+ if (help_text_ptr)
+ return help_text_ptr;
+
+ StreamString sstr;
+ sstr << "One of the following languages:\n";
+
+ Language::PrintAllLanguages(sstr, " ", "\n");
+
+ sstr.Flush();
+
+ std::string data = sstr.GetString();
+
+ help_text_ptr = new char[data.length() + 1];
+
+ data.copy(help_text_ptr, data.length());
+
+ return help_text_ptr;
+}
+
+static const char *SummaryStringHelpTextCallback() {
+ return "A summary string is a way to extract information from variables in "
+ "order to present them using a summary.\n"
+ "Summary strings contain static text, variables, scopes and control "
+ "sequences:\n"
+ " - Static text can be any sequence of non-special characters, i.e. "
+ "anything but '{', '}', '$', or '\\'.\n"
+ " - Variables are sequences of characters beginning with ${, ending "
+ "with } and that contain symbols in the format described below.\n"
+ " - Scopes are any sequence of text between { and }. Anything "
+ "included in a scope will only appear in the output summary if there "
+ "were no errors.\n"
+ " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus "
+ "'\\$', '\\{' and '\\}'.\n"
+ "A summary string works by copying static text verbatim, turning "
+ "control sequences into their character counterpart, expanding "
+ "variables and trying to expand scopes.\n"
+ "A variable is expanded by giving it a value other than its textual "
+ "representation, and the way this is done depends on what comes after "
+ "the ${ marker.\n"
+ "The most common sequence if ${var followed by an expression path, "
+ "which is the text one would type to access a member of an aggregate "
+ "types, given a variable of that type"
+ " (e.g. if type T has a member named x, which has a member named y, "
+ "and if t is of type T, the expression path would be .x.y and the way "
+ "to fit that into a summary string would be"
+ " ${var.x.y}). You can also use ${*var followed by an expression path "
+ "and in that case the object referred by the path will be "
+ "dereferenced before being displayed."
+ " If the object is not a pointer, doing so will cause an error. For "
+ "additional details on expression paths, you can type 'help "
+ "expr-path'. \n"
+ "By default, summary strings attempt to display the summary for any "
+ "variable they reference, and if that fails the value. If neither can "
+ "be shown, nothing is displayed."
+ "In a summary string, you can also use an array index [n], or a "
+ "slice-like range [n-m]. This can have two different meanings "
+ "depending on what kind of object the expression"
+ " path refers to:\n"
+ " - if it is a scalar type (any basic type like int, float, ...) the "
+ "expression is a bitfield, i.e. the bits indicated by the indexing "
+ "operator are extracted out of the number"
+ " and displayed as an individual variable\n"
+ " - if it is an array or pointer the array items indicated by the "
+ "indexing operator are shown as the result of the variable. if the "
+ "expression is an array, real array items are"
+ " printed; if it is a pointer, the pointer-as-array syntax is used to "
+ "obtain the values (this means, the latter case can have no range "
+ "checking)\n"
+ "If you are trying to display an array for which the size is known, "
+ "you can also use [] instead of giving an exact range. This has the "
+ "effect of showing items 0 thru size - 1.\n"
+ "Additionally, a variable can contain an (optional) format code, as "
+ "in ${var.x.y%code}, where code can be any of the valid formats "
+ "described in 'help format', or one of the"
+ " special symbols only allowed as part of a variable:\n"
+ " %V: show the value of the object by default\n"
+ " %S: show the summary of the object by default\n"
+ " %@: show the runtime-provided object description (for "
+ "Objective-C, it calls NSPrintForDebugger; for C/C++ it does "
+ "nothing)\n"
+ " %L: show the location of the object (memory address or a "
+ "register name)\n"
+ " %#: show the number of children of the object\n"
+ " %T: show the type of the object\n"
+ "Another variable that you can use in summary strings is ${svar . "
+ "This sequence works exactly like ${var, including the fact that "
+ "${*svar is an allowed sequence, but uses"
+ " the object's synthetic children provider instead of the actual "
+ "objects. For instance, if you are using STL synthetic children "
+ "providers, the following summary string would"
+ " count the number of actual elements stored in an std::list:\n"
+ "type summary add -s \"${svar%#}\" -x \"std::list<\"";
+}
+
+static const char *ExprPathHelpTextCallback() {
+ return "An expression path is the sequence of symbols that is used in C/C++ "
+ "to access a member variable of an aggregate object (class).\n"
+ "For instance, given a class:\n"
+ " class foo {\n"
+ " int a;\n"
+ " int b; .\n"
+ " foo* next;\n"
+ " };\n"
+ "the expression to read item b in the item pointed to by next for foo "
+ "aFoo would be aFoo.next->b.\n"
+ "Given that aFoo could just be any object of type foo, the string "
+ "'.next->b' is the expression path, because it can be attached to any "
+ "foo instance to achieve the effect.\n"
+ "Expression paths in LLDB include dot (.) and arrow (->) operators, "
+ "and most commands using expression paths have ways to also accept "
+ "the star (*) operator.\n"
+ "The meaning of these operators is the same as the usual one given to "
+ "them by the C/C++ standards.\n"
+ "LLDB also has support for indexing ([ ]) in expression paths, and "
+ "extends the traditional meaning of the square brackets operator to "
+ "allow bitfield extraction:\n"
+ "for objects of native types (int, float, char, ...) saying '[n-m]' "
+ "as an expression path (where n and m are any positive integers, e.g. "
+ "[3-5]) causes LLDB to extract"
+ " bits n thru m from the value of the variable. If n == m, [n] is "
+ "also allowed as a shortcut syntax. For arrays and pointers, "
+ "expression paths can only contain one index"
+ " and the meaning of the operation is the same as the one defined by "
+ "C/C++ (item extraction). Some commands extend bitfield-like syntax "
+ "for arrays and pointers with the"
+ " meaning of array slicing (taking elements n thru m inside the array "
+ "or pointed-to memory).";
+}
+
+void CommandObject::FormatLongHelpText(Stream &output_strm,
+ const char *long_help) {
+ CommandInterpreter &interpreter = GetCommandInterpreter();
+ std::stringstream lineStream(long_help);
+ std::string line;
+ while (std::getline(lineStream, line)) {
+ if (line.empty()) {
+ output_strm << "\n";
+ continue;
+ }
+ size_t result = line.find_first_not_of(" \t");
+ if (result == std::string::npos) {
+ result = 0;
+ }
+ std::string whitespace_prefix = line.substr(0, result);
+ std::string remainder = line.substr(result);
+ interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(),
+ remainder.c_str());
+ }
+}
+
+void CommandObject::GenerateHelpText(CommandReturnObject &result) {
+ GenerateHelpText(result.GetOutputStream());
+
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+}
+
+void CommandObject::GenerateHelpText(Stream &output_strm) {
+ CommandInterpreter &interpreter = GetCommandInterpreter();
+ if (WantsRawCommandString()) {
+ std::string help_text(GetHelp());
+ help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
+ interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(),
+ 1);
+ } else
+ interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1);
+ output_strm.Printf("\nSyntax: %s\n", GetSyntax());
+ Options *options = GetOptions();
+ if (options != nullptr) {
+ options->GenerateOptionUsage(
+ output_strm, this,
+ GetCommandInterpreter().GetDebugger().GetTerminalWidth());
+ }
+ const char *long_help = GetHelpLong();
+ if ((long_help != nullptr) && (strlen(long_help) > 0)) {
+ FormatLongHelpText(output_strm, long_help);
+ }
+ if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
+ if (WantsRawCommandString() && !WantsCompletion()) {
+ // Emit the message about using ' -- ' between the end of the command
+ // options and the raw input
+ // conditionally, i.e., only if the command object does not want
+ // completion.
+ interpreter.OutputFormattedHelpText(
+ output_strm, "", "",
+ "\nImportant Note: Because this command takes 'raw' input, if you "
+ "use any command options"
+ " you must use ' -- ' between the end of the command options and the "
+ "beginning of the raw input.",
+ 1);
+ } else if (GetNumArgumentEntries() > 0) {
+ // Also emit a warning about using "--" in case you are using a command
+ // that takes options and arguments.
+ interpreter.OutputFormattedHelpText(
+ output_strm, "", "",
+ "\nThis command takes options and free-form arguments. If your "
+ "arguments resemble"
+ " option specifiers (i.e., they start with a - or --), you must use "
+ "' -- ' between"
+ " the end of the command options and the beginning of the arguments.",
+ 1);
+ }
+ }
+}
+
+void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg,
+ CommandArgumentType ID,
+ CommandArgumentType IDRange) {
+ CommandArgumentData id_arg;
+ CommandArgumentData id_range_arg;
+
+ // Create the first variant for the first (and only) argument for this
+ // command.
+ id_arg.arg_type = ID;
+ id_arg.arg_repetition = eArgRepeatOptional;
+
+ // Create the second variant for the first (and only) argument for this
+ // command.
+ id_range_arg.arg_type = IDRange;
+ id_range_arg.arg_repetition = eArgRepeatOptional;
+
+ // The first (and only) argument for this command could be either an id or an
+ // id_range.
+ // Push both variants into the entry for the first argument for this command.
+ arg.push_back(id_arg);
+ arg.push_back(id_range_arg);
+}
+
+const char *CommandObject::GetArgumentTypeAsCString(
+ const lldb::CommandArgumentType arg_type) {
+ assert(arg_type < eArgTypeLastArg &&
+ "Invalid argument type passed to GetArgumentTypeAsCString");
+ return g_arguments_data[arg_type].arg_name;
+}
+
+const char *CommandObject::GetArgumentDescriptionAsCString(
+ const lldb::CommandArgumentType arg_type) {
+ assert(arg_type < eArgTypeLastArg &&
+ "Invalid argument type passed to GetArgumentDescriptionAsCString");
+ return g_arguments_data[arg_type].help_text;
+}
+
+Target *CommandObject::GetDummyTarget() {
+ return m_interpreter.GetDebugger().GetDummyTarget();
+}
+
+Target *CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) {
+ return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
+}
+
+Thread *CommandObject::GetDefaultThread() {
+ Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
+ if (thread_to_use)
+ return thread_to_use;
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ if (!process) {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (!target) {
+ target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ }
+ if (target)
+ process = target->GetProcessSP().get();
+ }
+
+ if (process)
+ return process->GetThreadList().GetSelectedThread().get();
+ else
+ return nullptr;
}
-static
-const char *arch_helper()
-{
- static StreamString g_archs_help;
- if (g_archs_help.Empty())
- {
- StringList archs;
- ArchSpec::AutoComplete(nullptr, archs);
- g_archs_help.Printf("These are the supported architecture names:\n");
- archs.Join("\n", g_archs_help);
- }
- return g_archs_help.GetData();
+bool CommandObjectParsed::Execute(const char *args_string,
+ CommandReturnObject &result) {
+ bool handled = false;
+ Args cmd_args(args_string);
+ if (HasOverrideCallback()) {
+ Args full_args(GetCommandName());
+ full_args.AppendArguments(cmd_args);
+ handled =
+ InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
+ }
+ if (!handled) {
+ for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i) {
+ const char *tmp_str = cmd_args.GetArgumentAtIndex(i);
+ if (tmp_str[0] == '`') // back-quote
+ cmd_args.ReplaceArgumentAtIndex(
+ i, m_interpreter.ProcessEmbeddedScriptCommands(tmp_str));
+ }
+
+ if (CheckRequirements(result)) {
+ if (ParseOptions(cmd_args, result)) {
+ // Call the command-specific version of 'Execute', passing it the
+ // already processed arguments.
+ handled = DoExecute(cmd_args, result);
+ }
+ }
+
+ Cleanup();
+ }
+ return handled;
+}
+
+bool CommandObjectRaw::Execute(const char *args_string,
+ CommandReturnObject &result) {
+ bool handled = false;
+ if (HasOverrideCallback()) {
+ std::string full_command(GetCommandName());
+ full_command += ' ';
+ full_command += args_string;
+ const char *argv[2] = {nullptr, nullptr};
+ argv[0] = full_command.c_str();
+ handled = InvokeOverrideCallback(argv, result);
+ }
+ if (!handled) {
+ if (CheckRequirements(result))
+ handled = DoExecute(args_string, result);
+
+ Cleanup();
+ }
+ return handled;
+}
+
+static const char *arch_helper() {
+ static StreamString g_archs_help;
+ if (g_archs_help.Empty()) {
+ StringList archs;
+ ArchSpec::AutoComplete(nullptr, archs);
+ g_archs_help.Printf("These are the supported architecture names:\n");
+ archs.Join("\n", g_archs_help);
+ }
+ return g_archs_help.GetData();
}
CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
@@ -1204,12 +1137,10 @@ CommandObject::ArgumentTableEntry Comman
// clang-format on
};
-const CommandObject::ArgumentTableEntry*
-CommandObject::GetArgumentTable ()
-{
- // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration
- assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
- return CommandObject::g_arguments_data;
+const CommandObject::ArgumentTableEntry *CommandObject::GetArgumentTable() {
+ // If this assertion fires, then the table above is out of date with the
+ // CommandArgumentType enumeration
+ assert((sizeof(CommandObject::g_arguments_data) /
+ sizeof(CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
+ return CommandObject::g_arguments_data;
}
-
-
Modified: lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp Tue Sep 6 15:57:50 2016
@@ -22,129 +22,99 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// CommandObjectRegexCommand constructor
//----------------------------------------------------------------------
-CommandObjectRegexCommand::CommandObjectRegexCommand
-(
- CommandInterpreter &interpreter,
- const char *name,
- const char *help,
- const char *syntax,
- uint32_t max_matches,
- uint32_t completion_type_mask,
- bool is_removable
-) :
- CommandObjectRaw (interpreter, name, help, syntax),
- m_max_matches (max_matches),
- m_completion_type_mask (completion_type_mask),
- m_entries (),
- m_is_removable (is_removable)
-{
-}
+CommandObjectRegexCommand::CommandObjectRegexCommand(
+ CommandInterpreter &interpreter, const char *name, const char *help,
+ const char *syntax, uint32_t max_matches, uint32_t completion_type_mask,
+ bool is_removable)
+ : CommandObjectRaw(interpreter, name, help, syntax),
+ m_max_matches(max_matches), m_completion_type_mask(completion_type_mask),
+ m_entries(), m_is_removable(is_removable) {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-CommandObjectRegexCommand::~CommandObjectRegexCommand()
-{
-}
-
+CommandObjectRegexCommand::~CommandObjectRegexCommand() {}
-bool
-CommandObjectRegexCommand::DoExecute
-(
- const char *command,
- CommandReturnObject &result
-)
-{
- if (command)
- {
- EntryCollection::const_iterator pos, end = m_entries.end();
- for (pos = m_entries.begin(); pos != end; ++pos)
- {
- RegularExpression::Match regex_match(m_max_matches);
-
- if (pos->regex.Execute (command, ®ex_match))
- {
- std::string new_command(pos->command);
- std::string match_str;
- char percent_var[8];
- size_t idx, percent_var_idx;
- for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx)
- {
- if (regex_match.GetMatchAtIndex (command, match_idx, match_str))
- {
- const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx);
- for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; )
- {
- new_command.erase(percent_var_idx, percent_var_len);
- new_command.insert(percent_var_idx, match_str);
- idx += percent_var_idx + match_str.size();
- }
- }
- }
- // Interpret the new command and return this as the result!
- if (m_interpreter.GetExpandRegexAliases())
- result.GetOutputStream().Printf("%s\n", new_command.c_str());
- // Pass in true for "no context switching". The command that called us should have set up the context
- // appropriately, we shouldn't have to redo that.
- return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true);
+bool CommandObjectRegexCommand::DoExecute(const char *command,
+ CommandReturnObject &result) {
+ if (command) {
+ EntryCollection::const_iterator pos, end = m_entries.end();
+ for (pos = m_entries.begin(); pos != end; ++pos) {
+ RegularExpression::Match regex_match(m_max_matches);
+
+ if (pos->regex.Execute(command, ®ex_match)) {
+ std::string new_command(pos->command);
+ std::string match_str;
+ char percent_var[8];
+ size_t idx, percent_var_idx;
+ for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) {
+ if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) {
+ const int percent_var_len =
+ ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx);
+ for (idx = 0; (percent_var_idx = new_command.find(
+ percent_var, idx)) != std::string::npos;) {
+ new_command.erase(percent_var_idx, percent_var_len);
+ new_command.insert(percent_var_idx, match_str);
+ idx += percent_var_idx + match_str.size();
}
+ }
}
- result.SetStatus(eReturnStatusFailed);
- if (GetSyntax() != nullptr)
- result.AppendError (GetSyntax());
- else
- result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
- command,
- m_cmd_name.c_str());
- return false;
+ // Interpret the new command and return this as the result!
+ if (m_interpreter.GetExpandRegexAliases())
+ result.GetOutputStream().Printf("%s\n", new_command.c_str());
+ // Pass in true for "no context switching". The command that called us
+ // should have set up the context
+ // appropriately, we shouldn't have to redo that.
+ return m_interpreter.HandleCommand(new_command.c_str(),
+ eLazyBoolCalculate, result, nullptr,
+ true, true);
+ }
}
- result.AppendError("empty command passed to regular expression command");
result.SetStatus(eReturnStatusFailed);
+ if (GetSyntax() != nullptr)
+ result.AppendError(GetSyntax());
+ else
+ result.AppendErrorWithFormat("Command contents '%s' failed to match any "
+ "regular expression in the '%s' regex "
+ "command.\n",
+ command, m_cmd_name.c_str());
return false;
+ }
+ result.AppendError("empty command passed to regular expression command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
-
-bool
-CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *command_cstr)
-{
- m_entries.resize(m_entries.size() + 1);
- // Only add the regular expression if it compiles
- if (m_entries.back().regex.Compile (re_cstr))
- {
- m_entries.back().command.assign (command_cstr);
- return true;
- }
- // The regex didn't compile...
- m_entries.pop_back();
- return false;
+bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr,
+ const char *command_cstr) {
+ m_entries.resize(m_entries.size() + 1);
+ // Only add the regular expression if it compiles
+ if (m_entries.back().regex.Compile(re_cstr)) {
+ m_entries.back().command.assign(command_cstr);
+ return true;
+ }
+ // The regex didn't compile...
+ m_entries.pop_back();
+ return false;
}
-int
-CommandObjectRegexCommand::HandleCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- if (m_completion_type_mask)
- {
- std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
- CommandCompletions::InvokeCommonCompletionCallbacks (GetCommandInterpreter(),
- m_completion_type_mask,
- completion_str.c_str(),
- match_start_point,
- max_return_elements,
- nullptr,
- word_complete,
- matches);
- return matches.GetSize();
- }
- else
- {
- matches.Clear();
- word_complete = false;
- }
- return 0;
+int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) {
+ if (m_completion_type_mask) {
+ std::string completion_str(input.GetArgumentAtIndex(cursor_index),
+ cursor_char_position);
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
+ match_start_point, max_return_elements, nullptr, word_complete,
+ matches);
+ return matches.GetSize();
+ } else {
+ matches.Clear();
+ word_complete = false;
+ }
+ return 0;
}
Modified: lldb/trunk/source/Interpreter/CommandObjectScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectScript.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectScript.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectScript.cpp Tue Sep 6 15:57:50 2016
@@ -30,61 +30,57 @@ using namespace lldb_private;
// CommandObjectScript
//-------------------------------------------------------------------------
-CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter, ScriptLanguage script_lang)
- : CommandObjectRaw(interpreter, "script", "Invoke the script interpreter with provided code and display any "
- "results. Start the interactive interpreter if no code is supplied.",
- "script [<script-code>]")
-{
-}
+CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter,
+ ScriptLanguage script_lang)
+ : CommandObjectRaw(
+ interpreter, "script",
+ "Invoke the script interpreter with provided code and display any "
+ "results. Start the interactive interpreter if no code is supplied.",
+ "script [<script-code>]") {}
-CommandObjectScript::~CommandObjectScript ()
-{
-}
+CommandObjectScript::~CommandObjectScript() {}
-bool
-CommandObjectScript::DoExecute
-(
- const char *command,
- CommandReturnObject &result
-)
-{
+bool CommandObjectScript::DoExecute(const char *command,
+ CommandReturnObject &result) {
#ifdef LLDB_DISABLE_PYTHON
- // if we ever support languages other than Python this simple #ifdef won't work
- result.AppendError("your copy of LLDB does not support scripting.");
- result.SetStatus (eReturnStatusFailed);
- return false;
+ // if we ever support languages other than Python this simple #ifdef won't
+ // work
+ result.AppendError("your copy of LLDB does not support scripting.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
#else
- if (m_interpreter.GetDebugger().GetScriptLanguage() == lldb::eScriptLanguageNone)
- {
- result.AppendError("the script-lang setting is set to none - scripting not available");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter ();
-
- if (script_interpreter == nullptr)
- {
- result.AppendError("no script interpreter");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- DataVisualization::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
-
- if (command == nullptr || command[0] == '\0')
- {
- script_interpreter->ExecuteInterpreterLoop ();
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
-
- // We can do better when reporting the status of one-liner script execution.
- if (script_interpreter->ExecuteOneLine (command, &result))
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- else
- result.SetStatus(eReturnStatusFailed);
+ if (m_interpreter.GetDebugger().GetScriptLanguage() ==
+ lldb::eScriptLanguageNone) {
+ result.AppendError(
+ "the script-lang setting is set to none - scripting not available");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter();
+ if (script_interpreter == nullptr) {
+ result.AppendError("no script interpreter");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ DataVisualization::ForceUpdate(); // script might change Python code we use
+ // for formatting.. make sure we keep up to
+ // date with it
+
+ if (command == nullptr || command[0] == '\0') {
+ script_interpreter->ExecuteInterpreterLoop();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
+ }
+
+ // We can do better when reporting the status of one-liner script execution.
+ if (script_interpreter->ExecuteOneLine(command, &result))
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return result.Succeeded();
#endif
}
Modified: lldb/trunk/source/Interpreter/CommandObjectScript.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectScript.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectScript.h (original)
+++ lldb/trunk/source/Interpreter/CommandObjectScript.h Tue Sep 6 15:57:50 2016
@@ -22,17 +22,15 @@ namespace lldb_private {
// CommandObjectScript
//-------------------------------------------------------------------------
-class CommandObjectScript : public CommandObjectRaw
-{
+class CommandObjectScript : public CommandObjectRaw {
public:
- CommandObjectScript(CommandInterpreter &interpreter,
- lldb::ScriptLanguage script_lang);
+ CommandObjectScript(CommandInterpreter &interpreter,
+ lldb::ScriptLanguage script_lang);
- ~CommandObjectScript() override;
+ ~CommandObjectScript() override;
protected:
- bool
- DoExecute(const char *command, CommandReturnObject &result) override;
+ bool DoExecute(const char *command, CommandReturnObject &result) override;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Interpreter/CommandOptionValidators.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandOptionValidators.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandOptionValidators.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandOptionValidators.cpp Tue Sep 6 15:57:50 2016
@@ -15,25 +15,23 @@
using namespace lldb;
using namespace lldb_private;
-bool PosixPlatformCommandOptionValidator::IsValid(Platform &platform, const ExecutionContext &target) const
-{
- llvm::Triple::OSType os = platform.GetSystemArchitecture().GetTriple().getOS();
- switch (os)
- {
- // Are there any other platforms that are not POSIX-compatible?
- case llvm::Triple::Win32:
- return false;
- default:
- return true;
- }
+bool PosixPlatformCommandOptionValidator::IsValid(
+ Platform &platform, const ExecutionContext &target) const {
+ llvm::Triple::OSType os =
+ platform.GetSystemArchitecture().GetTriple().getOS();
+ switch (os) {
+ // Are there any other platforms that are not POSIX-compatible?
+ case llvm::Triple::Win32:
+ return false;
+ default:
+ return true;
+ }
}
-const char* PosixPlatformCommandOptionValidator::ShortConditionString() const
-{
- return "POSIX";
+const char *PosixPlatformCommandOptionValidator::ShortConditionString() const {
+ return "POSIX";
}
-const char* PosixPlatformCommandOptionValidator::LongConditionString() const
-{
- return "Option only valid for POSIX-compliant hosts.";
+const char *PosixPlatformCommandOptionValidator::LongConditionString() const {
+ return "Option only valid for POSIX-compliant hosts.";
}
Modified: lldb/trunk/source/Interpreter/CommandReturnObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandReturnObject.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandReturnObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandReturnObject.cpp Tue Sep 6 15:57:50 2016
@@ -19,218 +19,154 @@
using namespace lldb;
using namespace lldb_private;
-static void
-DumpStringToStreamWithNewline (Stream &strm, const std::string &s, bool add_newline_if_empty)
-{
- bool add_newline = false;
- if (s.empty())
- {
- add_newline = add_newline_if_empty;
- }
- else
- {
- // We already checked for empty above, now make sure there is a newline
- // in the error, and if there isn't one, add one.
- strm.Write(s.c_str(), s.size());
-
- const char last_char = *s.rbegin();
- add_newline = last_char != '\n' && last_char != '\r';
-
- }
- if (add_newline)
- strm.EOL();
-}
-
-
-CommandReturnObject::CommandReturnObject () :
- m_out_stream (),
- m_err_stream (),
- m_status (eReturnStatusStarted),
- m_did_change_process_state (false),
- m_interactive (true),
- m_abnormal_stop_was_expected(false)
-{
-}
-
-CommandReturnObject::~CommandReturnObject ()
-{
-}
-
-void
-CommandReturnObject::AppendErrorWithFormat (const char *format, ...)
-{
- if (!format)
- return;
- va_list args;
- va_start (args, format);
- StreamString sstrm;
- sstrm.PrintfVarArg(format, args);
- va_end (args);
-
-
- const std::string &s = sstrm.GetString();
- if (!s.empty())
- {
- Stream &error_strm = GetErrorStream();
- error_strm.PutCString ("error: ");
- DumpStringToStreamWithNewline (error_strm, s, false);
- }
-}
-
-void
-CommandReturnObject::AppendMessageWithFormat (const char *format, ...)
-{
- if (!format)
- return;
- va_list args;
- va_start (args, format);
- StreamString sstrm;
- sstrm.PrintfVarArg(format, args);
- va_end (args);
-
- GetOutputStream().Printf("%s", sstrm.GetData());
-}
-
-void
-CommandReturnObject::AppendWarningWithFormat (const char *format, ...)
-{
- if (!format)
- return;
- va_list args;
- va_start (args, format);
- StreamString sstrm;
- sstrm.PrintfVarArg(format, args);
- va_end (args);
-
- GetErrorStream().Printf("warning: %s", sstrm.GetData());
-}
-
-void
-CommandReturnObject::AppendMessage (const char *in_string)
-{
- if (!in_string)
- return;
- GetOutputStream().Printf("%s\n", in_string);
-}
-
-void
-CommandReturnObject::AppendWarning (const char *in_string)
-{
- if (!in_string || *in_string == '\0')
- return;
- GetErrorStream().Printf("warning: %s\n", in_string);
+static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s,
+ bool add_newline_if_empty) {
+ bool add_newline = false;
+ if (s.empty()) {
+ add_newline = add_newline_if_empty;
+ } else {
+ // We already checked for empty above, now make sure there is a newline
+ // in the error, and if there isn't one, add one.
+ strm.Write(s.c_str(), s.size());
+
+ const char last_char = *s.rbegin();
+ add_newline = last_char != '\n' && last_char != '\r';
+ }
+ if (add_newline)
+ strm.EOL();
+}
+
+CommandReturnObject::CommandReturnObject()
+ : m_out_stream(), m_err_stream(), m_status(eReturnStatusStarted),
+ m_did_change_process_state(false), m_interactive(true),
+ m_abnormal_stop_was_expected(false) {}
+
+CommandReturnObject::~CommandReturnObject() {}
+
+void CommandReturnObject::AppendErrorWithFormat(const char *format, ...) {
+ if (!format)
+ return;
+ va_list args;
+ va_start(args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end(args);
+
+ const std::string &s = sstrm.GetString();
+ if (!s.empty()) {
+ Stream &error_strm = GetErrorStream();
+ error_strm.PutCString("error: ");
+ DumpStringToStreamWithNewline(error_strm, s, false);
+ }
+}
+
+void CommandReturnObject::AppendMessageWithFormat(const char *format, ...) {
+ if (!format)
+ return;
+ va_list args;
+ va_start(args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end(args);
+
+ GetOutputStream().Printf("%s", sstrm.GetData());
+}
+
+void CommandReturnObject::AppendWarningWithFormat(const char *format, ...) {
+ if (!format)
+ return;
+ va_list args;
+ va_start(args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end(args);
+
+ GetErrorStream().Printf("warning: %s", sstrm.GetData());
+}
+
+void CommandReturnObject::AppendMessage(const char *in_string) {
+ if (!in_string)
+ return;
+ GetOutputStream().Printf("%s\n", in_string);
+}
+
+void CommandReturnObject::AppendWarning(const char *in_string) {
+ if (!in_string || *in_string == '\0')
+ return;
+ GetErrorStream().Printf("warning: %s\n", in_string);
}
// Similar to AppendWarning, but do not prepend 'warning: ' to message, and
// don't append "\n" to the end of it.
-void
-CommandReturnObject::AppendRawWarning (const char *in_string)
-{
- if (in_string && in_string[0])
- GetErrorStream().PutCString(in_string);
-}
-
-void
-CommandReturnObject::AppendError (const char *in_string)
-{
- if (!in_string || *in_string == '\0')
- return;
- GetErrorStream().Printf ("error: %s\n", in_string);
-}
-
-void
-CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr)
-{
- const char *error_cstr = error.AsCString();
- if (error_cstr == nullptr)
- error_cstr = fallback_error_cstr;
- SetError(error_cstr);
-}
-
-void
-CommandReturnObject::SetError (const char *error_cstr)
-{
- if (error_cstr)
- {
- AppendError (error_cstr);
- SetStatus (eReturnStatusFailed);
- }
+void CommandReturnObject::AppendRawWarning(const char *in_string) {
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(in_string);
+}
+
+void CommandReturnObject::AppendError(const char *in_string) {
+ if (!in_string || *in_string == '\0')
+ return;
+ GetErrorStream().Printf("error: %s\n", in_string);
+}
+
+void CommandReturnObject::SetError(const Error &error,
+ const char *fallback_error_cstr) {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr == nullptr)
+ error_cstr = fallback_error_cstr;
+ SetError(error_cstr);
+}
+
+void CommandReturnObject::SetError(const char *error_cstr) {
+ if (error_cstr) {
+ AppendError(error_cstr);
+ SetStatus(eReturnStatusFailed);
+ }
}
// Similar to AppendError, but do not prepend 'Error: ' to message, and
// don't append "\n" to the end of it.
-void
-CommandReturnObject::AppendRawError (const char *in_string)
-{
- if (in_string && in_string[0])
- GetErrorStream().PutCString(in_string);
+void CommandReturnObject::AppendRawError(const char *in_string) {
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(in_string);
}
-void
-CommandReturnObject::SetStatus (ReturnStatus status)
-{
- m_status = status;
-}
-
-ReturnStatus
-CommandReturnObject::GetStatus ()
-{
- return m_status;
-}
+void CommandReturnObject::SetStatus(ReturnStatus status) { m_status = status; }
-bool
-CommandReturnObject::Succeeded ()
-{
- return m_status <= eReturnStatusSuccessContinuingResult;
-}
+ReturnStatus CommandReturnObject::GetStatus() { return m_status; }
-bool
-CommandReturnObject::HasResult ()
-{
- return (m_status == eReturnStatusSuccessFinishResult ||
- m_status == eReturnStatusSuccessContinuingResult);
+bool CommandReturnObject::Succeeded() {
+ return m_status <= eReturnStatusSuccessContinuingResult;
}
-void
-CommandReturnObject::Clear()
-{
- lldb::StreamSP stream_sp;
- stream_sp = m_out_stream.GetStreamAtIndex (eStreamStringIndex);
- if (stream_sp)
- static_cast<StreamString *>(stream_sp.get())->Clear();
- stream_sp = m_err_stream.GetStreamAtIndex (eStreamStringIndex);
- if (stream_sp)
- static_cast<StreamString *>(stream_sp.get())->Clear();
- m_status = eReturnStatusStarted;
- m_did_change_process_state = false;
- m_interactive = true;
+bool CommandReturnObject::HasResult() {
+ return (m_status == eReturnStatusSuccessFinishResult ||
+ m_status == eReturnStatusSuccessContinuingResult);
}
-bool
-CommandReturnObject::GetDidChangeProcessState ()
-{
- return m_did_change_process_state;
+void CommandReturnObject::Clear() {
+ lldb::StreamSP stream_sp;
+ stream_sp = m_out_stream.GetStreamAtIndex(eStreamStringIndex);
+ if (stream_sp)
+ static_cast<StreamString *>(stream_sp.get())->Clear();
+ stream_sp = m_err_stream.GetStreamAtIndex(eStreamStringIndex);
+ if (stream_sp)
+ static_cast<StreamString *>(stream_sp.get())->Clear();
+ m_status = eReturnStatusStarted;
+ m_did_change_process_state = false;
+ m_interactive = true;
}
-void
-CommandReturnObject::SetDidChangeProcessState (bool b)
-{
- m_did_change_process_state = b;
-}
-
-
-bool
-CommandReturnObject::GetInteractive () const
-{
- return m_interactive;
+bool CommandReturnObject::GetDidChangeProcessState() {
+ return m_did_change_process_state;
}
-void
-CommandReturnObject::SetInteractive (bool b)
-{
- m_interactive = b;
+void CommandReturnObject::SetDidChangeProcessState(bool b) {
+ m_did_change_process_state = b;
}
+bool CommandReturnObject::GetInteractive() const { return m_interactive; }
+void CommandReturnObject::SetInteractive(bool b) { m_interactive = b; }
Modified: lldb/trunk/source/Interpreter/OptionGroupArchitecture.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupArchitecture.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupArchitecture.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupArchitecture.cpp Tue Sep 6 15:57:50 2016
@@ -18,70 +18,53 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupArchitecture::OptionGroupArchitecture() :
- m_arch_str ()
-{
-}
+OptionGroupArchitecture::OptionGroupArchitecture() : m_arch_str() {}
-OptionGroupArchitecture::~OptionGroupArchitecture ()
-{
-}
+OptionGroupArchitecture::~OptionGroupArchitecture() {}
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1 , false, "arch" , 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "arch", 'a', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeArchitecture,
+ "Specify the architecture for the target."},
};
-uint32_t
-OptionGroupArchitecture::GetNumDefinitions ()
-{
- return llvm::array_lengthof(g_option_table);
+uint32_t OptionGroupArchitecture::GetNumDefinitions() {
+ return llvm::array_lengthof(g_option_table);
}
-const OptionDefinition *
-OptionGroupArchitecture::GetDefinitions ()
-{
- return g_option_table;
+const OptionDefinition *OptionGroupArchitecture::GetDefinitions() {
+ return g_option_table;
}
-bool
-OptionGroupArchitecture::GetArchitecture (Platform *platform, ArchSpec &arch)
-{
- if (m_arch_str.empty())
- arch.Clear();
- else
- arch.SetTriple(m_arch_str.c_str(), platform);
- return arch.IsValid();
+bool OptionGroupArchitecture::GetArchitecture(Platform *platform,
+ ArchSpec &arch) {
+ if (m_arch_str.empty())
+ arch.Clear();
+ else
+ arch.SetTriple(m_arch_str.c_str(), platform);
+ return arch.IsValid();
}
+Error OptionGroupArchitecture::SetOptionValue(
+ uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
-Error
-OptionGroupArchitecture::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
-
- switch (short_option)
- {
- case 'a':
- m_arch_str.assign (option_arg);
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
+ switch (short_option) {
+ case 'a':
+ m_arch_str.assign(option_arg);
+ break;
- return error;
-}
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
-void
-OptionGroupArchitecture::OptionParsingStarting(
- ExecutionContext *execution_context)
-{
- m_arch_str.clear();
+ return error;
}
+void OptionGroupArchitecture::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_arch_str.clear();
+}
Modified: lldb/trunk/source/Interpreter/OptionGroupBoolean.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupBoolean.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupBoolean.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupBoolean.cpp Tue Sep 6 15:57:50 2016
@@ -17,52 +17,44 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask,
- bool required,
- const char *long_option,
- int short_option,
- const char *usage_text,
- bool default_value,
- bool no_argument_toggle_default) :
- m_value (default_value, default_value)
-{
- m_option_definition.usage_mask = usage_mask;
- m_option_definition.required = required;
- m_option_definition.long_option = long_option;
- m_option_definition.short_option = short_option;
- m_option_definition.validator = nullptr;
- m_option_definition.option_has_arg = no_argument_toggle_default ? OptionParser::eNoArgument : OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
- m_option_definition.completion_type = 0;
- m_option_definition.argument_type = eArgTypeBoolean;
- m_option_definition.usage_text = usage_text;
+OptionGroupBoolean::OptionGroupBoolean(uint32_t usage_mask, bool required,
+ const char *long_option,
+ int short_option, const char *usage_text,
+ bool default_value,
+ bool no_argument_toggle_default)
+ : m_value(default_value, default_value) {
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
+ m_option_definition.option_has_arg = no_argument_toggle_default
+ ? OptionParser::eNoArgument
+ : OptionParser::eRequiredArgument;
+ m_option_definition.enum_values = nullptr;
+ m_option_definition.completion_type = 0;
+ m_option_definition.argument_type = eArgTypeBoolean;
+ m_option_definition.usage_text = usage_text;
}
-OptionGroupBoolean::~OptionGroupBoolean ()
-{
-}
+OptionGroupBoolean::~OptionGroupBoolean() {}
-Error
-OptionGroupBoolean::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- if (m_option_definition.option_has_arg == OptionParser::eNoArgument)
- {
- // Not argument, toggle the default value and mark the option as having been set
- m_value.SetCurrentValue (!m_value.GetDefaultValue());
- m_value.SetOptionWasSet ();
- }
- else
- {
- error = m_value.SetValueFromString (option_arg);
- }
- return error;
+Error OptionGroupBoolean::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ if (m_option_definition.option_has_arg == OptionParser::eNoArgument) {
+ // Not argument, toggle the default value and mark the option as having been
+ // set
+ m_value.SetCurrentValue(!m_value.GetDefaultValue());
+ m_value.SetOptionWasSet();
+ } else {
+ error = m_value.SetValueFromString(option_arg);
+ }
+ return error;
}
-void
-OptionGroupBoolean::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_value.Clear();
+void OptionGroupBoolean::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_value.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupFile.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupFile.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupFile.cpp Tue Sep 6 15:57:50 2016
@@ -17,83 +17,65 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupFile::OptionGroupFile (uint32_t usage_mask,
- bool required,
- const char *long_option,
- int short_option,
- uint32_t completion_type,
- lldb::CommandArgumentType argument_type,
- const char *usage_text) :
- m_file ()
-{
- m_option_definition.usage_mask = usage_mask;
- m_option_definition.required = required;
- m_option_definition.long_option = long_option;
- m_option_definition.short_option = short_option;
- m_option_definition.validator = nullptr;
- m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
- m_option_definition.completion_type = completion_type;
- m_option_definition.argument_type = argument_type;
- m_option_definition.usage_text = usage_text;
-}
-
-OptionGroupFile::~OptionGroupFile ()
-{
-}
-
-Error
-OptionGroupFile::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error (m_file.SetValueFromString (option_arg));
- return error;
-}
-
-void
-OptionGroupFile::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_file.Clear();
-}
-
-
-OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask,
- bool required,
- const char *long_option,
- int short_option,
- uint32_t completion_type,
- lldb::CommandArgumentType argument_type,
- const char *usage_text) :
- m_file_list ()
-{
- m_option_definition.usage_mask = usage_mask;
- m_option_definition.required = required;
- m_option_definition.long_option = long_option;
- m_option_definition.short_option = short_option;
- m_option_definition.validator = nullptr;
- m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
- m_option_definition.completion_type = completion_type;
- m_option_definition.argument_type = argument_type;
- m_option_definition.usage_text = usage_text;
-}
-
-OptionGroupFileList::~OptionGroupFileList ()
-{
-}
-
-Error
-OptionGroupFileList::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error (m_file_list.SetValueFromString (option_arg));
- return error;
-}
-
-void
-OptionGroupFileList::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_file_list.Clear();
+OptionGroupFile::OptionGroupFile(uint32_t usage_mask, bool required,
+ const char *long_option, int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text)
+ : m_file() {
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
+ m_option_definition.enum_values = nullptr;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupFile::~OptionGroupFile() {}
+
+Error OptionGroupFile::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error(m_file.SetValueFromString(option_arg));
+ return error;
+}
+
+void OptionGroupFile::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_file.Clear();
+}
+
+OptionGroupFileList::OptionGroupFileList(
+ uint32_t usage_mask, bool required, const char *long_option,
+ int short_option, uint32_t completion_type,
+ lldb::CommandArgumentType argument_type, const char *usage_text)
+ : m_file_list() {
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
+ m_option_definition.enum_values = nullptr;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupFileList::~OptionGroupFileList() {}
+
+Error OptionGroupFileList::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error(m_file_list.SetValueFromString(option_arg));
+ return error;
+}
+
+void OptionGroupFileList::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_file_list.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupFormat.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupFormat.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupFormat.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupFormat.cpp Tue Sep 6 15:57:50 2016
@@ -22,251 +22,263 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupFormat::OptionGroupFormat (lldb::Format default_format,
- uint64_t default_byte_size,
- uint64_t default_count) :
- m_format (default_format, default_format),
- m_byte_size (default_byte_size, default_byte_size),
- m_count (default_count, default_count),
- m_prev_gdb_format('x'),
- m_prev_gdb_size('w')
-{
+OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
+ uint64_t default_byte_size,
+ uint64_t default_count)
+ : m_format(default_format, default_format),
+ m_byte_size(default_byte_size, default_byte_size),
+ m_count(default_count, default_count), m_prev_gdb_format('x'),
+ m_prev_gdb_size('w') {}
+
+OptionGroupFormat::~OptionGroupFormat() {}
+
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeFormat,
+ "Specify a format to be used for display."},
+ {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeGDBFormat,
+ "Specify a format using a GDB format specifier string."},
+ {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeByteSize,
+ "The size in bytes to use when displaying with the selected format."},
+ {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeCount,
+ "The number of total items to display."},
+};
+
+uint32_t OptionGroupFormat::GetNumDefinitions() {
+ if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
+ if (m_count.GetDefaultValue() < UINT64_MAX)
+ return 4;
+ else
+ return 3;
+ }
+ return 2;
}
-OptionGroupFormat::~OptionGroupFormat ()
-{
+const OptionDefinition *OptionGroupFormat::GetDefinitions() {
+ return g_option_table;
}
-static OptionDefinition
-g_option_table[] =
-{
-{ LLDB_OPT_SET_1, false, "format" ,'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFormat , "Specify a format to be used for display."},
-{ LLDB_OPT_SET_2, false, "gdb-format",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."},
-{ LLDB_OPT_SET_3, false, "size" ,'s', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."},
-{ LLDB_OPT_SET_4, false, "count" ,'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount , "The number of total items to display."},
-};
+Error OptionGroupFormat::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option) {
+ case 'f':
+ error = m_format.SetValueFromString(option_arg);
+ break;
+
+ case 'c':
+ if (m_count.GetDefaultValue() == 0) {
+ error.SetErrorString("--count option is disabled");
+ } else {
+ error = m_count.SetValueFromString(option_arg);
+ if (m_count.GetCurrentValue() == 0)
+ error.SetErrorStringWithFormat("invalid --count option value '%s'",
+ option_arg);
+ }
+ break;
-uint32_t
-OptionGroupFormat::GetNumDefinitions ()
-{
- if (m_byte_size.GetDefaultValue() < UINT64_MAX)
- {
- if (m_count.GetDefaultValue() < UINT64_MAX)
- return 4;
- else
- return 3;
+ case 's':
+ if (m_byte_size.GetDefaultValue() == 0) {
+ error.SetErrorString("--size option is disabled");
+ } else {
+ error = m_byte_size.SetValueFromString(option_arg);
+ if (m_byte_size.GetCurrentValue() == 0)
+ error.SetErrorStringWithFormat("invalid --size option value '%s'",
+ option_arg);
}
- return 2;
-}
+ break;
-const OptionDefinition *
-OptionGroupFormat::GetDefinitions ()
-{
- return g_option_table;
-}
+ case 'G': {
+ char *end = nullptr;
+ const char *gdb_format_cstr = option_arg;
+ uint64_t count = 0;
+ if (::isdigit(gdb_format_cstr[0])) {
+ count = strtoull(gdb_format_cstr, &end, 0);
+
+ if (option_arg != end)
+ gdb_format_cstr =
+ end; // We have a valid count, advance the string position
+ else
+ count = 0;
+ }
-Error
-OptionGroupFormat::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
+ Format format = eFormatDefault;
+ uint32_t byte_size = 0;
- switch (short_option)
- {
- case 'f':
- error = m_format.SetValueFromString (option_arg);
- break;
-
- case 'c':
- if (m_count.GetDefaultValue() == 0)
- {
- error.SetErrorString ("--count option is disabled");
- }
- else
- {
- error = m_count.SetValueFromString (option_arg);
- if (m_count.GetCurrentValue() == 0)
- error.SetErrorStringWithFormat("invalid --count option value '%s'", option_arg);
- }
- break;
-
- case 's':
- if (m_byte_size.GetDefaultValue() == 0)
- {
- error.SetErrorString ("--size option is disabled");
- }
- else
- {
- error = m_byte_size.SetValueFromString (option_arg);
- if (m_byte_size.GetCurrentValue() == 0)
- error.SetErrorStringWithFormat("invalid --size option value '%s'", option_arg);
- }
- break;
-
- case 'G':
- {
- char *end = nullptr;
- const char *gdb_format_cstr = option_arg;
- uint64_t count = 0;
- if (::isdigit (gdb_format_cstr[0]))
- {
- count = strtoull (gdb_format_cstr, &end, 0);
-
- if (option_arg != end)
- gdb_format_cstr = end; // We have a valid count, advance the string position
- else
- count = 0;
- }
-
- Format format = eFormatDefault;
- uint32_t byte_size = 0;
-
- while (ParserGDBFormatLetter (execution_context,
- gdb_format_cstr[0], format,
- byte_size))
- {
- ++gdb_format_cstr;
- }
-
- // We the first character of the "gdb_format_cstr" is not the
- // NULL terminator, we didn't consume the entire string and
- // something is wrong. Also, if none of the format, size or count
- // was specified correctly, then abort.
- if (gdb_format_cstr[0] || (format == eFormatInvalid && byte_size == 0 && count == 0))
- {
- // Nothing got set correctly
- error.SetErrorStringWithFormat ("invalid gdb format string '%s'", option_arg);
- return error;
- }
-
- // At least one of the format, size or count was set correctly.
- // Anything that wasn't set correctly should be set to the
- // previous default
- if (format == eFormatInvalid)
- ParserGDBFormatLetter (execution_context, m_prev_gdb_format,
- format, byte_size);
-
- const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
- const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
- if (byte_size_enabled)
- {
- // Byte size is enabled
- if (byte_size == 0)
- ParserGDBFormatLetter (execution_context, m_prev_gdb_size, format, byte_size);
- }
- else
- {
- // Byte size is disabled, make sure it wasn't specified
- // but if this is an address, it's actually necessary to
- // specify one so don't error out
- if (byte_size > 0 && format != lldb::eFormatAddressInfo)
- {
- error.SetErrorString ("this command doesn't support specifying a byte size");
- return error;
- }
- }
-
- if (count_enabled)
- {
- // Count is enabled and was not set, set it to the default for gdb format statements (which is 1).
- if (count == 0)
- count = 1;
- }
- else
- {
- // Count is disabled, make sure it wasn't specified
- if (count > 0)
- {
- error.SetErrorString ("this command doesn't support specifying a count");
- return error;
- }
- }
-
- m_format.SetCurrentValue (format);
- m_format.SetOptionWasSet ();
- if (byte_size_enabled)
- {
- m_byte_size.SetCurrentValue (byte_size);
- m_byte_size.SetOptionWasSet ();
- }
- if (count_enabled)
- {
- m_count.SetCurrentValue(count);
- m_count.SetOptionWasSet ();
- }
- }
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
+ while (ParserGDBFormatLetter(execution_context, gdb_format_cstr[0], format,
+ byte_size)) {
+ ++gdb_format_cstr;
}
- return error;
+ // We the first character of the "gdb_format_cstr" is not the
+ // NULL terminator, we didn't consume the entire string and
+ // something is wrong. Also, if none of the format, size or count
+ // was specified correctly, then abort.
+ if (gdb_format_cstr[0] ||
+ (format == eFormatInvalid && byte_size == 0 && count == 0)) {
+ // Nothing got set correctly
+ error.SetErrorStringWithFormat("invalid gdb format string '%s'",
+ option_arg);
+ return error;
+ }
+
+ // At least one of the format, size or count was set correctly.
+ // Anything that wasn't set correctly should be set to the
+ // previous default
+ if (format == eFormatInvalid)
+ ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
+ byte_size);
+
+ const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
+ const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
+ if (byte_size_enabled) {
+ // Byte size is enabled
+ if (byte_size == 0)
+ ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
+ byte_size);
+ } else {
+ // Byte size is disabled, make sure it wasn't specified
+ // but if this is an address, it's actually necessary to
+ // specify one so don't error out
+ if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
+ error.SetErrorString(
+ "this command doesn't support specifying a byte size");
+ return error;
+ }
+ }
+
+ if (count_enabled) {
+ // Count is enabled and was not set, set it to the default for gdb format
+ // statements (which is 1).
+ if (count == 0)
+ count = 1;
+ } else {
+ // Count is disabled, make sure it wasn't specified
+ if (count > 0) {
+ error.SetErrorString("this command doesn't support specifying a count");
+ return error;
+ }
+ }
+
+ m_format.SetCurrentValue(format);
+ m_format.SetOptionWasSet();
+ if (byte_size_enabled) {
+ m_byte_size.SetCurrentValue(byte_size);
+ m_byte_size.SetOptionWasSet();
+ }
+ if (count_enabled) {
+ m_count.SetCurrentValue(count);
+ m_count.SetOptionWasSet();
+ }
+ } break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
}
-bool
-OptionGroupFormat::ParserGDBFormatLetter(ExecutionContext *execution_context,
- char format_letter, Format &format,
- uint32_t &byte_size)
-{
- m_has_gdb_format = true;
- switch (format_letter)
+bool OptionGroupFormat::ParserGDBFormatLetter(
+ ExecutionContext *execution_context, char format_letter, Format &format,
+ uint32_t &byte_size) {
+ m_has_gdb_format = true;
+ switch (format_letter) {
+ case 'o':
+ format = eFormatOctal;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'x':
+ format = eFormatHex;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'd':
+ format = eFormatDecimal;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'u':
+ format = eFormatUnsigned;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 't':
+ format = eFormatBinary;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'f':
+ format = eFormatFloat;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'a':
+ format = eFormatAddressInfo;
{
- case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true;
- case 'x': format = eFormatHex; m_prev_gdb_format = format_letter; return true;
- case 'd': format = eFormatDecimal; m_prev_gdb_format = format_letter; return true;
- case 'u': format = eFormatUnsigned; m_prev_gdb_format = format_letter; return true;
- case 't': format = eFormatBinary; m_prev_gdb_format = format_letter; return true;
- case 'f': format = eFormatFloat; m_prev_gdb_format = format_letter; return true;
- case 'a': format = eFormatAddressInfo;
- {
- TargetSP target_sp = execution_context ?
- execution_context->GetTargetSP() : TargetSP();
- if (target_sp)
- byte_size = target_sp->GetArchitecture().GetAddressByteSize();
- m_prev_gdb_format = format_letter;
- return true;
- }
- case 'i': format = eFormatInstruction; m_prev_gdb_format = format_letter; return true;
- case 'c': format = eFormatChar; m_prev_gdb_format = format_letter; return true;
- case 's': format = eFormatCString; m_prev_gdb_format = format_letter; return true;
- case 'T': format = eFormatOSType; m_prev_gdb_format = format_letter; return true;
- case 'A': format = eFormatHexFloat; m_prev_gdb_format = format_letter; return true;
-
- // Size isn't used for printing instructions, so if a size is specified, and the previous format was
- // 'i', then we should reset it to the default ('x'). Otherwise we'll continue to print as instructions,
- // which isn't expected.
- case 'b':
- byte_size = 1;
- LLVM_FALLTHROUGH;
- case 'h':
- byte_size = 2;
- LLVM_FALLTHROUGH;
- case 'w':
- byte_size = 4;
- LLVM_FALLTHROUGH;
- case 'g':
- byte_size = 8;
-
- m_prev_gdb_size = format_letter;
- if (m_prev_gdb_format == 'i')
- m_prev_gdb_format = 'x';
- return true;
-
- break;
- default: break;
+ TargetSP target_sp =
+ execution_context ? execution_context->GetTargetSP() : TargetSP();
+ if (target_sp)
+ byte_size = target_sp->GetArchitecture().GetAddressByteSize();
+ m_prev_gdb_format = format_letter;
+ return true;
}
- return false;
+ case 'i':
+ format = eFormatInstruction;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'c':
+ format = eFormatChar;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 's':
+ format = eFormatCString;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'T':
+ format = eFormatOSType;
+ m_prev_gdb_format = format_letter;
+ return true;
+ case 'A':
+ format = eFormatHexFloat;
+ m_prev_gdb_format = format_letter;
+ return true;
+
+ // Size isn't used for printing instructions, so if a size is specified, and
+ // the previous format was
+ // 'i', then we should reset it to the default ('x'). Otherwise we'll
+ // continue to print as instructions,
+ // which isn't expected.
+ case 'b':
+ byte_size = 1;
+ LLVM_FALLTHROUGH;
+ case 'h':
+ byte_size = 2;
+ LLVM_FALLTHROUGH;
+ case 'w':
+ byte_size = 4;
+ LLVM_FALLTHROUGH;
+ case 'g':
+ byte_size = 8;
+
+ m_prev_gdb_size = format_letter;
+ if (m_prev_gdb_format == 'i')
+ m_prev_gdb_format = 'x';
+ return true;
+
+ break;
+ default:
+ break;
+ }
+ return false;
}
-void
-OptionGroupFormat::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_format.Clear();
- m_byte_size.Clear();
- m_count.Clear();
- m_has_gdb_format = false;
+void OptionGroupFormat::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_format.Clear();
+ m_byte_size.Clear();
+ m_count.Clear();
+ m_has_gdb_format = false;
}
Modified: lldb/trunk/source/Interpreter/OptionGroupOutputFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupOutputFile.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupOutputFile.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupOutputFile.cpp Tue Sep 6 15:57:50 2016
@@ -18,69 +18,55 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupOutputFile::OptionGroupOutputFile() :
- m_file (),
- m_append (false, false)
-{
-}
+OptionGroupOutputFile::OptionGroupOutputFile()
+ : m_file(), m_append(false, false) {}
-OptionGroupOutputFile::~OptionGroupOutputFile ()
-{
-}
+OptionGroupOutputFile::~OptionGroupOutputFile() {}
-static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd'
+static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd'
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1 , false, "outfile", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename , "Specify a path for capturing command output."},
- { LLDB_OPT_SET_1 , false, "append-outfile" , SHORT_OPTION_APND,
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone ,
- "Append to the file specified with '--outfile <path>'."},
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "outfile", 'o', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeFilename,
+ "Specify a path for capturing command output."},
+ {LLDB_OPT_SET_1, false, "append-outfile", SHORT_OPTION_APND,
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Append to the file specified with '--outfile <path>'."},
};
-uint32_t
-OptionGroupOutputFile::GetNumDefinitions ()
-{
- return llvm::array_lengthof(g_option_table);
+uint32_t OptionGroupOutputFile::GetNumDefinitions() {
+ return llvm::array_lengthof(g_option_table);
}
-const OptionDefinition *
-OptionGroupOutputFile::GetDefinitions ()
-{
- return g_option_table;
+const OptionDefinition *OptionGroupOutputFile::GetDefinitions() {
+ return g_option_table;
}
-Error
-OptionGroupOutputFile::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
-
- switch (short_option)
- {
- case 'o':
- error = m_file.SetValueFromString (option_arg);
- break;
-
- case SHORT_OPTION_APND:
- m_append.SetCurrentValue(true);
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
+Error OptionGroupOutputFile::SetOptionValue(
+ uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option) {
+ case 'o':
+ error = m_file.SetValueFromString(option_arg);
+ break;
+
+ case SHORT_OPTION_APND:
+ m_append.SetCurrentValue(true);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
- return error;
+ return error;
}
-void
-OptionGroupOutputFile::OptionParsingStarting(
- ExecutionContext *execution_context)
-{
- m_file.Clear();
- m_append.Clear();
+void OptionGroupOutputFile::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_file.Clear();
+ m_append.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp Tue Sep 6 15:57:50 2016
@@ -20,163 +20,145 @@
using namespace lldb;
using namespace lldb_private;
-PlatformSP
-OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter,
- const ArchSpec &arch,
- bool make_selected,
- Error& error,
- ArchSpec &platform_arch) const
-{
- PlatformSP platform_sp;
-
- if (!m_platform_name.empty())
- {
- platform_sp = Platform::Create (ConstString(m_platform_name.c_str()), error);
- if (platform_sp)
- {
- if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
- {
- error.SetErrorStringWithFormat ("platform '%s' doesn't support '%s'",
- platform_sp->GetName().GetCString(),
- arch.GetTriple().getTriple().c_str());
- platform_sp.reset();
- return platform_sp;
- }
- }
+PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
+ CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected,
+ Error &error, ArchSpec &platform_arch) const {
+ PlatformSP platform_sp;
+
+ if (!m_platform_name.empty()) {
+ platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error);
+ if (platform_sp) {
+ if (platform_arch.IsValid() &&
+ !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
+ error.SetErrorStringWithFormat("platform '%s' doesn't support '%s'",
+ platform_sp->GetName().GetCString(),
+ arch.GetTriple().getTriple().c_str());
+ platform_sp.reset();
+ return platform_sp;
+ }
}
- else if (arch.IsValid())
- {
- platform_sp = Platform::Create (arch, &platform_arch, error);
- }
-
- if (platform_sp)
- {
- interpreter.GetDebugger().GetPlatformList().Append (platform_sp, make_selected);
- if (m_os_version_major != UINT32_MAX)
- {
- platform_sp->SetOSVersion (m_os_version_major,
- m_os_version_minor,
- m_os_version_update);
- }
-
- if (m_sdk_sysroot)
- platform_sp->SetSDKRootDirectory (m_sdk_sysroot);
-
- if (m_sdk_build)
- platform_sp->SetSDKBuild (m_sdk_build);
+ } else if (arch.IsValid()) {
+ platform_sp = Platform::Create(arch, &platform_arch, error);
+ }
+
+ if (platform_sp) {
+ interpreter.GetDebugger().GetPlatformList().Append(platform_sp,
+ make_selected);
+ if (m_os_version_major != UINT32_MAX) {
+ platform_sp->SetOSVersion(m_os_version_major, m_os_version_minor,
+ m_os_version_update);
}
- return platform_sp;
-}
+ if (m_sdk_sysroot)
+ platform_sp->SetSDKRootDirectory(m_sdk_sysroot);
-void
-OptionGroupPlatform::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_platform_name.clear();
- m_sdk_sysroot.Clear();
- m_sdk_build.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
-}
-
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
- { LLDB_OPT_SET_ALL, false, "version" , 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
- { LLDB_OPT_SET_ALL, false, "build" , 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "Specify the initial SDK build number." },
- { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
-};
-
-const OptionDefinition*
-OptionGroupPlatform::GetDefinitions ()
-{
- if (m_include_platform_option)
- return g_option_table;
- return g_option_table + 1;
-}
-
-uint32_t
-OptionGroupPlatform::GetNumDefinitions ()
-{
- if (m_include_platform_option)
- return llvm::array_lengthof(g_option_table);
- return llvm::array_lengthof(g_option_table) - 1;
-}
-
-
-Error
-OptionGroupPlatform::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- if (!m_include_platform_option)
- ++option_idx;
-
- const int short_option = g_option_table[option_idx].short_option;
-
- switch (short_option)
- {
- case 'p':
- m_platform_name.assign (option_arg);
- break;
-
- case 'v':
- if (Args::StringToVersion (option_arg,
- m_os_version_major,
- m_os_version_minor,
- m_os_version_update) == option_arg)
- error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg);
- break;
-
- case 'b':
- m_sdk_build.SetCString (option_arg);
- break;
-
- case 'S':
- m_sdk_sysroot.SetCString (option_arg);
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
+ if (m_sdk_build)
+ platform_sp->SetSDKBuild(m_sdk_build);
+ }
+
+ return platform_sp;
+}
+
+void OptionGroupPlatform::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_platform_name.clear();
+ m_sdk_sysroot.Clear();
+ m_sdk_build.Clear();
+ m_os_version_major = UINT32_MAX;
+ m_os_version_minor = UINT32_MAX;
+ m_os_version_update = UINT32_MAX;
+}
+
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to "
+ "use for this target, creating the "
+ "platform if necessary."},
+ {LLDB_OPT_SET_ALL, false, "version", 'v', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeNone,
+ "Specify the initial SDK version to use prior to connecting."},
+ {LLDB_OPT_SET_ALL, false, "build", 'b', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeNone,
+ "Specify the initial SDK build number."},
+ {LLDB_OPT_SET_ALL, false, "sysroot", 'S', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory "
+ "that contains a root of all "
+ "remote system files."}};
+
+const OptionDefinition *OptionGroupPlatform::GetDefinitions() {
+ if (m_include_platform_option)
+ return g_option_table;
+ return g_option_table + 1;
+}
+
+uint32_t OptionGroupPlatform::GetNumDefinitions() {
+ if (m_include_platform_option)
+ return llvm::array_lengthof(g_option_table);
+ return llvm::array_lengthof(g_option_table) - 1;
+}
+
+Error OptionGroupPlatform::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ if (!m_include_platform_option)
+ ++option_idx;
+
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option) {
+ case 'p':
+ m_platform_name.assign(option_arg);
+ break;
+
+ case 'v':
+ if (Args::StringToVersion(option_arg, m_os_version_major,
+ m_os_version_minor,
+ m_os_version_update) == option_arg)
+ error.SetErrorStringWithFormat("invalid version string '%s'", option_arg);
+ break;
+
+ case 'b':
+ m_sdk_build.SetCString(option_arg);
+ break;
+
+ case 'S':
+ m_sdk_sysroot.SetCString(option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+}
+
+bool OptionGroupPlatform::PlatformMatches(
+ const lldb::PlatformSP &platform_sp) const {
+ if (platform_sp) {
+ if (!m_platform_name.empty()) {
+ if (platform_sp->GetName() != ConstString(m_platform_name.c_str()))
+ return false;
}
- return error;
-}
-bool
-OptionGroupPlatform::PlatformMatches(const lldb::PlatformSP &platform_sp) const
-{
- if (platform_sp)
- {
- if (!m_platform_name.empty())
- {
- if (platform_sp->GetName() != ConstString(m_platform_name.c_str()))
- return false;
- }
-
- if (m_sdk_build && m_sdk_build != platform_sp->GetSDKBuild())
- return false;
-
- if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory())
- return false;
-
- if (m_os_version_major != UINT32_MAX)
- {
- uint32_t major, minor, update;
- if (platform_sp->GetOSVersion (major, minor, update))
- {
- if (m_os_version_major != major)
- return false;
- if (m_os_version_minor != minor)
- return false;
- if (m_os_version_update != update)
- return false;
- }
- }
- return true;
+ if (m_sdk_build && m_sdk_build != platform_sp->GetSDKBuild())
+ return false;
+
+ if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory())
+ return false;
+
+ if (m_os_version_major != UINT32_MAX) {
+ uint32_t major, minor, update;
+ if (platform_sp->GetOSVersion(major, minor, update)) {
+ if (m_os_version_major != major)
+ return false;
+ if (m_os_version_minor != minor)
+ return false;
+ if (m_os_version_update != update)
+ return false;
+ }
}
- return false;
+ return true;
+ }
+ return false;
}
Modified: lldb/trunk/source/Interpreter/OptionGroupString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupString.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupString.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupString.cpp Tue Sep 6 15:57:50 2016
@@ -17,43 +17,35 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupString::OptionGroupString (uint32_t usage_mask,
- bool required,
- const char *long_option,
- int short_option,
- uint32_t completion_type,
- lldb::CommandArgumentType argument_type,
- const char *usage_text,
- const char *default_value) :
- m_value (default_value, default_value)
-{
- m_option_definition.usage_mask = usage_mask;
- m_option_definition.required = required;
- m_option_definition.long_option = long_option;
- m_option_definition.short_option = short_option;
- m_option_definition.validator = nullptr;
- m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
- m_option_definition.completion_type = completion_type;
- m_option_definition.argument_type = argument_type;
- m_option_definition.usage_text = usage_text;
+OptionGroupString::OptionGroupString(uint32_t usage_mask, bool required,
+ const char *long_option, int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text,
+ const char *default_value)
+ : m_value(default_value, default_value) {
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
+ m_option_definition.enum_values = nullptr;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
}
-OptionGroupString::~OptionGroupString ()
-{
-}
+OptionGroupString::~OptionGroupString() {}
-Error
-OptionGroupString::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error (m_value.SetValueFromString (option_arg));
- return error;
+Error OptionGroupString::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error(m_value.SetValueFromString(option_arg));
+ return error;
}
-void
-OptionGroupString::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_value.Clear();
+void OptionGroupString::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_value.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupUInt64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupUInt64.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupUInt64.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupUInt64.cpp Tue Sep 6 15:57:50 2016
@@ -17,43 +17,35 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupUInt64::OptionGroupUInt64 (uint32_t usage_mask,
- bool required,
- const char *long_option,
- int short_option,
- uint32_t completion_type,
- lldb::CommandArgumentType argument_type,
- const char *usage_text,
- uint64_t default_value) :
- m_value (default_value, default_value)
-{
- m_option_definition.usage_mask = usage_mask;
- m_option_definition.required = required;
- m_option_definition.long_option = long_option;
- m_option_definition.short_option = short_option;
- m_option_definition.validator = nullptr;
- m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
- m_option_definition.completion_type = completion_type;
- m_option_definition.argument_type = argument_type;
- m_option_definition.usage_text = usage_text;
+OptionGroupUInt64::OptionGroupUInt64(uint32_t usage_mask, bool required,
+ const char *long_option, int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text,
+ uint64_t default_value)
+ : m_value(default_value, default_value) {
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.validator = nullptr;
+ m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
+ m_option_definition.enum_values = nullptr;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
}
-OptionGroupUInt64::~OptionGroupUInt64 ()
-{
-}
+OptionGroupUInt64::~OptionGroupUInt64() {}
-Error
-OptionGroupUInt64::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error (m_value.SetValueFromString (option_arg));
- return error;
+Error OptionGroupUInt64::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error(m_value.SetValueFromString(option_arg));
+ return error;
}
-void
-OptionGroupUInt64::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_value.Clear();
+void OptionGroupUInt64::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_value.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupUUID.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupUUID.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupUUID.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupUUID.cpp Tue Sep 6 15:57:50 2016
@@ -18,59 +18,45 @@
using namespace lldb;
using namespace lldb_private;
-OptionGroupUUID::OptionGroupUUID() :
- m_uuid ()
-{
-}
+OptionGroupUUID::OptionGroupUUID() : m_uuid() {}
-OptionGroupUUID::~OptionGroupUUID ()
-{
-}
+OptionGroupUUID::~OptionGroupUUID() {}
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1 , false, "uuid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."},
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."},
};
-uint32_t
-OptionGroupUUID::GetNumDefinitions ()
-{
- return llvm::array_lengthof(g_option_table);
+uint32_t OptionGroupUUID::GetNumDefinitions() {
+ return llvm::array_lengthof(g_option_table);
}
-const OptionDefinition *
-OptionGroupUUID::GetDefinitions ()
-{
- return g_option_table;
+const OptionDefinition *OptionGroupUUID::GetDefinitions() {
+ return g_option_table;
}
-Error
-OptionGroupUUID::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
-
- switch (short_option)
- {
- case 'u':
- error = m_uuid.SetValueFromString (option_arg);
- if (error.Success())
- m_uuid.SetOptionWasSet();
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
+Error OptionGroupUUID::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option) {
+ case 'u':
+ error = m_uuid.SetValueFromString(option_arg);
+ if (error.Success())
+ m_uuid.SetOptionWasSet();
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
- return error;
+ return error;
}
-void
-OptionGroupUUID::OptionParsingStarting(ExecutionContext *execution_context)
-{
- m_uuid.Clear();
+void OptionGroupUUID::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_uuid.Clear();
}
Modified: lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp Tue Sep 6 15:57:50 2016
@@ -15,191 +15,209 @@
// Project includes
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Target/Target.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
using namespace lldb;
using namespace lldb_private;
-OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay()
-{
-}
+OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() {}
-OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay ()
-{
-}
+OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {}
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1, false, "dynamic-type", 'd', OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
- { LLDB_OPT_SET_1, false, "synthetic-type", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
- { LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
- { LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
- { LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable location information."},
- { LLDB_OPT_SET_1, false, "object-description", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print as an Objective-C object."},
- { LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
- { LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable types when dumping values."},
- { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
- { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."},
- { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
- { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr,0, eArgTypeBoolean, "Show results of type validators."},
- { LLDB_OPT_SET_1, false, "element-count", 'Z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Treat the result of the expression as if its type is an array of this many values."},
- { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
-};
-
-uint32_t
-OptionGroupValueObjectDisplay::GetNumDefinitions ()
-{
- return llvm::array_lengthof(g_option_table);
-}
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "dynamic-type", 'd',
+ OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0,
+ eArgTypeNone, "Show the object as its full dynamic type, not its static "
+ "type, if available."},
+ {LLDB_OPT_SET_1, false, "synthetic-type", 'S',
+ OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ "Show the object obeying its synthetic provider, if available."},
+ {LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when "
+ "dumping aggregate types (default is "
+ "infinity)."},
+ {LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr,
+ nullptr, 0, eArgTypeNone, "Display results in a flat format that uses "
+ "expression paths for each variable or member."},
+ {LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr,
+ nullptr, 0, eArgTypeNone, "Show variable location information."},
+ {LLDB_OPT_SET_1, false, "object-description", 'O',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Print as an Objective-C object."},
+ {LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be "
+ "traversed when dumping values "
+ "(default is zero)."},
+ {LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument,
+ nullptr, nullptr, 0, eArgTypeNone,
+ "Show variable types when dumping values."},
+ {LLDB_OPT_SET_1, false, "no-summary-depth", 'Y',
+ OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount,
+ "Set the depth at which omitting summary information stops (default is "
+ "1)."},
+ {LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument,
+ nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."},
+ {LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument,
+ nullptr, nullptr, 0, eArgTypeNone,
+ "Ignore the upper bound on the number of children to show."},
+ {LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."},
+ {LLDB_OPT_SET_1, false, "element-count", 'Z',
+ OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,
+ "Treat the result of the expression as if its type is an array of this "
+ "many values."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+
+uint32_t OptionGroupValueObjectDisplay::GetNumDefinitions() {
+ return llvm::array_lengthof(g_option_table);
+}
+
+const OptionDefinition *OptionGroupValueObjectDisplay::GetDefinitions() {
+ return g_option_table;
+}
+
+Error OptionGroupValueObjectDisplay::SetOptionValue(
+ uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+ bool success = false;
+
+ switch (short_option) {
+ case 'd': {
+ int32_t result;
+ result =
+ Args::StringToOptionEnum(option_arg, g_dynamic_value_types, 2, error);
+ if (error.Success())
+ use_dynamic = (lldb::DynamicValueType)result;
+ } break;
+ case 'T':
+ show_types = true;
+ break;
+ case 'L':
+ show_location = true;
+ break;
+ case 'F':
+ flat_output = true;
+ break;
+ case 'O':
+ use_objc = true;
+ break;
+ case 'R':
+ be_raw = true;
+ break;
+ case 'A':
+ ignore_cap = true;
+ break;
+
+ case 'D':
+ max_depth = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg);
+ break;
+
+ case 'Z':
+ elem_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid element count '%s'", option_arg);
+ break;
+
+ case 'P':
+ ptr_depth = StringConvert::ToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg);
+ break;
+
+ case 'Y':
+ if (option_arg) {
+ no_summary_depth = StringConvert::ToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid pointer depth '%s'",
+ option_arg);
+ } else
+ no_summary_depth = 1;
+ break;
+
+ case 'S':
+ use_synth = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg);
+ break;
+
+ case 'V':
+ run_validator = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid validate '%s'", option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void OptionGroupValueObjectDisplay::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ // If these defaults change, be sure to modify AnyOptionWasSet().
+ show_types = false;
+ no_summary_depth = 0;
+ show_location = false;
+ flat_output = false;
+ use_objc = false;
+ max_depth = UINT32_MAX;
+ ptr_depth = 0;
+ elem_count = 0;
+ use_synth = true;
+ be_raw = false;
+ ignore_cap = false;
+ run_validator = false;
+
+ TargetSP target_sp =
+ execution_context ? execution_context->GetTargetSP() : TargetSP();
+ if (target_sp)
+ use_dynamic = target_sp->GetPreferDynamicValue();
+ else {
+ // If we don't have any targets, then dynamic values won't do us much good.
+ use_dynamic = lldb::eNoDynamicValues;
+ }
+}
+
+DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions(
+ LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity,
+ lldb::Format format, lldb::TypeSummaryImplSP summary_sp) {
+ DumpValueObjectOptions options;
+ options.SetMaximumPointerDepth(
+ {DumpValueObjectOptions::PointerDepth::Mode::Always, ptr_depth});
+ if (use_objc)
+ options.SetShowSummary(false);
+ else
+ options.SetOmitSummaryDepth(no_summary_depth);
+ options.SetMaximumDepth(max_depth)
+ .SetShowTypes(show_types)
+ .SetShowLocation(show_location)
+ .SetUseObjectiveC(use_objc)
+ .SetUseDynamicType(use_dynamic)
+ .SetUseSyntheticValue(use_synth)
+ .SetFlatOutput(flat_output)
+ .SetIgnoreCap(ignore_cap)
+ .SetFormat(format)
+ .SetSummary(summary_sp);
+
+ if (lang_descr_verbosity ==
+ eLanguageRuntimeDescriptionDisplayVerbosityCompact)
+ options.SetHideRootType(use_objc).SetHideName(use_objc).SetHideValue(
+ use_objc);
-const OptionDefinition *
-OptionGroupValueObjectDisplay::GetDefinitions ()
-{
- return g_option_table;
-}
+ if (be_raw)
+ options.SetRawDisplay();
+ options.SetRunValidator(run_validator);
-Error
-OptionGroupValueObjectDisplay::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext
- *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
- bool success = false;
-
- switch (short_option)
- {
- case 'd':
- {
- int32_t result;
- result = Args::StringToOptionEnum (option_arg, g_dynamic_value_types, 2, error);
- if (error.Success())
- use_dynamic = (lldb::DynamicValueType) result;
- }
- break;
- case 'T': show_types = true; break;
- case 'L': show_location= true; break;
- case 'F': flat_output = true; break;
- case 'O': use_objc = true; break;
- case 'R': be_raw = true; break;
- case 'A': ignore_cap = true; break;
-
- case 'D':
- max_depth = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg);
- break;
-
- case 'Z':
- elem_count = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid element count '%s'", option_arg);
- break;
-
- case 'P':
- ptr_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg);
- break;
-
- case 'Y':
- if (option_arg)
- {
- no_summary_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg);
- }
- else
- no_summary_depth = 1;
- break;
-
- case 'S':
- use_synth = Args::StringToBoolean(option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg);
- break;
-
- case 'V':
- run_validator = Args::StringToBoolean(option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid validate '%s'", option_arg);
- break;
-
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
-}
-
-void
-OptionGroupValueObjectDisplay::OptionParsingStarting(ExecutionContext
- *execution_context)
-{
- // If these defaults change, be sure to modify AnyOptionWasSet().
- show_types = false;
- no_summary_depth = 0;
- show_location = false;
- flat_output = false;
- use_objc = false;
- max_depth = UINT32_MAX;
- ptr_depth = 0;
- elem_count = 0;
- use_synth = true;
- be_raw = false;
- ignore_cap = false;
- run_validator = false;
-
- TargetSP target_sp =
- execution_context ? execution_context->GetTargetSP() : TargetSP();
- if (target_sp)
- use_dynamic = target_sp->GetPreferDynamicValue();
- else
- {
- // If we don't have any targets, then dynamic values won't do us much good.
- use_dynamic = lldb::eNoDynamicValues;
- }
-}
-
-DumpValueObjectOptions
-OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity,
- lldb::Format format,
- lldb::TypeSummaryImplSP summary_sp)
-{
- DumpValueObjectOptions options;
- options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Always,ptr_depth} );
- if (use_objc)
- options.SetShowSummary(false);
- else
- options.SetOmitSummaryDepth(no_summary_depth);
- options.SetMaximumDepth(max_depth)
- .SetShowTypes(show_types)
- .SetShowLocation(show_location)
- .SetUseObjectiveC(use_objc)
- .SetUseDynamicType(use_dynamic)
- .SetUseSyntheticValue(use_synth)
- .SetFlatOutput(flat_output)
- .SetIgnoreCap(ignore_cap)
- .SetFormat(format)
- .SetSummary(summary_sp);
-
- if (lang_descr_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact)
- options.SetHideRootType(use_objc)
- .SetHideName(use_objc)
- .SetHideValue(use_objc);
-
- if (be_raw)
- options.SetRawDisplay();
-
- options.SetRunValidator(run_validator);
-
- options.SetElementCount(elem_count);
+ options.SetElementCount(elem_count);
- return options;
+ return options;
}
Modified: lldb/trunk/source/Interpreter/OptionGroupVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupVariable.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupVariable.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupVariable.cpp Tue Sep 6 15:57:50 2016
@@ -22,121 +22,129 @@
using namespace lldb;
using namespace lldb_private;
-// if you add any options here, remember to update the counters in OptionGroupVariable::GetNumDefinitions()
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit function arguments."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Omit local variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
- { LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify the summary that the variable output should use."},
- { LLDB_OPT_SET_2, false, "summary-string", 'z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
+// if you add any options here, remember to update the counters in
+// OptionGroupVariable::GetNumDefinitions()
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Omit function arguments."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Omit local variables."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Show the current frame source file global and static variables."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration", 'c',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Show variable declaration information (source file and line where the "
+ "variable was declared)."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression,
+ "The <variable-name> argument for name lookups are regular expressions."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's',
+ OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ "Show variable scope (argument, local, global, static)."},
+ {LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeName,
+ "Specify the summary that the variable output should use."},
+ {LLDB_OPT_SET_2, false, "summary-string", 'z',
+ OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,
+ "Specify a summary string to use to format the variable output."},
};
-static Error
-ValidateNamedSummary (const char* str, void*)
-{
- if (!str || !str[0])
- return Error("must specify a valid named summary");
- TypeSummaryImplSP summary_sp;
- if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(str), summary_sp) == false)
- return Error("must specify a valid named summary");
- return Error();
-}
-
-static Error
-ValidateSummaryString (const char* str, void*)
-{
- if (!str || !str[0])
- return Error("must specify a non-empty summary string");
- return Error();
-}
-
-OptionGroupVariable::OptionGroupVariable (bool show_frame_options) :
- OptionGroup(),
- include_frame_options (show_frame_options),
- summary(ValidateNamedSummary),
- summary_string(ValidateSummaryString)
-{
-}
-
-OptionGroupVariable::~OptionGroupVariable ()
-{
-}
-
-Error
-OptionGroupVariable::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- if (!include_frame_options)
- option_idx += 3;
- const int short_option = g_option_table[option_idx].short_option;
- switch (short_option)
- {
- case 'r': use_regex = true; break;
- case 'a': show_args = false; break;
- case 'l': show_locals = false; break;
- case 'g': show_globals = true; break;
- case 'c': show_decl = true; break;
- case 's':
- show_scope = true;
- break;
- case 'y':
- error = summary.SetCurrentValue(option_arg);
- break;
- case 'z':
- error = summary_string.SetCurrentValue(option_arg);
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
- break;
- }
-
- return error;
-}
-
-void
-OptionGroupVariable::OptionParsingStarting(ExecutionContext *execution_context)
-{
- show_args = true; // Frame option only
- show_locals = true; // Frame option only
- show_globals = false; // Frame option only
- show_decl = false;
- use_regex = false;
- show_scope = false;
- summary.Clear();
- summary_string.Clear();
+static Error ValidateNamedSummary(const char *str, void *) {
+ if (!str || !str[0])
+ return Error("must specify a valid named summary");
+ TypeSummaryImplSP summary_sp;
+ if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(
+ ConstString(str), summary_sp) == false)
+ return Error("must specify a valid named summary");
+ return Error();
+}
+
+static Error ValidateSummaryString(const char *str, void *) {
+ if (!str || !str[0])
+ return Error("must specify a non-empty summary string");
+ return Error();
+}
+
+OptionGroupVariable::OptionGroupVariable(bool show_frame_options)
+ : OptionGroup(), include_frame_options(show_frame_options),
+ summary(ValidateNamedSummary), summary_string(ValidateSummaryString) {}
+
+OptionGroupVariable::~OptionGroupVariable() {}
+
+Error OptionGroupVariable::SetOptionValue(uint32_t option_idx,
+ const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ if (!include_frame_options)
+ option_idx += 3;
+ const int short_option = g_option_table[option_idx].short_option;
+ switch (short_option) {
+ case 'r':
+ use_regex = true;
+ break;
+ case 'a':
+ show_args = false;
+ break;
+ case 'l':
+ show_locals = false;
+ break;
+ case 'g':
+ show_globals = true;
+ break;
+ case 'c':
+ show_decl = true;
+ break;
+ case 's':
+ show_scope = true;
+ break;
+ case 'y':
+ error = summary.SetCurrentValue(option_arg);
+ break;
+ case 'z':
+ error = summary_string.SetCurrentValue(option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+}
+
+void OptionGroupVariable::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ show_args = true; // Frame option only
+ show_locals = true; // Frame option only
+ show_globals = false; // Frame option only
+ show_decl = false;
+ use_regex = false;
+ show_scope = false;
+ summary.Clear();
+ summary_string.Clear();
}
#define NUM_FRAME_OPTS 3
-const OptionDefinition*
-OptionGroupVariable::GetDefinitions ()
-{
- // Show the "--no-args", "--no-locals" and "--show-globals"
- // options if we are showing frame specific options
- if (include_frame_options)
- return g_option_table;
-
- // Skip the "--no-args", "--no-locals" and "--show-globals"
- // options if we are not showing frame specific options (globals only)
- return &g_option_table[NUM_FRAME_OPTS];
-}
-
-uint32_t
-OptionGroupVariable::GetNumDefinitions ()
-{
- // Count the "--no-args", "--no-locals" and "--show-globals"
- // options if we are showing frame specific options.
- if (include_frame_options)
- return llvm::array_lengthof(g_option_table);
- else
- return llvm::array_lengthof(g_option_table) - NUM_FRAME_OPTS;
+const OptionDefinition *OptionGroupVariable::GetDefinitions() {
+ // Show the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are showing frame specific options
+ if (include_frame_options)
+ return g_option_table;
+
+ // Skip the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are not showing frame specific options (globals only)
+ return &g_option_table[NUM_FRAME_OPTS];
+}
+
+uint32_t OptionGroupVariable::GetNumDefinitions() {
+ // Count the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are showing frame specific options.
+ if (include_frame_options)
+ return llvm::array_lengthof(g_option_table);
+ else
+ return llvm::array_lengthof(g_option_table) - NUM_FRAME_OPTS;
}
-
-
Modified: lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupWatchpoint.cpp Tue Sep 6 15:57:50 2016
@@ -13,110 +13,90 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-enumerations.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Utility/Utils.h"
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
-static OptionEnumValueElement g_watch_type[] =
-{
- { OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"},
- { OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"},
- { OptionGroupWatchpoint::eWatchReadWrite, "read_write", "Watch for read/write"},
- { 0, nullptr, nullptr }
-};
-
-static OptionEnumValueElement g_watch_size[] =
-{
- { 1, "1", "Watch for byte size of 1"},
- { 2, "2", "Watch for byte size of 2"},
- { 4, "4", "Watch for byte size of 4"},
- { 8, "8", "Watch for byte size of 8"},
- { 0, nullptr, nullptr }
-};
-
-static OptionDefinition
-g_option_table[] =
-{
- { LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, nullptr, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."},
- { LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, nullptr, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}
-};
-
-
-bool
-OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size)
-{
- for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i)
- {
- if (g_watch_size[i].value == 0)
- break;
- if (watch_size == g_watch_size[i].value)
- return true;
+static OptionEnumValueElement g_watch_type[] = {
+ {OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"},
+ {OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"},
+ {OptionGroupWatchpoint::eWatchReadWrite, "read_write",
+ "Watch for read/write"},
+ {0, nullptr, nullptr}};
+
+static OptionEnumValueElement g_watch_size[] = {
+ {1, "1", "Watch for byte size of 1"},
+ {2, "2", "Watch for byte size of 2"},
+ {4, "4", "Watch for byte size of 4"},
+ {8, "8", "Watch for byte size of 8"},
+ {0, nullptr, nullptr}};
+
+static OptionDefinition g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument,
+ nullptr, g_watch_type, 0, eArgTypeWatchType,
+ "Specify the type of watching to perform."},
+ {LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument,
+ nullptr, g_watch_size, 0, eArgTypeByteSize,
+ "Number of bytes to use to watch a region."}};
+
+bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) {
+ for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i) {
+ if (g_watch_size[i].value == 0)
+ break;
+ if (watch_size == g_watch_size[i].value)
+ return true;
+ }
+ return false;
+}
+
+OptionGroupWatchpoint::OptionGroupWatchpoint() : OptionGroup() {}
+
+OptionGroupWatchpoint::~OptionGroupWatchpoint() {}
+
+Error OptionGroupWatchpoint::SetOptionValue(
+ uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) {
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+ switch (short_option) {
+ case 'w': {
+ WatchType tmp_watch_type;
+ tmp_watch_type = (WatchType)Args::StringToOptionEnum(
+ option_arg, g_option_table[option_idx].enum_values, 0, error);
+ if (error.Success()) {
+ watch_type = tmp_watch_type;
+ watch_type_specified = true;
}
- return false;
-}
-
-OptionGroupWatchpoint::OptionGroupWatchpoint () :
- OptionGroup()
-{
-}
+ break;
+ }
+ case 's':
+ watch_size = (uint32_t)Args::StringToOptionEnum(
+ option_arg, g_option_table[option_idx].enum_values, 0, error);
+ break;
-OptionGroupWatchpoint::~OptionGroupWatchpoint ()
-{
-}
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'",
+ short_option);
+ break;
+ }
-Error
-OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx,
- const char *option_arg,
- ExecutionContext *execution_context)
-{
- Error error;
- const int short_option = g_option_table[option_idx].short_option;
- switch (short_option)
- {
- case 'w':
- {
- WatchType tmp_watch_type;
- tmp_watch_type = (WatchType) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
- if (error.Success())
- {
- watch_type = tmp_watch_type;
- watch_type_specified = true;
- }
- break;
- }
- case 's':
- watch_size = (uint32_t) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
- break;
-
- default:
- error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
- break;
- }
-
- return error;
+ return error;
}
-void
-OptionGroupWatchpoint::OptionParsingStarting(ExecutionContext
- *execution_context)
-{
- watch_type_specified = false;
- watch_type = eWatchInvalid;
- watch_size = 0;
+void OptionGroupWatchpoint::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ watch_type_specified = false;
+ watch_type = eWatchInvalid;
+ watch_size = 0;
}
-
-const OptionDefinition*
-OptionGroupWatchpoint::GetDefinitions ()
-{
- return g_option_table;
+const OptionDefinition *OptionGroupWatchpoint::GetDefinitions() {
+ return g_option_table;
}
-uint32_t
-OptionGroupWatchpoint::GetNumDefinitions ()
-{
- return llvm::array_lengthof(g_option_table);
+uint32_t OptionGroupWatchpoint::GetNumDefinitions() {
+ return llvm::array_lengthof(g_option_table);
}
Modified: lldb/trunk/source/Interpreter/OptionValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValue.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValue.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValue.cpp Tue Sep 6 15:57:50 2016
@@ -19,720 +19,606 @@
using namespace lldb;
using namespace lldb_private;
-
//-------------------------------------------------------------------------
// Get this value as a uint64_t value if it is encoded as a boolean,
-// uint64_t or int64_t. Other types will cause "fail_value" to be
+// uint64_t or int64_t. Other types will cause "fail_value" to be
// returned
//-------------------------------------------------------------------------
-uint64_t
-OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr)
-{
- if (success_ptr)
- *success_ptr = true;
- switch (GetType())
- {
- case OptionValue::eTypeBoolean: return static_cast<OptionValueBoolean *>(this)->GetCurrentValue();
- case OptionValue::eTypeSInt64: return static_cast<OptionValueSInt64 *>(this)->GetCurrentValue();
- case OptionValue::eTypeUInt64: return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
- default:
- break;
- }
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
-
-Error
-OptionValue::SetSubValue (const ExecutionContext *exe_ctx,
- VarSetOperationType op,
- const char *name,
- const char *value)
-{
- Error error;
- error.SetErrorStringWithFormat("SetSubValue is not supported");
- return error;
-}
-
-
-OptionValueBoolean *
-OptionValue::GetAsBoolean ()
-{
- if (GetType () == OptionValue::eTypeBoolean)
- return static_cast<OptionValueBoolean *>(this);
- return nullptr;
-}
-
-const OptionValueBoolean *
-OptionValue::GetAsBoolean () const
-{
- if (GetType () == OptionValue::eTypeBoolean)
- return static_cast<const OptionValueBoolean *>(this);
- return nullptr;
-}
-
-const OptionValueChar *
-OptionValue::GetAsChar () const
-{
- if (GetType () == OptionValue::eTypeChar)
- return static_cast<const OptionValueChar *>(this);
- return nullptr;
-}
-
-OptionValueChar *
-OptionValue::GetAsChar ()
-{
- if (GetType () == OptionValue::eTypeChar)
- return static_cast<OptionValueChar *>(this);
- return nullptr;
-}
-
-OptionValueFileSpec *
-OptionValue::GetAsFileSpec ()
-{
- if (GetType () == OptionValue::eTypeFileSpec)
- return static_cast<OptionValueFileSpec *>(this);
- return nullptr;
-
-}
-
-const OptionValueFileSpec *
-OptionValue::GetAsFileSpec () const
-{
- if (GetType () == OptionValue::eTypeFileSpec)
- return static_cast<const OptionValueFileSpec *>(this);
- return nullptr;
-
-}
-
-OptionValueFileSpecList *
-OptionValue::GetAsFileSpecList ()
-{
- if (GetType () == OptionValue::eTypeFileSpecList)
- return static_cast<OptionValueFileSpecList *>(this);
- return nullptr;
-
-}
-
-const OptionValueFileSpecList *
-OptionValue::GetAsFileSpecList () const
-{
- if (GetType () == OptionValue::eTypeFileSpecList)
- return static_cast<const OptionValueFileSpecList *>(this);
- return nullptr;
-
-}
-
-OptionValueArch *
-OptionValue::GetAsArch ()
-{
- if (GetType () == OptionValue::eTypeArch)
- return static_cast<OptionValueArch *>(this);
- return nullptr;
-}
-
-
-const OptionValueArch *
-OptionValue::GetAsArch () const
-{
- if (GetType () == OptionValue::eTypeArch)
- return static_cast<const OptionValueArch *>(this);
- return nullptr;
-}
-
-OptionValueArray *
-OptionValue::GetAsArray ()
-{
- if (GetType () == OptionValue::eTypeArray)
- return static_cast<OptionValueArray *>(this);
- return nullptr;
-}
-
-
-const OptionValueArray *
-OptionValue::GetAsArray () const
-{
- if (GetType () == OptionValue::eTypeArray)
- return static_cast<const OptionValueArray *>(this);
- return nullptr;
-}
-
-OptionValueArgs *
-OptionValue::GetAsArgs ()
-{
- if (GetType () == OptionValue::eTypeArgs)
- return static_cast<OptionValueArgs *>(this);
- return nullptr;
-}
-
-
-const OptionValueArgs *
-OptionValue::GetAsArgs () const
-{
- if (GetType () == OptionValue::eTypeArgs)
- return static_cast<const OptionValueArgs *>(this);
- return nullptr;
-}
-
-OptionValueDictionary *
-OptionValue::GetAsDictionary ()
-{
- if (GetType () == OptionValue::eTypeDictionary)
- return static_cast<OptionValueDictionary *>(this);
- return nullptr;
-}
-
-const OptionValueDictionary *
-OptionValue::GetAsDictionary () const
-{
- if (GetType () == OptionValue::eTypeDictionary)
- return static_cast<const OptionValueDictionary *>(this);
- return nullptr;
-}
-
-OptionValueEnumeration *
-OptionValue::GetAsEnumeration ()
-{
- if (GetType () == OptionValue::eTypeEnum)
- return static_cast<OptionValueEnumeration *>(this);
- return nullptr;
-}
-
-const OptionValueEnumeration *
-OptionValue::GetAsEnumeration () const
-{
- if (GetType () == OptionValue::eTypeEnum)
- return static_cast<const OptionValueEnumeration *>(this);
- return nullptr;
-}
-
-OptionValueFormat *
-OptionValue::GetAsFormat ()
-{
- if (GetType () == OptionValue::eTypeFormat)
- return static_cast<OptionValueFormat *>(this);
- return nullptr;
-}
-
-const OptionValueFormat *
-OptionValue::GetAsFormat () const
-{
- if (GetType () == OptionValue::eTypeFormat)
- return static_cast<const OptionValueFormat *>(this);
- return nullptr;
-}
-
-OptionValueLanguage *
-OptionValue::GetAsLanguage ()
-{
- if (GetType () == OptionValue::eTypeLanguage)
- return static_cast<OptionValueLanguage *>(this);
- return NULL;
-}
-
-const OptionValueLanguage *
-OptionValue::GetAsLanguage () const
-{
- if (GetType () == OptionValue::eTypeLanguage)
- return static_cast<const OptionValueLanguage *>(this);
- return NULL;
-}
-
-OptionValueFormatEntity *
-OptionValue::GetAsFormatEntity ()
-{
- if (GetType () == OptionValue::eTypeFormatEntity)
- return static_cast<OptionValueFormatEntity *>(this);
- return nullptr;
-}
-
-const OptionValueFormatEntity *
-OptionValue::GetAsFormatEntity () const
-{
- if (GetType () == OptionValue::eTypeFormatEntity)
- return static_cast<const OptionValueFormatEntity *>(this);
- return nullptr;
-}
-
-OptionValuePathMappings *
-OptionValue::GetAsPathMappings ()
-{
- if (GetType () == OptionValue::eTypePathMap)
- return static_cast<OptionValuePathMappings *>(this);
- return nullptr;
-}
-
-const OptionValuePathMappings *
-OptionValue::GetAsPathMappings () const
-{
- if (GetType () == OptionValue::eTypePathMap)
- return static_cast<const OptionValuePathMappings *>(this);
- return nullptr;
-}
-
-OptionValueProperties *
-OptionValue::GetAsProperties ()
-{
- if (GetType () == OptionValue::eTypeProperties)
- return static_cast<OptionValueProperties *>(this);
- return nullptr;
-}
-
-const OptionValueProperties *
-OptionValue::GetAsProperties () const
-{
- if (GetType () == OptionValue::eTypeProperties)
- return static_cast<const OptionValueProperties *>(this);
- return nullptr;
-}
-
-OptionValueRegex *
-OptionValue::GetAsRegex ()
-{
- if (GetType () == OptionValue::eTypeRegex)
- return static_cast<OptionValueRegex *>(this);
- return nullptr;
-}
-
-const OptionValueRegex *
-OptionValue::GetAsRegex () const
-{
- if (GetType () == OptionValue::eTypeRegex)
- return static_cast<const OptionValueRegex *>(this);
- return nullptr;
-}
-
-OptionValueSInt64 *
-OptionValue::GetAsSInt64 ()
-{
- if (GetType () == OptionValue::eTypeSInt64)
- return static_cast<OptionValueSInt64 *>(this);
- return nullptr;
-}
-
-const OptionValueSInt64 *
-OptionValue::GetAsSInt64 () const
-{
- if (GetType () == OptionValue::eTypeSInt64)
- return static_cast<const OptionValueSInt64 *>(this);
- return nullptr;
-}
-
-OptionValueString *
-OptionValue::GetAsString ()
-{
- if (GetType () == OptionValue::eTypeString)
- return static_cast<OptionValueString *>(this);
- return nullptr;
-}
-
-const OptionValueString *
-OptionValue::GetAsString () const
-{
- if (GetType () == OptionValue::eTypeString)
- return static_cast<const OptionValueString *>(this);
- return nullptr;
-}
-
-OptionValueUInt64 *
-OptionValue::GetAsUInt64 ()
-{
- if (GetType () == OptionValue::eTypeUInt64)
- return static_cast<OptionValueUInt64 *>(this);
- return nullptr;
-}
-
-const OptionValueUInt64 *
-OptionValue::GetAsUInt64 () const
-{
- if (GetType () == OptionValue::eTypeUInt64)
- return static_cast<const OptionValueUInt64 *>(this);
- return nullptr;
-}
-
-OptionValueUUID *
-OptionValue::GetAsUUID ()
-{
- if (GetType () == OptionValue::eTypeUUID)
- return static_cast<OptionValueUUID *>(this);
- return nullptr;
-
-}
-
-const OptionValueUUID *
-OptionValue::GetAsUUID () const
-{
- if (GetType () == OptionValue::eTypeUUID)
- return static_cast<const OptionValueUUID *>(this);
- return nullptr;
-
-}
-
-bool
-OptionValue::GetBooleanValue (bool fail_value) const
-{
- const OptionValueBoolean *option_value = GetAsBoolean ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetBooleanValue (bool new_value)
-{
- OptionValueBoolean *option_value = GetAsBoolean ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
-}
-
-char
-OptionValue::GetCharValue(char fail_value) const
-{
- const OptionValueChar *option_value = GetAsChar();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-char
-OptionValue::SetCharValue(char new_value)
-{
- OptionValueChar *option_value = GetAsChar();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
-}
-
-int64_t
-OptionValue::GetEnumerationValue (int64_t fail_value) const
-{
- const OptionValueEnumeration *option_value = GetAsEnumeration();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetEnumerationValue (int64_t value)
-{
- OptionValueEnumeration *option_value = GetAsEnumeration();
- if (option_value)
- {
- option_value->SetCurrentValue(value);
- return true;
- }
- return false;
-}
-
-FileSpec
-OptionValue::GetFileSpecValue () const
-{
- const OptionValueFileSpec *option_value = GetAsFileSpec ();
- if (option_value)
- return option_value->GetCurrentValue();
- return FileSpec();
-}
-
-
-bool
-OptionValue::SetFileSpecValue (const FileSpec &file_spec)
-{
- OptionValueFileSpec *option_value = GetAsFileSpec ();
- if (option_value)
- {
- option_value->SetCurrentValue(file_spec, false);
- return true;
- }
- return false;
-}
-
-FileSpecList
-OptionValue::GetFileSpecListValue () const
-{
- const OptionValueFileSpecList *option_value = GetAsFileSpecList ();
- if (option_value)
- return option_value->GetCurrentValue();
- return FileSpecList();
-}
-
-
-lldb::Format
-OptionValue::GetFormatValue (lldb::Format fail_value) const
-{
- const OptionValueFormat *option_value = GetAsFormat ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetFormatValue (lldb::Format new_value)
-{
- OptionValueFormat *option_value = GetAsFormat ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
+uint64_t OptionValue::GetUInt64Value(uint64_t fail_value, bool *success_ptr) {
+ if (success_ptr)
+ *success_ptr = true;
+ switch (GetType()) {
+ case OptionValue::eTypeBoolean:
+ return static_cast<OptionValueBoolean *>(this)->GetCurrentValue();
+ case OptionValue::eTypeSInt64:
+ return static_cast<OptionValueSInt64 *>(this)->GetCurrentValue();
+ case OptionValue::eTypeUInt64:
+ return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
+ default:
+ break;
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
}
-lldb::LanguageType
-OptionValue::GetLanguageValue (lldb::LanguageType fail_value) const
-{
- const OptionValueLanguage *option_value = GetAsLanguage ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetLanguageValue (lldb::LanguageType new_language)
-{
- OptionValueLanguage *option_value = GetAsLanguage ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_language);
- return true;
- }
- return false;
-}
-
-const FormatEntity::Entry *
-OptionValue::GetFormatEntity () const
-{
- const OptionValueFormatEntity *option_value = GetAsFormatEntity();
- if (option_value)
- return &option_value->GetCurrentValue();
- return nullptr;
-}
-
-const RegularExpression *
-OptionValue::GetRegexValue () const
-{
- const OptionValueRegex *option_value = GetAsRegex ();
- if (option_value)
- return option_value->GetCurrentValue();
- return nullptr;
-}
-
-
-int64_t
-OptionValue::GetSInt64Value (int64_t fail_value) const
-{
- const OptionValueSInt64 *option_value = GetAsSInt64 ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetSInt64Value (int64_t new_value)
-{
- OptionValueSInt64 *option_value = GetAsSInt64 ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
-}
-
-const char *
-OptionValue::GetStringValue (const char *fail_value) const
-{
- const OptionValueString *option_value = GetAsString ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetStringValue (const char *new_value)
-{
- OptionValueString *option_value = GetAsString ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
-}
-
-uint64_t
-OptionValue::GetUInt64Value (uint64_t fail_value) const
-{
- const OptionValueUInt64 *option_value = GetAsUInt64 ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-bool
-OptionValue::SetUInt64Value (uint64_t new_value)
-{
- OptionValueUInt64 *option_value = GetAsUInt64 ();
- if (option_value)
- {
- option_value->SetCurrentValue(new_value);
- return true;
- }
- return false;
-}
-
-UUID
-OptionValue::GetUUIDValue () const
-{
- const OptionValueUUID *option_value = GetAsUUID();
- if (option_value)
- return option_value->GetCurrentValue();
- return UUID();
-}
-
-bool
-OptionValue::SetUUIDValue (const UUID &uuid)
-{
- OptionValueUUID *option_value = GetAsUUID();
- if (option_value)
- {
- option_value->SetCurrentValue(uuid);
- return true;
- }
- return false;
-}
-
-const char *
-OptionValue::GetBuiltinTypeAsCString (Type t)
-{
- switch (t)
- {
- case eTypeInvalid: return "invalid";
- case eTypeArch: return "arch";
- case eTypeArgs: return "arguments";
- case eTypeArray: return "array";
- case eTypeBoolean: return "boolean";
- case eTypeChar:
- return "char";
- case eTypeDictionary: return "dictionary";
- case eTypeEnum: return "enum";
- case eTypeFileSpec: return "file";
- case eTypeFileSpecList: return "file-list";
- case eTypeFormat: return "format";
- case eTypeFormatEntity: return "format-string";
- case eTypeLanguage: return "language";
- case eTypePathMap: return "path-map";
- case eTypeProperties: return "properties";
- case eTypeRegex: return "regex";
- case eTypeSInt64: return "int";
- case eTypeString: return "string";
- case eTypeUInt64: return "unsigned";
- case eTypeUUID: return "uuid";
- }
- return nullptr;
-}
-
-
-lldb::OptionValueSP
-OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t type_mask, Error &error)
-{
- // If only 1 bit is set in the type mask for a dictionary or array
- // then we know how to decode a value from a cstring
- lldb::OptionValueSP value_sp;
- switch (type_mask)
- {
- case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break;
- case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break;
- case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break;
- case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break;
- case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break;
- case 1u << eTypeFormatEntity: value_sp.reset(new OptionValueFormatEntity(NULL)); break;
- case 1u << eTypeLanguage: value_sp.reset(new OptionValueLanguage(eLanguageTypeUnknown)); break;
- case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break;
- case 1u << eTypeString: value_sp.reset(new OptionValueString()); break;
- case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break;
- case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break;
- }
+Error OptionValue::SetSubValue(const ExecutionContext *exe_ctx,
+ VarSetOperationType op, const char *name,
+ const char *value) {
+ Error error;
+ error.SetErrorStringWithFormat("SetSubValue is not supported");
+ return error;
+}
- if (value_sp)
- error = value_sp->SetValueFromString (value_cstr, eVarSetOperationAssign);
- else
- error.SetErrorString("unsupported type mask");
- return value_sp;
+OptionValueBoolean *OptionValue::GetAsBoolean() {
+ if (GetType() == OptionValue::eTypeBoolean)
+ return static_cast<OptionValueBoolean *>(this);
+ return nullptr;
+}
+
+const OptionValueBoolean *OptionValue::GetAsBoolean() const {
+ if (GetType() == OptionValue::eTypeBoolean)
+ return static_cast<const OptionValueBoolean *>(this);
+ return nullptr;
+}
+
+const OptionValueChar *OptionValue::GetAsChar() const {
+ if (GetType() == OptionValue::eTypeChar)
+ return static_cast<const OptionValueChar *>(this);
+ return nullptr;
+}
+
+OptionValueChar *OptionValue::GetAsChar() {
+ if (GetType() == OptionValue::eTypeChar)
+ return static_cast<OptionValueChar *>(this);
+ return nullptr;
+}
+
+OptionValueFileSpec *OptionValue::GetAsFileSpec() {
+ if (GetType() == OptionValue::eTypeFileSpec)
+ return static_cast<OptionValueFileSpec *>(this);
+ return nullptr;
+}
+
+const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {
+ if (GetType() == OptionValue::eTypeFileSpec)
+ return static_cast<const OptionValueFileSpec *>(this);
+ return nullptr;
+}
+
+OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {
+ if (GetType() == OptionValue::eTypeFileSpecList)
+ return static_cast<OptionValueFileSpecList *>(this);
+ return nullptr;
+}
+
+const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {
+ if (GetType() == OptionValue::eTypeFileSpecList)
+ return static_cast<const OptionValueFileSpecList *>(this);
+ return nullptr;
+}
+
+OptionValueArch *OptionValue::GetAsArch() {
+ if (GetType() == OptionValue::eTypeArch)
+ return static_cast<OptionValueArch *>(this);
+ return nullptr;
+}
+
+const OptionValueArch *OptionValue::GetAsArch() const {
+ if (GetType() == OptionValue::eTypeArch)
+ return static_cast<const OptionValueArch *>(this);
+ return nullptr;
+}
+
+OptionValueArray *OptionValue::GetAsArray() {
+ if (GetType() == OptionValue::eTypeArray)
+ return static_cast<OptionValueArray *>(this);
+ return nullptr;
+}
+
+const OptionValueArray *OptionValue::GetAsArray() const {
+ if (GetType() == OptionValue::eTypeArray)
+ return static_cast<const OptionValueArray *>(this);
+ return nullptr;
}
-bool
-OptionValue::DumpQualifiedName (Stream &strm) const
-{
- bool dumped_something = false;
- lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());
- if (m_parent_sp)
- {
- if (m_parent_sp->DumpQualifiedName(strm))
- dumped_something = true;
- }
- ConstString name (GetName());
- if (name)
- {
- if (dumped_something)
- strm.PutChar('.');
- else
- dumped_something = true;
- strm << name;
- }
- return dumped_something;
-}
-
-size_t
-OptionValue::AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- word_complete = false;
- matches.Clear();
- return matches.GetSize();
-}
-
-Error
-OptionValue::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
- Error error;
- switch (op)
- {
- case eVarSetOperationReplace:
- error.SetErrorStringWithFormat ("%s objects do not support the 'replace' operation", GetTypeAsCString());
- break;
- case eVarSetOperationInsertBefore:
- error.SetErrorStringWithFormat ("%s objects do not support the 'insert-before' operation", GetTypeAsCString());
- break;
- case eVarSetOperationInsertAfter:
- error.SetErrorStringWithFormat ("%s objects do not support the 'insert-after' operation", GetTypeAsCString());
- break;
- case eVarSetOperationRemove:
- error.SetErrorStringWithFormat ("%s objects do not support the 'remove' operation", GetTypeAsCString());
- break;
- case eVarSetOperationAppend:
- error.SetErrorStringWithFormat ("%s objects do not support the 'append' operation", GetTypeAsCString());
- break;
- case eVarSetOperationClear:
- error.SetErrorStringWithFormat ("%s objects do not support the 'clear' operation", GetTypeAsCString());
- break;
- case eVarSetOperationAssign:
- error.SetErrorStringWithFormat ("%s objects do not support the 'assign' operation", GetTypeAsCString());
- break;
- case eVarSetOperationInvalid:
- error.SetErrorStringWithFormat ("invalid operation performed on a %s object", GetTypeAsCString());
- break;
- }
- return error;
+OptionValueArgs *OptionValue::GetAsArgs() {
+ if (GetType() == OptionValue::eTypeArgs)
+ return static_cast<OptionValueArgs *>(this);
+ return nullptr;
}
+const OptionValueArgs *OptionValue::GetAsArgs() const {
+ if (GetType() == OptionValue::eTypeArgs)
+ return static_cast<const OptionValueArgs *>(this);
+ return nullptr;
+}
+
+OptionValueDictionary *OptionValue::GetAsDictionary() {
+ if (GetType() == OptionValue::eTypeDictionary)
+ return static_cast<OptionValueDictionary *>(this);
+ return nullptr;
+}
+
+const OptionValueDictionary *OptionValue::GetAsDictionary() const {
+ if (GetType() == OptionValue::eTypeDictionary)
+ return static_cast<const OptionValueDictionary *>(this);
+ return nullptr;
+}
+
+OptionValueEnumeration *OptionValue::GetAsEnumeration() {
+ if (GetType() == OptionValue::eTypeEnum)
+ return static_cast<OptionValueEnumeration *>(this);
+ return nullptr;
+}
+
+const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {
+ if (GetType() == OptionValue::eTypeEnum)
+ return static_cast<const OptionValueEnumeration *>(this);
+ return nullptr;
+}
+
+OptionValueFormat *OptionValue::GetAsFormat() {
+ if (GetType() == OptionValue::eTypeFormat)
+ return static_cast<OptionValueFormat *>(this);
+ return nullptr;
+}
+
+const OptionValueFormat *OptionValue::GetAsFormat() const {
+ if (GetType() == OptionValue::eTypeFormat)
+ return static_cast<const OptionValueFormat *>(this);
+ return nullptr;
+}
+
+OptionValueLanguage *OptionValue::GetAsLanguage() {
+ if (GetType() == OptionValue::eTypeLanguage)
+ return static_cast<OptionValueLanguage *>(this);
+ return NULL;
+}
+
+const OptionValueLanguage *OptionValue::GetAsLanguage() const {
+ if (GetType() == OptionValue::eTypeLanguage)
+ return static_cast<const OptionValueLanguage *>(this);
+ return NULL;
+}
+
+OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {
+ if (GetType() == OptionValue::eTypeFormatEntity)
+ return static_cast<OptionValueFormatEntity *>(this);
+ return nullptr;
+}
+
+const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {
+ if (GetType() == OptionValue::eTypeFormatEntity)
+ return static_cast<const OptionValueFormatEntity *>(this);
+ return nullptr;
+}
+
+OptionValuePathMappings *OptionValue::GetAsPathMappings() {
+ if (GetType() == OptionValue::eTypePathMap)
+ return static_cast<OptionValuePathMappings *>(this);
+ return nullptr;
+}
+
+const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {
+ if (GetType() == OptionValue::eTypePathMap)
+ return static_cast<const OptionValuePathMappings *>(this);
+ return nullptr;
+}
+
+OptionValueProperties *OptionValue::GetAsProperties() {
+ if (GetType() == OptionValue::eTypeProperties)
+ return static_cast<OptionValueProperties *>(this);
+ return nullptr;
+}
+
+const OptionValueProperties *OptionValue::GetAsProperties() const {
+ if (GetType() == OptionValue::eTypeProperties)
+ return static_cast<const OptionValueProperties *>(this);
+ return nullptr;
+}
+
+OptionValueRegex *OptionValue::GetAsRegex() {
+ if (GetType() == OptionValue::eTypeRegex)
+ return static_cast<OptionValueRegex *>(this);
+ return nullptr;
+}
+
+const OptionValueRegex *OptionValue::GetAsRegex() const {
+ if (GetType() == OptionValue::eTypeRegex)
+ return static_cast<const OptionValueRegex *>(this);
+ return nullptr;
+}
+
+OptionValueSInt64 *OptionValue::GetAsSInt64() {
+ if (GetType() == OptionValue::eTypeSInt64)
+ return static_cast<OptionValueSInt64 *>(this);
+ return nullptr;
+}
+
+const OptionValueSInt64 *OptionValue::GetAsSInt64() const {
+ if (GetType() == OptionValue::eTypeSInt64)
+ return static_cast<const OptionValueSInt64 *>(this);
+ return nullptr;
+}
+
+OptionValueString *OptionValue::GetAsString() {
+ if (GetType() == OptionValue::eTypeString)
+ return static_cast<OptionValueString *>(this);
+ return nullptr;
+}
+
+const OptionValueString *OptionValue::GetAsString() const {
+ if (GetType() == OptionValue::eTypeString)
+ return static_cast<const OptionValueString *>(this);
+ return nullptr;
+}
+
+OptionValueUInt64 *OptionValue::GetAsUInt64() {
+ if (GetType() == OptionValue::eTypeUInt64)
+ return static_cast<OptionValueUInt64 *>(this);
+ return nullptr;
+}
+
+const OptionValueUInt64 *OptionValue::GetAsUInt64() const {
+ if (GetType() == OptionValue::eTypeUInt64)
+ return static_cast<const OptionValueUInt64 *>(this);
+ return nullptr;
+}
+
+OptionValueUUID *OptionValue::GetAsUUID() {
+ if (GetType() == OptionValue::eTypeUUID)
+ return static_cast<OptionValueUUID *>(this);
+ return nullptr;
+}
+
+const OptionValueUUID *OptionValue::GetAsUUID() const {
+ if (GetType() == OptionValue::eTypeUUID)
+ return static_cast<const OptionValueUUID *>(this);
+ return nullptr;
+}
+
+bool OptionValue::GetBooleanValue(bool fail_value) const {
+ const OptionValueBoolean *option_value = GetAsBoolean();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetBooleanValue(bool new_value) {
+ OptionValueBoolean *option_value = GetAsBoolean();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+char OptionValue::GetCharValue(char fail_value) const {
+ const OptionValueChar *option_value = GetAsChar();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+char OptionValue::SetCharValue(char new_value) {
+ OptionValueChar *option_value = GetAsChar();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+int64_t OptionValue::GetEnumerationValue(int64_t fail_value) const {
+ const OptionValueEnumeration *option_value = GetAsEnumeration();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetEnumerationValue(int64_t value) {
+ OptionValueEnumeration *option_value = GetAsEnumeration();
+ if (option_value) {
+ option_value->SetCurrentValue(value);
+ return true;
+ }
+ return false;
+}
+
+FileSpec OptionValue::GetFileSpecValue() const {
+ const OptionValueFileSpec *option_value = GetAsFileSpec();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return FileSpec();
+}
+
+bool OptionValue::SetFileSpecValue(const FileSpec &file_spec) {
+ OptionValueFileSpec *option_value = GetAsFileSpec();
+ if (option_value) {
+ option_value->SetCurrentValue(file_spec, false);
+ return true;
+ }
+ return false;
+}
+
+FileSpecList OptionValue::GetFileSpecListValue() const {
+ const OptionValueFileSpecList *option_value = GetAsFileSpecList();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return FileSpecList();
+}
+
+lldb::Format OptionValue::GetFormatValue(lldb::Format fail_value) const {
+ const OptionValueFormat *option_value = GetAsFormat();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetFormatValue(lldb::Format new_value) {
+ OptionValueFormat *option_value = GetAsFormat();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+lldb::LanguageType
+OptionValue::GetLanguageValue(lldb::LanguageType fail_value) const {
+ const OptionValueLanguage *option_value = GetAsLanguage();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) {
+ OptionValueLanguage *option_value = GetAsLanguage();
+ if (option_value) {
+ option_value->SetCurrentValue(new_language);
+ return true;
+ }
+ return false;
+}
+
+const FormatEntity::Entry *OptionValue::GetFormatEntity() const {
+ const OptionValueFormatEntity *option_value = GetAsFormatEntity();
+ if (option_value)
+ return &option_value->GetCurrentValue();
+ return nullptr;
+}
+
+const RegularExpression *OptionValue::GetRegexValue() const {
+ const OptionValueRegex *option_value = GetAsRegex();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return nullptr;
+}
+
+int64_t OptionValue::GetSInt64Value(int64_t fail_value) const {
+ const OptionValueSInt64 *option_value = GetAsSInt64();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetSInt64Value(int64_t new_value) {
+ OptionValueSInt64 *option_value = GetAsSInt64();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+const char *OptionValue::GetStringValue(const char *fail_value) const {
+ const OptionValueString *option_value = GetAsString();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetStringValue(const char *new_value) {
+ OptionValueString *option_value = GetAsString();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+uint64_t OptionValue::GetUInt64Value(uint64_t fail_value) const {
+ const OptionValueUInt64 *option_value = GetAsUInt64();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool OptionValue::SetUInt64Value(uint64_t new_value) {
+ OptionValueUInt64 *option_value = GetAsUInt64();
+ if (option_value) {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+UUID OptionValue::GetUUIDValue() const {
+ const OptionValueUUID *option_value = GetAsUUID();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return UUID();
+}
+
+bool OptionValue::SetUUIDValue(const UUID &uuid) {
+ OptionValueUUID *option_value = GetAsUUID();
+ if (option_value) {
+ option_value->SetCurrentValue(uuid);
+ return true;
+ }
+ return false;
+}
+
+const char *OptionValue::GetBuiltinTypeAsCString(Type t) {
+ switch (t) {
+ case eTypeInvalid:
+ return "invalid";
+ case eTypeArch:
+ return "arch";
+ case eTypeArgs:
+ return "arguments";
+ case eTypeArray:
+ return "array";
+ case eTypeBoolean:
+ return "boolean";
+ case eTypeChar:
+ return "char";
+ case eTypeDictionary:
+ return "dictionary";
+ case eTypeEnum:
+ return "enum";
+ case eTypeFileSpec:
+ return "file";
+ case eTypeFileSpecList:
+ return "file-list";
+ case eTypeFormat:
+ return "format";
+ case eTypeFormatEntity:
+ return "format-string";
+ case eTypeLanguage:
+ return "language";
+ case eTypePathMap:
+ return "path-map";
+ case eTypeProperties:
+ return "properties";
+ case eTypeRegex:
+ return "regex";
+ case eTypeSInt64:
+ return "int";
+ case eTypeString:
+ return "string";
+ case eTypeUInt64:
+ return "unsigned";
+ case eTypeUUID:
+ return "uuid";
+ }
+ return nullptr;
+}
+
+lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(
+ const char *value_cstr, uint32_t type_mask, Error &error) {
+ // If only 1 bit is set in the type mask for a dictionary or array
+ // then we know how to decode a value from a cstring
+ lldb::OptionValueSP value_sp;
+ switch (type_mask) {
+ case 1u << eTypeArch:
+ value_sp.reset(new OptionValueArch());
+ break;
+ case 1u << eTypeBoolean:
+ value_sp.reset(new OptionValueBoolean(false));
+ break;
+ case 1u << eTypeChar:
+ value_sp.reset(new OptionValueChar('\0'));
+ break;
+ case 1u << eTypeFileSpec:
+ value_sp.reset(new OptionValueFileSpec());
+ break;
+ case 1u << eTypeFormat:
+ value_sp.reset(new OptionValueFormat(eFormatInvalid));
+ break;
+ case 1u << eTypeFormatEntity:
+ value_sp.reset(new OptionValueFormatEntity(NULL));
+ break;
+ case 1u << eTypeLanguage:
+ value_sp.reset(new OptionValueLanguage(eLanguageTypeUnknown));
+ break;
+ case 1u << eTypeSInt64:
+ value_sp.reset(new OptionValueSInt64());
+ break;
+ case 1u << eTypeString:
+ value_sp.reset(new OptionValueString());
+ break;
+ case 1u << eTypeUInt64:
+ value_sp.reset(new OptionValueUInt64());
+ break;
+ case 1u << eTypeUUID:
+ value_sp.reset(new OptionValueUUID());
+ break;
+ }
+
+ if (value_sp)
+ error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign);
+ else
+ error.SetErrorString("unsupported type mask");
+ return value_sp;
+}
+
+bool OptionValue::DumpQualifiedName(Stream &strm) const {
+ bool dumped_something = false;
+ lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());
+ if (m_parent_sp) {
+ if (m_parent_sp->DumpQualifiedName(strm))
+ dumped_something = true;
+ }
+ ConstString name(GetName());
+ if (name) {
+ if (dumped_something)
+ strm.PutChar('.');
+ else
+ dumped_something = true;
+ strm << name;
+ }
+ return dumped_something;
+}
+
+size_t OptionValue::AutoComplete(CommandInterpreter &interpreter, const char *s,
+ int match_start_point, int max_return_elements,
+ bool &word_complete, StringList &matches) {
+ word_complete = false;
+ matches.Clear();
+ return matches.GetSize();
+}
+
+Error OptionValue::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Error error;
+ switch (op) {
+ case eVarSetOperationReplace:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'replace' operation",
+ GetTypeAsCString());
+ break;
+ case eVarSetOperationInsertBefore:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'insert-before' operation",
+ GetTypeAsCString());
+ break;
+ case eVarSetOperationInsertAfter:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'insert-after' operation",
+ GetTypeAsCString());
+ break;
+ case eVarSetOperationRemove:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'remove' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationAppend:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'append' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationClear:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'clear' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationAssign:
+ error.SetErrorStringWithFormat(
+ "%s objects do not support the 'assign' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationInvalid:
+ error.SetErrorStringWithFormat("invalid operation performed on a %s object",
+ GetTypeAsCString());
+ break;
+ }
+ return error;
+}
Modified: lldb/trunk/source/Interpreter/OptionValueArch.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueArch.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueArch.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueArch.cpp Tue Sep 6 15:57:50 2016
@@ -22,88 +22,65 @@
using namespace lldb;
using namespace lldb_private;
-void
-OptionValueArch::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
+void OptionValueArch::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
+ uint32_t dump_mask) {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf("(%s)", GetTypeAsCString());
+ if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- strm.Printf ("(%s)", GetTypeAsCString ());
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.PutCString (" = ");
-
- if (m_current_value.IsValid())
- {
- const char *arch_name = m_current_value.GetArchitectureName();
- if (arch_name)
- strm.PutCString (arch_name);
- }
- }
-}
+ strm.PutCString(" = ");
-Error
-OptionValueArch::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
- Error error;
- switch (op)
- {
- case eVarSetOperationClear:
- Clear();
- NotifyValueChanged();
- break;
-
- case eVarSetOperationReplace:
- case eVarSetOperationAssign:
- {
- std::string value_str = value.trim().str();
- if (m_current_value.SetTriple (value_str.c_str()))
- {
- m_value_was_set = true;
- NotifyValueChanged();
- }
- else
- error.SetErrorStringWithFormat("unsupported architecture '%s'", value_str.c_str());
- break;
- }
- case eVarSetOperationInsertBefore:
- case eVarSetOperationInsertAfter:
- case eVarSetOperationRemove:
- case eVarSetOperationAppend:
- case eVarSetOperationInvalid:
- error = OptionValue::SetValueFromString (value, op);
- break;
+ if (m_current_value.IsValid()) {
+ const char *arch_name = m_current_value.GetArchitectureName();
+ if (arch_name)
+ strm.PutCString(arch_name);
}
- return error;
+ }
}
-lldb::OptionValueSP
-OptionValueArch::DeepCopy () const
-{
- return OptionValueSP(new OptionValueArch(*this));
+Error OptionValueArch::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Error error;
+ switch (op) {
+ case eVarSetOperationClear:
+ Clear();
+ NotifyValueChanged();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign: {
+ std::string value_str = value.trim().str();
+ if (m_current_value.SetTriple(value_str.c_str())) {
+ m_value_was_set = true;
+ NotifyValueChanged();
+ } else
+ error.SetErrorStringWithFormat("unsupported architecture '%s'",
+ value_str.c_str());
+ break;
+ }
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromString(value, op);
+ break;
+ }
+ return error;
}
-
-size_t
-OptionValueArch::AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- word_complete = false;
- matches.Clear();
- CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
- CommandCompletions::eArchitectureCompletion,
- s,
- match_start_point,
- max_return_elements,
- nullptr,
- word_complete,
- matches);
- return matches.GetSize();
+lldb::OptionValueSP OptionValueArch::DeepCopy() const {
+ return OptionValueSP(new OptionValueArch(*this));
}
-
-
-
+size_t OptionValueArch::AutoComplete(CommandInterpreter &interpreter,
+ const char *s, int match_start_point,
+ int max_return_elements,
+ bool &word_complete, StringList &matches) {
+ word_complete = false;
+ matches.Clear();
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ interpreter, CommandCompletions::eArchitectureCompletion, s,
+ match_start_point, max_return_elements, nullptr, word_complete, matches);
+ return matches.GetSize();
+}
Modified: lldb/trunk/source/Interpreter/OptionValueArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueArgs.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueArgs.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueArgs.cpp Tue Sep 6 15:57:50 2016
@@ -18,21 +18,18 @@
using namespace lldb;
using namespace lldb_private;
-size_t
-OptionValueArgs::GetArgs (Args &args)
-{
- const uint32_t size = m_values.size();
- std::vector<const char *> argv;
- for (uint32_t i = 0; i<size; ++i)
- {
- const char *string_value = m_values[i]->GetStringValue ();
- if (string_value)
- argv.push_back(string_value);
- }
+size_t OptionValueArgs::GetArgs(Args &args) {
+ const uint32_t size = m_values.size();
+ std::vector<const char *> argv;
+ for (uint32_t i = 0; i < size; ++i) {
+ const char *string_value = m_values[i]->GetStringValue();
+ if (string_value)
+ argv.push_back(string_value);
+ }
- if (argv.empty())
- args.Clear();
- else
- args.SetArguments(argv.size(), &argv[0]);
- return args.GetArgumentCount();
+ if (argv.empty())
+ args.Clear();
+ else
+ args.SetArguments(argv.size(), &argv[0]);
+ return args.GetArgumentCount();
}
Modified: lldb/trunk/source/Interpreter/OptionValueArray.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueArray.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueArray.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueArray.cpp Tue Sep 6 15:57:50 2016
@@ -20,340 +20,294 @@
using namespace lldb;
using namespace lldb_private;
-void
-OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
- const Type array_element_type = ConvertTypeMaskToType (m_type_mask);
+void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
+ uint32_t dump_mask) {
+ const Type array_element_type = ConvertTypeMaskToType(m_type_mask);
+ if (dump_mask & eDumpOptionType) {
+ if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
+ strm.Printf("(%s of %ss)", GetTypeAsCString(),
+ GetBuiltinTypeAsCString(array_element_type));
+ else
+ strm.Printf("(%s)", GetTypeAsCString());
+ }
+ if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- {
- if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
- strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type));
- else
- strm.Printf ("(%s)", GetTypeAsCString());
- }
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : "");
- strm.IndentMore();
- const uint32_t size = m_values.size();
- for (uint32_t i = 0; i<size; ++i)
- {
- strm.Indent();
- strm.Printf("[%u]: ", i);
- const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
- switch (array_element_type)
- {
- default:
- case eTypeArray:
- case eTypeDictionary:
- case eTypeProperties:
- case eTypeFileSpecList:
- case eTypePathMap:
- m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
- break;
-
- case eTypeBoolean:
- case eTypeChar:
- case eTypeEnum:
- case eTypeFileSpec:
- case eTypeFormat:
- case eTypeSInt64:
- case eTypeString:
- case eTypeUInt64:
- case eTypeUUID:
- // No need to show the type for dictionaries of simple items
- m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
- break;
- }
- if (i < (size - 1))
- strm.EOL();
- }
- strm.IndentLess();
+ strm.Printf(" =%s", (m_values.size() > 0) ? "\n" : "");
+ strm.IndentMore();
+ const uint32_t size = m_values.size();
+ for (uint32_t i = 0; i < size; ++i) {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+ switch (array_element_type) {
+ default:
+ case eTypeArray:
+ case eTypeDictionary:
+ case eTypeProperties:
+ case eTypeFileSpecList:
+ case eTypePathMap:
+ m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
+ break;
+
+ case eTypeBoolean:
+ case eTypeChar:
+ case eTypeEnum:
+ case eTypeFileSpec:
+ case eTypeFormat:
+ case eTypeSInt64:
+ case eTypeString:
+ case eTypeUInt64:
+ case eTypeUUID:
+ // No need to show the type for dictionaries of simple items
+ m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) |
+ extra_dump_options);
+ break;
+ }
+ if (i < (size - 1))
+ strm.EOL();
}
+ strm.IndentLess();
+ }
}
-Error
-OptionValueArray::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
- Args args(value.str().c_str());
- Error error = SetArgs (args, op);
- if (error.Success())
- NotifyValueChanged();
- return error;
+Error OptionValueArray::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Args args(value.str().c_str());
+ Error error = SetArgs(args, op);
+ if (error.Success())
+ NotifyValueChanged();
+ return error;
}
-
lldb::OptionValueSP
-OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx,
- const char *name,
- bool will_modify,
- Error &error) const
-{
- if (name && name[0] == '[')
- {
- const char *end_bracket = strchr (name+1, ']');
- if (end_bracket)
- {
- const char *sub_value = nullptr;
- if (end_bracket[1])
- sub_value = end_bracket + 1;
- std::string index_str (name+1, end_bracket);
- const size_t array_count = m_values.size();
- int32_t idx = StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr);
- if (idx != INT32_MAX)
- {
- ;
- uint32_t new_idx = UINT32_MAX;
- if (idx < 0)
- {
- // Access from the end of the array if the index is negative
- new_idx = array_count - idx;
- }
- else
- {
- // Just a standard index
- new_idx = idx;
- }
-
- if (new_idx < array_count)
- {
- if (m_values[new_idx])
- {
- if (sub_value)
- return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error);
- else
- return m_values[new_idx];
- }
- }
- else
- {
- if (array_count == 0)
- error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx);
- else if (idx > 0)
- error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %" PRIu64, idx, (uint64_t)(array_count - 1));
- else
- error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%" PRIu64, idx, (uint64_t)array_count);
- }
- }
+OptionValueArray::GetSubValue(const ExecutionContext *exe_ctx, const char *name,
+ bool will_modify, Error &error) const {
+ if (name && name[0] == '[') {
+ const char *end_bracket = strchr(name + 1, ']');
+ if (end_bracket) {
+ const char *sub_value = nullptr;
+ if (end_bracket[1])
+ sub_value = end_bracket + 1;
+ std::string index_str(name + 1, end_bracket);
+ const size_t array_count = m_values.size();
+ int32_t idx =
+ StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr);
+ if (idx != INT32_MAX) {
+ ;
+ uint32_t new_idx = UINT32_MAX;
+ if (idx < 0) {
+ // Access from the end of the array if the index is negative
+ new_idx = array_count - idx;
+ } else {
+ // Just a standard index
+ new_idx = idx;
}
+
+ if (new_idx < array_count) {
+ if (m_values[new_idx]) {
+ if (sub_value)
+ return m_values[new_idx]->GetSubValue(exe_ctx, sub_value,
+ will_modify, error);
+ else
+ return m_values[new_idx];
+ }
+ } else {
+ if (array_count == 0)
+ error.SetErrorStringWithFormat(
+ "index %i is not valid for an empty array", idx);
+ else if (idx > 0)
+ error.SetErrorStringWithFormat(
+ "index %i out of range, valid values are 0 through %" PRIu64,
+ idx, (uint64_t)(array_count - 1));
+ else
+ error.SetErrorStringWithFormat("negative index %i out of range, "
+ "valid values are -1 through "
+ "-%" PRIu64,
+ idx, (uint64_t)array_count);
+ }
+ }
}
- else
- {
- error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString());
- }
- return OptionValueSP();
+ } else {
+ error.SetErrorStringWithFormat(
+ "invalid value path '%s', %s values only support '[<index>]' subvalues "
+ "where <index> is a positive or negative array index",
+ name, GetTypeAsCString());
+ }
+ return OptionValueSP();
}
-
-size_t
-OptionValueArray::GetArgs (Args &args) const
-{
- const uint32_t size = m_values.size();
- std::vector<const char *> argv;
- for (uint32_t i = 0; i<size; ++i)
- {
- const char *string_value = m_values[i]->GetStringValue ();
- if (string_value)
- argv.push_back(string_value);
- }
-
- if (argv.empty())
- args.Clear();
- else
- args.SetArguments(argv.size(), &argv[0]);
- return args.GetArgumentCount();
+size_t OptionValueArray::GetArgs(Args &args) const {
+ const uint32_t size = m_values.size();
+ std::vector<const char *> argv;
+ for (uint32_t i = 0; i < size; ++i) {
+ const char *string_value = m_values[i]->GetStringValue();
+ if (string_value)
+ argv.push_back(string_value);
+ }
+
+ if (argv.empty())
+ args.Clear();
+ else
+ args.SetArguments(argv.size(), &argv[0]);
+ return args.GetArgumentCount();
}
-Error
-OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
-{
- Error error;
- const size_t argc = args.GetArgumentCount();
- switch (op)
- {
- case eVarSetOperationInvalid:
- error.SetErrorString("unsupported operation");
- break;
-
- case eVarSetOperationInsertBefore:
- case eVarSetOperationInsertAfter:
- if (argc > 1)
- {
- uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
- const uint32_t count = GetSize();
- if (idx > count)
- {
- error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count);
- }
- else
- {
- if (op == eVarSetOperationInsertAfter)
- ++idx;
- for (size_t i=1; i<argc; ++i, ++idx)
- {
- lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
- m_type_mask,
- error));
- if (value_sp)
- {
- if (error.Fail())
- return error;
- if (idx >= m_values.size())
- m_values.push_back(value_sp);
- else
- m_values.insert(m_values.begin() + idx, value_sp);
- }
- else
- {
- error.SetErrorString("array of complex types must subclass OptionValueArray");
- return error;
- }
- }
- }
- }
- else
- {
- error.SetErrorString("insert operation takes an array index followed by one or more values");
- }
- break;
-
- case eVarSetOperationRemove:
- if (argc > 0)
- {
- const uint32_t size = m_values.size();
- std::vector<int> remove_indexes;
- bool all_indexes_valid = true;
- size_t i;
- for (i=0; i<argc; ++i)
- {
- const size_t idx =
- StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
- if (idx >= size)
- {
- all_indexes_valid = false;
- break;
- }
- else
- remove_indexes.push_back(idx);
- }
-
- if (all_indexes_valid)
- {
- size_t num_remove_indexes = remove_indexes.size();
- if (num_remove_indexes)
- {
- // Sort and then erase in reverse so indexes are always valid
- if (num_remove_indexes > 1)
- {
- std::sort(remove_indexes.begin(), remove_indexes.end());
- for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos)
- {
- m_values.erase(m_values.begin() + *pos);
- }
- }
- else
- {
- // Only one index
- m_values.erase(m_values.begin() + remove_indexes.front());
- }
- }
- }
+Error OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
+ Error error;
+ const size_t argc = args.GetArgumentCount();
+ switch (op) {
+ case eVarSetOperationInvalid:
+ error.SetErrorString("unsupported operation");
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ if (argc > 1) {
+ uint32_t idx =
+ StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = GetSize();
+ if (idx > count) {
+ error.SetErrorStringWithFormat(
+ "invalid insert array index %u, index must be 0 through %u", idx,
+ count);
+ } else {
+ if (op == eVarSetOperationInsertAfter)
+ ++idx;
+ for (size_t i = 1; i < argc; ++i, ++idx) {
+ lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+ args.GetArgumentAtIndex(i), m_type_mask, error));
+ if (value_sp) {
+ if (error.Fail())
+ return error;
+ if (idx >= m_values.size())
+ m_values.push_back(value_sp);
else
- {
- error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
- }
+ m_values.insert(m_values.begin() + idx, value_sp);
+ } else {
+ error.SetErrorString(
+ "array of complex types must subclass OptionValueArray");
+ return error;
+ }
}
- else
- {
- error.SetErrorString("remove operation takes one or more array indices");
- }
- break;
-
- case eVarSetOperationClear:
- Clear ();
- break;
-
- case eVarSetOperationReplace:
- if (argc > 1)
- {
- uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
- const uint32_t count = GetSize();
- if (idx > count)
- {
- error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count);
- }
- else
- {
- for (size_t i=1; i<argc; ++i, ++idx)
- {
- lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
- m_type_mask,
- error));
- if (value_sp)
- {
- if (error.Fail())
- return error;
- if (idx < count)
- m_values[idx] = value_sp;
- else
- m_values.push_back(value_sp);
- }
- else
- {
- error.SetErrorString("array of complex types must subclass OptionValueArray");
- return error;
- }
- }
- }
- }
- else
- {
- error.SetErrorString("replace operation takes an array index followed by one or more values");
+ }
+ } else {
+ error.SetErrorString("insert operation takes an array index followed by "
+ "one or more values");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0) {
+ const uint32_t size = m_values.size();
+ std::vector<int> remove_indexes;
+ bool all_indexes_valid = true;
+ size_t i;
+ for (i = 0; i < argc; ++i) {
+ const size_t idx =
+ StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+ if (idx >= size) {
+ all_indexes_valid = false;
+ break;
+ } else
+ remove_indexes.push_back(idx);
+ }
+
+ if (all_indexes_valid) {
+ size_t num_remove_indexes = remove_indexes.size();
+ if (num_remove_indexes) {
+ // Sort and then erase in reverse so indexes are always valid
+ if (num_remove_indexes > 1) {
+ std::sort(remove_indexes.begin(), remove_indexes.end());
+ for (std::vector<int>::const_reverse_iterator
+ pos = remove_indexes.rbegin(),
+ end = remove_indexes.rend();
+ pos != end; ++pos) {
+ m_values.erase(m_values.begin() + *pos);
+ }
+ } else {
+ // Only one index
+ m_values.erase(m_values.begin() + remove_indexes.front());
+ }
}
- break;
-
- case eVarSetOperationAssign:
- m_values.clear();
- // Fall through to append case
- LLVM_FALLTHROUGH;
- case eVarSetOperationAppend:
- for (size_t i=0; i<argc; ++i)
- {
- lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
- m_type_mask,
- error));
- if (value_sp)
- {
- if (error.Fail())
- return error;
- m_value_was_set = true;
- AppendValue(value_sp);
- }
+ } else {
+ error.SetErrorStringWithFormat(
+ "invalid array index '%s', aborting remove operation",
+ args.GetArgumentAtIndex(i));
+ }
+ } else {
+ error.SetErrorString("remove operation takes one or more array indices");
+ }
+ break;
+
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ if (argc > 1) {
+ uint32_t idx =
+ StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = GetSize();
+ if (idx > count) {
+ error.SetErrorStringWithFormat(
+ "invalid replace array index %u, index must be 0 through %u", idx,
+ count);
+ } else {
+ for (size_t i = 1; i < argc; ++i, ++idx) {
+ lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+ args.GetArgumentAtIndex(i), m_type_mask, error));
+ if (value_sp) {
+ if (error.Fail())
+ return error;
+ if (idx < count)
+ m_values[idx] = value_sp;
else
- {
- error.SetErrorString("array of complex types must subclass OptionValueArray");
- }
+ m_values.push_back(value_sp);
+ } else {
+ error.SetErrorString(
+ "array of complex types must subclass OptionValueArray");
+ return error;
+ }
}
- break;
+ }
+ } else {
+ error.SetErrorString("replace operation takes an array index followed by "
+ "one or more values");
}
- return error;
-}
+ break;
-lldb::OptionValueSP
-OptionValueArray::DeepCopy () const
-{
- OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump);
- lldb::OptionValueSP copied_value_sp(copied_array);
- *static_cast<OptionValue *>(copied_array) = *this;
- copied_array->m_callback = m_callback;
- const uint32_t size = m_values.size();
- for (uint32_t i = 0; i<size; ++i)
- {
- copied_array->AppendValue (m_values[i]->DeepCopy());
+ case eVarSetOperationAssign:
+ m_values.clear();
+ // Fall through to append case
+ LLVM_FALLTHROUGH;
+ case eVarSetOperationAppend:
+ for (size_t i = 0; i < argc; ++i) {
+ lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+ args.GetArgumentAtIndex(i), m_type_mask, error));
+ if (value_sp) {
+ if (error.Fail())
+ return error;
+ m_value_was_set = true;
+ AppendValue(value_sp);
+ } else {
+ error.SetErrorString(
+ "array of complex types must subclass OptionValueArray");
+ }
}
- return copied_value_sp;
+ break;
+ }
+ return error;
}
-
-
+lldb::OptionValueSP OptionValueArray::DeepCopy() const {
+ OptionValueArray *copied_array =
+ new OptionValueArray(m_type_mask, m_raw_value_dump);
+ lldb::OptionValueSP copied_value_sp(copied_array);
+ *static_cast<OptionValue *>(copied_array) = *this;
+ copied_array->m_callback = m_callback;
+ const uint32_t size = m_values.size();
+ for (uint32_t i = 0; i < size; ++i) {
+ copied_array->AppendValue(m_values[i]->DeepCopy());
+ }
+ return copied_value_sp;
+}
Modified: lldb/trunk/source/Interpreter/OptionValueBoolean.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueBoolean.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueBoolean.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueBoolean.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- OptionValueBoolean.cpp ------------------------------------*- C++ -*-===//
+//===-- OptionValueBoolean.cpp ------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,117 +23,90 @@
using namespace lldb;
using namespace lldb_private;
-void
-OptionValueBoolean::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
+void OptionValueBoolean::DumpValue(const ExecutionContext *exe_ctx,
+ Stream &strm, uint32_t dump_mask) {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf("(%s)", GetTypeAsCString());
+ // if (dump_mask & eDumpOptionName)
+ // DumpQualifiedName (strm);
+ if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- strm.Printf ("(%s)", GetTypeAsCString ());
-// if (dump_mask & eDumpOptionName)
-// DumpQualifiedName (strm);
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.PutCString (" = ");
- strm.PutCString (m_current_value ? "true" : "false");
- }
+ strm.PutCString(" = ");
+ strm.PutCString(m_current_value ? "true" : "false");
+ }
}
-Error
-OptionValueBoolean::SetValueFromString (llvm::StringRef value_str,
- VarSetOperationType op)
-{
- Error error;
- switch (op)
- {
- case eVarSetOperationClear:
- Clear();
- NotifyValueChanged();
- break;
-
- case eVarSetOperationReplace:
- case eVarSetOperationAssign:
- {
- bool success = false;
- bool value = Args::StringToBoolean(value_str.str().c_str(), false, &success);
- if (success)
- {
- m_value_was_set = true;
- m_current_value = value;
- NotifyValueChanged();
- }
- else
- {
- if (value_str.size() == 0)
- error.SetErrorString ("invalid boolean string value <empty>");
- else
- error.SetErrorStringWithFormat ("invalid boolean string value: '%s'",
- value_str.str().c_str());
- }
- }
- break;
-
- case eVarSetOperationInsertBefore:
- case eVarSetOperationInsertAfter:
- case eVarSetOperationRemove:
- case eVarSetOperationAppend:
- case eVarSetOperationInvalid:
- error = OptionValue::SetValueFromString (value_str, op);
- break;
+Error OptionValueBoolean::SetValueFromString(llvm::StringRef value_str,
+ VarSetOperationType op) {
+ Error error;
+ switch (op) {
+ case eVarSetOperationClear:
+ Clear();
+ NotifyValueChanged();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign: {
+ bool success = false;
+ bool value =
+ Args::StringToBoolean(value_str.str().c_str(), false, &success);
+ if (success) {
+ m_value_was_set = true;
+ m_current_value = value;
+ NotifyValueChanged();
+ } else {
+ if (value_str.size() == 0)
+ error.SetErrorString("invalid boolean string value <empty>");
+ else
+ error.SetErrorStringWithFormat("invalid boolean string value: '%s'",
+ value_str.str().c_str());
}
- return error;
+ } break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromString(value_str, op);
+ break;
+ }
+ return error;
}
-lldb::OptionValueSP
-OptionValueBoolean::DeepCopy () const
-{
- return OptionValueSP(new OptionValueBoolean(*this));
+lldb::OptionValueSP OptionValueBoolean::DeepCopy() const {
+ return OptionValueSP(new OptionValueBoolean(*this));
}
-size_t
-OptionValueBoolean::AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- word_complete = false;
- matches.Clear();
- struct StringEntry {
- const char *string;
- const size_t length;
- };
- static const StringEntry g_autocomplete_entries[] =
- {
- { "true" , 4 },
- { "false", 5 },
- { "on" , 2 },
- { "off" , 3 },
- { "yes" , 3 },
- { "no" , 2 },
- { "1" , 1 },
- { "0" , 1 },
- };
- const size_t k_num_autocomplete_entries = llvm::array_lengthof(g_autocomplete_entries);
-
- if (s && s[0])
- {
- const size_t s_len = strlen(s);
- for (size_t i=0; i<k_num_autocomplete_entries; ++i)
- {
- if (s_len <= g_autocomplete_entries[i].length)
- if (::strncasecmp(s, g_autocomplete_entries[i].string, s_len) == 0)
- matches.AppendString(g_autocomplete_entries[i].string);
- }
- }
- else
- {
- // only suggest "true" or "false" by default
- for (size_t i=0; i<2; ++i)
- matches.AppendString(g_autocomplete_entries[i].string);
+size_t OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter,
+ const char *s, int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) {
+ word_complete = false;
+ matches.Clear();
+ struct StringEntry {
+ const char *string;
+ const size_t length;
+ };
+ static const StringEntry g_autocomplete_entries[] = {
+ {"true", 4}, {"false", 5}, {"on", 2}, {"off", 3},
+ {"yes", 3}, {"no", 2}, {"1", 1}, {"0", 1},
+ };
+ const size_t k_num_autocomplete_entries =
+ llvm::array_lengthof(g_autocomplete_entries);
+
+ if (s && s[0]) {
+ const size_t s_len = strlen(s);
+ for (size_t i = 0; i < k_num_autocomplete_entries; ++i) {
+ if (s_len <= g_autocomplete_entries[i].length)
+ if (::strncasecmp(s, g_autocomplete_entries[i].string, s_len) == 0)
+ matches.AppendString(g_autocomplete_entries[i].string);
}
- return matches.GetSize();
+ } else {
+ // only suggest "true" or "false" by default
+ for (size_t i = 0; i < 2; ++i)
+ matches.AppendString(g_autocomplete_entries[i].string);
+ }
+ return matches.GetSize();
}
-
-
-
Modified: lldb/trunk/source/Interpreter/OptionValueChar.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueChar.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueChar.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueChar.cpp Tue Sep 6 15:57:50 2016
@@ -21,60 +21,48 @@
using namespace lldb;
using namespace lldb_private;
-void
-OptionValueChar::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
- if (dump_mask & eDumpOptionType)
- strm.Printf ("(%s)", GetTypeAsCString ());
+void OptionValueChar::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
+ uint32_t dump_mask) {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf("(%s)", GetTypeAsCString());
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.PutCString (" = ");
- if (m_current_value != '\0')
- strm.PutChar(m_current_value);
- else
- strm.PutCString("(null)");
- }
+ if (dump_mask & eDumpOptionValue) {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString(" = ");
+ if (m_current_value != '\0')
+ strm.PutChar(m_current_value);
+ else
+ strm.PutCString("(null)");
+ }
}
-Error
-OptionValueChar::SetValueFromString (llvm::StringRef value,
- VarSetOperationType op)
-{
- Error error;
- switch (op)
- {
- case eVarSetOperationClear:
- Clear();
- break;
-
- case eVarSetOperationReplace:
- case eVarSetOperationAssign:
- {
- bool success = false;
- char char_value = Args::StringToChar(value.str().c_str(), '\0', &success);
- if (success)
- {
- m_current_value = char_value;
- m_value_was_set = true;
- }
- else
- error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character", value.str().c_str());
- }
- break;
-
- default:
- error = OptionValue::SetValueFromString (value.str().c_str(), op);
- break;
- }
- return error;
+Error OptionValueChar::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Error error;
+ switch (op) {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign: {
+ bool success = false;
+ char char_value = Args::StringToChar(value.str().c_str(), '\0', &success);
+ if (success) {
+ m_current_value = char_value;
+ m_value_was_set = true;
+ } else
+ error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character",
+ value.str().c_str());
+ } break;
+
+ default:
+ error = OptionValue::SetValueFromString(value.str().c_str(), op);
+ break;
+ }
+ return error;
}
-lldb::OptionValueSP
-OptionValueChar::DeepCopy () const
-{
- return OptionValueSP(new OptionValueChar(*this));
+lldb::OptionValueSP OptionValueChar::DeepCopy() const {
+ return OptionValueSP(new OptionValueChar(*this));
}
-
-
Modified: lldb/trunk/source/Interpreter/OptionValueDictionary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueDictionary.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueDictionary.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueDictionary.cpp Tue Sep 6 15:57:50 2016
@@ -22,423 +22,371 @@
using namespace lldb;
using namespace lldb_private;
-void
-OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
- const Type dict_type = ConvertTypeMaskToType (m_type_mask);
+void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx,
+ Stream &strm, uint32_t dump_mask) {
+ const Type dict_type = ConvertTypeMaskToType(m_type_mask);
+ if (dump_mask & eDumpOptionType) {
+ if (m_type_mask != eTypeInvalid)
+ strm.Printf("(%s of %ss)", GetTypeAsCString(),
+ GetBuiltinTypeAsCString(dict_type));
+ else
+ strm.Printf("(%s)", GetTypeAsCString());
+ }
+ if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- {
- if (m_type_mask != eTypeInvalid)
- strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type));
- else
- strm.Printf ("(%s)", GetTypeAsCString());
- }
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.PutCString (" =");
-
- collection::iterator pos, end = m_values.end();
-
- strm.IndentMore();
-
- for (pos = m_values.begin(); pos != end; ++pos)
- {
- OptionValue *option_value = pos->second.get();
- strm.EOL();
- strm.Indent(pos->first.GetCString());
-
- const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
- switch (dict_type)
- {
- default:
- case eTypeArray:
- case eTypeDictionary:
- case eTypeProperties:
- case eTypeFileSpecList:
- case eTypePathMap:
- strm.PutChar (' ');
- option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
- break;
-
- case eTypeBoolean:
- case eTypeChar:
- case eTypeEnum:
- case eTypeFileSpec:
- case eTypeFormat:
- case eTypeSInt64:
- case eTypeString:
- case eTypeUInt64:
- case eTypeUUID:
- // No need to show the type for dictionaries of simple items
- strm.PutCString("=");
- option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
- break;
- }
- }
- strm.IndentLess();
- }
+ strm.PutCString(" =");
-}
+ collection::iterator pos, end = m_values.end();
+
+ strm.IndentMore();
-size_t
-OptionValueDictionary::GetArgs (Args &args) const
-{
- args.Clear();
- collection::const_iterator pos, end = m_values.end();
- for (pos = m_values.begin(); pos != end; ++pos)
- {
- StreamString strm;
- strm.Printf("%s=", pos->first.GetCString());
- pos->second->DumpValue(nullptr, strm, eDumpOptionValue|eDumpOptionRaw);
- args.AppendArgument(strm.GetString().c_str());
+ for (pos = m_values.begin(); pos != end; ++pos) {
+ OptionValue *option_value = pos->second.get();
+ strm.EOL();
+ strm.Indent(pos->first.GetCString());
+
+ const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+ switch (dict_type) {
+ default:
+ case eTypeArray:
+ case eTypeDictionary:
+ case eTypeProperties:
+ case eTypeFileSpecList:
+ case eTypePathMap:
+ strm.PutChar(' ');
+ option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
+ break;
+
+ case eTypeBoolean:
+ case eTypeChar:
+ case eTypeEnum:
+ case eTypeFileSpec:
+ case eTypeFormat:
+ case eTypeSInt64:
+ case eTypeString:
+ case eTypeUInt64:
+ case eTypeUUID:
+ // No need to show the type for dictionaries of simple items
+ strm.PutCString("=");
+ option_value->DumpValue(exe_ctx, strm,
+ (dump_mask & (~eDumpOptionType)) |
+ extra_dump_options);
+ break;
+ }
}
- return args.GetArgumentCount();
+ strm.IndentLess();
+ }
}
-Error
-OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
-{
- Error error;
- const size_t argc = args.GetArgumentCount();
- switch (op)
- {
- case eVarSetOperationClear:
- Clear();
- break;
-
- case eVarSetOperationAppend:
- case eVarSetOperationReplace:
- case eVarSetOperationAssign:
- if (argc > 0)
- {
- for (size_t i=0; i<argc; ++i)
- {
- llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
- if (!key_and_value.empty())
- {
- if (key_and_value.find('=') == llvm::StringRef::npos)
- {
- error.SetErrorString("assign operation takes one or more key=value arguments");
- return error;
- }
-
- std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('='));
- llvm::StringRef key = kvp.first;
- bool key_valid = false;
- if (!key.empty())
- {
- if (key.front() == '[')
- {
- // Key name starts with '[', so the key value must be in single or double quotes like:
- // ['<key>']
- // ["<key>"]
- if ((key.size() > 2) && (key.back() == ']'))
- {
- // Strip leading '[' and trailing ']'
- key = key.substr(1, key.size()-2);
- const char quote_char = key.front();
- if ((quote_char == '\'') || (quote_char == '"'))
- {
- if ((key.size() > 2) && (key.back() == quote_char))
- {
- // Strip the quotes
- key = key.substr(1, key.size()-2);
- key_valid = true;
- }
- }
- else
- {
- // square brackets, no quotes
- key_valid = true;
- }
- }
- }
- else
- {
- // No square brackets or quotes
- key_valid = true;
- }
- }
- if (!key_valid)
- {
- error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str());
- return error;
- }
-
- lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(),
- m_type_mask,
- error));
- if (value_sp)
- {
- if (error.Fail())
- return error;
- m_value_was_set = true;
- SetValueForKey (ConstString(key), value_sp, true);
- }
- else
- {
- error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray");
- }
- }
- else
- {
- error.SetErrorString("empty argument");
+size_t OptionValueDictionary::GetArgs(Args &args) const {
+ args.Clear();
+ collection::const_iterator pos, end = m_values.end();
+ for (pos = m_values.begin(); pos != end; ++pos) {
+ StreamString strm;
+ strm.Printf("%s=", pos->first.GetCString());
+ pos->second->DumpValue(nullptr, strm, eDumpOptionValue | eDumpOptionRaw);
+ args.AppendArgument(strm.GetString().c_str());
+ }
+ return args.GetArgumentCount();
+}
+
+Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) {
+ Error error;
+ const size_t argc = args.GetArgumentCount();
+ switch (op) {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationAppend:
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (argc > 0) {
+ for (size_t i = 0; i < argc; ++i) {
+ llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
+ if (!key_and_value.empty()) {
+ if (key_and_value.find('=') == llvm::StringRef::npos) {
+ error.SetErrorString(
+ "assign operation takes one or more key=value arguments");
+ return error;
+ }
+
+ std::pair<llvm::StringRef, llvm::StringRef> kvp(
+ key_and_value.split('='));
+ llvm::StringRef key = kvp.first;
+ bool key_valid = false;
+ if (!key.empty()) {
+ if (key.front() == '[') {
+ // Key name starts with '[', so the key value must be in single or
+ // double quotes like:
+ // ['<key>']
+ // ["<key>"]
+ if ((key.size() > 2) && (key.back() == ']')) {
+ // Strip leading '[' and trailing ']'
+ key = key.substr(1, key.size() - 2);
+ const char quote_char = key.front();
+ if ((quote_char == '\'') || (quote_char == '"')) {
+ if ((key.size() > 2) && (key.back() == quote_char)) {
+ // Strip the quotes
+ key = key.substr(1, key.size() - 2);
+ key_valid = true;
+ }
+ } else {
+ // square brackets, no quotes
+ key_valid = true;
}
+ }
+ } else {
+ // No square brackets or quotes
+ key_valid = true;
}
+ }
+ if (!key_valid) {
+ error.SetErrorStringWithFormat(
+ "invalid key \"%s\", the key must be a bare string or "
+ "surrounded by brackets with optional quotes: [<key>] or "
+ "['<key>'] or [\"<key>\"]",
+ kvp.first.str().c_str());
+ return error;
+ }
+
+ lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+ kvp.second.data(), m_type_mask, error));
+ if (value_sp) {
+ if (error.Fail())
+ return error;
+ m_value_was_set = true;
+ SetValueForKey(ConstString(key), value_sp, true);
+ } else {
+ error.SetErrorString("dictionaries that can contain multiple types "
+ "must subclass OptionValueArray");
+ }
+ } else {
+ error.SetErrorString("empty argument");
}
- else
- {
- error.SetErrorString("assign operation takes one or more key=value arguments");
+ }
+ } else {
+ error.SetErrorString(
+ "assign operation takes one or more key=value arguments");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0) {
+ for (size_t i = 0; i < argc; ++i) {
+ ConstString key(args.GetArgumentAtIndex(i));
+ if (!DeleteValueForKey(key)) {
+ error.SetErrorStringWithFormat(
+ "no value found named '%s', aborting remove operation",
+ key.GetCString());
+ break;
}
- break;
-
- case eVarSetOperationRemove:
- if (argc > 0)
- {
- for (size_t i=0; i<argc; ++i)
- {
- ConstString key(args.GetArgumentAtIndex(i));
- if (!DeleteValueForKey(key))
- {
- error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString());
- break;
- }
- }
+ }
+ } else {
+ error.SetErrorString("remove operation takes one or more key arguments");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromString(llvm::StringRef(), op);
+ break;
+ }
+ return error;
+}
+
+Error OptionValueDictionary::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Args args(value.str().c_str());
+ Error error = SetArgs(args, op);
+ if (error.Success())
+ NotifyValueChanged();
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx,
+ const char *name, bool will_modify,
+ Error &error) const {
+ lldb::OptionValueSP value_sp;
+
+ if (name && name[0]) {
+ const char *sub_name = nullptr;
+ ConstString key;
+ const char *open_bracket = ::strchr(name, '[');
+
+ if (open_bracket) {
+ const char *key_start = open_bracket + 1;
+ const char *key_end = nullptr;
+ switch (open_bracket[1]) {
+ case '\'':
+ ++key_start;
+ key_end = strchr(key_start, '\'');
+ if (key_end) {
+ if (key_end[1] == ']') {
+ if (key_end[2])
+ sub_name = key_end + 2;
+ } else {
+ error.SetErrorStringWithFormat("invalid value path '%s', single "
+ "quoted key names must be formatted "
+ "as ['<key>'] where <key> is a "
+ "string that doesn't contain quotes",
+ name);
+ return value_sp;
+ }
+ } else {
+ error.SetErrorString(
+ "missing '] key name terminator, key name started with ['");
+ return value_sp;
}
- else
- {
- error.SetErrorString("remove operation takes one or more key arguments");
+ break;
+ case '"':
+ ++key_start;
+ key_end = strchr(key_start, '"');
+ if (key_end) {
+ if (key_end[1] == ']') {
+ if (key_end[2])
+ sub_name = key_end + 2;
+ break;
+ }
+ error.SetErrorStringWithFormat("invalid value path '%s', double "
+ "quoted key names must be formatted "
+ "as [\"<key>\"] where <key> is a "
+ "string that doesn't contain quotes",
+ name);
+ return value_sp;
+ } else {
+ error.SetErrorString(
+ "missing \"] key name terminator, key name started with [\"");
+ return value_sp;
}
break;
-
- case eVarSetOperationInsertBefore:
- case eVarSetOperationInsertAfter:
- case eVarSetOperationInvalid:
- error = OptionValue::SetValueFromString (llvm::StringRef(), op);
+
+ default:
+ key_end = strchr(key_start, ']');
+ if (key_end) {
+ if (key_end[1])
+ sub_name = key_end + 1;
+ } else {
+ error.SetErrorString(
+ "missing ] key name terminator, key name started with [");
+ return value_sp;
+ }
break;
- }
- return error;
-}
+ }
-Error
-OptionValueDictionary::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
- Args args(value.str().c_str());
- Error error = SetArgs (args, op);
- if (error.Success())
- NotifyValueChanged();
- return error;
-}
+ if (key_start && key_end) {
+ key.SetCStringWithLength(key_start, key_end - key_start);
-lldb::OptionValueSP
-OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char *name, bool will_modify, Error &error) const
-{
- lldb::OptionValueSP value_sp;
-
- if (name && name[0])
- {
- const char *sub_name = nullptr;
- ConstString key;
- const char *open_bracket = ::strchr (name, '[');
-
- if (open_bracket)
- {
- const char *key_start = open_bracket + 1;
- const char *key_end = nullptr;
- switch (open_bracket[1])
- {
- case '\'':
- ++key_start;
- key_end = strchr(key_start, '\'');
- if (key_end)
- {
- if (key_end[1] == ']')
- {
- if (key_end[2])
- sub_name = key_end + 2;
- }
- else
- {
- error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as ['<key>'] where <key> is a string that doesn't contain quotes", name);
- return value_sp;
- }
- }
- else
- {
- error.SetErrorString ("missing '] key name terminator, key name started with ['");
- return value_sp;
- }
- break;
- case '"':
- ++key_start;
- key_end = strchr(key_start, '"');
- if (key_end)
- {
- if (key_end[1] == ']')
- {
- if (key_end[2])
- sub_name = key_end + 2;
- break;
- }
- error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"<key>\"] where <key> is a string that doesn't contain quotes", name);
- return value_sp;
- }
- else
- {
- error.SetErrorString ("missing \"] key name terminator, key name started with [\"");
- return value_sp;
- }
- break;
-
- default:
- key_end = strchr(key_start, ']');
- if (key_end)
- {
- if (key_end[1])
- sub_name = key_end + 1;
- }
- else
- {
- error.SetErrorString ("missing ] key name terminator, key name started with [");
- return value_sp;
- }
- break;
- }
-
- if (key_start && key_end)
- {
- key.SetCStringWithLength (key_start, key_end - key_start);
-
- value_sp = GetValueForKey (key);
- if (value_sp)
- {
- if (sub_name)
- return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
- }
- else
- {
- error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString());
- }
- }
- }
- if (!value_sp && error.AsCString() == nullptr)
- {
- error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimited by single or double quotes",
- name,
- GetTypeAsCString());
+ value_sp = GetValueForKey(key);
+ if (value_sp) {
+ if (sub_name)
+ return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
+ } else {
+ error.SetErrorStringWithFormat(
+ "dictionary does not contain a value for the key name '%s'",
+ key.GetCString());
}
+ }
}
- return value_sp;
+ if (!value_sp && error.AsCString() == nullptr) {
+ error.SetErrorStringWithFormat("invalid value path '%s', %s values only "
+ "support '[<key>]' subvalues where <key> "
+ "a string value optionally delimited by "
+ "single or double quotes",
+ name, GetTypeAsCString());
+ }
+ }
+ return value_sp;
+}
+
+Error OptionValueDictionary::SetSubValue(const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *name, const char *value) {
+ Error error;
+ const bool will_modify = true;
+ lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
+ if (value_sp)
+ error = value_sp->SetValueFromString(value, op);
+ else {
+ if (error.AsCString() == nullptr)
+ error.SetErrorStringWithFormat("invalid value path '%s'", name);
+ }
+ return error;
}
-Error
-OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value)
-{
- Error error;
- const bool will_modify = true;
- lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
- if (value_sp)
- error = value_sp->SetValueFromString(value, op);
- else
- {
- if (error.AsCString() == nullptr)
- error.SetErrorStringWithFormat("invalid value path '%s'", name);
- }
- return error;
-}
-
-
lldb::OptionValueSP
-OptionValueDictionary::GetValueForKey (const ConstString &key) const
-{
- lldb::OptionValueSP value_sp;
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- value_sp = pos->second;
- return value_sp;
+OptionValueDictionary::GetValueForKey(const ConstString &key) const {
+ lldb::OptionValueSP value_sp;
+ collection::const_iterator pos = m_values.find(key);
+ if (pos != m_values.end())
+ value_sp = pos->second;
+ return value_sp;
}
const char *
-OptionValueDictionary::GetStringValueForKey (const ConstString &key)
-{
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- OptionValueString *string_value = pos->second->GetAsString();
- if (string_value)
- return string_value->GetCurrentValue();
+OptionValueDictionary::GetStringValueForKey(const ConstString &key) {
+ collection::const_iterator pos = m_values.find(key);
+ if (pos != m_values.end()) {
+ OptionValueString *string_value = pos->second->GetAsString();
+ if (string_value)
+ return string_value->GetCurrentValue();
+ }
+ return nullptr;
+}
+
+bool OptionValueDictionary::SetStringValueForKey(const ConstString &key,
+ const char *value,
+ bool can_replace) {
+ collection::const_iterator pos = m_values.find(key);
+ if (pos != m_values.end()) {
+ if (!can_replace)
+ return false;
+ if (pos->second->GetType() == OptionValue::eTypeString) {
+ pos->second->SetValueFromString(value);
+ return true;
+ }
+ }
+ m_values[key] = OptionValueSP(new OptionValueString(value));
+ return true;
+}
+
+bool OptionValueDictionary::SetValueForKey(const ConstString &key,
+ const lldb::OptionValueSP &value_sp,
+ bool can_replace) {
+ // Make sure the value_sp object is allowed to contain
+ // values of the type passed in...
+ if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
+ if (!can_replace) {
+ collection::const_iterator pos = m_values.find(key);
+ if (pos != m_values.end())
+ return false;
}
- return nullptr;
-}
-
-
-bool
-OptionValueDictionary::SetStringValueForKey (const ConstString &key,
- const char *value,
- bool can_replace)
-{
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- if (!can_replace)
- return false;
- if (pos->second->GetType() == OptionValue::eTypeString)
- {
- pos->second->SetValueFromString(value);
- return true;
- }
- }
- m_values[key] = OptionValueSP (new OptionValueString (value));
+ m_values[key] = value_sp;
return true;
-
-}
-
-bool
-OptionValueDictionary::SetValueForKey (const ConstString &key,
- const lldb::OptionValueSP &value_sp,
- bool can_replace)
-{
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
- if (value_sp && (m_type_mask & value_sp->GetTypeAsMask()))
- {
- if (!can_replace)
- {
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- return false;
- }
- m_values[key] = value_sp;
- return true;
- }
- return false;
+ }
+ return false;
}
-bool
-OptionValueDictionary::DeleteValueForKey (const ConstString &key)
-{
- collection::iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- m_values.erase(pos);
- return true;
- }
- return false;
+bool OptionValueDictionary::DeleteValueForKey(const ConstString &key) {
+ collection::iterator pos = m_values.find(key);
+ if (pos != m_values.end()) {
+ m_values.erase(pos);
+ return true;
+ }
+ return false;
}
-lldb::OptionValueSP
-OptionValueDictionary::DeepCopy () const
-{
- OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump);
- lldb::OptionValueSP copied_value_sp(copied_dict);
- collection::const_iterator pos, end = m_values.end();
- for (pos = m_values.begin(); pos != end; ++pos)
- {
- StreamString strm;
- strm.Printf("%s=", pos->first.GetCString());
- copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true);
- }
- return copied_value_sp;
+lldb::OptionValueSP OptionValueDictionary::DeepCopy() const {
+ OptionValueDictionary *copied_dict =
+ new OptionValueDictionary(m_type_mask, m_raw_value_dump);
+ lldb::OptionValueSP copied_value_sp(copied_dict);
+ collection::const_iterator pos, end = m_values.end();
+ for (pos = m_values.begin(); pos != end; ++pos) {
+ StreamString strm;
+ strm.Printf("%s=", pos->first.GetCString());
+ copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true);
+ }
+ return copied_value_sp;
}
-
Modified: lldb/trunk/source/Interpreter/OptionValueEnumeration.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueEnumeration.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueEnumeration.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueEnumeration.cpp Tue Sep 6 15:57:50 2016
@@ -18,146 +18,115 @@
using namespace lldb;
using namespace lldb_private;
-OptionValueEnumeration::OptionValueEnumeration (const OptionEnumValueElement *enumerators,
- enum_type value) :
- OptionValue(),
- m_current_value (value),
- m_default_value (value),
- m_enumerations ()
-{
- SetEnumerations(enumerators);
-}
-
-OptionValueEnumeration::~OptionValueEnumeration()
-{
-}
-
-void
-OptionValueEnumeration::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
- if (dump_mask & eDumpOptionType)
- strm.Printf ("(%s)", GetTypeAsCString ());
- if (dump_mask & eDumpOptionValue)
- {
- if (dump_mask & eDumpOptionType)
- strm.PutCString (" = ");
- const size_t count = m_enumerations.GetSize ();
- for (size_t i=0; i<count; ++i)
- {
- if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value)
- {
- strm.PutCString(m_enumerations.GetCStringAtIndex(i));
- return;
- }
- }
- strm.Printf("%" PRIu64, (uint64_t)m_current_value);
- }
+OptionValueEnumeration::OptionValueEnumeration(
+ const OptionEnumValueElement *enumerators, enum_type value)
+ : OptionValue(), m_current_value(value), m_default_value(value),
+ m_enumerations() {
+ SetEnumerations(enumerators);
}
-Error
-OptionValueEnumeration::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
- Error error;
- switch (op)
- {
- case eVarSetOperationClear:
- Clear ();
- NotifyValueChanged();
- break;
-
- case eVarSetOperationReplace:
- case eVarSetOperationAssign:
- {
- ConstString const_enumerator_name(value.trim());
- const EnumerationMapEntry *enumerator_entry = m_enumerations.FindFirstValueForName (const_enumerator_name.GetCString());
- if (enumerator_entry)
- {
- m_current_value = enumerator_entry->value.value;
- NotifyValueChanged();
- }
- else
- {
- StreamString error_strm;
- error_strm.Printf("invalid enumeration value '%s'", value.str().c_str());
- const size_t count = m_enumerations.GetSize ();
- if (count)
- {
- error_strm.Printf(", valid values are: %s", m_enumerations.GetCStringAtIndex(0));
- for (size_t i=1; i<count; ++i)
- {
- error_strm.Printf (", %s", m_enumerations.GetCStringAtIndex(i));
- }
- }
- error.SetErrorString(error_strm.GetData());
- }
- break;
- }
-
- case eVarSetOperationInsertBefore:
- case eVarSetOperationInsertAfter:
- case eVarSetOperationRemove:
- case eVarSetOperationAppend:
- case eVarSetOperationInvalid:
- error = OptionValue::SetValueFromString (value, op);
- break;
+OptionValueEnumeration::~OptionValueEnumeration() {}
+
+void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx,
+ Stream &strm, uint32_t dump_mask) {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf("(%s)", GetTypeAsCString());
+ if (dump_mask & eDumpOptionValue) {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString(" = ");
+ const size_t count = m_enumerations.GetSize();
+ for (size_t i = 0; i < count; ++i) {
+ if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) {
+ strm.PutCString(m_enumerations.GetCStringAtIndex(i));
+ return;
+ }
}
- return error;
+ strm.Printf("%" PRIu64, (uint64_t)m_current_value);
+ }
}
-void
-OptionValueEnumeration::SetEnumerations (const OptionEnumValueElement *enumerators)
-{
- m_enumerations.Clear();
- if (enumerators)
- {
- for (size_t i=0; enumerators[i].string_value != nullptr; ++i)
- {
- ConstString const_enumerator_name(enumerators[i].string_value);
- EnumeratorInfo enumerator_info = { enumerators[i].value, enumerators[i].usage };
- m_enumerations.Append (const_enumerator_name.GetCString(), enumerator_info);
+Error OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op) {
+ Error error;
+ switch (op) {
+ case eVarSetOperationClear:
+ Clear();
+ NotifyValueChanged();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign: {
+ ConstString const_enumerator_name(value.trim());
+ const EnumerationMapEntry *enumerator_entry =
+ m_enumerations.FindFirstValueForName(
+ const_enumerator_name.GetCString());
+ if (enumerator_entry) {
+ m_current_value = enumerator_entry->value.value;
+ NotifyValueChanged();
+ } else {
+ StreamString error_strm;
+ error_strm.Printf("invalid enumeration value '%s'", value.str().c_str());
+ const size_t count = m_enumerations.GetSize();
+ if (count) {
+ error_strm.Printf(", valid values are: %s",
+ m_enumerations.GetCStringAtIndex(0));
+ for (size_t i = 1; i < count; ++i) {
+ error_strm.Printf(", %s", m_enumerations.GetCStringAtIndex(i));
}
- m_enumerations.Sort();
+ }
+ error.SetErrorString(error_strm.GetData());
}
-}
-
+ break;
+ }
-lldb::OptionValueSP
-OptionValueEnumeration::DeepCopy () const
-{
- return OptionValueSP(new OptionValueEnumeration(*this));
-}
-
-size_t
-OptionValueEnumeration::AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- word_complete = false;
- matches.Clear();
-
- const uint32_t num_enumerators = m_enumerations.GetSize();
- if (s && s[0])
- {
- const size_t s_len = strlen(s);
- for (size_t i=0; i<num_enumerators; ++i)
- {
- const char *name = m_enumerations.GetCStringAtIndex(i);
- if (::strncmp(s, name, s_len) == 0)
- matches.AppendString(name);
- }
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromString(value, op);
+ break;
+ }
+ return error;
+}
+
+void OptionValueEnumeration::SetEnumerations(
+ const OptionEnumValueElement *enumerators) {
+ m_enumerations.Clear();
+ if (enumerators) {
+ for (size_t i = 0; enumerators[i].string_value != nullptr; ++i) {
+ ConstString const_enumerator_name(enumerators[i].string_value);
+ EnumeratorInfo enumerator_info = {enumerators[i].value,
+ enumerators[i].usage};
+ m_enumerations.Append(const_enumerator_name.GetCString(),
+ enumerator_info);
}
- else
- {
- // only suggest "true" or "false" by default
- for (size_t i=0; i<num_enumerators; ++i)
- matches.AppendString(m_enumerations.GetCStringAtIndex(i));
- }
- return matches.GetSize();
+ m_enumerations.Sort();
+ }
}
+lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
+ return OptionValueSP(new OptionValueEnumeration(*this));
+}
-
-
+size_t OptionValueEnumeration::AutoComplete(
+ CommandInterpreter &interpreter, const char *s, int match_start_point,
+ int max_return_elements, bool &word_complete, StringList &matches) {
+ word_complete = false;
+ matches.Clear();
+
+ const uint32_t num_enumerators = m_enumerations.GetSize();
+ if (s && s[0]) {
+ const size_t s_len = strlen(s);
+ for (size_t i = 0; i < num_enumerators; ++i) {
+ const char *name = m_enumerations.GetCStringAtIndex(i);
+ if (::strncmp(s, name, s_len) == 0)
+ matches.AppendString(name);
+ }
+ } else {
+ // only suggest "true" or "false" by default
+ for (size_t i = 0; i < num_enumerators; ++i)
+ matches.AppendString(m_enumerations.GetCStringAtIndex(i));
+ }
+ return matches.GetSize();
+}
More information about the lldb-commits
mailing list