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

tarantool / luajit / 27779361586

18 Jun 2026 05:40PM UTC coverage: 93.219% (+0.2%) from 93.028%
27779361586

push

github

Buristan
dbg: introduce lj-bc, lj-func and lj-proto dumpers

This patch adds dumpers for a single bytecode instruction (`lj-bc`), as
well as for all bytecodes inside one function (`lj-func`) or prototype
(`lj-proto`). Its dump is quite similar to the -bl flag but also
reports types of register operands (`jmp`, `dst`, `str`, etc.).

For LLDB, the result from the `lookup_global()` method is wrapped to the
`lldb.value` object to make it more convenient. Also, it workarounds
several LLDB revisions in which this can't be done for the array
objects. See details in the corresponding comment.

Part of tarantool/tarantool#4808

5734 of 6058 branches covered (94.65%)

Branch coverage included in aggregate %.

21871 of 23555 relevant lines covered (92.85%)

3972097.73 hits per line

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

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

85
/* Peek next raw character. */
86
static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
1,174✔
87
{
88
  return (CPChar)(uint8_t)(*cp->p);
1,174✔
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)
10,424,897✔
95
{
96
  cp->c = (CPChar)(uint8_t)(*cp->p++);
10,424,897✔
97
  if (LJ_LIKELY(cp->c != '\\')) return cp->c;
10,424,897✔
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)
8,441,448✔
115
{
116
  lj_buf_putb(&cp->sb, c);
16,882,896✔
117
}
×
118

119
/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
120
static void cp_newline(CPState *cp)
1,171✔
121
{
122
  CPChar c = cp_rawpeek(cp);
1,171✔
123
  if (cp_iseol(c) && c != cp->c) cp->p++;
134✔
124
  cp->linenumber++;
1,171✔
125
}
1,171✔
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)
372,148✔
173
{
174
  StrScanFmt fmt;
372,447✔
175
  TValue o;
372,447✔
176
  do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
372,448✔
177
  cp_save(cp, '\0');
372,148✔
178
  fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), sbuflen(&cp->sb)-1,
372,148✔
179
                        &o, STRSCAN_OPT_C);
180
  if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
372,148✔
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;
372,148✔
185
  return CTOK_INTEGER;
372,148✔
186
}
187

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

199
/* Parse parameter. */
200
static CPToken cp_param(CPState *cp)
3✔
201
{
202
  CPChar c = cp_get(cp);
3✔
203
  TValue *o = cp->param;
3✔
204
  if (lj_char_isident(c) || c == '$')  /* Reserve $xyz for future extensions. */
3✔
205
    cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
×
206
  if (!o || o >= cp->L->top)
3✔
207
    cp_err(cp, LJ_ERR_FFI_NUMPARAM);
×
208
  cp->param = o+1;
3✔
209
  if (tvisstr(o)) {
3✔
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)) {
3✔
215
    cp->val.i32 = numberVint(o);
1✔
216
    cp->val.id = CTID_INT32;
1✔
217
    return CTOK_INTEGER;
1✔
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)
9✔
303
{
304
  while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
337✔
305
    ;
328✔
306
}
9✔
307

308
/* Lexical scanner for C. Only a minimal subset is implemented. */
309
static CPToken cp_next_(CPState *cp)
3,247,716✔
310
{
311
  lj_buf_reset(&cp->sb);
3,247,716✔
312
  for (;;) {
3,716,231✔
313
    if (lj_char_isident(cp->c))
3,716,231✔
314
      return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
1,361,191✔
315
    switch (cp->c) {
2,355,040✔
316
    case '\n': case '\r': cp_newline(cp);  /* fallthrough. */
1,171✔
317
    case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
4,184,730✔
318
    case '"': case '\'': return cp_string(cp);
24✔
319
    case '/':
320
      if (cp_get(cp) == '*') cp_comment_c(cp);
16✔
321
      else if (cp->c == '/') cp_comment_cpp(cp);
9✔
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 '&';
8✔
329
      cp_get(cp); return CTOK_ANDAND;
×
330
    case '=':
331
      if (cp_get(cp) != '=') return '=';
43✔
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 '-';
12✔
346
      cp_get(cp); return CTOK_DEREF;
1✔
347
    case '$':
3✔
348
      return cp_param(cp);
3✔
349
    case '\0': return CTOK_EOF;
350
    default: { CPToken c = cp->c; cp_get(cp); return c; }
902,558✔
351
    }
352
  }
353
}
354

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

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

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

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

