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

tarantool / luajit / 6147164734

11 Sep 2023 01:34PM UTC coverage: 88.218% (-0.006%) from 88.224%
6147164734

push

github

fckxorg
Fix frame for more types of on-trace error messages.

Thanks to Maxim Kokryashkin.

(cherry-picked from commit d5bbf9cdb)

This patch fixes the same issue with the frame as the previous
one, but now for the table overflow error in the `err_msgv`
function. The test for the problem uses the table of GC
finalizers, although they are not required to reproduce the
issue. They are only used to make the test as simple as possible.

Resolves tarantool/tarantool#562
Part of tarantool/tarantool#8825

5338 of 5971 branches covered (0.0%)

Branch coverage included in aggregate %.

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

20478 of 23293 relevant lines covered (87.91%)

2738020.45 hits per line

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

61.83
/src/lj_cparse.c
1
/*
2
** C declaration parser.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#include "lj_obj.h"
7

8
#if LJ_HASFFI
9

10
#include "lj_gc.h"
11
#include "lj_err.h"
12
#include "lj_buf.h"
13
#include "lj_ctype.h"
14
#include "lj_cparse.h"
15
#include "lj_frame.h"
16
#include "lj_vm.h"
17
#include "lj_char.h"
18
#include "lj_strscan.h"
19
#include "lj_strfmt.h"
20

21
/*
22
** Important note: this is NOT a validating C parser! This is a minimal
23
** C declaration parser, solely for use by the LuaJIT FFI.
24
**
25
** It ought to return correct results for properly formed C declarations,
26
** but it may accept some invalid declarations, too (and return nonsense).
27
** Also, it shows rather generic error messages to avoid unnecessary bloat.
28
** If in doubt, please check the input against your favorite C compiler.
29
*/
30

31
#ifdef LUA_USE_ASSERT
32
#define lj_assertCP(c, ...)        (lj_assertG_(G(cp->L), (c), __VA_ARGS__))
33
#else
34
#define lj_assertCP(c, ...)        ((void)cp)
35
#endif
36

37
/* -- Miscellaneous ------------------------------------------------------- */
38

39
/* Match string against a C literal. */
40
#define cp_str_is(str, k) \
41
  ((str)->len == sizeof(k)-1 && !memcmp(strdata(str), k, sizeof(k)-1))
42

43
/* Check string against a linear list of matches. */
44
int lj_cparse_case(GCstr *str, const char *match)
256✔
45
{
46
  MSize len;
256✔
47
  int n;
256✔
48
  for  (n = 0; (len = (MSize)*match++); n++, match += len) {
1,015✔
49
    if (str->len == len && !memcmp(match, strdata(str), len))
890✔
50
      return n;
131✔
51
  }
52
  return -1;
53
}
54

55
/* -- C lexer ------------------------------------------------------------- */
56

57
/* C lexer token names. */
58
static const char *const ctoknames[] = {
59
#define CTOKSTR(name, str)        str,
60
CTOKDEF(CTOKSTR)
61
#undef CTOKSTR
62
  NULL
63
};
64

65
/* Forward declaration. */
66
LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
67

68
static const char *cp_tok2str(CPState *cp, CPToken tok)
69
{
70
  lj_assertCP(tok < CTOK_FIRSTDECL, "bad CPToken %d", tok);
71
  if (tok > CTOK_OFS)
72
    return ctoknames[tok-CTOK_OFS-1];
73
  else if (!lj_char_iscntrl(tok))
74
    return lj_strfmt_pushf(cp->L, "%c", tok);
75
  else
76
    return lj_strfmt_pushf(cp->L, "char(%d)", tok);
77
}
78

79
/* End-of-line? */
80
static LJ_AINLINE int cp_iseol(CPChar c)
320✔
81
{
82
  return (c == '\n' || c == '\r');
320✔
83
}
84

85
/* Peek next raw character. */
86
static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
195✔
87
{
88
  return (CPChar)(uint8_t)(*cp->p);
195✔
89
}
90

91
static LJ_NOINLINE CPChar cp_get_bs(CPState *cp);
92

93
/* Get next character. */
94
static LJ_AINLINE CPChar cp_get(CPState *cp)
3,979,378✔
95
{
96
  cp->c = (CPChar)(uint8_t)(*cp->p++);
3,979,378✔
97
  if (LJ_LIKELY(cp->c != '\\')) return cp->c;
3,979,378✔
98
  return cp_get_bs(cp);
×
99
}
100

101
/* Transparently skip backslash-escaped line breaks. */
102
static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
×
103
{
104
  CPChar c2, c = cp_rawpeek(cp);
×
105
  if (!cp_iseol(c)) return cp->c;
×
106
  cp->p++;
×
107
  c2 = cp_rawpeek(cp);
×
108
  if (cp_iseol(c2) && c2 != c) cp->p++;
×
109
  cp->linenumber++;
×
110
  return cp_get(cp);
×
111
}
112

113
/* Save character in buffer. */
114
static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
3,534,503✔
115
{
116
  lj_buf_putb(&cp->sb, c);
7,069,006✔
117
}
×
118

119
/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
120
static void cp_newline(CPState *cp)
195✔
121
{
122
  CPChar c = cp_rawpeek(cp);
195✔
123
  if (cp_iseol(c) && c != cp->c) cp->p++;
13✔
124
  cp->linenumber++;
195✔
125
}
195✔
126

127
LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
×
128
{
129
  const char *msg, *tokstr;
×
130
  lua_State *L;
×
131
  va_list argp;
×
132
  if (tok == 0) {
×
133
    tokstr = NULL;
134
  } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
×
135
             tok >= CTOK_FIRSTDECL) {
×
136
    if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
×
137
    cp_save(cp, '\0');
×
138
    tokstr = sbufB(&cp->sb);
×
139
  } else {
140
    tokstr = cp_tok2str(cp, tok);
×
141
  }
142
  L = cp->L;
×
143
  va_start(argp, em);
×
144
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
×
145
  va_end(argp);
×
146
  if (tokstr)
×
147
    msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
×
148
  if (cp->linenumber > 1)
×
149
    msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber);
×
150
  lj_err_callermsg(L, msg);
×
151
}
152

153
LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
×
154
{
155
  cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
×
156
}
157

158
LJ_NORET LJ_NOINLINE static void cp_err_badidx(CPState *cp, CType *ct)
×
159
{
160
  GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
×
161
  cp_errmsg(cp, 0, LJ_ERR_FFI_BADIDX, strdata(s));
×
162
}
163

164
LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
×
165
{
166
  cp_errmsg(cp, 0, em);
×
167
}
168

169
/* -- Main lexical scanner ------------------------------------------------ */
170

171
/* Parse number literal. Only handles int32_t/uint32_t right now. */
172
static CPToken cp_number(CPState *cp)
100✔
173
{
174
  StrScanFmt fmt;
128✔
175
  TValue o;
128✔
176
  do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
128✔
177
  cp_save(cp, '\0');
100✔
178
  fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), sbuflen(&cp->sb)-1,
100✔
179
                        &o, STRSCAN_OPT_C);
180
  if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
100✔
181
  else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
×
182
  else if (!(cp->mode & CPARSE_MODE_SKIP))
×
183
    cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER);
×
184
  cp->val.u32 = (uint32_t)o.i;
100✔
185
  return CTOK_INTEGER;
100✔
186
}
187

188
/* Parse identifier or keyword. */
189
static CPToken cp_ident(CPState *cp)
442,381✔
190
{
191
  do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
3,975,939✔
192
  cp->str = lj_buf_str(cp->L, &cp->sb);
442,381✔
193
  cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
442,381✔
194
  if (ctype_type(cp->ct->info) == CT_KW)
442,381✔
195
    return ctype_cid(cp->ct->info);
1,102✔
196
  return CTOK_IDENT;
197
}
198

199
/* Parse parameter. */
200
static CPToken cp_param(CPState *cp)
2✔
201
{
202
  CPChar c = cp_get(cp);
2✔
203
  TValue *o = cp->param;
2✔
204
  if (lj_char_isident(c) || c == '$')  /* Reserve $xyz for future extensions. */
2✔
205
    cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
×
206
  if (!o || o >= cp->L->top)
2✔
207
    cp_err(cp, LJ_ERR_FFI_NUMPARAM);
×
208
  cp->param = o+1;
2✔
209
  if (tvisstr(o)) {
2✔
210
    cp->str = strV(o);
×
211
    cp->val.id = 0;
×
212
    cp->ct = &cp->cts->tab[0];
×
213
    return CTOK_IDENT;
×
214
  } else if (tvisnumber(o)) {
2✔
215
    cp->val.i32 = numberVint(o);
×
216
    cp->val.id = CTID_INT32;
×
217
    return CTOK_INTEGER;
×
218
  } else {
219
    GCcdata *cd;
2✔
220
    if (!tviscdata(o))
2✔
221
      lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
×
222
    cd = cdataV(o);
2✔
223
    if (cd->ctypeid == CTID_CTYPEID)
2✔
224
      cp->val.id = *(CTypeID *)cdataptr(cd);
2✔
225
    else
226
      cp->val.id = cd->ctypeid;
×
227
    return '$';
2✔
228
  }
229
}
230

231
/* Parse string or character constant. */
232
static CPToken cp_string(CPState *cp)
3✔
233
{
234
  CPChar delim = cp->c;
3✔
235
  cp_get(cp);
3✔
236
  while (cp->c != delim) {
20✔
237
    CPChar c = cp->c;
17✔
238
    if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
17✔
239
    if (c == '\\') {
17✔
240
      c = cp_get(cp);
×
241
      switch (c) {
×
242
      case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
×
243
      case 'a': c = '\a'; break;
244
      case 'b': c = '\b'; break;
×
245
      case 'f': c = '\f'; break;
×
246
      case 'n': c = '\n'; break;
×
247
      case 'r': c = '\r'; break;
×
248
      case 't': c = '\t'; break;
×
249
      case 'v': c = '\v'; break;
×
250
      case 'e': c = 27; break;
×
251
      case 'x':
252
        c = 0;
253
        while (lj_char_isxdigit(cp_get(cp)))
×
254
          c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
×
255
        cp_save(cp, (c & 0xff));
×
256
        continue;
×
257
      default:
×
258
        if (lj_char_isdigit(c)) {
×
259
          c -= '0';
×
260
          if (lj_char_isdigit(cp_get(cp))) {
×
261
            c = c*8 + (cp->c - '0');
×
262
            if (lj_char_isdigit(cp_get(cp))) {
×
263
              c = c*8 + (cp->c - '0');
×
264
              cp_get(cp);
×
265
            }
266
          }
267
          cp_save(cp, (c & 0xff));
×
268
          continue;
×
269
        }
270
        break;
271
      }
272
    }
17✔
273
    cp_save(cp, c);
17✔
274
    cp_get(cp);
37✔
275
  }
276
  cp_get(cp);
3✔
277
  if (delim == '"') {
3✔
278
    cp->str = lj_buf_str(cp->L, &cp->sb);
3✔
279
    return CTOK_STRING;
3✔
280
  } else {
281
    if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
×
282
    cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
×
283
    cp->val.id = CTID_INT32;
×
284
    return CTOK_INTEGER;
×
285
  }
286
}
287

