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

tarantool / luajit / 8545943226

03 Apr 2024 09:46PM UTC coverage: 92.672% (+4.6%) from 88.067%
8545943226

push

github

mkokryashkin
test: add tests for debugging extensions

This patch adds tests for LuaJIT debugging
extensions for lldb and gdb.

5662 of 6018 branches covered (94.08%)

Branch coverage included in aggregate %.

21615 of 23416 relevant lines covered (92.31%)

2822621.74 hits per line

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

91.39
/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)
401✔
45
{
46
  MSize len;
401✔
47
  int n;
401✔
48
  for  (n = 0; (len = (MSize)*match++); n++, match += len) {
1,428✔
49
    if (str->len == len && !memcmp(match, strdata(str), len))
1,293✔
50
      return n;
266✔
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)
817✔
81
{
82
  return (c == '\n' || c == '\r');
817✔
83
}
84

85
/* Peek next raw character. */
86
static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
625✔
87
{
88
  return (CPChar)(uint8_t)(*cp->p);
625✔
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)
5,023,877✔
95
{
96
  cp->c = (CPChar)(uint8_t)(*cp->p++);
5,023,877✔
97
  if (LJ_LIKELY(cp->c != '\\')) return cp->c;
5,023,877✔
98
  return cp_get_bs(cp);
2✔
99
}
100

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

113
/* Save character in buffer. */
114
static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
4,224,068✔
115
{
116
  lj_buf_putb(&cp->sb, c);
8,448,136✔
117
}
×
118

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

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

153
LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
16✔
154
{
155
  cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
16✔
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)
24✔
165
{
166
  cp_errmsg(cp, 0, em);
24✔
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)
437✔
173
{
174
  StrScanFmt fmt;
685✔
175
  TValue o;
685✔
176
  do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
686✔
177
  cp_save(cp, '\0');
437✔
178
  fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), sbuflen(&cp->sb)-1,
437✔
179
                        &o, STRSCAN_OPT_C);
180
  if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
437✔
181
  else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
5✔
182
  else if (!(cp->mode & CPARSE_MODE_SKIP))
1✔
183
    cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER);
×
184
  cp->val.u32 = (uint32_t)o.i;
437✔
185
  return CTOK_INTEGER;
437✔
186
}
187

188
/* Parse identifier or keyword. */
189
static CPToken cp_ident(CPState *cp)
554,157✔
190
{
191
  do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
4,773,570✔
192
  cp->str = lj_buf_str(cp->L, &cp->sb);
554,157✔
193
  cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
554,157✔
194
  if (ctype_type(cp->ct->info) == CT_KW)
554,157✔
195
    return ctype_cid(cp->ct->info);
89,143✔
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)
24✔
233
{
234
  CPChar delim = cp->c;
24✔
235
  cp_get(cp);
24✔
236
  while (cp->c != delim) {
148✔
237
    CPChar c = cp->c;
124✔
238
    if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
124✔
239
    if (c == '\\') {
124✔
240
      c = cp_get(cp);
1✔
241
      switch (c) {
1✔
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:
1✔
258
        if (lj_char_isdigit(c)) {
1✔
259
          c -= '0';
1✔
260
          if (lj_char_isdigit(cp_get(cp))) {
1✔
261
            c = c*8 + (cp->c - '0');
1✔
262
            if (lj_char_isdigit(cp_get(cp))) {
1✔
263
              c = c*8 + (cp->c - '0');
1✔
264
              cp_get(cp);
1✔
265
            }
266
          }
267
          cp_save(cp, (c & 0xff));
1✔
268
          continue;
1✔
269
        }
270
        break;
271
      }
272
    }
123✔
273
    cp_save(cp, c);
123✔
274
    cp_get(cp);
271✔
275
  }
276
  cp_get(cp);
24✔
277
  if (delim == '"') {
24✔
278
    cp->str = lj_buf_str(cp->L, &cp->sb);
21✔
279
    return CTOK_STRING;
21✔
280
  } else {
281
    if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
3✔
282
    cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
3✔
283
    cp->val.id = CTID_INT32;
3✔
284
    return CTOK_INTEGER;
3✔
285
  }
286
}
287

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

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