429
/* Check if the next token may start a type declaration. */
430
static int cp_istypedecl(CPState *cp)
65✔
431
{
432
  if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
65✔
433
  if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
58✔
434
  if (cp->tok == '$') return 1;
57✔
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)
4✔
459
{
460
  CTSize sz;
4✔
461
  CTInfo info;
4✔
462
  if (cp_opt(cp, '(')) {
4✔
463
    if (cp_istypedecl(cp))
4✔
464
      k->id = cp_decl_abstract(cp);
3✔
465
    else
466
      cp_expr_comma(cp, k);
1✔
467
    cp_check(cp, ')');
4✔
468
  } else {
469
    cp_expr_unary(cp, k);
×
470
  }
471
  info = lj_ctype_info_raw(cp->cts, k->id, &sz);
4✔
472
  if (wantsz) {
4✔
473
    if (sz != CTSIZE_INVALID)
3✔
474
      k->u32 = sz;
2✔
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);
1✔
479
  }
480
  k->id = CTID_UINT32;  /* Really size_t. */
4✔
481
}
4✔
482

483
/* Parse prefix operators. */
484
static void cp_expr_prefix(CPState *cp, CPValue *k)
372,170✔
485
{
486
  if (cp->tok == CTOK_INTEGER) {
372,170✔
487
    *k = cp->val; cp_next(cp);
372,134✔
488
  } else if (cp_opt(cp, '+')) {
36✔
489
    cp_expr_unary(cp, k);  /* Nothing to do (well, integer promotion). */
×
490
  } else if (cp_opt(cp, '-')) {
36✔
491
    cp_expr_unary(cp, k); k->i32 = (int32_t)(~(uint32_t)k->i32+1);
10✔
492
  } else if (cp_opt(cp, '~')) {
26✔
493
    cp_expr_unary(cp, k); k->i32 = ~k->i32;
×
494
  } else if (cp_opt(cp, '!')) {
26✔
495
    cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
×
496
  } else if (cp_opt(cp, '(')) {
26✔
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. */
21✔
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. */
21✔
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)) {
21✔
518
    cp_expr_sizeof(cp, k, 1);
3✔
519
  } else if (cp_opt(cp, CTOK_ALIGNOF)) {
18✔
520
    cp_expr_sizeof(cp, k, 0);
1✔
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
}
372,164✔
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)
372,170✔
733
{
734
  if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
372,170✔
735
  cp_expr_prefix(cp, k);
372,170✔
736
  cp_expr_postfix(cp, k);
372,164✔
737
  cp->depth--;
372,164✔
738
}
372,164✔
739

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

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

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

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

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

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

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

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