288
/* Skip C comment. */
289
static void cp_comment_c(CPState *cp)
4✔
290
{
291
  do {
129✔
292
    if (cp_get(cp) == '*') {
129✔
293
      do {
4✔
294
        if (cp_get(cp) == '/') { cp_get(cp); return; }
4✔
295
      } while (cp->c == '*');
×
296
    }
297
    if (cp_iseol(cp->c)) cp_newline(cp);
125✔
298
  } while (cp->c != '\0');
125✔
299
}
300

301
/* Skip C++ comment. */
302
static void cp_comment_cpp(CPState *cp)
×
303
{
304
  while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
×
305
    ;
×
306
}
×
307

308
/* Lexical scanner for C. Only a minimal subset is implemented. */
309
static CPToken cp_next_(CPState *cp)
885,900✔
310
{
311
  lj_buf_reset(&cp->sb);
885,900✔
312
  for (;;) {
887,316✔
313
    if (lj_char_isident(cp->c))
887,316✔
314
      return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
442,481✔
315
    switch (cp->c) {
444,835✔
316
    case '\n': case '\r': cp_newline(cp);  /* fallthrough. */
195✔
317
    case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
888,728✔
318
    case '"': case '\'': return cp_string(cp);
3✔
319
    case '/':
320
      if (cp_get(cp) == '*') cp_comment_c(cp);
4✔
321
      else if (cp->c == '/') cp_comment_cpp(cp);
×
322
      else return '/';
323
      break;
324
    case '|':
325
      if (cp_get(cp) != '|') return '|';
×
326
      cp_get(cp); return CTOK_OROR;
×
327
    case '&':
328
      if (cp_get(cp) != '&') return '&';
×
329
      cp_get(cp); return CTOK_ANDAND;
×
330
    case '=':
331
      if (cp_get(cp) != '=') return '=';
1✔
332
      cp_get(cp); return CTOK_EQ;
×
333
    case '!':
334
      if (cp_get(cp) != '=') return '!';
×
335
      cp_get(cp); return CTOK_NE;
×
336
    case '<':
337
      if (cp_get(cp) == '=') { cp_get(cp); return CTOK_LE; }
×
338
      else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
×
339
      return '<';
340
    case '>':
341
      if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; }
×
342
      else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
×
343
      return '>';
344
    case '-':
345
      if (cp_get(cp) != '>') return '-';
1✔
346
      cp_get(cp); return CTOK_DEREF;
×
347
    case '$':
2✔
348
      return cp_param(cp);
2✔
349
    case '\0': return CTOK_EOF;
350
    default: { CPToken c = cp->c; cp_get(cp); return c; }
1,731✔
351
    }
352
  }
353
}
354

355
static LJ_NOINLINE CPToken cp_next(CPState *cp)
885,900✔
356
{
357
  return (cp->tok = cp_next_(cp));
885,900✔
358
}
359

360
/* -- C parser ------------------------------------------------------------ */
361

362
/* Namespaces for resolving identifiers. */
363
#define CPNS_DEFAULT \
364
  ((1u<<CT_KW)|(1u<<CT_TYPEDEF)|(1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
365
#define CPNS_STRUCT        ((1u<<CT_KW)|(1u<<CT_STRUCT)|(1u<<CT_ENUM))
366

367
typedef CTypeID CPDeclIdx;        /* Index into declaration stack. */
368
typedef uint32_t CPscl;                /* Storage class flags. */
369

370
/* Type declaration context. */
371
typedef struct CPDecl {
372
  CPDeclIdx top;        /* Top of declaration stack. */
373
  CPDeclIdx pos;        /* Insertion position in declaration chain. */
374
  CPDeclIdx specpos;        /* Saved position for declaration specifier. */
375
  uint32_t mode;        /* Declarator mode. */
376
  CPState *cp;                /* C parser state. */
377
  GCstr *name;                /* Name of declared identifier (if direct). */
378
  GCstr *redir;                /* Redirected symbol name. */
379
  CTypeID nameid;        /* Existing typedef for declared identifier. */
380
  CTInfo attr;                /* Attributes. */
381
  CTInfo fattr;                /* Function attributes. */
382
  CTInfo specattr;        /* Saved attributes. */
383
  CTInfo specfattr;        /* Saved function attributes. */
384
  CTSize bits;                /* Field size in bits (if any). */
385
  CType stack[CPARSE_MAX_DECLSTACK];  /* Type declaration stack. */
386
} CPDecl;
387

388
/* Forward declarations. */
389
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
390
static void cp_declarator(CPState *cp, CPDecl *decl);
391
static CTypeID cp_decl_abstract(CPState *cp);
392

393
/* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
394
static void cp_init(CPState *cp)
441,681✔
395
{
396
  cp->linenumber = 1;
441,681✔
397
  cp->depth = 0;
441,681✔
398
  cp->curpack = 0;
441,681✔
399
  cp->packstack[0] = 255;
441,681✔
400
  lj_buf_init(cp->L, &cp->sb);
441,681✔
401
  lj_assertCP(cp->p != NULL, "uninitialized cp->p");
441,681✔
402
  cp_get(cp);  /* Read-ahead first char. */
441,681✔
403
  cp->tok = 0;
441,681✔
404
  cp->tmask = CPNS_DEFAULT;
441,681✔
405
  cp_next(cp);  /* Read-ahead first token. */
441,681✔
406
}
441,681✔
407

408
/* Cleanup C parser state. */
409
static void cp_cleanup(CPState *cp)
441,681✔
410
{
411
  global_State *g = G(cp->L);
441,681✔
412
  lj_buf_free(g, &cp->sb);
441,681✔
413
}
441,681✔
414

415
/* Check and consume optional token. */
416
static int cp_opt(CPState *cp, CPToken tok)
2,654,254✔
417
{
418
  if (cp->tok == tok) { cp_next(cp); return 1; }
1,104✔
419
  return 0;
420
}
421

422
/* Check and consume token. */
423
static void cp_check(CPState *cp, CPToken tok)
569✔
424
{
425
  if (cp->tok != tok) cp_err_token(cp, tok);
569✔
426
  cp_next(cp);
569✔
427
}
569✔
428

429
/* Check if the next token may start a type declaration. */
430
static int cp_istypedecl(CPState *cp)
6✔
431
{
432
  if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
6✔
433
  if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
5✔
434
  if (cp->tok == '$') return 1;
5✔
435
  return 0;
436
}
437

438
/* -- Constant expression evaluator --------------------------------------- */
439

440
/* Forward declarations. */
441
static void cp_expr_unary(CPState *cp, CPValue *k);
442
static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
443

444
/* Please note that type handling is very weak here. Most ops simply
445
** assume integer operands. Accessors are only needed to compute types and
446
** return synthetic values. The only purpose of the expression evaluator
447
** is to compute the values of constant expressions one would typically
448
** find in C header files. And again: this is NOT a validating C parser!
449
*/
450

451
/* Parse comma separated expression and return last result. */
452
static void cp_expr_comma(CPState *cp, CPValue *k)
×
453
{
454
  do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
×
455
}
×
456

457
/* Parse sizeof/alignof operator. */
458
static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
×
459
{
460
  CTSize sz;
×
461
  CTInfo info;
×
462
  if (cp_opt(cp, '(')) {
×
463
    if (cp_istypedecl(cp))
×
464
      k->id = cp_decl_abstract(cp);
×
465
    else
466
      cp_expr_comma(cp, k);
×
467
    cp_check(cp, ')');
×
468
  } else {
469
    cp_expr_unary(cp, k);
×
470
  }
471
  info = lj_ctype_info(cp->cts, k->id, &sz);
×
472
  if (wantsz) {
×
473
    if (sz != CTSIZE_INVALID)
×
474
      k->u32 = sz;
×
475
    else if (k->id != CTID_A_CCHAR)  /* Special case for sizeof("string"). */
×
476
      cp_err(cp, LJ_ERR_FFI_INVSIZE);
×
477
  } else {
478
    k->u32 = 1u << ctype_align(info);
×
479
  }
480
  k->id = CTID_UINT32;  /* Really size_t. */
×
481
}
×
482

483
/* Parse prefix operators. */
484
static void cp_expr_prefix(CPState *cp, CPValue *k)
101✔
485
{
486
  if (cp->tok == CTOK_INTEGER) {
101✔
487
    *k = cp->val; cp_next(cp);
100✔
488
  } else if (cp_opt(cp, '+')) {
1✔
489
    cp_expr_unary(cp, k);  /* Nothing to do (well, integer promotion). */
×
490
  } else if (cp_opt(cp, '-')) {
1✔
491
    cp_expr_unary(cp, k); k->i32 = -k->i32;
1✔
492
  } else if (cp_opt(cp, '~')) {
×
493
    cp_expr_unary(cp, k); k->i32 = ~k->i32;
×
494
  } else if (cp_opt(cp, '!')) {
×
495
    cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
×
496
  } else if (cp_opt(cp, '(')) {
×
497
    if (cp_istypedecl(cp)) {  /* Cast operator. */
×
498
      CTypeID id = cp_decl_abstract(cp);
×
499
      cp_check(cp, ')');
×
500
      cp_expr_unary(cp, k);
×
501
      k->id = id;  /* No conversion performed. */
×
502
    } else {  /* Sub-expression. */
503
      cp_expr_comma(cp, k);
×
504
      cp_check(cp, ')');
×
505
    }
506
  } else if (cp_opt(cp, '*')) {  /* Indirection. */
×
507
    CType *ct;
×
508
    cp_expr_unary(cp, k);
×
509
    ct = lj_ctype_rawref(cp->cts, k->id);
×
510
    if (!ctype_ispointer(ct->info))
×
511
      cp_err_badidx(cp, ct);
×
512
    k->u32 = 0; k->id = ctype_cid(ct->info);
×
513
  } else if (cp_opt(cp, '&')) {  /* Address operator. */
×
514
    cp_expr_unary(cp, k);
×
515
    k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
×
516
                            CTSIZE_PTR);
517
  } else if (cp_opt(cp, CTOK_SIZEOF)) {
×
518
    cp_expr_sizeof(cp, k, 1);
×
519
  } else if (cp_opt(cp, CTOK_ALIGNOF)) {
×
520
    cp_expr_sizeof(cp, k, 0);
×
521
  } else if (cp->tok == CTOK_IDENT) {
×
522
    if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
×
523
      k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
×
524
    } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
×
525
      k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
×
526
    } else if (ctype_type(cp->ct->info) == CT_FUNC) {
×
527
      k->u32 = cp->val.id; k->id = cp->val.id;
×
528
    } else {
529
      goto err_expr;
×
530
    }
