• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 7119175127

06 Dec 2023 06:58PM UTC coverage: 88.591% (-0.03%) from 88.621%
7119175127

push

github

igormunkin
Fix HREFK forwarding vs. table.clear().

Reported by XmiliaH.

(cherry-picked from commit d5a237eae)

When performing HREFK (and also ALOAD, HLOAD) forwarding optimization,
the `table.clear()` function call may be performed on the table operand
from HREFK between table creation and IR, from which value is forwarded.
This call isn't taken in the account, so it may lead to too optimistic
value-forwarding from NEWREF (and also ASTORE, HSTORE), or the omitted
type guard for HREFK operation. Therefore, this leads to incorrect trace
behaviour (for example, taking a non-nil value from the cleared table).

This patch adds necessary checks for `table.clear()` calls.

Sergey Kaplun:
* added the description and the test for the problem

Part of tarantool/tarantool#9145

Reviewed-by: Maxim Kokryashkin <m.kokryashkin@tarantool.org>
Reviewed-by: Sergey Bronnikov <sergeyb@tarantool.org>
Signed-off-by: Igor Munkin <imun@tarantool.org>

5377 of 5987 branches covered (0.0%)

Branch coverage included in aggregate %.

12 of 12 new or added lines in 1 file covered. (100.0%)

24 existing lines in 5 files now uncovered.

20619 of 23357 relevant lines covered (88.28%)

2754697.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.96
/src/luajit.c
1
/*
2
** LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
**
5
** Major portions taken verbatim or adapted from the Lua interpreter.
6
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7
*/
8

9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12

13
#define luajit_c
14

15
#include "lua.h"
16
#include "lauxlib.h"
17
#include "lualib.h"
18
#include "luajit.h"
19

20
#include "lj_arch.h"
21

22
#if LJ_TARGET_POSIX
23
#include <unistd.h>
24
#define lua_stdin_is_tty()        isatty(0)
25
#elif LJ_TARGET_WINDOWS
26
#include <io.h>
27
#ifdef __BORLANDC__
28
#define lua_stdin_is_tty()        isatty(_fileno(stdin))
29
#else
30
#define lua_stdin_is_tty()        _isatty(_fileno(stdin))
31
#endif
32
#else
33
#define lua_stdin_is_tty()        1
34
#endif
35

36
#if !LJ_TARGET_CONSOLE
37
#include <signal.h>
38
#endif
39

40
static lua_State *globalL = NULL;
41
static const char *progname = LUA_PROGNAME;
42

43
#if !LJ_TARGET_CONSOLE
44
static void lstop(lua_State *L, lua_Debug *ar)
×
45
{
46
  (void)ar;  /* unused arg. */
×
47
  lua_sethook(L, NULL, 0, 0);
×
48
  /* Avoid luaL_error -- a C hook doesn't add an extra frame. */
49
  luaL_where(L, 0);
×
50
  lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1));
×
51
  lua_error(L);
×
52
}
×
53

54
static void laction(int i)
×
55
{
56
  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
×
57
                         terminate process (default action) */
58
  lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
×
59
}
×
60
#endif
61

62
static void print_usage(void)
5✔
63
{
64
  fputs("usage: ", stderr);
5✔
65
  fputs(progname, stderr);
5✔
66
  fputs(" [options]... [script [args]...].\n"
5✔
67
  "Available options are:\n"
68
  "  -e chunk  Execute string " LUA_QL("chunk") ".\n"
69
  "  -l name   Require library " LUA_QL("name") ".\n"
70
  "  -b ...    Save or list bytecode.\n"
71
  "  -j cmd    Perform LuaJIT control command.\n"
72
  "  -O[opt]   Control LuaJIT optimizations.\n"
73
  "  -i        Enter interactive mode after executing " LUA_QL("script") ".\n"
74
  "  -v        Show version information.\n"
75
  "  -t<cmd>   Execute tool.\n"
76
  "  -E        Ignore environment variables.\n"
77
  "  --        Stop handling options.\n"
78
  "  -         Execute stdin and stop handling options.\n", stderr);
79
  fflush(stderr);
5✔
80
}
5✔
81

82
static void print_tools_usage(void)
2✔
83
{
84
  fputs("usage: ", stderr);
2✔
85
  fputs(progname, stderr);
2✔
86
  fputs(" -t<cmd>\n"
2✔
87
  "Available tools are:\n"
88
  "  -m [--leak-only] input  Memprof profile data parser.\n"
89
  "  -s input                Sysprof profile data parser.\n", stderr);
90
  fflush(stderr);
2✔
91
}
2✔
92