308
/* Lexical scanner for C. Only a minimal subset is implemented. */
309
static CPToken cp_next_(CPState *cp)
1,263,101✔
310
{
311
  lj_buf_reset(&cp->sb);
1,263,101✔
312
  for (;;) {
1,354,555✔
313
    if (lj_char_isident(cp->c))
1,354,555✔
314
      return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
554,594✔
315
    switch (cp->c) {
799,961✔
316
    case '\n': case '\r': cp_newline(cp);  /* fallthrough. */
622✔
317
    case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
1,445,999✔
318
    case '"': case '\'': return cp_string(cp);
24✔
319
    case '/':
320
      if (cp_get(cp) == '*') cp_comment_c(cp);
10✔
321
      else if (cp->c == '/') cp_comment_cpp(cp);
3✔
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 '&';
5✔
329
      cp_get(cp); return CTOK_ANDAND;
×
330
    case '=':
331
      if (cp_get(cp) != '=') return '=';
30✔
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; }
1✔
338
      else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
1✔
339
      return '<';
340
    case '>':
341
      if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; }
3✔
342
      else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
3✔
343
      return '>';
344
    case '-':
345
      if (cp_get(cp) != '>') return '-';
10✔
346
      cp_get(cp); return CTOK_DEREF;
1✔
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; }
157,715✔
351
    }
352
  }
353
}
354

355
static LJ_NOINLINE CPToken cp_next(CPState *cp)
1,263,101✔
356
{
357
  return (cp->tok = cp_next_(cp));
1,263,101✔
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)
550,774✔
395
{
396
  cp->linenumber = 1;
550,774✔
397
  cp->depth = 0;
550,774✔
398
  cp->curpack = 0;
550,774✔
399
  cp->packstack[0] = 255;
550,774✔
400
  lj_buf_init(cp->L, &cp->sb);
550,774✔
401
  lj_assertCP(cp->p != NULL, "uninitialized cp->p");
550,774✔
402
  cp_get(cp);  /* Read-ahead first char. */
550,774✔
403
  cp->tok = 0;
550,774✔
404
  cp->tmask = CPNS_DEFAULT;
550,774✔
405
  cp_next(cp);  /* Read-ahead first token. */
550,774✔
406
}
550,774✔
407

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

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

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

429
/* Check if the next token may start a type declaration. */
430
static int cp_istypedecl(CPState *cp)
60✔
431
{
432
  if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
60✔
433
  if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
55✔
434
  if (cp->tok == '$') return 1;
54✔
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)
3✔
453
{
454
  do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
3✔
455
}
3✔
456