531
    cp_next(cp);
×
532
  } else if (cp->tok == CTOK_STRING) {
×
533
    CTSize sz = cp->str->len;
×
534
    while (cp_next(cp) == CTOK_STRING)
×
535
      sz += cp->str->len;
×
536
    k->u32 = sz + 1;
×
537
    k->id = CTID_A_CCHAR;
×
538
  } else {
539
  err_expr:
×
540
    cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
×
541
  }
542
}
101✔
543

544
/* Parse postfix operators. */
545
static void cp_expr_postfix(CPState *cp, CPValue *k)
546
{
547
  for (;;) {
548
    CType *ct;
549
    if (cp_opt(cp, '[')) {  /* Array/pointer index. */
550
      CPValue k2;
551
      cp_expr_comma(cp, &k2);
552
      ct = lj_ctype_rawref(cp->cts, k->id);
553
      if (!ctype_ispointer(ct->info)) {
554
        ct = lj_ctype_rawref(cp->cts, k2.id);
555
        if (!ctype_ispointer(ct->info))
556
          cp_err_badidx(cp, ct);
557
      }
558
      cp_check(cp, ']');
559
      k->u32 = 0;
560
    } else if (cp->tok == '.' || cp->tok == CTOK_DEREF) {  /* Struct deref. */
561
      CTSize ofs;
562
      CType *fct;
563
      ct = lj_ctype_rawref(cp->cts, k->id);
564
      if (cp->tok == CTOK_DEREF) {
565
        if (!ctype_ispointer(ct->info))
566
          cp_err_badidx(cp, ct);
567
        ct = lj_ctype_rawref(cp->cts, ctype_cid(ct->info));
568
      }
569
      cp_next(cp);
570
      if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
571
      if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
572
          !(fct = lj_ctype_getfield(cp->cts, ct, cp->str, &ofs)) ||
573
          ctype_isbitfield(fct->info)) {
574
        GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
575
        cp_errmsg(cp, 0, LJ_ERR_FFI_BADMEMBER, strdata(s), strdata(cp->str));
576
      }
577
      ct = fct;
578
      k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
579
      cp_next(cp);
580
    } else {
581
      return;
582
    }
583
    k->id = ctype_cid(ct->info);
584
  }
585
}
586