93
static void l_message(const char *pname, const char *msg)
9✔
94
{
95
  if (pname) { fputs(pname, stderr); fputc(':', stderr); fputc(' ', stderr); }
9✔
96
  fputs(msg, stderr); fputc('\n', stderr);
9✔
97
  fflush(stderr);
9✔
98
}
9✔
99

100
static int report(lua_State *L, int status)
550✔
101
{
102
  if (status && !lua_isnil(L, -1)) {
550✔
103
    const char *msg = lua_tostring(L, -1);
8✔
104
    if (msg == NULL) msg = "(error object is not a string)";
8✔
105
    l_message(progname, msg);
8✔
106
    lua_pop(L, 1);
8✔
107
  }
108
  return status;
550✔
109
}
110

111
static int traceback(lua_State *L)
4✔
112
{
113
  if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */
4✔
114
    if (lua_isnoneornil(L, 1) ||
2✔
115
        !luaL_callmeta(L, 1, "__tostring") ||
1✔
UNCOV
116
        !lua_isstring(L, -1))
×
117
      return 1;  /* Return non-string error object. */
1✔
UNCOV
118
    lua_remove(L, 1);  /* Replace object by result of __tostring metamethod. */
×
119
  }
120
  luaL_traceback(L, L, lua_tostring(L, 1), 1);
3✔
121
  return 1;
3✔
122
}
123

124
static int docall(lua_State *L, int narg, int clear)
510✔
125
{
126
  int status;
510✔
127
  int base = lua_gettop(L) - narg;  /* function index */
510✔
128
  lua_pushcfunction(L, traceback);  /* push traceback function */
510✔
129
  lua_insert(L, base);  /* put it under chunk and args */
510✔
130
#if !LJ_TARGET_CONSOLE
131
  signal(SIGINT, laction);
510✔
132
#endif
133
  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
738✔
134
#if !LJ_TARGET_CONSOLE
135
  signal(SIGINT, SIG_DFL);
387✔
136
#endif
137
  lua_remove(L, base);  /* remove traceback function */
387✔
138
  /* force a complete garbage collection in case of errors */
139
  if (status != LUA_OK) lua_gc(L, LUA_GCCOLLECT, 0);
387✔
140
  return status;
387✔
141
}
142

143
static void print_version(void)
10✔
144
{
145
  fputs(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n", stdout);
10✔
146
}
10✔
147

148
static void print_jit_status(lua_State *L)
6✔
149
{
150
  int n;
6✔
151
  const char *s;
6✔
152
  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
6✔
153
  lua_getfield(L, -1, "jit");  /* Get jit.* module table. */
6✔
154
  lua_remove(L, -2);
6✔
155
  lua_getfield(L, -1, "status");
6✔
156
  lua_remove(L, -2);
6✔
157
  n = lua_gettop(L);
6✔
158
  lua_call(L, 0, LUA_MULTRET);
6✔
159
  fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stdout);
6✔
160
  for (n++; (s = lua_tostring(L, n)); n++) {
90✔
161
    putc(' ', stdout);
84✔
162
    fputs(s, stdout);
84✔
163
  }
164
  putc('\n', stdout);
6✔
165
}
6✔
166

167
static void createargtable(lua_State *L, char **argv, int argc, int argf)
262✔
168
{
169
  int i;
262✔
170
  lua_createtable(L, argc - argf, argf);
262✔
171
  for (i = 0; i < argc; i++) {
1,685✔
172
    lua_pushstring(L, argv[i]);
1,161✔
173
    lua_rawseti(L, -2, i - argf);
1,161✔
174
  }
175
  lua_setglobal(L, "arg");
262✔
176
}
262✔
177

178
static int dofile(lua_State *L, const char *name)
1✔
179
{
180
  int status = luaL_loadfile(L, name) || docall(L, 0, 1);
1✔
181
  return report(L, status);
1✔
182
}
183

184
static int dostring(lua_State *L, const char *s, const char *name)
226✔
185
{
186
  int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
226✔
187
  return report(L, status);
223✔
188
}
189

190
static int dolibrary(lua_State *L, const char *name)
57✔
191
{
192
  lua_getglobal(L, "require");
57✔
193
  lua_pushstring(L, name);
57✔
194
  return report(L, docall(L, 1, 1));
57✔
195
}
196