968
/* Reset declaration state to declaration specifier. */
969
static void cp_decl_reset(CPDecl *decl)
268✔
970
{
971
  decl->pos = decl->specpos;
268✔
972
  decl->top = decl->specpos+1;
268✔
973
  decl->stack[decl->specpos].next = 0;
268✔
974
  decl->attr = decl->specattr;
268✔
975
  decl->fattr = decl->specfattr;
268✔
976
  decl->name = NULL;
268✔
977
  decl->redir = NULL;
268✔
978
}
268✔
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)
70✔
1012
{
1013
  CTSize sz;
70✔
1014
  uint32_t oldtmask = cp->tmask;
70✔
1015
  cp->tmask = CPNS_DEFAULT;  /* Required for expression evaluator. */
70✔
1016
  cp_check(cp, '(');
70✔
1017
  sz = cp_expr_ksize(cp);
70✔
1018
  cp->tmask = oldtmask;
70✔
1019
  cp_check(cp, ')');
70✔
1020
  return sz;
70✔
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)
105✔
1088
{
1089
  cp_next(cp);
105✔
1090
  cp_check(cp, '(');
105✔
1091
  cp_check(cp, '(');
105✔
1092
  while (cp->tok != ')') {
106✔
1093
    if (cp->tok == CTOK_IDENT) {
106✔
1094
      GCstr *attrstr = cp->str;
106✔
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);
106✔
1102
      if (attrstr->len > 12 && c[0]=='_' && c[1]=='_' && c[2] != '_' &&
106✔
1103
          c[attrstr->len-2]=='_' && c[attrstr->len-1]=='_')
3✔
1104
        attrstr = lj_str_new(cp->L, c+2, attrstr->len-4);
3✔
1105
#endif
1106
      cp_next(cp);
106✔
1107
      switch (lj_cparse_case(attrstr,
106✔
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 */
56✔
1122
        cp_decl_align(cp, decl);
56✔
1123
        break;
56✔
1124
      case 2: case 3: /* packed */
14✔
1125
        decl->attr |= CTFP_PACKED;
14✔
1126
        break;
14✔
1127
      case 4: case 5: /* mode */
24✔
1128
        cp_decl_mode(cp, decl);
24✔
1129
        break;
24✔
1130
      case 6: case 7: /* vector_size */
12✔
1131
        {
1132
          CTSize vsize = cp_decl_sizeattr(cp);
12✔
1133
          if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
12✔
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;
106✔
1176
  }
1177
  cp_check(cp, ')');
105✔
1178
  cp_check(cp, ')');
105✔
1179
}
105✔
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)
3,484,224✔
1203
{
1204
  for (;;) {
3,484,568✔
1205
    switch (cp->tok) {
3,484,568✔
1206
    case CTOK_CONST: decl->attr |= CTF_CONST; break;
188✔
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;
105✔
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;
3,484,224✔
1225
    }
1226
    cp_next(cp);
218✔
1227
  }
1228
}
1229

1230
/* Parse struct/union/enum name. */
1231
static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
65,925✔
1232
{
1233
  CTypeID sid;
65,925✔
1234
  CType *ct;
65,925✔
1235
  cp->tmask = CPNS_STRUCT;
65,925✔
1236
  cp_next(cp);
65,925✔
1237
  cp_decl_attributes(cp, sdecl);
65,925✔
1238
  cp->tmask = CPNS_DEFAULT;
65,925✔
1239
  if (cp->tok != '{') {
65,925✔
1240
    if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
188✔
1241
    if (cp->val.id) {  /* Name of existing struct/union/enum. */
184✔
1242
      sid = cp->val.id;
70✔
1243
      ct = cp->ct;
70✔
1244
      if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION))  /* Wrong type. */
70✔
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))
114✔
1248
        cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
4✔
1249
      sid = lj_ctype_new(cp->cts, &ct);
110✔
1250
      ct->info = info;
110✔
1251
      ct->size = CTSIZE_INVALID;
110✔
1252
      ctype_setname(ct, cp->str);
110✔
1253
      lj_ctype_addname(cp->cts, ct, sid);
110✔
1254
    }
1255
    cp_next(cp);
176✔
1256
  } else {  /* Create anonymous, incomplete struct/union/enum. */
1257
    sid = lj_ctype_new(cp->cts, &ct);
65,737✔
1258
    ct->info = info;
65,736✔
1259
    ct->size = CTSIZE_INVALID;
65,736✔
1260
  }
1261
  if (cp->tok == '{') {
65,912✔
1262
    if (ct->size != CTSIZE_INVALID || ct->sib)
65,820✔
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,819✔
1265
  }
1266
  return sid;
65,911✔
1267
}
1268

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

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

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