587
/* Parse infix operators. */
588
static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
589
{
590
  CPValue k2;
591
  k2.u32 = 0; k2.id = 0;  /* Silence the compiler. */
592
  for (;;) {
593
    switch (pri) {
594
    case 0:
595
      if (cp_opt(cp, '?')) {
596
        CPValue k3;
597
        cp_expr_comma(cp, &k2);  /* Right-associative. */
598
        cp_check(cp, ':');
599
        cp_expr_sub(cp, &k3, 0);
600
        k->u32 = k->u32 ? k2.u32 : k3.u32;
601
        k->id = k2.id > k3.id ? k2.id : k3.id;
602
        continue;
603
      }
604
      /* fallthrough */
605
    case 1:
606
      if (cp_opt(cp, CTOK_OROR)) {
607
        cp_expr_sub(cp, &k2, 2); k->i32 = k->u32 || k2.u32; k->id = CTID_INT32;
608
        continue;
609
      }
610
      /* fallthrough */
611
    case 2:
612
      if (cp_opt(cp, CTOK_ANDAND)) {
613
        cp_expr_sub(cp, &k2, 3); k->i32 = k->u32 && k2.u32; k->id = CTID_INT32;
614
        continue;
615
      }
616
      /* fallthrough */
617
    case 3:
618
      if (cp_opt(cp, '|')) {
619
        cp_expr_sub(cp, &k2, 4); k->u32 = k->u32 | k2.u32; goto arith_result;
620
      }
621
      /* fallthrough */
622
    case 4:
623
      if (cp_opt(cp, '^')) {
624
        cp_expr_sub(cp, &k2, 5); k->u32 = k->u32 ^ k2.u32; goto arith_result;
625
      }
626
      /* fallthrough */
627
    case 5:
628
      if (cp_opt(cp, '&')) {
629
        cp_expr_sub(cp, &k2, 6); k->u32 = k->u32 & k2.u32; goto arith_result;
630
      }
631
      /* fallthrough */
632
    case 6:
633
      if (cp_opt(cp, CTOK_EQ)) {
634
        cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 == k2.u32; k->id = CTID_INT32;
635
        continue;
636
      } else if (cp_opt(cp, CTOK_NE)) {
637
        cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 != k2.u32; k->id = CTID_INT32;
638
        continue;
639
      }
640
      /* fallthrough */
641
    case 7:
642
      if (cp_opt(cp, '<')) {
643
        cp_expr_sub(cp, &k2, 8);
644
        if (k->id == CTID_INT32 && k2.id == CTID_INT32)
645
          k->i32 = k->i32 < k2.i32;
646
        else
647
          k->i32 = k->u32 < k2.u32;
648
        k->id = CTID_INT32;
649
        continue;
650
      } else if (cp_opt(cp, '>')) {
651
        cp_expr_sub(cp, &k2, 8);
652
        if (k->id == CTID_INT32 && k2.id == CTID_INT32)
653
          k->i32 = k->i32 > k2.i32;
654
        else
655
          k->i32 = k->u32 > k2.u32;
656
        k->id = CTID_INT32;
657
        continue;
658
      } else if (cp_opt(cp, CTOK_LE)) {
659
        cp_expr_sub(cp, &k2, 8);
660
        if (k->id == CTID_INT32 && k2.id == CTID_INT32)
661
          k->i32 = k->i32 <= k2.i32;
662
        else
663
          k->i32 = k->u32 <= k2.u32;
664
        k->id = CTID_INT32;
665
        continue;
666
      } else if (cp_opt(cp, CTOK_GE)) {
667
        cp_expr_sub(cp, &k2, 8);
668
        if (k->id == CTID_INT32 && k2.id == CTID_INT32)
669
          k->i32 = k->i32 >= k2.i32;
670
        else
671
          k->i32 = k->u32 >= k2.u32;
672
        k->id = CTID_INT32;
673
        continue;
674
      }
675
      /* fallthrough */
676
    case 8:
677
      if (cp_opt(cp, CTOK_SHL)) {
678
        cp_expr_sub(cp, &k2, 9); k->u32 = k->u32 << k2.u32;
679
        continue;
680
      } else if (cp_opt(cp, CTOK_SHR)) {
681
        cp_expr_sub(cp, &k2, 9);
682
        if (k->id == CTID_INT32)
683
          k->i32 = k->i32 >> k2.i32;
684
        else
685
          k->u32 = k->u32 >> k2.u32;
686
        continue;
687
      }
688
      /* fallthrough */
689
    case 9:
690
      if (cp_opt(cp, '+')) {
691
        cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 + k2.u32;
692
      arith_result:
693
        if (k2.id > k->id) k->id = k2.id;  /* Trivial promotion to unsigned. */
694
        continue;
695
      } else if (cp_opt(cp, '-')) {
696
        cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 - k2.u32; goto arith_result;
697
      }
698
      /* fallthrough */
699
    case 10:
700
      if (cp_opt(cp, '*')) {
701
        cp_expr_unary(cp, &k2); k->u32 = k->u32 * k2.u32; goto arith_result;
702
      } else if (cp_opt(cp, '/')) {
703
        cp_expr_unary(cp, &k2);
704
        if (k2.id > k->id) k->id = k2.id;  /* Trivial promotion to unsigned. */
705
        if (k2.u32 == 0 ||
706
            (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
707
          cp_err(cp, LJ_ERR_BADVAL);
708
        if (k->id == CTID_INT32)
709
          k->i32 = k->i32 / k2.i32;
710
        else
711
          k->u32 = k->u32 / k2.u32;
712
        continue;
713
      } else if (cp_opt(cp, '%')) {
714
        cp_expr_unary(cp, &k2);
715
        if (k2.id > k->id) k->id = k2.id;  /* Trivial promotion to unsigned. */
716
        if (k2.u32 == 0 ||
717
            (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
718
          cp_err(cp, LJ_ERR_BADVAL);
719
        if (k->id == CTID_INT32)
720
          k->i32 = k->i32 % k2.i32;
721
        else
722
          k->u32 = k->u32 % k2.u32;
723
        continue;
724
      }
725
    default:
726
      return;
727
    }
728
  }
729
}
730

731
/* Parse and evaluate unary expression. */
732
static void cp_expr_unary(CPState *cp, CPValue *k)
101✔
733
{
734
  if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
101✔
735
  cp_expr_prefix(cp, k);
101✔
736
  cp_expr_postfix(cp, k);
101✔
737
  cp->depth--;
101✔
738
}
101✔
739

740
/* Parse and evaluate sub-expression. */
741
static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
100✔
742
{
743
  cp_expr_unary(cp, k);
×
744
  cp_expr_infix(cp, k, pri);
100✔
745
}
746

747
/* Parse constant integer expression. */
748
static void cp_expr_kint(CPState *cp, CPValue *k)
100✔
749
{
750
  CType *ct;
100✔
751
  cp_expr_sub(cp, k, 0);
100✔
752
  ct = ctype_raw(cp->cts, k->id);
100✔
753
  if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
100✔
754
}
100✔
755

756
/* Parse (non-negative) size expression. */
757
static CTSize cp_expr_ksize(CPState *cp)
99✔
758
{
759
  CPValue k;
99✔
760
  cp_expr_kint(cp, &k);
99✔
761
  if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
99✔
762
  return k.u32;
99✔
763
}
764

765
/* -- Type declaration stack management ----------------------------------- */
766

767
/* Add declaration element behind the insertion position. */
768
static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
442,731✔
769
{
770
  CPDeclIdx top = decl->top;
442,731✔
771
  if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
272✔
772
  decl->stack[top].info = info;
442,731✔
773
  decl->stack[top].size = size;
442,731✔
774
  decl->stack[top].sib = 0;
442,731✔
775
  setgcrefnull(decl->stack[top].name);
442,731✔
776
  decl->stack[top].next = decl->stack[decl->pos].next;
442,731✔
777
  decl->stack[decl->pos].next = (CTypeID1)top;
442,731✔
778
  decl->top = top+1;
442,731✔
779
  return top;
442,731✔
780
}
781

782
/* Push declaration element before the insertion position. */
783
static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
442,427✔
784
{
785
  return (decl->pos = cp_add(decl, info, size));
442,427✔
786
}
787

788
/* Push or merge attributes. */
789
static void cp_push_attributes(CPDecl *decl)
442,048✔
790
{
791
  CType *ct = &decl->stack[decl->pos];
442,048✔
792
  if (ctype_isfunc(ct->info)) {  /* Ok to modify in-place. */
442,048✔
793
#if LJ_TARGET_X86
794
    if ((decl->fattr & CTFP_CCONV))
795
      ct->info = (ct->info & (CTMASK_NUM|CTF_VARARG|CTMASK_CID)) +
796
                 (decl->fattr & ~CTMASK_CID);
797
#endif
798
  } else {
799
    if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
442,048✔
800
      cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
×
801
              ctype_align(decl->attr));
×
802
  }
803
}
442,048✔
804

805
/* Push unrolled type to declaration stack and merge qualifiers. */
806
static void cp_push_type(CPDecl *decl, CTypeID id)
441,028✔
807
{
808
  CType *ct = ctype_get(decl->cp->cts, id);
441,028✔
809
  CTInfo info = ct->info;
441,028✔
810
  CTSize size = ct->size;
441,028✔
811
  switch (ctype_type(info)) {
441,028✔
812
  case CT_STRUCT: case CT_ENUM:
250✔
813
    cp_push(decl, CTINFO(CT_TYPEDEF, id), 0);  /* Don't copy unique types. */
250✔
814
    if ((decl->attr & CTF_QUAL)) {  /* Push unmerged qualifiers. */
250✔
815
      cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
1✔
816
              (decl->attr & CTF_QUAL));
817
      decl->attr &= ~CTF_QUAL;
1✔
818
    }
819
    break;
820
  case CT_ATTRIB:
×
821
    if (ctype_isxattrib(info, CTA_QUAL))
×
822
      decl->attr &= ~size;  /* Remove redundant qualifiers. */
×
823
    cp_push_type(decl, ctype_cid(info));  /* Unroll. */
×
824
    cp_push(decl, info & ~CTMASK_CID, size);  /* Copy type. */
×
825
    break;
×
826
  case CT_ARRAY:
20✔
827
    if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) {
20✔
828
      info |= (decl->attr & CTF_QUAL);
15✔
829
      decl->attr &= ~CTF_QUAL;
15✔
830
    }
831
    cp_push_type(decl, ctype_cid(info));  /* Unroll. */
20✔
832
    cp_push(decl, info & ~CTMASK_CID, size);  /* Copy type. */
20✔
833
    decl->stack[decl->pos].sib = 1;  /* Mark as already checked and sized. */
20✔
834
    /* Note: this is not copied to the ct->sib in the C type table. */
835
    break;
20✔
836
  case CT_FUNC:
837
    /* Copy type, link parameters (shared). */
838
    decl->stack[cp_push(decl, info, size)].sib = ct->sib;
×
839
    break;
×
840
  default:
440,758✔
841
    /* Copy type, merge common qualifiers. */
842
    cp_push(decl, info|(decl->attr & CTF_QUAL), size);
440,758✔
843
    decl->attr &= ~CTF_QUAL;
440,758✔
844
    break;
440,758✔
845
  }
846
}
441,028✔
847

848
/* Consume the declaration element chain and intern the C type. */
849
static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
442,043✔
850
{
851
  CTypeID id = 0;
442,043✔
852
  CPDeclIdx idx = 0;
442,043✔
853
  CTSize csize = CTSIZE_INVALID;
442,043✔
854
  CTSize cinfo = 0;
442,043✔
855
  do {
442,837✔
856
    CType *ct = &decl->stack[idx];
442,837✔
857
    CTInfo info = ct->info;
442,837✔
858
    CTInfo size = ct->size;
442,837✔
859
    /* The cid is already part of info for copies of pointers/functions. */
860
    idx = ct->next;
442,837✔
861
    if (ctype_istypedef(info)) {
442,837✔
862
      lj_assertCP(id == 0, "typedef not at toplevel");
248✔
863
      id = ctype_cid(info);
248✔
864
      /* Always refetch info/size, since struct/enum may have been completed. */
865
      cinfo = ctype_get(cp->cts, id)->info;
248✔
866
      csize = ctype_get(cp->cts, id)->size;
248✔
867
      lj_assertCP(ctype_isstruct(cinfo) || ctype_isenum(cinfo),
248✔
868
                  "typedef of bad type");
869
    } else if (ctype_isfunc(info)) {  /* Intern function. */
442,589✔
870
      CType *fct;
32✔
871
      CTypeID fid;
32✔
872
      CTypeID sib;
32✔
873
      if (id) {
32✔
874
        CType *refct = ctype_raw(cp->cts, id);
32✔
875
        /* Reject function or refarray return types. */
876
        if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
32✔
877
          cp_err(cp, LJ_ERR_FFI_INVTYPE);
×
878
      }
879
      /* No intervening attributes allowed, skip forward. */
880
      while (idx) {
32✔
881
        CType *ctn = &decl->stack[idx];
2✔
882
        if (!ctype_isattrib(ctn->info)) break;
2✔
883
        idx = ctn->next;  /* Skip attribute. */
×
884
      }
885
      sib = ct->sib;  /* Next line may reallocate the C type table. */
32✔
886
      fid = lj_ctype_new(cp->cts, &fct);
32✔
887
      csize = CTSIZE_INVALID;
32✔
888
      fct->info = cinfo = info + id;
32✔
889
      fct->size = size;
32✔
890
      fct->sib = sib;
32✔
891
      id = fid;
32✔
892
    } else if (ctype_isattrib(info)) {
442,557✔
893
      if (ctype_isxattrib(info, CTA_QUAL))
1✔
894
        cinfo |= size;
1✔
895
      else if (ctype_isxattrib(info, CTA_ALIGN))
×
896
        CTF_INSERT(cinfo, ALIGN, size);
×
897
      id = lj_ctype_intern(cp->cts, info+id, size);
1✔
898
      /* Inherit csize/cinfo from original type. */
899
    } else {
900
      if (ctype_isnum(info)) {  /* Handle mode/vector-size attributes. */
442,556✔
901
        lj_assertCP(id == 0, "number not at toplevel");
441,556✔
902
        if (!(info & CTF_BOOL)) {
441,556✔
903
          CTSize msize = ctype_msizeP(decl->attr);
441,545✔
904
          CTSize vsize = ctype_vsizeP(decl->attr);
441,545✔
905
          if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8))) {
441,545✔
906
            CTSize malign = lj_fls(msize);
×
907
            if (malign > 4) malign = 4;  /* Limit alignment. */
×
908
            CTF_INSERT(info, ALIGN, malign);
×
909
            size = msize;  /* Override size via mode. */
×
910
          }
911
          if (vsize) {  /* Vector size set? */
441,545✔
912
            CTSize esize = lj_fls(size);
×
913
            if (vsize >= esize) {
×
914
              /* Intern the element type first. */
915
              id = lj_ctype_intern(cp->cts, info, size);
×
916
              /* Then create a vector (array) with vsize alignment. */
917
              size = (1u << vsize);
×
918
              if (vsize > 4) vsize = 4;  /* Limit alignment. */
×
919
              if (ctype_align(info) > vsize) vsize = ctype_align(info);
×
920
              info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
×
921
                                      CTALIGN(vsize));
922
            }
923
          }
924
        }
925
      } else if (ctype_isptr(info)) {
1,000✔
926
        /* Reject pointer/ref to ref. */
927
        if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
936✔
928
          cp_err(cp, LJ_ERR_FFI_INVTYPE);
×
929
        if (ctype_isref(info)) {
468✔
930
          info &= ~CTF_VOLATILE;  /* Refs are always const, never volatile. */
×
931
          /* No intervening attributes allowed, skip forward. */
932
          while (idx) {
×
933
            CType *ctn = &decl->stack[idx];
×
934
            if (!ctype_isattrib(ctn->info)) break;
×
935
            idx = ctn->next;  /* Skip attribute. */
×
936
          }
937
        }
938
      } else if (ctype_isarray(info)) {  /* Check for valid array size etc. */
532✔
939
        if (ct->sib == 0) {  /* Only check/size arrays not copied by unroll. */
293✔
940
          if (ctype_isref(cinfo))  /* Reject arrays of refs. */
272✔
941
            cp_err(cp, LJ_ERR_FFI_INVTYPE);
×
942
          /* Reject VLS or unknown-sized types. */
943
          if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
272✔
944
            cp_err(cp, LJ_ERR_FFI_INVSIZE);
×
945
          /* a[] and a[?] keep their invalid size. */
946
          if (size != CTSIZE_INVALID) {
272✔
947
            uint64_t xsz = (uint64_t)size * csize;
99✔
948
            if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
99✔
949
            size = (CTSize)xsz;
99✔
950
          }
951
        }
952
        if ((cinfo & CTF_ALIGN) > (info & CTF_ALIGN))  /* Find max. align. */
293✔
953
          info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN);
63✔
954
        info |= (cinfo & CTF_QUAL);  /* Inherit qual. */
293✔
955
      } else {
956
        lj_assertCP(ctype_isvoid(info), "bad ctype %08x", info);
442,556✔
957
      }
958
      csize = size;
442,556✔
959
      cinfo = info+id;
442,556✔
960
      id = lj_ctype_intern(cp->cts, info+id, size);
442,556✔
961
    }
962
  } while (idx);
442,837✔
963
  return id;
442,043✔
964
}
965

966
/* -- C declaration parser ------------------------------------------------ */
967

968
/* Reset declaration state to declaration specifier. */
969
static void cp_decl_reset(CPDecl *decl)
107✔
970
{
971
  decl->pos = decl->specpos;
107✔
972
  decl->top = decl->specpos+1;
107✔
973
  decl->stack[decl->specpos].next = 0;
107✔
974
  decl->attr = decl->specattr;
107✔
975
  decl->fattr = decl->specfattr;
107✔
976
  decl->name = NULL;
107✔
977
  decl->redir = NULL;
107✔
978
}
107✔
979