197
static void write_prompt(lua_State *L, int firstline)
135✔
198
{
199
  const char *p;
135✔
200
  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
244✔
201
  p = lua_tostring(L, -1);
135✔
202
  if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2;
135✔
203
  fputs(p, stdout);
135✔
204
  fflush(stdout);
135✔
205
  lua_pop(L, 1);  /* remove global */
135✔
206
}
135✔
207

208
static int incomplete(lua_State *L, int status)
129✔
209
{
210
  if (status == LUA_ERRSYNTAX) {
129✔
211
    size_t lmsg;
109✔
212
    const char *msg = lua_tolstring(L, -1, &lmsg);
109✔
213
    const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
109✔
214
    if (strstr(msg, LUA_QL("<eof>")) == tp) {
109✔
215
      lua_pop(L, 1);
109✔
216
      return 1;
109✔
217
    }
218
  }
219
  return 0;  /* else... */
220
}
221

222
static int pushline(lua_State *L, int firstline)
135✔
223
{
224
  char buf[LUA_MAXINPUT];
135✔
225
  write_prompt(L, firstline);
135✔
226
  if (fgets(buf, LUA_MAXINPUT, stdin)) {
135✔
227
    size_t len = strlen(buf);
129✔
228
    if (len > 0 && buf[len-1] == '\n')
129✔
229
      buf[len-1] = '\0';
127✔
230
    if (firstline && buf[0] == '=')
129✔
231
      lua_pushfstring(L, "return %s", buf+1);
5✔
232
    else
233
      lua_pushstring(L, buf);
124✔
234
    return 1;
129✔
235
  }
236
  return 0;
237
}
238

239
static int loadline(lua_State *L)
26✔
240
{
241
  int status;
26✔
242
  lua_settop(L, 0);
26✔
243
  if (!pushline(L, 1))
26✔
244
    return -1;  /* no input */
245
  for (;;) {  /* repeat until gets a complete line */
238✔
246
    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
129✔
247
    if (!incomplete(L, status)) break;  /* cannot try to add lines? */
129✔
248
    if (!pushline(L, 0))  /* no more input? */
109✔
249
      return -1;
250
    lua_pushliteral(L, "\n");  /* add a new line... */
109✔
251
    lua_insert(L, -2);  /* ...between the two lines */
109✔
252
    lua_concat(L, 3);  /* join them */
109✔
253
  }
254
  lua_remove(L, 1);  /* remove line */
20✔
255
  return status;
20✔
256
}
257

258
static void dotty(lua_State *L)
6✔
259
{
260
  int status;
6✔
261
  const char *oldprogname = progname;
6✔
262
  progname = NULL;
6✔
263
  while ((status = loadline(L)) != -1) {
32✔
264
    if (status == LUA_OK) status = docall(L, 0, 0);
20✔
265
    report(L, status);
20✔
266
    if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
20✔
267
      lua_getglobal(L, "print");
5✔
268
      lua_insert(L, 1);
5✔
269
      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
5✔
270
        l_message(progname,
×
271
          lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
272
                              lua_tostring(L, -1)));
273
    }
274
  }
275
  lua_settop(L, 0);  /* clear stack */
6✔
276
  fputs("\n", stdout);
6✔
277
  fflush(stdout);
6✔
278
  progname = oldprogname;
6✔
279
}
6✔
280

281
static int handle_script(lua_State *L, char **argx)
209✔
282
{
283
  int status;
209✔
284
  const char *fname = argx[0];
209✔
285
  if (strcmp(fname, "-") == 0 && strcmp(argx[-1], "--") != 0)
209✔
286
    fname = NULL;  /* stdin */
4✔
287
  status = luaL_loadfile(L, fname);
209✔
288
  if (status == LUA_OK) {
209✔
289
    /* Fetch args from arg table. LUA_INIT or -e might have changed them. */
290
    int narg = 0;
208✔
291
    lua_getglobal(L, "arg");
208✔
292
    if (lua_istable(L, -1)) {
208✔
293
      do {
267✔
294
        narg++;
267✔
295
        lua_rawgeti(L, -narg, narg);
267✔
296
      } while (!lua_isnil(L, -1));
267✔
297
      lua_pop(L, 1);
208✔
298
      lua_remove(L, -narg);
208✔
299
      narg--;
208✔
300
    } else {
301
      lua_pop(L, 1);
×
302
    }
303
    status = docall(L, narg, 0);
208✔
304
  }
305
  return report(L, status);
89✔
306
}
307

