[mw-devel] [Git][arthur/mw][master] 4 commits: Implement load_jsfile() for duktape

Andrew Price welshbyte at sucs.org
Mon Jul 10 11:53:25 BST 2017


Andrew Price pushed to branch master at Justin Mitchell / mw


Commits:
046b2a2a by Andrew Price at 2017-07-09T20:46:42+01:00
Implement load_jsfile() for duktape

- - - - -
91c9c0c7 by Andrew Price at 2017-07-10T11:34:15+01:00
Implement js_bind() and js_exec() with duktape

- - - - -
7273bb23 by Andrew Price at 2017-07-10T11:36:02+01:00
duktape: define 'whoami'

- - - - -
e2de6c24 by Andrew Price at 2017-07-10T11:36:43+01:00
Build duktape with debugging symbols

- - - - -


4 changed files:

- duktape/Makefile
- src/client/js-duk.c
- src/client/js-moz.c
- src/client/js.h


Changes:

=====================================
duktape/Makefile
=====================================
--- a/duktape/Makefile
+++ b/duktape/Makefile
@@ -5,7 +5,7 @@ include $(DEPTH)Makefile.common
 build: duktape.o
 
 duktape.o: duktape.c duktape.h duk_config.h
-	$(CC) -std=c99 $(CCSEC) duktape.c -c
+	$(CC) -std=c99 -g $(CCSEC) duktape.c -c
 
 clean:
 	-rm -f *.o .*.d *.d


=====================================
src/client/js-duk.c
=====================================
--- a/src/client/js-duk.c
+++ b/src/client/js-duk.c
@@ -1,26 +1,174 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
 #include <duktape.h>
 
 #include "js.h"
+#include "alias.h"
+#include "user.h"
+
+extern struct user * const user;
+
+duk_context *ctx;
+
+struct binding {
+	int type;
+	int name_required;
+	alias **list;
+	const char *name;
+};
+
+const struct binding bindings[] = {
+	{ K_BIND, 1, &bind_list, "Bind" },
+	{ K_BIND_ALIAS, 1, &alias_list, "Alias" },
+	{ K_BIND_RPC, 1, &rpc_list, "RPC bind" },
+	{ K_BIND_EVENT, 0, &event_list, "Event bind" },
+	{ K_BIND_ONOFF, 0, &onoff_list, "Check on/off bind" },
+	{ K_BIND_IPC, 0, &ipc_list, "IPC bind" },
+	{ K_BIND_FORCE, 0, &force_list, "Force bind" },
+	{ K_BIND_SHUTDOWN, 0, &shutdown_list, "Shutdown bind" },
+	{ K_BIND_INPUT, 0, &eventin_list, "Input event bind" },
+	{ 0, 0, NULL, NULL }
+};
+
+static duk_ret_t js_bind(duk_context *cx)
+{
+	const char *bind_name = NULL;
+	const char *func_name = NULL;
+	const struct binding *bind;
+	int bind_type = -1;
+
+	if (duk_is_undefined(cx, -2) ||
+	    duk_is_undefined(cx, -3)) {
+		fprintf(stderr, "mwjs error: bind() expects 2 or 3 arguments\n");
+		return DUK_RET_SYNTAX_ERROR;
+	}
+	if (duk_is_string(cx, -3)) {
+		bind_name = duk_get_string(cx, -3);
+		bind_type = K_BIND;
+		if (!duk_is_undefined(cx, -1)) {
+			fprintf(stderr, "mwjs error: bind(str, str) expects 2 arguments\n");
+			return DUK_RET_SYNTAX_ERROR;
+		}
+		duk_pop(cx);
+	} else if (duk_is_number(cx, -3)) {
+		bind_type = duk_get_int_default(cx, -3, -1);
+		if (bind_type == K_BIND ||
+		    bind_type == K_BIND_ALIAS ||
+		    bind_type == K_BIND_RPC) {
+			bind_name = duk_get_string(cx, -2);
+		} else {
+			duk_pop(cx);
+		}
+	} else {
+		fprintf(stderr, "mwjs error: first argument to bind() must be a "
+		                "string or bind id\n");
+		return DUK_RET_SYNTAX_ERROR;
+	}
+
+	func_name = duk_get_string(cx, -1);
+	if (func_name == NULL) {
+		fprintf(stderr, "mwjs error: bind(): invalid function name\n");
+		return DUK_RET_SYNTAX_ERROR;
+	}
+
+	for (bind = &bindings[0]; bind->list != NULL && bind->type != bind_type; bind++);
+
+	if (bind->list == NULL) {
+		fprintf(stderr, "Bind type %d not recognised\n", bind_type);
+		return DUK_RET_ERROR;
+	}
+	if (bind->name_required) {
+		if (bind_name == NULL || bind_name[0] == '\0') {
+			fprintf(stderr, "Bind name is empty\n");
+			return DUK_RET_ERROR;
+		}
+	} else {
+		bind_name = func_name;
+		func_name = "";
+	}
+	if (AddLink(bind->list, bind_name, func_name)) {
+		fprintf(stderr, "Warning: %s %s already exists.\n",
+		        bind->name, bind_name);
+	}
+	return 0;
+}
 
 int js_isrunning(void)
 {
 	return 0;
 }
 
