Conflicts:

.gitignore
	.project
	.travis.yml
	Examples/Makefile.in
	Examples/test-suite/director_nspace.i
This commit is contained in:
Oliver Buchtala 2013-09-27 02:29:02 +02:00
commit 6dcbbf07db
134 changed files with 10011 additions and 15 deletions

View file

@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include "js_shell.h"
void print_usage() {
std::cout << "javascript [-i] [-jsc|-v8] [-l module] <js-file>" << std::endl;
}
int main(int argc, char* argv[]) {
std::string scriptPath = "";
bool interactive = false;
JSShell* shell = 0;
for (int idx = 1; idx < argc; ++idx) {
if(strcmp(argv[idx], "-v8") == 0) {
shell = JSShell::Create(JSShell::V8);
} else if(strcmp(argv[idx], "-jsc") == 0) {
shell = JSShell::Create(JSShell::JSC);
} else if(strcmp(argv[idx], "-i") == 0) {
interactive = true;
} else {
scriptPath = argv[idx];
}
}
if (shell == 0) {
shell = JSShell::Create();
}
bool failed = false;
if(interactive) {
failed = !(shell->RunShell());
} else {
failed = !(shell->RunScript(scriptPath));
}
if (failed) {
delete shell;
printf("FAIL: Error during execution of script.\n");
return 1;
}
delete shell;
return 0;
}

View file

@ -0,0 +1,145 @@
#include "js_shell.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#ifdef __GNUC__
#ifdef __APPLE__
#define LIBRARY_EXT ".dylib"
#else
#define LIBRARY_EXT ".so"
#endif
#include <dlfcn.h>
#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
#define CLOSE_LIBRARY(handle) dlclose(handle)
#define LIBRARY_ERROR dlerror
#define LIBRARYFILE(name) std::string("lib").append(name).append(LIBRARY_EXT)
#else
#error "implement dll loading"
#endif
JSShell::~JSShell() {
for(std::vector<HANDLE>::iterator it = loaded_modules.begin();
it != loaded_modules.end(); ++it) {
HANDLE handle = *it;
CLOSE_LIBRARY(handle);
}
}
// TODO: this could be done more intelligent...
// - can we achieve source file relative loading?
// - better path resolution
std::string JSShell::LoadModule(const std::string& name, HANDLE* library) {
// works only for posix like OSs
size_t pathIdx = name.find_last_of("/");
std::string lib_name;
std::string module_name;
if (pathIdx == std::string::npos) {
module_name = name;
lib_name = std::string(name).append(LIBRARY_EXT);
} else {
std::string path = name.substr(0, pathIdx+1);
module_name = name.substr(pathIdx+1);
lib_name = path.append(module_name).append(LIBRARY_EXT);
}
HANDLE handle = LOAD_LIBRARY(lib_name.c_str());
if(handle == 0) {
std::cout << "Could not load library " << lib_name << ":"
<< std::endl << LIBRARY_ERROR() << std::endl;
return 0;
}
loaded_modules.push_back(handle);
*library = handle;
return module_name;
}
bool JSShell::RunScript(const std::string& scriptPath) {
std::string source = ReadFile(scriptPath);
if(!InitializeEngine()) return false;
// Node.js compatibility: make `print` available as `console.log()`
ExecuteScript("var console = {}; console.log = print;", "<console>");
if(!ExecuteScript(source, scriptPath)) {
return false;
}
return DisposeEngine();
}
bool JSShell::RunShell() {
if(!InitializeEngine()) return false;
static const int kBufferSize = 1024;
while (true) {
char buffer[kBufferSize];
printf("> ");
char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break;
std::string source(str);
ExecuteScript(source, "(shell)");
}
printf("\n");
return true;
}
std::string JSShell::ReadFile(const std::string& fileName)
{
std::string script;
std::ifstream file(fileName.c_str());
if (file.is_open()) {
while ( file.good() ) {
std::string line;
getline(file, line);
script.append(line);
script.append("\n");
}
file.close();
} else {
std::cout << "Unable to open file " << fileName << "." << std::endl;
}
return script;
}
#ifdef ENABLE_JSC
extern JSShell* JSCShell_Create();
#endif
#ifdef ENABLE_V8
extern JSShell* V8Shell_Create();
#endif
typedef JSShell*(*ShellFactory)();
static ShellFactory js_shell_factories[2] = {
#ifdef ENABLE_JSC
JSCShell_Create,
#else
0,
#endif
#ifdef ENABLE_V8
V8Shell_Create,
#else
0,
#endif
};
JSShell *JSShell::Create(Engine engine) {
if(js_shell_factories[engine] == 0) {
throw "Engine not available.";
}
return js_shell_factories[engine]();
}

