[Lldb-commits] [lldb] r192714 - Patch enabling lldb command line driver to run on windows.
Deepak Panickal
deepak at codeplay.com
Tue Oct 15 08:46:40 PDT 2013
Author: panickal
Date: Tue Oct 15 10:46:40 2013
New Revision: 192714
URL: http://llvm.org/viewvc/llvm-project?rev=192714&view=rev
Log:
Patch enabling lldb command line driver to run on windows.
CHANGES:
- Thread locking switched from pthreads to C++11 standard library.
- Abstracted platform specific header includes into 'platform.h'.
- Create editline emulator for windows.
- Emulated various platform dependant functions on windows.
TODO:
- User input currently handled by gets_s(), work started on better handler:
see _WIP_INPUT_METHOD define blocks in 'ELWrapper.cpp'.
Aim is to handle 'tab' auto completion on windows.
- Tidy up 'getopt.inc' from lldbHostCommon to serve as LLDB Drivers getopt windows implementation.
Added:
lldb/trunk/tools/driver/ELWrapper.cpp
lldb/trunk/tools/driver/ELWrapper.h
lldb/trunk/tools/driver/GetOptWrapper.cpp
lldb/trunk/tools/driver/GetOptWrapper.h
lldb/trunk/tools/driver/Platform.cpp
lldb/trunk/tools/driver/Platform.h
Modified:
lldb/trunk/tools/CMakeLists.txt
lldb/trunk/tools/driver/CMakeLists.txt
lldb/trunk/tools/driver/Driver.cpp
lldb/trunk/tools/driver/Driver.h
lldb/trunk/tools/driver/IOChannel.cpp
lldb/trunk/tools/driver/IOChannel.h
Modified: lldb/trunk/tools/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/CMakeLists.txt?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/CMakeLists.txt (original)
+++ lldb/trunk/tools/CMakeLists.txt Tue Oct 15 10:46:40 2013
@@ -1,7 +1,7 @@
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(debugserver)
endif()
-if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
add_subdirectory(driver)
+if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
add_subdirectory(lldb-platform)
endif()
Modified: lldb/trunk/tools/driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/CMakeLists.txt?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/driver/CMakeLists.txt (original)
+++ lldb/trunk/tools/driver/CMakeLists.txt Tue Oct 15 10:46:40 2013
@@ -5,6 +5,9 @@ add_lldb_executable(lldb
#DriverOptions.cpp
#DriverPosix.cpp
IOChannel.cpp
+ ELWrapper.cpp
+ Platform.cpp
+ GetOptWrapper.cpp
)
target_link_libraries(lldb liblldb)
Modified: lldb/trunk/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Tue Oct 15 10:46:40 2013
@@ -9,19 +9,15 @@
#include "Driver.h"
-#include <getopt.h>
-#include <libgen.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
+#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <string>
+#include <thread>
#include "IOChannel.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -155,7 +151,9 @@ Driver::CloseIOChannelFile ()
// Write an End of File sequence to the file descriptor to ensure any
// read functions can exit.
char eof_str[] = "\x04";
- ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
+ int mfd = m_editline_pty.GetMasterFileDescriptor();
+ if (mfd != -1)
+ ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
m_editline_pty.CloseMasterFileDescriptor();
@@ -569,7 +567,7 @@ Driver::GetDebugMode() const
// if the user only wanted help or version information.
SBError
-Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
+Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
{
ResetOptionValues ();
@@ -802,12 +800,12 @@ Driver::ParseArgs (int argc, const char
if (error.Fail() || m_option_data.m_print_help)
{
ShowUsage (out_fh, g_options, m_option_data);
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_version)
{
::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_python_path)
{
@@ -825,7 +823,7 @@ Driver::ParseArgs (int argc, const char
}
else
::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
{
@@ -1311,6 +1309,12 @@ Driver::EditLineInputReaderCallback
void
Driver::MainLoop ()
{
+#if defined(_MSC_VER)
+ m_editline_slave_fh = stdin;
+ FILE *editline_output_slave_fh = stdout;
+ lldb_utility::PseudoTerminal editline_output_pty;
+#else
+
char error_str[1024];
if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
{
@@ -1371,6 +1375,7 @@ Driver::MainLoop ()
::setbuf (editline_output_slave_fh, NULL);
}
}
+#endif
// struct termios stdin_termios;
@@ -1412,6 +1417,7 @@ Driver::MainLoop ()
m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
+#if !defined (_MSC_VER)
SBCommunication out_comm_2("driver.editline_output");
out_comm_2.SetCloseOnEOF (false);
out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
@@ -1422,6 +1428,7 @@ Driver::MainLoop ()
::fprintf (stderr, "error: failed to start libedit output read thread");
exit (5);
}
+#endif
struct winsize window_size;
@@ -1663,9 +1670,11 @@ Driver::MainLoop ()
master_out_comm.Disconnect();
master_out_comm.ReadThreadStop();
+#if !defined(_MSC_VER)
out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
out_comm_2.Disconnect();
out_comm_2.ReadThreadStop();
+#endif
editline_output_pty.CloseMasterFileDescriptor();
reset_stdin_termios();
@@ -1780,15 +1789,15 @@ main (int argc, char const *argv[], cons
{
Driver driver;
- bool exit = false;
- SBError error (driver.ParseArgs (argc, argv, stdout, exit));
+ bool exiting = false;
+ SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString ();
if (error_cstr)
::fprintf (stderr, "error: %s\n", error_cstr);
}
- else if (!exit)
+ else if (!exiting)
{
driver.MainLoop ();
}
Modified: lldb/trunk/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Tue Oct 15 10:46:40 2013
@@ -10,6 +10,7 @@
#ifndef lldb_Driver_h_
#define lldb_Driver_h_
+#include "Platform.h"
#include "lldb/Utility/PseudoTerminal.h"
#include <set>
Added: lldb/trunk/tools/driver/ELWrapper.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/ELWrapper.cpp?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/ELWrapper.cpp (added)
+++ lldb/trunk/tools/driver/ELWrapper.cpp Tue Oct 15 10:46:40 2013
@@ -0,0 +1,422 @@
+//===-- ELWrapper.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "lldb/Host/windows/windows.h"
+
+#include "ELWrapper.h"
+#include <vector>
+#include <assert.h>
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( X ) ( (void* ) *( ( (int**) &el ) + ((X) + 2) ) )
+
+// edit line EL_ADDFN function pointer type
+typedef unsigned char (*el_addfn_func)(EditLine *e, int ch);
+
+// 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;
+};
+
+// stored key bindings
+static std::vector<el_binding*> _bindings;
+
+//TODO: this should infact 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 )
+
+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;
+ }
+ }
+ return false;
+}
+
+// replacement get_s which is EL_BIND aware
+static char *
+el_get_s (char *buffer, int chars)
+{
+ //
+ char *head = buffer;
+ //
+ for ( ;; Sleep( 10 ) )
+ {
+ //
+ INPUT_RECORD _record;
+ //
+ DWORD _read = 0;
+ if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE )
+ break;
+ // if we didnt 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;
+ }
+ }
+ // insert end of line character
+ *head = '\0';
+
+ return buffer;
+}
+#endif
+
+// edit line initalise
+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( _prompt );
+ // create a buffer for the user input
+ char *buffer = new char[ 64 ];
+ // try to get user input string
+ if ( el_get_s( buffer, 64 ) )
+ {
+ // 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, ...)
+{
+ int **arg = (int**) ⪙
+ //
+ 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*) *(arg+2);
+ // cast to suitable prototype
+ const char* (*func_fp)(EditLine*) = (const char*(*)(EditLine *)) func_vp;
+ // call to get the prompt as a string
+ _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 histroy function to use, which is usualy 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 involcation 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 usefull if a key binding outputs extra information.
+ // CC_ERROR an error occured. beep and flush tty.
+ // CC_FATAL fatal error, reset tty to known state.
+
+ el_binding *binding = new el_binding;
+ binding->name = (const char *) GETARG( 0 );
+ binding->help = (const char *) GETARG( 1 );
+ binding->func = (el_addfn_func) GETARG( 2 );
+ 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 buildin command. Refer to editrc(5) for more information.
+
+ const char *name = (const char*) GETARG( 1 );
+
+ for ( int i=0; i<_bindings.size(); i++ )
+ {
+ el_binding *bind = _bindings[i];
+ if ( strcmp( bind->name, name ) == 0 )
+ {
+ bind->key = (const char *) GETARG( 0 );
+ break;
+ }
+ }
+
+ }
+ break;
+ case ( EL_CLIENTDATA ):
+ {
+ clientData = GETARG( 0 );
+ }
+ break;
+ default:
+ assert( !"Not Implemented!" );
+ }
+ return 0;
+}
+
+void
+el_end (EditLine *el)
+{
+ assert( !"Not implemented!" );
+}
+
+void
+el_reset (EditLine *)
+{
+ assert( !"Not implemented!" );
+}
+
+int
+el_getc (EditLine *, char *)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void
+el_push (EditLine *, char *)
+{
+ assert( !"Not implemented!" );
+}
+
+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, ...)
+{
+ switch ( code )
+ {
+ case ( EL_CLIENTDATA ):
+ {
+ void **dout = (void**) GETARG( 0 );
+ *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;
+}
+
+void
+el_resize (EditLine *)
+{
+ assert( !"Not implemented!" );
+}
+
+const LineInfo *
+el_line (EditLine *el)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+int
+el_insertstr (EditLine *, const char *)
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void
+el_deletestr (EditLine *, int)
+{
+ assert( !"Not implemented!" );
+}
+
+History *
+history_init (void)
+{
+ // return dummy handle
+ return (History*) -1;
+}
+
+void
+history_end (History *)
+{
+ assert( !"Not implemented!" );
+}
+
+int
+history (History *, HistEvent *, int op, ...)
+{
+ // perform operation 'op' on the history list with optional argumetns as needed by
+ // the operation.
+ return 0;
+}
+
+#endif
Added: lldb/trunk/tools/driver/ELWrapper.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/ELWrapper.h?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/ELWrapper.h (added)
+++ lldb/trunk/tools/driver/ELWrapper.h Tue Oct 15 10:46:40 2013
@@ -0,0 +1,122 @@
+//===-- ELWrapper.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <stdio.h>
+
+// EditLine editor function return codes.
+// For user-defined function interface
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_ARGHACK 3
+#define CC_REFRESH 4
+#define CC_CURSOR 5
+#define CC_ERROR 6
+#define CC_FATAL 7
+#define CC_REDISPLAY 8
+#define CC_REFRESH_BEEP 9
+
+// el_set/el_get parameters
+#define EL_PROMPT 0 // , el_pfunc_t
+#define EL_TERMINAL 1 // , const char *
+#define EL_EDITOR 2 // , const char *
+#define EL_SIGNAL 3 // , int);
+#define EL_BIND 4 // , const char *, ..., NULL
+#define EL_TELLTC 5 // , const char *, ..., NULL
+#define EL_SETTC 6 // , const char *, ..., NULL
+#define EL_ECHOTC 7 // , const char *, ..., NULL
+#define EL_SETTY 8 // , const char *, ..., NULL
+#define EL_ADDFN 9 // , const char *, const char *, el_func_t
+#define EL_HIST 10 // , hist_fun_t, const char *
+#define EL_EDITMODE 11 // , int
+#define EL_RPROMPT 12 // , el_pfunc_t
+#define EL_GETCFN 13 // , el_rfunc_t
+#define EL_CLIENTDATA 14 // , void *
+#define EL_UNBUFFERED 15 // , int
+#define EL_PREP_TERM 16 // , int
+#define EL_GETTC 17 // , const char *, ..., NULL
+#define EL_GETFP 18 // , int, FILE **
+#define EL_SETFP 19 // , int, FILE *
+#define EL_REFRESH 20 // , void
+
+#define EL_BUILTIN_GETCFN (NULL)
+
+// history defines
+#define H_FUNC 0 // , UTSL
+#define H_SETSIZE 1 // , const int
+#define H_GETSIZE 2 // , void
+#define H_FIRST 3 // , void
+#define H_LAST 4 // , void
+#define H_PREV 5 // , void
+#define H_NEXT 6 // , void
+#define H_CURR 8 // , const int
+#define H_SET 7 // , int
+#define H_ADD 9 // , const char *
+#define H_ENTER 10 // , const char *
+#define H_APPEND 11 // , const char *
+#define H_END 12 // , void
+#define H_NEXT_STR 13 // , const char *
+#define H_PREV_STR 14 // , const char *
+#define H_NEXT_EVENT 15 // , const int
+#define H_PREV_EVENT 16 // , const int
+#define H_LOAD 17 // , const char *
+#define H_SAVE 18 // , const char *
+#define H_CLEAR 19 // , void
+#define H_SETUNIQUE 20 // , int
+#define H_GETUNIQUE 21 // , void
+#define H_DEL 22 // , int
+
+struct EditLine
+{
+};
+
+struct LineInfo
+{
+ const char *buffer;
+ const char *cursor;
+ const char *lastchar;
+};
+
+struct History
+{
+};
+
+struct HistEvent
+{
+ int num;
+ const char *str;
+};
+
+extern "C"
+{
+ // edit line API
+ EditLine *el_init ( const char *, FILE *, FILE *, FILE * );
+ const char *el_gets ( EditLine *, int * );
+ int el_set ( EditLine *, int, ... );
+
+ void el_end ( EditLine * );
+ void el_reset ( EditLine * );
+ int el_getc ( EditLine *, char * );
+ void el_push ( EditLine *, char * );
+ void el_beep ( EditLine * );
+ int el_parse ( EditLine *, int, const char ** );
+ int el_get ( EditLine *, int, ... );
+ int el_source ( EditLine *, const char * );
+ void el_resize ( EditLine * );
+ const LineInfo *el_line ( EditLine * );
+ int el_insertstr( EditLine *, const char * );
+ void el_deletestr( EditLine *, int );
+
+ // history API
+ History *history_init( void );
+ void history_end ( History * );
+ int history ( History *, HistEvent *, int, ... );
+};
\ No newline at end of file
Added: lldb/trunk/tools/driver/GetOptWrapper.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/GetOptWrapper.cpp?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/GetOptWrapper.cpp (added)
+++ lldb/trunk/tools/driver/GetOptWrapper.cpp Tue Oct 15 10:46:40 2013
@@ -0,0 +1,33 @@
+//===-- GetOptWrapper.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "GetOptWrapper.h"
+
+/*
+
+// already defined in lldbHostCommon.lib due to 'getopt.inc'
+
+extern int
+getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+)
+{
+ return -1;
+}
+*/
+
+#endif
\ No newline at end of file
Added: lldb/trunk/tools/driver/GetOptWrapper.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/GetOptWrapper.h?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/GetOptWrapper.h (added)
+++ lldb/trunk/tools/driver/GetOptWrapper.h Tue Oct 15 10:46:40 2013
@@ -0,0 +1,49 @@
+//===-- GetOptWrapper.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_GetOptWrapper_h_
+#define lldb_GetOptWrapper_h_
+
+// from getopt.h
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+// defined int unistd.h
+extern int optreset;
+
+// from getopt.h
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+// option structure
+struct option
+{
+ const char *name;
+ // has_arg can't be an enum because some compilers complain about
+ // type mismatches in all the code that assumes it is an int.
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+//
+extern int
+getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+);
+
+#endif // lldb_GetOptWrapper_h_
\ No newline at end of file
Modified: lldb/trunk/tools/driver/IOChannel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.cpp?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/driver/IOChannel.cpp (original)
+++ lldb/trunk/tools/driver/IOChannel.cpp Tue Oct 15 10:46:40 2013
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Platform.h"
#include "IOChannel.h"
#include <map>
@@ -73,7 +74,8 @@ void
IOChannel::EraseCharsBeforeCursor ()
{
const LineInfo *line_info = el_line(m_edit_line);
- el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
+ if (line_info != NULL)
+ el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
}
unsigned char
@@ -213,17 +215,14 @@ IOChannel::IOChannel
m_history_event(),
m_getting_command (false),
m_expecting_prompt (false),
- m_prompt_str (),
+ m_prompt_str (),
m_refresh_request_pending (false)
{
assert (m_edit_line);
- ::el_set (m_edit_line, EL_PROMPT, el_prompt);
- ::el_set (m_edit_line, EL_EDITOR, "emacs");
- ::el_set (m_edit_line, EL_HIST, history, m_history);
-
- el_set (m_edit_line, EL_ADDFN, "lldb_complete",
- "LLDB completion function",
- IOChannel::ElCompletionFn);
+ el_set (m_edit_line, EL_PROMPT, el_prompt);
+ el_set (m_edit_line, EL_EDITOR, "emacs");
+ el_set (m_edit_line, EL_HIST, history, m_history);
+ el_set (m_edit_line, EL_ADDFN, "lldb_complete", "LLDB completion function", IOChannel::ElCompletionFn);
el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
@@ -231,35 +230,20 @@ IOChannel::IOChannel
el_set (m_edit_line, EL_CLIENTDATA, this);
// Source $PWD/.editrc then $HOME/.editrc
- ::el_source (m_edit_line, NULL);
+ el_source (m_edit_line, NULL);
assert (m_history);
- ::history (m_history, &m_history_event, H_SETSIZE, 800);
- ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
+ history (m_history, &m_history_event, H_SETSIZE, 800);
+ history (m_history, &m_history_event, H_SETUNIQUE, 1);
// Load history
HistorySaveLoad (false);
- // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
- // with each other when writing.
-
- int error;
- ::pthread_mutexattr_t attr;
- error = ::pthread_mutexattr_init (&attr);
- assert (error == 0);
- error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
- assert (error == 0);
- error = ::pthread_mutex_init (&m_output_mutex, &attr);
- assert (error == 0);
- error = ::pthread_mutexattr_destroy (&attr);
- assert (error == 0);
-
- error = ::pthread_cond_init (&m_output_cond, NULL);
- assert (error == 0);
-
// Initialize time that ::el_gets was last called.
-
m_enter_elgets_time.tv_sec = 0;
m_enter_elgets_time.tv_usec = 0;
+
+ // set the initial state to non flushed
+ m_output_flushed = false;
}
IOChannel::~IOChannel ()
@@ -278,9 +262,6 @@ IOChannel::~IOChannel ()
::el_end (m_edit_line);
m_edit_line = NULL;
}
-
- ::pthread_cond_destroy (&m_output_cond);
- ::pthread_mutex_destroy (&m_output_mutex);
}
void
@@ -304,16 +285,15 @@ IOChannel::HistorySaveLoad (bool save)
void
IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
{
- // Make this a member variable.
- // static std::string prompt_str;
IOChannel *io_channel = (IOChannel *) baton;
- IOLocker locker (io_channel->m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(io_channel->m_output_mutex);
const char *bytes = (const char *) src;
bool flush = false;
- // See if we have a 'flush' syncronization point in there.
- if (src_len > 0 && bytes[src_len-1] == 0)
+ // See if we have a 'flush' synchronization point in there.
+ // this is performed from 'fputc ('\0', m_editline_out);' in LibeditGetInput()
+ if (src_len > 0 && bytes[src_len-1] == '\0')
{
src_len--;
flush = true;
@@ -322,7 +302,7 @@ IOChannel::LibeditOutputBytesReceived (v
if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
{
io_channel->m_prompt_str.append (bytes, src_len);
- // Log this to make sure the prompt is really what you think it is.
+ // Log this to make sure the prompt is really what you think it is.
if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
{
io_channel->m_expecting_prompt = false;
@@ -342,13 +322,14 @@ IOChannel::LibeditOutputBytesReceived (v
io_channel->OutWrite (bytes, src_len, NO_ASYNC);
}
+#if !defined (_MSC_VER)
if (flush)
{
- // Signal that we have finished all data up to the sync point.
- IOLocker locker (io_channel->m_output_mutex);
io_channel->m_output_flushed = true;
- pthread_cond_signal (&io_channel->m_output_cond);
+ io_channel->m_output_cond.notify_all();
}
+#endif
+
}
IOChannel::LibeditGetInputResult
@@ -367,22 +348,27 @@ IOChannel::LibeditGetInput (std::string
// Call el_gets to prompt the user and read the user's input.
const char *line = ::el_gets (m_edit_line, &line_len);
+#if !defined (_MSC_VER)
// Force the piped output from el_gets to finish processing.
// el_gets does an fflush internally, which is not sufficient here; it only
// writes the data into m_editline_out, but doesn't affect whether our worker
// thread will read that data yet. So we block here manually.
{
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
m_output_flushed = false;
// Write a synchronization point into the stream, so we can guarantee
// LibeditOutputBytesReceived has processed everything up till that mark.
- fputc (0, m_editline_out);
+ fputc ('\0', m_editline_out);
- while (!m_output_flushed && pthread_cond_wait (&m_output_cond, &m_output_mutex))
- { /* wait */ }
+ while (!m_output_flushed)
+ {
+ // wait until the condition variable is signaled
+ m_output_cond.wait(m_output_mutex);
+ }
}
-
+#endif
+
// Re-set the boolean indicating whether or not el_gets is trying to get input.
SetGettingCommand (false);
@@ -417,7 +403,7 @@ IOChannel::LibeditGetInput (std::string
return retval;
}
-void *
+thread_result_t
IOChannel::IOReadThread (void *ptr)
{
IOChannel *myself = static_cast<IOChannel *> (ptr);
@@ -540,8 +526,7 @@ IOChannel::Start ()
if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
return true;
- m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
- NULL);
+ m_read_thread = SBHostOS::ThreadCreate("<lldb.driver.commandline_io>", (lldb::thread_func_t) IOChannel::IOReadThread, this, NULL);
return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
}
@@ -569,11 +554,11 @@ IOChannel::RefreshPrompt ()
{
// If we are not in the middle of getting input from the user, there is no need to
// refresh the prompt.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (! IsGettingCommand())
return;
- // If we haven't finished writing the prompt, there's no need to refresh it.
+ // If we haven't finished writing the prompt, there's no need to refresh it.
if (m_expecting_prompt)
return;
@@ -600,7 +585,7 @@ IOChannel::OutWrite (const char *buffer,
}
// Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (m_driver->EditlineReaderIsTop() && asynchronous)
::fwrite (undo_prompt_string, 1, 4, m_out_file);
::fwrite (buffer, 1, len, m_out_file);
@@ -615,7 +600,7 @@ IOChannel::ErrWrite (const char *buffer,
return;
// Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- IOLocker locker (m_output_mutex);
+ std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
if (asynchronous)
::fwrite (undo_prompt_string, 1, 4, m_err_file);
::fwrite (buffer, 1, len, m_err_file);
@@ -669,17 +654,3 @@ IOChannel::SetGettingCommand (bool new_v
{
m_getting_command = new_value;
}
-
-IOLocker::IOLocker (pthread_mutex_t &mutex) :
- m_mutex_ptr (&mutex)
-{
- if (m_mutex_ptr)
- ::pthread_mutex_lock (m_mutex_ptr);
-
-}
-
-IOLocker::~IOLocker ()
-{
- if (m_mutex_ptr)
- ::pthread_mutex_unlock (m_mutex_ptr);
-}
Modified: lldb/trunk/tools/driver/IOChannel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.h?rev=192714&r1=192713&r2=192714&view=diff
==============================================================================
--- lldb/trunk/tools/driver/IOChannel.h (original)
+++ lldb/trunk/tools/driver/IOChannel.h Tue Oct 15 10:46:40 2013
@@ -10,18 +10,13 @@
#ifndef lldb_IOChannel_h_
#define lldb_IOChannel_h_
+#include <thread>
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
+
#include <string>
#include <queue>
-
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-#include <readline/readline.h>
-#else
-#include <editline/readline.h>
-#endif
-#include <histedit.h>
-#include <pthread.h>
-#include <sys/time.h>
-
#include "Driver.h"
class IOChannel : public lldb::SBBroadcaster
@@ -63,7 +58,7 @@ public:
bool
Stop ();
- static void *
+ static lldb::thread_result_t
IOReadThread (void *);
void
@@ -127,8 +122,8 @@ protected:
private:
- pthread_mutex_t m_output_mutex;
- pthread_cond_t m_output_cond;
+ std::recursive_mutex m_output_mutex;
+ std::condition_variable_any m_output_cond;
struct timeval m_enter_elgets_time;
Driver *m_driver;
@@ -156,22 +151,4 @@ private:
HandleCompletion (EditLine *e, int ch);
};
-class IOLocker
-{
-public:
-
- IOLocker (pthread_mutex_t &mutex);
-
- ~IOLocker ();
-
-protected:
-
- pthread_mutex_t *m_mutex_ptr;
-
-private:
-
- IOLocker (const IOLocker&);
- const IOLocker& operator= (const IOLocker&);
-};
-
#endif // lldb_IOChannel_h_
Added: lldb/trunk/tools/driver/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Platform.cpp?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/Platform.cpp (added)
+++ lldb/trunk/tools/driver/Platform.cpp Tue Oct 15 10:46:40 2013
@@ -0,0 +1,111 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include <process.h>
+#include <assert.h>
+
+#include "Platform.h"
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( Y, X ) ( (void* ) *( ( (int**) &(Y) ) + (X) ) )
+
+// the control handler or SIGINT handler
+static sighandler_t _ctrlHandler = NULL;
+
+// the default console control handler
+BOOL
+WINAPI CtrlHandler (DWORD ctrlType)
+{
+ if ( _ctrlHandler != NULL )
+ {
+ _ctrlHandler( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+ioctl (int d, int request, ...)
+{
+ switch ( request )
+ {
+ // request the console windows size
+ case ( TIOCGWINSZ ):
+ {
+ // locate the window size structure on stack
+ winsize *ws = (winsize*) GETARG( d, 2 );
+ // get screen buffer information
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info );
+ // fill in the columns
+ ws->ws_col = info.dwMaximumWindowSize.X;
+ //
+ return 0;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return -1;
+}
+
+int
+kill (pid_t pid, int sig)
+{
+ // is the app trying to kill itself
+ if ( pid == getpid( ) )
+ exit( sig );
+ //
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
+{
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcgetattr (int fildes, struct termios *termios_p)
+{
+// assert( !"Not implemented!" );
+ // error return value (0=success)
+ return -1;
+}
+
+sighandler_t
+signal (int sig, sighandler_t sigFunc)
+{
+ switch ( sig )
+ {
+ case ( SIGINT ):
+ {
+ _ctrlHandler = sigFunc;
+ SetConsoleCtrlHandler( CtrlHandler, TRUE );
+ }
+ break;
+ case ( SIGPIPE ):
+ case ( SIGWINCH ):
+ case ( SIGTSTP ):
+ case ( SIGCONT ):
+ // ignore these for now
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+#endif
\ No newline at end of file
Added: lldb/trunk/tools/driver/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Platform.h?rev=192714&view=auto
==============================================================================
--- lldb/trunk/tools/driver/Platform.h (added)
+++ lldb/trunk/tools/driver/Platform.h Tue Oct 15 10:46:40 2013
@@ -0,0 +1,120 @@
+//===-- Platform.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Platform_h_
+#define lldb_Platform_h_
+
+#if defined( _MSC_VER )
+
+ #define PRIu32 "u"
+ #define PRId64 "I64d"
+ #define PRIi64 "I64i"
+ #define PRIo64 "I64o"
+ #define PRIu64 "I64u"
+ #define PRIx64 "I64x"
+ #define PRIX64 "I64X"
+
+ // this will stop signal.h being included
+ #define _INC_SIGNAL
+
+ #include <io.h>
+ #include <eh.h>
+ #include "ELWrapper.h"
+ #include "lldb/Host/windows/Windows.h"
+ #include "GetOptWrapper.h"
+
+ struct timeval
+ {
+ long tv_sec;
+ long tv_usec;
+ };
+
+ struct winsize
+ {
+ long ws_col;
+ };
+
+ typedef unsigned char cc_t;
+ typedef unsigned int speed_t;
+ typedef unsigned int tcflag_t;
+
+ // fcntl.h
+ #define O_NOCTTY 0400
+
+ // ioctls.h
+ #define TIOCGWINSZ 0x5413
+
+ // signal.h
+ #define SIGPIPE 13
+ #define SIGCONT 18
+ #define SIGTSTP 20
+ #define SIGWINCH 28
+
+ // tcsetattr arguments
+ #define TCSANOW 0
+
+ #define NCCS 32
+ struct termios
+ {
+ tcflag_t c_iflag; // input mode flags
+ tcflag_t c_oflag; // output mode flags
+ tcflag_t c_cflag; // control mode flags
+ tcflag_t c_lflag; // local mode flags
+ cc_t c_line; // line discipline
+ cc_t c_cc[NCCS]; // control characters
+ speed_t c_ispeed; // input speed
+ speed_t c_ospeed; // output speed
+ };
+
+ typedef long pid_t;
+
+ #define STDIN_FILENO 0
+
+ #define PATH_MAX MAX_PATH
+ #define snprintf _snprintf
+
+ extern int ioctl( int d, int request, ... );
+ extern int kill ( pid_t pid, int sig );
+ extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p );
+ extern int tcgetattr( int fildes, struct termios *termios_p );
+
+ // signal handler function pointer type
+ typedef void (*sighandler_t)(int);
+
+ // signal.h
+ #define SIGINT 2
+ // default handler
+ #define SIG_DFL ( (sighandler_t) -1 )
+ // ignored
+ #define SIG_IGN ( (sighandler_t) -2 )
+ extern sighandler_t signal( int sig, sighandler_t );
+
+#else
+
+ #if defined(__FreeBSD__)
+ #include <readline/readline.h>
+ #else
+ #include <editline/readline.h>
+ #endif
+
+ #include <inttypes.h>
+
+ #include <getopt.h>
+ #include <libgen.h>
+ #include <sys/ioctl.h>
+ #include <termios.h>
+ #include <unistd.h>
+
+ #include <histedit.h>
+ #include <pthread.h>
+ #include <sys/time.h>
+
+#endif
+
+#endif // lldb_Platform_h_
\ No newline at end of file
More information about the lldb-commits
mailing list