~ubuntu-branches/ubuntu/lucid/fceux/lucid

« back to all changes in this revision

Viewing changes to fceu/src/lua/src/lua.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2009-12-14 08:05:17 UTC
  • Revision ID: james.westby@ubuntu.com-20091214080517-abi5tj8avthfan7c
Tags: upstream-2.1.2+repack
ImportĀ upstreamĀ versionĀ 2.1.2+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
 
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
static lua_State *globalL = NULL;
 
23
 
 
24
static const char *progname = LUA_PROGNAME;
 
25
 
 
26
 
 
27
 
 
28
static void lstop (lua_State *L, lua_Debug *ar) {
 
29
  (void)ar;  /* unused arg. */
 
30
  lua_sethook(L, NULL, 0, 0);
 
31
  luaL_error(L, "interrupted!");
 
32
}
 
33
 
 
34
 
 
35
static void laction (int i) {
 
36
  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
 
37
                              terminate process (default action) */
 
38
  lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
 
39
}
 
40
 
 
41
 
 
42
static void print_usage (void) {
 
43
  fprintf(stderr,
 
44
  "usage: %s [options] [script [args]].\n"
 
45
  "Available options are:\n"
 
46
  "  -e stat  execute string " LUA_QL("stat") "\n"
 
47
  "  -l name  require library " LUA_QL("name") "\n"
 
48
  "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
 
49
  "  -v       show version information\n"
 
50
  "  --       stop handling options\n"
 
51
  "  -        execute stdin and stop handling options\n"
 
52
  ,
 
53
  progname);
 
54
  fflush(stderr);
 
55
}
 
56
 
 
57
 
 
58
static void l_message (const char *pname, const char *msg) {
 
59
  if (pname) fprintf(stderr, "%s: ", pname);
 
60
  fprintf(stderr, "%s\n", msg);
 
61
  fflush(stderr);
 
62
}
 
63
 
 
64
 
 
65
static int report (lua_State *L, int status) {
 
66
  if (status && !lua_isnil(L, -1)) {
 
67
    const char *msg = lua_tostring(L, -1);
 
68
    if (msg == NULL) msg = "(error object is not a string)";
 
69
    l_message(progname, msg);
 
70
    lua_pop(L, 1);
 
71
  }
 
72
  return status;
 
73
}
 
74
 
 
75
 
 
76
static int traceback (lua_State *L) {
 
77
  if (!lua_isstring(L, 1))  /* 'message' not a string? */
 
78
    return 1;  /* keep it intact */
 
79
  lua_getfield(L, LUA_GLOBALSINDEX, "debug");
 
80
  if (!lua_istable(L, -1)) {
 
81
    lua_pop(L, 1);
 
82
    return 1;
 
83
  }
 
84
  lua_getfield(L, -1, "traceback");
 
85
  if (!lua_isfunction(L, -1)) {
 
86
    lua_pop(L, 2);
 
87
    return 1;
 
88
  }
 
89
  lua_pushvalue(L, 1);  /* pass error message */
 
90
  lua_pushinteger(L, 2);  /* skip this function and traceback */
 
91
  lua_call(L, 2, 1);  /* call debug.traceback */
 
92
  return 1;
 
93
}
 
94
 
 
95
 
 
96
static int docall (lua_State *L, int narg, int clear) {
 
97
  int status;
 
98
  int base = lua_gettop(L) - narg;  /* function index */
 
99
  lua_pushcfunction(L, traceback);  /* push traceback function */
 
100
  lua_insert(L, base);  /* put it under chunk and args */
 
101
  signal(SIGINT, laction);
 
102
  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
 
103
  signal(SIGINT, SIG_DFL);
 
104
  lua_remove(L, base);  /* remove traceback function */
 
105
  /* force a complete garbage collection in case of errors */
 
106
  if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
 
107
  return status;
 
108
}
 
109
 
 
110
 
 
111
static void print_version (void) {
 
112
  l_message(NULL, LUA_RELEASE "  " LUA_COPYRIGHT);
 
113
}
 
114
 
 
115
 
 
116
static int getargs (lua_State *L, char **argv, int n) {
 
117
  int narg;
 
118
  int i;
 
119
  int argc = 0;
 
120
  while (argv[argc]) argc++;  /* count total number of arguments */
 
121
  narg = argc - (n + 1);  /* number of arguments to the script */
 
122
  luaL_checkstack(L, narg + 3, "too many arguments to script");
 
123
  for (i=n+1; i < argc; i++)
 
124
    lua_pushstring(L, argv[i]);
 
125
  lua_createtable(L, narg, n + 1);
 
126
  for (i=0; i < argc; i++) {
 
127
    lua_pushstring(L, argv[i]);
 
128
    lua_rawseti(L, -2, i - n);
 
129
  }
 
130
  return narg;
 
131
}
 