View file

@ -0,0 +1,48 @@
#ifndef JS_SHELL_H
#define JS_SHELL_H
#include <vector>
#include <string>
typedef void* HANDLE;
typedef void* MODULE;
class JSShell {
public:
enum Engine {
JSC = 0,
V8
};
public:
JSShell() {}
virtual ~JSShell() = 0;
static JSShell* Create(Engine engine = JSC);
std::string LoadModule(const std::string& name, HANDLE* library);
virtual bool RunScript(const std::string& scriptPath);
virtual bool RunShell();
protected:
virtual bool InitializeEngine() = 0;
virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath) = 0;
virtual bool DisposeEngine() = 0;
static std::string ReadFile(const std::string& fileName);
protected:
std::vector<HANDLE> loaded_modules;
};
#endif // JS_SHELL_H

View file

@ -0,0 +1,229 @@
#include <JavaScriptCore/JavaScript.h>
#include "js_shell.h"
#include <iostream>
#include <stdio.h>
#ifdef __GNUC__
#include <dlfcn.h>
#define LOAD_SYMBOL(handle, name) dlsym(handle, name)
#else
#error "implement dll loading"
#endif
class JSCShell: public JSShell {
typedef int (*JSCIntializer)(JSGlobalContextRef context, JSObjectRef *module);
public:
JSCShell() {};
virtual ~JSCShell();
protected:
virtual bool InitializeEngine();
virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath);
virtual bool DisposeEngine();
private:
JSObjectRef Import(const std::string &moduleName);
static JSValueRef Print(JSContextRef context, JSObjectRef object, JSObjectRef globalobj, size_t argc, const JSValueRef args[], JSValueRef* ex);
static JSValueRef Require(JSContextRef context, JSObjectRef object, JSObjectRef globalobj, size_t argc, const JSValueRef args[], JSValueRef* ex);
static bool RegisterFunction(JSGlobalContextRef context, JSObjectRef object, const char* functionName, JSObjectCallAsFunctionCallback cbFunction);
static void PrintError(JSContextRef, JSValueRef);
private:
JSGlobalContextRef context;
};
JSCShell::~JSCShell() {
if(context != 0) {
JSGlobalContextRelease(context);
context = 0;
}
}
bool JSCShell::InitializeEngine() {
if(context != 0) {
JSGlobalContextRelease(context);
context = 0;
}
// TODO: check for initialization errors
context = JSGlobalContextCreate(NULL);
if(context == 0) return false;
JSObjectRef globalObject = JSContextGetGlobalObject(context);
// store this for later use
JSClassDefinition __shell_classdef__;
JSClassRef __shell_class__ = JSClassCreate(&__shell_classdef__);
JSObjectRef __shell__ = JSObjectMake(context, __shell_class__, 0);
bool success = JSObjectSetPrivate(__shell__, (void*) (long) this);
JSStringRef shellKey = JSStringCreateWithUTF8CString("__shell__");
JSObjectSetProperty(context, globalObject, shellKey, __shell__, kJSPropertyAttributeReadOnly, NULL);
JSStringRelease(shellKey);
JSCShell::RegisterFunction(context, globalObject, "print", JSCShell::Print);
JSCShell::RegisterFunction(context, globalObject, "require", JSCShell::Require);
return true;
}
bool JSCShell::ExecuteScript(const std::string& source, const std::string& scriptPath) {
JSStringRef jsScript;
JSStringRef sourceURL;
JSValueRef ex;
jsScript = JSStringCreateWithUTF8CString(source.c_str());
sourceURL = JSStringCreateWithUTF8CString(scriptPath.c_str());
JSValueRef jsResult = JSEvaluateScript(context, jsScript, 0, sourceURL, 0, &ex);
JSStringRelease(jsScript);
if (jsResult == NULL && ex != NULL) {
JSCShell::PrintError(context, ex);
return false;
}
return true;
}
bool JSCShell::DisposeEngine() {
JSGlobalContextRelease(context);
context = 0;
return true;
}
JSValueRef JSCShell::Print(JSContextRef context, JSObjectRef object,
JSObjectRef globalobj, size_t argc,
const JSValueRef args[], JSValueRef* ex) {
if (argc > 0)
{
JSStringRef string = JSValueToStringCopy(context, args[0], NULL);
size_t numChars = JSStringGetMaximumUTF8CStringSize(string);
char *stringUTF8 = new char[numChars];
JSStringGetUTF8CString(string, stringUTF8, numChars);
printf("%s\n", stringUTF8);
delete[] stringUTF8;
}
return JSValueMakeUndefined(context);
}
// Attention: this feature should not create too high expectations.
// It is only capable of loading things relative to the execution directory
// and not relative to the parent script.
JSValueRef JSCShell::Require(JSContextRef context, JSObjectRef object,
JSObjectRef globalObj, size_t argc,
const JSValueRef args[], JSValueRef* ex) {
JSObjectRef module;
JSStringRef shellKey = JSStringCreateWithUTF8CString("__shell__");
JSValueRef shellAsVal = JSObjectGetProperty(context, globalObj, shellKey, NULL);
JSStringRelease(shellKey);
JSObjectRef shell = JSValueToObject(context, shellAsVal, 0);
JSCShell *_this = (JSCShell*) (long) JSObjectGetPrivate(shell);
if (argc > 0)
{
JSStringRef string = JSValueToStringCopy(context, args[0], NULL);
size_t numChars = JSStringGetMaximumUTF8CStringSize(string);
char *stringUTF8 = new char[numChars];
JSStringGetUTF8CString(string, stringUTF8, numChars);
std::string modulePath(stringUTF8);
module = _this->Import(modulePath);
delete[] stringUTF8;
}
if (module) {
return module;
} else {
printf("Ooops.\n");
return JSValueMakeUndefined(context);
}
}
JSObjectRef JSCShell::Import(const std::string& module_path) {
HANDLE library;
std::string module_name = LoadModule(module_path, &library);
if (library == 0) {
printf("Could not load module.");
return 0;
}
std::string symname = std::string(module_name).append("_initialize");
JSCIntializer init_function = reinterpret_cast<JSCIntializer>((long) LOAD_SYMBOL(library, symname.c_str()));
if(init_function == 0) {
printf("Could not find module's initializer function.");
return 0;
}
JSObjectRef module;
init_function(context, &module);
return module;
}
bool JSCShell::RegisterFunction(JSGlobalContextRef context, JSObjectRef object,
const char* functionName, JSObjectCallAsFunctionCallback callback) {
JSStringRef js_functionName = JSStringCreateWithUTF8CString(functionName);
JSObjectSetProperty(context, object, js_functionName,
JSObjectMakeFunctionWithCallback(context, js_functionName, callback),
kJSPropertyAttributeNone, NULL);
JSStringRelease(js_functionName);
return true;
}
void JSCShell::PrintError(JSContextRef ctx, JSValueRef err) {
char *buffer;
size_t length;
JSStringRef string = JSValueToStringCopy(ctx, err, 0);
length = JSStringGetLength(string);
buffer = new char[length+1];
JSStringGetUTF8CString(string, buffer, length+1);
std::string errMsg(buffer);
JSStringRelease(string);
delete[] buffer;
JSObjectRef errObj = JSValueToObject(ctx, err, 0);
if(errObj == 0) {
std::cerr << errMsg << std::endl;
return;
}
JSStringRef sourceURLKey = JSStringCreateWithUTF8CString("sourceURL");
JSStringRef sourceURLStr = JSValueToStringCopy(ctx, JSObjectGetProperty(ctx, errObj, sourceURLKey, 0), 0);
length = JSStringGetLength(sourceURLStr);
buffer = new char[length+1];
JSStringGetUTF8CString(sourceURLStr, buffer, length+1);
std::string sourceURL(buffer);
delete[] buffer;
JSStringRelease(sourceURLStr);
JSStringRelease(sourceURLKey);
JSStringRef lineKey = JSStringCreateWithUTF8CString("line");
JSValueRef jsLine = JSObjectGetProperty(ctx, errObj, lineKey, 0);
int line = (int) JSValueToNumber(ctx, jsLine, 0);
JSStringRelease(lineKey);
std::cerr << sourceURL << ":" << line << ":" << errMsg << std::endl;
}
JSShell* JSCShell_Create() {
return new JSCShell();
}