457
/* Parse sizeof/alignof operator. */
458
static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
2✔
459
{
460
  CTSize sz;
2✔
461
  CTInfo info;
2✔
462
  if (cp_opt(cp, '(')) {
2✔
463
    if (cp_istypedecl(cp))
2✔
464
      k->id = cp_decl_abstract(cp);
1✔
465
    else
466
      cp_expr_comma(cp, k);
1✔
467
    cp_check(cp, ')');
2✔
468
  } else {
469
    cp_expr_unary(cp, k);
×
470
  }
471
  info = lj_ctype_info(cp->cts, k->id, &sz);
2✔
472
  if (wantsz) {
2✔
473
    if (sz != CTSIZE_INVALID)
2✔
474
      k->u32 = sz;
1✔
475
    else if (k->id != CTID_A_CCHAR)  /* Special case for sizeof("string"). */
1✔
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. */
2✔
481
}
2✔
482

483
/* Parse prefix operators. */
484
static void cp_expr_prefix(CPState *cp, CPValue *k)
455✔
485
{
486
  if (cp->tok == CTOK_INTEGER) {
455✔
487
    *k = cp->val; cp_next(cp);
422✔
488
  } else if (cp_opt(cp, '+')) {
33✔
489
    cp_expr_unary(cp, k);  /* Nothing to do (well, integer promotion). */
×
490
  } else if (cp_opt(cp, '-')) {
33✔
491
    cp_expr_unary(cp, k); k->i32 = -k->i32;
9✔
492
  } else if (cp_opt(cp, '~')) {
24✔
493
    cp_expr_unary(cp, k); k->i32 = ~k->i32;
×
494
  } else if (cp_opt(cp, '!')) {
24✔
495
    cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
×
496
  } else if (cp_opt(cp, '(')) {
24✔
497
    if (cp_istypedecl(cp)) {  /* Cast operator. */
5✔
498
      CTypeID id = cp_decl_abstract(cp);
3✔
499
      cp_check(cp, ')');
3✔
500
      cp_expr_unary(cp, k);
3✔
501
      k->id = id;  /* No conversion performed. */
3✔
502
    } else {  /* Sub-expression. */
503
      cp_expr_comma(cp, k);
2✔
504
      cp_check(cp, ')');
2✔
505
    }
506
  } else if (cp_opt(cp, '*')) {  /* Indirection. */
19✔
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. */
19✔
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)) {
19✔
518
    cp_expr_sizeof(cp, k, 1);
2✔
519
  } else if (cp_opt(cp, CTOK_ALIGNOF)) {
17✔
520
    cp_expr_sizeof(cp, k, 0);
×
521
  } else if (cp->tok == CTOK_IDENT) {
17✔
522
    if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
12✔
523
      k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
8✔
524
    } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
4✔
525
      k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
2✔
526
    } else if (ctype_type(cp->ct->info) == CT_FUNC) {
2✔
527
      k->u32 = cp->val.id; k->id = cp->val.id;
×
528
    } else {
529
      goto err_expr;
2✔
530
    }
531
    cp_next(cp);
10✔
532
  } else if (cp->tok == CTOK_STRING) {
5✔
533
    CTSize sz = cp->str->len;
1✔
534
    while (cp_next(cp) == CTOK_STRING)
2✔
535
      sz += cp->str->len;
1✔
536
    k->u32 = sz + 1;
1✔
537
    k->id = CTID_A_CCHAR;
1✔
538
  } else {
539
  err_expr:
4✔
540
    cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
6✔
541
  }
542
}
449✔
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)
455✔
733
{
734
  if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
455✔
735
  cp_expr_prefix(cp, k);
455✔
736
  cp_expr_postfix(cp, k);
449✔
737
  cp->depth--;
449✔
738
}
449✔
739

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

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

756
/* Parse (non-negative) size expression. */
757
static CTSize cp_expr_ksize(CPState *cp)
414✔
758
{
759
  CPValue k;
414✔
760
  cp_expr_kint(cp, &k);
414✔
761
  if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
408✔
762
  return k.u32;
406✔
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)
574,441✔
769
{
770
  CPDeclIdx top = decl->top;
574,441✔
771
  if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
826✔
772
  decl->stack[top].info = info;
574,441✔
773
  decl->stack[top].size = size;
574,441✔
774
  decl->stack[top].sib = 0;
574,441✔
775
  setgcrefnull(decl->stack[top].name);
574,441✔
776
  decl->stack[top].next = decl->stack[decl->pos].next;
574,441✔
777
  decl->stack[decl->pos].next = (CTypeID1)top;
574,441✔
778
  decl->top = top+1;
574,441✔
779
  return top;
574,441✔
780
}
781

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

788
/* Push or merge attributes. */
789
static void cp_push_attributes(CPDecl *decl)
552,327✔
790
{
791
  CType *ct = &decl->stack[decl->pos];
552,327✔
792
  if (ctype_isfunc(ct->info)) {  /* Ok to modify in-place. */
552,327✔
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))
552,327✔
800
      cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