132
 
 
133
 
 
134
static int dofile (lua_State *L, const char *name) {
 
135
  int status = luaL_loadfile(L, name) || docall(L, 0, 1);
 
136
  return report(L, status);
 
137
}
 
138
 
 
139
 
 
140
static int dostring (lua_State *L, const char *s, const char *name) {
 
141
  int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
 
142
  return report(L, status);
 
143
}
 
144
 
 
145
 
 
146
static int dolibrary (lua_State *L, const char *name) {
 
147
  lua_getglobal(L, "require");
 
148
  lua_pushstring(L, name);
 
149
  return report(L, docall(L, 1, 1));
 
150
}
 
151
 
 
152
 
 
153
static const char *get_prompt (lua_State *L, int firstline) {
 
154
  const char *p;
 
155
  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
 
156
  p = lua_tostring(L, -1);
 
157
  if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
 
158
  lua_pop(L, 1);  /* remove global */
 
159
  return p;
 
160
}
 
161
 
 
162
 
 
163
static int incomplete (lua_State *L, int status) {
 
164
  if (status == LUA_ERRSYNTAX) {
 
165
    size_t lmsg;
 
166
    const char *msg = lua_tolstring(L, -1, &lmsg);
 
167
    const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
 
168
    if (strstr(msg, LUA_QL("<eof>")) == tp) {
 
169
      lua_pop(L, 1);
 
170
      return 1;
 
171
    }
 
172
  }
 
173
  return 0;  /* else... */
 
174
}
 
175
 
 
176
 
 
177
static int pushline (lua_State *L, int firstline) {
 
178
  char buffer[LUA_MAXINPUT];
 
179
  char *b = buffer;
 
180
  size_t l;
 
181
  const char *prmt = get_prompt(L, firstline);
 
182
  if (lua_readline(L, b, prmt) == 0)
 
183
    return 0;  /* no input */
 
184
  l = strlen(b);
 
185
  if (l > 0 && b[l-1] == '\n')  /* line ends with newline? */
 
186
    b[l-1] = '\0';  /* remove it */
 
187
  if (firstline && b[0] == '=')  /* first line starts with `=' ? */
 
188
    lua_pushfstring(L, "return %s", b+1);  /* change it to `return' */
 
189
  else
 
190
    lua_pushstring(L, b);
 
191
  lua_freeline(L, b);
 
192
  return 1;
 
193
}
 
194
 
 
195
 
 
196
static int loadline (lua_State *L) {
 
197
  int status;
 
198
  lua_settop(L, 0);
 
199
  if (!pushline(L, 1))
 
200
    return -1;  /* no input */
 
201
  for (;;) {  /* repeat until gets a complete line */
 
202
    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
 
203
    if (!incomplete(L, status)) break;  /* cannot try to add lines? */
 
204
    if (!pushline(L, 0))  /* no more input? */
 
205
      return -1;
 
206
    lua_pushliteral(L, "\n");  /* add a new line... */
 
207
    lua_insert(L, -2);  /* ...between the two lines */
 
208
    lua_concat(L, 3);  /* join them */
 
209
  }
 
210
  lua_saveline(L, 1);
 
211
  lua_remove(L, 1);  /* remove line */
 
212
  return status;
 
213
}
 
214
 
 
215
 
 
216
static void dotty (lua_State *L) {
 
217
  int status;
 
218
  const char *oldprogname = progname;
 
219
  progname = NULL;
 
220
  while ((status = loadline(L)) != -1) {
 
221
    if (status == 0) status = docall(L, 0, 0);
 
222
    report(L, status);
 
223
    if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */
 
224
      lua_getglobal(L, "print");
 
225
      lua_insert(L, 1);
 
226
      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
 
227
        l_message(progname, lua_pushfstring(L,
 
228
                               "error calling " LUA_QL("print") " (%s)",
 
229
                               lua_tostring(L, -1)));
 
230
    }
 
231
  }
 
232
  lua_settop(L, 0);  /* clear stack */
 
233
  fputs("\n", stdout);
 
234
  fflush(stdout);
 
235
  progname = oldprogname;
 
236
}
 
237
 
 
238
 
 
239
static int handle_script (lua_State *L, char **argv, int n) {
 
240
  int status;
 
241
  const char *fname;
 
242
  int narg = getargs(L, argv, n);  /* collect arguments */
 
243
  lua_setglobal(L, "arg");
 
244
  fname = argv[n];
 
245
  if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) 
 
246
    fname = NULL;  /* stdin */
 
247
  status = luaL_loadfile(L, fname);
 
248
  lua_insert(L, -(narg+1));
 
249
  if (status == 0)
 
250
    status = docall(L, narg, 0);
 
251
  else
 
252
    lua_pop(L, narg);      
 
253
  return report(L, status);
 
254
}
 
255
 
 
256
 
 
257
/* check that argument has no extra characters at the end */
 
258
#define notail(x)       {if ((x)[2] != '\0') return -1;}
 