980
/* Parse constant initializer. */
981
/* NYI: FP constants and strings as initializers. */
982
static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
×
983
{
984
  CType *ctt = ctype_get(cp->cts, ctypeid);
×
985
  CTInfo info;
×
986
  CTSize size;
×
987
  CPValue k;
×
988
  CTypeID constid;
×
989
  while (ctype_isattrib(ctt->info)) {  /* Skip attributes. */
×
990
    ctypeid = ctype_cid(ctt->info);  /* Update ID, too. */
×
991
    ctt = ctype_get(cp->cts, ctypeid);
×
992
  }
993
  info = ctt->info;
×
994
  size = ctt->size;
×
995
  if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
×
996
    cp_err(cp, LJ_ERR_FFI_INVTYPE);
×
997
  cp_check(cp, '=');
×
998
  cp_expr_sub(cp, &k, 0);
×
999
  constid = lj_ctype_new(cp->cts, ctp);
×
1000
  (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
×
1001
  k.u32 <<= 8*(4-size);
×
1002
  if ((info & CTF_UNSIGNED))
×
1003
    k.u32 >>= 8*(4-size);
×
1004
  else
1005
    k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
×
1006
  (*ctp)->size = k.u32;
×
1007
  return constid;
×
1008
}
1009

1010
/* Parse size in parentheses as part of attribute. */
1011
static CTSize cp_decl_sizeattr(CPState *cp)
×
1012
{
1013
  CTSize sz;
×
1014
  uint32_t oldtmask = cp->tmask;
×
1015
  cp->tmask = CPNS_DEFAULT;  /* Required for expression evaluator. */
×
1016
  cp_check(cp, '(');
×
1017
  sz = cp_expr_ksize(cp);
×
1018
  cp->tmask = oldtmask;
×
1019
  cp_check(cp, ')');
×
1020
  return sz;
×
1021
}
1022

1023
/* Parse alignment attribute. */
1024
static void cp_decl_align(CPState *cp, CPDecl *decl)
1025
{
1026
  CTSize al = 4;  /* Unspecified alignment is 16 bytes. */
1027
  if (cp->tok == '(') {
1028
    al = cp_decl_sizeattr(cp);
1029
    al = al ? lj_fls(al) : 0;
1030
  }
1031
  CTF_INSERT(decl->attr, ALIGN, al);
1032
  decl->attr |= CTFP_ALIGNED;
1033
}
1034

1035
/* Parse GCC asm("name") redirect. */
1036
static void cp_decl_asm(CPState *cp, CPDecl *decl)
1037
{
1038
  UNUSED(decl);
1039
  cp_next(cp);
1040
  cp_check(cp, '(');
1041
  if (cp->tok == CTOK_STRING) {
1042
    GCstr *str = cp->str;
1043
    while (cp_next(cp) == CTOK_STRING) {
1044
      lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str));
1045
      cp->L->top--;
1046
      str = strV(cp->L->top);
1047
    }
1048
    decl->redir = str;
1049
  }
1050
  cp_check(cp, ')');
1051
}
1052

1053
/* Parse GCC __attribute__((mode(...))). */
1054
static void cp_decl_mode(CPState *cp, CPDecl *decl)
1055
{
1056
  cp_check(cp, '(');
1057
  if (cp->tok == CTOK_IDENT) {
1058
    const char *s = strdata(cp->str);
1059
    CTSize sz = 0, vlen = 0;
1060
    if (s[0] == '_' && s[1] == '_') s += 2;
1061
    if (*s == 'V') {
1062
      s++;
1063
      vlen = *s++ - '0';
1064
      if (*s >= '0' && *s <= '9')
1065
        vlen = vlen*10 + (*s++ - '0');
1066
    }
1067
    switch (*s++) {
1068
    case 'Q': sz = 1; break;
1069
    case 'H': sz = 2; break;
1070
    case 'S': sz = 4; break;
1071
    case 'D': sz = 8; break;
1072
    case 'T': sz = 16; break;
1073
    case 'O': sz = 32; break;
1074
    default: goto bad_size;
1075
    }
1076
    if (*s == 'I' || *s == 'F') {
1077
      CTF_INSERT(decl->attr, MSIZEP, sz);
1078
      if (vlen) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vlen*sz));
1079
    }
1080
  bad_size:
1081
    cp_next(cp);
1082
  }
1083
  cp_check(cp, ')');
1084
}
1085

1086
/* Parse GCC __attribute__((...)). */
1087
static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
×
1088
{
1089
  cp_next(cp);
×
1090
  cp_check(cp, '(');
×
1091
  cp_check(cp, '(');
×
1092
  while (cp->tok != ')') {
×
1093
    if (cp->tok == CTOK_IDENT) {
×
1094
      GCstr *attrstr = cp->str;
×
1095
#if LUAJIT_SMART_STRINGS
1096
      /*
1097
       * Sadly, several option __name__-s exceed 12 bytes hence they
1098
       * could've been interned using the full hash.  Strip "__" to stay
1099
       * within limits.
1100
       */
1101
      const char *c = strdata(cp->str);
×
1102
      if (attrstr->len > 12 && c[0]=='_' && c[1]=='_' && c[2] != '_' &&
×
1103
          c[attrstr->len-2]=='_' && c[attrstr->len-1]=='_')
×
1104
        attrstr = lj_str_new(cp->L, c+2, attrstr->len-4);
×
1105
#endif
1106
      cp_next(cp);
×
1107
      switch (lj_cparse_case(attrstr,
×
1108
                "\007aligned" "\013__aligned__"
1109
                "\006packed" "\012__packed__"
1110
                "\004mode" "\010__mode__"
1111
                "\013vector_size" "\017__vector_size__"
1112
#if LJ_TARGET_X86
1113
                "\007regparm" "\013__regparm__"
1114
                "\005cdecl"  "\011__cdecl__"
1115
                "\010thiscall" "\014__thiscall__"
1116
                "\010fastcall" "\014__fastcall__"
1117
                "\007stdcall" "\013__stdcall__"
1118
                "\012sseregparm" "\016__sseregparm__"
1119
#endif
1120
              )) {
1121
      case 0: case 1: /* aligned */
×
1122
        cp_decl_align(cp, decl);
×
1123
        break;
×
1124
      case 2: case 3: /* packed */
×
1125
        decl->attr |= CTFP_PACKED;
×
1126
        break;
×
1127
      case 4: case 5: /* mode */
×
1128
        cp_decl_mode(cp, decl);
×
1129
        break;
×
1130
      case 6: case 7: /* vector_size */
×
1131
        {
1132
          CTSize vsize = cp_decl_sizeattr(cp);
×
1133
          if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
×
1134
        }
1135
        break;
1136
#if LJ_TARGET_X86
1137
      case 8: case 9: /* regparm */
1138
        CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1139
        decl->fattr |= CTFP_CCONV;
1140
        break;
1141
      case 10: case 11: /* cdecl */
1142
        CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1143
        decl->fattr |= CTFP_CCONV;
1144
        break;
1145
      case 12: case 13: /* thiscall */
1146
        CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1147
        decl->fattr |= CTFP_CCONV;
1148
        break;
1149
      case 14: case 15: /* fastcall */
1150
        CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1151
        decl->fattr |= CTFP_CCONV;
1152
        break;
1153
      case 16: case 17: /* stdcall */
1154
        CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1155
        decl->fattr |= CTFP_CCONV;
1156
        break;
1157
      case 18: case 19: /* sseregparm */
1158
        decl->fattr |= CTF_SSEREGPARM;
1159
        decl->fattr |= CTFP_CCONV;
1160
        break;
1161
#endif
1162
      default:  /* Skip all other attributes. */
×
1163
        goto skip_attr;
×
1164
      }
1165
    } else if (cp->tok >= CTOK_FIRSTDECL) {  /* For __attribute((const)) etc. */
×
1166
      cp_next(cp);
×
1167
    skip_attr:
×
1168
      if (cp_opt(cp, '(')) {
×
1169
        while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
×
1170
        cp_check(cp, ')');
×
1171
      }
1172
    } else {
1173
      break;
1174
    }
1175
    if (!cp_opt(cp, ',')) break;
×
1176
  }
1177
  cp_check(cp, ')');
×
1178
  cp_check(cp, ')');
×
1179
}
×
1180

1181
/* Parse MSVC __declspec(...). */
1182
static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
×
1183
{
1184
  cp_next(cp);
×
1185
  cp_check(cp, '(');
×
1186
  while (cp->tok == CTOK_IDENT) {
×
1187
    GCstr *attrstr = cp->str;
×
1188
    cp_next(cp);
×
1189
    if (cp_str_is(attrstr, "align")) {
×
1190
      cp_decl_align(cp, decl);
×
1191
    } else {  /* Ignore all other attributes. */
1192
      if (cp_opt(cp, '(')) {
×
1193
        while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
×
1194
        cp_check(cp, ')');
×
1195
      }
1196
    }
1197
  }
1198
  cp_check(cp, ')');
×
1199
}
×
1200

1201
/* Parse declaration attributes (and common qualifiers). */
1202
static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1,326,843✔
1203
{
1204
  for (;;) {
1,326,882✔
1205
    switch (cp->tok) {
1,326,882✔
1206
    case CTOK_CONST: decl->attr |= CTF_CONST; break;
35✔
1207
    case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
1✔
1208
    case CTOK_RESTRICT: break;  /* Ignore. */
1209
    case CTOK_EXTENSION: break;  /* Ignore. */
1210
    case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
×
1211
    case CTOK_ASM: cp_decl_asm(cp, decl); continue;
3✔
1212
    case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
×
1213
    case CTOK_CCDECL:
1214
#if LJ_TARGET_X86
1215
      CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1216
      decl->fattr |= CTFP_CCONV;
1217
#endif
1218
      break;
1219
    case CTOK_PTRSZ:
×
1220
#if LJ_64
1221
      CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
×
1222
#endif
1223
      break;
×
1224
    default: return;
1,326,843✔
1225
    }
1226
    cp_next(cp);
36✔
1227
  }
1228
}
1229

1230
/* Parse struct/union/enum name. */
1231
static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
79✔
1232
{
1233
  CTypeID sid;
79✔
1234
  CType *ct;
79✔
1235
  cp->tmask = CPNS_STRUCT;
79✔
1236
  cp_next(cp);
79✔
1237
  cp_decl_attributes(cp, sdecl);
79✔
1238
  cp->tmask = CPNS_DEFAULT;
79✔
1239
  if (cp->tok != '{') {
79✔
1240
    if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
27✔
1241
    if (cp->val.id) {  /* Name of existing struct/union/enum. */
27✔
1242
      sid = cp->val.id;
15✔
1243
      ct = cp->ct;
15✔
1244
      if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION))  /* Wrong type. */
15✔
1245
        cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
×
1246
    } else {  /* Create named, incomplete struct/union/enum. */
1247
      if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
12✔
1248
        cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
×
1249
      sid = lj_ctype_new(cp->cts, &ct);
12✔
1250
      ct->info = info;
12✔
1251
      ct->size = CTSIZE_INVALID;
12✔
1252
      ctype_setname(ct, cp->str);
12✔
1253
      lj_ctype_addname(cp->cts, ct, sid);
12✔
1254
    }