15✔
801
              ctype_align(decl->attr));
15✔
802
  }
803
}
552,327✔
804

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

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

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

968
/* Reset declaration state to declaration specifier. */
969
static void cp_decl_reset(CPDecl *decl)
214✔
970
{
971
  decl->pos = decl->specpos;
214✔
972
  decl->top = decl->specpos+1;
214✔
973
  decl->stack[decl->specpos].next = 0;
214✔
974
  decl->attr = decl->specattr;
214✔
975
  decl->fattr = decl->specfattr;
214✔
976
  decl->name = NULL;
214✔
977
  decl->redir = NULL;
214✔
978
}
214✔
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)
16✔
983
{
984
  CType *ctt = ctype_get(cp->cts, ctypeid);
16✔
985
  CTInfo info;
16✔
986
  CTSize size;
16✔
987
  CPValue k;
16✔
988
  CTypeID constid;
16✔
989
  while (ctype_isattrib(ctt->info)) {  /* Skip attributes. */
16✔
990
    ctypeid = ctype_cid(ctt->info);  /* Update ID, too. */
×
991
    ctt = ctype_get(cp->cts, ctypeid);
×
992
  }
993
  info = ctt->info;
16✔
994
  size = ctt->size;
16✔
995
  if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
16✔
996
    cp_err(cp, LJ_ERR_FFI_INVTYPE);
6✔
997
  cp_check(cp, '=');
10✔
998
  cp_expr_sub(cp, &k, 0);
10✔
999
  constid = lj_ctype_new(cp->cts, ctp);
10✔
1000
  (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
10✔
1001
  k.u32 <<= 8*(4-size);
10✔
1002
  if ((info & CTF_UNSIGNED))
10✔
1003
    k.u32 >>= 8*(4-size);
1✔
1004
  else
1005
    k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
9✔
1006
  (*ctp)->size = k.u32;
10✔
1007
  return constid;
10✔
1008
}
1009

1010
/* Parse size in parentheses as part of attribute. */
1011
static CTSize cp_decl_sizeattr(CPState *cp)
50✔
1012
{
1013
  CTSize sz;
50✔
1014
  uint32_t oldtmask = cp->tmask;
50✔
1015
  cp->tmask = CPNS_DEFAULT;  /* Required for expression evaluator. */
50✔
1016
  cp_check(cp, '(');
50✔
1017
  sz = cp_expr_ksize(cp);
50✔
1018
  cp->tmask = oldtmask;
50✔
1019
  cp_check(cp, ')');
50✔
1020
  return sz;
50✔
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)
84✔
1088
{
1089
  cp_next(cp);
84✔
1090
  cp_check(cp, '(');
84✔
1091
  cp_check(cp, '(');
84✔
1092
  while (cp->tok != ')') {
84✔
1093
    if (cp->tok == CTOK_IDENT) {
84✔
1094
      GCstr *attrstr = cp->str;
84✔
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);
84✔
1102
      if (attrstr->len > 12 && c[0]=='_' && c[1]=='_' && c[2] != '_' &&
84✔
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);
84✔
1107
      switch (lj_cparse_case(attrstr,
84✔
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 */
39✔
1122
        cp_decl_align(cp, decl);
39✔
1123
        break;
39✔
1124
      case 2: case 3: /* packed */
12✔
1125
        decl->attr |= CTFP_PACKED;
12✔
1126
        break;
12✔
1127
      case 4: case 5: /* mode */
24✔
1128
        cp_decl_mode(cp, decl);
24✔
1129
        break;
24✔
1130
      case 6: case 7: /* vector_size */
9✔
1131
        {
1132
          CTSize vsize = cp_decl_sizeattr(cp);
9✔
1133
          if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
9✔
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;
84✔
1176
  }
1177
  cp_check(cp, ')');
84✔
1178
  cp_check(cp, ')');
84✔
1179
}
84✔
1180

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

1201
/* Parse declaration attributes (and common qualifiers). */
1202
static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1,810,336✔
1203
{
1204
  for (;;) {
1,810,589✔
1205
    switch (cp->tok) {
1,810,589✔
1206
    case CTOK_CONST: decl->attr |= CTF_CONST; break;
118✔
1207
    case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
4✔
1208
    case CTOK_RESTRICT: break;  /* Ignore. */
1209
    case CTOK_EXTENSION: break;  /* Ignore. */
1210
    case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
84✔
1211
    case CTOK_ASM: cp_decl_asm(cp, decl); continue;
19✔
1212
    case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
2✔
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:
2✔
1220
#if LJ_64
1221
      CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
2✔
1222
#endif
1223
      break;
2✔
1224
    default: return;
1,810,336✔
1225
    }
1226
    cp_next(cp);
148✔
1227
  }
1228
}
1229

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

1269
/* Determine field alignment. */
1270
static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
774✔
1271
{
1272
  CTSize align = ctype_align(info);
774✔
1273
  UNUSED(cp); UNUSED(ct);
774✔
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;
774✔
1288
}
1289

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

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

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

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

1336
        /* Prefer regular field over bitfield. */
1337
        if (bsz == csz && (bofs & amask) == 0) {
133✔
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,
133✔
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);
133✔
1348
#endif
1349
          ct->size = ((bofs & ~(csz-1)) >> 3);  /* Store container offset. */
133✔
1350
        }
1351
      }
1352

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

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

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

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

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

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

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

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

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

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

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

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

1450
/* Parse enum declaration. */
1451
static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
15✔
1452
{
1453
  CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
15✔
1454
  CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
13✔
1455
  CTSize esize = 4;  /* Only 32 bit enums are supported. */
13✔
1456
  if (cp_opt(cp, '{')) {  /* Enum definition. */
13✔
1457
    CPValue k;
13✔
1458
    CTypeID lastid = eid;
13✔
1459
    k.u32 = 0;
13✔
1460
    k.id = CTID_INT32;
13✔
1461
    do {
23✔
1462
      GCstr *name = cp->str;
23✔
1463
      if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
23✔
1464
      if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
23✔
1465
      cp_next(cp);
23✔
1466
      if (cp_opt(cp, '=')) {
23✔
1467
        cp_expr_kint(cp, &k);
12✔
1468
        if (k.id == CTID_UINT32) {
12✔
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;
1✔
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;
11✔
1480
          if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
11✔
1481
        }
1482
      }
1483
      /* Add named enum constant. */
1484
      {
1485
        CType *ct;
23✔
1486
        CTypeID constid = lj_ctype_new(cp->cts, &ct);
23✔
1487
        ctype_get(cp->cts, lastid)->sib = constid;
23✔
1488
        lastid = constid;
23✔
1489
        ctype_setname(ct, name);
23✔
1490
        ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
23✔
1491
        ct->size = k.u32++;
23✔
1492
        if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
23✔
1493
        lj_ctype_addname(cp->cts, ct, constid);
23✔
1494
      }
1495
      if (!cp_opt(cp, ',')) break;
23✔
1496
    } while (cp->tok != '}');  /* Trailing ',' is ok. */
10✔
1497
    cp_check(cp, '}');
13✔
1498
    /* Complete enum. */
1499
    ctype_get(cp->cts, eid)->info = einfo;
13✔
1500
    ctype_get(cp->cts, eid)->size = esize;
13✔
1501
  }
1502
  return eid;
13✔
1503
}
1504

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

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

1520
  for (;;) {  /* Parse basic types. */
1,104,404✔
1521
    cp_decl_attributes(cp, decl);
1,104,404✔
1522
    if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1,104,404✔
1523
      uint32_t cbit;
23,054✔
1524
      if (cp->ct->size) {
23,054✔
1525
        if (sz) goto end_decl;
22,773✔
1526
        sz = cp->ct->size;
1527
      }
1528
      cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
23,051✔
1529
      cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
23,051✔
1530
      if (cp->tok >= CTOK_FIRSTSCL) {
23,051✔
1531
        if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
108✔
1532
      } else if (tdef) {
22,943✔
1533
        goto end_decl;
×
1534
      }
1535
      cp_next(cp);
23,046✔
1536
      continue;
23,046✔
1537
    }
1538
    if (sz || tdef ||
1,081,350✔
1539
        (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
529,382✔
1540
      break;
1541
    switch (cp->tok) {
529,278✔
1542
    case CTOK_STRUCT:
65,756✔
1543
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
65,756✔
1544
      continue;
65,730✔
1545
    case CTOK_UNION:
60✔
1546
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
60✔
1547
      continue;
47✔
1548
    case CTOK_ENUM:
15✔
1549
      tdef = cp_decl_enum(cp, decl);
15✔
1550
      continue;
13✔
1551
    case CTOK_IDENT:
463,426✔
1552
      if (ctype_istypedef(cp->ct->info)) {
463,426✔
1553
        tdef = ctype_cid(cp->ct->info);  /* Get typedef. */
463,409✔
1554
        cp_next(cp);
463,409✔
1555
        continue;
463,409✔
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:
552,072✔
1568

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

1572
  if (tdef) {
552,092✔
1573
    cp_push_type(decl, tdef);
529,266✔
1574
  } else if ((cds & CDF_VOID)) {
22,845✔
1575
    cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
20,841✔
1576
    decl->attr &= ~CTF_QUAL;
20,841✔
1577
  } else {
1578
    /* Determine type info and size. */
1579
    CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
2,004✔
1580
    if ((cds & CDF_BOOL)) {
2,004✔
1581
      if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
42✔
1582
        cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
×
1583
      info |= CTF_BOOL;
42✔
1584
      if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
42✔
1585
      if (!sz) {
42✔
1586
        sz = 1;
1587
      }
1588
    } else if ((cds & CDF_FP)) {
1,962✔
1589
      info = CTINFO(CT_NUM, CTF_FP);
184✔
1590
      if ((cds & CDF_LONG)) sz = sizeof(long double);
184✔
1591
    } else if ((cds & CDF_CHAR)) {
1,778✔
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)) {
1,029✔
1595
      sz = sizeof(short);
1596
    } else if ((cds & CDF_LONGLONG)) {
996✔
1597
      sz = 8;
1598
    } else if ((cds & CDF_LONG)) {
986✔
1599
      info |= CTF_LONG;
6✔
1600
      sz = sizeof(long);
6✔
1601
    } else if (!sz) {
980✔
1602
      if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
34✔
1603
        cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
19✔
1604
      sz = sizeof(int);
1605
    }
1606
    lj_assertCP(sz != 0, "basic ctype with zero size");
1,985✔
1607
    info += CTALIGN(lj_fls(sz));  /* Use natural alignment. */
1,985✔
1608
    info += (decl->attr & CTF_QUAL);  /* Merge qualifiers. */
1,985✔
1609
    cp_push(decl, info, sz);
1,985✔
1610
    decl->attr &= ~CTF_QUAL;
1,985✔
1611
  }
1612
  decl->specpos = decl->pos;
552,092✔
1613
  decl->specattr = decl->attr;
552,092✔
1614
  decl->specfattr = decl->fattr;
552,092✔
1615
  return (cds & CDF_SCL);  /* Return storage class. */
552,092✔
1616
}
1617

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

1632
/* Parse function declaration. */
1633
static void cp_decl_func(CPState *cp, CPDecl *fdecl)
245✔
1634
{
1635
  CTSize nargs = 0;
245✔
1636
  CTInfo info = CTINFO(CT_FUNC, 0);
245✔
1637
  CTypeID lastid = 0, anchor = 0;
245✔
1638
  if (cp->tok != ')') {
245✔
1639
    do {
534✔
1640
      CPDecl decl;
534✔
1641
      CTypeID ctypeid, fieldid;
534✔
1642
      CType *ct;
534✔
1643
      if (cp_opt(cp, '.')) {  /* Vararg function. */
534✔
1644
        cp_check(cp, '.');  /* Workaround for the minimalistic lexer. */
2✔
1645
        cp_check(cp, '.');
2✔
1646
        info |= CTF_VARARG;
2✔
1647
        break;
62✔
1648
      }
1649
      cp_decl_spec(cp, &decl, CDF_REGISTER);
532✔
1650
      decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
532✔
1651
      cp_declarator(cp, &decl);
532✔
1652
      ctypeid = cp_decl_intern(cp, &decl);
532✔
1653
      ct = ctype_raw(cp->cts, ctypeid);
532✔
1654
      if (ctype_isvoid(ct->info))
532✔
1655
        break;
1656
      else if (ctype_isrefarray(ct->info))
474✔
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))
474✔
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);
474✔
1664
      if (anchor)
474✔
1665
        ctype_get(cp->cts, lastid)->sib = fieldid;
290✔
1666
      else
1667
        anchor = fieldid;
1668
      lastid = fieldid;
474✔
1669
      if (decl.name) ctype_setname(ct, decl.name);
474✔
1670
      ct->info = CTINFO(CT_FIELD, ctypeid);
474✔
1671
      ct->size = nargs++;
474✔
1672
    } while (cp_opt(cp, ','));
474✔
1673
  }
1674
  cp_check(cp, ')');
245✔
1675
  if (cp_opt(cp, '{')) {  /* Skip function definition. */
245✔
1676
    int level = 1;
1✔
1677
    cp->mode |= CPARSE_MODE_SKIP;
1✔
1678
    for (;;) {
77✔
1679
      if (cp->tok == '{') level++;
39✔
1680
      else if (cp->tok == '}' && --level == 0) break;
38✔
1681
      else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
37✔
1682
      cp_next(cp);
38✔
1683
    }
1684
    cp->mode &= ~CPARSE_MODE_SKIP;
1✔
1685
    cp->tok = ';';  /* Ok for cp_decl_multi(), error in cp_decl_single(). */
1✔
1686
  }
1687
  info |= (fdecl->fattr & ~CTMASK_CID);
245✔
1688
  fdecl->fattr = 0;
245✔
1689
  fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
245✔
1690
}
245✔
1691

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

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

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

1740
  for (;;) {  /* Tail of declarator. */
553,404✔
1741
    if (cp_opt(cp, '[')) {  /* Array. */
553,404✔
1742
      cp_decl_array(cp, decl);
830✔
1743
    } else if (cp_opt(cp, '(')) {  /* Function. */
552,574✔
1744
    func_decl:
245✔
1745
      cp_decl_func(cp, decl);
245✔
1746
    } else {
1747
      break;
1748
    }
1749
  }
1750

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

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

1758
  cp->depth--;
552,327✔
1759
}
552,327✔
1760

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

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

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

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

1900
/* Parse a single C type declaration. */
1901
static void cp_decl_single(CPState *cp)
550,699✔
1902
{
1903
  CPDecl decl;
550,699✔
1904
  cp_decl_spec(cp, &decl, 0);
550,699✔
1905
  cp_declarator(cp, &decl);
550,642✔
1906
  cp->val.id = cp_decl_intern(cp, &decl);
550,638✔
1907
  if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
550,627✔
1908
}
550,623✔
1909

1910
/* ------------------------------------------------------------------------ */
1911

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

1929
/* C parser. */
1930
int lj_cparse(CPState *cp)
550,774✔
1931
{
1932
  LJ_CTYPE_SAVE(cp->cts);
550,774✔
1933
  int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
550,774✔
1934
  if (errcode)
550,774✔
1935
    LJ_CTYPE_RESTORE(cp->cts);
90✔
1936
  cp_cleanup(cp);
550,774✔
1937
  return errcode;
550,774✔
1938
}
1939

1940
#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