MIPS: Fix calls to floor/ceil/trunc.
[luajit-2.0/celess22.git] / src / lj_cparse.c
blobe98267152ba36efac77fd139658c24be3673946a
1 /*
2 ** C declaration parser.
3 ** Copyright (C) 2005-2012 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_str.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"
20 ** Important note: this is NOT a validating C parser! This is a minimal
21 ** C declaration parser, solely for use by the LuaJIT FFI.
23 ** It ought to return correct results for properly formed C declarations,
24 ** but it may accept some invalid declarations, too (and return nonsense).
25 ** Also, it shows rather generic error messages to avoid unnecessary bloat.
26 ** If in doubt, please check the input against your favorite C compiler.
29 /* -- C lexer ------------------------------------------------------------- */
31 /* C lexer token names. */
32 static const char *const ctoknames[] = {
33 #define CTOKSTR(name, str) str,
34 CTOKDEF(CTOKSTR)
35 #undef CTOKSTR
36 NULL
39 /* Forward declaration. */
40 LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
42 static const char *cp_tok2str(CPState *cp, CPToken tok)
44 lua_assert(tok < CTOK_FIRSTDECL);
45 if (tok > CTOK_OFS)
46 return ctoknames[tok-CTOK_OFS-1];
47 else if (!lj_char_iscntrl(tok))
48 return lj_str_pushf(cp->L, "%c", tok);
49 else
50 return lj_str_pushf(cp->L, "char(%d)", tok);
53 /* End-of-line? */
54 static LJ_AINLINE int cp_iseol(CPChar c)
56 return (c == '\n' || c == '\r');
59 static LJ_AINLINE CPChar cp_get(CPState *cp);
61 /* Peek next raw character. */
62 static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
64 return (CPChar)(uint8_t)(*cp->p);
67 /* Transparently skip backslash-escaped line breaks. */
68 static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
70 CPChar c2, c = cp_rawpeek(cp);
71 if (!cp_iseol(c)) return cp->c;
72 cp->p++;
73 c2 = cp_rawpeek(cp);
74 if (cp_iseol(c2) && c2 != c) cp->p++;
75 cp->linenumber++;
76 return cp_get(cp);
79 /* Get next character. */
80 static LJ_AINLINE CPChar cp_get(CPState *cp)
82 cp->c = (CPChar)(uint8_t)(*cp->p++);
83 if (LJ_LIKELY(cp->c != '\\')) return cp->c;
84 return cp_get_bs(cp);
87 /* Grow save buffer. */
88 static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c)
90 MSize newsize;
91 if (cp->sb.sz >= CPARSE_MAX_BUF/2)
92 cp_err(cp, LJ_ERR_XELEM);
93 newsize = cp->sb.sz * 2;
94 lj_str_resizebuf(cp->L, &cp->sb, newsize);
95 cp->sb.buf[cp->sb.n++] = (char)c;
98 /* Save character in buffer. */
99 static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
101 if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz))
102 cp_save_grow(cp, c);
103 else
104 cp->sb.buf[cp->sb.n++] = (char)c;
107 /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
108 static void cp_newline(CPState *cp)
110 CPChar c = cp_rawpeek(cp);
111 if (cp_iseol(c) && c != cp->c) cp->p++;
112 cp->linenumber++;
115 LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
117 const char *msg, *tokstr;
118 lua_State *L;
119 va_list argp;
120 if (tok == 0) {
121 tokstr = NULL;
122 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
123 tok >= CTOK_FIRSTDECL) {
124 if (cp->sb.n == 0) cp_save(cp, '$');
125 cp_save(cp, '\0');
126 tokstr = cp->sb.buf;
127 } else {
128 tokstr = cp_tok2str(cp, tok);
130 L = cp->L;
131 va_start(argp, em);
132 msg = lj_str_pushvf(L, err2msg(em), argp);
133 va_end(argp);
134 if (tokstr)
135 msg = lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
136 if (cp->linenumber > 1)
137 msg = lj_str_pushf(L, "%s at line %d", msg, cp->linenumber);
138 lj_err_callermsg(L, msg);
141 LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
143 cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
146 LJ_NORET LJ_NOINLINE static void cp_err_badidx(CPState *cp, CType *ct)
148 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
149 cp_errmsg(cp, 0, LJ_ERR_FFI_BADIDX, strdata(s));
152 LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
154 cp_errmsg(cp, 0, em);
157 /* -- Main lexical scanner ------------------------------------------------ */
159 /* Parse integer literal. */
160 static CPToken cp_integer(CPState *cp)
162 uint32_t n = 0;
163 cp->val.id = CTID_INT32;
164 if (cp->c != '0') { /* Decimal. */
165 do {
166 n = n*10 + (cp->c - '0');
167 } while (lj_char_isdigit(cp_get(cp)));
168 } else if ((cp_get(cp)& ~0x20) == 'X') { /* Hexadecimal. */
169 if (!lj_char_isxdigit(cp_get(cp)))
170 cp_err(cp, LJ_ERR_XNUMBER);
171 do {
172 n = n*16 + (cp->c & 15);
173 if (!lj_char_isdigit(cp->c)) n += 9;
174 } while (lj_char_isxdigit(cp_get(cp)));
175 if (n >= 0x80000000u) cp->val.id = CTID_UINT32;
176 } else { /* Octal. */
177 while (cp->c >= '0' && cp->c <= '7') {
178 n = n*8 + (cp->c - '0');
179 cp_get(cp);
181 if (n >= 0x80000000u) cp->val.id = CTID_UINT32;
183 cp->val.u32 = n;
184 for (;;) { /* Parse suffixes. */
185 if ((cp->c & ~0x20) == 'U')
186 cp->val.id = CTID_UINT32;
187 else if ((cp->c & ~0x20) != 'L')
188 break;
189 cp_get(cp);
191 if (lj_char_isident(cp->c) && !(cp->mode & CPARSE_MODE_SKIP))
192 cp_errmsg(cp, cp->c, LJ_ERR_XNUMBER);
193 return CTOK_INTEGER;
196 /* Parse identifier or keyword. */
197 static CPToken cp_ident(CPState *cp)
199 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
200 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
201 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
202 if (ctype_type(cp->ct->info) == CT_KW)
203 return ctype_cid(cp->ct->info);
204 return CTOK_IDENT;
207 /* Parse parameter. */
208 static CPToken cp_param(CPState *cp)
210 CPChar c = cp_get(cp);
211 TValue *o = cp->param;
212 if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
213 cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
214 if (!o || o >= cp->L->top)
215 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
216 cp->param = o+1;
217 if (tvisstr(o)) {
218 cp->str = strV(o);
219 cp->val.id = 0;
220 cp->ct = &cp->cts->tab[0];
221 return CTOK_IDENT;
222 } else if (tvisnumber(o)) {
223 cp->val.i32 = numberVint(o);
224 cp->val.id = CTID_INT32;
225 return CTOK_INTEGER;
226 } else {
227 GCcdata *cd;
228 if (!tviscdata(o))
229 lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
230 cd = cdataV(o);
231 if (cd->ctypeid == CTID_CTYPEID)
232 cp->val.id = *(CTypeID *)cdataptr(cd);
233 else
234 cp->val.id = cd->ctypeid;
235 return '$';
239 /* Parse string or character constant. */
240 static CPToken cp_string(CPState *cp)
242 CPChar delim = cp->c;
243 cp_get(cp);
244 while (cp->c != delim) {
245 CPChar c = cp->c;
246 if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
247 if (c == '\\') {
248 c = cp_get(cp);
249 switch (c) {
250 case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
251 case 'a': c = '\a'; break;
252 case 'b': c = '\b'; break;
253 case 'f': c = '\f'; break;
254 case 'n': c = '\n'; break;
255 case 'r': c = '\r'; break;
256 case 't': c = '\t'; break;
257 case 'v': c = '\v'; break;
258 case 'e': c = 27; break;
259 case 'x':
260 c = 0;
261 while (lj_char_isxdigit(cp_get(cp)))
262 c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
263 cp_save(cp, (c & 0xff));
264 continue;
265 default:
266 if (lj_char_isdigit(c)) {
267 c -= '0';
268 if (lj_char_isdigit(cp_get(cp))) {
269 c = c*8 + (cp->c - '0');
270 if (lj_char_isdigit(cp_get(cp))) {
271 c = c*8 + (cp->c - '0');
272 cp_get(cp);
275 cp_save(cp, (c & 0xff));
276 continue;
278 break;
281 cp_save(cp, c);
282 cp_get(cp);
284 cp_get(cp);
285 if (delim == '"') {
286 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
287 return CTOK_STRING;
288 } else {
289 if (cp->sb.n != 1) cp_err_token(cp, '\'');
290 cp->val.i32 = (int32_t)(char)cp->sb.buf[0];
291 cp->val.id = CTID_INT32;
292 return CTOK_INTEGER;
296 /* Skip C comment. */
297 static void cp_comment_c(CPState *cp)
299 do {
300 if (cp_get(cp) == '*') {
301 do {
302 if (cp_get(cp) == '/') { cp_get(cp); return; }
303 } while (cp->c == '*');
305 if (cp_iseol(cp->c)) cp_newline(cp);
306 } while (cp->c != '\0');
309 /* Skip C++ comment. */
310 static void cp_comment_cpp(CPState *cp)
312 while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
316 /* Lexical scanner for C. Only a minimal subset is implemented. */
317 static CPToken cp_next_(CPState *cp)
319 lj_str_resetbuf(&cp->sb);
320 for (;;) {
321 if (lj_char_isident(cp->c))
322 return lj_char_isdigit(cp->c) ? cp_integer(cp) : cp_ident(cp);
323 switch (cp->c) {
324 case '\n': case '\r': cp_newline(cp); /* fallthrough. */
325 case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
326 case '"': case '\'': return cp_string(cp);
327 case '/':
328 cp_get(cp);
329 if (cp->c == '*') cp_comment_c(cp);
330 else if (cp->c == '/') cp_comment_cpp(cp);
331 else return '/';
332 break;
333 case '|':
334 cp_get(cp); if (cp->c != '|') return '|'; cp_get(cp); return CTOK_OROR;
335 case '&':
336 cp_get(cp); if (cp->c != '&') return '&'; cp_get(cp); return CTOK_ANDAND;
337 case '=':
338 cp_get(cp); if (cp->c != '=') return '='; cp_get(cp); return CTOK_EQ;
339 case '!':
340 cp_get(cp); if (cp->c != '=') return '!'; cp_get(cp); return CTOK_NE;
341 case '<':
342 cp_get(cp);
343 if (cp->c == '=') { cp_get(cp); return CTOK_LE; }
344 else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
345 return '<';
346 case '>':
347 cp_get(cp);
348 if (cp->c == '=') { cp_get(cp); return CTOK_GE; }
349 else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
350 return '>';
351 case '-':
352 cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF;
353 case '$':
354 return cp_param(cp);
355 case '\0': return CTOK_EOF;
356 default: { CPToken c = cp->c; cp_get(cp); return c; }
361 static LJ_NOINLINE CPToken cp_next(CPState *cp)
363 return (cp->tok = cp_next_(cp));
366 /* -- C parser ------------------------------------------------------------ */
368 /* Namespaces for resolving identifiers. */
369 #define CPNS_DEFAULT \
370 ((1u<<CT_KW)|(1u<<CT_TYPEDEF)|(1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
371 #define CPNS_STRUCT ((1u<<CT_KW)|(1u<<CT_STRUCT)|(1u<<CT_ENUM))
373 typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
374 typedef uint32_t CPscl; /* Storage class flags. */
376 /* Type declaration context. */
377 typedef struct CPDecl {
378 CPDeclIdx top; /* Top of declaration stack. */
379 CPDeclIdx pos; /* Insertion position in declaration chain. */
380 CPDeclIdx specpos; /* Saved position for declaration specifier. */
381 uint32_t mode; /* Declarator mode. */
382 CPState *cp; /* C parser state. */
383 GCstr *name; /* Name of declared identifier (if direct). */
384 GCstr *redir; /* Redirected symbol name. */
385 CTypeID nameid; /* Existing typedef for declared identifier. */
386 CTInfo attr; /* Attributes. */
387 CTInfo fattr; /* Function attributes. */
388 CTInfo specattr; /* Saved attributes. */
389 CTInfo specfattr; /* Saved function attributes. */
390 CTSize bits; /* Field size in bits (if any). */
391 CType stack[CPARSE_MAX_DECLSTACK]; /* Type declaration stack. */
392 } CPDecl;
394 /* Forward declarations. */
395 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
396 static void cp_declarator(CPState *cp, CPDecl *decl);
397 static CTypeID cp_decl_abstract(CPState *cp);
399 /* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
400 static void cp_init(CPState *cp)
402 cp->linenumber = 1;
403 cp->depth = 0;
404 cp->curpack = 0;
405 cp->packstack[0] = 255;
406 lj_str_initbuf(&cp->sb);
407 lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF);
408 lua_assert(cp->p != NULL);
409 cp_get(cp); /* Read-ahead first char. */
410 cp->tok = 0;
411 cp->tmask = CPNS_DEFAULT;
412 cp_next(cp); /* Read-ahead first token. */
415 /* Cleanup C parser state. */
416 static void cp_cleanup(CPState *cp)
418 global_State *g = G(cp->L);
419 lj_str_freebuf(g, &cp->sb);
422 /* Check and consume optional token. */
423 static int cp_opt(CPState *cp, CPToken tok)
425 if (cp->tok == tok) { cp_next(cp); return 1; }
426 return 0;
429 /* Check and consume token. */
430 static void cp_check(CPState *cp, CPToken tok)
432 if (cp->tok != tok) cp_err_token(cp, tok);
433 cp_next(cp);
436 /* Check if the next token may start a type declaration. */
437 static int cp_istypedecl(CPState *cp)
439 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
440 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
441 if (cp->tok == '$') return 1;
442 return 0;
445 /* -- Constant expression evaluator --------------------------------------- */
447 /* Forward declarations. */
448 static void cp_expr_unary(CPState *cp, CPValue *k);
449 static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
451 /* Please note that type handling is very weak here. Most ops simply
452 ** assume integer operands. Accessors are only needed to compute types and
453 ** return synthetic values. The only purpose of the expression evaluator
454 ** is to compute the values of constant expressions one would typically
455 ** find in C header files. And again: this is NOT a validating C parser!
458 /* Parse comma separated expression and return last result. */
459 static void cp_expr_comma(CPState *cp, CPValue *k)
461 do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
464 /* Parse sizeof/alignof operator. */
465 static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
467 CTSize sz;
468 CTInfo info;
469 if (cp_opt(cp, '(')) {
470 if (cp_istypedecl(cp))
471 k->id = cp_decl_abstract(cp);
472 else
473 cp_expr_comma(cp, k);
474 cp_check(cp, ')');
475 } else {
476 cp_expr_unary(cp, k);
478 info = lj_ctype_info(cp->cts, k->id, &sz);
479 if (wantsz) {
480 if (sz != CTSIZE_INVALID)
481 k->u32 = sz;
482 else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
483 cp_err(cp, LJ_ERR_FFI_INVSIZE);
484 } else {
485 k->u32 = 1u << ctype_align(info);
487 k->id = CTID_UINT32; /* Really size_t. */
490 /* Parse prefix operators. */
491 static void cp_expr_prefix(CPState *cp, CPValue *k)
493 if (cp->tok == CTOK_INTEGER) {
494 *k = cp->val; cp_next(cp);
495 } else if (cp_opt(cp, '+')) {
496 cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
497 } else if (cp_opt(cp, '-')) {
498 cp_expr_unary(cp, k); k->i32 = -k->i32;
499 } else if (cp_opt(cp, '~')) {
500 cp_expr_unary(cp, k); k->i32 = ~k->i32;
501 } else if (cp_opt(cp, '!')) {
502 cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
503 } else if (cp_opt(cp, '(')) {
504 if (cp_istypedecl(cp)) { /* Cast operator. */
505 CTypeID id = cp_decl_abstract(cp);
506 cp_check(cp, ')');
507 cp_expr_unary(cp, k);
508 k->id = id; /* No conversion performed. */
509 } else { /* Sub-expression. */
510 cp_expr_comma(cp, k);
511 cp_check(cp, ')');
513 } else if (cp_opt(cp, '*')) { /* Indirection. */
514 CType *ct;
515 cp_expr_unary(cp, k);
516 ct = lj_ctype_rawref(cp->cts, k->id);
517 if (!ctype_ispointer(ct->info))
518 cp_err_badidx(cp, ct);
519 k->u32 = 0; k->id = ctype_cid(ct->info);
520 } else if (cp_opt(cp, '&')) { /* Address operator. */
521 cp_expr_unary(cp, k);
522 k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
523 CTSIZE_PTR);
524 } else if (cp_opt(cp, CTOK_SIZEOF)) {
525 cp_expr_sizeof(cp, k, 1);
526 } else if (cp_opt(cp, CTOK_ALIGNOF)) {
527 cp_expr_sizeof(cp, k, 0);
528 } else if (cp->tok == CTOK_IDENT) {
529 if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
530 k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
531 } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
532 k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
533 } else if (ctype_type(cp->ct->info) == CT_FUNC) {
534 k->u32 = cp->val.id; k->id = cp->val.id;
535 } else {
536 goto err_expr;
538 cp_next(cp);
539 } else if (cp->tok == CTOK_STRING) {
540 CTSize sz = cp->str->len;
541 while (cp_next(cp) == CTOK_STRING)
542 sz += cp->str->len;
543 k->u32 = sz + 1;
544 k->id = CTID_A_CCHAR;
545 } else {
546 err_expr:
547 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
551 /* Parse postfix operators. */
552 static void cp_expr_postfix(CPState *cp, CPValue *k)
554 for (;;) {
555 CType *ct;
556 if (cp_opt(cp, '[')) { /* Array/pointer index. */
557 CPValue k2;
558 cp_expr_comma(cp, &k2);
559 ct = lj_ctype_rawref(cp->cts, k->id);
560 if (!ctype_ispointer(ct->info)) {
561 ct = lj_ctype_rawref(cp->cts, k2.id);
562 if (!ctype_ispointer(ct->info))
563 cp_err_badidx(cp, ct);
565 cp_check(cp, ']');
566 k->u32 = 0;
567 } else if (cp->tok == '.' || cp->tok == CTOK_DEREF) { /* Struct deref. */
568 CTSize ofs;
569 CType *fct;
570 ct = lj_ctype_rawref(cp->cts, k->id);
571 if (cp->tok == CTOK_DEREF) {
572 if (!ctype_ispointer(ct->info))
573 cp_err_badidx(cp, ct);
574 ct = lj_ctype_rawref(cp->cts, ctype_cid(ct->info));
576 cp_next(cp);
577 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
578 if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
579 !(fct = lj_ctype_getfield(cp->cts, ct, cp->str, &ofs)) ||
580 ctype_isbitfield(fct->info)) {
581 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
582 cp_errmsg(cp, 0, LJ_ERR_FFI_BADMEMBER, strdata(s), strdata(cp->str));
584 ct = fct;
585 k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
586 cp_next(cp);
587 } else {
588 return;
590 k->id = ctype_cid(ct->info);
594 /* Parse infix operators. */
595 static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
597 CPValue k2;
598 k2.u32 = 0; k2.id = 0; /* Silence the compiler. */
599 for (;;) {
600 switch (pri) {
601 case 0:
602 if (cp_opt(cp, '?')) {
603 CPValue k3;
604 cp_expr_comma(cp, &k2); /* Right-associative. */
605 cp_check(cp, ':');
606 cp_expr_sub(cp, &k3, 0);
607 k->u32 = k->u32 ? k2.u32 : k3.u32;
608 k->id = k2.id > k3.id ? k2.id : k3.id;
609 continue;
611 case 1:
612 if (cp_opt(cp, CTOK_OROR)) {
613 cp_expr_sub(cp, &k2, 2); k->i32 = k->u32 || k2.u32; k->id = CTID_INT32;
614 continue;
616 case 2:
617 if (cp_opt(cp, CTOK_ANDAND)) {
618 cp_expr_sub(cp, &k2, 3); k->i32 = k->u32 && k2.u32; k->id = CTID_INT32;
619 continue;
621 case 3:
622 if (cp_opt(cp, '|')) {
623 cp_expr_sub(cp, &k2, 4); k->u32 = k->u32 | k2.u32; goto arith_result;
625 case 4:
626 if (cp_opt(cp, '^')) {
627 cp_expr_sub(cp, &k2, 5); k->u32 = k->u32 ^ k2.u32; goto arith_result;
629 case 5:
630 if (cp_opt(cp, '&')) {
631 cp_expr_sub(cp, &k2, 6); k->u32 = k->u32 & k2.u32; goto arith_result;
633 case 6:
634 if (cp_opt(cp, CTOK_EQ)) {
635 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 == k2.u32; k->id = CTID_INT32;
636 continue;
637 } else if (cp_opt(cp, CTOK_NE)) {
638 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 != k2.u32; k->id = CTID_INT32;
639 continue;
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;
675 case 8:
676 if (cp_opt(cp, CTOK_SHL)) {
677 cp_expr_sub(cp, &k2, 9); k->u32 = k->u32 << k2.u32;
678 continue;
679 } else if (cp_opt(cp, CTOK_SHR)) {
680 cp_expr_sub(cp, &k2, 9);
681 if (k->id == CTID_INT32)
682 k->i32 = k->i32 >> k2.i32;
683 else
684 k->u32 = k->u32 >> k2.u32;
685 continue;
687 case 9:
688 if (cp_opt(cp, '+')) {
689 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 + k2.u32;
690 arith_result:
691 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
692 continue;
693 } else if (cp_opt(cp, '-')) {
694 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 - k2.u32; goto arith_result;
696 case 10:
697 if (cp_opt(cp, '*')) {
698 cp_expr_unary(cp, &k2); k->u32 = k->u32 * k2.u32; goto arith_result;
699 } else if (cp_opt(cp, '/')) {
700 cp_expr_unary(cp, &k2);
701 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
702 if (k2.u32 == 0 ||
703 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
704 cp_err(cp, LJ_ERR_BADVAL);
705 if (k->id == CTID_INT32)
706 k->i32 = k->i32 / k2.i32;
707 else
708 k->u32 = k->u32 / k2.u32;
709 continue;
710 } else if (cp_opt(cp, '%')) {
711 cp_expr_unary(cp, &k2);
712 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
713 if (k2.u32 == 0 ||
714 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
715 cp_err(cp, LJ_ERR_BADVAL);
716 if (k->id == CTID_INT32)
717 k->i32 = k->i32 % k2.i32;
718 else
719 k->u32 = k->u32 % k2.u32;
720 continue;
722 default:
723 return;
728 /* Parse and evaluate unary expression. */
729 static void cp_expr_unary(CPState *cp, CPValue *k)
731 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
732 cp_expr_prefix(cp, k);
733 cp_expr_postfix(cp, k);
734 cp->depth--;
737 /* Parse and evaluate sub-expression. */
738 static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
740 cp_expr_unary(cp, k);
741 cp_expr_infix(cp, k, pri);
744 /* Parse constant integer expression. */
745 static void cp_expr_kint(CPState *cp, CPValue *k)
747 CType *ct;
748 cp_expr_sub(cp, k, 0);
749 ct = ctype_raw(cp->cts, k->id);
750 if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
753 /* Parse (non-negative) size expression. */
754 static CTSize cp_expr_ksize(CPState *cp)
756 CPValue k;
757 cp_expr_kint(cp, &k);
758 if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
759 return k.u32;
762 /* -- Type declaration stack management ----------------------------------- */
764 /* Add declaration element behind the insertion position. */
765 static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
767 CPDeclIdx top = decl->top;
768 if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
769 decl->stack[top].info = info;
770 decl->stack[top].size = size;
771 decl->stack[top].sib = 0;
772 setgcrefnull(decl->stack[top].name);
773 decl->stack[top].next = decl->stack[decl->pos].next;
774 decl->stack[decl->pos].next = (CTypeID1)top;
775 decl->top = top+1;
776 return top;
779 /* Push declaration element before the insertion position. */
780 static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
782 return (decl->pos = cp_add(decl, info, size));
785 /* Push or merge attributes. */
786 static void cp_push_attributes(CPDecl *decl)
788 CType *ct = &decl->stack[decl->pos];
789 if (ctype_isfunc(ct->info)) { /* Ok to modify in-place. */
790 #if LJ_TARGET_X86
791 if ((decl->fattr & CTFP_CCONV))
792 ct->info = (ct->info & (CTMASK_NUM|CTF_VARARG|CTMASK_CID)) +
793 (decl->fattr & ~CTMASK_CID);
794 #endif
795 } else {
796 if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
797 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
798 ctype_align(decl->attr));
802 /* Push unrolled type to declaration stack and merge qualifiers. */
803 static void cp_push_type(CPDecl *decl, CTypeID id)
805 CType *ct = ctype_get(decl->cp->cts, id);
806 CTInfo info = ct->info;
807 CTSize size = ct->size;
808 switch (ctype_type(info)) {
809 case CT_STRUCT: case CT_ENUM:
810 cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
811 if ((decl->attr & CTF_QUAL)) { /* Push unmerged qualifiers. */
812 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
813 (decl->attr & CTF_QUAL));
814 decl->attr &= ~CTF_QUAL;
816 break;
817 case CT_ATTRIB:
818 if (ctype_isxattrib(info, CTA_QUAL))
819 decl->attr &= ~size; /* Remove redundant qualifiers. */
820 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
821 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
822 break;
823 case CT_ARRAY:
824 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
825 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
826 decl->stack[decl->pos].sib = 1; /* Mark as already checked and sized. */
827 /* Note: this is not copied to the ct->sib in the C type table. */
828 break;
829 case CT_FUNC:
830 /* Copy type, link parameters (shared). */
831 decl->stack[cp_push(decl, info, size)].sib = ct->sib;
832 break;
833 default:
834 /* Copy type, merge common qualifiers. */
835 cp_push(decl, info|(decl->attr & CTF_QUAL), size);
836 decl->attr &= ~CTF_QUAL;
837 break;
841 /* Consume the declaration element chain and intern the C type. */
842 static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
844 CTypeID id = 0;
845 CPDeclIdx idx = 0;
846 CTSize csize = CTSIZE_INVALID;
847 CTSize cinfo = 0;
848 do {
849 CType *ct = &decl->stack[idx];
850 CTInfo info = ct->info;
851 CTInfo size = ct->size;
852 /* The cid is already part of info for copies of pointers/functions. */
853 idx = ct->next;
854 if (ctype_istypedef(info)) {
855 lua_assert(id == 0);
856 id = ctype_cid(info);
857 /* Always refetch info/size, since struct/enum may have been completed. */
858 cinfo = ctype_get(cp->cts, id)->info;
859 csize = ctype_get(cp->cts, id)->size;
860 lua_assert(ctype_isstruct(cinfo) || ctype_isenum(cinfo));
861 } else if (ctype_isfunc(info)) { /* Intern function. */
862 CType *fct;
863 CTypeID fid;
864 CTypeID sib;
865 if (id) {
866 CType *refct = ctype_raw(cp->cts, id);
867 /* Reject function or refarray return types. */
868 if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
869 cp_err(cp, LJ_ERR_FFI_INVTYPE);
871 /* No intervening attributes allowed, skip forward. */
872 while (idx) {
873 CType *ctn = &decl->stack[idx];
874 if (!ctype_isattrib(ctn->info)) break;
875 idx = ctn->next; /* Skip attribute. */
877 sib = ct->sib; /* Next line may reallocate the C type table. */
878 fid = lj_ctype_new(cp->cts, &fct);
879 csize = CTSIZE_INVALID;
880 fct->info = cinfo = info + id;
881 fct->size = size;
882 fct->sib = sib;
883 id = fid;
884 } else if (ctype_isattrib(info)) {
885 if (ctype_isxattrib(info, CTA_QUAL))
886 cinfo |= size;
887 else if (ctype_isxattrib(info, CTA_ALIGN))
888 CTF_INSERT(cinfo, ALIGN, size);
889 id = lj_ctype_intern(cp->cts, info+id, size);
890 /* Inherit csize/cinfo from original type. */
891 } else {
892 if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */
893 lua_assert(id == 0);
894 if (!(info & CTF_BOOL)) {
895 CTSize msize = ctype_msizeP(decl->attr);
896 CTSize vsize = ctype_vsizeP(decl->attr);
897 if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8))) {
898 CTSize malign = lj_fls(msize);
899 if (malign > 4) malign = 4; /* Limit alignment. */
900 CTF_INSERT(info, ALIGN, malign);
901 size = msize; /* Override size via mode. */
903 if (vsize) { /* Vector size set? */
904 CTSize esize = lj_fls(size);
905 if (vsize >= esize) {
906 /* Intern the element type first. */
907 id = lj_ctype_intern(cp->cts, info, size);
908 /* Then create a vector (array) with vsize alignment. */
909 size = (1u << vsize);
910 if (vsize > 4) vsize = 4; /* Limit alignment. */
911 if (ctype_align(info) > vsize) vsize = ctype_align(info);
912 info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
913 CTALIGN(vsize));
917 } else if (ctype_isptr(info)) {
918 /* Reject pointer/ref to ref. */
919 if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
920 cp_err(cp, LJ_ERR_FFI_INVTYPE);
921 if (ctype_isref(info)) {
922 info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
923 /* No intervening attributes allowed, skip forward. */
924 while (idx) {
925 CType *ctn = &decl->stack[idx];
926 if (!ctype_isattrib(ctn->info)) break;
927 idx = ctn->next; /* Skip attribute. */
930 } else if (ctype_isarray(info)) { /* Check for valid array size etc. */
931 if (ct->sib == 0) { /* Only check/size arrays not copied by unroll. */
932 if (ctype_isref(cinfo)) /* Reject arrays of refs. */
933 cp_err(cp, LJ_ERR_FFI_INVTYPE);
934 /* Reject VLS or unknown-sized types. */
935 if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
936 cp_err(cp, LJ_ERR_FFI_INVSIZE);
937 /* a[] and a[?] keep their invalid size. */
938 if (size != CTSIZE_INVALID) {
939 uint64_t xsz = (uint64_t)size * csize;
940 if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
941 size = (CTSize)xsz;
944 info |= (cinfo & (CTF_QUAL|CTF_ALIGN)); /* Inherit qual and align. */
945 } else {
946 lua_assert(ctype_isvoid(info));
948 csize = size;
949 cinfo = info+id;
950 id = lj_ctype_intern(cp->cts, info+id, size);
952 } while (idx);
953 return id;
956 /* -- C declaration parser ------------------------------------------------ */
958 #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
960 /* Reset declaration state to declaration specifier. */
961 static void cp_decl_reset(CPDecl *decl)
963 decl->pos = decl->specpos;
964 decl->top = decl->specpos+1;
965 decl->stack[decl->specpos].next = 0;
966 decl->attr = decl->specattr;
967 decl->fattr = decl->specfattr;
968 decl->name = NULL;
969 decl->redir = NULL;
972 /* Parse constant initializer. */
973 /* NYI: FP constants and strings as initializers. */
974 static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
976 CType *ctt = ctype_get(cp->cts, ctypeid);
977 CTInfo info;
978 CTSize size;
979 CPValue k;
980 CTypeID constid;
981 while (ctype_isattrib(ctt->info)) { /* Skip attributes. */
982 ctypeid = ctype_cid(ctt->info); /* Update ID, too. */
983 ctt = ctype_get(cp->cts, ctypeid);
985 info = ctt->info;
986 size = ctt->size;
987 if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
988 cp_err(cp, LJ_ERR_FFI_INVTYPE);
989 cp_check(cp, '=');
990 cp_expr_sub(cp, &k, 0);
991 constid = lj_ctype_new(cp->cts, ctp);
992 (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
993 k.u32 <<= 8*(4-size);
994 if ((info & CTF_UNSIGNED))
995 k.u32 >>= 8*(4-size);
996 else
997 k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
998 (*ctp)->size = k.u32;
999 return constid;
1002 /* Parse size in parentheses as part of attribute. */
1003 static CTSize cp_decl_sizeattr(CPState *cp)
1005 CTSize sz;
1006 uint32_t oldtmask = cp->tmask;
1007 cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
1008 cp_check(cp, '(');
1009 sz = cp_expr_ksize(cp);
1010 cp->tmask = oldtmask;
1011 cp_check(cp, ')');
1012 return sz;
1015 /* Parse alignment attribute. */
1016 static void cp_decl_align(CPState *cp, CPDecl *decl)
1018 CTSize al = 4; /* Unspecified alignment is 16 bytes. */
1019 if (cp->tok == '(') {
1020 al = cp_decl_sizeattr(cp);
1021 al = al ? lj_fls(al) : 0;
1023 CTF_INSERT(decl->attr, ALIGN, al);
1024 decl->attr |= CTFP_ALIGNED;
1027 /* Parse GCC asm("name") redirect. */
1028 static void cp_decl_asm(CPState *cp, CPDecl *decl)
1030 UNUSED(decl);
1031 cp_next(cp);
1032 cp_check(cp, '(');
1033 if (cp->tok == CTOK_STRING) {
1034 GCstr *str = cp->str;
1035 while (cp_next(cp) == CTOK_STRING) {
1036 lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str));
1037 cp->L->top--;
1038 str = strV(cp->L->top);
1040 decl->redir = str;
1042 cp_check(cp, ')');
1045 /* Parse GCC __attribute__((mode(...))). */
1046 static void cp_decl_mode(CPState *cp, CPDecl *decl)
1048 cp_check(cp, '(');
1049 if (cp->tok == CTOK_IDENT) {
1050 const char *s = strdata(cp->str);
1051 CTSize sz = 0, vlen = 0;
1052 if (s[0] == '_' && s[1] == '_') s += 2;
1053 if (*s == 'V') {
1054 s++;
1055 vlen = *s++ - '0';
1056 if (*s >= '0' && *s <= '9')
1057 vlen = vlen*10 + (*s++ - '0');
1059 switch (*s++) {
1060 case 'Q': sz = 1; break;
1061 case 'H': sz = 2; break;
1062 case 'S': sz = 4; break;
1063 case 'D': sz = 8; break;
1064 case 'T': sz = 16; break;
1065 case 'O': sz = 32; break;
1066 default: goto bad_size;
1068 if (*s == 'I' || *s == 'F') {
1069 CTF_INSERT(decl->attr, MSIZEP, sz);
1070 if (vlen) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vlen*sz));
1072 bad_size:
1073 cp_next(cp);
1075 cp_check(cp, ')');
1078 /* Parse GCC __attribute__((...)). */
1079 static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
1081 cp_next(cp);
1082 cp_check(cp, '(');
1083 cp_check(cp, '(');
1084 while (cp->tok != ')') {
1085 if (cp->tok == CTOK_IDENT) {
1086 GCstr *attrstr = cp->str;
1087 cp_next(cp);
1088 switch (attrstr->hash) {
1089 case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */
1090 cp_decl_align(cp, decl);
1091 break;
1092 case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */
1093 decl->attr |= CTFP_PACKED;
1094 break;
1095 case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */
1096 cp_decl_mode(cp, decl);
1097 break;
1098 case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */
1100 CTSize vsize = cp_decl_sizeattr(cp);
1101 if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
1103 break;
1104 #if LJ_TARGET_X86
1105 case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */
1106 CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1107 decl->fattr |= CTFP_CCONV;
1108 break;
1109 case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */
1110 CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1111 decl->fattr |= CTFP_CCONV;
1112 break;
1113 case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */
1114 CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1115 decl->fattr |= CTFP_CCONV;
1116 break;
1117 case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */
1118 CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1119 decl->fattr |= CTFP_CCONV;
1120 break;
1121 case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */
1122 CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1123 decl->fattr |= CTFP_CCONV;
1124 break;
1125 case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */
1126 decl->fattr |= CTF_SSEREGPARM;
1127 decl->fattr |= CTFP_CCONV;
1128 break;
1129 #endif
1130 default: /* Skip all other attributes. */
1131 goto skip_attr;
1133 } else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
1134 cp_next(cp);
1135 skip_attr:
1136 if (cp_opt(cp, '(')) {
1137 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1138 cp_check(cp, ')');
1140 } else {
1141 break;
1143 if (!cp_opt(cp, ',')) break;
1145 cp_check(cp, ')');
1146 cp_check(cp, ')');
1149 /* Parse MSVC __declspec(...). */
1150 static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
1152 cp_next(cp);
1153 cp_check(cp, '(');
1154 while (cp->tok == CTOK_IDENT) {
1155 GCstr *attrstr = cp->str;
1156 cp_next(cp);
1157 switch (attrstr->hash) {
1158 case H_(bc2395fa,98f267f8): /* align */
1159 cp_decl_align(cp, decl);
1160 break;
1161 default: /* Ignore all other attributes. */
1162 if (cp_opt(cp, '(')) {
1163 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1164 cp_check(cp, ')');
1166 break;
1169 cp_check(cp, ')');
1172 /* Parse declaration attributes (and common qualifiers). */
1173 static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1175 for (;;) {
1176 switch (cp->tok) {
1177 case CTOK_CONST: decl->attr |= CTF_CONST; break;
1178 case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
1179 case CTOK_RESTRICT: break; /* Ignore. */
1180 case CTOK_EXTENSION: break; /* Ignore. */
1181 case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
1182 case CTOK_ASM: cp_decl_asm(cp, decl); continue;
1183 case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
1184 case CTOK_CCDECL:
1185 #if LJ_TARGET_X86
1186 CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1187 decl->fattr |= CTFP_CCONV;
1188 #endif
1189 break;
1190 case CTOK_PTRSZ:
1191 #if LJ_64
1192 CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
1193 #endif
1194 break;
1195 default: return;
1197 cp_next(cp);
1201 /* Parse struct/union/enum name. */
1202 static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
1204 CTypeID sid;
1205 CType *ct;
1206 cp->tmask = CPNS_STRUCT;
1207 cp_next(cp);
1208 cp_decl_attributes(cp, sdecl);
1209 cp->tmask = CPNS_DEFAULT;
1210 if (cp->tok != '{') {
1211 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1212 if (cp->val.id) { /* Name of existing struct/union/enum. */
1213 sid = cp->val.id;
1214 ct = cp->ct;
1215 if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION)) /* Wrong type. */
1216 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1217 } else { /* Create named, incomplete struct/union/enum. */
1218 if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
1219 cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
1220 sid = lj_ctype_new(cp->cts, &ct);
1221 ct->info = info;
1222 ct->size = CTSIZE_INVALID;
1223 ctype_setname(ct, cp->str);
1224 lj_ctype_addname(cp->cts, ct, sid);
1226 cp_next(cp);
1227 } else { /* Create anonymous, incomplete struct/union/enum. */
1228 sid = lj_ctype_new(cp->cts, &ct);
1229 ct->info = info;
1230 ct->size = CTSIZE_INVALID;
1232 if (cp->tok == '{') {
1233 if (ct->size != CTSIZE_INVALID || ct->sib)
1234 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1235 ct->sib = 1; /* Indicate the type is currently being defined. */
1237 return sid;
1240 /* Determine field alignment. */
1241 static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
1243 CTSize align = ctype_align(info);
1244 UNUSED(cp); UNUSED(ct);
1245 #if (LJ_TARGET_X86 && !LJ_ABI_WIN) || (LJ_TARGET_ARM && __APPLE__)
1246 /* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
1247 if (align > 2 && !(info & CTFP_ALIGNED)) {
1248 if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
1249 do {
1250 ct = ctype_rawchild(cp->cts, ct);
1251 info = ct->info;
1252 } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1254 if (ctype_isnum(info) || ctype_isenum(info))
1255 align = 2;
1257 #endif
1258 return align;
1261 /* Layout struct/union fields. */
1262 static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1264 CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
1265 CTSize maxalign = ctype_align(sattr);
1266 CType *sct = ctype_get(cp->cts, sid);
1267 CTInfo sinfo = sct->info;
1268 CTypeID fieldid = sct->sib;
1269 while (fieldid) {
1270 CType *ct = ctype_get(cp->cts, fieldid);
1271 CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
1273 if (ctype_isfield(ct->info) ||
1274 (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
1275 CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
1276 CTSize sz;
1277 CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
1278 CTSize bsz, csz = 8*sz; /* Field size and container size (in bits). */
1279 sinfo |= (info & (CTF_QUAL|CTF_VLA)); /* Merge pseudo-qualifiers. */
1281 /* Check for size overflow and determine alignment. */
1282 if (sz >= 0x20000000u || bofs + csz < bofs) {
1283 if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
1284 !(sinfo & CTF_UNION)))
1285 cp_err(cp, LJ_ERR_FFI_INVSIZE);
1286 csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
1288 align = cp_field_align(cp, ct, info);
1289 if (((attr|sattr) & CTFP_PACKED) ||
1290 ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
1291 align = ctype_align(attr);
1292 if (cp->packstack[cp->curpack] < align)
1293 align = cp->packstack[cp->curpack];
1294 if (align > maxalign) maxalign = align;
1295 amask = (8u << align) - 1;
1297 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1298 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1299 bsz = csz; /* Regular fields or subtypes always fill the container. */
1300 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1301 ct->size = (bofs >> 3); /* Store field offset. */
1302 } else { /* Bitfield. */
1303 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
1304 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
1305 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1307 /* Prefer regular field over bitfield. */
1308 if (bsz == csz && (bofs & amask) == 0) {
1309 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
1310 ct->size = (bofs >> 3); /* Store field offset. */
1311 } else {
1312 ct->info = CTINFO(CT_BITFIELD,
1313 (info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
1314 (csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
1315 #if LJ_BE
1316 ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
1317 #else
1318 ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
1319 #endif
1320 ct->size = ((bofs & ~(csz-1)) >> 3); /* Store container offset. */
1324 /* Determine next offset or max. offset. */
1325 if ((sinfo & CTF_UNION)) {
1326 if (bsz > bmaxofs) bmaxofs = bsz;
1327 } else {
1328 bofs += bsz;
1330 } /* All other fields in the chain are already set up. */
1332 fieldid = ct->sib;
1335 /* Complete struct/union. */
1336 sct->info = sinfo + CTALIGN(maxalign);
1337 bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
1338 maxalign = (8u << maxalign) - 1;
1339 sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
1342 /* Parse struct/union declaration. */
1343 static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
1345 CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
1346 if (cp_opt(cp, '{')) { /* Struct/union definition. */
1347 CTypeID lastid = sid;
1348 int lastdecl = 0;
1349 while (cp->tok != '}') {
1350 CPDecl decl;
1351 CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
1352 decl.mode = scl ? CPARSE_MODE_DIRECT :
1353 CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
1355 for (;;) {
1356 CTypeID ctypeid;
1358 if (lastdecl) cp_err_token(cp, '}');
1360 /* Parse field declarator. */
1361 decl.bits = CTSIZE_INVALID;
1362 cp_declarator(cp, &decl);
1363 ctypeid = cp_decl_intern(cp, &decl);
1365 if ((scl & CDF_STATIC)) { /* Static constant in struct namespace. */
1366 CType *ct;
1367 CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
1368 ctype_get(cp->cts, lastid)->sib = fieldid;
1369 lastid = fieldid;
1370 ctype_setname(ct, decl.name);
1371 } else {
1372 CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
1373 CType *ct;
1374 CTypeID fieldid = lj_ctype_new(cp->cts, &ct); /* Do this first. */
1375 CType *tct = ctype_raw(cp->cts, ctypeid);
1377 if (decl.bits == CTSIZE_INVALID) { /* Regular field. */
1378 if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
1379 lastdecl = 1; /* a[] or a[?] must be the last declared field. */
1381 /* Accept transparent struct/union/enum. */
1382 if (!decl.name) {
1383 if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
1384 ctype_isenum(tct->info)))
1385 cp_err_token(cp, CTOK_IDENT);
1386 ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
1387 ct->size = ctype_isstruct(tct->info) ?
1388 (decl.attr|0x80000000u) : 0; /* For layout phase. */
1389 goto add_field;
1391 } else { /* Bitfield. */
1392 bsz = decl.bits;
1393 if (!ctype_isinteger_or_bool(tct->info) ||
1394 (bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
1395 bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
1396 cp_errmsg(cp, ':', LJ_ERR_BADVAL);
1399 /* Create temporary field for layout phase. */
1400 ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
1401 ct->size = decl.attr;
1402 if (decl.name) ctype_setname(ct, decl.name);
1404 add_field:
1405 ctype_get(cp->cts, lastid)->sib = fieldid;
1406 lastid = fieldid;
1408 if (!cp_opt(cp, ',')) break;
1409 cp_decl_reset(&decl);
1411 cp_check(cp, ';');
1413 cp_check(cp, '}');
1414 ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
1415 cp_decl_attributes(cp, sdecl); /* Layout phase needs postfix attributes. */
1416 cp_struct_layout(cp, sid, sdecl->attr);
1418 return sid;
1421 /* Parse enum declaration. */
1422 static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
1424 CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
1425 CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
1426 CTSize esize = 4; /* Only 32 bit enums are supported. */
1427 if (cp_opt(cp, '{')) { /* Enum definition. */
1428 CPValue k;
1429 CTypeID lastid = eid;
1430 k.u32 = 0;
1431 k.id = CTID_INT32;
1432 do {
1433 GCstr *name = cp->str;
1434 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1435 if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
1436 cp_next(cp);
1437 if (cp_opt(cp, '=')) {
1438 cp_expr_kint(cp, &k);
1439 if (k.id == CTID_UINT32) {
1440 /* C99 says that enum constants are always (signed) integers.
1441 ** But since unsigned constants like 0x80000000 are quite common,
1442 ** those are left as uint32_t.
1444 if (k.i32 >= 0) k.id = CTID_INT32;
1445 } else {
1446 /* OTOH it's common practice and even mandated by some ABIs
1447 ** that the enum type itself is unsigned, unless there are any
1448 ** negative constants.
1450 k.id = CTID_INT32;
1451 if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
1454 /* Add named enum constant. */
1456 CType *ct;
1457 CTypeID constid = lj_ctype_new(cp->cts, &ct);
1458 ctype_get(cp->cts, lastid)->sib = constid;
1459 lastid = constid;
1460 ctype_setname(ct, name);
1461 ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
1462 ct->size = k.u32++;
1463 if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
1464 lj_ctype_addname(cp->cts, ct, constid);
1466 if (!cp_opt(cp, ',')) break;
1467 } while (cp->tok != '}'); /* Trailing ',' is ok. */
1468 cp_check(cp, '}');
1469 /* Complete enum. */
1470 ctype_get(cp->cts, eid)->info = einfo;
1471 ctype_get(cp->cts, eid)->size = esize;
1473 return eid;
1476 /* Parse declaration specifiers. */
1477 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1479 uint32_t cds = 0, sz = 0;
1480 CTypeID tdef = 0;
1482 decl->cp = cp;
1483 decl->mode = cp->mode;
1484 decl->name = NULL;
1485 decl->redir = NULL;
1486 decl->attr = 0;
1487 decl->fattr = 0;
1488 decl->pos = decl->top = 0;
1489 decl->stack[0].next = 0;
1491 for (;;) { /* Parse basic types. */
1492 cp_decl_attributes(cp, decl);
1493 switch (cp->tok) {
1494 case CTOK_STRUCT:
1495 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
1496 break;
1497 case CTOK_UNION:
1498 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
1499 break;
1500 case CTOK_ENUM:
1501 tdef = cp_decl_enum(cp, decl);
1502 break;
1503 case CTOK_IDENT:
1504 if (!ctype_istypedef(cp->ct->info) || sz || tdef ||
1505 (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
1506 goto end_decl;
1507 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
1508 cp_next(cp);
1509 break;
1510 case '$':
1511 tdef = cp->val.id;
1512 cp_next(cp);
1513 break;
1514 default:
1515 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1516 uint32_t cbit;
1517 if (cp->ct->size) {
1518 if (sz) goto end_decl;
1519 sz = cp->ct->size;
1521 cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
1522 cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
1523 if (cp->tok >= CTOK_FIRSTSCL && !(scl & cbit))
1524 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
1525 cp_next(cp);
1526 break;
1528 goto end_decl;
1531 end_decl:
1533 if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
1534 tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
1536 if (tdef) {
1537 cp_push_type(decl, tdef);
1538 } else if ((cds & CDF_VOID)) {
1539 cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
1540 decl->attr &= ~CTF_QUAL;
1541 } else {
1542 /* Determine type info and size. */
1543 CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
1544 if ((cds & CDF_BOOL)) {
1545 if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
1546 cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
1547 info |= CTF_BOOL;
1548 if (!sz) {
1549 if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
1550 sz = 1;
1552 } else if ((cds & CDF_FP)) {
1553 info = CTINFO(CT_NUM, CTF_FP);
1554 if ((cds & CDF_LONG)) sz = sizeof(long double);
1555 } else if ((cds & CDF_CHAR)) {
1556 if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1557 info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
1558 } else if ((cds & CDF_SHORT)) {
1559 sz = sizeof(short);
1560 } else if ((cds & CDF_LONGLONG)) {
1561 sz = 8;
1562 } else if ((cds & CDF_LONG)) {
1563 info |= CTF_LONG;
1564 sz = sizeof(long);
1565 } else if (!sz) {
1566 if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
1567 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
1568 sz = sizeof(int);
1570 lua_assert(sz != 0);
1571 info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */
1572 info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
1573 cp_push(decl, info, sz);
1574 decl->attr &= ~CTF_QUAL;
1576 decl->specpos = decl->pos;
1577 decl->specattr = decl->attr;
1578 decl->specfattr = decl->fattr;
1579 return (cds & CDF_SCL); /* Return storage class. */
1582 /* Parse array declaration. */
1583 static void cp_decl_array(CPState *cp, CPDecl *decl)
1585 CTInfo info = CTINFO(CT_ARRAY, 0);
1586 CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
1587 cp_decl_attributes(cp, decl);
1588 if (cp_opt(cp, '?'))
1589 info |= CTF_VLA; /* Create variable-length array a[?]. */
1590 else if (cp->tok != ']')
1591 nelem = cp_expr_ksize(cp);
1592 cp_check(cp, ']');
1593 cp_add(decl, info, nelem);
1596 /* Parse function declaration. */
1597 static void cp_decl_func(CPState *cp, CPDecl *fdecl)
1599 CTSize nargs = 0;
1600 CTInfo info = CTINFO(CT_FUNC, 0);
1601 CTypeID lastid = 0, anchor = 0;
1602 if (cp->tok != ')') {
1603 do {
1604 CPDecl decl;
1605 CTypeID ctypeid, fieldid;
1606 CType *ct;
1607 if (cp_opt(cp, '.')) { /* Vararg function. */
1608 cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
1609 cp_check(cp, '.');
1610 info |= CTF_VARARG;
1611 break;
1613 cp_decl_spec(cp, &decl, CDF_REGISTER);
1614 decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
1615 cp_declarator(cp, &decl);
1616 ctypeid = cp_decl_intern(cp, &decl);
1617 ct = ctype_raw(cp->cts, ctypeid);
1618 if (ctype_isvoid(ct->info))
1619 break;
1620 else if (ctype_isrefarray(ct->info))
1621 ctypeid = lj_ctype_intern(cp->cts,
1622 CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
1623 else if (ctype_isfunc(ct->info))
1624 ctypeid = lj_ctype_intern(cp->cts,
1625 CTINFO(CT_PTR, CTALIGN_PTR|ctypeid), CTSIZE_PTR);
1626 /* Add new parameter. */
1627 fieldid = lj_ctype_new(cp->cts, &ct);
1628 if (anchor)
1629 ctype_get(cp->cts, lastid)->sib = fieldid;
1630 else
1631 anchor = fieldid;
1632 lastid = fieldid;
1633 if (decl.name) ctype_setname(ct, decl.name);
1634 ct->info = CTINFO(CT_FIELD, ctypeid);
1635 ct->size = nargs++;
1636 } while (cp_opt(cp, ','));
1638 cp_check(cp, ')');
1639 if (cp_opt(cp, '{')) { /* Skip function definition. */
1640 int level = 1;
1641 cp->mode |= CPARSE_MODE_SKIP;
1642 for (;;) {
1643 if (cp->tok == '{') level++;
1644 else if (cp->tok == '}' && --level == 0) break;
1645 else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
1646 cp_next(cp);
1648 cp->mode &= ~CPARSE_MODE_SKIP;
1649 cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
1651 info |= (fdecl->fattr & ~CTMASK_CID);
1652 fdecl->fattr = 0;
1653 fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
1656 /* Parse declarator. */
1657 static void cp_declarator(CPState *cp, CPDecl *decl)
1659 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
1661 for (;;) { /* Head of declarator. */
1662 if (cp_opt(cp, '*')) { /* Pointer. */
1663 CTSize sz;
1664 CTInfo info;
1665 cp_decl_attributes(cp, decl);
1666 sz = CTSIZE_PTR;
1667 info = CTINFO(CT_PTR, CTALIGN_PTR);
1668 #if LJ_64
1669 if (ctype_msizeP(decl->attr) == 4) {
1670 sz = 4;
1671 info = CTINFO(CT_PTR, CTALIGN(2));
1673 #endif
1674 info += (decl->attr & (CTF_QUAL|CTF_REF));
1675 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1676 cp_push(decl, info, sz);
1677 } else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) { /* Reference. */
1678 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1679 cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
1680 } else {
1681 break;
1685 if (cp_opt(cp, '(')) { /* Inner declarator. */
1686 CPDeclIdx pos;
1687 cp_decl_attributes(cp, decl);
1688 /* Resolve ambiguity between inner declarator and 1st function parameter. */
1689 if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
1690 (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
1691 pos = decl->pos;
1692 cp_declarator(cp, decl);
1693 cp_check(cp, ')');
1694 decl->pos = pos;
1695 } else if (cp->tok == CTOK_IDENT) { /* Direct declarator. */
1696 if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
1697 decl->name = cp->str;
1698 decl->nameid = cp->val.id;
1699 cp_next(cp);
1700 } else { /* Abstract declarator. */
1701 if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
1704 for (;;) { /* Tail of declarator. */
1705 if (cp_opt(cp, '[')) { /* Array. */
1706 cp_decl_array(cp, decl);
1707 } else if (cp_opt(cp, '(')) { /* Function. */
1708 func_decl:
1709 cp_decl_func(cp, decl);
1710 } else {
1711 break;
1715 if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
1716 decl->bits = cp_expr_ksize(cp);
1718 /* Process postfix attributes. */
1719 cp_decl_attributes(cp, decl);
1720 cp_push_attributes(decl);
1722 cp->depth--;
1725 /* Parse an abstract type declaration and return it's C type ID. */
1726 static CTypeID cp_decl_abstract(CPState *cp)
1728 CPDecl decl;
1729 cp_decl_spec(cp, &decl, 0);
1730 decl.mode = CPARSE_MODE_ABSTRACT;
1731 cp_declarator(cp, &decl);
1732 return cp_decl_intern(cp, &decl);
1735 /* Handle pragmas. */
1736 static void cp_pragma(CPState *cp, BCLine pragmaline)
1738 cp_next(cp);
1739 if (cp->tok == CTOK_IDENT &&
1740 cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */
1741 cp_next(cp);
1742 cp_check(cp, '(');
1743 if (cp->tok == CTOK_IDENT) {
1744 if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */
1745 if (cp->curpack < CPARSE_MAX_PACKSTACK) {
1746 cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
1747 cp->curpack++;
1749 } else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */
1750 if (cp->curpack > 0) cp->curpack--;
1751 } else {
1752 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1754 cp_next(cp);
1755 if (!cp_opt(cp, ',')) goto end_pack;
1757 if (cp->tok == CTOK_INTEGER) {
1758 cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
1759 cp_next(cp);
1760 } else {
1761 cp->packstack[cp->curpack] = 255;
1763 end_pack:
1764 cp_check(cp, ')');
1765 } else { /* Ignore all other pragmas. */
1766 while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
1767 cp_next(cp);
1771 /* Parse multiple C declarations of types or extern identifiers. */
1772 static void cp_decl_multi(CPState *cp)
1774 int first = 1;
1775 while (cp->tok != CTOK_EOF) {
1776 CPDecl decl;
1777 CPscl scl;
1778 if (cp_opt(cp, ';')) { /* Skip empty statements. */
1779 first = 0;
1780 continue;
1782 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
1783 BCLine pragmaline = cp->linenumber;
1784 if (!(cp_next(cp) == CTOK_IDENT &&
1785 cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */
1786 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1787 cp_pragma(cp, pragmaline);
1788 continue;
1790 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
1791 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
1792 ctype_istypedef(decl.stack[0].info)) {
1793 CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
1794 if (ctype_isstruct(info) || ctype_isenum(info))
1795 goto decl_end; /* Accept empty declaration of struct/union/enum. */
1797 for (;;) {
1798 CTypeID ctypeid;
1799 cp_declarator(cp, &decl);
1800 ctypeid = cp_decl_intern(cp, &decl);
1801 if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */
1802 CType *ct;
1803 CTypeID id;
1804 if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */
1805 id = lj_ctype_new(cp->cts, &ct);
1806 ct->info = CTINFO(CT_TYPEDEF, ctypeid);
1807 goto noredir;
1808 } else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info)) {
1809 /* Treat both static and extern function declarations as extern. */
1810 ct = ctype_get(cp->cts, ctypeid);
1811 /* We always get new anonymous functions (typedefs are copied). */
1812 lua_assert(gcref(ct->name) == NULL);
1813 id = ctypeid; /* Just name it. */
1814 } else if ((scl & CDF_STATIC)) { /* Accept static constants. */
1815 id = cp_decl_constinit(cp, &ct, ctypeid);
1816 goto noredir;
1817 } else { /* External references have extern or no storage class. */
1818 id = lj_ctype_new(cp->cts, &ct);
1819 ct->info = CTINFO(CT_EXTERN, ctypeid);
1821 if (decl.redir) { /* Add attribute for redirected symbol name. */
1822 CType *cta;
1823 CTypeID aid = lj_ctype_new(cp->cts, &cta);
1824 ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
1825 cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
1826 cta->sib = ct->sib;
1827 ct->sib = aid;
1828 ctype_setname(cta, decl.redir);
1830 noredir:
1831 ctype_setname(ct, decl.name);
1832 lj_ctype_addname(cp->cts, ct, id);
1834 if (!cp_opt(cp, ',')) break;
1835 cp_decl_reset(&decl);
1837 decl_end:
1838 if (cp->tok == CTOK_EOF && first) break; /* May omit ';' for 1 decl. */
1839 first = 0;
1840 cp_check(cp, ';');
1844 /* Parse a single C type declaration. */
1845 static void cp_decl_single(CPState *cp)
1847 CPDecl decl;
1848 cp_decl_spec(cp, &decl, 0);
1849 cp_declarator(cp, &decl);
1850 cp->val.id = cp_decl_intern(cp, &decl);
1851 if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
1854 #undef H_
1856 /* ------------------------------------------------------------------------ */
1858 /* Protected callback for C parser. */
1859 static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
1861 CPState *cp = (CPState *)ud;
1862 UNUSED(dummy);
1863 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
1864 cp_init(cp);
1865 if ((cp->mode & CPARSE_MODE_MULTI))
1866 cp_decl_multi(cp);
1867 else
1868 cp_decl_single(cp);
1869 if (cp->param && cp->param != cp->L->top)
1870 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
1871 lua_assert(cp->depth == 0);
1872 return NULL;
1875 /* C parser. */
1876 int lj_cparse(CPState *cp)
1878 LJ_CTYPE_SAVE(cp->cts);
1879 int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
1880 if (errcode)
1881 LJ_CTYPE_RESTORE(cp->cts);
1882 cp_cleanup(cp);
1883 return errcode;
1886 #endif