~ubuntu-branches/debian/sid/simpleitk/sid

« back to all changes in this revision

Viewing changes to Wrapping/Lua/SimpleITKLuaMain.cxx

  • Committer: Package Import Robot
  • Author(s): Ghislain Antony Vaillant
  • Date: 2017-11-02 08:49:18 UTC
  • Revision ID: package-import@ubuntu.com-20171102084918-7hs09ih668xq87ej
Tags: upstream-1.0.1
ImportĀ upstreamĀ versionĀ 1.0.1

Show diffs side-by-side

added added

removed removed

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