summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-08-20 17:36:29 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2018-08-20 17:37:22 +0100
commit53c3de3575351bd1892a203932ffc1288e8e9640 (patch)
tree2e00e38f3f24210933a3cb805ab0cfc6e6b5fbac
parent55f066e8d50760bbd1493e46bb62258a9afd41d4 (diff)
igt/shell: Bare v8 baselineigt-shell
-rw-r--r--meson.build7
-rw-r--r--shell/meson.build6
-rw-r--r--shell/v8-shell.cc314
3 files changed, 326 insertions, 1 deletions
diff --git a/meson.build b/meson.build
index 7d7072bd..527574eb 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('igt-gpu-tools', 'c',
+project('igt-gpu-tools', [ 'c', 'cpp' ],
version : '1.23',
default_options: [
'warning_level=2',
@@ -8,6 +8,7 @@ project('igt-gpu-tools', 'c',
meson_version : '>=0.44.0')
cc = meson.get_compiler('c')
+cxx = meson.get_compiler('cpp')
cc_args = [
'-Wno-unused-parameter',
@@ -24,6 +25,9 @@ foreach cc_arg : cc_args
if cc.has_argument(cc_arg)
add_global_arguments(cc_arg, language : 'c')
endif
+ if cxx.has_argument(cc_arg)
+ add_global_arguments(cc_arg, language : 'cpp')
+ endif
endforeach
_build_overlay = false
@@ -104,6 +108,7 @@ libkmod = dependency('libkmod')
libprocps = dependency('libprocps', required : true)
libunwind = dependency('libunwind', required : true)
ssl = dependency('openssl', required : true)
+v8 = cxx.find_library('v8')
valgrind = null_dep
valgrindinfo = 'No'
diff --git a/shell/meson.build b/shell/meson.build
index ee11b0b5..8eb06b71 100644
--- a/shell/meson.build
+++ b/shell/meson.build
@@ -1,3 +1,9 @@
+executable('v8', [
+ 'v8-shell.cc',
+ ], dependencies : [ v8, math, libkmod ],
+ include_directories : include_directories('include', '../include')
+)
+
executable('igt', [
'duktape/duktape.c',
'drm/drm-constants.c',
diff --git a/shell/v8-shell.cc b/shell/v8-shell.cc
new file mode 100644
index 00000000..1e10c512
--- /dev/null
+++ b/shell/v8-shell.cc
@@ -0,0 +1,314 @@
+#include <v8.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include "../lib/version.h"
+#include "../config.h"
+
+const char* ToCString(const v8::String::Utf8Value& value) {
+ return *value ? *value : "<invalid string>";
+}
+
+v8::Handle<v8::Value> Print(const v8::Arguments& args)
+{
+ for (int i = 0; i < args.Length(); i++) {
+ v8::HandleScope handle_scope;
+ v8::String::Utf8Value str(args[i]);
+ printf("%s%s", i ? " " : "", ToCString(str));
+ }
+ printf("\n");
+ fflush(stdout);
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::String> ReadFile(const char *name)
+{
+ FILE *file = fopen(name, "rb");
+ if (file == NULL)
+ return v8::Handle<v8::String>();
+
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ rewind(file);
+
+ char *buf = new char[size + 1];
+ size_t i = 0;
+ while (i < size) {
+ size_t r = fread(buf + i, 1, size - i, file);
+ if (!r)
+ break;
+
+ i += r;
+ }
+ buf[i] = '\0';
+ fclose(file);
+
+ v8::Handle<v8::String> result = v8::String::New(buf, i);
+ delete[] buf;
+
+ return result;
+}
+
+v8::Handle<v8::Value> Read(const v8::Arguments& args)
+{
+ if (args.Length() != 1)
+ return v8::ThrowException(v8::String::New("Bad parameters"));
+
+ v8::String::Utf8Value file(args[0]);
+ if (*file == NULL)
+ return v8::ThrowException(v8::String::New("Error loading file"));
+
+ v8::Handle<v8::String> source = ReadFile(*file);
+ if (source.IsEmpty())
+ return v8::ThrowException(v8::String::New("Error loading file"));
+
+ return source;
+}
+
+v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
+ fflush(stdout);
+ fflush(stderr);
+ exit(args[0]->Int32Value());
+ return v8::Undefined();
+}
+
+void ReportException(v8::TryCatch* try_catch) {
+ v8::HandleScope handle_scope;
+
+ v8::String::Utf8Value exception(try_catch->Exception());
+ const char* exception_string = ToCString(exception);
+
+ v8::Handle<v8::Message> message = try_catch->Message();
+ if (message.IsEmpty()) {
+ printf("%s\n", exception_string);
+ } else {
+ v8::String::Utf8Value filename(message->GetScriptResourceName());
+ printf("%s:%i: %s\n",
+ ToCString(filename), message->GetLineNumber(), exception_string);
+
+ v8::String::Utf8Value sourceline(message->GetSourceLine());
+ printf("%s\n", ToCString(sourceline));
+
+ 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)
+ printf("%s\n", ToCString(stack_trace));
+ }
+}
+
+bool ExecuteString(v8::Handle<v8::String> source,
+ v8::Handle<v8::Value> name,
+ bool print_result,
+ bool report_exceptions)
+{
+ v8::HandleScope handle_scope;
+ v8::TryCatch try_catch;
+
+ v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
+ if (script.IsEmpty()) {
+ if (report_exceptions)
+ ReportException(&try_catch);
+ return false;
+ }
+
+ v8::Handle<v8::Value> result = script->Run();
+ if (result.IsEmpty()) {
+ if (report_exceptions)
+ ReportException(&try_catch);
+ return false;
+ }
+
+ if (print_result && !result->IsUndefined()) {
+ v8::String::Utf8Value str(result);
+ printf("%s\n", ToCString(str));
+ }
+
+ return true;
+}
+
+v8::Handle<v8::Value> Load(const v8::Arguments& args) {
+ for (int i = 0; i < args.Length(); i++) {
+ v8::HandleScope handle_scope;
+
+ v8::String::Utf8Value file(args[i]);
+ if (*file == NULL)
+ return v8::ThrowException(v8::String::New("Error loading file"));
+
+ v8::Handle<v8::String> source = ReadFile(*file);
+ if (source.IsEmpty())
+ return v8::ThrowException(v8::String::New("Error loading file"));
+
+ if (!ExecuteString(source, v8::String::New(*file), false, false))
+ return v8::ThrowException(v8::String::New("Error executing file"));
+ }
+
+ return v8::Undefined();
+}
+
+v8::Persistent<v8::Context> ShellContext()
+{
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
+
+#if 1
+ static const struct {
+ const char *name;
+ v8::Handle<v8::Value> (*fn)(const v8::Arguments&);
+ } globals[] = {
+ { "print", Print },
+ { "read", Read },
+ { "load", Load },
+ { "quit", Quit },
+ { },
+ };
+ for (typeof(*globals) *g = globals; g->name; g++)
+ global->Set(v8::String::New(g->name), v8::FunctionTemplate::New(g->fn));
+#endif
+
+ return v8::Context::New(NULL, global);
+}
+
+void print_welcome()
+{
+ struct utsname uts;
+
+ uname(&uts);
+ printf("IGT Version: %s-%s (%s) (%s: %s %s)\n",
+ PACKAGE_VERSION, IGT_GIT_SHA1, TARGET_CPU_PLATFORM,
+ uts.sysname, uts.release, uts.machine);
+ printf("V8: %s\n", v8::V8::GetVersion());
+}
+
+int do_eval(v8::Handle<v8::Context> ctx, const char *str)
+{
+ v8::Handle<v8::String> filename = v8::String::New("cmdline");
+ v8::Handle<v8::String> source = v8::String::New(str);
+ return !ExecuteString(source, filename, false, true);
+}
+
+int run(v8::Handle<v8::Context> ctx, int argc, char **argv)
+{
+ while (++optind < argc) {
+ const char *str = argv[optind];
+ v8::Handle<v8::String> file_name = v8::String::New(str);
+ v8::Handle<v8::String> source = ReadFile(str);
+ if (source.IsEmpty()) {
+ printf("Error reading '%s'\n", str);
+ continue;
+ }
+
+ if (!ExecuteString(source, file_name, false, true))
+ return 1;
+ }
+
+ return 0;
+}
+
+int shell(v8::Handle<v8::Context> ctx, int argc, char **argv)
+{
+ print_welcome();
+
+ static const int kBufferSize = 256;
+
+ // Enter the execution environment before evaluating any code.
+ v8::Context::Scope context_scope(ctx);
+ v8::Local<v8::String> name(v8::String::New("(shell)"));
+
+#if 0
+ static const struct {
+ const char *name;
+ v8::Handle<v8::Value> (*fn)(const v8::Arguments&);
+ } globals[] = {
+ { "print", Print },
+ { "read", Read },
+ { "load", Load },
+ { "quit", Quit },
+ { },
+ };
+ for (typeof(*globals) *g = globals; g->name; g++) {
+ v8::Handle<v8::String> name(v8::String::New(g->name));
+ v8::Local<v8::Function> fn(v8::Function::New(g->fn));
+ ctx->Global()->Set(name, fn);
+ }
+#endif
+ while (true) {
+ char buffer[kBufferSize];
+
+ printf("igt> ");
+ char *str = fgets(buffer, kBufferSize, stdin);
+ if (str == NULL)
+ break;
+
+ v8::HandleScope handle_scope;
+ ExecuteString(v8::String::New(str), name, true, true);
+ }
+
+ printf("\n");
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
+ int err, opt;
+
+ {
+ v8::HandleScope handle_scope;
+ v8::Persistent<v8::Context> ctx = ShellContext();
+ if (ctx.IsEmpty()) {
+ fprintf(stderr, "Error creating V8 context\n");
+ return 1;
+ }
+
+ ctx->Enter();
+
+ while ((opt = getopt(argc, argv, "e:")) != -1) {
+ switch (opt) {
+ case 'e':
+ if (do_eval(ctx, optarg))
+ goto err;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ static const struct target {
+ const char *name;
+ int (*func)(v8::Handle<v8::Context>, int, char **);
+ } targets[] = {
+ { "shell", shell },
+ { "run", run },
+ { }
+ };
+ for (typeof(*targets) *t = targets; t->name; t++) {
+ if (!strcmp(argv[optind], t->name)) {
+ err = t->func(ctx, argc, argv);
+ goto err;
+ }
+ }
+ fprintf(stderr, "Unrecognised command '%s'\n", argv[optind]);
+ } else {
+ err = shell(ctx, 0, NULL);
+ }
+
+err:
+ ctx->Exit();
+ ctx.Dispose();
+ }
+
+ v8::V8::Dispose();
+ return err;
+}