PageRenderTime 62ms CodeModel.GetById 30ms app.highlight 28ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/rel-1.3.35/Examples/lua/lua.c

#
C | 439 lines | 339 code | 77 blank | 23 comment | 75 complexity | 19617bbbee4ded669d6f2e6ed8b50346 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1/*
  2** $Id: lua.c 7470 2005-09-20 19:35:23Z wsfulton $
  3** Lua stand-alone interpreter
  4** See Copyright Notice in lua.h
  5*/
  6
  7
  8#include <signal.h>
  9#include <stdio.h>
 10#include <stdlib.h>
 11#include <string.h>
 12
 13#define lua_c
 14
 15#include "lua.h"
 16
 17#include "lauxlib.h"
 18#include "lualib.h"
 19
 20
 21/*
 22** generic extra include file
 23*/
 24#ifdef LUA_USERCONFIG
 25#include LUA_USERCONFIG
 26#endif
 27
 28
 29/*
 30** definition of `isatty'
 31*/
 32#ifdef _POSIX_C_SOURCE
 33#include <unistd.h>
 34#define stdin_is_tty()	isatty(0)
 35#else
 36#define stdin_is_tty()	1  /* assume stdin is a tty */
 37#endif
 38
 39
 40
 41#ifndef PROMPT
 42#define PROMPT		"> "
 43#endif
 44
 45
 46#ifndef PROMPT2
 47#define PROMPT2		">> "
 48#endif
 49
 50#ifndef PROGNAME
 51#define PROGNAME	"lua"
 52#endif
 53
 54#ifndef lua_userinit
 55#define lua_userinit(L)		openstdlibs(L)
 56#endif
 57
 58
 59#ifndef LUA_EXTRALIBS
 60#define LUA_EXTRALIBS	/* empty */
 61#endif
 62
 63
 64static lua_State *L = NULL;
 65
 66static const char *progname = PROGNAME;
 67
 68extern int Example_Init(lua_State* L);
 69
 70static const luaL_reg lualibs[] = {
 71  {"base", luaopen_base},
 72  {"table", luaopen_table},
 73  {"io", luaopen_io},
 74  {"string", luaopen_string},
 75  {"math", luaopen_math},
 76  {"debug", luaopen_debug},
 77  {"loadlib", luaopen_loadlib},
 78  /* add your libraries here */
 79  {"example", Example_Init},
 80  LUA_EXTRALIBS
 81  {NULL, NULL}
 82};
 83
 84
 85
 86static void lstop (lua_State *l, lua_Debug *ar) {
 87  (void)ar;  /* unused arg. */
 88  lua_sethook(l, NULL, 0, 0);
 89  luaL_error(l, "interrupted!");
 90}
 91
 92
 93static void laction (int i) {
 94  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
 95                              terminate process (default action) */
 96  lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
 97}
 98
 99
