shithub: lua9

Download patch

ref: 553c8b384de1e6afd0463eecbf812a39a8071dcf
parent: 6acb1876c6aff7dc67dabc11c353bdda967a3504
author: telephil9 <telephil9@gmail.com>
date: Tue Oct 27 15:55:04 EDT 2020

Initial plumb module implementation

	New module to export libplumb functions. Currently implemented are: plumbopen,
	plumbsendtext, plumbrecv and eplumb.
	The eplumb() function is exported through the event module. For this to work,
	plumb.msg() allows for converting an Event.v value to a Plumbmsg pointer.

--- a/event.c
+++ b/event.c
@@ -5,6 +5,7 @@
 #include <draw.h>
 #include <event.h>
 #include <keyboard.h>
+#include <plumb.h>
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
@@ -60,6 +61,8 @@
 	lua_pushinteger(L, ev.mouse.msec);
 	lua_setfield(L, -2, "msec");
 	lua_setfield(L, -2, "mouse");
+	lua_pushlightuserdata(L, ev.v);
+	lua_setfield(L, -2, "v");
 	return 2;
 }
 
@@ -175,8 +178,22 @@
 	else
 		lua_pushnil(L);
 	return 1;
-}	
+}
 
+static int
+lplumb(lua_State *L)
+{
+	int key, ret;
+	char *port;
+
+	key  = luaL_checkinteger(L, 1);
+	port = luaL_checkstring(L, 2);
+	ret  = eplumb(key, port);
+	lua_pushinteger(L, ret);
+	return 1;
+}
+
+
 static const struct luaL_Reg libevent [] = {
 	{ "init",      leinit },
 	{ "event",     levent },
@@ -187,6 +204,7 @@
 	{ "menuhit",   lmenuhit },
 	{ "moveto",    lmoveto },
 	{ "enter",     lenter },
+	{ "plumb",     lplumb },
 	{ NULL, NULL }
 };
 
--- /dev/null
+++ b/lplumb.h
@@ -1,0 +1,14 @@
+#ifndef LPLUMB_H__
+#define LPLUMB_H__
+
+void registerplumbmsgmeta(lua_State *L);
+void pushplumbmsg(lua_State *L, Plumbmsg *m);
+Plumbmsg* checkplumbmsg(lua_State *L, int index);
+
+void registerplumbattrmeta(lua_State *L);
+void pushplumbattr(lua_State *L, Plumbattr *a);
+Plumbattr* checkplumbattr(lua_State *L, int index);
+
+int openlibplumb(lua_State *L);
+
+#endif
--- a/lua9.c
+++ b/lua9.c
@@ -5,10 +5,12 @@
 #include <draw.h>
 #include <event.h>
 #include <keyboard.h>
+#include <plumb.h>
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
 #include "ldraw.h"
+#include "lplumb.h"
 #include "utils.h"
 
 static const luaL_Reg libs[] = {
@@ -17,6 +19,7 @@
 	{ "g", openlibgeometry },
 	{ "key",  openlibkey },
 	{ "color", openlibcolor },
+	{ "plumb", openlibplumb },
 	{ NULL, NULL },
 };
 
--- a/mkfile
+++ b/mkfile
@@ -14,6 +14,9 @@
 	event.$O \
 	key.$O \
 	color.$O \
+	plumb.$O \
+	plumbmsg.$O \
+	plumbattr.$O \
 	utils.$O \
 	lua9.$O
 
