[Lldb-commits] LLDB Windows Driver Patch

Aidan Dodds aidan at codeplay.com
Fri Sep 27 09:56:19 PDT 2013


Hello,

As an extension of our PlatformWindows patch, we would like to submit 
some changes to the LLDB Command Line Driver allowing it to cleanly 
build and run on Windows.

This patch will not show any change in functionality for non windows 
hosts. Without any Windows specific testing in place we have simply 
loaded an elf file and viewed its sections, etc to confirm that it 
functions properly.

An work-in-progress wrapper for EditLine functionality has been created, 
leaving the main driver code minimally modified. Also a minimal 
abstraction of the pthread code has been made. Our intention is to later 
revise the threading code and instead use the existing threading classes 
of LLDB.

The Linux test suite passes successfully after application of this patch.

This patch is based on trunk revision, 
https://llvm.org/svn/llvm-project/lldb/trunk@191399

Thanks,
Aidan Dodds
-------------- next part --------------
diff --git tools/CMakeLists.txt tools/CMakeLists.txt
index b1989f8..43163f6 100644
--- tools/CMakeLists.txt
+++ tools/CMakeLists.txt
@@ -1,7 +1,7 @@
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
-  add_subdirectory(debugserver)
-endif()
-if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
-  add_subdirectory(driver)
-  add_subdirectory(lldb-platform)
-endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  add_subdirectory(debugserver)
+endif()
+add_subdirectory(driver)
+if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
+  add_subdirectory(lldb-platform)
+endif()
diff --git tools/driver/CMakeLists.txt tools/driver/CMakeLists.txt
index c70a2db..aa4c798 100644
--- tools/driver/CMakeLists.txt
+++ tools/driver/CMakeLists.txt
@@ -1,18 +1,22 @@
-set(LLVM_NO_RTTI 1)
-add_lldb_executable(lldb
-  Driver.cpp
-  #DriverEvents.cpp
-  #DriverOptions.cpp
-  #DriverPosix.cpp
-  IOChannel.cpp
-  )
-
-target_link_libraries(lldb liblldb)
-# TODO: why isn't this done by add_lldb_executable?
-#target_link_libraries(lldb ${LLDB_USED_LIBS})
-#llvm_config(lldb ${LLVM_LINK_COMPONENTS})
-
-set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION})
-
-install(TARGETS lldb
-  RUNTIME DESTINATION bin)
+set(LLVM_NO_RTTI 1)
+add_lldb_executable(lldb
+  Driver.cpp
+  #DriverEvents.cpp
+  #DriverOptions.cpp
+  #DriverPosix.cpp
+  IOChannel.cpp
+  ELWrapper.cpp
+  Mutex.cpp
+  Platform.cpp
+  GetOptWrapper.cpp
+  )
+
+target_link_libraries(lldb liblldb)
+# TODO: why isn't this done by add_lldb_executable?
+#target_link_libraries(lldb ${LLDB_USED_LIBS})
+#llvm_config(lldb ${LLVM_LINK_COMPONENTS})
+
+set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION})
+
+install(TARGETS lldb
+  RUNTIME DESTINATION bin)
diff --git tools/driver/Driver.cpp tools/driver/Driver.cpp
index a4fc67f..98977ba 100644
--- tools/driver/Driver.cpp
+++ tools/driver/Driver.cpp
@@ -9,16 +9,11 @@
 
 #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>
 
@@ -155,7 +150,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 +566,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 +799,12 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
     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 +822,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
         }
         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 +1308,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 +1374,7 @@ Driver::MainLoop ()
             ::setbuf (editline_output_slave_fh, NULL);
         }
     }
+#endif
 
    // struct termios stdin_termios;
 
@@ -1780,15 +1784,15 @@ main (int argc, char const *argv[], const char *envp[])
     {
         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 ();
         }
diff --git tools/driver/Driver.h tools/driver/Driver.h
index 6681611..dcfd5ed 100644
--- tools/driver/Driver.h
+++ tools/driver/Driver.h
@@ -10,6 +10,7 @@
 #ifndef lldb_Driver_h_
 #define lldb_Driver_h_
 