100static void print_usage (void) {
101  fprintf(stderr,
102  "usage: %s [options] [script [args]].\n"
103  "Available options are:\n"
104  "  -        execute stdin as a file\n"
105  "  -e stat  execute string `stat'\n"
106  "  -i       enter interactive mode after executing `script'\n"
107  "  -l name  load and run library `name'\n"
108  "  -v       show version information\n"
109  "  --       stop handling options\n" ,
110  progname);
111}
112
113
114static void l_message (const char *pname, const char *msg) {
115  if (pname) fprintf(stderr, "%s: ", pname);
116  fprintf(stderr, "%s\n", msg);
117}
118
119
120static int report (int status) {
121  const char *msg;
122  if (status) {
123    msg = lua_tostring(L, -1);
124    if (msg == NULL) msg = "(error with no message)";
125    l_message(progname, msg);
126    lua_pop(L, 1);
127  }
128  return status;
129}
130
131
132static int lcall (int narg, int clear) {
133  int status;
134  int base = lua_gettop(L) - narg;  /* function index */
135  lua_pushliteral(L, "_TRACEBACK");
136  lua_rawget(L, LUA_GLOBALSINDEX);  /* get traceback function */
137  lua_insert(L, base);  /* put it under chunk and args */
138  signal(SIGINT, laction);
139  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
140  signal(SIGINT, SIG_DFL);
141  lua_remove(L, base);  /* remove traceback function */
142  return status;
143}
144
145
146static void print_version (void) {
147  l_message(NULL, LUA_VERSION "  " LUA_COPYRIGHT);
148}
149
150
151static void getargs (char *argv[], int n) {
152  int i;
153  lua_newtable(L);
154  for (i=0; argv[i]; i++) {
155    lua_pushnumber(L, i - n);
156    lua_pushstring(L, argv[i]);
157    lua_rawset(L, -3);
158  }
159  /* arg.n = maximum index in table `arg' */
160  lua_pushliteral(L, "n");
161  lua_pushnumber(L, i-n-1);
162  lua_rawset(L, -3);
163}
164
165
166static int docall (int status) {
167  if (status == 0) status = lcall(0, 1);
168  return report(status);
169}
170
171
172static int file_input (const char *name) {
173  return docall(luaL_loadfile(L, name));
174}
175
176
177static int dostring (const char *s, const char *name) {
178  return docall(luaL_loadbuffer(L, s, strlen(s), name));
179}
180
181
182static int load_file (const char *name) {
183  lua_pushliteral(L, "require");
184  lua_rawget(L, LUA_GLOBALSINDEX);
185  if (!lua_isfunction(L, -1)) {  /* no `require' defined? */
186    lua_pop(L, 1);
187    return file_input(name);
188  }
189  else {
190    lua_pushstring(L, name);
191    return report(lcall(1, 1));
192  }
193}
194
195
196/*
197** this macro can be used by some `history' system to save lines
198** read in manual input
199*/
200#ifndef lua_saveline
201#define lua_saveline(L,line)	/* empty */
202#endif
203
204
205/*
206** this macro defines a function to show the prompt and reads the
207** next line for manual input
208*/
209#ifndef lua_readline
210#define lua_readline(L,prompt)		readline(L,prompt)
211
212/* maximum length of an input line */
213#ifndef MAXINPUT
214#define MAXINPUT	512
215#endif
216
217
218static int readline (lua_State *l, const char *prompt) {
219  static char buffer[MAXINPUT];
220  if (prompt) {
221    fputs(prompt, stdout);
222    fflush(stdout);
223  }
224  if (fgets(buffer, sizeof(buffer), stdin) == NULL)
225    return 0;  /* read fails */
226  else {
227    lua_pushstring(l, buffer);
228    return 1;
229  }
230}
231
232#endif
233
234
235static const char *get_prompt (int firstline) {
236  const char *p = NULL;
237  lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2");
238  lua_rawget(L, LUA_GLOBALSINDEX);
239  p = lua_tostring(L, -1);
240  if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
241  lua_pop(L, 1);  /* remove global */
242  return p;
243}
244
245
246static int incomplete (int status) {
247  if (status == LUA_ERRSYNTAX &&
248         strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
249    lua_pop(L, 1);
250    return 1;
251  }
252  else
253    return 0;
254}
255
256
257static int load_string (void) {
258  int status;
259  lua_settop(L, 0);
260  if (lua_readline(L, get_prompt(1)) == 0)  /* no input? */
261    return -1;
262  if (lua_tostring(L, -1)[0] == '=') {  /* line starts with `=' ? */
263    lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */
264    lua_remove(L, -2);  /* remove original line */
265  }
266  for (;;) {  /* repeat until gets a complete line */
267    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
268    if (!incomplete(status)) break;  /* cannot try to add lines? */
269    if (lua_readline(L, get_prompt(0)) == 0)  /* no more input? */
270      return -1;
271    lua_concat(L, lua_gettop(L));  /* join lines */
272  }
273  lua_saveline(L, lua_tostring(L, 1));
274  lua_remove(L, 1);  /* remove line */
275  return status;
276}
277
278
279static void manual_input (void) {
280  int status;
281  const char *oldprogname = progname;
282  progname = NULL;
283  while ((status = load_string()) != -1) {
284    if (status == 0) status = lcall(0, 0);
285    report(status);
286    if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */
287      lua_getglobal(L, "print");
288      lua_insert(L, 1);
289      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
290        l_message(progname, lua_pushfstring(L, "error calling `print' (%s)",
291                                               lua_tostring(L, -1)));
292    }
293  }
294  lua_settop(L, 0);  /* clear stack */
295  fputs("\n", stdout);
296  progname = oldprogname;
297}
298
299
300static int handle_argv (char *argv[], int *interactive) {
301  if (argv[1] == NULL) {  /* no more arguments? */
302    if (stdin_is_tty()) {
303      print_version();
304      manual_input();
305    }
306    else
307      file_input(NULL);  /* executes stdin as a file */
308  }
309  else {  /* other arguments; loop over them */
310    int i;
311    for (i = 1; argv[i] != NULL; i++) {
312      if (argv[i][0] != '-') break;  /* not an option? */
313      switch (argv[i][1]) {  /* option */
314        case '-': {  /* `--' */
315          if (argv[i][2] != '\0') {
316            print_usage();
317            return 1;
318          }
319          i++;  /* skip this argument */
320          goto endloop;  /* stop handling arguments */
321        }
322        case '\0': {
323          file_input(NULL);  /* executes stdin as a file */
324          break;
325        }
326        case 'i': {
327          *interactive = 1;
328          break;
329        }
330        case 'v': {
331          print_version();
332          break;
333        }
334        case 'e': {
335          const char *chunk = argv[i] + 2;
336          if (*chunk == '\0') chunk = argv[++i];
337          if (chunk == NULL) {
338            print_usage();
339            return 1;
340          }
341          if (dostring(chunk, "=<command line>") != 0)
342            return 1;
343          break;
344        }
345        case 'l': {
346          const char *filename = argv[i] + 2;
347          if (*filename == '\0') filename = argv[++i];
348          if (filename == NULL) {
349            print_usage();
350            return 1;
351          }
352          if (load_file(filename))
353            return 1;  /* stop if file fails */
354          break;
355        }
356        case 'c': {
357          l_message(progname, "option `-c' is deprecated");
358          break;
359        }
360        case 's': {
361          l_message(progname, "option `-s' is deprecated");
362          break;
363        }
364        default: {
365          print_usage();
366          return 1;
367        }
368      }
369    } endloop:
370    if (argv[i] != NULL) {
371      const char *filename = argv[i];
372      getargs(argv, i);  /* collect arguments */
373      lua_setglobal(L, "arg");
374      return file_input(filename);  /* stop scanning arguments */
375    }
376  }
377  return 0;
378}
379
380
381static void openstdlibs (lua_State *l) {
382  const luaL_reg *lib = lualibs;
383  for (; lib->func; lib++) {
384    lib->func(l);  /* open library */
385    lua_settop(l, 0);  /* discard any results */
386  }
387}
388
389
390static int handle_luainit (void) {
391  const char *init = getenv("LUA_INIT");
392  if (init == NULL) return 0;  /* status OK */
393  else if (init[0] == '@')
394    return file_input(init+1);
395  else
396    return dostring(init, "=LUA_INIT");
397}
398
399
400struct Smain {
401  int argc;
402  char **argv;
403  int status;
404};
405
406
407static int pmain (lua_State *l) {
408  struct Smain *s = (struct Smain *)lua_touserdata(l, 1);
409  int status;
410  int interactive = 0;
411  if (s->argv[0] && s->argv[0][0]) progname = s->argv[0];
412  L = l;
413  lua_userinit(l);  /* open libraries */
414  status = handle_luainit();
415  if (status == 0) {
416    status = handle_argv(s->argv, &interactive);
417    if (status == 0 && interactive) manual_input();
418  }
419  s->status = status;
420  return 0;
421}
422
423
424int main (int argc, char *argv[]) {
425  int status;
426  struct Smain s;
427  lua_State *l = lua_open();  /* create state */
428  if (l == NULL) {
429    l_message(argv[0], "cannot create state: not enough memory");
430    return EXIT_FAILURE;
431  }
432  s.argc = argc;
433  s.argv = argv;
434  status = lua_cpcall(l, &pmain, &s);
435  report(status);
436  lua_close(l);
437  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
438}
439