-int js_exec(char *name, int argc, const char **argvc)
+int js_exec(char *name, int argc, const char **argv)
 {
+	int i;
+
+	if (duk_get_global_string(ctx, name) && duk_is_function(ctx, -1)) {
+		for (i = 0; i < argc; i++)
+			duk_push_string(ctx, argv[i]);
+		if (duk_pcall(ctx, argc) != DUK_EXEC_SUCCESS) {
+			if (duk_is_error(ctx, -1)) {
+				duk_get_prop_string(ctx, -1, "stack");
+				fprintf(stderr, "mwjs error: %s\n", duk_safe_to_string(ctx, -1));
+				duk_pop(ctx);
+			} else {
+				fprintf(stderr, "mwjs error: %s\n", duk_safe_to_string(ctx, -1));
+			}
+		}
+	}
+	duk_pop(ctx);
 	return 0;
 }
 
+/* This limit is fairly arbitrary but a limit is needed and 256K
+   seems a reasonable file and (temporary) buffer size */
+#define MWJS_FILE_MAX_SIZE (256*1024)
+
 int load_jsfile(FILE *f, const char *filename)
 {
+	char buf[MWJS_FILE_MAX_SIZE + 1];
+	int fd = fileno(f);
+	struct stat st;
+	size_t ret;
+
+	if (fd == -1) {
+		fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno));
+		return 1;
+	}
+	if (fstat(fd, &st) != 0) {
+		fprintf(stderr, "Failed to stat '%s': %s\n", filename, strerror(errno));
+		return 1;
+	}
+	errno = EFBIG;
+	if (st.st_size > MWJS_FILE_MAX_SIZE) {
+		fprintf(stderr, "Failed to load '%s': %s\n", filename, strerror(errno));
+		return 1;
+	}
+	ret = fread(buf, sizeof(char), st.st_size, f);
+	if (ret != st.st_size) {
+		fprintf(stderr, "Failed to read '%s': %llu bytes read\n",
+		        filename, (unsigned long long)ret);
+		return 1;
+	}
+	buf[MWJS_FILE_MAX_SIZE] = '\0';
+	if (duk_peval_string(ctx, buf) != 0) {
+		printf("Failed to execute '%s': %s\n", filename, duk_safe_to_string(ctx, -1));
+	}
+	duk_pop(ctx);
 	return 0;
 }
 
 int is_js(char *name)
 {
-	return 0;
+	int ret = 0;
+
+	if (duk_get_global_string(ctx, name) && duk_is_function(ctx, -1))
+		ret = 1;
+
+	duk_pop(ctx);
+	return ret;
 }
 
 void js_stop_execution(void)
@@ -29,11 +177,59 @@ void js_stop_execution(void)
 
 int stop_js(void)
 {
+	duk_destroy_heap(ctx);
 	return 0;
 }
 
