shithub: libmujs

Download patch

ref: 1f137b8e48ba8345cc7a45494009b1cf69e6a47b
parent: e7314780c63546179a1f0a139b5ca706567b0bf1
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Jul 31 12:52:26 EDT 2014

Improve MuJS interactive shell.

Add read/readline/write/quit functions.
Add CommonJS style modules with require function.

--- a/jsstate.c
+++ b/jsstate.c
@@ -115,7 +115,8 @@
 	js_pushglobal(J);
 	js_call(J, 0);
 	if (report)
-		printf("%s\n", js_tostring(J, -1));
+		if (js_isdefined(J, -1))
+			printf("%s\n", js_tostring(J, -1));
 	js_pop(J, 1);
 	js_endtry(J);
 	return 0;
--- a/main.c
+++ b/main.c
@@ -1,4 +1,6 @@
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include "mujs.h"
 
@@ -30,6 +32,84 @@
 	js_pushundefined(J);
 }
 
+static void jsB_write(js_State *J)
+{
+	unsigned int i, top = js_gettop(J);
+	for (i = 1; i < top; ++i) {
+		const char *s = js_tostring(J, i);
+		if (i > 1) putchar(' ');
+		fputs(s, stdout);
+	}
+	js_pushundefined(J);
+}
+
+static void jsB_read(js_State *J)
+{
+	const char *filename = js_tostring(J, 1);
+	FILE *f;
+	char *s;
+	int n, t;
+
+	f = fopen(filename, "rb");
+	if (!f) {
+		js_error(J, "cannot open file: '%s'", filename);
+	}
+
+	if (fseek(f, 0, SEEK_END) < 0) {
+		fclose(f);
+		js_error(J, "cannot seek in file: '%s'", filename);
+	}
+	n = ftell(f);
+	fseek(f, 0, SEEK_SET);
+
+	s = malloc(n + 1);
+	if (!s) {
+		fclose(f);
+		js_error(J, "cannot allocate storage for file contents: '%s'", filename);
+	}
+
+	t = fread(s, 1, n, f);
+	if (t != n) {
+		free(s);
+		fclose(f);
+		js_error(J, "cannot read data from file: '%s'", filename);
+	}
+	s[n] = 0;
+
+	js_pushstring(J, s);
+	free(s);
+	fclose(f);
+}
+
+static void jsB_readline(js_State *J)
+{
+	char line[256];
+	int n;
+	if (!fgets(line, sizeof line, stdin))
+		js_error(J, "cannot read line from stdin");
+	n = strlen(line);
+	if (n > 0 && line[n-1] == '\n')
+		line[n-1] = 0;
+	js_pushstring(J, line);
+}
+
+static void jsB_quit(js_State *J)
+{
+	exit(js_tonumber(J, 1));
+}
+
+static const char *require_js =
+	"function require(name) {\n"
+	"var cache = require.cache;\n"
+	"if (name in cache) return cache[name];\n"
+	"var exports = {};\n"
+	"cache[name] = exports;\n"
+	"Function('exports', read(name+'.js'))(exports);\n"
+	"return exports;\n"
+	"}\n"
+	"require.cache = Object.create(null);\n"
+;
+
 int
 main(int argc, char **argv)
 {
@@ -47,6 +127,20 @@
 
 	js_newcfunction(J, jsB_print, 1);
 	js_setglobal(J, "print");
+
+	js_newcfunction(J, jsB_write, 0);
+	js_setglobal(J, "write");
+
+	js_newcfunction(J, jsB_read, 1);
+	js_setglobal(J, "read");
+
+	js_newcfunction(J, jsB_readline, 0);
+	js_setglobal(J, "readline");
+
+	js_newcfunction(J, jsB_quit, 1);
+	js_setglobal(J, "quit");
+
+	js_dostring(J, require_js, 0);
 
 	if (argc > 1) {
 		for (i = 1; i < argc; ++i) {