308
/* Load add-on module. */
309
static int loadjitmodule(lua_State *L)
10✔
310
{
311
  lua_getglobal(L, "require");
10✔
312
  lua_pushliteral(L, "jit.");
10✔
313
  lua_pushvalue(L, -3);
10✔
314
  lua_concat(L, 2);
10✔
315
  if (lua_pcall(L, 1, 1, 0)) {
10✔
316
    const char *msg = lua_tostring(L, -1);
1✔
317
    if (msg && !strncmp(msg, "module ", 7))
1✔
318
      goto nomodule;
1✔
319
    return report(L, 1);
×
320
  }
321
  lua_getfield(L, -1, "start");
9✔
322
  if (lua_isnil(L, -1)) {
9✔
323
  nomodule:
×
324
    l_message(progname,
1✔
325
              "unknown luaJIT command or jit.* modules not installed");
326
    return 1;
1✔
327
  }
328
  lua_remove(L, -2);  /* Drop module table. */
9✔
329
  return 0;
9✔
330
}
331

332
/* Run command with options. */
333
static int runcmdopt(lua_State *L, const char *opt)
10✔
334
{
335
  int narg = 0;
10✔
336
  if (opt && *opt) {
10✔
337
    for (;;) {  /* Split arguments. */
10✔
338
      const char *p = strchr(opt, ',');
8✔
339
      narg++;
8✔
340
      if (!p) break;
8✔
341
      if (p == opt)
2✔
342
        lua_pushnil(L);
×
343
      else
344
        lua_pushlstring(L, opt, (size_t)(p - opt));
2✔
345
      opt = p + 1;
2✔
346
    }
347
    if (*opt)
6✔
348
      lua_pushstring(L, opt);
6✔
349
    else
350
      lua_pushnil(L);
×
351
  }
352
  return report(L, lua_pcall(L, narg, 0, 0));
10✔
353
}
354

355
/* JIT engine control command: try jit library first or load add-on module. */
356
static int dojitcmd(lua_State *L, const char *cmd)
4✔
357
{
358
  const char *opt = strchr(cmd, '=');
4✔
359
  lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd));
4✔
360
  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
4✔
361
  lua_getfield(L, -1, "jit");  /* Get jit.* module table. */
4✔
362
  lua_remove(L, -2);
4✔
363
  lua_pushvalue(L, -2);
4✔
364
  lua_gettable(L, -2);  /* Lookup library function. */
4✔
365
  if (!lua_isfunction(L, -1)) {
4✔
366
    lua_pop(L, 2);  /* Drop non-function and jit.* table, keep module name. */
1✔
367
    if (loadjitmodule(L))
1✔
368
      return 1;
369
  } else {
370
    lua_remove(L, -2);  /* Drop jit.* table. */
3✔
371
  }
372
  lua_remove(L, -2);  /* Drop module name. */
3✔
373
  return runcmdopt(L, opt ? opt+1 : opt);
3✔
374
}
375

376
static int runtoolcmd(lua_State *L, const char *tool_name)
7✔
377
{
378
  lua_getglobal(L, "require");
7✔
379
  lua_pushstring(L, tool_name);
7✔
380
  if (lua_pcall(L, 1, 1, 0)) {
7✔
381
    const char *msg = lua_tostring(L, -1);
×
382
    if (msg) {
×
383
      if (!strncmp(msg, "module ", 7))
×
384
        msg = "unknown luaJIT command or tools not installed";
×
385
      l_message(progname, msg);
×
386
    }
387
    return 1;
×
388
  }
389
  lua_getglobal(L, "arg");
7✔
390
  return report(L, lua_pcall(L, 1, 1, 0));
7✔
391
}
392

393
static int dotoolcmd(lua_State *L, const char *cmd)
394
{
395
  switch (cmd[0]) {
396
  case 'm':
397
    return runtoolcmd(L, "memprof");
398
  case 's':
399
    return runtoolcmd(L, "sysprof");
400
  default:
401
    print_tools_usage();
402
    break;
403
  }
404
  return -1;
405
}
406