+/* The owning object must be at the top of the stack when calling this */
+static void define_func(const char *name, duk_c_function func, int nargs)
+{
+	duk_push_string(ctx, name);
+	duk_push_c_function(ctx, func, nargs);
+	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
+}
+
+/* The owning object must be at the top of the stack when calling this */
+static void define_number(const char *name, duk_double_t num)
+{
+	duk_push_string(ctx, name);
+	duk_push_number(ctx, num);
+	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
+}
+
+/* The owning object must be at the top of the stack when calling this */
+static void define_string(const char *name, const char *value)
+{
+	duk_push_string(ctx, name);
+	duk_push_string(ctx, value);
+	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE);
+}
+
+/* The owning object must be at the top of the stack when calling this */
+static void define_constants(void)
+{
+	define_number("K_BIND_EVENT", (duk_double_t)K_BIND_EVENT);
+	define_number("K_BIND_IPC", (duk_double_t)K_BIND_IPC);
+	define_number("K_BIND_ONOFF", (duk_double_t)K_BIND_ONOFF);
+	define_number("K_BIND_FORCE", (duk_double_t)K_BIND_FORCE);
+	define_number("K_BIND_SHUTDOWN", (duk_double_t)K_BIND_SHUTDOWN);
+	define_number("K_BIND_RPC", (duk_double_t)K_BIND_RPC);
+	define_number("K_BIND_ALIAS", (duk_double_t)K_BIND_ALIAS);
+	define_number("K_BIND_INPUT", (duk_double_t)K_BIND_INPUT);
+	define_number("K_BROADCAST", (duk_double_t)K_BROADCAST);
+	define_string("whoami", user->record.name);
+}
+
 int setup_js(void)
 {
+	ctx = duk_create_heap_default();
+	if (ctx == NULL)
+		return -1;
+
+	duk_push_global_object(ctx);
+	define_constants();
+	define_func("bind", js_bind, 3);
+	duk_pop(ctx);
 	return 0;
 }
 


=====================================
src/client/js-moz.c
=====================================
--- a/src/client/js-moz.c
+++ b/src/client/js-moz.c
@@ -48,9 +48,6 @@ static JSObject *jsroot = NULL;
 int js_interrupted=1;
 struct alarm *js_timeout_event=NULL;
 
-enum bindtype { K_BIND=0, K_BIND_EVENT, K_BIND_ONOFF, K_BIND_IPC, K_BIND_FORCE, K_BIND_SHUTDOWN, K_BIND_ALIAS, K_BIND_RPC, K_BIND_INPUT };
-#define K_BROADCAST 1
-
 JSClass globclass = {
 	"milliways", JSCLASS_GLOBAL_FLAGS,
 	JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_StrictPropertyStub,


=====================================
src/client/js.h
=====================================
--- a/src/client/js.h
+++ b/src/client/js.h
@@ -13,4 +13,17 @@ int setup_js(void);
 size_t urldata(void *ptr, size_t size, size_t nmemb, void *stream);
 size_t headlimit(void *ptr, size_t size, size_t nmemb, void *stream);
 
+enum bindtype {
+	K_BIND = 0,
+	K_BIND_EVENT,
+	K_BIND_ONOFF,
+	K_BIND_IPC,
+	K_BIND_FORCE,
+	K_BIND_SHUTDOWN,
+	K_BIND_ALIAS,
+	K_BIND_RPC,
+	K_BIND_INPUT
+};
+#define K_BROADCAST 1
+
 #endif /* JS_H */



View it on GitLab: https://projects.sucs.org/arthur/mw/compare/feb65f5be90bf3f51f64245cd2c0fd45f805ecc8...e2de6c248043c9120d92512c94a199294ae136e3

---
View it on GitLab: https://projects.sucs.org/arthur/mw/compare/feb65f5be90bf3f51f64245cd2c0fd45f805ecc8...e2de6c248043c9120d92512c94a199294ae136e3
You're receiving this email because of your account on projects.sucs.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sucs.org/pipermail/mw-devel/attachments/20170710/474a69a3/attachment-0001.html>


More information about the mw-devel mailing list