--- /dev/null
+++ b/plumb.c
@@ -1,0 +1,98 @@
+#include <u.h>
+#include <lib9.h>
+#include <plumb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include "lplumb.h"
+#include "utils.h"
+
+static int
+lopen(lua_State *L)
+{
+	char *port;
+	int omode, fd;
+	char err[128];
+
+	port  = luaL_checkstring(L, 1);
+	omode = luaL_checkinteger(L, 2);
+	fd    = plumbopen(port, omode);
+	if(fd < 0){
+		errstr(err, sizeof err);
+		lua_pushfstring(L, "unable to open plumb port '%s': %s", port, err);
+		return lua_error(L);
+	}
+	lua_pushinteger(L, fd);
+	return 1;
+}
+
+static int
+lclose(lua_State *L)
+{
+	int fd;
+
+	fd = luaL_checkinteger(L, 1);
+	//close(fd);
+	return 0;
+}
+
+static int
+lsendtext(lua_State *L)
+{
+	char *src, *dst, *wdir, *data;
+	int fd, n;
+
+	fd   = luaL_checkinteger(L, 1);
+	src  = luaL_optstring(L, 2, NULL);
+	dst  = luaL_checkstring(L, 3);
+	wdir = luaL_optstring(L, 4, NULL);
+	data = luaL_checkstring(L, 5);
+	n    = plumbsendtext(fd, src, dst, wdir, data);
+	lua_pushinteger(L, n);
+	return 1;
+}	
+
+static int
+lrecv(lua_State *L)
+{
+	int fd;
+	Plumbmsg *m;
+
+	fd = luaL_checkinteger(L, 1);
+	m  = plumbrecv(fd);
+	pushplumbmsg(L, m);
+	return 1;
+}
+
+static int
+lmsg(lua_State *L)
+{
+	void *p;
+
+	if(lua_islightuserdata(L, 1)){
+		p = lua_touserdata(L, 1);
+		pushplumbmsg(L, (Plumbmsg*)p);
+	} else
+		lua_pushnil(L);
+	return 1;
+}
+
+static const struct luaL_Reg libplumb [] = {
+	{ "open", lopen },
+	{ "close", lclose },
+	{ "sendtext", lsendtext },
+	{ "recv", lrecv },
+	{ "msg", lmsg },
+	{ NULL, NULL }
+};
+
+int
+openlibplumb(lua_State *L)
+{
+	registerplumbmsgmeta(L);
+	registerplumbattrmeta(L);
+	luaL_newlib(L, libplumb);
+	return 1;
+}
--- /dev/null
+++ b/plumbattr.c
@@ -1,0 +1,88 @@
+#include <plumb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include "lplumb.h"
+#include "utils.h"
+
+#define PLUMBATTR "Plumbattr"
+
+typedef struct LPlumbattr LPlumbattr;
+
+struct LPlumbattr
+{
+	Plumbattr *a;
+};
+
+void
+pushplumbattr(lua_State *L, Plumbattr *a)
+{
+	LPlumbattr *l;
+
+	l = (LPlumbattr*)lua_newuserdata(L, sizeof(LPlumbattr));
+	luaL_getmetatable(L, PLUMBATTR);
+	lua_setmetatable(L, -2);
+	l->a = a;
+}
+
+Plumbattr*
+checkplumbattr(lua_State *L, int index)
+{
+	LPlumbattr *l;
+
+	l = (LPlumbattr*)luaL_checkudata(L, index, PLUMBATTR);
+	luaL_argcheck(L, l != NULL, index, "Plumbattr expected");
+	return l->a;
+}
+
+static int
+plumbattr__gc(lua_State *L)
+{
+	/* already freed by plumbmsg gc */
+	lua_pushboolean(L, 0);
+	return 1;
+}
+
+static int
+plumbattr__tostring(lua_State *L)
+{
+	void *p;
+
+	p = lua_touserdata(L, 1);
+	lua_pushfstring(L, "plumbattr: %p", p);
+	return 1;
+}
+
+static int
+plumbattr__index(lua_State *L)
+{
+	Plumbattr *a;
+	const char *s;
+
+	a = checkplumbattr(L, 1);
+	s = luaL_checkstring(L, 2);
+	if(strncmp(s, "name", 4) == 0)
+		lua_pushstring(L, a->name);
+	else if(strncmp(s, "value", 5) == 0)
+		lua_pushstring(L, a->value);
+	else if(strncmp(s, "next", 4) == 0)
+		pushplumbattr(L, a->next);
+	else
+		return 0;
+	return 1;
+}
+
+static const struct luaL_Reg plumbattr_funcs[] = {
+	{ "__gc", plumbattr__gc },
+	{ "__tostring", plumbattr__tostring },
+	{ "__index", plumbattr__index },
+	{ NULL, NULL },
+};
+
+void
+registerplumbattrmeta(lua_State *L)
+{
+	createmetatable(L, PLUMBATTR, plumbattr_funcs);
+}
--- /dev/null
+++ b/plumbmsg.c
@@ -1,0 +1,99 @@
+#include <plumb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include "lplumb.h"
+#include "utils.h"
+
+#define PLUMBMSG "Plumbmsg"
+
+typedef struct LPlumbmsg LPlumbmsg;
+
+struct LPlumbmsg
+{
+	Plumbmsg *m;
+};
+
+void
+pushplumbmsg(lua_State *L, Plumbmsg *m)
+{
+	LPlumbmsg *l;
+
+	l = (LPlumbmsg*)lua_newuserdata(L, sizeof(LPlumbmsg));
+	luaL_getmetatable(L, PLUMBMSG);
+	lua_setmetatable(L, -2);
+	l->m = m;
+}
+
+Plumbmsg*
+checkplumbmsg(lua_State *L, int index)
+{
+	LPlumbmsg *l;
+
+	l = (LPlumbmsg*)luaL_checkudata(L, index, PLUMBMSG);
+	luaL_argcheck(L, l != NULL, index, "Plumbmsg expected");
+	return l->m;
+}
+
+static int
+plumbmsg__gc(lua_State *L)
+{
+	LPlumbmsg *l;
+
+	l = (LPlumbmsg*)luaL_checkudata(L, 1, PLUMBMSG);
+	luaL_argcheck(L, l != NULL, 1, "Plumbmsg expected");
+	plumbfree(l->m);
+	free(l);
+	lua_pushboolean(L, 1);
+	return 1;
+}
+
+static int
+plumbmsg__tostring(lua_State *L)
+{
+	void *p;
+
+	p = lua_touserdata(L, 1);
+	lua_pushfstring(L, "plumbmsg: %p", p);
+	return 1;
+}
+
+static int
+plumbmsg__index(lua_State *L)
+{
+	Plumbmsg *m;
+	const char *s;
+
+	m = checkplumbmsg(L, 1);
+	s = luaL_checkstring(L, 2);
+	if(strncmp(s, "src", 3) == 0)
+		lua_pushstring(L, m->src);
+	else if(strncmp(s, "dst", 3) == 0)
+		lua_pushstring(L, m->dst);
+	else if(strncmp(s, "wdir", 4) == 0)
+		lua_pushstring(L, m->wdir);
+	else if(strncmp(s, "type", 4) == 0)
+		lua_pushstring(L, m->type);
+	else if(strncmp(s, "data", 4) == 0)
+		lua_pushstring(L, m->data);
+	else if(strncmp(s, "attr", 4) == 0)
+		pushplumbattr(L, m->attr);
+	else
+		return 0;
+	return 1;
+}
+
+static const struct luaL_Reg plumbmsg_funcs[] = {
+	{ "__gc", plumbmsg__gc },
+	{ "__tostring", plumbmsg__tostring },
+	{ "__index", plumbmsg__index },
+	{ NULL, NULL },
+};
+
+void
+registerplumbmsgmeta(lua_State *L)
+{
+	createmetatable(L, PLUMBMSG, plumbmsg_funcs);
+}