310
Tools/javascript/v8_shell.cxx Executable file
View file

@ -0,0 +1,310 @@
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <v8.h>
#include <vector>
#include "js_shell.h"
typedef int (*V8ExtensionInitializer) (v8::Handle<v8::Object> module);
class V8Shell: public JSShell {
public:
V8Shell();
virtual ~V8Shell();
virtual bool RunScript(const std::string& scriptPath);
virtual bool RunShell();
protected:
virtual bool InitializeEngine();
virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath);
virtual bool DisposeEngine();
private:
v8::Handle<v8::Value> Import(const std::string& moduleName);
v8::Persistent<v8::Context> CreateShellContext();
void ReportException(v8::TryCatch* handler);
static v8::Handle<v8::Value> Print(const v8::Arguments& args);
static v8::Handle<v8::Value> Require(const v8::Arguments& args);
static v8::Handle<v8::Value> Quit(const v8::Arguments& args);
static v8::Handle<v8::Value> Version(const v8::Arguments& args);
static const char* ToCString(const v8::String::Utf8Value& value);
protected:
v8::Persistent<v8::Context> context;
};
#ifdef __GNUC__
#include <dlfcn.h>
#define LOAD_SYMBOL(handle, name) dlsym(handle, name)
#else
#error "implement dll loading"
#endif
V8Shell::V8Shell()
{
}
V8Shell::~V8Shell() {
context.Dispose();
v8::V8::Dispose();
}
bool V8Shell::RunScript(const std::string& scriptPath) {
if (!context.IsEmpty()) {
context.Dispose();
}
std::string source = ReadFile(scriptPath);
context = CreateShellContext();
if (context.IsEmpty()) {
printf("Could not create context.\n");
return false;
}
context->Enter();
//v8::Context::Scope context_scope(context);
v8::HandleScope scope;
// Store a pointer to this shell for later use
v8::Handle<v8::Object> global = context->Global();
v8::Local<v8::External> __shell__ = v8::External::New((void*) (long) this);
global->SetHiddenValue(v8::String::New("__shell__"), __shell__);
// Node.js compatibility: make `print` available as `console.log()`
ExecuteScript("var console = {}; console.log = print;", "<console>");
if(!ExecuteScript(source, scriptPath)) {
return false;
}
context->Exit();
context.Dispose();
v8::V8::Dispose();
return true;
}
bool V8Shell::RunShell() {
if (!context.IsEmpty()) {
context.Dispose();
}
context = CreateShellContext();
if (context.IsEmpty()) {
printf("Could not create context.\n");
return false;
}
context->Enter();
v8::Context::Scope context_scope(context);
ExecuteScript("var console = {}; console.log = print;", "<console>");
static const int kBufferSize = 1024;
while (true) {
char buffer[kBufferSize];
printf("> ");
char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break;
std::string source(str);
ExecuteScript(source, "(shell)");
}
printf("\n");
context->Exit();
context.Dispose();
v8::V8::Dispose();
return true;
}
bool V8Shell::InitializeEngine() {
return true;
}
bool V8Shell::ExecuteScript(const std::string& source, const std::string& name) {
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(source.c_str()), v8::String::New(name.c_str()));
// Stop if script is empty
if (script.IsEmpty()) {
// Print errors that happened during compilation.
ReportException(&try_catch);
return false;
}
v8::Handle<v8::Value> result = script->Run();
// Print errors that happened during execution.
if (try_catch.HasCaught()) {
ReportException(&try_catch);
return false;
} else {
return true;
}
}
bool V8Shell::DisposeEngine() {
return true;
}
v8::Persistent<v8::Context> V8Shell::CreateShellContext() {
v8::HandleScope scope;
// Create a template for the global object.
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// Bind global functions
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8Shell::Print));
global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(V8Shell::Quit));
global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8Shell::Require));
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(V8Shell::Version));
v8::Persistent<v8::Context> _context = v8::Context::New(NULL, global);
return _context;
}
v8::Handle<v8::Value> V8Shell::Import(const std::string& module_path)
{
v8::HandleScope scope;
HANDLE library;
std::string module_name = LoadModule(module_path, &library);
std::string symname = std::string(module_name).append("_initialize");
V8ExtensionInitializer init_function = reinterpret_cast<V8ExtensionInitializer>((long) LOAD_SYMBOL(library, symname.c_str()));
if(init_function == 0) {
printf("Could not find initializer function.");
return v8::Undefined();
}
v8::Local<v8::Object> module = v8::Object::New();
init_function(module);
return scope.Close(module);
}
v8::Handle<v8::Value> V8Shell::Print(const v8::Arguments& args) {
bool first = true;
for (int i = 0; i < args.Length(); i++) {
v8::HandleScope handle_scope;
if (first) {
first = false;
} else {
printf(" ");
}
v8::String::Utf8Value str(args[i]);
const char* cstr = V8Shell::ToCString(str);
printf("%s", cstr);
}
printf("\n");
fflush(stdout);
return v8::Undefined();
}
v8::Handle<v8::Value> V8Shell::Require(const v8::Arguments& args) {
v8::HandleScope scope;
if (args.Length() != 1) {
printf("Illegal arguments for `require`");
};
v8::String::Utf8Value str(args[0]);
const char* cstr = V8Shell::ToCString(str);
std::string moduleName(cstr);
v8::Local<v8::Object> global = v8::Context::GetCurrent()->Global();
v8::Local<v8::Value> hidden = global->GetHiddenValue(v8::String::New("__shell__"));
v8::Local<v8::External> __shell__ = v8::Local<v8::External>::Cast(hidden);
V8Shell* _this = (V8Shell*) (long) __shell__->Value();
v8::Handle<v8::Value> module = _this->Import(moduleName);
return scope.Close(module);
}
v8::Handle<v8::Value> V8Shell::Quit(const v8::Arguments& args) {
int exit_code = args[0]->Int32Value();
fflush(stdout);
fflush(stderr);
exit(exit_code);
return v8::Undefined();
}
v8::Handle<v8::Value> V8Shell::Version(const v8::Arguments& args) {
return v8::String::New(v8::V8::GetVersion());
}
void V8Shell::ReportException(v8::TryCatch* try_catch) {
v8::HandleScope handle_scope;
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = V8Shell::ToCString(exception);
v8::Handle<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
printf("%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(message->GetScriptResourceName());
const char* filename_string = V8Shell::ToCString(filename);
int linenum = message->GetLineNumber();
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
// Print line of source code.
v8::String::Utf8Value sourceline(message->GetSourceLine());
const char* sourceline_string = V8Shell::ToCString(sourceline);
printf("%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn();
for (int i = 0; i < start; i++) {
printf(" ");
}
int end = message->GetEndColumn();
for (int i = start; i < end; i++) {
printf("^");
}
printf("\n");
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
if (stack_trace.length() > 0) {
const char* stack_trace_string = V8Shell::ToCString(stack_trace);
printf("%s\n", stack_trace_string);
}
}
}
// Extracts a C string from a V8 Utf8Value.
const char* V8Shell::ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>";
}
JSShell* V8Shell_Create() {
return new V8Shell();
}