1310
      /* Check for size overflow and determine alignment. */
1311
      if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA)) {
1,026✔
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);
1,021✔
1318
      if (((attr|sattr) & CTFP_PACKED) ||
1,021✔
1319
          ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
988✔
1320
        align = ctype_align(attr);
58✔
1321
      if (cp->packstack[cp->curpack] < align)
1,021✔
1322
        align = cp->packstack[cp->curpack];
1323
      bsz = ctype_bitcsz(ct->info);  /* Bitfield size (temp.). */
1,021✔
1324
      if (align > maxalign && bsz) maxalign = align;
1,021✔
1325
      amask = (8u << align) - 1;
1,021✔
1326

1327
      if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1,021✔
1328
        bsz = csz;  /* Regular fields or subtypes always fill the container. */
879✔
1329
        bofs = (bofs + amask) & ~amask;  /* Start new aligned field. */
879✔
1330
        ct->size = (bofs >> 3);  /* Store field offset. */
879✔
1331
        if (ctype_isfield(ct->info))
879✔
1332
          ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info)) + CTALIGN(align);
850✔
1333
      } else {  /* Bitfield. */
1334
        if (bsz == 0 || (attr & CTFP_ALIGNED) ||
142✔
1335
            (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
104✔
1336
          bofs = (bofs + amask) & ~amask;  /* Start new aligned field. */
36✔
1337

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

1356
      /* Determine next offset or max. offset. */
1357
      if ((sinfo & CTF_UNION)) {
1,021✔
1358
        if (bsz > bmaxofs) bmaxofs = bsz;
107✔
1359
      } else {
1360
        bofs += bsz;
914✔
1361
      }
1362
    }  /* All other fields in the chain are already set up. */
1363

1364
    fieldid = ct->sib;
1,027✔
1365
  }
1366

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

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

1387
      for (;;) {
1,056✔
1388
        CTypeID ctypeid;
1,056✔
1389

1390
        if (lastdecl) cp_err_token(cp, '}');
×
1391

1392
        /* Parse field declarator. */
1393
        decl.bits = CTSIZE_INVALID;
1,056✔
1394
        cp_declarator(cp, &decl);
1,056✔
1395
        ctypeid = cp_decl_intern(cp, &decl);
1,052✔
1396

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

1409
          if (decl.bits == CTSIZE_INVALID) {  /* Regular field. */
1,048✔
1410
            if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
897✔
1411
              lastdecl = 1;  /* a[] or a[?] must be the last declared field. */
8✔
1412

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

1431
          /* Create temporary field for layout phase. */
1432
          ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
1,005✔
1433
          ct->size = decl.attr;
1,005✔
1434
          if (decl.name) ctype_setname(ct, decl.name);
1,005✔
1435

1436
        add_field:
15✔
1437
          ctype_get(cp->cts, lastid)->sib = fieldid;
1,037✔
1438
          lastid = fieldid;
1,037✔
1439
        }
1440
        if (!cp_opt(cp, ',')) break;
1,040✔
1441
        cp_decl_reset(&decl);
1,056✔
1442
      }
1443
      cp_check(cp, ';');
772✔
1444
    }
1445
    cp_check(cp, '}');
65,781✔
1446
    ctype_get(cp->cts, lastid)->sib = 0;  /* Drop sib = 1 for empty structs. */
65,781✔
1447
    cp_decl_attributes(cp, sdecl);  /* Layout phase needs postfix attributes. */
65,781✔
1448
    cp_struct_layout(cp, sid, sdecl->attr);
65,781✔
1449
  }
1450
  return sid;
65,868✔
1451
}
1452

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

