forked from OSchip/llvm-project
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. llvm-svn: 192714
This commit is contained in:
parent
0f3b4aaf34
commit
429222c1f6
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *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 +823,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 +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[], 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 ();
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef lldb_Driver_h_
|
||||
#define lldb_Driver_h_
|
||||
|
||||
#include "Platform.h"
|
||||
#include "lldb/Utility/PseudoTerminal.h"
|
||||
|
||||
#include <set>
|
||||
|
|
|
@ -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
|
|
@ -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, ... );
|
||||
};
|
|
@ -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
|
|
@ -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_
|
|
@ -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 (void *baton, const void *src, size_t src_
|
|||
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 (void *baton, const void *src, size_t src_
|
|||
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 &new_line)
|
|||
// 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 &new_line)
|
|||
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, size_t len, bool asynchronous)
|
|||
}
|
||||
|
||||
// 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, size_t len, bool asynchronous)
|
|||
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_value)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
|
@ -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_
|
Loading…
Reference in New Issue