beta-0.89.2
[luatex.git] / source / libs / luajit / LuaJIT-src / src / lj_cparse.c
blobf212bd3682075f76836cb848ac878cb2ac6ff192
1 /*
2 ** C declaration parser.
3 ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #include "lj_obj.h"
8 #if LJ_HASFFI
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"
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.
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.
31 /* -- C lexer ------------------------------------------------------------- */
33 /* C lexer token names. */
34 static const char *const ctoknames[] = {
35 #define CTOKSTR(name, str) str,
36 CTOKDEF(CTOKSTR)
37 #undef CTOKSTR
38 NULL
41 /* Forward declaration. */
42 LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
44 static const char *cp_tok2str(CPState *cp, CPToken tok)
46 lua_assert(tok < CTOK_FIRSTDECL);
47 if (tok > CTOK_OFS)
48 return ctoknames[tok-CTOK_OFS-1];
49 else if (!lj_char_iscntrl(tok))
50 return lj_strfmt_pushf(cp->L, "%c", tok);
51 else
52 return lj_strfmt_pushf(cp->L, "char(%d)", tok);
55 /* End-of-line? */
56 static LJ_AINLINE int cp_iseol(CPChar c)
58 return (c == '\n' || c == '\r');
61 /* Peek next raw character. */
62 static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
64 return (CPChar)(uint8_t)(*cp->p);
67 static LJ_NOINLINE CPChar cp_get_bs(CPState *cp);
69 /* Get next character. */
70 static LJ_AINLINE CPChar cp_get(CPState *cp)
72 cp->c = (CPChar)(uint8_t)(*cp->p++);
73 if (LJ_LIKELY(cp->c != '\\')) return cp->c;
74 return cp_get_bs(cp);
77 /* Transparently skip backslash-escaped line breaks. */
78 static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
80 CPChar c2, c = cp_rawpeek(cp);
81 if (!cp_iseol(c)) return cp->c;
82 cp->p++;
83 c2 = cp_rawpeek(cp);
84 if (cp_iseol(c2) && c2 != c) cp->p++;
85 cp->linenumber++;
86 return cp_get(cp);
89 /* Save character in buffer. */
90 static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
92 lj_buf_putb(&cp->sb, c);
95 /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
96 static void cp_newline(CPState *cp)
98 CPChar c = cp_rawpeek(cp);
99 if (cp_iseol(c) && c != cp->c) cp->p++;
100 cp->linenumber++;
103 LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
105 const char *msg, *tokstr;
106 lua_State *L;
107 va_list argp;
108 if (tok == 0) {
109 tokstr = NULL;
110 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
111 tok >= CTOK_FIRSTDECL) {
112 if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
113 cp_save(cp, '\0');
114 tokstr = sbufB(&cp->sb);
115 } else {
116 tokstr = cp_tok2str(cp, tok);
118 L = cp->L;
119 va_start(argp, em);
120 msg = lj_strfmt_pushvf(L, err2msg(em), argp);
121 va_end(argp);
122 if (tokstr)
123 msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
124 if (cp->linenumber > 1)
125 msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber);
126 lj_err_callermsg(L, msg);
129 LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
131 cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
134 LJ_NORET LJ_NOINLINE static void cp_err_badidx(CPState *cp, CType *ct)
136 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
137 cp_errmsg(cp, 0, LJ_ERR_FFI_BADIDX, strdata(s));
140 LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
142 cp_errmsg(cp, 0, em);
145 /* -- Main lexical scanner ------------------------------------------------ */
147 /* Parse number literal. Only handles int32_t/uint32_t right now. */
148 static CPToken cp_number(CPState *cp)
150 StrScanFmt fmt;
151 TValue o;
152 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
153 cp_save(cp, '\0');
154 fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C);
155 if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
156 else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
157 else if (!(cp->mode & CPARSE_MODE_SKIP))
158 cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER);
159 cp->val.u32 = (uint32_t)o.i;
160 return CTOK_INTEGER;
163 /* Parse identifier or keyword. */
164 static CPToken cp_ident(CPState *cp)
166 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
167 cp->str = lj_buf_str(cp->L, &cp->sb);
168 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
169 if (ctype_type(cp->ct->info) == CT_KW)
170 return ctype_cid(cp->ct->info);
171 return CTOK_IDENT;
174 /* Parse parameter. */
175 static CPToken cp_param(CPState *cp)
177 CPChar c = cp_get(cp);
178 TValue *o = cp->param;
179 if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
180 cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
181 if (!o || o >= cp->L->top)
182 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
183 cp->param = o+1;
184 if (tvisstr(o)) {
185 cp->str = strV(o);
186 cp->val.id = 0;
187 cp->ct = &cp->cts->tab[0];
188 return CTOK_IDENT;
189 } else if (tvisnumber(o)) {
190 cp->val.i32 = numberVint(o);
191 cp->val.id = CTID_INT32;
192 return CTOK_INTEGER;
193 } else {
194 GCcdata *cd;
195 if (!tviscdata(o))
196 lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
197 cd = cdataV(o);
198 if (cd->ctypeid == CTID_CTYPEID)
199 cp->val.id = *(CTypeID *)cdataptr(cd);
200 else
201 cp->val.id = cd->ctypeid;
202 return '$';
206 /* Parse string or character constant. */
207 static CPToken cp_string(CPState *cp)
209 CPChar delim = cp->c;
210 cp_get(cp);
211 while (cp->c != delim) {
212 CPChar c = cp->c;
213 if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
214 if (c == '\\') {
215 c = cp_get(cp);
216 switch (c) {
217 case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
218 case 'a': c = '\a'; break;
219 case 'b': c = '\b'; break;
220 case 'f': c = '\f'; break;
221 case 'n': c = '\n'; break;
222 case 'r': c = '\r'; break;
223 case 't': c = '\t'; break;
224 case 'v': c = '\v'; break;
225 case 'e': c = 27; break;
226 case 'x':
227 c = 0;
228 while (lj_char_isxdigit(cp_get(cp)))
229 c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
230 cp_save(cp, (c & 0xff));
231 continue;
232 default:
233 if (lj_char_isdigit(c)) {
234 c -= '0';
235 if (lj_char_isdigit(cp_get(cp))) {
236 c = c*8 + (cp->c - '0');
237 if (lj_char_isdigit(cp_get(cp))) {
238 c = c*8 + (cp->c - '0');
239 cp_get(cp);
242 cp_save(cp, (c & 0xff));
243 continue;
245 break;
248 cp_save(cp, c);
249 cp_get(cp);
251 cp_get(cp);
252 if (delim == '"') {
253 cp->str = lj_buf_str(cp->L, &cp->sb);
254 return CTOK_STRING;
255 } else {
256 if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
257 cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
258 cp->val.id = CTID_INT32;
259 return CTOK_INTEGER;
263 /* Skip C comment. */
264 static void cp_comment_c(CPState *cp)
266 do {
267 if (cp_get(cp) == '*') {
268 do {
269 if (cp_get(cp) == '/') { cp_get(cp); return; }
270 } while (cp->c == '*');
272 if (cp_iseol(cp->c)) cp_newline(cp);
273 } while (cp->c != '\0');
276 /* Skip C++ comment. */
277 static void cp_comment_cpp(CPState *cp)
279 while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
283 /* Lexical scanner for C. Only a minimal subset is implemented. */
284 static CPToken cp_next_(CPState *cp)
286 lj_buf_reset(&cp->sb);
287 for (;;) {
288 if (lj_char_isident(cp->c))
289 return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
290 switch (cp->c) {
291 case '\n': case '\r': cp_newline(cp); /* fallthrough. */
292 case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
293 case '"': case '\'': return cp_string(cp);
294 case '/':
295 if (cp_get(cp) == '*') cp_comment_c(cp);
296 else if (cp->c == '/') cp_comment_cpp(cp);
297 else return '/';
298 break;
299 case '|':
300 if (cp_get(cp) != '|') return '|'; cp_get(cp); return CTOK_OROR;
301 case '&':
302 if (cp_get(cp) != '&') return '&'; cp_get(cp); return CTOK_ANDAND;
303 case '=':
304 if (cp_get(cp) != '=') return '='; cp_get(cp); return CTOK_EQ;
305 case '!':
306 if (cp_get(cp) != '=') return '!'; cp_get(cp); return CTOK_NE;
307 case '<':
308 if (cp_get(cp) == '=') { cp_get(cp); return CTOK_LE; }
309 else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
310 return '<';
311 case '>':
312 if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; }
313 else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
314 return '>';
315 case '-':
316 if (cp_get(cp) != '>') return '-'; cp_get(cp); return CTOK_DEREF;
317 case '$':
318 return cp_param(cp);
319 case '\0': return CTOK_EOF;
320 default: { CPToken c = cp->c; cp_get(cp); return c; }
325 static LJ_NOINLINE CPToken cp_next(CPState *cp)
327 return (cp->tok = cp_next_(cp));
330 /* -- C parser ------------------------------------------------------------ */
332 /* Namespaces for resolving identifiers. */
333 #define CPNS_DEFAULT \
334 ((1u<<CT_KW)|(1u<<CT_TYPEDEF)|(1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
335 #define CPNS_STRUCT ((1u<<CT_KW)|(1u<<CT_STRUCT)|(1u<<CT_ENUM))
337 typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
338 typedef uint32_t CPscl; /* Storage class flags. */
340 /* Type declaration context. */
341 typedef struct CPDecl {
342 CPDeclIdx top; /* Top of declaration stack. */
343 CPDeclIdx pos; /* Insertion position in declaration chain. */
344 CPDeclIdx specpos; /* Saved position for declaration specifier. */
345 uint32_t mode; /* Declarator mode. */
346 CPState *cp; /* C parser state. */
347 GCstr *name; /* Name of declared identifier (if direct). */
348 GCstr *redir; /* Redirected symbol name. */
349 CTypeID nameid; /* Existing typedef for declared identifier. */
350 CTInfo attr; /* Attributes. */
351 CTInfo fattr; /* Function attributes. */
352 CTInfo specattr; /* Saved attributes. */
353 CTInfo specfattr; /* Saved function attributes. */
354 CTSize bits; /* Field size in bits (if any). */
355 CType stack[CPARSE_MAX_DECLSTACK]; /* Type declaration stack. */
356 } CPDecl;
358 /* Forward declarations. */
359 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
360 static void cp_declarator(CPState *cp, CPDecl *decl);
361 static CTypeID cp_decl_abstract(CPState *cp);
363 /* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
364 static void cp_init(CPState *cp)
366 cp->linenumber = 1;
367 cp->depth = 0;
368 cp->curpack = 0;
369 cp->packstack[0] = 255;
370 lj_buf_init(cp->L, &cp->sb);
371 lua_assert(cp->p != NULL);
372 cp_get(cp); /* Read-ahead first char. */
373 cp->tok = 0;
374 cp->tmask = CPNS_DEFAULT;
375 cp_next(cp); /* Read-ahead first token. */
378 /* Cleanup C parser state. */
379 static void cp_cleanup(CPState *cp)
381 global_State *g = G(cp->L);
382 lj_buf_free(g, &cp->sb);
385 /* Check and consume optional token. */
386 static int cp_opt(CPState *cp, CPToken tok)
388 if (cp->tok == tok) { cp_next(cp); return 1; }
389 return 0;
392 /* Check and consume token. */
393 static void cp_check(CPState *cp, CPToken tok)
395 if (cp->tok != tok) cp_err_token(cp, tok);
396 cp_next(cp);
399 /* Check if the next token may start a type declaration. */
400 static int cp_istypedecl(CPState *cp)
402 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
403 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
404 if (cp->tok == '$') return 1;
405 return 0;
408 /* -- Constant expression evaluator --------------------------------------- */
410 /* Forward declarations. */
411 static void cp_expr_unary(CPState *cp, CPValue *k);
412 static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
414 /* Please note that type handling is very weak here. Most ops simply
415 ** assume integer operands. Accessors are only needed to compute types and
416 ** return synthetic values. The only purpose of the expression evaluator
417 ** is to compute the values of constant expressions one would typically
418 ** find in C header files. And again: this is NOT a validating C parser!
421 /* Parse comma separated expression and return last result. */
422 static void cp_expr_comma(CPState *cp, CPValue *k)
424 do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
427 /* Parse sizeof/alignof operator. */
428 static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
430 CTSize sz;
431 CTInfo info;
432 if (cp_opt(cp, '(')) {
433 if (cp_istypedecl(cp))
434 k->id = cp_decl_abstract(cp);
435 else
436 cp_expr_comma(cp, k);
437 cp_check(cp, ')');
438 } else {
439 cp_expr_unary(cp, k);
441 info = lj_ctype_info(cp->cts, k->id, &sz);
442 if (wantsz) {
443 if (sz != CTSIZE_INVALID)
444 k->u32 = sz;
445 else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
446 cp_err(cp, LJ_ERR_FFI_INVSIZE);
447 } else {
448 k->u32 = 1u << ctype_align(info);
450 k->id = CTID_UINT32; /* Really size_t. */
453 /* Parse prefix operators. */
454 static void cp_expr_prefix(CPState *cp, CPValue *k)
456 if (cp->tok == CTOK_INTEGER) {
457 *k = cp->val; cp_next(cp);
458 } else if (cp_opt(cp, '+')) {
459 cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
460 } else if (cp_opt(cp, '-')) {
461 cp_expr_unary(cp, k); k->i32 = -k->i32;
462 } else if (cp_opt(cp, '~')) {
463 cp_expr_unary(cp, k); k->i32 = ~k->i32;
464 } else if (cp_opt(cp, '!')) {
465 cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
466 } else if (cp_opt(cp, '(')) {
467 if (cp_istypedecl(cp)) { /* Cast operator. */
468 CTypeID id = cp_decl_abstract(cp);
469 cp_check(cp, ')');
470 cp_expr_unary(cp, k);
471 k->id = id; /* No conversion performed. */
472 } else { /* Sub-expression. */
473 cp_expr_comma(cp, k);
474 cp_check(cp, ')');
476 } else if (cp_opt(cp, '*')) { /* Indirection. */
477 CType *ct;
478 cp_expr_unary(cp, k);
479 ct = lj_ctype_rawref(cp->cts, k->id);
480 if (!ctype_ispointer(ct->info))
481 cp_err_badidx(cp, ct);
482 k->u32 = 0; k->id = ctype_cid(ct->info);
483 } else if (cp_opt(cp, '&')) { /* Address operator. */
484 cp_expr_unary(cp, k);
485 k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
486 CTSIZE_PTR);
487 } else if (cp_opt(cp, CTOK_SIZEOF)) {
488 cp_expr_sizeof(cp, k, 1);
489 } else if (cp_opt(cp, CTOK_ALIGNOF)) {
490 cp_expr_sizeof(cp, k, 0);
491 } else if (cp->tok == CTOK_IDENT) {
492 if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
493 k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
494 } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
495 k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
496 } else if (ctype_type(cp->ct->info) == CT_FUNC) {
497 k->u32 = cp->val.id; k->id = cp->val.id;
498 } else {
499 goto err_expr;
501 cp_next(cp);
502 } else if (cp->tok == CTOK_STRING) {
503 CTSize sz = cp->str->len;
504 while (cp_next(cp) == CTOK_STRING)
505 sz += cp->str->len;
506 k->u32 = sz + 1;
507 k->id = CTID_A_CCHAR;
508 } else {
509 err_expr:
510 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
514 /* Parse postfix operators. */
515 static void cp_expr_postfix(CPState *cp, CPValue *k)
517 for (;;) {
518 CType *ct;
519 if (cp_opt(cp, '[')) { /* Array/pointer index. */
520 CPValue k2;
521 cp_expr_comma(cp, &k2);
522 ct = lj_ctype_rawref(cp->cts, k->id);
523 if (!ctype_ispointer(ct->info)) {
524 ct = lj_ctype_rawref(cp->cts, k2.id);
525 if (!ctype_ispointer(ct->info))
526 cp_err_badidx(cp, ct);
528 cp_check(cp, ']');
529 k->u32 = 0;
530 } else if (cp->tok == '.' || cp->tok == CTOK_DEREF) { /* Struct deref. */
531 CTSize ofs;
532 CType *fct;
533 ct = lj_ctype_rawref(cp->cts, k->id);
534 if (cp->tok == CTOK_DEREF) {
535 if (!ctype_ispointer(ct->info))
536 cp_err_badidx(cp, ct);
537 ct = lj_ctype_rawref(cp->cts, ctype_cid(ct->info));
539 cp_next(cp);
540 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
541 if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
542 !(fct = lj_ctype_getfield(cp->cts, ct, cp->str, &ofs)) ||
543 ctype_isbitfield(fct->info)) {
544 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
545 cp_errmsg(cp, 0, LJ_ERR_FFI_BADMEMBER, strdata(s), strdata(cp->str));
547 ct = fct;
548 k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
549 cp_next(cp);
550 } else {
551 return;
553 k->id = ctype_cid(ct->info);
557 /* Parse infix operators. */
558 static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
560 CPValue k2;
561 k2.u32 = 0; k2.id = 0; /* Silence the compiler. */
562 for (;;) {
563 switch (pri) {
564 case 0:
565 if (cp_opt(cp, '?')) {
566 CPValue k3;
567 cp_expr_comma(cp, &k2); /* Right-associative. */
568 cp_check(cp, ':');
569 cp_expr_sub(cp, &k3, 0);
570 k->u32 = k->u32 ? k2.u32 : k3.u32;
571 k->id = k2.id > k3.id ? k2.id : k3.id;
572 continue;
574 case 1:
575 if (cp_opt(cp, CTOK_OROR)) {
576 cp_expr_sub(cp, &k2, 2); k->i32 = k->u32 || k2.u32; k->id = CTID_INT32;
577 continue;
579 case 2:
580 if (cp_opt(cp, CTOK_ANDAND)) {
581 cp_expr_sub(cp, &k2, 3); k->i32 = k->u32 && k2.u32; k->id = CTID_INT32;
582 continue;
584 case 3:
585 if (cp_opt(cp, '|')) {
586 cp_expr_sub(cp, &k2, 4); k->u32 = k->u32 | k2.u32; goto arith_result;
588 case 4:
589 if (cp_opt(cp, '^')) {
590 cp_expr_sub(cp, &k2, 5); k->u32 = k->u32 ^ k2.u32; goto arith_result;
592 case 5:
593 if (cp_opt(cp, '&')) {
594 cp_expr_sub(cp, &k2, 6); k->u32 = k->u32 & k2.u32; goto arith_result;
596 case 6:
597 if (cp_opt(cp, CTOK_EQ)) {
598 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 == k2.u32; k->id = CTID_INT32;
599 continue;
600 } else if (cp_opt(cp, CTOK_NE)) {
601 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 != k2.u32; k->id = CTID_INT32;
602 continue;
604 case 7:
605 if (cp_opt(cp, '<')) {
606 cp_expr_sub(cp, &k2, 8);
607 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
608 k->i32 = k->i32 < k2.i32;
609 else
610 k->i32 = k->u32 < k2.u32;
611 k->id = CTID_INT32;
612 continue;
613 } else if (cp_opt(cp, '>')) {
614 cp_expr_sub(cp, &k2, 8);
615 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
616 k->i32 = k->i32 > k2.i32;
617 else
618 k->i32 = k->u32 > k2.u32;
619 k->id = CTID_INT32;
620 continue;
621 } else if (cp_opt(cp, CTOK_LE)) {
622 cp_expr_sub(cp, &k2, 8);
623 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
624 k->i32 = k->i32 <= k2.i32;
625 else
626 k->i32 = k->u32 <= k2.u32;
627 k->id = CTID_INT32;
628 continue;
629 } else if (cp_opt(cp, CTOK_GE)) {
630 cp_expr_sub(cp, &k2, 8);
631 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
632 k->i32 = k->i32 >= k2.i32;
633 else
634 k->i32 = k->u32 >= k2.u32;
635 k->id = CTID_INT32;
636 continue;
638 case 8:
639 if (cp_opt(cp, CTOK_SHL)) {
640 cp_expr_sub(cp, &k2, 9); k->u32 = k->u32 << k2.u32;
641 continue;
642 } else if (cp_opt(cp, CTOK_SHR)) {
643 cp_expr_sub(cp, &k2, 9);
644 if (k->id == CTID_INT32)
645 k->i32 = k->i32 >> k2.i32;
646 else
647 k->u32 = k->u32 >> k2.u32;
648 continue;
650 case 9:
651 if (cp_opt(cp, '+')) {
652 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 + k2.u32;
653 arith_result:
654 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
655 continue;
656 } else if (cp_opt(cp, '-')) {
657 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 - k2.u32; goto arith_result;
659 case 10:
660 if (cp_opt(cp, '*')) {
661 cp_expr_unary(cp, &k2); k->u32 = k->u32 * k2.u32; goto arith_result;
662 } else if (cp_opt(cp, '/')) {
663 cp_expr_unary(cp, &k2);
664 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
665 if (k2.u32 == 0 ||
666 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
667 cp_err(cp, LJ_ERR_BADVAL);
668 if (k->id == CTID_INT32)
669 k->i32 = k->i32 / k2.i32;
670 else
671 k->u32 = k->u32 / k2.u32;
672 continue;
673 } else if (cp_opt(cp, '%')) {
674 cp_expr_unary(cp, &k2);
675 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
676 if (k2.u32 == 0 ||
677 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
678 cp_err(cp, LJ_ERR_BADVAL);
679 if (k->id == CTID_INT32)
680 k->i32 = k->i32 % k2.i32;
681 else
682 k->u32 = k->u32 % k2.u32;
683 continue;
685 default:
686 return;
691 /* Parse and evaluate unary expression. */
692 static void cp_expr_unary(CPState *cp, CPValue *k)
694 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
695 cp_expr_prefix(cp, k);
696 cp_expr_postfix(cp, k);
697 cp->depth--;
700 /* Parse and evaluate sub-expression. */
701 static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
703 cp_expr_unary(cp, k);
704 cp_expr_infix(cp, k, pri);
707 /* Parse constant integer expression. */
708 static void cp_expr_kint(CPState *cp, CPValue *k)
710 CType *ct;
711 cp_expr_sub(cp, k, 0);
712 ct = ctype_raw(cp->cts, k->id);
713 if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
716 /* Parse (non-negative) size expression. */
717 static CTSize cp_expr_ksize(CPState *cp)
719 CPValue k;
720 cp_expr_kint(cp, &k);
721 if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
722 return k.u32;
725 /* -- Type declaration stack management ----------------------------------- */
727 /* Add declaration element behind the insertion position. */
728 static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
730 CPDeclIdx top = decl->top;
731 if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
732 decl->stack[top].info = info;
733 decl->stack[top].size = size;
734 decl->stack[top].sib = 0;
735 setgcrefnull(decl->stack[top].name);
736 decl->stack[top].next = decl->stack[decl->pos].next;
737 decl->stack[decl->pos].next = (CTypeID1)top;
738 decl->top = top+1;
739 return top;
742 /* Push declaration element before the insertion position. */
743 static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
745 return (decl->pos = cp_add(decl, info, size));
748 /* Push or merge attributes. */
749 static void cp_push_attributes(CPDecl *decl)
751 CType *ct = &decl->stack[decl->pos];
752 if (ctype_isfunc(ct->info)) { /* Ok to modify in-place. */
753 #if LJ_TARGET_X86
754 if ((decl->fattr & CTFP_CCONV))
755 ct->info = (ct->info & (CTMASK_NUM|CTF_VARARG|CTMASK_CID)) +
756 (decl->fattr & ~CTMASK_CID);
757 #endif
758 } else {
759 if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
760 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
761 ctype_align(decl->attr));
765 /* Push unrolled type to declaration stack and merge qualifiers. */
766 static void cp_push_type(CPDecl *decl, CTypeID id)
768 CType *ct = ctype_get(decl->cp->cts, id);
769 CTInfo info = ct->info;
770 CTSize size = ct->size;
771 switch (ctype_type(info)) {
772 case CT_STRUCT: case CT_ENUM:
773 cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
774 if ((decl->attr & CTF_QUAL)) { /* Push unmerged qualifiers. */
775 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
776 (decl->attr & CTF_QUAL));
777 decl->attr &= ~CTF_QUAL;
779 break;
780 case CT_ATTRIB:
781 if (ctype_isxattrib(info, CTA_QUAL))
782 decl->attr &= ~size; /* Remove redundant qualifiers. */
783 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
784 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
785 break;
786 case CT_ARRAY:
787 if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) {
788 info |= (decl->attr & CTF_QUAL);
789 decl->attr &= ~CTF_QUAL;
791 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
792 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
793 decl->stack[decl->pos].sib = 1; /* Mark as already checked and sized. */
794 /* Note: this is not copied to the ct->sib in the C type table. */
795 break;
796 case CT_FUNC:
797 /* Copy type, link parameters (shared). */
798 decl->stack[cp_push(decl, info, size)].sib = ct->sib;
799 break;
800 default:
801 /* Copy type, merge common qualifiers. */
802 cp_push(decl, info|(decl->attr & CTF_QUAL), size);
803 decl->attr &= ~CTF_QUAL;
804 break;
808 /* Consume the declaration element chain and intern the C type. */
809 static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
811 CTypeID id = 0;
812 CPDeclIdx idx = 0;
813 CTSize csize = CTSIZE_INVALID;
814 CTSize cinfo = 0;
815 do {
816 CType *ct = &decl->stack[idx];
817 CTInfo info = ct->info;
818 CTInfo size = ct->size;
819 /* The cid is already part of info for copies of pointers/functions. */
820 idx = ct->next;
821 if (ctype_istypedef(info)) {
822 lua_assert(id == 0);
823 id = ctype_cid(info);
824 /* Always refetch info/size, since struct/enum may have been completed. */
825 cinfo = ctype_get(cp->cts, id)->info;
826 csize = ctype_get(cp->cts, id)->size;
827 lua_assert(ctype_isstruct(cinfo) || ctype_isenum(cinfo));
828 } else if (ctype_isfunc(info)) { /* Intern function. */
829 CType *fct;
830 CTypeID fid;
831 CTypeID sib;
832 if (id) {
833 CType *refct = ctype_raw(cp->cts, id);
834 /* Reject function or refarray return types. */
835 if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
836 cp_err(cp, LJ_ERR_FFI_INVTYPE);
838 /* No intervening attributes allowed, skip forward. */
839 while (idx) {
840 CType *ctn = &decl->stack[idx];
841 if (!ctype_isattrib(ctn->info)) break;
842 idx = ctn->next; /* Skip attribute. */
844 sib = ct->sib; /* Next line may reallocate the C type table. */
845 fid = lj_ctype_new(cp->cts, &fct);
846 csize = CTSIZE_INVALID;
847 fct->info = cinfo = info + id;
848 fct->size = size;
849 fct->sib = sib;
850 id = fid;
851 } else if (ctype_isattrib(info)) {
852 if (ctype_isxattrib(info, CTA_QUAL))
853 cinfo |= size;
854 else if (ctype_isxattrib(info, CTA_ALIGN))
855 CTF_INSERT(cinfo, ALIGN, size);
856 id = lj_ctype_intern(cp->cts, info+id, size);
857 /* Inherit csize/cinfo from original type. */
858 } else {
859 if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */
860 lua_assert(id == 0);
861 if (!(info & CTF_BOOL)) {
862 CTSize msize = ctype_msizeP(decl->attr);
863 CTSize vsize = ctype_vsizeP(decl->attr);
864 if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8))) {
865 CTSize malign = lj_fls(msize);
866 if (malign > 4) malign = 4; /* Limit alignment. */
867 CTF_INSERT(info, ALIGN, malign);
868 size = msize; /* Override size via mode. */
870 if (vsize) { /* Vector size set? */
871 CTSize esize = lj_fls(size);
872 if (vsize >= esize) {
873 /* Intern the element type first. */
874 id = lj_ctype_intern(cp->cts, info, size);
875 /* Then create a vector (array) with vsize alignment. */
876 size = (1u << vsize);
877 if (vsize > 4) vsize = 4; /* Limit alignment. */
878 if (ctype_align(info) > vsize) vsize = ctype_align(info);
879 info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
880 CTALIGN(vsize));
884 } else if (ctype_isptr(info)) {
885 /* Reject pointer/ref to ref. */
886 if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
887 cp_err(cp, LJ_ERR_FFI_INVTYPE);
888 if (ctype_isref(info)) {
889 info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
890 /* No intervening attributes allowed, skip forward. */
891 while (idx) {
892 CType *ctn = &decl->stack[idx];
893 if (!ctype_isattrib(ctn->info)) break;
894 idx = ctn->next; /* Skip attribute. */
897 } else if (ctype_isarray(info)) { /* Check for valid array size etc. */
898 if (ct->sib == 0) { /* Only check/size arrays not copied by unroll. */
899 if (ctype_isref(cinfo)) /* Reject arrays of refs. */
900 cp_err(cp, LJ_ERR_FFI_INVTYPE);
901 /* Reject VLS or unknown-sized types. */
902 if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
903 cp_err(cp, LJ_ERR_FFI_INVSIZE);
904 /* a[] and a[?] keep their invalid size. */
905 if (size != CTSIZE_INVALID) {
906 uint64_t xsz = (uint64_t)size * csize;
907 if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
908 size = (CTSize)xsz;
911 if ((cinfo & CTF_ALIGN) > (info & CTF_ALIGN)) /* Find max. align. */
912 info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN);
913 info |= (cinfo & CTF_QUAL); /* Inherit qual. */
914 } else {
915 lua_assert(ctype_isvoid(info));
917 csize = size;
918 cinfo = info+id;
919 id = lj_ctype_intern(cp->cts, info+id, size);
921 } while (idx);
922 return id;
925 /* -- C declaration parser ------------------------------------------------ */
927 #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
929 /* Reset declaration state to declaration specifier. */
930 static void cp_decl_reset(CPDecl *decl)
932 decl->pos = decl->specpos;
933 decl->top = decl->specpos+1;
934 decl->stack[decl->specpos].next = 0;
935 decl->attr = decl->specattr;
936 decl->fattr = decl->specfattr;
937 decl->name = NULL;
938 decl->redir = NULL;
941 /* Parse constant initializer. */
942 /* NYI: FP constants and strings as initializers. */
943 static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
945 CType *ctt = ctype_get(cp->cts, ctypeid);
946 CTInfo info;
947 CTSize size;
948 CPValue k;
949 CTypeID constid;
950 while (ctype_isattrib(ctt->info)) { /* Skip attributes. */
951 ctypeid = ctype_cid(ctt->info); /* Update ID, too. */
952 ctt = ctype_get(cp->cts, ctypeid);
954 info = ctt->info;
955 size = ctt->size;
956 if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
957 cp_err(cp, LJ_ERR_FFI_INVTYPE);
958 cp_check(cp, '=');
959 cp_expr_sub(cp, &k, 0);
960 constid = lj_ctype_new(cp->cts, ctp);
961 (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
962 k.u32 <<= 8*(4-size);
963 if ((info & CTF_UNSIGNED))
964 k.u32 >>= 8*(4-size);
965 else
966 k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
967 (*ctp)->size = k.u32;
968 return constid;
971 /* Parse size in parentheses as part of attribute. */
972 static CTSize cp_decl_sizeattr(CPState *cp)
974 CTSize sz;
975 uint32_t oldtmask = cp->tmask;
976 cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
977 cp_check(cp, '(');
978 sz = cp_expr_ksize(cp);
979 cp->tmask = oldtmask;
980 cp_check(cp, ')');
981 return sz;
984 /* Parse alignment attribute. */
985 static void cp_decl_align(CPState *cp, CPDecl *decl)
987 CTSize al = 4; /* Unspecified alignment is 16 bytes. */
988 if (cp->tok == '(') {
989 al = cp_decl_sizeattr(cp);
990 al = al ? lj_fls(al) : 0;
992 CTF_INSERT(decl->attr, ALIGN, al);
993 decl->attr |= CTFP_ALIGNED;
996 /* Parse GCC asm("name") redirect. */
997 static void cp_decl_asm(CPState *cp, CPDecl *decl)
999 UNUSED(decl);
1000 cp_next(cp);
1001 cp_check(cp, '(');
1002 if (cp->tok == CTOK_STRING) {
1003 GCstr *str = cp->str;
1004 while (cp_next(cp) == CTOK_STRING) {
1005 lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str));
1006 cp->L->top--;
1007 str = strV(cp->L->top);
1009 decl->redir = str;
1011 cp_check(cp, ')');
1014 /* Parse GCC __attribute__((mode(...))). */
1015 static void cp_decl_mode(CPState *cp, CPDecl *decl)
1017 cp_check(cp, '(');
1018 if (cp->tok == CTOK_IDENT) {
1019 const char *s = strdata(cp->str);
1020 CTSize sz = 0, vlen = 0;
1021 if (s[0] == '_' && s[1] == '_') s += 2;
1022 if (*s == 'V') {
1023 s++;
1024 vlen = *s++ - '0';
1025 if (*s >= '0' && *s <= '9')
1026 vlen = vlen*10 + (*s++ - '0');
1028 switch (*s++) {
1029 case 'Q': sz = 1; break;
1030 case 'H': sz = 2; break;
1031 case 'S': sz = 4; break;
1032 case 'D': sz = 8; break;
1033 case 'T': sz = 16; break;
1034 case 'O': sz = 32; break;
1035 default: goto bad_size;
1037 if (*s == 'I' || *s == 'F') {
1038 CTF_INSERT(decl->attr, MSIZEP, sz);
1039 if (vlen) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vlen*sz));
1041 bad_size:
1042 cp_next(cp);
1044 cp_check(cp, ')');
1047 /* Parse GCC __attribute__((...)). */
1048 static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
1050 cp_next(cp);
1051 cp_check(cp, '(');
1052 cp_check(cp, '(');
1053 while (cp->tok != ')') {
1054 if (cp->tok == CTOK_IDENT) {
1055 GCstr *attrstr = cp->str;
1056 cp_next(cp);
1057 switch (attrstr->hash) {
1058 case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */
1059 cp_decl_align(cp, decl);
1060 break;
1061 case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */
1062 decl->attr |= CTFP_PACKED;
1063 break;
1064 case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */
1065 cp_decl_mode(cp, decl);
1066 break;
1067 case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */
1069 CTSize vsize = cp_decl_sizeattr(cp);
1070 if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
1072 break;
1073 #if LJ_TARGET_X86
1074 case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */
1075 CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1076 decl->fattr |= CTFP_CCONV;
1077 break;
1078 case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */
1079 CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1080 decl->fattr |= CTFP_CCONV;
1081 break;
1082 case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */
1083 CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1084 decl->fattr |= CTFP_CCONV;
1085 break;
1086 case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */
1087 CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1088 decl->fattr |= CTFP_CCONV;
1089 break;
1090 case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */
1091 CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1092 decl->fattr |= CTFP_CCONV;
1093 break;
1094 case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */
1095 decl->fattr |= CTF_SSEREGPARM;
1096 decl->fattr |= CTFP_CCONV;
1097 break;
1098 #endif
1099 default: /* Skip all other attributes. */
1100 goto skip_attr;
1102 } else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
1103 cp_next(cp);
1104 skip_attr:
1105 if (cp_opt(cp, '(')) {
1106 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1107 cp_check(cp, ')');
1109 } else {
1110 break;
1112 if (!cp_opt(cp, ',')) break;
1114 cp_check(cp, ')');
1115 cp_check(cp, ')');
1118 /* Parse MSVC __declspec(...). */
1119 static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
1121 cp_next(cp);
1122 cp_check(cp, '(');
1123 while (cp->tok == CTOK_IDENT) {
1124 GCstr *attrstr = cp->str;
1125 cp_next(cp);
1126 switch (attrstr->hash) {
1127 case H_(bc2395fa,98f267f8): /* align */
1128 cp_decl_align(cp, decl);
1129 break;
1130 default: /* Ignore all other attributes. */
1131 if (cp_opt(cp, '(')) {
1132 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1133 cp_check(cp, ')');
1135 break;
1138 cp_check(cp, ')');
1141 /* Parse declaration attributes (and common qualifiers). */
1142 static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1144 for (;;) {
1145 switch (cp->tok) {
1146 case CTOK_CONST: decl->attr |= CTF_CONST; break;
1147 case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
1148 case CTOK_RESTRICT: break; /* Ignore. */
1149 case CTOK_EXTENSION: break; /* Ignore. */
1150 case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
1151 case CTOK_ASM: cp_decl_asm(cp, decl); continue;
1152 case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
1153 case CTOK_CCDECL:
1154 #if LJ_TARGET_X86
1155 CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1156 decl->fattr |= CTFP_CCONV;
1157 #endif
1158 break;
1159 case CTOK_PTRSZ:
1160 #if LJ_64
1161 CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
1162 #endif
1163 break;
1164 default: return;
1166 cp_next(cp);
1170 /* Parse struct/union/enum name. */
1171 static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
1173 CTypeID sid;
1174 CType *ct;
1175 cp->tmask = CPNS_STRUCT;
1176 cp_next(cp);
1177 cp_decl_attributes(cp, sdecl);
1178 cp->tmask = CPNS_DEFAULT;
1179 if (cp->tok != '{') {
1180 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1181 if (cp->val.id) { /* Name of existing struct/union/enum. */
1182 sid = cp->val.id;
1183 ct = cp->ct;
1184 if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION)) /* Wrong type. */
1185 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1186 } else { /* Create named, incomplete struct/union/enum. */
1187 if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
1188 cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
1189 sid = lj_ctype_new(cp->cts, &ct);
1190 ct->info = info;
1191 ct->size = CTSIZE_INVALID;
1192 ctype_setname(ct, cp->str);
1193 lj_ctype_addname(cp->cts, ct, sid);
1195 cp_next(cp);
1196 } else { /* Create anonymous, incomplete struct/union/enum. */
1197 sid = lj_ctype_new(cp->cts, &ct);
1198 ct->info = info;
1199 ct->size = CTSIZE_INVALID;
1201 if (cp->tok == '{') {
1202 if (ct->size != CTSIZE_INVALID || ct->sib)
1203 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1204 ct->sib = 1; /* Indicate the type is currently being defined. */
1206 return sid;
1209 /* Determine field alignment. */
1210 static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
1212 CTSize align = ctype_align(info);
1213 UNUSED(cp); UNUSED(ct);
1214 #if (LJ_TARGET_X86 && !LJ_ABI_WIN) || (LJ_TARGET_ARM && __APPLE__)
1215 /* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
1216 if (align > 2 && !(info & CTFP_ALIGNED)) {
1217 if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
1218 do {
1219 ct = ctype_rawchild(cp->cts, ct);
1220 info = ct->info;
1221 } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1223 if (ctype_isnum(info) || ctype_isenum(info))
1224 align = 2;
1226 #endif
1227 return align;
1230 /* Layout struct/union fields. */
1231 static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1233 CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
1234 CTSize maxalign = ctype_align(sattr);
1235 CType *sct = ctype_get(cp->cts, sid);
1236 CTInfo sinfo = sct->info;
1237 CTypeID fieldid = sct->sib;
1238 while (fieldid) {
1239 CType *ct = ctype_get(cp->cts, fieldid);
1240 CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
1242 if (ctype_isfield(ct->info) ||
1243 (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
1244 CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
1245 CTSize sz;
1246 CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
1247 CTSize bsz, csz = 8*sz; /* Field size and container size (in bits). */
1248 sinfo |= (info & (CTF_QUAL|CTF_VLA)); /* Merge pseudo-qualifiers. */
1250 /* Check for size overflow and determine alignment. */
1251 if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA)) {
1252 if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
1253 !(sinfo & CTF_UNION)))
1254 cp_err(cp, LJ_ERR_FFI_INVSIZE);
1255 csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
1257 align = cp_field_align(cp, ct, info);
1258 if (((attr|sattr) & CTFP_PACKED) ||
1259 ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
1260 align = ctype_align(attr);
1261 if (cp->packstack[cp->curpack] < align)
1262 align = cp->packstack[cp->curpack];
1263 if (align > maxalign) maxalign = align;
1264 amask = (8u << align) - 1;
1266 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1267 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1268 bsz = csz; /* Regular fields or subtypes always fill the container. */
1269 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1270 ct->size = (bofs >> 3); /* Store field offset. */
1271 } else { /* Bitfield. */
1272 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
1273 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
1274 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1276 /* Prefer regular field over bitfield. */
1277 if (bsz == csz && (bofs & amask) == 0) {
1278 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
1279 ct->size = (bofs >> 3); /* Store field offset. */
1280 } else {
1281 ct->info = CTINFO(CT_BITFIELD,
1282 (info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
1283 (csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
1284 #if LJ_BE
1285 ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
1286 #else
1287 ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
1288 #endif
1289 ct->size = ((bofs & ~(csz-1)) >> 3); /* Store container offset. */
1293 /* Determine next offset or max. offset. */
1294 if ((sinfo & CTF_UNION)) {
1295 if (bsz > bmaxofs) bmaxofs = bsz;
1296 } else {
1297 bofs += bsz;
1299 } /* All other fields in the chain are already set up. */
1301 fieldid = ct->sib;
1304 /* Complete struct/union. */
1305 sct->info = sinfo + CTALIGN(maxalign);
1306 bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
1307 maxalign = (8u << maxalign) - 1;
1308 sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
1311 /* Parse struct/union declaration. */
1312 static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
1314 CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
1315 if (cp_opt(cp, '{')) { /* Struct/union definition. */
1316 CTypeID lastid = sid;
1317 int lastdecl = 0;
1318 while (cp->tok != '}') {
1319 CPDecl decl;
1320 CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
1321 decl.mode = scl ? CPARSE_MODE_DIRECT :
1322 CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
1324 for (;;) {
1325 CTypeID ctypeid;
1327 if (lastdecl) cp_err_token(cp, '}');
1329 /* Parse field declarator. */
1330 decl.bits = CTSIZE_INVALID;
1331 cp_declarator(cp, &decl);
1332 ctypeid = cp_decl_intern(cp, &decl);
1334 if ((scl & CDF_STATIC)) { /* Static constant in struct namespace. */
1335 CType *ct;
1336 CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
1337 ctype_get(cp->cts, lastid)->sib = fieldid;
1338 lastid = fieldid;
1339 ctype_setname(ct, decl.name);
1340 } else {
1341 CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
1342 CType *ct;
1343 CTypeID fieldid = lj_ctype_new(cp->cts, &ct); /* Do this first. */
1344 CType *tct = ctype_raw(cp->cts, ctypeid);
1346 if (decl.bits == CTSIZE_INVALID) { /* Regular field. */
1347 if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
1348 lastdecl = 1; /* a[] or a[?] must be the last declared field. */
1350 /* Accept transparent struct/union/enum. */
1351 if (!decl.name) {
1352 if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
1353 ctype_isenum(tct->info)))
1354 cp_err_token(cp, CTOK_IDENT);
1355 ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
1356 ct->size = ctype_isstruct(tct->info) ?
1357 (decl.attr|0x80000000u) : 0; /* For layout phase. */
1358 goto add_field;
1360 } else { /* Bitfield. */
1361 bsz = decl.bits;
1362 if (!ctype_isinteger_or_bool(tct->info) ||
1363 (bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
1364 bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
1365 cp_errmsg(cp, ':', LJ_ERR_BADVAL);
1368 /* Create temporary field for layout phase. */
1369 ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
1370 ct->size = decl.attr;
1371 if (decl.name) ctype_setname(ct, decl.name);
1373 add_field:
1374 ctype_get(cp->cts, lastid)->sib = fieldid;
1375 lastid = fieldid;
1377 if (!cp_opt(cp, ',')) break;
1378 cp_decl_reset(&decl);
1380 cp_check(cp, ';');
1382 cp_check(cp, '}');
1383 ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
1384 cp_decl_attributes(cp, sdecl); /* Layout phase needs postfix attributes. */
1385 cp_struct_layout(cp, sid, sdecl->attr);
1387 return sid;
1390 /* Parse enum declaration. */
1391 static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
1393 CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
1394 CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
1395 CTSize esize = 4; /* Only 32 bit enums are supported. */
1396 if (cp_opt(cp, '{')) { /* Enum definition. */
1397 CPValue k;
1398 CTypeID lastid = eid;
1399 k.u32 = 0;
1400 k.id = CTID_INT32;
1401 do {
1402 GCstr *name = cp->str;
1403 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1404 if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
1405 cp_next(cp);
1406 if (cp_opt(cp, '=')) {
1407 cp_expr_kint(cp, &k);
1408 if (k.id == CTID_UINT32) {
1409 /* C99 says that enum constants are always (signed) integers.
1410 ** But since unsigned constants like 0x80000000 are quite common,
1411 ** those are left as uint32_t.
1413 if (k.i32 >= 0) k.id = CTID_INT32;
1414 } else {
1415 /* OTOH it's common practice and even mandated by some ABIs
1416 ** that the enum type itself is unsigned, unless there are any
1417 ** negative constants.
1419 k.id = CTID_INT32;
1420 if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
1423 /* Add named enum constant. */
1425 CType *ct;
1426 CTypeID constid = lj_ctype_new(cp->cts, &ct);
1427 ctype_get(cp->cts, lastid)->sib = constid;
1428 lastid = constid;
1429 ctype_setname(ct, name);
1430 ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
1431 ct->size = k.u32++;
1432 if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
1433 lj_ctype_addname(cp->cts, ct, constid);
1435 if (!cp_opt(cp, ',')) break;
1436 } while (cp->tok != '}'); /* Trailing ',' is ok. */
1437 cp_check(cp, '}');
1438 /* Complete enum. */
1439 ctype_get(cp->cts, eid)->info = einfo;
1440 ctype_get(cp->cts, eid)->size = esize;
1442 return eid;
1445 /* Parse declaration specifiers. */
1446 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1448 uint32_t cds = 0, sz = 0;
1449 CTypeID tdef = 0;
1451 decl->cp = cp;
1452 decl->mode = cp->mode;
1453 decl->name = NULL;
1454 decl->redir = NULL;
1455 decl->attr = 0;
1456 decl->fattr = 0;
1457 decl->pos = decl->top = 0;
1458 decl->stack[0].next = 0;
1460 for (;;) { /* Parse basic types. */
1461 cp_decl_attributes(cp, decl);
1462 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1463 uint32_t cbit;
1464 if (cp->ct->size) {
1465 if (sz) goto end_decl;
1466 sz = cp->ct->size;
1468 cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
1469 cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
1470 if (cp->tok >= CTOK_FIRSTSCL) {
1471 if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
1472 } else if (tdef) {
1473 goto end_decl;
1475 cp_next(cp);
1476 continue;
1478 if (sz || tdef ||
1479 (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
1480 break;
1481 switch (cp->tok) {
1482 case CTOK_STRUCT:
1483 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
1484 continue;
1485 case CTOK_UNION:
1486 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
1487 continue;
1488 case CTOK_ENUM:
1489 tdef = cp_decl_enum(cp, decl);
1490 continue;
1491 case CTOK_IDENT:
1492 if (ctype_istypedef(cp->ct->info)) {
1493 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
1494 cp_next(cp);
1495 continue;
1497 break;
1498 case '$':
1499 tdef = cp->val.id;
1500 cp_next(cp);
1501 continue;
1502 default:
1503 break;
1505 break;
1507 end_decl:
1509 if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
1510 tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
1512 if (tdef) {
1513 cp_push_type(decl, tdef);
1514 } else if ((cds & CDF_VOID)) {
1515 cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
1516 decl->attr &= ~CTF_QUAL;
1517 } else {
1518 /* Determine type info and size. */
1519 CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
1520 if ((cds & CDF_BOOL)) {
1521 if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
1522 cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
1523 info |= CTF_BOOL;
1524 if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
1525 if (!sz) {
1526 sz = 1;
1528 } else if ((cds & CDF_FP)) {
1529 info = CTINFO(CT_NUM, CTF_FP);
1530 if ((cds & CDF_LONG)) sz = sizeof(long double);
1531 } else if ((cds & CDF_CHAR)) {
1532 if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1533 info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
1534 } else if ((cds & CDF_SHORT)) {
1535 sz = sizeof(short);
1536 } else if ((cds & CDF_LONGLONG)) {
1537 sz = 8;
1538 } else if ((cds & CDF_LONG)) {
1539 info |= CTF_LONG;
1540 sz = sizeof(long);
1541 } else if (!sz) {
1542 if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
1543 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
1544 sz = sizeof(int);
1546 lua_assert(sz != 0);
1547 info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */
1548 info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
1549 cp_push(decl, info, sz);
1550 decl->attr &= ~CTF_QUAL;
1552 decl->specpos = decl->pos;
1553 decl->specattr = decl->attr;
1554 decl->specfattr = decl->fattr;
1555 return (cds & CDF_SCL); /* Return storage class. */
1558 /* Parse array declaration. */
1559 static void cp_decl_array(CPState *cp, CPDecl *decl)
1561 CTInfo info = CTINFO(CT_ARRAY, 0);
1562 CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
1563 cp_decl_attributes(cp, decl);
1564 if (cp_opt(cp, '?'))
1565 info |= CTF_VLA; /* Create variable-length array a[?]. */
1566 else if (cp->tok != ']')
1567 nelem = cp_expr_ksize(cp);
1568 cp_check(cp, ']');
1569 cp_add(decl, info, nelem);
1572 /* Parse function declaration. */
1573 static void cp_decl_func(CPState *cp, CPDecl *fdecl)
1575 CTSize nargs = 0;
1576 CTInfo info = CTINFO(CT_FUNC, 0);
1577 CTypeID lastid = 0, anchor = 0;
1578 if (cp->tok != ')') {
1579 do {
1580 CPDecl decl;
1581 CTypeID ctypeid, fieldid;
1582 CType *ct;
1583 if (cp_opt(cp, '.')) { /* Vararg function. */
1584 cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
1585 cp_check(cp, '.');
1586 info |= CTF_VARARG;
1587 break;
1589 cp_decl_spec(cp, &decl, CDF_REGISTER);
1590 decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
1591 cp_declarator(cp, &decl);
1592 ctypeid = cp_decl_intern(cp, &decl);
1593 ct = ctype_raw(cp->cts, ctypeid);
1594 if (ctype_isvoid(ct->info))
1595 break;
1596 else if (ctype_isrefarray(ct->info))
1597 ctypeid = lj_ctype_intern(cp->cts,
1598 CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
1599 else if (ctype_isfunc(ct->info))
1600 ctypeid = lj_ctype_intern(cp->cts,
1601 CTINFO(CT_PTR, CTALIGN_PTR|ctypeid), CTSIZE_PTR);
1602 /* Add new parameter. */
1603 fieldid = lj_ctype_new(cp->cts, &ct);
1604 if (anchor)
1605 ctype_get(cp->cts, lastid)->sib = fieldid;
1606 else
1607 anchor = fieldid;
1608 lastid = fieldid;
1609 if (decl.name) ctype_setname(ct, decl.name);
1610 ct->info = CTINFO(CT_FIELD, ctypeid);
1611 ct->size = nargs++;
1612 } while (cp_opt(cp, ','));
1614 cp_check(cp, ')');
1615 if (cp_opt(cp, '{')) { /* Skip function definition. */
1616 int level = 1;
1617 cp->mode |= CPARSE_MODE_SKIP;
1618 for (;;) {
1619 if (cp->tok == '{') level++;
1620 else if (cp->tok == '}' && --level == 0) break;
1621 else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
1622 cp_next(cp);
1624 cp->mode &= ~CPARSE_MODE_SKIP;
1625 cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
1627 info |= (fdecl->fattr & ~CTMASK_CID);
1628 fdecl->fattr = 0;
1629 fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
1632 /* Parse declarator. */
1633 static void cp_declarator(CPState *cp, CPDecl *decl)
1635 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
1637 for (;;) { /* Head of declarator. */
1638 if (cp_opt(cp, '*')) { /* Pointer. */
1639 CTSize sz;
1640 CTInfo info;
1641 cp_decl_attributes(cp, decl);
1642 sz = CTSIZE_PTR;
1643 info = CTINFO(CT_PTR, CTALIGN_PTR);
1644 #if LJ_64
1645 if (ctype_msizeP(decl->attr) == 4) {
1646 sz = 4;
1647 info = CTINFO(CT_PTR, CTALIGN(2));
1649 #endif
1650 info += (decl->attr & (CTF_QUAL|CTF_REF));
1651 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1652 cp_push(decl, info, sz);
1653 } else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) { /* Reference. */
1654 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1655 cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
1656 } else {
1657 break;
1661 if (cp_opt(cp, '(')) { /* Inner declarator. */
1662 CPDeclIdx pos;
1663 cp_decl_attributes(cp, decl);
1664 /* Resolve ambiguity between inner declarator and 1st function parameter. */
1665 if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
1666 (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
1667 pos = decl->pos;
1668 cp_declarator(cp, decl);
1669 cp_check(cp, ')');
1670 decl->pos = pos;
1671 } else if (cp->tok == CTOK_IDENT) { /* Direct declarator. */
1672 if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
1673 decl->name = cp->str;
1674 decl->nameid = cp->val.id;
1675 cp_next(cp);
1676 } else { /* Abstract declarator. */
1677 if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
1680 for (;;) { /* Tail of declarator. */
1681 if (cp_opt(cp, '[')) { /* Array. */
1682 cp_decl_array(cp, decl);
1683 } else if (cp_opt(cp, '(')) { /* Function. */
1684 func_decl:
1685 cp_decl_func(cp, decl);
1686 } else {
1687 break;
1691 if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
1692 decl->bits = cp_expr_ksize(cp);
1694 /* Process postfix attributes. */
1695 cp_decl_attributes(cp, decl);
1696 cp_push_attributes(decl);
1698 cp->depth--;
1701 /* Parse an abstract type declaration and return it's C type ID. */
1702 static CTypeID cp_decl_abstract(CPState *cp)
1704 CPDecl decl;
1705 cp_decl_spec(cp, &decl, 0);
1706 decl.mode = CPARSE_MODE_ABSTRACT;
1707 cp_declarator(cp, &decl);
1708 return cp_decl_intern(cp, &decl);
1711 /* Handle pragmas. */
1712 static void cp_pragma(CPState *cp, BCLine pragmaline)
1714 cp_next(cp);
1715 if (cp->tok == CTOK_IDENT &&
1716 cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */
1717 cp_next(cp);
1718 cp_check(cp, '(');
1719 if (cp->tok == CTOK_IDENT) {
1720 if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */
1721 if (cp->curpack < CPARSE_MAX_PACKSTACK) {
1722 cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
1723 cp->curpack++;
1725 } else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */
1726 if (cp->curpack > 0) cp->curpack--;
1727 } else {
1728 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1730 cp_next(cp);
1731 if (!cp_opt(cp, ',')) goto end_pack;
1733 if (cp->tok == CTOK_INTEGER) {
1734 cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
1735 cp_next(cp);
1736 } else {
1737 cp->packstack[cp->curpack] = 255;
1739 end_pack:
1740 cp_check(cp, ')');
1741 } else { /* Ignore all other pragmas. */
1742 while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
1743 cp_next(cp);
1747 /* Parse multiple C declarations of types or extern identifiers. */
1748 static void cp_decl_multi(CPState *cp)
1750 int first = 1;
1751 while (cp->tok != CTOK_EOF) {
1752 CPDecl decl;
1753 CPscl scl;
1754 if (cp_opt(cp, ';')) { /* Skip empty statements. */
1755 first = 0;
1756 continue;
1758 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
1759 BCLine pragmaline = cp->linenumber;
1760 if (!(cp_next(cp) == CTOK_IDENT &&
1761 cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */
1762 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1763 cp_pragma(cp, pragmaline);
1764 continue;
1766 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
1767 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
1768 ctype_istypedef(decl.stack[0].info)) {
1769 CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
1770 if (ctype_isstruct(info) || ctype_isenum(info))
1771 goto decl_end; /* Accept empty declaration of struct/union/enum. */
1773 for (;;) {
1774 CTypeID ctypeid;
1775 cp_declarator(cp, &decl);
1776 ctypeid = cp_decl_intern(cp, &decl);
1777 if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */
1778 CType *ct;
1779 CTypeID id;
1780 if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */
1781 id = lj_ctype_new(cp->cts, &ct);
1782 ct->info = CTINFO(CT_TYPEDEF, ctypeid);
1783 goto noredir;
1784 } else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info)) {
1785 /* Treat both static and extern function declarations as extern. */
1786 ct = ctype_get(cp->cts, ctypeid);
1787 /* We always get new anonymous functions (typedefs are copied). */
1788 lua_assert(gcref(ct->name) == NULL);
1789 id = ctypeid; /* Just name it. */
1790 } else if ((scl & CDF_STATIC)) { /* Accept static constants. */
1791 id = cp_decl_constinit(cp, &ct, ctypeid);
1792 goto noredir;
1793 } else { /* External references have extern or no storage class. */
1794 id = lj_ctype_new(cp->cts, &ct);
1795 ct->info = CTINFO(CT_EXTERN, ctypeid);
1797 if (decl.redir) { /* Add attribute for redirected symbol name. */
1798 CType *cta;
1799 CTypeID aid = lj_ctype_new(cp->cts, &cta);
1800 ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
1801 cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
1802 cta->sib = ct->sib;
1803 ct->sib = aid;
1804 ctype_setname(cta, decl.redir);
1806 noredir:
1807 ctype_setname(ct, decl.name);
1808 lj_ctype_addname(cp->cts, ct, id);
1810 if (!cp_opt(cp, ',')) break;
1811 cp_decl_reset(&decl);
1813 decl_end:
1814 if (cp->tok == CTOK_EOF && first) break; /* May omit ';' for 1 decl. */
1815 first = 0;
1816 cp_check(cp, ';');
1820 /* Parse a single C type declaration. */
1821 static void cp_decl_single(CPState *cp)
1823 CPDecl decl;
1824 cp_decl_spec(cp, &decl, 0);
1825 cp_declarator(cp, &decl);
1826 cp->val.id = cp_decl_intern(cp, &decl);
1827 if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
1830 #undef H_
1832 /* ------------------------------------------------------------------------ */
1834 /* Protected callback for C parser. */
1835 static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
1837 CPState *cp = (CPState *)ud;
1838 UNUSED(dummy);
1839 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
1840 cp_init(cp);
1841 if ((cp->mode & CPARSE_MODE_MULTI))
1842 cp_decl_multi(cp);
1843 else
1844 cp_decl_single(cp);
1845 if (cp->param && cp->param != cp->L->top)
1846 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
1847 lua_assert(cp->depth == 0);
1848 return NULL;
1851 /* C parser. */
1852 int lj_cparse(CPState *cp)
1854 LJ_CTYPE_SAVE(cp->cts);
1855 int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
1856 if (errcode)
1857 LJ_CTYPE_RESTORE(cp->cts);
1858 cp_cleanup(cp);
1859 return errcode;
1862 #endif