1255
    cp_next(cp);
27✔
1256
  } else {  /* Create anonymous, incomplete struct/union/enum. */
1257
    sid = lj_ctype_new(cp->cts, &ct);
52✔
1258
    ct->info = info;
52✔
1259
    ct->size = CTSIZE_INVALID;
52✔
1260
  }
1261
  if (cp->tok == '{') {
79✔
1262
    if (ct->size != CTSIZE_INVALID || ct->sib)
57✔
1263
      cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
×
1264
    ct->sib = 1;  /* Indicate the type is currently being defined. */
57✔
1265
  }
1266
  return sid;
79✔
1267
}
1268

1269
/* Determine field alignment. */
1270
static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
246✔
1271
{
1272
  CTSize align = ctype_align(info);
246✔
1273
  UNUSED(cp); UNUSED(ct);
246✔
1274
#if (LJ_TARGET_X86 && !LJ_ABI_WIN) || (LJ_TARGET_ARM && __APPLE__)
1275
  /* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
1276
  if (align > 2 && !(info & CTFP_ALIGNED)) {
1277
    if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
1278
      do {
1279
        ct = ctype_rawchild(cp->cts, ct);
1280
        info = ct->info;
1281
      } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1282
    }
1283
    if (ctype_isnum(info) || ctype_isenum(info))
1284
      align = 2;
1285
  }
1286
#endif
1287
  return align;
246✔
1288
}
1289

1290
/* Layout struct/union fields. */
1291
static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
55✔
1292
{
1293
  CTSize bofs = 0, bmaxofs = 0;  /* Bit offset and max. bit offset. */
55✔
1294
  CTSize maxalign = ctype_align(sattr);
55✔
1295
  CType *sct = ctype_get(cp->cts, sid);
55✔
1296
  CTInfo sinfo = sct->info;
55✔
1297
  CTypeID fieldid = sct->sib;
55✔
1298
  while (fieldid) {
301✔
1299
    CType *ct = ctype_get(cp->cts, fieldid);
246✔
1300
    CTInfo attr = ct->size;  /* Field declaration attributes (temp.). */
246✔
1301

1302
    if (ctype_isfield(ct->info) ||
246✔
1303
        (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
1✔
1304
      CTSize align, amask;  /* Alignment (pow2) and alignment mask (bits). */
246✔
1305
      CTSize sz;
246✔
1306
      CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
246✔
1307
      CTSize bsz, csz = 8*sz;  /* Field size and container size (in bits). */
246✔
1308
      sinfo |= (info & (CTF_QUAL|CTF_VLA));  /* Merge pseudo-qualifiers. */
246✔
1309

1310
      /* Check for size overflow and determine alignment. */
1311
      if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA)) {
246✔
1312
        if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
×
1313
              !(sinfo & CTF_UNION)))
×
1314
          cp_err(cp, LJ_ERR_FFI_INVSIZE);
×
1315
        csz = sz = 0;  /* Treat a[] and a[?] as zero-sized. */
×
1316
      }
1317
      align = cp_field_align(cp, ct, info);
246✔
1318
      if (((attr|sattr) & CTFP_PACKED) ||
246✔
1319
          ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
246✔
1320
        align = ctype_align(attr);
×
1321
      if (cp->packstack[cp->curpack] < align)
246✔
1322
        align = cp->packstack[cp->curpack];
1323
      if (align > maxalign) maxalign = align;
246✔
1324
      amask = (8u << align) - 1;
246✔
1325

1326
      bsz = ctype_bitcsz(ct->info);  /* Bitfield size (temp.). */
246✔
1327
      if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
246✔
1328
        bsz = csz;  /* Regular fields or subtypes always fill the container. */
246✔
1329
        bofs = (bofs + amask) & ~amask;  /* Start new aligned field. */
246✔
1330
        ct->size = (bofs >> 3);  /* Store field offset. */
246✔
1331
      } else {  /* Bitfield. */
1332
        if (bsz == 0 || (attr & CTFP_ALIGNED) ||
×
1333
            (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
×
1334
          bofs = (bofs + amask) & ~amask;  /* Start new aligned field. */
×
1335

1336
        /* Prefer regular field over bitfield. */
1337
        if (bsz == csz && (bofs & amask) == 0) {
×
1338
          ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
×
1339
          ct->size = (bofs >> 3);  /* Store field offset. */
×
1340
        } else {
1341
          ct->info = CTINFO(CT_BITFIELD,
×
1342
            (info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
1343
            (csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
1344
#if LJ_BE
1345
          ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
1346
#else
1347
          ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
×
1348
#endif
1349
          ct->size = ((bofs & ~(csz-1)) >> 3);  /* Store container offset. */
×
1350
        }
1351
      }
1352

1353
      /* Determine next offset or max. offset. */
1354
      if ((sinfo & CTF_UNION)) {
246✔
1355
        if (bsz > bmaxofs) bmaxofs = bsz;
25✔
1356
      } else {
1357
        bofs += bsz;
221✔
1358
      }
1359
    }  /* All other fields in the chain are already set up. */
1360

1361
    fieldid = ct->sib;
246✔
1362
  }
1363

1364
  /* Complete struct/union. */
1365
  sct->info = sinfo + CTALIGN(maxalign);
55✔
1366
  bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
55✔
1367
  maxalign = (8u << maxalign) - 1;
55✔
1368
  sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
55✔
1369
}
55✔
1370

1371
/* Parse struct/union declaration. */
1372
static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
77✔
1373
{
1374
  CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
77✔
1375
  if (cp_opt(cp, '{')) {  /* Struct/union definition. */
77✔
1376
    CTypeID lastid = sid;
1377
    int lastdecl = 0;
1378
    while (cp->tok != '}') {
194✔
1379
      CPDecl decl;
139✔
1380
      CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
139✔
1381
      decl.mode = scl ? CPARSE_MODE_DIRECT :
278✔
1382
        CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
1383

1384
      for (;;) {
246✔
1385
        CTypeID ctypeid;
246✔
1386

1387
        if (lastdecl) cp_err_token(cp, '}');
×
1388

1389
        /* Parse field declarator. */
1390
        decl.bits = CTSIZE_INVALID;
246✔
1391
        cp_declarator(cp, &decl);
246✔
1392
        ctypeid = cp_decl_intern(cp, &decl);
246✔
1393

1394
        if ((scl & CDF_STATIC)) {  /* Static constant in struct namespace. */
246✔
1395
          CType *ct;
×
1396
          CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
×
1397
          ctype_get(cp->cts, lastid)->sib = fieldid;
×
1398
          lastid = fieldid;
×
1399
          ctype_setname(ct, decl.name);
×
1400
        } else {
1401
          CTSize bsz = CTBSZ_FIELD;  /* Temp. for layout phase. */
246✔
1402
          CType *ct;
246✔
1403
          CTypeID fieldid = lj_ctype_new(cp->cts, &ct);  /* Do this first. */
246✔
1404
          CType *tct = ctype_raw(cp->cts, ctypeid);
246✔
1405

1406
          if (decl.bits == CTSIZE_INVALID) {  /* Regular field. */
246✔
1407
            if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
246✔
1408
              lastdecl = 1;  /* a[] or a[?] must be the last declared field. */
×
1409

1410
            /* Accept transparent struct/union/enum. */
1411
            if (!decl.name) {
246✔
1412
              if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
1✔
1413
                    ctype_isenum(tct->info)))
1414
                cp_err_token(cp, CTOK_IDENT);
×
1415
              ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
1✔
1416
              ct->size = ctype_isstruct(tct->info) ?
2✔
1417
                         (decl.attr|0x80000000u) : 0;  /* For layout phase. */
1✔
1418
              goto add_field;
1✔
1419
            }
1420
          } else {  /* Bitfield. */
1421
            bsz = decl.bits;
×
1422
            if (!ctype_isinteger_or_bool(tct->info) ||
×
1423
                (bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
×
1424
                bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
×
1425
              cp_errmsg(cp, ':', LJ_ERR_BADVAL);
×
1426
          }
1427

1428
          /* Create temporary field for layout phase. */
1429
          ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
245✔
1430
          ct->size = decl.attr;
245✔
1431
          if (decl.name) ctype_setname(ct, decl.name);
245✔
1432

1433
        add_field:
×
1434
          ctype_get(cp->cts, lastid)->sib = fieldid;
246✔
1435
          lastid = fieldid;
246✔
1436
        }
1437
        if (!cp_opt(cp, ',')) break;
246✔
1438
        cp_decl_reset(&decl);
246✔
1439
      }
1440
      cp_check(cp, ';');
139✔
1441
    }
1442
    cp_check(cp, '}');
55✔
1443
    ctype_get(cp->cts, lastid)->sib = 0;  /* Drop sib = 1 for empty structs. */
55✔
1444
    cp_decl_attributes(cp, sdecl);  /* Layout phase needs postfix attributes. */
55✔
1445
    cp_struct_layout(cp, sid, sdecl->attr);
55✔
1446
  }
1447
  return sid;
77✔
1448
}
1449

1450
/* Parse enum declaration. */
1451
static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
2✔
1452
{
1453
  CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
2✔
1454
  CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
2✔
1455
  CTSize esize = 4;  /* Only 32 bit enums are supported. */
2✔
1456
  if (cp_opt(cp, '{')) {  /* Enum definition. */
2✔
1457
    CPValue k;
2✔
1458
    CTypeID lastid = eid;
2✔
1459
    k.u32 = 0;
2✔
1460
    k.id = CTID_INT32;
2✔
1461
    do {
2✔
1462
      GCstr *name = cp->str;
2✔
1463
      if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
2✔
1464
      if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
2✔
1465
      cp_next(cp);
2✔
1466
      if (cp_opt(cp, '=')) {
2✔
1467
        cp_expr_kint(cp, &k);
1✔
1468
        if (k.id == CTID_UINT32) {
1✔
1469
          /* C99 says that enum constants are always (signed) integers.
1470
          ** But since unsigned constants like 0x80000000 are quite common,
1471
          ** those are left as uint32_t.
1472
          */
1473
          if (k.i32 >= 0) k.id = CTID_INT32;
×
1474
        } else {
1475
          /* OTOH it's common practice and even mandated by some ABIs
1476
          ** that the enum type itself is unsigned, unless there are any
1477
          ** negative constants.
1478
          */
1479
          k.id = CTID_INT32;
1✔
1480
          if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
1✔
1481
        }
1482
      }
1483
      /* Add named enum constant. */
1484
      {
1485
        CType *ct;
2✔
1486
        CTypeID constid = lj_ctype_new(cp->cts, &ct);
2✔
1487
        ctype_get(cp->cts, lastid)->sib = constid;
2✔
1488
        lastid = constid;
2✔
1489
        ctype_setname(ct, name);
2✔
1490
        ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
2✔
1491
        ct->size = k.u32++;
2✔
1492
        if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
2✔
1493
        lj_ctype_addname(cp->cts, ct, constid);
2✔
1494
      }
1495
      if (!cp_opt(cp, ',')) break;
2✔
1496
    } while (cp->tok != '}');  /* Trailing ',' is ok. */
×
1497
    cp_check(cp, '}');
2✔
1498
    /* Complete enum. */
1499
    ctype_get(cp->cts, eid)->info = einfo;
2✔
1500
    ctype_get(cp->cts, eid)->size = esize;
2✔
1501
  }
1502
  return eid;
2✔
1503
}
1504

1505
/* Parse declaration specifiers. */
1506
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
441,938✔
1507
{
1508
  uint32_t cds = 0, sz = 0;
441,938✔
1509
  CTypeID tdef = 0;
441,938✔
1510

1511
  decl->cp = cp;
441,938✔
1512
  decl->mode = cp->mode;
441,938✔
1513
  decl->name = NULL;
441,938✔
1514
  decl->redir = NULL;
441,938✔
1515
  decl->attr = 0;
441,938✔
1516
  decl->fattr = 0;
441,938✔
1517
  decl->pos = decl->top = 0;
441,938✔
1518
  decl->stack[0].next = 0;
441,938✔
1519

1520
  for (;;) {  /* Parse basic types. */
883,915✔
1521
    cp_decl_attributes(cp, decl);
883,915✔
1522
    if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
883,915✔
1523
      uint32_t cbit;
984✔
1524
      if (cp->ct->size) {
984✔
1525
        if (sz) goto end_decl;
932✔
1526
        sz = cp->ct->size;
1527
      }
1528
      cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
984✔
1529
      cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
984✔
1530
      if (cp->tok >= CTOK_FIRSTSCL) {
984✔
1531
        if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
32✔
1532
      } else if (tdef) {
952✔
1533
        goto end_decl;
×
1534
      }
1535
      cp_next(cp);
984✔
1536
      continue;
984✔
1537
    }
1538
    if (sz || tdef ||
882,931✔
1539
        (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
441,006✔
1540
      break;
1541
    switch (cp->tok) {
440,993✔
1542
    case CTOK_STRUCT:
71✔
1543
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
71✔
1544
      continue;
71✔
1545
    case CTOK_UNION:
6✔
1546
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
6✔
1547
      continue;
6✔
1548
    case CTOK_ENUM:
2✔
1549
      tdef = cp_decl_enum(cp, decl);
2✔
1550
      continue;
2✔
1551
    case CTOK_IDENT:
440,912✔
1552
      if (ctype_istypedef(cp->ct->info)) {
440,912✔
1553
        tdef = ctype_cid(cp->ct->info);  /* Get typedef. */
440,912✔
1554
        cp_next(cp);
440,912✔
1555
        continue;
440,912✔
1556
      }
1557
      break;
1558
    case '$':
2✔
1559
      tdef = cp->val.id;
2✔
1560
      cp_next(cp);
2✔
1561
      continue;
2✔
1562
    default:
1563
      break;
1564
    }
1565
    break;
1566
  }
1567
end_decl:
441,938✔
1568

1569
  if ((cds & CDF_COMPLEX))  /* Use predefined complex types. */
441,938✔
1570
    tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
15✔
1571

1572
  if (tdef) {
441,934✔
1573
    cp_push_type(decl, tdef);
441,008✔
1574
  } else if ((cds & CDF_VOID)) {
930✔
1575
    cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
239✔
1576
    decl->attr &= ~CTF_QUAL;
239✔
1577
  } else {
1578
    /* Determine type info and size. */
1579
    CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
691✔
1580
    if ((cds & CDF_BOOL)) {
691✔
1581
      if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
11✔
1582
        cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
×
1583
      info |= CTF_BOOL;
11✔
1584
      if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
11✔
1585
      if (!sz) {
11✔
1586
        sz = 1;
1587
      }
1588
    } else if ((cds & CDF_FP)) {
680✔
1589
      info = CTINFO(CT_NUM, CTF_FP);
21✔
1590
      if ((cds & CDF_LONG)) sz = sizeof(long double);
21✔
1591
    } else if ((cds & CDF_CHAR)) {
659✔
1592
      if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1593
        info |= CTF_UCHAR;  /* Handle platforms where char is unsigned. */
1594
    } else if ((cds & CDF_SHORT)) {
456✔
1595
      sz = sizeof(short);
1596
    } else if ((cds & CDF_LONGLONG)) {
456✔
1597
      sz = 8;
1598
    } else if ((cds & CDF_LONG)) {
454✔
1599
      info |= CTF_LONG;
×
1600
      sz = sizeof(long);
×
1601
    } else if (!sz) {
454✔
1602
      if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
×
1603
        cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
×
1604
      sz = sizeof(int);
1605
    }
1606
    lj_assertCP(sz != 0, "basic ctype with zero size");
691✔
1607
    info += CTALIGN(lj_fls(sz));  /* Use natural alignment. */
691✔
1608
    info += (decl->attr & CTF_QUAL);  /* Merge qualifiers. */
691✔
1609
    cp_push(decl, info, sz);
691✔
1610
    decl->attr &= ~CTF_QUAL;
691✔
1611
  }
1612
  decl->specpos = decl->pos;
441,938✔
1613
  decl->specattr = decl->attr;
441,938✔
1614
  decl->specfattr = decl->fattr;
441,938✔
1615
  return (cds & CDF_SCL);  /* Return storage class. */
441,938✔
1616
}
1617

1618
/* Parse array declaration. */
1619
static void cp_decl_array(CPState *cp, CPDecl *decl)
272✔
1620
{
1621
  CTInfo info = CTINFO(CT_ARRAY, 0);
272✔
1622
  CTSize nelem = CTSIZE_INVALID;  /* Default size for a[] or a[?]. */
272✔
1623
  cp_decl_attributes(cp, decl);
272✔
1624
  if (cp_opt(cp, '?'))
272✔
1625
    info |= CTF_VLA;  /* Create variable-length array a[?]. */
1626
  else if (cp->tok != ']')
100✔
1627
    nelem = cp_expr_ksize(cp);
99✔
1628
  cp_check(cp, ']');
272✔
1629
  cp_add(decl, info, nelem);
272✔
1630
}
272✔
1631

1632
/* Parse function declaration. */
1633
static void cp_decl_func(CPState *cp, CPDecl *fdecl)
32✔
1634
{
1635
  CTSize nargs = 0;
32✔
1636
  CTInfo info = CTINFO(CT_FUNC, 0);
32✔
1637
  CTypeID lastid = 0, anchor = 0;
32✔
1638
  if (cp->tok != ')') {
32✔
1639
    do {
80✔
1640
      CPDecl decl;
80✔
1641
      CTypeID ctypeid, fieldid;
80✔
1642
      CType *ct;
80✔
1643
      if (cp_opt(cp, '.')) {  /* Vararg function. */
80✔
1644
        cp_check(cp, '.');  /* Workaround for the minimalistic lexer. */
1✔
1645
        cp_check(cp, '.');
1✔
1646
        info |= CTF_VARARG;
1✔
1647
        break;
4✔
1648
      }
1649
      cp_decl_spec(cp, &decl, CDF_REGISTER);
79✔
1650
      decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
79✔
1651
      cp_declarator(cp, &decl);
79✔
1652
      ctypeid = cp_decl_intern(cp, &decl);
79✔
1653
      ct = ctype_raw(cp->cts, ctypeid);
79✔
1654
      if (ctype_isvoid(ct->info))
79✔
1655
        break;
1656
      else if (ctype_isrefarray(ct->info))
77✔
1657
        ctypeid = lj_ctype_intern(cp->cts,
×
1658
          CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
×
1659
      else if (ctype_isfunc(ct->info))
77✔
1660
        ctypeid = lj_ctype_intern(cp->cts,
×
1661
          CTINFO(CT_PTR, CTALIGN_PTR|ctypeid), CTSIZE_PTR);
×
1662
      /* Add new parameter. */
1663
      fieldid = lj_ctype_new(cp->cts, &ct);
77✔
1664
      if (anchor)
77✔
1665
        ctype_get(cp->cts, lastid)->sib = fieldid;
47✔
1666
      else
1667
        anchor = fieldid;
1668
      lastid = fieldid;
77✔
1669
      if (decl.name) ctype_setname(ct, decl.name);
77✔
1670
      ct->info = CTINFO(CT_FIELD, ctypeid);
77✔
1671
      ct->size = nargs++;
77✔
1672
    } while (cp_opt(cp, ','));
77✔
1673
  }
1674
  cp_check(cp, ')');
32✔
1675
  if (cp_opt(cp, '{')) {  /* Skip function definition. */
32✔
1676
    int level = 1;
×
1677
    cp->mode |= CPARSE_MODE_SKIP;
×
1678
    for (;;) {
×
1679
      if (cp->tok == '{') level++;
×
1680
      else if (cp->tok == '}' && --level == 0) break;
×
1681
      else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
×
1682
      cp_next(cp);
×
1683
    }
1684
    cp->mode &= ~CPARSE_MODE_SKIP;
×
1685
    cp->tok = ';';  /* Ok for cp_decl_multi(), error in cp_decl_single(). */
×
1686
  }
1687
  info |= (fdecl->fattr & ~CTMASK_CID);
32✔
1688
  fdecl->fattr = 0;
32✔
1689
  fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
32✔
1690
}
32✔
1691

1692
/* Parse declarator. */
1693
static void cp_declarator(CPState *cp, CPDecl *decl)
442,048✔
1694
{
1695
  if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
442,048✔
1696

1697
  for (;;) {  /* Head of declarator. */
442,516✔
1698
    if (cp_opt(cp, '*')) {  /* Pointer. */
442,516✔
1699
      CTSize sz;
468✔
1700
      CTInfo info;
468✔
1701
      cp_decl_attributes(cp, decl);
468✔
1702
      sz = CTSIZE_PTR;
468✔
1703
      info = CTINFO(CT_PTR, CTALIGN_PTR);
468✔
1704
#if LJ_64
1705
      if (ctype_msizeP(decl->attr) == 4) {
468✔
1706
        sz = 4;
×
1707
        info = CTINFO(CT_PTR, CTALIGN(2));
×
1708
      }
1709
#endif
1710
      info += (decl->attr & (CTF_QUAL|CTF_REF));
468✔
1711
      decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
468✔
1712
      cp_push(decl, info, sz);
468✔
1713
    } else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) {  /* Reference. */
442,048✔
1714
      decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
×
1715
      cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
×
1716
    } else {
1717
      break;
1718
    }
1719
  }
1720

1721
  if (cp_opt(cp, '(')) {  /* Inner declarator. */
442,048✔
1722
    CPDeclIdx pos;
6✔
1723
    cp_decl_attributes(cp, decl);
6✔
1724
    /* Resolve ambiguity between inner declarator and 1st function parameter. */
1725
    if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
6✔
1726
        (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
6✔
1727
    pos = decl->pos;
5✔
1728
    cp_declarator(cp, decl);
5✔
1729
    cp_check(cp, ')');
5✔
1730
    decl->pos = pos;
5✔
1731
  } else if (cp->tok == CTOK_IDENT) {  /* Direct declarator. */
442,042✔
1732
    if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
338✔
1733
    decl->name = cp->str;
338✔
1734
    decl->nameid = cp->val.id;
338✔
1735
    cp_next(cp);
338✔
1736
  } else {  /* Abstract declarator. */
1737
    if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
441,704✔
1738
  }
1739

1740
  for (;;) {  /* Tail of declarator. */
442,351✔
1741
    if (cp_opt(cp, '[')) {  /* Array. */
442,351✔
1742
      cp_decl_array(cp, decl);
272✔
1743
    } else if (cp_opt(cp, '(')) {  /* Function. */
442,079✔
1744
    func_decl:
32✔
1745
      cp_decl_func(cp, decl);
32✔
1746
    } else {
1747
      break;
1748
    }
1749
  }
1750

1751
  if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':'))  /* Field width. */
442,048✔
1752
    decl->bits = cp_expr_ksize(cp);
×
1753

1754
  /* Process postfix attributes. */
1755
  cp_decl_attributes(cp, decl);
442,048✔
1756
  cp_push_attributes(decl);
442,048✔
1757

1758
  cp->depth--;
442,048✔
1759
}
442,048✔
1760

1761
/* Parse an abstract type declaration and return it's C type ID. */
1762
static CTypeID cp_decl_abstract(CPState *cp)
×
1763
{
1764
  CPDecl decl;
×
1765
  cp_decl_spec(cp, &decl, 0);
×
1766
  decl.mode = CPARSE_MODE_ABSTRACT;
×
1767
  cp_declarator(cp, &decl);
×
1768
  return cp_decl_intern(cp, &decl);
×
1769
}
1770

1771
/* Handle pragmas. */
1772
static void cp_pragma(CPState *cp, BCLine pragmaline)
×
1773
{
1774
  cp_next(cp);
×
1775
  if (cp->tok == CTOK_IDENT && cp_str_is(cp->str, "pack"))  {
×
1776
    cp_next(cp);
×
1777
    cp_check(cp, '(');
×
1778
    if (cp->tok == CTOK_IDENT) {
×
1779
      if (cp_str_is(cp->str, "push")) {
×
1780
        if (cp->curpack < CPARSE_MAX_PACKSTACK) {
×
1781
          cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
×
1782
          cp->curpack++;
×
1783
        }
1784
      } else if (cp_str_is(cp->str, "pop")) {
×
1785
        if (cp->curpack > 0) cp->curpack--;
×
1786
      } else {
1787
        cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
×
1788
      }
1789
      cp_next(cp);
×
1790
      if (!cp_opt(cp, ',')) goto end_pack;
×
1791
    }
1792
    if (cp->tok == CTOK_INTEGER) {
×
1793
      cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
×
1794
      cp_next(cp);
×
1795
    } else {
1796
      cp->packstack[cp->curpack] = 255;
×
1797
    }
1798
  end_pack:
×
1799
    cp_check(cp, ')');
×
1800
  } else {  /* Ignore all other pragmas. */
1801
    while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
×
1802
      cp_next(cp);
×
1803
  }
1804
}
×
1805

1806
/* Handle line number. */
1807
static void cp_line(CPState *cp, BCLine hashline)
×
1808
{
1809
  BCLine newline = cp->val.u32;
×
1810
  /* TODO: Handle file name and include it in error messages. */
1811
  while (cp->tok != CTOK_EOF && cp->linenumber == hashline)
×
1812
    cp_next(cp);
×
1813
  cp->linenumber = newline;
×
1814
}
1815

1816
/* Parse multiple C declarations of types or extern identifiers. */
1817
static void cp_decl_multi(CPState *cp)
25✔
1818
{
1819
  int first = 1;
25✔
1820
  while (cp->tok != CTOK_EOF) {
81✔
1821
    CPDecl decl;
64✔
1822
    CPscl scl;
64✔
1823
    if (cp_opt(cp, ';')) {  /* Skip empty statements. */
64✔
1824
      first = 0;
×
1825
      continue;
×
1826
    }
1827
    if (cp->tok == '#') {  /* Workaround, since we have no preprocessor, yet. */
64✔
1828
      BCLine hashline = cp->linenumber;
×
1829
      CPToken tok = cp_next(cp);
×
1830
      if (tok == CTOK_INTEGER) {
×
1831
        cp_line(cp, hashline);
×
1832
        continue;
×
1833
      } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "line")) {
×
1834
        if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok);
×
1835
        cp_line(cp, hashline);
×
1836
        continue;
×
1837
      } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "pragma")) {
×
1838
        cp_pragma(cp, hashline);
×
1839
        continue;
×
1840
      } else {
1841
        cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
×
1842
      }
1843
    }