+#include "Platform.h"
 #include "lldb/Utility/PseudoTerminal.h"
 
 #include <set>
diff --git tools/driver/ELWrapper.cpp tools/driver/ELWrapper.cpp
new file mode 100644
index 0000000..dc71b7f
--- /dev/null
+++ tools/driver/ELWrapper.cpp
@@ -0,0 +1,398 @@
+//===-- 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
diff --git tools/driver/ELWrapper.h tools/driver/ELWrapper.h
new file mode 100644
index 0000000..a30182d
--- /dev/null
+++ tools/driver/ELWrapper.h
@@ -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
diff --git tools/driver/GetOptWrapper.cpp tools/driver/GetOptWrapper.cpp
new file mode 100644
index 0000000..d190867
--- /dev/null
+++ tools/driver/GetOptWrapper.cpp
@@ -0,0 +1,32 @@
+//===-- 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
diff --git tools/driver/GetOptWrapper.h tools/driver/GetOptWrapper.h
new file mode 100644
index 0000000..9c9cf03
--- /dev/null
+++ tools/driver/GetOptWrapper.h
@@ -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
diff --git tools/driver/IOChannel.cpp tools/driver/IOChannel.cpp
index 520cba8..79c500d 100644
--- tools/driver/IOChannel.cpp
+++ tools/driver/IOChannel.cpp
@@ -73,7 +73,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
@@ -242,19 +243,7 @@ IOChannel::IOChannel
     // 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);
+    mutex_init( &m_output_mutex );
 
     // Initialize time that ::el_gets was last called.
 
@@ -279,8 +268,7 @@ IOChannel::~IOChannel ()
         m_edit_line = NULL;
     }
 
-    ::pthread_cond_destroy (&m_output_cond);
-    ::pthread_mutex_destroy (&m_output_mutex);
+    mutex_free(&m_output_mutex);
 }
 
 void
@@ -347,7 +335,7 @@ IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_
         // 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);
+        condvar_signal( &io_channel->m_output_cond );
     }
 }
 
@@ -379,7 +367,7 @@ IOChannel::LibeditGetInput (std::string &new_line)
             // LibeditOutputBytesReceived has processed everything up till that mark.
             fputc (0, m_editline_out);
 
-            while (!m_output_flushed && pthread_cond_wait (&m_output_cond, &m_output_mutex))
+            while (!m_output_flushed && condvar_wait(&m_output_cond, &m_output_mutex))
             { /* wait */ }
         }
         
@@ -417,8 +405,8 @@ IOChannel::LibeditGetInput (std::string &new_line)
     return retval;
 }
 
-void *
-IOChannel::IOReadThread (void *ptr)
+thread_result_t
+IOChannel::IOReadThread( void *ptr )
 {
     IOChannel *myself = static_cast<IOChannel *> (ptr);
     myself->Run();
@@ -540,8 +528,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));
 }
@@ -670,16 +657,16 @@ IOChannel::SetGettingCommand (bool new_value)
     m_getting_command = new_value;
 }
 
-IOLocker::IOLocker (pthread_mutex_t &mutex) :
+IOLocker::IOLocker (lldb_mutex &mutex) :
     m_mutex_ptr (&mutex)
 {
     if (m_mutex_ptr)
-        ::pthread_mutex_lock (m_mutex_ptr);
+        mutex_lock (m_mutex_ptr);
         
 }
 
 IOLocker::~IOLocker ()
 {
     if (m_mutex_ptr)
-        ::pthread_mutex_unlock (m_mutex_ptr);
+        mutex_unlock (m_mutex_ptr);
 }
diff --git tools/driver/IOChannel.h tools/driver/IOChannel.h
index 9006f70..2b82b3a 100644
--- tools/driver/IOChannel.h
+++ tools/driver/IOChannel.h
@@ -12,16 +12,6 @@
 
 #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 +53,7 @@ public:
     bool
     Stop ();
 
-    static void *
+    static lldb::thread_result_t
     IOReadThread (void *);
 
     void