259
 
 
260
 
 
261
static int collectargs (char **argv, int *pi, int *pv, int *pe) {
 
262
  int i;
 
263
  for (i = 1; argv[i] != NULL; i++) {
 
264
    if (argv[i][0] != '-')  /* not an option? */
 
265
        return i;
 
266
    switch (argv[i][1]) {  /* option */
 
267
      case '-':
 
268
        notail(argv[i]);
 
269
        return (argv[i+1] != NULL ? i+1 : 0);
 
270
      case '\0':
 
271
        return i;
 
272
      case 'i':
 
273
        notail(argv[i]);
 
274
        *pi = 1;  /* go through */
 
275
      case 'v':
 
276
        notail(argv[i]);
 
277
        *pv = 1;
 
278
        break;
 
279
      case 'e':
 
280
        *pe = 1;  /* go through */
 
281
      case 'l':
 
282
        if (argv[i][2] == '\0') {
 
283
          i++;
 
284
          if (argv[i] == NULL) return -1;
 
285
        }
 
286
        break;
 
287
      default: return -1;  /* invalid option */
 
288
    }
 
289
  }
 
290
  return 0;
 
291
}
 
292
 
 
293
 
 
294
static int runargs (lua_State *L, char **argv, int n) {
 
295
  int i;
 
296
  for (i = 1; i < n; i++) {
 
297
    if (argv[i] == NULL) continue;
 
298
    lua_assert(argv[i][0] == '-');
 
299
    switch (argv[i][1]) {  /* option */
 
300
      case 'e': {
 
301
        const char *chunk = argv[i] + 2;
 
302
        if (*chunk == '\0') chunk = argv[++i];
 
303
        lua_assert(chunk != NULL);
 
304
        if (dostring(L, chunk, "=(command line)") != 0)
 
305
          return 1;
 
306
        break;
 
307
      }
 
308
      case 'l': {
 
309
        const char *filename = argv[i] + 2;
 
310
        if (*filename == '\0') filename = argv[++i];
 
311
        lua_assert(filename != NULL);
 
312
        if (dolibrary(L, filename))
 
313
          return 1;  /* stop if file fails */
 
314
        break;
 
315
      }
 
316
      default: break;
 
317
    }
 
318
  }
 
319
  return 0;
 
320
}
 
321
 
 
322
 
 
323
static int handle_luainit (lua_State *L) {
 
324
  const char *init = getenv(LUA_INIT);
 
325
  if (init == NULL) return 0;  /* status OK */
 
326
  else if (init[0] == '@')
 
327
    return dofile(L, init+1);
 
328
  else
 
329
    return dostring(L, init, "=" LUA_INIT);
 
330
}
 
331
 
 
332
 
 
333
struct Smain {
 
334
  int argc;
 
335
  char **argv;
 
336
  int status;
 
337
};
 
338
 
 
339
 
 
340
static int pmain (lua_State *L) {
 
341
  struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
 
342
  char **argv = s->argv;
 
343
  int script;
 
344
  int has_i = 0, has_v = 0, has_e = 0;
 
345
  globalL = L;
 
346
  if (argv[0] && argv[0][0]) progname = argv[0];
 
347
  lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
 
348
  luaL_openlibs(L);  /* open libraries */
 
349
  lua_gc(L, LUA_GCRESTART, 0);
 
350
  s->status = handle_luainit(L);
 
351
  if (s->status != 0) return 0;
 
352
  script = collectargs(argv, &has_i, &has_v, &has_e);
 
353
  if (script < 0) {  /* invalid args? */
 
354
    print_usage();
 
355
    s->status = 1;
 
356
    return 0;
 
357
  }
 
358
  if (has_v) print_version();
 
359
  s->status = runargs(L, argv, (script > 0) ? script : s->argc);
 
360
  if (s->status != 0) return 0;
 
361
  if (script)
 
362
    s->status = handle_script(L, argv, script);
 
363
  if (s->status != 0) return 0;
 
364
  if (has_i)
 
365
    dotty(L);
 
366
  else if (script == 0 && !has_e && !has_v) {
 
367
    if (lua_stdin_is_tty()) {
 
368
      print_version();
 
369
      dotty(L);
 
370
    }
 
371
    else dofile(L, NULL);  /* executes stdin as a file */
 
372
  }
 
373
  return 0;
 
374
}
 
375
 
 
376
 
 
377
int main (int argc, char **argv) {
 
378
  int status;
 
379
  struct Smain s;
 
380
  lua_State *L = lua_open();  /* create state */
 
381
  if (L == NULL) {
 
382
    l_message(argv[0], "cannot create state: not enough memory");
 
383
    return EXIT_FAILURE;
 
384
  }
 
385
  s.argc = argc;
 
386
  s.argv = argv;
 
387
  status = lua_cpcall(L, &pmain, &s);
 
388
  report(L, status);
 
389
  lua_close(L);
 
390
  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
 
391
}
 
392