1508
/* Parse declaration specifiers. */
1509
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
986,046✔
1510
{
1511
  uint32_t cds = 0, sz = 0;
986,046✔
1512
  CTypeID tdef = 0;
986,046✔
1513

1514
  decl->cp = cp;
986,046✔
1515
  decl->mode = cp->mode;
986,046✔
1516
  decl->name = NULL;
986,046✔
1517
  decl->redir = NULL;
986,046✔
1518
  decl->attr = 0;
986,046✔
1519
  decl->fattr = 0;
986,046✔
1520
  decl->pos = decl->top = 0;
986,046✔
1521
  decl->stack[0].next = 0;
986,046✔
1522

1523
  for (;;) {  /* Parse basic types. */
1,972,262✔
1524
    cp_decl_attributes(cp, decl);
1,972,262✔
1525
    if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1,972,262✔
1526
      uint32_t cbit;
23,792✔
1527
      if (cp->ct->size) {
23,792✔
1528
        if (sz) goto end_decl;
23,411✔
1529
        sz = cp->ct->size;
1530
      }
1531
      cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
23,789✔
1532
      cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
23,789✔
1533
      if (cp->tok >= CTOK_FIRSTSCL) {
23,789✔
1534
        if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
165✔
1535
      } else if (tdef) {
23,624✔
1536
        goto end_decl;
×
1537
      }
1538
      cp_next(cp);
23,784✔
1539
      continue;
23,784✔
1540
    }
1541
    if (sz || tdef ||
1,948,470✔
1542
        (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
962,633✔
1543
      break;
1544
    switch (cp->tok) {
962,509✔
1545
    case CTOK_STRUCT:
65,845✔
1546
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
65,845✔
1547
      continue;
65,819✔
1548
    case CTOK_UNION:
62✔
1549
      tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
62✔
1550
      continue;
49✔
1551
    case CTOK_ENUM:
18✔
1552
      tdef = cp_decl_enum(cp, decl);
18✔
1553
      continue;
16✔
1554
    case CTOK_IDENT:
896,563✔
1555
      if (ctype_istypedef(cp->ct->info)) {
896,563✔
1556
        tdef = ctype_cid(cp->ct->info);  /* Get typedef. */
896,546✔
1557
        cp_next(cp);
896,546✔
1558
        continue;
896,546✔
1559
      }
1560
      break;
1561
    case '$':
2✔
1562
      tdef = cp->val.id;
2✔
1563
      cp_next(cp);
2✔
1564
      continue;
2✔
1565
    default:
1566
      break;
1567
    }
1568
    break;
1569
  }
1570
end_decl:
985,961✔
1571

1572
  if ((cds & CDF_COMPLEX))  /* Use predefined complex types. */
986,000✔
1573
    tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
65✔
1574

1575
  if (tdef) {
985,981✔
1576
    cp_push_type(decl, tdef);
962,497✔
1577
  } else if ((cds & CDF_VOID)) {
23,503✔
1578
    cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
20,968✔
1579
    decl->attr &= ~CTF_QUAL;
20,968✔
1580
  } else {
1581
    /* Determine type info and size. */
1582
    CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
2,535✔
1583
    if ((cds & CDF_BOOL)) {
2,535✔
1584
      if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
60✔
1585
        cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
×
1586
      info |= CTF_BOOL;
60✔
1587
      if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
60✔
1588
      if (!sz) {
60✔
1589
        sz = 1;
1590
      }
1591
    } else if ((cds & CDF_FP)) {
2,475✔
1592
      info = CTINFO(CT_NUM, CTF_FP);
231✔
1593
      if ((cds & CDF_LONG)) sz = sizeof(long double);
231✔
1594
    } else if ((cds & CDF_CHAR)) {
2,244✔
1595
      if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1596
        info |= CTF_UCHAR;  /* Handle platforms where char is unsigned. */
1597
    } else if ((cds & CDF_SHORT)) {
1,404✔
1598
      sz = sizeof(short);
1599
    } else if ((cds & CDF_LONGLONG)) {
1,359✔
1600
      sz = 8;
1601
    } else if ((cds & CDF_LONG)) {
1,341✔
1602
      info |= CTF_LONG;
6✔
1603
      sz = sizeof(long);
6✔
1604
    } else if (!sz) {
1,335✔
1605
      if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
34✔
1606
        cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
19✔
1607
      sz = sizeof(int);
1608
    }
1609
    lj_assertCP(sz != 0, "basic ctype with zero size");
2,516✔
1610
    info += CTALIGN(lj_fls(sz));  /* Use natural alignment. */
2,516✔
1611
    info += (decl->attr & CTF_QUAL);  /* Merge qualifiers. */
2,516✔
1612
    cp_push(decl, info, sz);
2,516✔
1613
    decl->attr &= ~CTF_QUAL;
2,516✔
1614
  }
1615
  decl->specpos = decl->pos;
985,981✔
1616
  decl->specattr = decl->attr;
985,981✔
1617
  decl->specfattr = decl->fattr;
985,981✔
1618
  return (cds & CDF_SCL);  /* Return storage class. */
985,981✔
1619
}
1620

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

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

1695
/* Parse declarator. */
1696
static void cp_declarator(CPState *cp, CPDecl *decl)
986,271✔
1697
{
1698
  if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
986,271✔
1699

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

1724
  if (cp_opt(cp, '(')) {  /* Inner declarator. */
986,271✔
1725
    CPDeclIdx pos;
56✔
1726
    cp_decl_attributes(cp, decl);
56✔
1727
    /* Resolve ambiguity between inner declarator and 1st function parameter. */
1728
    if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
56✔
1729
        (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
56✔
1730
    pos = decl->pos;
54✔
1731
    cp_declarator(cp, decl);
54✔
1732
    cp_check(cp, ')');
54✔
1733
    decl->pos = pos;
54✔
1734
  } else if (cp->tok == CTOK_IDENT) {  /* Direct declarator. */
986,215✔
1735
    if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
2,001✔
1736
    decl->name = cp->str;
2,001✔
1737
    decl->nameid = cp->val.id;
2,001✔
1738
    cp_next(cp);
2,001✔
1739
  } else {  /* Abstract declarator. */
1740
    if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
984,214✔
1741
  }
1742

1743
  for (;;) {  /* Tail of declarator. */
1,359,116✔
1744
    if (cp_opt(cp, '[')) {  /* Array. */
1,359,116✔
1745
      cp_decl_array(cp, decl);
372,504✔
1746
    } else if (cp_opt(cp, '(')) {  /* Function. */
986,612✔
1747
    func_decl:
348✔
1748
      cp_decl_func(cp, decl);
348✔
1749
    } else {
1750
      break;
1751
    }
1752
  }
1753

1754
  if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':'))  /* Field width. */
986,266✔
1755
    decl->bits = cp_expr_ksize(cp);
155✔
1756

1757
  /* Process postfix attributes. */
1758
  cp_decl_attributes(cp, decl);
986,262✔
1759
  cp_push_attributes(decl);
986,262✔
1760

1761
  cp->depth--;
986,262✔
1762
}
986,262✔
1763

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

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

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

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

1903
/* Parse a single C type declaration. */
1904
static void cp_decl_single(CPState *cp)
983,828✔
1905
{
1906
  CPDecl decl;
983,828✔
1907
  cp_decl_spec(cp, &decl, 0);
983,828✔
1908
  cp_declarator(cp, &decl);
983,771✔
1909
  cp->val.id = cp_decl_intern(cp, &decl);
983,767✔
1910
  if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
983,756✔
1911
}
983,752✔
1912

1913
/* ------------------------------------------------------------------------ */
1914

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

1932
/* C parser. */
1933
int lj_cparse(CPState *cp)
983,930✔
1934
{
1935
  LJ_CTYPE_SAVE(cp->cts);
983,930✔
1936
  int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
983,930✔
1937
  if (errcode)
983,930✔
1938
    LJ_CTYPE_RESTORE(cp->cts);
90✔
1939
  cp_cleanup(cp);
983,930✔
1940
  return errcode;
983,930✔
1941
}
1942

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