89
Tools/swigconfig.h.cmake Normal file
View file

@ -0,0 +1,89 @@
/* Define to 1 if the system has the type `bool'. */
#cmakedefine HAVE_BOOL 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the `dl' library (-ldl). */
#cmakedefine HAVE_LIBDL 1
/* Define to 1 if you have the `dld' library (-ldld). */
#cmakedefine HAVE_LIBDLD 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define if popen is available */
#cmakedefine HAVE_POPEN 1
/* Define if rxspencer is available */
#cmakedefine HAVE_RXSPENCER 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#cmakedefine NO_MINUS_C_MINUS_O 1
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Name of package */
#define PACKAGE "swig"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://www.swig.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "swig"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "swig @SWIG_VERSION@"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "swig"
/* Define to the version of this package. */
#define PACKAGE_VERSION "@SWIG_VERSION@"
/* Compiler that built SWIG */
#define SWIG_CXX "@SWIG_CXX@"
/* Directory for SWIG system-independent libraries */
#define SWIG_LIB "/usr/local/share/swig/2.0.0"
/* Directory for SWIG system-independent libraries (Unix install on native
Windows) */
#define SWIG_LIB_WIN_UNIX "C:/cygwin/usr/local/share/swig/2.0.0"
/* Platform that SWIG is built for */
#define SWIG_PLATFORM "i686-pc-cygwin"
/* Version number of package */
#define VERSION "@SWIG_VERSION@"
/* Default language */
#define SWIG_LANG "-tcl"
/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
#if defined(_MSC_VER)
# define _CRT_SECURE_NO_DEPRECATE
#endif