@@ -127,8 +117,8 @@ protected:
 
 private:
 
-    pthread_mutex_t m_output_mutex;
-    pthread_cond_t m_output_cond;
+    lldb_mutex m_output_mutex;
+    lldb_cond  m_output_cond;
     struct timeval m_enter_elgets_time;
 
     Driver *m_driver;
@@ -160,13 +150,13 @@ class IOLocker
 {
 public:
 
-    IOLocker (pthread_mutex_t &mutex);
+    IOLocker (lldb_mutex &mutex);
 
     ~IOLocker ();
 
 protected:
 
-    pthread_mutex_t *m_mutex_ptr;
+    lldb_mutex *m_mutex_ptr;
 
 private:
 
diff --git tools/driver/Mutex.cpp tools/driver/Mutex.cpp
new file mode 100644
index 0000000..fd38480
--- /dev/null
+++ tools/driver/Mutex.cpp
@@ -0,0 +1,91 @@
+//===-- Mutex.cpp -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Platform.h"
+
+#if defined( _MSC_VER )
+
+// platform indepentent locking functions
+void mutex_init( lldb_mutex *mux )
+{
+    InitializeCriticalSection( mux );
+}
+
+void mutex_free( lldb_mutex *mux )
+{
+    DeleteCriticalSection( mux );
+}
+
+void mutex_lock( lldb_mutex *mux )
+{
+    EnterCriticalSection( mux );
+}
+
+void mutex_unlock( lldb_mutex *mux )
+{
+    LeaveCriticalSection( mux );
+}
+
+// condition variables
+int condvar_signal( lldb_cond *cv )
+{
+    return 0;
+}
+
+int condvar_wait( lldb_cond *cv, lldb_mutex *mux )
+{
+    return 0;
+}
+
+
+#else
+    #include <assert.h>
+
+// platform indepentent locking functions
+void mutex_init( lldb_mutex *mux )
+{
+    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 ( mux, &attr);
+    assert (error == 0);
+    error = ::pthread_mutexattr_destroy (&attr);
+    assert (error == 0);
+}
+
+void mutex_free( lldb_mutex *mux )
+{
+    ::pthread_mutex_destroy ( mux);
+}
+
+void mutex_lock( lldb_mutex *mux )
+{
+    ::pthread_mutex_lock( mux );
+}
+
+void mutex_unlock( lldb_mutex *mux )
+{
+    ::pthread_mutex_unlock( mux );
+}
+
+// condition variables
+int condvar_signal( lldb_cond *cv )
+{
+    return pthread_cond_signal( cv );
+}
+
+int condvar_wait( lldb_cond *cv, lldb_mutex *mux )
+{
+    return pthread_cond_wait( cv, mux );
+}
+
+#endif
\ No newline at end of file
diff --git tools/driver/Platform.cpp tools/driver/Platform.cpp
new file mode 100644
index 0000000..1ca38d9
--- /dev/null
+++ tools/driver/Platform.cpp
@@ -0,0 +1,105 @@
+//===-- 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
diff --git tools/driver/Platform.h tools/driver/Platform.h
new file mode 100644
index 0000000..f3c0b82
--- /dev/null
+++ tools/driver/Platform.h
@@ -0,0 +1,134 @@
+//===-- 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 "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;
+    typedef CRITICAL_SECTION   lldb_mutex;
+    typedef CONDITION_VARIABLE lldb_cond;
+
+    #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>
+
+    typedef pthread_mutex_t lldb_mutex;
+    typedef pthread_cond_t  lldb_cond;
+
+#endif
+
+// platform independant locking functions
+extern void mutex_init  ( lldb_mutex *mux );
+extern void mutex_free  ( lldb_mutex *mux );
+extern void mutex_lock  ( lldb_mutex *mux );
+extern void mutex_unlock( lldb_mutex *mux );
+
+// platform independant condition variables
+extern int condvar_signal( lldb_cond *cnd );
+extern int condvar_wait  ( lldb_cond *cnd, lldb_mutex *mux );
+
+#endif // lldb_Platform_h_
\ No newline at end of file


More information about the lldb-commits mailing list