summaryrefslogtreecommitdiff
path: root/src/lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/Makefile4
-rw-r--r--src/lua/README50
-rw-r--r--src/lua/lua.c314
3 files changed, 252 insertions, 116 deletions
diff --git a/src/lua/Makefile b/src/lua/Makefile
index cf5d31b6..5b47161f 100644
--- a/src/lua/Makefile
+++ b/src/lua/Makefile
@@ -1,4 +1,4 @@
-# makefile for lua interpreter
+# makefile for Lua interpreter
LUA= ../..
@@ -14,7 +14,7 @@ T= $(BIN)/lua
all: $T
$T: $(OBJS) $(LIB)/liblua.a $(LIB)/liblualib.a
- $(CC) -o $@ $(OBJS) -L$(LIB) -llua -llualib -lm
+ $(CC) -o $@ $(OBJS) -L$(LIB) -llua -llualib $(EXTRA_LIBS)
$(LIB)/liblua.a:
cd ..; $(MAKE)
diff --git a/src/lua/README b/src/lua/README
index db2eafb7..832fb5bf 100644
--- a/src/lua/README
+++ b/src/lua/README
@@ -1,38 +1,40 @@
-This client is a sample lua interpreter.
+This is lua, a sample Lua interpreter.
It can be used as a batch interpreter and also interactively.
-
-Here are the options it understands:
-
+There are man pages for it in both nroff and html in ../../doc.
+
+Here are the options that it understands:
+ - execute stdin as a file
+ -c close Lua when exiting
+ -e stat execute string `stat'
+ -f name execute file `name' with remaining arguments in table `arg'
+ -i enter interactive mode with prompt
+ -q enter interactive mode without prompt
+ -sNUM set stack size to NUM (must be the first option)
-v print version information
- -d turn debug on
- -e stat dostring `stat'
- -q interactive mode without prompt
- -i interactive mode with prompt
- - executes stdin as a file
- a=b sets global `a' with string `b' (no need to quote b)
- name dofile `name'
+ a=b set global `a' to string `b'
+ name execute file `name'
If no options are given, then it reads lines from stdin and executes them
-as they are read. So, each line must contain a complete statement.
+as they are read -- so, each line must contain a complete statement.
To span a statement across several lines, end each line with a backslash '\'.
To change the prompt, set the global variable _PROMPT to whatever you want.
-You can do after calling the interpreter or on the command line with
- _PROMPT="lua: "
-for example.
+You can do this after calling the interpreter or on the command line with
+ lua _PROMPT="lua: " -i
+for example. Note that you need "-i" in this case.
You must be careful when using quotes on the command line because they are
usually handled by the shell.
This interpreter is good for using Lua as a standalone language.
-For a minimal interpreter, see etc/min.c.
+For a minimal interpreter, see ../../etc/min.c.
If your application simply exports new functions to Lua (which is common),
-then you can use this interpreter unmodified: just define a function
-
- void lua_userinit (void)
-
-in your code. In this function, you should do whatever initializations are
-need, typically exporting your functions to Lua.
-If you use this scheme, you must explicily open any standard libraries you need.
-See ../lib/linit.c
+then you can use this interpreter (almost) unmodified, as follows:
+First, define a function
+ void myinit (lua_State *L)
+in your own code. In this function, you should do whatever initializations
+are needed by your application, typically exporting your functions to Lua.
+Then, add a call "myinit(L)" in lua.c after the place marked
+ "add your libraries here"
+Of course, you can use any name instead of "myinit".
diff --git a/src/lua/lua.c b/src/lua/lua.c
index 5acd6173..2da857e1 100644
--- a/src/lua/lua.c
+++ b/src/lua/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.21 1999/07/02 18:22:38 roberto Exp $
+** $Id: lua.c,v 1.55 2000/10/20 16:36:32 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -11,24 +11,51 @@
#include <string.h>
#include "lua.h"
+
#include "luadebug.h"
#include "lualib.h"
+static lua_State *L = NULL;
+
+
+#ifndef PROMPT
+#define PROMPT "> "
+#endif
+
#ifdef _POSIX_SOURCE
#include <unistd.h>
#else
-#define isatty(x) (x==0) /* assume stdin is a tty */
+static int isatty (int x) { return x==0; } /* assume stdin is a tty */
#endif
+/*
+** global options
+*/
+struct Options {
+ int toclose;
+ int stacksize;
+};
+
+
typedef void (*handler)(int); /* type for signal actions */
static void laction (int i);
-static lua_LHFunction old_linehook = NULL;
-static lua_CHFunction old_callhook = NULL;
+static lua_Hook old_linehook = NULL;
+static lua_Hook old_callhook = NULL;
+
+
+static void userinit (void) {
+ lua_baselibopen(L);
+ lua_iolibopen(L);
+ lua_strlibopen(L);
+ lua_mathlibopen(L);
+ lua_dblibopen(L);
+ /* add your libraries here */
+}
static handler lreset (void) {
@@ -37,66 +64,125 @@ static handler lreset (void) {
static void lstop (void) {
- lua_setlinehook(old_linehook);
- lua_setcallhook(old_callhook);
+ lua_setlinehook(L, old_linehook);
+ lua_setcallhook(L, old_callhook);
lreset();
- lua_error("interrupted!");
+ lua_error(L, "interrupted!");
}
static void laction (int i) {
+ (void)i; /* to avoid warnings */
signal(SIGINT, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
- old_linehook = lua_setlinehook((lua_LHFunction)lstop);
- old_callhook = lua_setcallhook((lua_CHFunction)lstop);
+ old_linehook = lua_setlinehook(L, (lua_Hook)lstop);
+ old_callhook = lua_setcallhook(L, (lua_Hook)lstop);
}
-static int ldo (int (*f)(char *), char *name) {
+static int ldo (int (*f)(lua_State *l, const char *), const char *name) {
int res;
handler h = lreset();
- res = f(name); /* dostring | dofile */
+ int top = lua_gettop(L);
+ res = f(L, name); /* dostring | dofile */
+ lua_settop(L, top); /* remove eventual results */
signal(SIGINT, h); /* restore old action */
+ /* Lua gives no message in such cases, so lua.c provides one */
+ if (res == LUA_ERRMEM) {
+ fprintf(stderr, "lua: memory allocation error\n");
+ }
+ else if (res == LUA_ERRERR)
+ fprintf(stderr, "lua: error in error message\n");
return res;
}
static void print_message (void) {
fprintf(stderr,
-"Lua: command line options:\n"
-" -v print version information\n"
-" -d turn debug on\n"
-" -e stat dostring `stat'\n"
-" -q interactive mode without prompt\n"
-" -i interactive mode with prompt\n"
-" - executes stdin as a file\n"
-" a=b sets global `a' with string `b'\n"
-" name dofile `name'\n\n");
+ "usage: lua [options]. Available options are:\n"
+ " - execute stdin as a file\n"
+ " -c close Lua when exiting\n"
+ " -e stat execute string `stat'\n"
+ " -f name execute file `name' with remaining arguments in table `arg'\n"
+ " -i enter interactive mode with prompt\n"
+ " -q enter interactive mode without prompt\n"
+ " -sNUM set stack size to NUM (must be the first option)\n"
+ " -v print version information\n"
+ " a=b set global `a' to string `b'\n"
+ " name execute file `name'\n"
+);
+}
+
+
+static void print_version (void) {
+ printf("%.80s %.80s\n", LUA_VERSION, LUA_COPYRIGHT);
}
static void assign (char *arg) {
- if (strlen(arg) >= 500)
- fprintf(stderr, "lua: shell argument too long");
- else {
- char buffer[500];
- char *eq = strchr(arg, '=');
- lua_pushstring(eq+1);
- strncpy(buffer, arg, eq-arg);
- buffer[eq-arg] = 0;
- lua_setglobal(buffer);
+ char *eq = strchr(arg, '=');
+ *eq = '\0'; /* spilt `arg' in two strings (name & value) */
+ lua_pushstring(L, eq+1);
+ lua_setglobal(L, arg);
+}
+
+
+static void getargs (char *argv[]) {
+ int i;
+ lua_newtable(L);
+ for (i=0; argv[i]; i++) {
+ /* arg[i] = argv[i] */
+ lua_pushnumber(L, i);
+ lua_pushstring(L, argv[i]);
+ lua_settable(L, -3);
+ }
+ /* arg.n = maximum index in table `arg' */
+ lua_pushstring(L, "n");
+ lua_pushnumber(L, i-1);
+ lua_settable(L, -3);
+}
+
+
+static int l_getargs (lua_State *l) {
+ char **argv = (char **)lua_touserdata(l, -1);
+ getargs(argv);
+ return 1;
+}
+
+
+static int file_input (const char *argv) {
+ int result = ldo(lua_dofile, argv);
+ if (result) {
+ if (result == LUA_ERRFILE) {
+ fprintf(stderr, "lua: cannot execute file ");
+ perror(argv);
+ }
+ return EXIT_FAILURE;
}
+ else
+ return EXIT_SUCCESS;
}
-static void manual_input (int prompt) {
+/* maximum length of an input string */
+#ifndef MAXINPUT
+#define MAXINPUT BUFSIZ
+#endif
+
+static void manual_input (int version, int prompt) {
int cont = 1;
+ if (version) print_version();
while (cont) {
- char buffer[BUFSIZ];
+ char buffer[MAXINPUT];
int i = 0;
- lua_beginblock();
- if (prompt)
- printf("%s", lua_getstring(lua_getglobal("_PROMPT")));
+ if (prompt) {
+ const char *s;
+ lua_getglobal(L, "_PROMPT");
+ s = lua_tostring(L, -1);
+ if (!s) s = PROMPT;
+ fputs(s, stdout);
+ lua_pop(L, 1); /* remove global */
+ }
for(;;) {
int c = getchar();
if (c == EOF) {
@@ -108,81 +194,129 @@ static void manual_input (int prompt) {
buffer[i-1] = '\n';
else break;
}
- else if (i >= BUFSIZ-1) {
- fprintf(stderr, "lua: argument line too long\n");
+ else if (i >= MAXINPUT-1) {
+ fprintf(stderr, "lua: input line too long\n");
break;
}
else buffer[i++] = (char)c;
}
buffer[i] = '\0';
ldo(lua_dostring, buffer);
- lua_endblock();
+ lua_settop(L, 0); /* remove eventual results */
}
printf("\n");
}
-int main (int argc, char *argv[])
-{
- int i;
- lua_open();
- lua_pushstring("> "); lua_setglobal("_PROMPT");
- lua_userinit();
- if (argc < 2) { /* no arguments? */
+static int handle_argv (char *argv[], struct Options *opt) {
+ if (opt->stacksize > 0) argv++; /* skip option `-s' (if present) */
+ if (*argv == NULL) { /* no more arguments? */
if (isatty(0)) {
- printf("%s %s\n", LUA_VERSION, LUA_COPYRIGHT);
- manual_input(1);
+ manual_input(1, 1);
}
else
ldo(lua_dofile, NULL); /* executes stdin as a file */
}
- else for (i=1; i<argc; i++) {
- if (argv[i][0] == '-') { /* option? */
- switch (argv[i][1]) {
- case 0:
- ldo(lua_dofile, NULL); /* executes stdin as a file */
- break;
- case 'i':
- manual_input(1);
- break;
- case 'q':
- manual_input(0);
- break;
- case 'd':
- lua_setdebug(1);
- break;
- case 'v':
- printf("%s %s\n(written by %s)\n\n",
- LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS);
- break;
- case 'e':
- i++;
- if (ldo(lua_dostring, argv[i]) != 0) {
- fprintf(stderr, "lua: error running argument `%s'\n", argv[i]);
- return 1;
+ else { /* other arguments; loop over them */
+ int i;
+ for (i = 0; argv[i] != NULL; i++) {
+ if (argv[i][0] != '-') { /* not an option? */
+ if (strchr(argv[i], '='))
+ assign(argv[i]);
+ else
+ if (file_input(argv[i]) != EXIT_SUCCESS)
+ return EXIT_FAILURE; /* stop if file fails */
+ }
+ else switch (argv[i][1]) { /* option */
+ case 0: {
+ ldo(lua_dofile, NULL); /* executes stdin as a file */
+ break;
+ }
+ case 'i': {
+ manual_input(0, 1);
+ break;
+ }
+ case 'q': {
+ manual_input(0, 0);
+ break;
+ }
+ case 'c': {
+ opt->toclose = 1;
+ break;
+ }
+ case 'v': {
+ print_version();
+ break;
+ }
+ case 'e': {
+ i++;
+ if (argv[i] == NULL) {
+ print_message();
+ return EXIT_FAILURE;
+ }
+ if (ldo(lua_dostring, argv[i]) != 0) {
+ fprintf(stderr, "lua: error running argument `%.99s'\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'f': {
+ i++;
+ if (argv[i] == NULL) {
+ print_message();
+ return EXIT_FAILURE;
+ }
+ getargs(argv+i); /* collect remaining arguments */
+ lua_setglobal(L, "arg");
+ return file_input(argv[i]); /* stop scanning arguments */
+ }
+ case 's': {
+ fprintf(stderr, "lua: stack size (`-s') must be the first option\n");
+ return EXIT_FAILURE;
+ }
+ default: {
+ print_message();
+ return EXIT_FAILURE;
}
- break;
- default:
- print_message();
- exit(1);
- }
- }
- else if (strchr(argv[i], '='))
- assign(argv[i]);
- else {
- int result = ldo(lua_dofile, argv[i]);
- if (result) {
- if (result == 2) {
- fprintf(stderr, "lua: cannot execute file ");
- perror(argv[i]);
}
- exit(1);
- }
}
}
-#ifdef DEBUG
- lua_close();
-#endif
- return 0;
+ return EXIT_SUCCESS;
+}
+
+
+static void getstacksize (int argc, char *argv[], struct Options *opt) {
+ if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 's') {
+ int stacksize = atoi(&argv[1][2]);
+ if (stacksize <= 0) {
+ fprintf(stderr, "lua: invalid stack size ('%.20s')\n", &argv[1][2]);
+ exit(EXIT_FAILURE);
+ }
+ opt->stacksize = stacksize;
+ }
+ else
+ opt->stacksize = 0; /* no stack size */
+}
+
+
+static void register_getargs (char *argv[]) {
+ lua_pushuserdata(L, argv);
+ lua_pushcclosure(L, l_getargs, 1);
+ lua_setglobal(L, "getargs");
+}
+
+
+int main (int argc, char *argv[]) {
+ struct Options opt;
+ int status;
+ opt.toclose = 0;
+ getstacksize(argc, argv, &opt); /* handle option `-s' */
+ L = lua_open(opt.stacksize); /* create state */
+ userinit(); /* open libraries */
+ register_getargs(argv); /* create `getargs' function */
+ status = handle_argv(argv+1, &opt);
+ if (opt.toclose)
+ lua_close(L);
+ return status;
}