407
/* Optimization flags. */
408
static int dojitopt(lua_State *L, const char *opt)
7✔
409
{
410
  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
7✔
411
  lua_getfield(L, -1, "jit.opt");  /* Get jit.opt.* module table. */
7✔
412
  lua_remove(L, -2);
7✔
413
  lua_getfield(L, -1, "start");
7✔
414
  lua_remove(L, -2);
7✔
415
  return runcmdopt(L, opt);
7✔
416
}
417

418
/* Save or list bytecode. */
419
static int dobytecode(lua_State *L, char **argv)
9✔
420
{
421
  int narg = 0;
9✔
422
  lua_pushliteral(L, "bcsave");
9✔
423
  if (loadjitmodule(L))
9✔
424
    return 1;
425
  if (argv[0][2]) {
9✔
426
    narg++;
4✔
427
    argv[0][1] = '-';
4✔
428
    lua_pushstring(L, argv[0]+1);
4✔
429
  }
430
  for (argv++; *argv != NULL; narg++, argv++)
29✔
431
    lua_pushstring(L, *argv);
20✔
432
  report(L, lua_pcall(L, narg, 0, 0));
9✔
433
  return -1;
9✔
434
}
435

436
/* check that argument has no extra characters at the end */
437
#define notail(x)        {if ((x)[2] != '\0') return -1;}
438

439
#define FLAGS_INTERACTIVE        1
440
#define FLAGS_VERSION                2
441
#define FLAGS_EXEC                4
442
#define FLAGS_OPTION                8
443
#define FLAGS_NOENV                16
444
#define FLAGS_TOOL                32
445

446
static int collectargs(char **argv, int *flags)
267✔
447
{
448
  int i;
267✔
449
  for (i = 1; argv[i] != NULL; i++) {
572✔
450
    if (argv[i][0] != '-')  /* Not an option? */
540✔
451
      return i;
206✔
452
    switch (argv[i][1]) {  /* Check option. */
334✔
453
    case '-':
3✔
454
      notail(argv[i]);
3✔
455
      return i+1;
2✔
456
    case '\0':
457
      return i;
458
    case 'i':
6✔
459
      notail(argv[i]);
6✔
460
      *flags |= FLAGS_INTERACTIVE;
6✔
461
      /* fallthrough */
462
    case 'v':
10✔
463
      notail(argv[i]);
10✔
464
      *flags |= FLAGS_VERSION;
10✔
465
      break;
10✔
466
    case 't':
9✔
467
      *flags |= FLAGS_TOOL;
9✔
468
      return i + 1;
9✔
469
    case 'e':
228✔
470
      *flags |= FLAGS_EXEC;
228✔
471
      /* fallthrough */
472
    case 'j':  /* LuaJIT extension */
289✔
473
    case 'l':
474
      *flags |= FLAGS_OPTION;
289✔
475
      if (argv[i][2] == '\0') {
289✔
476
        i++;
274✔
477
        if (argv[i] == NULL) return -1;
274✔
478
      }
479
      break;
480
    case 'O': break;  /* LuaJIT extension */
481
    case 'b':  /* LuaJIT extension */
9✔
482
      if (*flags) return -1;
9✔
483
      *flags |= FLAGS_EXEC;
9✔
484
      return i+1;
9✔
485
    case 'E':
1✔
486
      *flags |= FLAGS_NOENV;
1✔
487
      break;
1✔
488
    default: return -1;  /* invalid option */
489
    }
490
  }
491
  return i;
492
}
493

494
static int runargs(lua_State *L, char **argv, int argn)
262✔
495
{
496
  int i;
262✔
497
  for (i = 1; i < argn; i++) {
560✔
498
    if (argv[i] == NULL) continue;
325✔
499
    lua_assert(argv[i][0] == '-');
325✔
500
    switch (argv[i][1]) {
325✔
501
    case 'e': {
226✔
502
      const char *chunk = argv[i] + 2;
226✔
503
      if (*chunk == '\0') chunk = argv[++i];
226✔
504
      lua_assert(chunk != NULL);
226✔
505
      if (dostring(L, chunk, "=(command line)") != 0)
226✔
506
        return 1;
507
      break;
508
      }
509
    case 'l': {
57✔
510
      const char *filename = argv[i] + 2;
57✔
511
      if (*filename == '\0') filename = argv[++i];
57✔
512
      lua_assert(filename != NULL);
57✔
513
      if (dolibrary(L, filename))
57✔
514
        return 1;
515
      break;
516
      }
517
    case 'j': {  /* LuaJIT extension. */
4✔
518
      const char *cmd = argv[i] + 2;
4✔
519
      if (*cmd == '\0') cmd = argv[++i];
4✔
520
      lua_assert(cmd != NULL);
4✔
521
      if (dojitcmd(L, cmd))
4✔
522
        return 1;
523
      break;
524
      }
525
    case 't': { /* Tarantool's fork extension. */
9✔
526
      const char *cmd = argv[i] + 2;
9✔
527
      return dotoolcmd(L, cmd) != LUA_OK;
9✔
528
    }
529
    case 'O':  /* LuaJIT extension. */
7✔
530
      if (dojitopt(L, argv[i] + 2))
7✔
531
        return 1;
532
      break;
533
    case 'b':  /* LuaJIT extension. */
9✔
534
      return dobytecode(L, argv+i);
9✔
535
    default: break;
536
    }
537
  }
538
  return LUA_OK;
539
}
540

