1/*
2** C declaration parser.
3** Copyright (C) 2005-2021 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. */
44int lj_cparse_case(GCstr *str, const char *match)
45{
46 MSize len;
47 int n;
48 for (n = 0; (len = (MSize)*match++); n++, match += len) {
49 if (str->len == len && !memcmp(match, strdata(str), len))
50 return n;
51 }
52 return -1;
53}
54
55/* -- C lexer ------------------------------------------------------------- */
56
57/* C lexer token names. */
58static const char *const ctoknames[] = {
59#define CTOKSTR(name, str) str,
60CTOKDEF(CTOKSTR)
61#undef CTOKSTR
62 NULL
63};
64
65/* Forward declaration. */
66LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
67
68static 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? */
80static LJ_AINLINE int cp_iseol(CPChar c)
81{
82 return (c == '\n' || c == '\r');
83}
84
85/* Peek next raw character. */
86static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
87{
88 return (CPChar)(uint8_t)(*cp->p);
89}
90
91static LJ_NOINLINE CPChar cp_get_bs(CPState *cp);
92
93/* Get next character. */
94static LJ_AINLINE CPChar cp_get(CPState *cp)
95{
96 cp->c = (CPChar)(uint8_t)(*cp->p++);
97 if (LJ_LIKELY(cp->c != '\\')) return cp->c;
98 return cp_get_bs(cp);
99}
100
101/* Transparently skip backslash-escaped line breaks. */
102static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
103{
104 CPChar c2, c = cp_rawpeek(cp);
105 if (!cp_iseol(c)) return cp->c;
106 cp->p++;
107 c2 = cp_rawpeek(cp);
108 if (cp_iseol(c2) && c2 != c) cp->p++;
109 cp->linenumber++;
110 return cp_get(cp);
111}
112
113/* Save character in buffer. */
114static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
115{
116 lj_buf_putb(&cp->sb, c);
117}
118
119/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
120static void cp_newline(CPState *cp)
121{
122 CPChar c = cp_rawpeek(cp);
123 if (cp_iseol(c) && c != cp->c) cp->p++;
124 cp->linenumber++;
125}
126
127LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
128{
129 const char *msg, *tokstr;
130 lua_State *L;
131 va_list argp;
132 if (tok == 0) {
133 tokstr = NULL;
134 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
135 tok >= CTOK_FIRSTDECL) {
136 if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
137 cp_save(cp, '\0');
138 tokstr = sbufB(&cp->sb);
139 } else {
140 tokstr = cp_tok2str(cp, tok);
141 }
142 L = cp->L;
143 va_start(argp, em);
144 msg = lj_strfmt_pushvf(L, err2msg(em), argp);
145 va_end(argp);
146 if (tokstr)
147 msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
148 if (cp->linenumber > 1)
149 msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber);
150 lj_err_callermsg(L, msg);
151}
152
153LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
154{
155 cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
156}
157
158LJ_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
164LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
165{
166 cp_errmsg(cp, 0, em);
167}
168
169/* -- Main lexical scanner ------------------------------------------------ */
170
171/* Parse number literal. Only handles int32_t/uint32_t right now. */
172static CPToken cp_number(CPState *cp)
173{
174 StrScanFmt fmt;
175 TValue o;
176 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
177 cp_save(cp, '\0');
178 fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), sbuflen(&cp->sb)-1,
179 &o, STRSCAN_OPT_C);
180 if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
181 else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
182 else if (!(cp->mode & CPARSE_MODE_SKIP))
183 cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER);
184 cp->val.u32 = (uint32_t)o.i;
185 return CTOK_INTEGER;
186}
187
188/* Parse identifier or keyword. */
189static CPToken cp_ident(CPState *cp)
190{
191 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
192 cp->str = lj_buf_str(cp->L, &cp->sb);
193 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
194 if (ctype_type(cp->ct->info) == CT_KW)
195 return ctype_cid(cp->ct->info);
196 return CTOK_IDENT;
197}
198
199/* Parse parameter. */
200static CPToken cp_param(CPState *cp)
201{
202 CPChar c = cp_get(cp);
203 TValue *o = cp->param;
204 if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
205 cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
206 if (!o || o >= cp->L->top)
207 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
208 cp->param = o+1;
209 if (tvisstr(o)) {
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)) {
215 cp->val.i32 = numberVint(o);
216 cp->val.id = CTID_INT32;
217 return CTOK_INTEGER;
218 } else {
219 GCcdata *cd;
220 if (!tviscdata(o))
221 lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
222 cd = cdataV(o);
223 if (cd->ctypeid == CTID_CTYPEID)
224 cp->val.id = *(CTypeID *)cdataptr(cd);
225 else
226 cp->val.id = cd->ctypeid;
227 return '$';
228 }
229}
230
231/* Parse string or character constant. */
232static CPToken cp_string(CPState *cp)
233{
234 CPChar delim = cp->c;
235 cp_get(cp);
236 while (cp->c != delim) {
237 CPChar c = cp->c;
238 if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
239 if (c == '\\') {
240 c = cp_get(cp);
241 switch (c) {
242 case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
243 case 'a': c = '\a'; break;
244 case 'b': c = '\b'; break;
245 case 'f': c = '\f'; break;
246 case 'n': c = '\n'; break;
247 case 'r': c = '\r'; break;
248 case 't': c = '\t'; break;
249 case 'v': c = '\v'; break;
250 case 'e': c = 27; break;
251 case 'x':
252 c = 0;
253 while (lj_char_isxdigit(cp_get(cp)))
254 c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
255 cp_save(cp, (c & 0xff));
256 continue;
257 default:
258 if (lj_char_isdigit(c)) {
259 c -= '0';
260 if (lj_char_isdigit(cp_get(cp))) {
261 c = c*8 + (cp->c - '0');
262 if (lj_char_isdigit(cp_get(cp))) {
263 c = c*8 + (cp->c - '0');
264 cp_get(cp);
265 }
266 }
267 cp_save(cp, (c & 0xff));
268 continue;
269 }
270 break;
271 }
272 }
273 cp_save(cp, c);
274 cp_get(cp);
275 }
276 cp_get(cp);
277 if (delim == '"') {
278 cp->str = lj_buf_str(cp->L, &cp->sb);
279 return CTOK_STRING;
280 } else {
281 if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
282 cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
283 cp->val.id = CTID_INT32;
284 return CTOK_INTEGER;
285 }
286}
287
288/* Skip C comment. */
289static void cp_comment_c(CPState *cp)
290{
291 do {
292 if (cp_get(cp) == '*') {
293 do {
294 if (cp_get(cp) == '/') { cp_get(cp); return; }
295 } while (cp->c == '*');
296 }
297 if (cp_iseol(cp->c)) cp_newline(cp);
298 } while (cp->c != '\0');
299}
300
301/* Skip C++ comment. */
302static void cp_comment_cpp(CPState *cp)
303{
304 while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
305 ;
306}
307
308/* Lexical scanner for C. Only a minimal subset is implemented. */
309static CPToken cp_next_(CPState *cp)
310{
311 lj_buf_reset(&cp->sb);
312 for (;;) {
313 if (lj_char_isident(cp->c))
314 return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
315 switch (cp->c) {
316 case '\n': case '\r': cp_newline(cp); /* fallthrough. */
317 case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
318 case '"': case '\'': return cp_string(cp);
319 case '/':
320 if (cp_get(cp) == '*') cp_comment_c(cp);
321 else if (cp->c == '/') cp_comment_cpp(cp);
322 else return '/';
323 break;
324 case '|':
325 if (cp_get(cp) != '|') return '|';
326 cp_get(cp); return CTOK_OROR;
327 case '&':
328 if (cp_get(cp) != '&') return '&';
329 cp_get(cp); return CTOK_ANDAND;
330 case '=':
331 if (cp_get(cp) != '=') return '=';
332 cp_get(cp); return CTOK_EQ;
333 case '!':
334 if (cp_get(cp) != '=') return '!';
335 cp_get(cp); return CTOK_NE;
336 case '<':
337 if (cp_get(cp) == '=') { cp_get(cp); return CTOK_LE; }
338 else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
339 return '<';
340 case '>':
341 if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; }
342 else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
343 return '>';
344 case '-':
345 if (cp_get(cp) != '>') return '-';
346 cp_get(cp); return CTOK_DEREF;
347 case '$':
348 return cp_param(cp);
349 case '\0': return CTOK_EOF;
350 default: { CPToken c = cp->c; cp_get(cp); return c; }
351 }
352 }
353}
354
355static LJ_NOINLINE CPToken cp_next(CPState *cp)
356{
357 return (cp->tok = cp_next_(cp));
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
367typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
368typedef uint32_t CPscl; /* Storage class flags. */
369
370/* Type declaration context. */
371typedef 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. */
389static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
390static void cp_declarator(CPState *cp, CPDecl *decl);
391static CTypeID cp_decl_abstract(CPState *cp);
392
393/* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
394static void cp_init(CPState *cp)
395{
396 cp->linenumber = 1;
397 cp->depth = 0;
398 cp->curpack = 0;
399 cp->packstack[0] = 255;
400 lj_buf_init(cp->L, &cp->sb);
401 lj_assertCP(cp->p != NULL, "uninitialized cp->p");
402 cp_get(cp); /* Read-ahead first char. */
403 cp->tok = 0;
404 cp->tmask = CPNS_DEFAULT;
405 cp_next(cp); /* Read-ahead first token. */
406}
407
408/* Cleanup C parser state. */
409static void cp_cleanup(CPState *cp)
410{
411 global_State *g = G(cp->L);
412 lj_buf_free(g, &cp->sb);
413}
414
415/* Check and consume optional token. */
416static int cp_opt(CPState *cp, CPToken tok)
417{
418 if (cp->tok == tok) { cp_next(cp); return 1; }
419 return 0;
420}
421
422/* Check and consume token. */
423static void cp_check(CPState *cp, CPToken tok)
424{
425 if (cp->tok != tok) cp_err_token(cp, tok);
426 cp_next(cp);
427}
428
429/* Check if the next token may start a type declaration. */
430static int cp_istypedecl(CPState *cp)
431{
432 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
433 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
434 if (cp->tok == '$') return 1;
435 return 0;
436}
437
438/* -- Constant expression evaluator --------------------------------------- */
439
440/* Forward declarations. */
441static void cp_expr_unary(CPState *cp, CPValue *k);
442static 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. */
452static void cp_expr_comma(CPState *cp, CPValue *k)
453{
454 do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
455}
456
457/* Parse sizeof/alignof operator. */
458static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
459{
460 CTSize sz;
461 CTInfo info;
462 if (cp_opt(cp, '(')) {
463 if (cp_istypedecl(cp))
464 k->id = cp_decl_abstract(cp);
465 else
466 cp_expr_comma(cp, k);
467 cp_check(cp, ')');
468 } else {
469 cp_expr_unary(cp, k);
470 }
471 info = lj_ctype_info(cp->cts, k->id, &sz);
472 if (wantsz) {
473 if (sz != CTSIZE_INVALID)
474 k->u32 = sz;
475 else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
476 cp_err(cp, LJ_ERR_FFI_INVSIZE);
477 } else {
478 k->u32 = 1u << ctype_align(info);
479 }
480 k->id = CTID_UINT32; /* Really size_t. */
481}
482
483/* Parse prefix operators. */
484static void cp_expr_prefix(CPState *cp, CPValue *k)
485{
486 if (cp->tok == CTOK_INTEGER) {
487 *k = cp->val; cp_next(cp);
488 } else if (cp_opt(cp, '+')) {
489 cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
490 } else if (cp_opt(cp, '-')) {
491 cp_expr_unary(cp, k); k->i32 = -k->i32;
492 } else if (cp_opt(cp, '~')) {
493 cp_expr_unary(cp, k); k->i32 = ~k->i32;
494 } else if (cp_opt(cp, '!')) {
495 cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
496 } else if (cp_opt(cp, '(')) {
497 if (cp_istypedecl(cp)) { /* Cast operator. */
498 CTypeID id = cp_decl_abstract(cp);
499 cp_check(cp, ')');
500 cp_expr_unary(cp, k);
501 k->id = id; /* No conversion performed. */
502 } else { /* Sub-expression. */
503 cp_expr_comma(cp, k);
504 cp_check(cp, ')');
505 }
506 } else if (cp_opt(cp, '*')) { /* Indirection. */
507 CType *ct;
508 cp_expr_unary(cp, k);
509 ct = lj_ctype_rawref(cp->cts, k->id);
510 if (!ctype_ispointer(ct->info))
511 cp_err_badidx(cp, ct);
512 k->u32 = 0; k->id = ctype_cid(ct->info);
513 } else if (cp_opt(cp, '&')) { /* Address operator. */
514 cp_expr_unary(cp, k);
515 k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
516 CTSIZE_PTR);
517 } else if (cp_opt(cp, CTOK_SIZEOF)) {
518 cp_expr_sizeof(cp, k, 1);
519 } else if (cp_opt(cp, CTOK_ALIGNOF)) {
520 cp_expr_sizeof(cp, k, 0);
521 } else if (cp->tok == CTOK_IDENT) {
522 if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
523 k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
524 } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
525 k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
526 } else if (ctype_type(cp->ct->info) == CT_FUNC) {
527 k->u32 = cp->val.id; k->id = cp->val.id;
528 } else {
529 goto err_expr;
530 }
531 cp_next(cp);
532 } else if (cp->tok == CTOK_STRING) {
533 CTSize sz = cp->str->len;
534 while (cp_next(cp) == CTOK_STRING)
535 sz += cp->str->len;
536 k->u32 = sz + 1;
537 k->id = CTID_A_CCHAR;
538 } else {
539 err_expr:
540 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
541 }
542}
543
544/* Parse postfix operators. */
545static 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. */
588static 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. */
732static void cp_expr_unary(CPState *cp, CPValue *k)
733{
734 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
735 cp_expr_prefix(cp, k);
736 cp_expr_postfix(cp, k);
737 cp->depth--;
738}
739
740/* Parse and evaluate sub-expression. */
741static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
742{
743 cp_expr_unary(cp, k);
744 cp_expr_infix(cp, k, pri);
745}
746
747/* Parse constant integer expression. */
748static void cp_expr_kint(CPState *cp, CPValue *k)
749{
750 CType *ct;
751 cp_expr_sub(cp, k, 0);
752 ct = ctype_raw(cp->cts, k->id);
753 if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
754}
755
756/* Parse (non-negative) size expression. */
757static CTSize cp_expr_ksize(CPState *cp)
758{
759 CPValue k;
760 cp_expr_kint(cp, &k);
761 if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
762 return k.u32;
763}
764
765/* -- Type declaration stack management ----------------------------------- */
766
767/* Add declaration element behind the insertion position. */
768static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
769{
770 CPDeclIdx top = decl->top;
771 if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
772 decl->stack[top].info = info;
773 decl->stack[top].size = size;
774 decl->stack[top].sib = 0;
775 setgcrefnull(decl->stack[top].name);
776 decl->stack[top].next = decl->stack[decl->pos].next;
777 decl->stack[decl->pos].next = (CTypeID1)top;
778 decl->top = top+1;
779 return top;
780}
781
782/* Push declaration element before the insertion position. */
783static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
784{
785 return (decl->pos = cp_add(decl, info, size));
786}
787
788/* Push or merge attributes. */
789static void cp_push_attributes(CPDecl *decl)
790{
791 CType *ct = &decl->stack[decl->pos];
792 if (ctype_isfunc(ct->info)) { /* Ok to modify in-place. */
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))
800 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
801 ctype_align(decl->attr));
802 }
803}
804
805/* Push unrolled type to declaration stack and merge qualifiers. */
806static void cp_push_type(CPDecl *decl, CTypeID id)
807{
808 CType *ct = ctype_get(decl->cp->cts, id);
809 CTInfo info = ct->info;
810 CTSize size = ct->size;
811 switch (ctype_type(info)) {
812 case CT_STRUCT: case CT_ENUM:
813 cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
814 if ((decl->attr & CTF_QUAL)) { /* Push unmerged qualifiers. */
815 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
816 (decl->attr & CTF_QUAL));
817 decl->attr &= ~CTF_QUAL;
818 }
819 break;
820 case CT_ATTRIB:
821 if (ctype_isxattrib(info, CTA_QUAL))
822 decl->attr &= ~size; /* Remove redundant qualifiers. */
823 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
824 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
825 break;
826 case CT_ARRAY:
827 if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) {
828 info |= (decl->attr & CTF_QUAL);
829 decl->attr &= ~CTF_QUAL;
830 }
831 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
832 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
833 decl->stack[decl->pos].sib = 1; /* Mark as already checked and sized. */
834 /* Note: this is not copied to the ct->sib in the C type table. */
835 break;
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:
841 /* Copy type, merge common qualifiers. */
842 cp_push(decl, info|(decl->attr & CTF_QUAL), size);
843 decl->attr &= ~CTF_QUAL;
844 break;
845 }
846}
847
848/* Consume the declaration element chain and intern the C type. */
849static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
850{
851 CTypeID id = 0;
852 CPDeclIdx idx = 0;
853 CTSize csize = CTSIZE_INVALID;
854 CTSize cinfo = 0;
855 do {
856 CType *ct = &decl->stack[idx];
857 CTInfo info = ct->info;
858 CTInfo size = ct->size;
859 /* The cid is already part of info for copies of pointers/functions. */
860 idx = ct->next;
861 if (ctype_istypedef(info)) {
862 lj_assertCP(id == 0, "typedef not at toplevel");
863 id = ctype_cid(info);
864 /* Always refetch info/size, since struct/enum may have been completed. */
865 cinfo = ctype_get(cp->cts, id)->info;
866 csize = ctype_get(cp->cts, id)->size;
867 lj_assertCP(ctype_isstruct(cinfo) || ctype_isenum(cinfo),
868 "typedef of bad type");
869 } else if (ctype_isfunc(info)) { /* Intern function. */
870 CType *fct;
871 CTypeID fid;
872 CTypeID sib;
873 if (id) {
874 CType *refct = ctype_raw(cp->cts, id);
875 /* Reject function or refarray return types. */
876 if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
877 cp_err(cp, LJ_ERR_FFI_INVTYPE);
878 }
879 /* No intervening attributes allowed, skip forward. */
880 while (idx) {
881 CType *ctn = &decl->stack[idx];
882 if (!ctype_isattrib(ctn->info)) break;
883 idx = ctn->next; /* Skip attribute. */
884 }
885 sib = ct->sib; /* Next line may reallocate the C type table. */
886 fid = lj_ctype_new(cp->cts, &fct);
887 csize = CTSIZE_INVALID;
888 fct->info = cinfo = info + id;
889 fct->size = size;
890 fct->sib = sib;
891 id = fid;
892 } else if (ctype_isattrib(info)) {
893 if (ctype_isxattrib(info, CTA_QUAL))
894 cinfo |= size;
895 else if (ctype_isxattrib(info, CTA_ALIGN))
896 CTF_INSERT(cinfo, ALIGN, size);
897 id = lj_ctype_intern(cp->cts, info+id, size);
898 /* Inherit csize/cinfo from original type. */
899 } else {
900 if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */
901 lj_assertCP(id == 0, "number not at toplevel");
902 if (!(info & CTF_BOOL)) {
903 CTSize msize = ctype_msizeP(decl->attr);
904 CTSize vsize = ctype_vsizeP(decl->attr);
905 if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8))) {
906 CTSize malign = lj_fls(msize);
907 if (malign > 4) malign = 4; /* Limit alignment. */
908 CTF_INSERT(info, ALIGN, malign);
909 size = msize; /* Override size via mode. */
910 }
911 if (vsize) { /* Vector size set? */
912 CTSize esize = lj_fls(size);
913 if (vsize >= esize) {
914 /* Intern the element type first. */
915 id = lj_ctype_intern(cp->cts, info, size);
916 /* Then create a vector (array) with vsize alignment. */
917 size = (1u << vsize);
918 if (vsize > 4) vsize = 4; /* Limit alignment. */
919 if (ctype_align(info) > vsize) vsize = ctype_align(info);
920 info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
921 CTALIGN(vsize));
922 }
923 }
924 }
925 } else if (ctype_isptr(info)) {
926 /* Reject pointer/ref to ref. */
927 if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
928 cp_err(cp, LJ_ERR_FFI_INVTYPE);
929 if (ctype_isref(info)) {
930 info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
931 /* No intervening attributes allowed, skip forward. */
932 while (idx) {
933 CType *ctn = &decl->stack[idx];
934 if (!ctype_isattrib(ctn->info)) break;
935 idx = ctn->next; /* Skip attribute. */
936 }
937 }
938 } else if (ctype_isarray(info)) { /* Check for valid array size etc. */
939 if (ct->sib == 0) { /* Only check/size arrays not copied by unroll. */
940 if (ctype_isref(cinfo)) /* Reject arrays of refs. */
941 cp_err(cp, LJ_ERR_FFI_INVTYPE);
942 /* Reject VLS or unknown-sized types. */
943 if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
944 cp_err(cp, LJ_ERR_FFI_INVSIZE);
945 /* a[] and a[?] keep their invalid size. */
946 if (size != CTSIZE_INVALID) {
947 uint64_t xsz = (uint64_t)size * csize;
948 if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
949 size = (CTSize)xsz;
950 }
951 }
952 if ((cinfo & CTF_ALIGN) > (info & CTF_ALIGN)) /* Find max. align. */
953 info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN);
954 info |= (cinfo & CTF_QUAL); /* Inherit qual. */
955 } else {
956 lj_assertCP(ctype_isvoid(info), "bad ctype %08x", info);
957 }
958 csize = size;
959 cinfo = info+id;
960 id = lj_ctype_intern(cp->cts, info+id, size);
961 }
962 } while (idx);
963 return id;
964}
965
966/* -- C declaration parser ------------------------------------------------ */
967
968/* Reset declaration state to declaration specifier. */
969static void cp_decl_reset(CPDecl *decl)
970{
971 decl->pos = decl->specpos;
972 decl->top = decl->specpos+1;
973 decl->stack[decl->specpos].next = 0;
974 decl->attr = decl->specattr;
975 decl->fattr = decl->specfattr;
976 decl->name = NULL;
977 decl->redir = NULL;
978}
979
980/* Parse constant initializer. */
981/* NYI: FP constants and strings as initializers. */
982static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
983{
984 CType *ctt = ctype_get(cp->cts, ctypeid);
985 CTInfo info;
986 CTSize size;
987 CPValue k;
988 CTypeID constid;
989 while (ctype_isattrib(ctt->info)) { /* Skip attributes. */
990 ctypeid = ctype_cid(ctt->info); /* Update ID, too. */
991 ctt = ctype_get(cp->cts, ctypeid);
992 }
993 info = ctt->info;
994 size = ctt->size;
995 if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
996 cp_err(cp, LJ_ERR_FFI_INVTYPE);
997 cp_check(cp, '=');
998 cp_expr_sub(cp, &k, 0);
999 constid = lj_ctype_new(cp->cts, ctp);
1000 (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
1001 k.u32 <<= 8*(4-size);
1002 if ((info & CTF_UNSIGNED))
1003 k.u32 >>= 8*(4-size);
1004 else
1005 k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
1006 (*ctp)->size = k.u32;
1007 return constid;
1008}
1009
1010/* Parse size in parentheses as part of attribute. */
1011static CTSize cp_decl_sizeattr(CPState *cp)
1012{
1013 CTSize sz;
1014 uint32_t oldtmask = cp->tmask;
1015 cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
1016 cp_check(cp, '(');
1017 sz = cp_expr_ksize(cp);
1018 cp->tmask = oldtmask;
1019 cp_check(cp, ')');
1020 return sz;
1021}
1022
1023/* Parse alignment attribute. */
1024static 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. */
1036static 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(...))). */
1054static 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__((...)). */
1087static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
1088{
1089 cp_next(cp);
1090 cp_check(cp, '(');
1091 cp_check(cp, '(');
1092 while (cp->tok != ')') {
1093 if (cp->tok == CTOK_IDENT) {
1094 GCstr *attrstr = cp->str;
1095 cp_next(cp);
1096 switch (lj_cparse_case(attrstr,
1097 "\007aligned" "\013__aligned__"
1098 "\006packed" "\012__packed__"
1099 "\004mode" "\010__mode__"
1100 "\013vector_size" "\017__vector_size__"
1101#if LJ_TARGET_X86
1102 "\007regparm" "\013__regparm__"
1103 "\005cdecl" "\011__cdecl__"
1104 "\010thiscall" "\014__thiscall__"
1105 "\010fastcall" "\014__fastcall__"
1106 "\007stdcall" "\013__stdcall__"
1107 "\012sseregparm" "\016__sseregparm__"
1108#endif
1109 )) {
1110 case 0: case 1: /* aligned */
1111 cp_decl_align(cp, decl);
1112 break;
1113 case 2: case 3: /* packed */
1114 decl->attr |= CTFP_PACKED;
1115 break;
1116 case 4: case 5: /* mode */
1117 cp_decl_mode(cp, decl);
1118 break;
1119 case 6: case 7: /* vector_size */
1120 {
1121 CTSize vsize = cp_decl_sizeattr(cp);
1122 if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
1123 }
1124 break;
1125#if LJ_TARGET_X86
1126 case 8: case 9: /* regparm */
1127 CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1128 decl->fattr |= CTFP_CCONV;
1129 break;
1130 case 10: case 11: /* cdecl */
1131 CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1132 decl->fattr |= CTFP_CCONV;
1133 break;
1134 case 12: case 13: /* thiscall */
1135 CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1136 decl->fattr |= CTFP_CCONV;
1137 break;
1138 case 14: case 15: /* fastcall */
1139 CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1140 decl->fattr |= CTFP_CCONV;
1141 break;
1142 case 16: case 17: /* stdcall */
1143 CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1144 decl->fattr |= CTFP_CCONV;
1145 break;
1146 case 18: case 19: /* sseregparm */
1147 decl->fattr |= CTF_SSEREGPARM;
1148 decl->fattr |= CTFP_CCONV;
1149 break;
1150#endif
1151 default: /* Skip all other attributes. */
1152 goto skip_attr;
1153 }
1154 } else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
1155 cp_next(cp);
1156 skip_attr:
1157 if (cp_opt(cp, '(')) {
1158 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1159 cp_check(cp, ')');
1160 }
1161 } else {
1162 break;
1163 }
1164 if (!cp_opt(cp, ',')) break;
1165 }
1166 cp_check(cp, ')');
1167 cp_check(cp, ')');
1168}
1169
1170/* Parse MSVC __declspec(...). */
1171static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
1172{
1173 cp_next(cp);
1174 cp_check(cp, '(');
1175 while (cp->tok == CTOK_IDENT) {
1176 GCstr *attrstr = cp->str;
1177 cp_next(cp);
1178 if (cp_str_is(attrstr, "align")) {
1179 cp_decl_align(cp, decl);
1180 } else { /* Ignore all other attributes. */
1181 if (cp_opt(cp, '(')) {
1182 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1183 cp_check(cp, ')');
1184 }
1185 }
1186 }
1187 cp_check(cp, ')');
1188}
1189
1190/* Parse declaration attributes (and common qualifiers). */
1191static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1192{
1193 for (;;) {
1194 switch (cp->tok) {
1195 case CTOK_CONST: decl->attr |= CTF_CONST; break;
1196 case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
1197 case CTOK_RESTRICT: break; /* Ignore. */
1198 case CTOK_EXTENSION: break; /* Ignore. */
1199 case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
1200 case CTOK_ASM: cp_decl_asm(cp, decl); continue;
1201 case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
1202 case CTOK_CCDECL:
1203#if LJ_TARGET_X86
1204 CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1205 decl->fattr |= CTFP_CCONV;
1206#endif
1207 break;
1208 case CTOK_PTRSZ:
1209#if LJ_64
1210 CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
1211#endif
1212 break;
1213 default: return;
1214 }
1215 cp_next(cp);
1216 }
1217}
1218
1219/* Parse struct/union/enum name. */
1220static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
1221{
1222 CTypeID sid;
1223 CType *ct;
1224 cp->tmask = CPNS_STRUCT;
1225 cp_next(cp);
1226 cp_decl_attributes(cp, sdecl);
1227 cp->tmask = CPNS_DEFAULT;
1228 if (cp->tok != '{') {
1229 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1230 if (cp->val.id) { /* Name of existing struct/union/enum. */
1231 sid = cp->val.id;
1232 ct = cp->ct;
1233 if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION)) /* Wrong type. */
1234 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1235 } else { /* Create named, incomplete struct/union/enum. */
1236 if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
1237 cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
1238 sid = lj_ctype_new(cp->cts, &ct);
1239 ct->info = info;
1240 ct->size = CTSIZE_INVALID;
1241 ctype_setname(ct, cp->str);
1242 lj_ctype_addname(cp->cts, ct, sid);
1243 }
1244 cp_next(cp);
1245 } else { /* Create anonymous, incomplete struct/union/enum. */
1246 sid = lj_ctype_new(cp->cts, &ct);
1247 ct->info = info;
1248 ct->size = CTSIZE_INVALID;
1249 }
1250 if (cp->tok == '{') {
1251 if (ct->size != CTSIZE_INVALID || ct->sib)
1252 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1253 ct->sib = 1; /* Indicate the type is currently being defined. */
1254 }
1255 return sid;
1256}
1257
1258/* Determine field alignment. */
1259static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
1260{
1261 CTSize align = ctype_align(info);
1262 UNUSED(cp); UNUSED(ct);
1263#if (LJ_TARGET_X86 && !LJ_ABI_WIN) || (LJ_TARGET_ARM && __APPLE__)
1264 /* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
1265 if (align > 2 && !(info & CTFP_ALIGNED)) {
1266 if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
1267 do {
1268 ct = ctype_rawchild(cp->cts, ct);
1269 info = ct->info;
1270 } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1271 }
1272 if (ctype_isnum(info) || ctype_isenum(info))
1273 align = 2;
1274 }
1275#endif
1276 return align;
1277}
1278
1279/* Layout struct/union fields. */
1280static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1281{
1282 CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
1283 CTSize maxalign = ctype_align(sattr);
1284 CType *sct = ctype_get(cp->cts, sid);
1285 CTInfo sinfo = sct->info;
1286 CTypeID fieldid = sct->sib;
1287 while (fieldid) {
1288 CType *ct = ctype_get(cp->cts, fieldid);
1289 CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
1290
1291 if (ctype_isfield(ct->info) ||
1292 (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
1293 CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
1294 CTSize sz;
1295 CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
1296 CTSize bsz, csz = 8*sz; /* Field size and container size (in bits). */
1297 sinfo |= (info & (CTF_QUAL|CTF_VLA)); /* Merge pseudo-qualifiers. */
1298
1299 /* Check for size overflow and determine alignment. */
1300 if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA)) {
1301 if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
1302 !(sinfo & CTF_UNION)))
1303 cp_err(cp, LJ_ERR_FFI_INVSIZE);
1304 csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
1305 }
1306 align = cp_field_align(cp, ct, info);
1307 if (((attr|sattr) & CTFP_PACKED) ||
1308 ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
1309 align = ctype_align(attr);
1310 if (cp->packstack[cp->curpack] < align)
1311 align = cp->packstack[cp->curpack];
1312 if (align > maxalign) maxalign = align;
1313 amask = (8u << align) - 1;
1314
1315 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1316 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1317 bsz = csz; /* Regular fields or subtypes always fill the container. */
1318 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1319 ct->size = (bofs >> 3); /* Store field offset. */
1320 } else { /* Bitfield. */
1321 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
1322 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
1323 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1324
1325 /* Prefer regular field over bitfield. */
1326 if (bsz == csz && (bofs & amask) == 0) {
1327 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
1328 ct->size = (bofs >> 3); /* Store field offset. */
1329 } else {
1330 ct->info = CTINFO(CT_BITFIELD,
1331 (info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
1332 (csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
1333#if LJ_BE
1334 ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
1335#else
1336 ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
1337#endif
1338 ct->size = ((bofs & ~(csz-1)) >> 3); /* Store container offset. */
1339 }
1340 }
1341
1342 /* Determine next offset or max. offset. */
1343 if ((sinfo & CTF_UNION)) {
1344 if (bsz > bmaxofs) bmaxofs = bsz;
1345 } else {
1346 bofs += bsz;
1347 }
1348 } /* All other fields in the chain are already set up. */
1349
1350 fieldid = ct->sib;
1351 }
1352
1353 /* Complete struct/union. */
1354 sct->info = sinfo + CTALIGN(maxalign);
1355 bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
1356 maxalign = (8u << maxalign) - 1;
1357 sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
1358}
1359
1360/* Parse struct/union declaration. */
1361static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
1362{
1363 CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
1364 if (cp_opt(cp, '{')) { /* Struct/union definition. */
1365 CTypeID lastid = sid;
1366 int lastdecl = 0;
1367 while (cp->tok != '}') {
1368 CPDecl decl;
1369 CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
1370 decl.mode = scl ? CPARSE_MODE_DIRECT :
1371 CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
1372
1373 for (;;) {
1374 CTypeID ctypeid;
1375
1376 if (lastdecl) cp_err_token(cp, '}');
1377
1378 /* Parse field declarator. */
1379 decl.bits = CTSIZE_INVALID;
1380 cp_declarator(cp, &decl);
1381 ctypeid = cp_decl_intern(cp, &decl);
1382
1383 if ((scl & CDF_STATIC)) { /* Static constant in struct namespace. */
1384 CType *ct;
1385 CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
1386 ctype_get(cp->cts, lastid)->sib = fieldid;
1387 lastid = fieldid;
1388 ctype_setname(ct, decl.name);
1389 } else {
1390 CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
1391 CType *ct;
1392 CTypeID fieldid = lj_ctype_new(cp->cts, &ct); /* Do this first. */
1393 CType *tct = ctype_raw(cp->cts, ctypeid);
1394
1395 if (decl.bits == CTSIZE_INVALID) { /* Regular field. */
1396 if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
1397 lastdecl = 1; /* a[] or a[?] must be the last declared field. */
1398
1399 /* Accept transparent struct/union/enum. */
1400 if (!decl.name) {
1401 if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
1402 ctype_isenum(tct->info)))
1403 cp_err_token(cp, CTOK_IDENT);
1404 ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
1405 ct->size = ctype_isstruct(tct->info) ?
1406 (decl.attr|0x80000000u) : 0; /* For layout phase. */
1407 goto add_field;
1408 }
1409 } else { /* Bitfield. */
1410 bsz = decl.bits;
1411 if (!ctype_isinteger_or_bool(tct->info) ||
1412 (bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
1413 bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
1414 cp_errmsg(cp, ':', LJ_ERR_BADVAL);
1415 }
1416
1417 /* Create temporary field for layout phase. */
1418 ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
1419 ct->size = decl.attr;
1420 if (decl.name) ctype_setname(ct, decl.name);
1421
1422 add_field:
1423 ctype_get(cp->cts, lastid)->sib = fieldid;
1424 lastid = fieldid;
1425 }
1426 if (!cp_opt(cp, ',')) break;
1427 cp_decl_reset(&decl);
1428 }
1429 cp_check(cp, ';');
1430 }
1431 cp_check(cp, '}');
1432 ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
1433 cp_decl_attributes(cp, sdecl); /* Layout phase needs postfix attributes. */
1434 cp_struct_layout(cp, sid, sdecl->attr);
1435 }
1436 return sid;
1437}
1438
1439/* Parse enum declaration. */
1440static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
1441{
1442 CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
1443 CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
1444 CTSize esize = 4; /* Only 32 bit enums are supported. */
1445 if (cp_opt(cp, '{')) { /* Enum definition. */
1446 CPValue k;
1447 CTypeID lastid = eid;
1448 k.u32 = 0;
1449 k.id = CTID_INT32;
1450 do {
1451 GCstr *name = cp->str;
1452 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1453 if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
1454 cp_next(cp);
1455 if (cp_opt(cp, '=')) {
1456 cp_expr_kint(cp, &k);
1457 if (k.id == CTID_UINT32) {
1458 /* C99 says that enum constants are always (signed) integers.
1459 ** But since unsigned constants like 0x80000000 are quite common,
1460 ** those are left as uint32_t.
1461 */
1462 if (k.i32 >= 0) k.id = CTID_INT32;
1463 } else {
1464 /* OTOH it's common practice and even mandated by some ABIs
1465 ** that the enum type itself is unsigned, unless there are any
1466 ** negative constants.
1467 */
1468 k.id = CTID_INT32;
1469 if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
1470 }
1471 }
1472 /* Add named enum constant. */
1473 {
1474 CType *ct;
1475 CTypeID constid = lj_ctype_new(cp->cts, &ct);
1476 ctype_get(cp->cts, lastid)->sib = constid;
1477 lastid = constid;
1478 ctype_setname(ct, name);
1479 ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
1480 ct->size = k.u32++;
1481 if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
1482 lj_ctype_addname(cp->cts, ct, constid);
1483 }
1484 if (!cp_opt(cp, ',')) break;
1485 } while (cp->tok != '}'); /* Trailing ',' is ok. */
1486 cp_check(cp, '}');
1487 /* Complete enum. */
1488 ctype_get(cp->cts, eid)->info = einfo;
1489 ctype_get(cp->cts, eid)->size = esize;
1490 }
1491 return eid;
1492}
1493
1494/* Parse declaration specifiers. */
1495static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1496{
1497 uint32_t cds = 0, sz = 0;
1498 CTypeID tdef = 0;
1499
1500 decl->cp = cp;
1501 decl->mode = cp->mode;
1502 decl->name = NULL;
1503 decl->redir = NULL;
1504 decl->attr = 0;
1505 decl->fattr = 0;
1506 decl->pos = decl->top = 0;
1507 decl->stack[0].next = 0;
1508
1509 for (;;) { /* Parse basic types. */
1510 cp_decl_attributes(cp, decl);
1511 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1512 uint32_t cbit;
1513 if (cp->ct->size) {
1514 if (sz) goto end_decl;
1515 sz = cp->ct->size;
1516 }
1517 cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
1518 cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
1519 if (cp->tok >= CTOK_FIRSTSCL) {
1520 if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
1521 } else if (tdef) {
1522 goto end_decl;
1523 }
1524 cp_next(cp);
1525 continue;
1526 }
1527 if (sz || tdef ||
1528 (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
1529 break;
1530 switch (cp->tok) {
1531 case CTOK_STRUCT:
1532 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
1533 continue;
1534 case CTOK_UNION:
1535 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
1536 continue;
1537 case CTOK_ENUM:
1538 tdef = cp_decl_enum(cp, decl);
1539 continue;
1540 case CTOK_IDENT:
1541 if (ctype_istypedef(cp->ct->info)) {
1542 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
1543 cp_next(cp);
1544 continue;
1545 }
1546 break;
1547 case '$':
1548 tdef = cp->val.id;
1549 cp_next(cp);
1550 continue;
1551 default:
1552 break;
1553 }
1554 break;
1555 }
1556end_decl:
1557
1558 if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
1559 tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
1560
1561 if (tdef) {
1562 cp_push_type(decl, tdef);
1563 } else if ((cds & CDF_VOID)) {
1564 cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
1565 decl->attr &= ~CTF_QUAL;
1566 } else {
1567 /* Determine type info and size. */
1568 CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
1569 if ((cds & CDF_BOOL)) {
1570 if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
1571 cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
1572 info |= CTF_BOOL;
1573 if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
1574 if (!sz) {
1575 sz = 1;
1576 }
1577 } else if ((cds & CDF_FP)) {
1578 info = CTINFO(CT_NUM, CTF_FP);
1579 if ((cds & CDF_LONG)) sz = sizeof(long double);
1580 } else if ((cds & CDF_CHAR)) {
1581 if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1582 info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
1583 } else if ((cds & CDF_SHORT)) {
1584 sz = sizeof(short);
1585 } else if ((cds & CDF_LONGLONG)) {
1586 sz = 8;
1587 } else if ((cds & CDF_LONG)) {
1588 info |= CTF_LONG;
1589 sz = sizeof(long);
1590 } else if (!sz) {
1591 if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
1592 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
1593 sz = sizeof(int);
1594 }
1595 lj_assertCP(sz != 0, "basic ctype with zero size");
1596 info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */
1597 info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
1598 cp_push(decl, info, sz);
1599 decl->attr &= ~CTF_QUAL;
1600 }
1601 decl->specpos = decl->pos;
1602 decl->specattr = decl->attr;
1603 decl->specfattr = decl->fattr;
1604 return (cds & CDF_SCL); /* Return storage class. */
1605}
1606
1607/* Parse array declaration. */
1608static void cp_decl_array(CPState *cp, CPDecl *decl)
1609{
1610 CTInfo info = CTINFO(CT_ARRAY, 0);
1611 CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
1612 cp_decl_attributes(cp, decl);
1613 if (cp_opt(cp, '?'))
1614 info |= CTF_VLA; /* Create variable-length array a[?]. */
1615 else if (cp->tok != ']')
1616 nelem = cp_expr_ksize(cp);
1617 cp_check(cp, ']');
1618 cp_add(decl, info, nelem);
1619}
1620
1621/* Parse function declaration. */
1622static void cp_decl_func(CPState *cp, CPDecl *fdecl)
1623{
1624 CTSize nargs = 0;
1625 CTInfo info = CTINFO(CT_FUNC, 0);
1626 CTypeID lastid = 0, anchor = 0;
1627 if (cp->tok != ')') {
1628 do {
1629 CPDecl decl;
1630 CTypeID ctypeid, fieldid;
1631 CType *ct;
1632 if (cp_opt(cp, '.')) { /* Vararg function. */
1633 cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
1634 cp_check(cp, '.');
1635 info |= CTF_VARARG;
1636 break;
1637 }
1638 cp_decl_spec(cp, &decl, CDF_REGISTER);
1639 decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
1640 cp_declarator(cp, &decl);
1641 ctypeid = cp_decl_intern(cp, &decl);
1642 ct = ctype_raw(cp->cts, ctypeid);
1643 if (ctype_isvoid(ct->info))
1644 break;
1645 else if (ctype_isrefarray(ct->info))
1646 ctypeid = lj_ctype_intern(cp->cts,
1647 CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
1648 else if (ctype_isfunc(ct->info))
1649 ctypeid = lj_ctype_intern(cp->cts,
1650 CTINFO(CT_PTR, CTALIGN_PTR|ctypeid), CTSIZE_PTR);
1651 /* Add new parameter. */
1652 fieldid = lj_ctype_new(cp->cts, &ct);
1653 if (anchor)
1654 ctype_get(cp->cts, lastid)->sib = fieldid;
1655 else
1656 anchor = fieldid;
1657 lastid = fieldid;
1658 if (decl.name) ctype_setname(ct, decl.name);
1659 ct->info = CTINFO(CT_FIELD, ctypeid);
1660 ct->size = nargs++;
1661 } while (cp_opt(cp, ','));
1662 }
1663 cp_check(cp, ')');
1664 if (cp_opt(cp, '{')) { /* Skip function definition. */
1665 int level = 1;
1666 cp->mode |= CPARSE_MODE_SKIP;
1667 for (;;) {
1668 if (cp->tok == '{') level++;
1669 else if (cp->tok == '}' && --level == 0) break;
1670 else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
1671 cp_next(cp);
1672 }
1673 cp->mode &= ~CPARSE_MODE_SKIP;
1674 cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
1675 }
1676 info |= (fdecl->fattr & ~CTMASK_CID);
1677 fdecl->fattr = 0;
1678 fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
1679}
1680
1681/* Parse declarator. */
1682static void cp_declarator(CPState *cp, CPDecl *decl)
1683{
1684 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
1685
1686 for (;;) { /* Head of declarator. */
1687 if (cp_opt(cp, '*')) { /* Pointer. */
1688 CTSize sz;
1689 CTInfo info;
1690 cp_decl_attributes(cp, decl);
1691 sz = CTSIZE_PTR;
1692 info = CTINFO(CT_PTR, CTALIGN_PTR);
1693#if LJ_64
1694 if (ctype_msizeP(decl->attr) == 4) {
1695 sz = 4;
1696 info = CTINFO(CT_PTR, CTALIGN(2));
1697 }
1698#endif
1699 info += (decl->attr & (CTF_QUAL|CTF_REF));
1700 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1701 cp_push(decl, info, sz);
1702 } else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) { /* Reference. */
1703 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1704 cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
1705 } else {
1706 break;
1707 }
1708 }
1709
1710 if (cp_opt(cp, '(')) { /* Inner declarator. */
1711 CPDeclIdx pos;
1712 cp_decl_attributes(cp, decl);
1713 /* Resolve ambiguity between inner declarator and 1st function parameter. */
1714 if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
1715 (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
1716 pos = decl->pos;
1717 cp_declarator(cp, decl);
1718 cp_check(cp, ')');
1719 decl->pos = pos;
1720 } else if (cp->tok == CTOK_IDENT) { /* Direct declarator. */
1721 if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
1722 decl->name = cp->str;
1723 decl->nameid = cp->val.id;
1724 cp_next(cp);
1725 } else { /* Abstract declarator. */
1726 if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
1727 }
1728
1729 for (;;) { /* Tail of declarator. */
1730 if (cp_opt(cp, '[')) { /* Array. */
1731 cp_decl_array(cp, decl);
1732 } else if (cp_opt(cp, '(')) { /* Function. */
1733 func_decl:
1734 cp_decl_func(cp, decl);
1735 } else {
1736 break;
1737 }
1738 }
1739
1740 if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
1741 decl->bits = cp_expr_ksize(cp);
1742
1743 /* Process postfix attributes. */
1744 cp_decl_attributes(cp, decl);
1745 cp_push_attributes(decl);
1746
1747 cp->depth--;
1748}
1749
1750/* Parse an abstract type declaration and return it's C type ID. */
1751static CTypeID cp_decl_abstract(CPState *cp)
1752{
1753 CPDecl decl;
1754 cp_decl_spec(cp, &decl, 0);
1755 decl.mode = CPARSE_MODE_ABSTRACT;
1756 cp_declarator(cp, &decl);
1757 return cp_decl_intern(cp, &decl);
1758}
1759
1760/* Handle pragmas. */
1761static void cp_pragma(CPState *cp, BCLine pragmaline)
1762{
1763 cp_next(cp);
1764 if (cp->tok == CTOK_IDENT && cp_str_is(cp->str, "pack")) {
1765 cp_next(cp);
1766 cp_check(cp, '(');
1767 if (cp->tok == CTOK_IDENT) {
1768 if (cp_str_is(cp->str, "push")) {
1769 if (cp->curpack < CPARSE_MAX_PACKSTACK) {
1770 cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
1771 cp->curpack++;
1772 }
1773 } else if (cp_str_is(cp->str, "pop")) {
1774 if (cp->curpack > 0) cp->curpack--;
1775 } else {
1776 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1777 }
1778 cp_next(cp);
1779 if (!cp_opt(cp, ',')) goto end_pack;
1780 }
1781 if (cp->tok == CTOK_INTEGER) {
1782 cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
1783 cp_next(cp);
1784 } else {
1785 cp->packstack[cp->curpack] = 255;
1786 }
1787 end_pack:
1788 cp_check(cp, ')');
1789 } else { /* Ignore all other pragmas. */
1790 while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
1791 cp_next(cp);
1792 }
1793}
1794
1795/* Handle line number. */
1796static void cp_line(CPState *cp, BCLine hashline)
1797{
1798 BCLine newline = cp->val.u32;
1799 /* TODO: Handle file name and include it in error messages. */
1800 while (cp->tok != CTOK_EOF && cp->linenumber == hashline)
1801 cp_next(cp);
1802 cp->linenumber = newline;
1803}
1804
1805/* Parse multiple C declarations of types or extern identifiers. */
1806static void cp_decl_multi(CPState *cp)
1807{
1808 int first = 1;
1809 while (cp->tok != CTOK_EOF) {
1810 CPDecl decl;
1811 CPscl scl;
1812 if (cp_opt(cp, ';')) { /* Skip empty statements. */
1813 first = 0;
1814 continue;
1815 }
1816 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
1817 BCLine hashline = cp->linenumber;
1818 CPToken tok = cp_next(cp);
1819 if (tok == CTOK_INTEGER) {
1820 cp_line(cp, hashline);
1821 continue;
1822 } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "line")) {
1823 if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok);
1824 cp_line(cp, hashline);
1825 continue;
1826 } else if (tok == CTOK_IDENT && cp_str_is(cp->str, "pragma")) {
1827 cp_pragma(cp, hashline);
1828 continue;
1829 } else {
1830 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1831 }
1832 }
1833 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
1834 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
1835 ctype_istypedef(decl.stack[0].info)) {
1836 CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
1837 if (ctype_isstruct(info) || ctype_isenum(info))
1838 goto decl_end; /* Accept empty declaration of struct/union/enum. */
1839 }
1840 for (;;) {
1841 CTypeID ctypeid;
1842 cp_declarator(cp, &decl);
1843 ctypeid = cp_decl_intern(cp, &decl);
1844 if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */
1845 CType *ct;
1846 CTypeID id;
1847 if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */
1848 id = lj_ctype_new(cp->cts, &ct);
1849 ct->info = CTINFO(CT_TYPEDEF, ctypeid);
1850 goto noredir;
1851 } else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info)) {
1852 /* Treat both static and extern function declarations as extern. */
1853 ct = ctype_get(cp->cts, ctypeid);
1854 /* We always get new anonymous functions (typedefs are copied). */
1855 lj_assertCP(gcref(ct->name) == NULL, "unexpected named function");
1856 id = ctypeid; /* Just name it. */
1857 } else if ((scl & CDF_STATIC)) { /* Accept static constants. */
1858 id = cp_decl_constinit(cp, &ct, ctypeid);
1859 goto noredir;
1860 } else { /* External references have extern or no storage class. */
1861 id = lj_ctype_new(cp->cts, &ct);
1862 ct->info = CTINFO(CT_EXTERN, ctypeid);
1863 }
1864 if (decl.redir) { /* Add attribute for redirected symbol name. */
1865 CType *cta;
1866 CTypeID aid = lj_ctype_new(cp->cts, &cta);
1867 ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
1868 cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
1869 cta->sib = ct->sib;
1870 ct->sib = aid;
1871 ctype_setname(cta, decl.redir);
1872 }
1873 noredir:
1874 ctype_setname(ct, decl.name);
1875 lj_ctype_addname(cp->cts, ct, id);
1876 }
1877 if (!cp_opt(cp, ',')) break;
1878 cp_decl_reset(&decl);
1879 }
1880 decl_end:
1881 if (cp->tok == CTOK_EOF && first) break; /* May omit ';' for 1 decl. */
1882 first = 0;
1883 cp_check(cp, ';');
1884 }
1885}
1886
1887/* Parse a single C type declaration. */
1888static void cp_decl_single(CPState *cp)
1889{
1890 CPDecl decl;
1891 cp_decl_spec(cp, &decl, 0);
1892 cp_declarator(cp, &decl);
1893 cp->val.id = cp_decl_intern(cp, &decl);
1894 if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
1895}
1896
1897/* ------------------------------------------------------------------------ */
1898
1899/* Protected callback for C parser. */
1900static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
1901{
1902 CPState *cp = (CPState *)ud;
1903 UNUSED(dummy);
1904 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
1905 cp_init(cp);
1906 if ((cp->mode & CPARSE_MODE_MULTI))
1907 cp_decl_multi(cp);
1908 else
1909 cp_decl_single(cp);
1910 if (cp->param && cp->param != cp->L->top)
1911 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
1912 lj_assertCP(cp->depth == 0, "unbalanced cparser declaration depth");
1913 return NULL;
1914}
1915
1916/* C parser. */
1917int lj_cparse(CPState *cp)
1918{
1919 LJ_CTYPE_SAVE(cp->cts);
1920 int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
1921 if (errcode)
1922 LJ_CTYPE_RESTORE(cp->cts);
1923 cp_cleanup(cp);
1924 return errcode;
1925}
1926
1927#endif
1928