1844
    scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
64✔
1845
    if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
64✔
1846
        ctype_istypedef(decl.stack[0].info)) {
2✔
1847
      CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
2✔
1848
      if (ctype_isstruct(info) || ctype_isenum(info))
2✔
1849
        goto decl_end;  /* Accept empty declaration of struct/union/enum. */
2✔
1850
    }
1851
    for (;;) {
62✔
1852
      CTypeID ctypeid;
62✔
1853
      cp_declarator(cp, &decl);
62✔
1854
      ctypeid = cp_decl_intern(cp, &decl);
62✔
1855
      if (decl.name && !decl.nameid) {  /* NYI: redeclarations are ignored. */
62✔
1856
        CType *ct;
62✔
1857
        CTypeID id;
62✔
1858
        if ((scl & CDF_TYPEDEF)) {  /* Create new typedef. */
62✔
1859
          id = lj_ctype_new(cp->cts, &ct);
32✔
1860
          ct->info = CTINFO(CT_TYPEDEF, ctypeid);
32✔
1861
          goto noredir;
32✔
1862
        } else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info)) {
30✔
1863
          /* Treat both static and extern function declarations as extern. */
1864
          ct = ctype_get(cp->cts, ctypeid);
29✔
1865
          /* We always get new anonymous functions (typedefs are copied). */
1866
          lj_assertCP(gcref(ct->name) == NULL, "unexpected named function");
29✔
1867
          id = ctypeid;  /* Just name it. */
29✔
1868
        } else if ((scl & CDF_STATIC)) {  /* Accept static constants. */
1✔
1869
          id = cp_decl_constinit(cp, &ct, ctypeid);
×
1870
          goto noredir;
×
1871
        } else {  /* External references have extern or no storage class. */
1872
          id = lj_ctype_new(cp->cts, &ct);
1✔
1873
          ct->info = CTINFO(CT_EXTERN, ctypeid);
1✔
1874
        }