541
static int handle_luainit(lua_State *L)
261✔
542
{
543
#if LJ_TARGET_CONSOLE
544
  const char *init = NULL;
545
#else
546
  const char *init = getenv(LUA_INIT);
261✔
547
#endif
548
  if (init == NULL)
261✔
549
    return LUA_OK;
550
  else if (init[0] == '@')
×
551
    return dofile(L, init+1);
×
552
  else
553
    return dostring(L, init, "=" LUA_INIT);
×
554
}
555

556
static struct Smain {
557
  char **argv;
558
  int argc;
559
  int status;
560
} smain;
561

562
static int pmain(lua_State *L)
267✔
563
{
564
  struct Smain *s = &smain;
267✔
565
  char **argv = s->argv;
267✔
566
  int argn;
267✔
567
  int flags = 0;
267✔
568
  globalL = L;
267✔
569
  if (argv[0] && argv[0][0]) progname = argv[0];
267✔
570

571
  LUAJIT_VERSION_SYM();  /* Linker-enforced version check. */
267✔
572

573
  argn = collectargs(argv, &flags);
267✔
574
  if (argn < 0) {  /* Invalid args? */
267✔
575
    print_usage();
5✔
576
    s->status = 1;
5✔
577
    return 0;
5✔
578
  }
579

580
  if ((flags & FLAGS_NOENV)) {
262✔
581
    lua_pushboolean(L, 1);
1✔
582
    lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
1✔
583
  }
584

585
  /* Stop collector during library initialization. */
586
  lua_gc(L, LUA_GCSTOP, 0);
262✔
587
  luaL_openlibs(L);
262✔
588
  lua_gc(L, LUA_GCRESTART, -1);
262✔
589

590
  createargtable(L, argv, s->argc, (flags & FLAGS_TOOL) ? argn - 1 : argn);
262✔
591

592
  if (!(flags & FLAGS_NOENV)) {
262✔
593
    s->status = handle_luainit(L);
261✔
594
    if (s->status != LUA_OK) return 0;
261✔
595
  }
596

597
  if ((flags & FLAGS_VERSION)) print_version();
262✔
598

599
  s->status = runargs(L, argv, argn);
262✔
600
  if (s->status != LUA_OK) return 0;
254✔
601

602
  if (s->argc > argn) {
235✔
603
    s->status = handle_script(L, argv + argn);
209✔
604
    if (s->status != LUA_OK) return 0;
89✔
605
  }
606

607
  if ((flags & FLAGS_INTERACTIVE)) {
114✔
608
    print_jit_status(L);
6✔
609
    dotty(L);
6✔
610
  } else if (s->argc == argn && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) {
108✔
611
    if (lua_stdin_is_tty()) {
1✔
612
      print_version();
×
613
      print_jit_status(L);
×
614
      dotty(L);
×
615
    } else {
616
      dofile(L, NULL);  /* Executes stdin as a file. */
1✔
617
    }
618
  }
619
  return 0;
620
}
621

622
int main(int argc, char **argv)
267✔
623
{
624
  int status;
267✔
625
  lua_State *L = lua_open();
267✔
626
  if (L == NULL) {
267✔
627
    l_message(argv[0], "cannot create state: not enough memory");
×
628
    return EXIT_FAILURE;
×
629
  }
630
  smain.argc = argc;
267✔
631
  smain.argv = argv;
267✔
632
  status = lua_cpcall(L, pmain, NULL);
267✔
633
  report(L, status);
139✔
634
  lua_close(L);
139✔
635
  return (status || smain.status > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
139✔
636
}
637

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc