shithub: lua9

Download patch

ref: 701a8f78c6f4371a9383fddcda5723c1cd791b92
author: telephil9 <telephil9@gmail.com>
date: Wed Oct 21 15:45:55 EDT 2020

Initial import

--- /dev/null
+++ b/README.md
@@ -1,0 +1,33 @@
+# About
+
+lua9 is a custom version of the [lua](http://lua.org) interpreter including bindings to plan9 libdraw.  
+This relies on the [lua 5.4 port](https://github.com/staalmannen/lua) for plan9 by @staalmannen.
+
+Disclaimer: This is work in progress and is sure to contain bugs.
+
+# Installation
+
+First, install the lua 5.4 port for plan9.  
+
+Clone the sources using the [git9](https://github.com/oridb/git9) client:
+```sh
+% git/clone git://github.com/telephil9/lua9
+```
+
+Install the lua9 interpreter:
+```sh
+% cd lua9
+% mk install
+```
+
+# Running
+
+```sh
+% ape/lua9 <script.lua>
+```
+
+**Note:** shebang scripts do not currently work.
+
+# Credits
+
+- Philippe (@telephil9)
--- /dev/null
+++ b/lua9.c
@@ -1,0 +1,394 @@
+#include <u.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#define IMAGE_META "Image"
+#define DISPLAY_META "Display"
+#define FONT_META "Font"
+
+typedef struct ImagePtr ImagePtr;
+typedef struct DisplayPtr DisplayPtr;
+typedef struct FontPtr FontPtr;
+
+struct ImagePtr {
+	Image *p;
+};
+
+struct DisplayPtr {
+	Display *p;
+};
+
+struct FontPtr {
+	Font *p;
+};
+
+static lua_State *state;
+static int ridx, tidx;
+
+void eresized(int new) {
+	if(new && getwindow(display, Refnone) < 0){
+		fprintf(stderr, "cannot reattach to window: %r");
+		exit(1);
+	}
+	lua_rawgeti(state, LUA_REGISTRYINDEX, ridx);
+	lua_rawgeti(state, -1, tidx);
+	lua_call(state, 0, 0);
+	lua_pop(state, 2);
+}
+
+static void create_globals(lua_State *L) {
+	ImagePtr *i;
+	DisplayPtr *d;
+	FontPtr *f;
+
+	i = (ImagePtr*)lua_newuserdatauv(L, sizeof(ImagePtr), 1);
+	luaL_getmetatable(L, IMAGE_META);
+	lua_setmetatable(L, -2);
+	i->p = screen;
+	lua_setglobal(L, "screen");
+	d = (DisplayPtr*)lua_newuserdata(L, sizeof(DisplayPtr));
+	luaL_getmetatable(L, DISPLAY_META);
+	lua_setmetatable(L, -2);
+	d->p = display;
+	lua_setglobal(L, "display");
+	f = (FontPtr*)lua_newuserdata(L, sizeof(FontPtr));
+	luaL_getmetatable(L, FONT_META);
+	lua_setmetatable(L, -2);
+	f->p = font;
+	lua_setglobal(L, "font");
+}
+
+static int l_initdraw(lua_State *L) {
+	const char *n;
+	char buf[256];
+	
+	n = luaL_checkstring(L, -1);
+	lua_newtable(L);
+	ridx = luaL_ref(L, LUA_REGISTRYINDEX);
+	lua_rawgeti(L, LUA_REGISTRYINDEX, ridx);
+	lua_getglobal(L, "eresized");
+	if(lua_isfunction(L, -1) == 0){
+		lua_pushstring(L, "eresized function not declared");
+		lua_error(L);
+	}
+	tidx = luaL_ref(L, -2);
+	lua_pop(L, 1);
+	if(initdraw(nil, nil, n) < 0){
+		snprintf(buf, sizeof buf, "initdraw failed: %r");
+		lua_pushstring(L, buf);
+		lua_error(L);
+	}
+	state = L;
+	create_globals(L);
+	return 0;
+}
+
+static int l_einit(lua_State *L) {
+	lua_Integer i;
+
+	i = luaL_checknumber(L, -1);
+	einit((ulong)i);
+	return 0;
+}
+
+static int l_event(lua_State *L) {
+	Event ev;
+	int e;
+
+	e = event(&ev);
+	lua_pushnumber(L, e);
+	lua_newtable(L);
+	lua_pushinteger(L, ev.kbdc);
+	lua_setfield(L, -2, "kbdc");
+	return 2;
+}
+
+static Point l_getpoint(lua_State *L, int index)
+{
+	Point p;
+
+	lua_pushstring(L, "x");
+	lua_gettable(L, index);
+	p.x = luaL_checkinteger(L, -1);
+	lua_pushstring(L, "y");
+	lua_gettable(L, index);
+	p.y = luaL_checkinteger(L, -1);
+	lua_pop(L, 2);
+	return p;
+}
+
+static Rectangle l_getrect(lua_State *L, int index)
+{
+	Rectangle r;
+	int t;
+
+	lua_pushstring(L, "min");
+	lua_gettable(L, index);
+	lua_pushstring(L, "x");
+	lua_gettable(L, -2);
+	r.min.x = luaL_checkinteger(L, -1);
+	lua_pushstring(L, "y");
+	t = lua_gettable(L, -3);
+	r.min.y = luaL_checkinteger(L, -1);
+	lua_pop(L, 3); /* table | x | y */
+	lua_pushstring(L, "max");
+	lua_gettable(L, index);
+	lua_pushstring(L, "x");
+	lua_gettable(L, -2);
+	r.max.x = luaL_checkinteger(L, -1);
+	lua_pushstring(L, "y");
+	lua_gettable(L, -3);
+	r.max.y = luaL_checkinteger(L, -1);
+	lua_pop(L, 3);
+	return r;
+}
+
+static int l_draw(lua_State *L) {
+	ImagePtr *p;
+	Image *dst, *src, *mask;
+	Point pt;
+	Rectangle r;
+	
+	p = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
+	luaL_argcheck(L, p != NULL, 1, "draw: Image expected");
+	dst = p->p;
+	if(lua_istable(L, 2) == 0) {
+		luaL_argerror(L, 2, "draw: table expected");
+	} else {
+		r = l_getrect(L, 2);
+	}
+	p = (ImagePtr*)luaL_checkudata(L, 3, IMAGE_META);
+	luaL_argcheck(L, p != NULL, 3, "draw: Image expected");
+	src = p->p;
+	mask = nil;
+	if(lua_isnil(L, 4) == 0) {
+		p = (ImagePtr*)luaL_checkudata(L, 4, IMAGE_META);
+		luaL_argcheck(L, p != NULL, 4, "draw: Image expected");
+		mask = p->p;
+	}
+	if(lua_istable(L, 5) == 0) {
+		luaL_argerror(L, 2, "draw: table expected");
+	} else {
+		pt = l_getpoint(L, 5);
+	}
+	draw(dst, r, src, mask, pt);
+	return 0;
+}
+
+static int l_string(lua_State *L) {
+	ImagePtr *p;
+	FontPtr *fp;
+	Image *dst, *src;
+	Font *f;
+	Point pt, spt;
+	const char *s;
+
+	p = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
+	luaL_argcheck(L, p != NULL, 1, "draw: Image expected");
+	dst = p->p;
+	if(lua_istable(L, 2)) {
+		pt = l_getpoint(L, 2);
+	} else {
+		luaL_argerror(L, 2, "draw: table expected");
+	}
+	p = (ImagePtr*)luaL_checkudata(L, 3, IMAGE_META);
+	luaL_argcheck(L, p != NULL, 3, "draw: Image expected");
+	src = p->p;
+	if(lua_istable(L, 4)) {
+		spt = l_getpoint(L, 4);
+	} else {
+		spt = ZP;
+	}
+	fp = (FontPtr*)luaL_checkudata(L, 5, FONT_META);
+	luaL_argcheck(L, fp != NULL, 5, "draw: Font expected");
+	f = fp->p;
+	s = luaL_checkstring(L, 6);
+	string(dst, pt, src, spt, f, s);
+	return 0;
+}
+
+/* Image metatable */
+static int l_image_gc(lua_State *L) {
+	ImagePtr *i;
+
+	i = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
+	luaL_argcheck(L, i != NULL, 1, "draw: Image expected");
+	if(i->p == screen) {
+		lua_pushboolean(L, 0);
+		return 1;
+	}
+	/* TODO freeimage */
+	lua_pushboolean(L, 1);
+	return 1;
+}
+
+static int l_image_tostring(lua_State *L) {
+	void *p;
+	char buf[64];
+
+	p = lua_touserdata(L, 1);
+	snprintf(buf, sizeof buf, "image: %p", p);
+	lua_pushstring(L, buf);
+	return 1;
+}
+
+static int l_image_index(lua_State *L) {
+	ImagePtr *i;
+	const char *s;
+	Rectangle r;
+
+	i = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
+	luaL_argcheck(L, i != NULL, 1, "draw: Image expected");
+	s = luaL_checkstring(L, 2);
+	if(!strncmp(s, "r", 1)) {
+		r = i->p->r;
+		lua_newtable(L);
+		lua_newtable(L);
+		lua_pushinteger(L, r.min.x);
+		lua_setfield(L, -2, "x");
+		lua_pushinteger(L, r.min.y);
+		lua_setfield(L, -2, "y");
+		lua_setfield(L, -2, "min");
+		lua_newtable(L);
+		lua_pushinteger(L, r.max.x);
+		lua_setfield(L, -2, "x");
+		lua_pushinteger(L, r.max.y);
+		lua_setfield(L, -2, "y");
+		lua_setfield(L, -2, "max");
+		return 1;
+	}
+	return 0;
+}
+
+static const struct luaL_Reg image_funcs[] = {
+	{ "__gc", l_image_gc },
+	{ "__tostring", l_image_tostring },
+	{ "__index", l_image_index },
+	{ NULL, NULL },
+};
+
+static int l_display_gc(lua_State *L) {
+	/* we do not GC the display */
+	lua_pushboolean(L, 0);
+	return 1;
+}
+
+static int l_display_tostring(lua_State *L) {
+	void *p;
+	char buf[64];
+
+	p = lua_touserdata(L, 1);
+	snprintf(buf, sizeof buf, "display: %p", p);
+	lua_pushstring(L, buf);
+	return 1;
+}
+
+static ImagePtr* to_image(lua_State *L, Image *img) {
+	ImagePtr *i;
+
+	i = (ImagePtr*)lua_newuserdata(L, sizeof(ImagePtr));
+	luaL_getmetatable(L, IMAGE_META);
+	lua_setmetatable(L, -2);
+	i->p = img;
+	return i;
+}
+
+static int l_display_index(lua_State *L) {
+	DisplayPtr *d;
+	const char *s;
+
+	d = (DisplayPtr*)luaL_checkudata(L, 1, DISPLAY_META);
+	luaL_argcheck(L, d != NULL, 1, "draw: Display expected");
+	s = luaL_checkstring(L, 2);
+	if(strncmp(s, "white", 5) == 0) {
+		to_image(L, d->p->white);
+		return 1;
+	} else if(strncmp(s, "black", 5) == 0) {
+		to_image(L, d->p->black);
+		return 1;
+	}
+	return 0;
+}
+
+static const struct luaL_Reg display_funcs[] = {
+	{ "__gc", l_display_gc },
+	{ "__tostring", l_display_tostring },
+	{ "__index", l_display_index },
+	{ NULL, NULL },
+};
+
+static int l_font_gc(lua_State *L) {
+	/* TODO */
+	lua_pushboolean(L, 0);
+	return 1;
+}
+
+static int l_font_tostring(lua_State *L) {
+	void *p;
+
+	p = lua_touserdata(L, 1);
+	lua_pushfstring(L, "font: %p", p);
+	return 1;
+}
+
+static const struct luaL_Reg font_funcs[] = {
+	{ "__gc", l_font_gc },
+	{ "__tostring", l_font_tostring },
+//	{ "__index", l_display_index },
+	{ NULL, NULL },
+};
+
+static void create_metatable(lua_State *L, const char *name, luaL_Reg *funcs) {
+	luaL_newmetatable(L, name);
+	luaL_setfuncs(L, funcs, 0);
+	lua_pushliteral (L, "__metatable");
+	lua_pushliteral (L, "draw: you're not allowed to get this metatable");
+	lua_settable (L, -3);
+}
+
+static const struct luaL_Reg drawlib [] = {
+	{ "initdraw", l_initdraw },
+	{ "einit",    l_einit },
+	{ "event",    l_event },
+	{ "draw",     l_draw },
+	{ "string",   l_string },
+	{ NULL, NULL }
+};
+
+int luaopen_drawlib (lua_State *L) {
+	create_metatable(L, IMAGE_META, image_funcs);
+	create_metatable(L, DISPLAY_META, display_funcs);
+	create_metatable(L, FONT_META, font_funcs);
+	luaL_newlib(L, drawlib);
+	lua_pushnumber(L, Emouse);
+	lua_setfield(L, -2, "Emouse");
+	lua_pushnumber(L, Ekeyboard);
+	lua_setfield(L, -2, "Ekeyboard");
+	return 1;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	lua_State *L;
+	char *f = NULL;
+	int r;
+
+	L = luaL_newstate();
+	luaL_openlibs(L);
+    	luaL_requiref(L, "draw", luaopen_drawlib, 1);
+    	lua_pop(L, 1);
+	if(argc > 1)
+		f = argv[1];
+	r = luaL_dofile(L, f);
+	lua_close(L);
+	return f == LUA_OK;
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,31 @@
+APE=/sys/src/ape
+<$APE/config
+
+TARG=lua9
+
+BIN=/$objtype/bin/ape
+
+OFILES=\
+    lua9.$O \
+    
+HFILES=\
+    /sys/include/ape/lauxlib.h \
+    /sys/include/ape/lua.h \
+    /sys/include/ape/luaconf.h \
+    /sys/include/ape/lualib.h
+
+</sys/src/cmd/mkone
+
+CC=pcc
+LD=pcc
+CFLAGS= -c -I. -D_C99_SNPRINTF_EXTENSION -D_PLAN9_SOURCE -D_POSIX_SOURCE \
+        -D_SUSV2_SOURCE -DLUA_POSIX -DENABLE_CJSON_GLOBAL \
+        -DPlan9 -DMAKE_LUA
+
+install:V:
+        cp $O.out /$objtype/bin/ape/$TARG
+        
+nuke:V:
+        rm -f /$objtype/bin/ape/$TARG
+        
+
--- /dev/null
+++ b/sample.lua
@@ -1,0 +1,32 @@
+#!/bin/ape/lua
+
+-- lua libdraw sample
+
+function rect(x0, y0, x1, y1)
+	r = { min={}, max={} }
+	r.min.x = x0
+	r.min.y = y0
+	r.max.x = x1
+	r.max.y = y1
+	return r
+end
+
+function eresized()
+	draw.draw(screen, screen.r, display.white, nil, {x=0, y=0})
+	draw.draw(screen, rect(50, 150, 100, 200), display.black, nil, {x=0, y=0})
+	draw.string(screen, {x=110, y=160}, display.black, nil, font, 'Hello LUA')
+end
+
+draw.initdraw('lua sample')
+draw.einit(draw.Emouse|draw.Ekeyboard)
+eresized()
+while true do
+	local e, ev = draw.event()
+	if e == draw.Emouse then
+		--print 'Mouse event'
+	elseif e == draw.Ekeyboard then
+		if string.char(ev.kbdc) == 'q' then
+			os.exit()
+		end
+	end
+end