1875
        if (decl.redir) {  /* Add attribute for redirected symbol name. */
30✔
1876
          CType *cta;
3✔
1877
          CTypeID aid = lj_ctype_new(cp->cts, &cta);
3✔
1878
          ct = ctype_get(cp->cts, id);  /* Table may have been reallocated. */
3✔
1879
          cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
3✔
1880
          cta->sib = ct->sib;
3✔
1881
          ct->sib = aid;
3✔
1882
          ctype_setname(cta, decl.redir);
3✔
1883
        }
1884
      noredir:
27✔
1885
        ctype_setname(ct, decl.name);
62✔
1886
        lj_ctype_addname(cp->cts, ct, id);
62✔
1887
      }
1888
      if (!cp_opt(cp, ',')) break;
62✔
1889
      cp_decl_reset(&decl);
62✔
1890
    }
1891
  decl_end:
64✔
1892
    if (cp->tok == CTOK_EOF && first) break;  /* May omit ';' for 1 decl. */
64✔
1893
    first = 0;
56✔
1894
    cp_check(cp, ';');
56✔
1895
  }
1896
}
25✔
1897

1898
/* Parse a single C type declaration. */
1899
static void cp_decl_single(CPState *cp)
441,656✔
1900
{
1901
  CPDecl decl;
441,656✔
1902
  cp_decl_spec(cp, &decl, 0);
441,656✔
1903
  cp_declarator(cp, &decl);
441,656✔
1904
  cp->val.id = cp_decl_intern(cp, &decl);
441,656✔
1905
  if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
441,656✔
1906
}
441,656✔
1907

1908
/* ------------------------------------------------------------------------ */
1909

1910
/* Protected callback for C parser. */
1911
static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
441,681✔
1912
{
1913
  CPState *cp = (CPState *)ud;
441,681✔
1914
  UNUSED(dummy);
441,681✔
1915
  cframe_errfunc(L->cframe) = -1;  /* Inherit error function. */
441,681✔
1916
  cp_init(cp);
441,681✔
1917
  if ((cp->mode & CPARSE_MODE_MULTI))
441,681✔
1918
    cp_decl_multi(cp);
25✔
1919
  else
1920
    cp_decl_single(cp);
441,656✔
1921
  if (cp->param && cp->param != cp->L->top)
441,681✔
1922
    cp_err(cp, LJ_ERR_FFI_NUMPARAM);
×
1923
  lj_assertCP(cp->depth == 0, "unbalanced cparser declaration depth");
441,681✔
1924
  return NULL;
441,681✔
1925
}
1926

1927
/* C parser. */
1928
int lj_cparse(CPState *cp)
441,681✔
1929
{
1930
  LJ_CTYPE_SAVE(cp->cts);
441,681✔
1931
  int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
441,681✔
1932
  if (errcode)
441,681✔
1933
    LJ_CTYPE_RESTORE(cp->cts);
×
1934
  cp_cleanup(cp);
441,681✔
1935
  return errcode;
441,681✔
1936
}
1937

1938
#endif
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

© 2026 Coveralls, Inc