24
Tools/swigprinters.gdb Normal file
View file

@ -0,0 +1,24 @@
python
import sys
import os
try:
global SWIG_PRINTER_DIR
sys.path.insert(0, SWIG_PRINTER_DIR)
except NameError:
raise RuntimeError("""
---------------------------------------------------------
Change ~/.gdbinit to be able to use swig pretty printers:
> set python SWIG_PRINTER_DIR = <path/to/swig>/Tools
> source <path/to/swig>/Tools/swigprinters.gdb
---------------------------------------------------------
""")
from swigprinters import register_swig_printers, enableGdbPrintWorkaround, \
setChildrenRecursionLevel
#enableGdbPrintWorkaround()
#setChildrenRecursionLevel(2)
register_swig_printers (None)
end

574
Tools/swigprinters.py Executable file
View file

@ -0,0 +1,574 @@
import gdb
import gdb.types
import itertools
import re
log_file = None
GDB_FLATTENED_CHILDREN_WORKAROUND = False
CHILDREN_MAX_RECURSION_LEVEL = 0
# workaround: don't cast the following DOHs to it's actual type
# to avoid infinite pretty-print loops
cast_black_list = {
'Hash': set(['parentNode', 'symtab', 'csymtab', 'sym:symtab', 'inherit', 'nextSibling', 'previousSibling'])
}
def print_(msg):
global log_file;
if True:
if log_file == None:
log_file = open('swig_gdb.log', 'w')
log_file.write(msg)
print(msg)
class SwigStringPrinter:
"""
Pretty print Swig String* types.
"""
def __init__ (self, typename, val):
self.typename = typename
self.val = val
try:
self.t_swigstr_ptr = gdb.lookup_type("struct String").pointer()
self.t_doh_base_ptr = gdb.lookup_type("DohBase").pointer()
except Exception as err:
print_("SwigStringPrinter: Could not retrieve gdb types.\n %s.\n"%(str(err)))
def display_hint(self):
return 'string'
def to_string(self):
ret = "<invalid>"
# Conversion taken from Swig Internals manual:
# http://peregrine.hpc.uwm.edu/Head-node-docs/swig/2.0.4/Devel/internals.html#7
# (*(struct String *)(((DohBase *)s)->data)).str
dohbase = None;
str_data = None;
char_ptr = None;
try:
dohbase = self.val.reinterpret_cast(self.t_doh_base_ptr).dereference()
except Exception as err:
print_("SwigStringPrinter: Could not dereference DOHBase*\n");
return "<invalid>";
try:
str_data = dohbase['data'].reinterpret_cast(self.t_swigstr_ptr).dereference()
except Exception as err:
print_("SwigStringPrinter: Could not dereference struct String*\n");
return "<invalid>";
try:
char_ptr = str_data['str']
except Exception as err:
print_("SwigStringPrinter: Could not access field (struct String).str\n");
return "<invalid>";
if char_ptr.is_lazy is True:
char_ptr.fetch_lazy ()
try:
ret = char_ptr.string()
except Exception as err:
print_("SwigStringPrinter: Could not convert const char* to string\n");
return "<invalid>";
return ret
class SwigIterator:
def __init__(self):
self.t_doh_base_ptr = gdb.lookup_type("DohBase").pointer()
self.t_string_ptr = gdb.lookup_type("String").pointer()
self.t_node_ptr = gdb.lookup_type("Node").pointer()
self.t_hash_ptr = gdb.lookup_type("Hash").pointer()
self.t_file_ptr = gdb.lookup_type("File").pointer()
self.t_void_ptr = gdb.lookup_type("void").pointer()
def cast_doh(self, doh, name = None):
if doh == 0:
return doh
doh = doh.reinterpret_cast(self.t_doh_base_ptr);
val_base = doh.dereference()
val_type = val_base['type'].dereference()
val_typestr = val_type['objname'].string()
if not name == None and val_typestr in cast_black_list:
blacklist = cast_black_list[val_typestr]
if name in blacklist:
return doh
if "String" == val_typestr:
doh = doh.reinterpret_cast(self.t_string_ptr)
elif "File" == val_typestr:
doh = doh.reinterpret_cast(self.t_file_ptr)
# BUG: GDB Pyhton can not handle cyclic references yet
# so these casts are deactivated
elif "Hash" == val_typestr:
doh = doh.reinterpret_cast(self.t_hash_ptr)
elif "Node" == val_typestr:
doh = doh.reinterpret_cast(self.t_node_ptr)
return doh
class SwigListIterator(SwigIterator):
def __init__(self, val):
SwigIterator.__init__(self);
try:
self.valid = False
self.val = val.reinterpret_cast(self.t_doh_base_ptr)
val_base = self.val.dereference()
val_type = val_base['type'].dereference()
val_typestr = val_type['objname'].string()
#print_("SwigListIterator: constructing iterator for value of type %s"%val_typestr)
self.t_struct_list_ptr = gdb.lookup_type("struct List").pointer()
doh_base = self.val.dereference()
self.l = doh_base['data'].reinterpret_cast(self.t_struct_list_ptr).dereference()
self.address = 0
self._index = 0
self.key = 0
self.item = 0
self.address = self.val.dereference().address
self.is_first = True
self.valid = True
except Exception as err:
print_("SwigListIterator: Construction failed.\n %s.\n"%(str(err)))
def __iter__(self):
return self
def List_first(self):
self.object = None;
self._index = 0
self.key = 0
self.nitems = int(self.l['nitems'])
self.items = self.l['items']
if self.nitems > 0:
self.item = self.items[0]
else:
self.stop()
def List_next(self):
self._index = self._index + 1
if self._index >= self.nitems:
self.stop()
else:
self.item = self.items[self._index]
def next(self):
if not self.valid:
self.stop()
if self.is_first:
self.is_first = False
try:
self.List_first()
except StopIteration:
raise StopIteration
except Exception as err:
print_("Error during iteration to first node: \n %s \n" %(str(err)))
self.stop()
else:
try:
self.List_next()
except StopIteration:
raise StopIteration
except Exception as err:
print_("Error during iteration to first node: \n %s \n" %(str(err)))
self.stop()
key_str = "[%d]"%self._index
item = 0
try:
item = self.cast_doh(self.item)
except Exception as err:
print_("SwigListIterator(%s): Exception during casting of value doh:\n %s\n" % (str(self.address), str(err)) )
self.stop()
return (key_str, item)
def stop(self):
self.is_first = True
self.item = 0
self.key = 0
raise StopIteration
class SwigHashIterator(SwigIterator):
def __init__(self, val):
SwigIterator.__init__(self);
try:
self.valid = False
self.val = val.reinterpret_cast(self.t_doh_base_ptr)
self.t_struct_hash_ptr = gdb.lookup_type("struct Hash").pointer()
self.t_struct_hash_node_ptr = gdb.lookup_type("struct HashNode").pointer()
doh_base = self.val.dereference()
hash_ = doh_base['data'].reinterpret_cast(self.t_struct_hash_ptr).dereference()
self.hashtable = hash_['hashtable']
self.hashsize = int(hash_['hashsize'])
self.nitems = int(hash_['nitems'])
self.next_ = 0
self.address = 0
self.pos = 0;
self._current = 0
self.item = 0
self.key = 0
self._index = 0
self.address = self.val.dereference().address
self.is_first = True
self.valid = True
except Exception as err:
print_("SwigHashIterator: Construction failed.\n %s.\n"%(str(err)))
def __iter__(self):
return self
def Hash_firstiter(self):
self._current = 0;
self.item = 0;
self.key = 0;
self._index = 0;
while (self._index < self.hashsize) and (self.hashtable[self._index] == 0):
self._index = self._index+1;
if self._index >= self.hashsize:
self.stop();
self._current = self.hashtable[self._index]
self._current = self._current.reinterpret_cast(self.t_struct_hash_node_ptr);
self.item = self._current['object'];
self.key = self._current['key'];
self._current = self._current['next'];
def Hash_nextiter(self):
if self._current == 0:
self._index = self._index + 1
while (self._index < self.hashsize) and (self.hashtable[self._index] == 0):
self._index = self._index + 1
if self._index >= self.hashsize:
self.item = 0;
self.key = 0;
self._current = 0;
self.stop()
self._current = self.hashtable[self._index];
self._current = self._current.reinterpret_cast(self.t_struct_hash_node_ptr);
self.key = self._current['key'];
self.item = self._current['object'];
self._current = self._current['next'];
def next(self):
if not self.valid:
self.stop()
if self.is_first:
self.is_first = False
try:
self.Hash_firstiter()
except StopIteration:
raise StopIteration
except Exception as err:
print_("Error during iteration to first node: \n %s \n" %(str(err)))
self.stop()
else:
try:
self.Hash_nextiter()
except StopIteration:
raise StopIteration
except Exception as err:
print_("Error during iteration to first node: \n %s \n" %(str(err)))
self.stop()
key_str = "<err>"
item = 0
try:
string_printer = SwigStringPrinter("String *", self.key)
key_str = string_printer.to_string()
except Exception as err:
print_("SwigHashIterator(%s): Exception during extracting key string:\n %s\n" % (str(self.address), str(err)) )
self.stop()
try:
item = self.cast_doh(self.item, key_str)
except Exception as err:
print_("SwigHashIterator(%s): Exception during casting of value doh:\n %s\n" % (str(self.address), str(err)) )
self.stop()
return (key_str, item)
def stop(self):
self.is_first = True
raise StopIteration
class AlternateKeyValueIterator():
def __init__(self, iterable):
self.it = iterable.__iter__()
self._next = None
self.count = -1
def __iter__(self):
return self
def next(self):
if self._next == None:
key, value = self.it.next()
self._next = value
self.count = self.count + 1
return ("[%d]"%self.count, key)
else:
value = self._next
self._next = None
return ("[%d]"%self.count, value)
class NopIterator:
def __init__(self):
pass
def __iter__(self):
return self
def next(self):
raise StopIteration
class SwigListPrinter:
"""
Pretty print Swig List* types (also ParmList*).
"""
def __init__ (self, typename, val):
self.typename = typename
self.val = val
it = SwigListIterator(val)
self.valid = it.valid
self.address = it.address
def display_hint(self):
return 'array'
def to_string(self):
return "%s(%s)" % (str(self.typename), str(self.address))
def children(self):
if not self.valid:
print_("SwigListPrinter: Invalid state.\n")
return NopIterator()
try:
it = SwigListIterator(self.val)
return it
except Exception as err:
print_("SwigListPrinter: Error during creation of children iterator. \n %s \n" %(str(err)))
raise err
class SwigHashPrinter:
"""
Pretty print Swig Hash* types (also Node*).
"""
def __init__ (self, typename, val):
self.typename = typename
self.val = val
it = SwigHashIterator(val)
self.valid = it.valid
self.address = it.address
self.level = 0;
def display_hint(self):
return 'map'
def to_string(self):
return "%s(%s)" % (str(self.typename), str(self.address))
def children(self):
global GDB_FLATTENED_CHILDREN_WORKAROUND
global CHILDREN_MAX_RECURSION_LEVEL
if not self.valid:
print_("SwigHashPrinter: Invalid state.\n")
return NopIterator()
if self.level > CHILDREN_MAX_RECURSION_LEVEL:
return NopIterator()
try:
it = SwigHashIterator(self.val)
if GDB_FLATTENED_CHILDREN_WORKAROUND:
return AlternateKeyValueIterator(it)
return it
except Exception as err:
print_("SwigHashPrinter: Error during creation of children iterator. \n %s \n" %(str(err)))
raise err
class SwigSimplePrinter:
def __init__ (self, typename, val):
self.typename = typename
self.val = val
def display_hint(self):
return "string"
def to_string(self):
return "%s(%s)"%(self.typename, str(self.val.address))
class SwigDelegatingPrinter:
def __init__ (self, typename, val):
t_doh_base_ptr = gdb.lookup_type("DohBase").pointer()
val_base = val.reinterpret_cast(t_doh_base_ptr).dereference()
val_type = val_base['type'].dereference()
val_typestr = val_type['objname'].string()
self.has_children = False
if val_typestr == "Hash":
self.delegate = SwigHashPrinter(typename, val)
self.has_children = True
elif val_typestr == "List":
self.delegate = SwigListPrinter(typename, val)
self.has_children = True
elif val_typestr == "String":
self.delegate = SwigStringPrinter(typename, val)
else:
self.delegate = SwigSimplePrinter(typename, val)
def display_hint(self):
return self.delegate.display_hint()
def to_string(self):
return self.delegate.to_string()
def children(self):
if not self.has_children:
return NopIterator()
return self.delegate.children()
class RxPrinter(object):
def __init__(self, name, function):
super(RxPrinter, self).__init__()
self.name = name
self.function = function
self.enabled = True
def invoke(self, value):
if not self.enabled:
return None
return self.function(self.name, value)
# A pretty-printer that conforms to the "PrettyPrinter" protocol from
# gdb.printing. It can also be used directly as an old-style printer.
class Printer(object):
def __init__(self, name):
super(Printer, self).__init__()
self.name = name
self.subprinters = []
self.lookup = {}
self.enabled = True
self.compiled_rx = re.compile('^([a-zA-Z0-9_: *]+)$')
def add(self, name, function):
if not self.compiled_rx.match(name):
raise ValueError, 'error: "%s" does not match' % name
printer = RxPrinter(name, function)
self.subprinters.append(printer)
self.lookup[name] = printer
print('Added pretty printer for %s. ' % (name))
def __call__(self, val):
typename = str(val.type)
if typename in self.lookup:
ret = self.lookup[typename].invoke(val)
return ret
# Cannot find a pretty printer. Return None.
return None
swig_printer = None
def register_swig_printers(obj):
global swig_printer
if obj is None:
obj = gdb
obj.pretty_printers.append(swig_printer)
def build_swig_printer():
global swig_printer
swig_printer = Printer("swig")
swig_printer.add('String *', SwigStringPrinter)
swig_printer.add('const String *', SwigStringPrinter)
swig_printer.add('SwigType *', SwigStringPrinter)
swig_printer.add('Hash *', SwigHashPrinter)
swig_printer.add('const Hash *', SwigHashPrinter)
swig_printer.add('Node *', SwigHashPrinter)
swig_printer.add('const Node *', SwigHashPrinter)
swig_printer.add('Parm *', SwigHashPrinter)
swig_printer.add('const Parm *', SwigHashPrinter)
swig_printer.add('List *', SwigListPrinter)
swig_printer.add('const List *', SwigListPrinter)
swig_printer.add('ParmList *', SwigDelegatingPrinter)
swig_printer.add('const ParmList *', SwigDelegatingPrinter)
swig_printer.add('File *', SwigDelegatingPrinter)
#swig_printer.add('DOH *', SwigDelegatingPrinter)
#swig_printer.add('const DOH *', SwigDelegatingPrinter)
print_("Loaded swig printers\n");
def enableGdbPrintWorkaround():
global GDB_FLATTENED_CHILDREN_WORKAROUND
GDB_FLATTENED_CHILDREN_WORKAROUND = True
def setChildrenRecursionLevel(level):
global CHILDREN_MAX_RECURSION_LEVEL
CHILDREN_MAX_RECURSION_LEVEL = level
build_swig_printer()