• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/lib/ffi/uc_cparse.c

  1 /*
  2 ** C declaration parser.
  3 ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice below.
  4 **
  5 ** This file contains derived work from LuaJIT's FFI C parser (uc_cparse.c).
  6 **
  7 ** Modifications:
  8 ** - Adapted VM interactions to use ucode's API (uc_vm_t, uc_value_t, etc.)
  9 ** - Removed JIT-specific code and dependencies
 10 ** - Adapted error handling to use ucode exceptions
 11 **
 12 ** See NOTICE and ATTRIBUTION.md for complete attribution details.
 13 */
 14 
 15 #include <ctype.h>
 16 #include <ucode/vm.h>
 17 #include "uc_ctype.h"
 18 #include "uc_cparse.h"
 19 
 20 #include "ucode/util.h"
 21 
 22 /*
 23 ** Important note: this is NOT a validating C parser! This is a minimal
 24 ** C declaration parser, solely for use by the LuaJIT FFI.
 25 **
 26 ** It ought to return correct results for properly formed C declarations,
 27 ** but it may accept some invalid declarations, too (and return nonsense).
 28 ** Also, it shows rather generic error messages to avoid unnecessary bloat.
 29 ** If in doubt, please check the input against your favorite C compiler.
 30 */
 31 
 32 /* Assertions disabled for production build. */
 33 #define uc_assertCP(c, ...) ((void)0)
 34 
 35 /* Check if two function types are structurally equivalent. */
 36 static bool
 37 ctype_func_is_equiv(CTState *cts, CType *ct1, CType *ct2)
 38 {
 39         CType *p1, *p2;
 40 
 41         if (ct1->info != ct2->info || ct1->size != ct2->size) {
 42                 return false;
 43         }
 44 
 45         /* Compare parameter chains. */
 46         p1 = ctype_get(cts, ct1->sib);
 47         p2 = ctype_get(cts, ct2->sib);
 48 
 49         while (p1 && p2) {
 50                 /* Stop at non-field entries (end of parameters or attributes). */
 51                 if (!ctype_isfield(p1->info) || !ctype_isfield(p2->info))
 52                         break;
 53                 if (p1->info != p2->info || p1->size != p2->size) {
 54                         return false;
 55                 }
 56                 p1 = ctype_get(cts, p1->sib);
 57                 p2 = ctype_get(cts, p2->sib);
 58         }
 59 
 60         return (p1 == p2);
 61 }
 62 
 63 /* -- Miscellaneous ------------------------------------------------------- */
 64 
 65 /* Match string against a C literal. */
 66 #define cp_str_is(str, k) \
 67         (ucv_string_length(str) == sizeof(k) - 1 && !memcmp(ucv_string_get(str), k, sizeof(k) - 1))
 68 
 69 /* Check string against a linear list of matches. */
 70 int uc_cparse_case(uc_value_t *str, const char *match)
 71 {
 72         size_t len;
 73         int n;
 74         for (n = 0; (len = *match++); n++, match += len)
 75         {
 76                 if (ucv_string_length(str) == len && !memcmp(match, ucv_string_get(str), len))
 77                         return n;
 78         }
 79         return -1;
 80 }
 81 
 82 /* -- C lexer ------------------------------------------------------------- */
 83 
 84 /* C lexer token names. */
 85 static const char *const ctoknames[] = {
 86 #define CTOKSTR(name, str) str,
 87         CTOKDEF(CTOKSTR)
 88 #undef CTOKSTR
 89                 NULL};
 90 
 91 /* Forward declaration. */
 92 static void cp_err(CPState *cp, const char *em);
 93 
 94 static const char *cp_tok2str(CPState *cp, CPToken tok)
 95 {
 96         char *e;
 97         uc_assertCP(tok < CTOK_FIRSTDECL, "bad CPToken %d", tok);
 98         if (tok > CTOK_OFS)
 99                 return ctoknames[tok - CTOK_OFS - 1];
100         else if (!iscntrl(tok))
101         {
102                 xasprintf(&e, "%c", tok);
103                 return e;
104         }
105         else
106         {
107                 xasprintf(&e, "char(%d)", tok);
108                 return e;
109         }
110 }
111 
112 /* End-of-line? */
113 static UC_AINLINE int cp_iseol(CPChar c)
114 {
115         return (c == '\n' || c == '\r');
116 }
117 
118 /* Peek next raw character. */
119 static UC_AINLINE CPChar cp_rawpeek(CPState *cp)
120 {
121         return (CPChar)(uint8_t)(*cp->p);
122 }
123 
124 static UC_NOINLINE CPChar cp_get_bs(CPState *cp);
125 
126 /* Get next character. */
127 static UC_AINLINE CPChar cp_get(CPState *cp)
128 {
129         cp->c = (CPChar)(uint8_t)(*cp->p++);
130         if (UC_LIKELY(cp->c != '\\'))
131                 return cp->c;
132         return cp_get_bs(cp);
133 }
134 
135 /* Transparently skip backslash-escaped line breaks. */
136 static UC_NOINLINE CPChar cp_get_bs(CPState *cp)
137 {
138         CPChar c2, c = cp_rawpeek(cp);
139         if (!cp_iseol(c))
140                 return cp->c;
141         cp->p++;
142         c2 = cp_rawpeek(cp);
143         if (cp_iseol(c2) && c2 != c)
144                 cp->p++;
145         cp->linenumber++;
146         return cp_get(cp);
147 }
148 
149 /* Save character in buffer. */
150 static UC_AINLINE void cp_save(CPState *cp, CPChar c)
151 {
152         sprintbuf(&cp->pb, "%c", c);
153 }
154 
155 /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
156 static void cp_newline(CPState *cp)
157 {
158         CPChar c = cp_rawpeek(cp);
159         if (cp_iseol(c) && c != cp->c)
160                 cp->p++;
161         cp->linenumber++;
162 }
163 
164 static void __attribute__((format(printf, 3, 0)))
165 cp_errmsg(CPState *cp, CPToken tok, const char *em, ...)
166 {
167         const char *tokstr;
168         char *s, *msg;
169         va_list argp;
170 
171         if (cp->error)
172                 return;
173 
174         if (tok == 0)
175         {
176                 tokstr = NULL;
177         }
178         else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
179                          tok >= CTOK_FIRSTDECL)
180         {
181                 if (cp->pb.bpos == 0)
182                         cp_save(cp, '$');
183                 cp_save(cp, '\0');
184                 tokstr = cp->pb.buf;
185         }
186         else
187         {
188                 tokstr = cp_tok2str(cp, tok);
189         }
190         va_start(argp, em);
191         xvasprintf(&msg, em, argp);
192         va_end(argp);
193         if (tokstr)
194         {
195                 xasprintf(&s, "%s near '%s'", msg, tokstr);
196                 free(msg);
197                 msg = s;
198         }
199         if (cp->linenumber > 1)
200         {
201                 xasprintf(&s, "%s at line %d", msg, cp->linenumber);
202                 free(msg);
203                 msg = s;
204         }
205 
206         cp->error = msg;
207 }
208 
209 static void cp_err_token(CPState *cp, CPToken tok)
210 {
211         cp_errmsg(cp, cp->tok, "'%s' expected", cp_tok2str(cp, tok));
212 }
213 
214 static void cp_err_badidx(CPState *cp, CType *ct)
215 {
216         uc_value_t *s = uc_ctype_repr(cp->uv_vm, ctype_typeid(cp->cts, ct), NULL);
217         cp_errmsg(cp, 0, "'%s' cannot be indexed", ucv_string_get(s));
218         ucv_put(s);
219 }
220 
221 static void cp_err(CPState *cp, const char *em)
222 {
223         cp_errmsg(cp, 0, "%s", em);
224 }
225 
226 /* -- Main lexical scanner ------------------------------------------------ */
227 
228 static inline bool is_ident(uint8_t c)
229 {
230         return (c >= 48 && c <= 57) ||
231                    (c >= 65 && c <= 90) ||
232                    (c == '_') ||
233                    (c >= 97 && c <= 122) ||
234                    (c >= 128);
235 }
236 
237 /* Parse number literal. Only handles int32_t/uint32_t right now. */
238 static CPToken cp_number(CPState *cp)
239 {
240         unsigned long long val;
241         bool sign = false;
242         int base = 0;
243         char *s, *e;
244 
245         do
246         {
247                 cp_save(cp, cp->c);
248         } while (is_ident(cp_get(cp)));
249 
250         cp_save(cp, '\0');
251 
252         s = cp->pb.buf;
253 
254         while (isspace(*s))
255                 s++;
256 
257         if (*s == '-')
258         {
259                 sign = true;
260                 s++;
261         }
262         else if (*s == '+')
263         {
264                 s++;
265         }
266 
267         if (*s == '')
268         {
269                 switch (s[1] | 32)
270                 {
271                 case 'x':
272                         base = 16;
273                         s += 2;
274                         break;
275 
276                 case 'o':
277                         base = 8;
278                         s += 2;
279                         break;
280 
281                 case 'b':
282                         base = 2;
283                         s += 2;
284                         break;
285                 }
286         }
287 
288         val = strtoull(s, &e, base);
289 
290         /* handle potential suffix */
291         if (!strcasecmp(e, "ull") || !strcasecmp(e, "llu"))
292         {
293                 if (sizeof(unsigned long long) > sizeof(uint32_t) && !(cp->mode & CPARSE_MODE_SKIP))
294                         cp_errmsg(cp, CTOK_INTEGER, "malformed number");
295 
296                 cp->val.id = CTID_UINT32;
297                 e += 3;
298         }
299         else if (!strcasecmp(e, "ll"))
300         {
301                 if (sizeof(long long) > sizeof(int32_t) && !(cp->mode & CPARSE_MODE_SKIP))
302                         cp_errmsg(cp, CTOK_INTEGER, "malformed number");
303 
304                 cp->val.id = CTID_INT32;
305                 e += 2;
306         }
307         else if (!strcasecmp(e, "ul") || !strcasecmp(e, "lu"))
308         {
309                 if (sizeof(unsigned long) > sizeof(uint32_t) && !(cp->mode & CPARSE_MODE_SKIP))
310                         cp_errmsg(cp, CTOK_INTEGER, "malformed number");
311 
312                 cp->val.id = CTID_UINT32;
313                 e += 2;
314         }
315         else if ((*e | 32) == 'u')
316         {
317                 cp->val.id = CTID_UINT32;
318                 e++;
319         }
320         else if ((*e | 32) == 'l')
321         {
322                 if (sizeof(long) > sizeof(int32_t) && !(cp->mode & CPARSE_MODE_SKIP))
323                         cp_errmsg(cp, CTOK_INTEGER, "malformed number");
324 
325                 cp->val.id = CTID_INT32;
326                 e++;
327         }
328         else if ((*e | 32) == 'i')
329         {
330                 if (!(cp->mode & CPARSE_MODE_SKIP))
331                         cp_errmsg(cp, CTOK_INTEGER, "malformed number");
332 
333                 e++;
334         }
335         else
336         {
337                 cp->val.id = CTID_INT32;
338         }
339 
340         while (isspace(*e))
341                 e++;
342 
343         if (*e)
344                 cp_errmsg(cp, CTOK_INTEGER, "malformed number");
345 
346         cp->val.u32 = sign ? (uint32_t)-val : (uint32_t)val;
347         return CTOK_INTEGER;
348 }
349 
350 /* Parse identifier or keyword. */
351 static CPToken cp_ident(CPState *cp)
352 {
353         do
354         {
355                 cp_save(cp, cp->c);
356         } while (is_ident(cp_get(cp)));
357         ucv_put(cp->uv_str);
358         cp->uv_str = ucv_string_new(cp->pb.buf);
359         // cp->str = lj_buf_str(cp->L, &cp->sb);
360         cp->val.id = uc_ctype_getname(cp->cts, &cp->ct, cp->uv_str, cp->tmask);
361 
362         if (ctype_type(cp->ct->info) == CT_KW)
363                 return ctype_cid(cp->ct->info);
364         return CTOK_IDENT;
365 }
366 
367 /* Parse parameter. */
368 static CPToken cp_param(CPState *cp)
369 {
370         CPChar c = cp_get(cp);
371         // TValue *o = cp->param;
372         uc_value_t **uv = cp->uv_param;
373         if (is_ident(c) || c == '$') /* Reserve $xyz for future extensions. */ {
374                 cp_errmsg(cp, c, "syntax error");
375                 return CTOK_EOF;
376         }
377         if (!uv || uv >= &cp->uv_vm->stack.entries[cp->uv_vm->stack.count]) {
378                 cp_err(cp, "wrong number of type parameters");
379                 return CTOK_EOF;
380         }
381         cp->uv_param = uv + 1;
382         if (ucv_type(*uv) == UC_STRING)
383         {
384                 ucv_put(cp->uv_str);
385                 cp->uv_str = ucv_get(*uv);
386                 cp->val.id = 0;
387                 cp->ct = &cp->cts->vtab.entries[0];
388                 return CTOK_IDENT;
389         }
390         else if (ucv_type(*uv) == UC_INTEGER)
391         {
392                 cp->val.i32 = (int32_t)ucv_int64_get(*uv);
393                 cp->val.id = CTID_INT32;
394                 return CTOK_INTEGER;
395         }
396         else
397         {
398                 void *ctype = ucv_resource_dataptr(*uv, "ffi.ctype");
399                 if (!ctype)
400                         cp_errmsg(cp, 0, "type parameter expected, got %s", ucv_typename(*uv));
401                 // lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
402                 cp->val.id = (CTypeID)(uintptr_t)ctype;
403                 return '$';
404         }
405 }
406 
407 /* Parse string or character constant. */
408 static CPToken cp_string(CPState *cp)
409 {
410         CPChar delim = cp->c;
411         cp_get(cp);
412         while (cp->c != delim)
413         {
414                 CPChar c = cp->c;
415                 if (c == '\0') {
416                         cp_errmsg(cp, CTOK_EOF, "unfinished string");
417                         return CTOK_EOF;
418                 }
419                 if (c == '\\')
420                 {
421                         c = cp_get(cp);
422                         switch (c)
423                         {
424                         case '\0':
425                                 cp_errmsg(cp, CTOK_EOF, "unfinished string");
426                                 return CTOK_EOF;
427                         case 'a':
428                                 c = '\a';
429                                 break;
430                         case 'b':
431                                 c = '\b';
432                                 break;
433                         case 'f':
434                                 c = '\f';
435                                 break;
436                         case 'n':
437                                 c = '\n';
438                                 break;
439                         case 'r':
440                                 c = '\r';
441                                 break;
442                         case 't':
443                                 c = '\t';
444                                 break;
445                         case 'v':
446                                 c = '\v';
447                                 break;
448                         case 'e':
449                                 c = 27;
450                                 break;
451                         case 'x':
452                                 c = 0;
453                                 while (isxdigit(cp_get(cp)))
454                                         c = (c << 4) + (isdigit(cp->c) ? cp->c - '' : (cp->c & 15) + 9);
455                                 cp_save(cp, (c & 0xff));
456                                 continue;
457                         default:
458                                 if (isdigit(c))
459                                 {
460                                         c -= '';
461                                         if (isdigit(cp_get(cp)))
462                                         {
463                                                 c = c * 8 + (cp->c - '');
464                                                 if (isdigit(cp_get(cp)))
465                                                 {
466                                                         c = c * 8 + (cp->c - '');
467                                                         cp_get(cp);
468                                                 }
469                                         }
470                                         cp_save(cp, (c & 0xff));
471                                         continue;
472                                 }
473                                 break;
474                         }
475                 }
476                 cp_save(cp, c);
477                 cp_get(cp);
478         }
479         cp_get(cp);
480         if (delim == '"')
481         {
482                 // FIXME: consider ucv_stringbuf_new
483                 ucv_put(cp->uv_str);
484                 cp->uv_str = ucv_string_new(cp->pb.buf);
485                 // cp->str = lj_buf_str(cp->L, &cp->sb);
486                 return CTOK_STRING;
487         }
488         else
489         {
490                 if (printbuf_length(&cp->pb) != 1)
491                         cp_err_token(cp, '\'');
492                 cp->val.i32 = (int32_t)(char)*cp->pb.buf;
493                 cp->val.id = CTID_INT32;
494                 return CTOK_INTEGER;
495         }
496 }
497 
498 /* Skip C comment. */
499 static void cp_comment_c(CPState *cp)
500 {
501         do
502         {
503                 if (cp_get(cp) == '*')
504                 {
505                         do
506                         {
507                                 if (cp_get(cp) == '/')
508                                 {
509                                         cp_get(cp);
510                                         return;
511                                 }
512                         } while (cp->c == '*');
513                 }
514                 if (cp_iseol(cp->c))
515                         cp_newline(cp);
516         } while (cp->c != '\0');
517 }
518 
519 /* Skip C++ comment. */
520 static void cp_comment_cpp(CPState *cp)
521 {
522         while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
523                 ;
524 }
525 
526 /* Lexical scanner for C. Only a minimal subset is implemented. */
527 static CPToken cp_next_(CPState *cp)
528 {
529         //lj_buf_reset(&cp->sb);
530         if (cp->pb.buf)
531                 printbuf_reset(&cp->pb);
532 
533         for (;;)
534         {
535                 if (is_ident(cp->c))
536                         return isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
537                 switch (cp->c)
538                 {
539                 case '\n':
540                 case '\r':
541                         cp_newline(cp); /* fallthrough. */
542                 case ' ':
543                 case '\t':
544                 case '\v':
545                 case '\f':
546                         cp_get(cp);
547                         break;
548                 case '"':
549                 case '\'':
550                         return cp_string(cp);
551                 case '/':
552                         if (cp_get(cp) == '*')
553                                 cp_comment_c(cp);
554                         else if (cp->c == '/')
555                                 cp_comment_cpp(cp);
556                         else
557                                 return '/';
558                         break;
559                 case '|':
560                         if (cp_get(cp) != '|')
561                                 return '|';
562                         cp_get(cp);
563                         return CTOK_OROR;
564                 case '&':
565                         if (cp_get(cp) != '&')
566                                 return '&';
567                         cp_get(cp);
568                         return CTOK_ANDAND;
569                 case '=':
570                         if (cp_get(cp) != '=')
571                                 return '=';
572                         cp_get(cp);
573                         return CTOK_EQ;
574                 case '!':
575                         if (cp_get(cp) != '=')
576                                 return '!';
577                         cp_get(cp);
578                         return CTOK_NE;
579                 case '<':
580                         if (cp_get(cp) == '=')
581                         {
582                                 cp_get(cp);
583                                 return CTOK_LE;
584                         }
585                         else if (cp->c == '<')
586                         {
587                                 cp_get(cp);
588                                 return CTOK_SHL;
589                         }
590                         return '<';
591                 case '>':
592                         if (cp_get(cp) == '=')
593                         {
594                                 cp_get(cp);
595                                 return CTOK_GE;
596                         }
597                         else if (cp->c == '>')
598                         {
599                                 cp_get(cp);
600                                 return CTOK_SHR;
601                         }
602                         return '>';
603                 case '-':
604                         if (cp_get(cp) != '>')
605                                 return '-';
606                         cp_get(cp);
607                         return CTOK_DEREF;
608                 case '$':
609                         return cp_param(cp);
610                 case '\0':
611                         return CTOK_EOF;
612                 default:
613                 {
614                         CPToken c = cp->c;
615                         cp_get(cp);
616                         return c;
617                 }
618                 }
619         }
620 }
621 
622 static UC_NOINLINE CPToken cp_next(CPState *cp)
623 {
624         return (cp->tok = cp_next_(cp));
625 }
626 
627 /* -- C parser ------------------------------------------------------------ */
628 
629 /* Namespaces for resolving identifiers. */
630 #define CPNS_DEFAULT \
631         ((1u << CT_KW) | (1u << CT_TYPEDEF) | (1u << CT_FUNC) | (1u << CT_EXTERN) | (1u << CT_CONSTVAL))
632 #define CPNS_STRUCT ((1u << CT_KW) | (1u << CT_STRUCT) | (1u << CT_ENUM))
633 
634 typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
635 typedef uint32_t CPscl;    /* Storage class flags. */
636 
637 /* Type declaration context. */
638 typedef struct CPDecl
639 {
640         CPDeclIdx top;                                     /* Top of declaration stack. */
641         CPDeclIdx pos;                                     /* Insertion position in declaration chain. */
642         CPDeclIdx specpos;                                 /* Saved position for declaration specifier. */
643         uint32_t mode;                                     /* Declarator mode. */
644         CPState *cp;                                       /* C parser state. */
645         CTypeID nameid;                                    /* Existing typedef for declared identifier. */
646         CTInfo attr;                                       /* Attributes. */
647         CTInfo fattr;                                      /* Function attributes. */
648         CTInfo specattr;                                   /* Saved attributes. */
649         CTInfo specfattr;                                  /* Saved function attributes. */
650         CTSize bits;                                       /* Field size in bits (if any). */
651         CType stack[CPARSE_MAX_DECLSTACK]; /* Type declaration stack. */
652         uc_value_t *uv_name;
653         uc_value_t *uv_redir;
654 } CPDecl;
655 
656 /* Forward declarations. */
657 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
658 static void cp_declarator(CPState *cp, CPDecl *decl);
659 static CTypeID cp_decl_abstract(CPState *cp);
660 
661 /* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
662 static void cp_init(CPState *cp)
663 {
664         cp->error = NULL;
665         cp->linenumber = 1;
666         cp->depth = 0;
667         cp->curpack = 0;
668         cp->packstack[0] = 255;
669         cp->pb.bpos = 0;
670         cp->pb.buf = 0;
671         cp->pb.size = 0;
672         cp->uv_str = NULL;
673         // lj_buf_init(cp->L, &cp->sb);
674         uc_assertCP(cp->p != NULL, "uninitialized cp->p");
675         cp_get(cp); /* Read-ahead first char. */
676         cp->tok = 0;
677         cp->tmask = CPNS_DEFAULT;
678         cp_next(cp); /* Read-ahead first token. */
679 }
680 
681 /* Cleanup C parser state. */
682 static void cp_cleanup(CPState *cp)
683 {
684         // global_State *g = G(cp->L);
685         // lj_buf_free(g, &cp->sb);
686         ucv_put(cp->uv_str);
687         free(cp->pb.buf);
688         free(cp->error);
689 }
690 
691 /* Check and consume optional token. */
692 static int cp_opt(CPState *cp, CPToken tok)
693 {
694         if (cp->tok == tok)
695         {
696                 cp_next(cp);
697                 return 1;
698         }
699         return 0;
700 }
701 
702 /* Check and consume token. */
703 static void cp_check(CPState *cp, CPToken tok)
704 {
705         if (cp->tok != tok)
706                 cp_err_token(cp, tok);
707         cp_next(cp);
708 }
709 
710 /* Check if the next token may start a type declaration. */
711 static int cp_istypedecl(CPState *cp)
712 {
713         if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL)
714                 return 1;
715         if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info))
716                 return 1;
717         if (cp->tok == '$')
718                 return 1;
719         return 0;
720 }
721 
722 /* -- Constant expression evaluator --------------------------------------- */
723 
724 /* Forward declarations. */
725 static void cp_expr_unary(CPState *cp, CPValue *k);
726 static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
727 
728 /* Please note that type handling is very weak here. Most ops simply
729 ** assume integer operands. Accessors are only needed to compute types and
730 ** return synthetic values. The only purpose of the expression evaluator
731 ** is to compute the values of constant expressions one would typically
732 ** find in C header files. And again: this is NOT a validating C parser!
733 */
734 
735 /* Parse comma separated expression and return last result. */
736 static void cp_expr_comma(CPState *cp, CPValue *k)
737 {
738         do
739         {
740                 cp_expr_sub(cp, k, 0);
741                 if (cp->error)
742                         return;
743         } while (cp_opt(cp, ','));
744 }
745 
746 /* Parse sizeof/alignof operator. */
747 static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
748 {
749         CTSize sz;
750         CTInfo info;
751         if (cp_opt(cp, '('))
752         {
753                 if (cp_istypedecl(cp))
754                         k->id = cp_decl_abstract(cp);
755                 else
756                         cp_expr_comma(cp, k);
757                 cp_check(cp, ')');
758         }
759         else
760         {
761                 cp_expr_unary(cp, k);
762         }
763         info = uc_ctype_info_raw(cp->cts, k->id, &sz);
764         if (wantsz)
765         {
766                 if (sz != CTSIZE_INVALID)
767                         k->u32 = sz;
768                 else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
769                 {
770                         cp_err(cp, "size of C type is unknown or too large");
771                         return;
772                 }
773         }
774         else
775         {
776                 k->u32 = 1u << ctype_align(info);
777         }
778         k->id = CTID_UINT32; /* Really size_t. */
779 }
780 
781 /* Parse prefix operators. */
782 static void cp_expr_prefix(CPState *cp, CPValue *k)
783 {
784         if (cp->tok == CTOK_INTEGER)
785         {
786                 *k = cp->val;
787                 cp_next(cp);
788         }
789         else if (cp_opt(cp, '+'))
790         {
791                 cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
792         }
793         else if (cp_opt(cp, '-'))
794         {
795                 cp_expr_unary(cp, k);
796                 k->i32 = (int32_t)(~(uint32_t)k->i32 + 1);
797         }
798         else if (cp_opt(cp, '~'))
799         {
800                 cp_expr_unary(cp, k);
801                 k->i32 = ~k->i32;
802         }
803         else if (cp_opt(cp, '!'))
804         {
805                 cp_expr_unary(cp, k);
806                 k->i32 = !k->i32;
807                 k->id = CTID_INT32;
808         }
809         else if (cp_opt(cp, '('))
810         {
811                 if (cp_istypedecl(cp))
812                 { /* Cast operator. */
813                         CTypeID id = cp_decl_abstract(cp);
814                         cp_check(cp, ')');
815                         cp_expr_unary(cp, k);
816                         k->id = id; /* No conversion performed. */
817                 }
818                 else
819                 { /* Sub-expression. */
820                         cp_expr_comma(cp, k);
821                         cp_check(cp, ')');
822                 }
823         }
824         else if (cp_opt(cp, '*'))
825         { /* Indirection. */
826                 CType *ct;
827                 cp_expr_unary(cp, k);
828                 if (cp->error)
829                         return;
830                 ct = uc_ctype_rawref(cp->cts, k->id);
831                 if (!ctype_ispointer(ct->info))
832                 {
833                         cp_err_badidx(cp, ct);
834                         return;
835                 }
836                 k->u32 = 0;
837                 k->id = ctype_cid(ct->info);
838         }
839         else if (cp_opt(cp, '&'))
840         { /* Address operator. */
841                 cp_expr_unary(cp, k);
842                 k->id = uc_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR + k->id),
843                                                                 CTSIZE_PTR);
844         }
845         else if (cp_opt(cp, CTOK_SIZEOF))
846         {
847                 cp_expr_sizeof(cp, k, 1);
848         }
849         else if (cp_opt(cp, CTOK_ALIGNOF))
850         {
851                 cp_expr_sizeof(cp, k, 0);
852         }
853         else if (cp->tok == CTOK_IDENT)
854         {
855                 if (ctype_type(cp->ct->info) == CT_CONSTVAL)
856                 {
857                         k->u32 = cp->ct->size;
858                         k->id = ctype_cid(cp->ct->info);
859                 }
860                 else if (ctype_type(cp->ct->info) == CT_EXTERN)
861                 {
862                         k->u32 = cp->val.id;
863                         k->id = ctype_cid(cp->ct->info);
864                 }
865                 else if (ctype_type(cp->ct->info) == CT_FUNC)
866                 {
867                         k->u32 = cp->val.id;
868                         k->id = cp->val.id;
869                 }
870                 else
871                 {
872                         goto err_expr;
873                 }
874                 cp_next(cp);
875         }
876         else if (cp->tok == CTOK_STRING)
877         {
878                 CTSize sz = ucv_string_length(cp->uv_str);
879                 while (cp_next(cp) == CTOK_STRING)
880                         sz += ucv_string_length(cp->uv_str);
881                 k->u32 = sz + 1;
882                 k->id = CTID_A_CCHAR;
883         }
884         else
885         {
886         err_expr:
887                 cp_errmsg(cp, cp->tok, "unexpected symbol");
888         }
889 }
890 
891 /* Parse postfix operators. */
892 static void cp_expr_postfix(CPState *cp, CPValue *k)
893 {
894         for (;;)
895         {
896                 CType *ct;
897                 if (cp_opt(cp, '['))
898                 { /* Array/pointer index. */
899                         CPValue k2;
900                         cp_expr_comma(cp, &k2);
901                         ct = uc_ctype_rawref(cp->cts, k->id);
902                         if (!ctype_ispointer(ct->info))
903                         {
904                                 ct = uc_ctype_rawref(cp->cts, k2.id);
905                                 if (!ctype_ispointer(ct->info)) {
906                                         cp_err_badidx(cp, ct);
907                                         return;
908                                 }
909                         }
910                         cp_check(cp, ']');
911                         k->u32 = 0;
912                 }
913                 else if (cp->tok == '.' || cp->tok == CTOK_DEREF)
914                 { /* Struct deref. */
915                         CTSize ofs;
916                         CType *fct;
917                         ct = uc_ctype_rawref(cp->cts, k->id);
918                         if (cp->tok == CTOK_DEREF)
919                         {
920                                 if (!ctype_ispointer(ct->info)) {
921                                         cp_err_badidx(cp, ct);
922                                         return;
923                                 }
924                                 ct = uc_ctype_rawref(cp->cts, ctype_cid(ct->info));
925                         }
926                         cp_next(cp);
927                         if (cp->tok != CTOK_IDENT) {
928                                 cp_err_token(cp, CTOK_IDENT);
929                                 return;
930                         }
931                         if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
932                                 !(fct = uc_ctype_getfield(cp->cts, ct, cp->uv_str, &ofs)) ||
933                                 ctype_isbitfield(fct->info))
934                         {
935                                 uc_value_t *s = uc_ctype_repr(cp->uv_vm, ctype_typeid(cp->cts, ct), NULL);
936                                 cp_errmsg(cp, 0, "'%s' has no member named '%s'", ucv_string_get(s), ucv_string_get(cp->uv_str));
937                                 ucv_put(s);
938 
939                                 return;
940                         }
941                         ct = fct;
942                         k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
943                         cp_next(cp);
944                 }
945                 else
946                 {
947                         return;
948                 }
949                 k->id = ctype_cid(ct->info);
950         }
951 }
952 
953 /* Parse infix operators. */
954 static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
955 {
956         CPValue k2;
957         k2.u32 = 0;
958         k2.id = 0; /* Silence the compiler. */
959         for (;;)
960         {
961                 switch (pri)
962                 {
963                 case 0:
964                         if (cp_opt(cp, '?'))
965                         {
966                                 CPValue k3;
967                                 cp_expr_comma(cp, &k2); /* Right-associative. */
968                                 if (cp->error)
969                                         return;
970                                 cp_check(cp, ':');
971                                 cp_expr_sub(cp, &k3, 0);
972                                 if (cp->error)
973                                         return;
974                                 k->u32 = k->u32 ? k2.u32 : k3.u32;
975                                 k->id = k2.id > k3.id ? k2.id : k3.id;
976                                 continue;
977                         }
978                         /* fallthrough */
979                 case 1:
980                         if (cp_opt(cp, CTOK_OROR))
981                         {
982                                 cp_expr_sub(cp, &k2, 2);
983                                 if (cp->error)
984                                         return;
985                                 k->i32 = k->u32 || k2.u32;
986                                 k->id = CTID_INT32;
987                                 continue;
988                         }
989                         /* fallthrough */
990                 case 2:
991                         if (cp_opt(cp, CTOK_ANDAND))
992                         {
993                                 cp_expr_sub(cp, &k2, 3);
994                                 if (cp->error)
995                                         return;
996                                 k->i32 = k->u32 && k2.u32;
997                                 k->id = CTID_INT32;
998                                 continue;
999                         }
1000                         /* fallthrough */
1001                 case 3:
1002                         if (cp_opt(cp, '|'))
1003                         {
1004                                 cp_expr_sub(cp, &k2, 4);
1005                                 if (cp->error)
1006                                         return;
1007                                 k->u32 = k->u32 | k2.u32;
1008                                 goto arith_result;
1009                         }
1010                         /* fallthrough */
1011                 case 4:
1012                         if (cp_opt(cp, '^'))
1013                         {
1014                                 cp_expr_sub(cp, &k2, 5);
1015                                 if (cp->error)
1016                                         return;
1017                                 k->u32 = k->u32 ^ k2.u32;
1018                                 goto arith_result;
1019                         }
1020                         /* fallthrough */
1021                 case 5:
1022                         if (cp_opt(cp, '&'))
1023                         {
1024                                 cp_expr_sub(cp, &k2, 6);
1025                                 if (cp->error)
1026                                         return;
1027                                 k->u32 = k->u32 & k2.u32;
1028                                 goto arith_result;
1029                         }
1030                         /* fallthrough */
1031                 case 6:
1032                         if (cp_opt(cp, CTOK_EQ))
1033                         {
1034                                 cp_expr_sub(cp, &k2, 7);
1035                                 if (cp->error)
1036                                         return;
1037                                 k->i32 = k->u32 == k2.u32;
1038                                 k->id = CTID_INT32;
1039                                 continue;
1040                         }
1041                         else if (cp_opt(cp, CTOK_NE))
1042                         {
1043                                 cp_expr_sub(cp, &k2, 7);
1044                                 if (cp->error)
1045                                         return;
1046                                 k->i32 = k->u32 != k2.u32;
1047                                 k->id = CTID_INT32;
1048                                 continue;
1049                         }
1050                         /* fallthrough */
1051                 case 7:
1052                         if (cp_opt(cp, '<'))
1053                         {
1054                                 cp_expr_sub(cp, &k2, 8);
1055                                 if (cp->error)
1056                                         return;
1057                                 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
1058                                         k->i32 = k->i32 < k2.i32;
1059                                 else
1060                                         k->i32 = k->u32 < k2.u32;
1061                                 k->id = CTID_INT32;
1062                                 continue;
1063                         }
1064                         else if (cp_opt(cp, '>'))
1065                         {
1066                                 cp_expr_sub(cp, &k2, 8);
1067                                 if (cp->error)
1068                                         return;
1069                                 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
1070                                         k->i32 = k->i32 > k2.i32;
1071                                 else
1072                                         k->i32 = k->u32 > k2.u32;
1073                                 k->id = CTID_INT32;
1074                                 continue;
1075                         }
1076                         else if (cp_opt(cp, CTOK_LE))
1077                         {
1078                                 cp_expr_sub(cp, &k2, 8);
1079                                 if (cp->error)
1080                                         return;
1081                                 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
1082                                         k->i32 = k->i32 <= k2.i32;
1083                                 else
1084                                         k->i32 = k->u32 <= k2.u32;
1085                                 k->id = CTID_INT32;
1086                                 continue;
1087                         }
1088                         else if (cp_opt(cp, CTOK_GE))
1089                         {
1090                                 cp_expr_sub(cp, &k2, 8);
1091                                 if (cp->error)
1092                                         return;
1093                                 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
1094                                         k->i32 = k->i32 >= k2.i32;
1095                                 else
1096                                         k->i32 = k->u32 >= k2.u32;
1097                                 k->id = CTID_INT32;
1098                                 continue;
1099                         }
1100                         /* fallthrough */
1101                 case 8:
1102                         if (cp_opt(cp, CTOK_SHL))
1103                         {
1104                                 cp_expr_sub(cp, &k2, 9);
1105                                 if (cp->error)
1106                                         return;
1107                                 k->u32 = k->u32 << k2.u32;
1108                                 continue;
1109                         }
1110                         else if (cp_opt(cp, CTOK_SHR))
1111                         {
1112                                 cp_expr_sub(cp, &k2, 9);
1113                                 if (cp->error)
1114                                         return;
1115                                 if (k->id == CTID_INT32)
1116                                         k->i32 = k->i32 >> k2.i32;
1117                                 else
1118                                         k->u32 = k->u32 >> k2.u32;
1119                                 continue;
1120                         }
1121                         /* fallthrough */
1122                 case 9:
1123                         if (cp_opt(cp, '+'))
1124                         {
1125                                 cp_expr_sub(cp, &k2, 10);
1126                                 if (cp->error)
1127                                         return;
1128                                 k->u32 = k->u32 + k2.u32;
1129                         arith_result:
1130                                 if (k2.id > k->id)
1131                                         k->id = k2.id; /* Trivial promotion to unsigned. */
1132                                 continue;
1133                         }
1134                         else if (cp_opt(cp, '-'))
1135                         {
1136                                 cp_expr_sub(cp, &k2, 10);
1137                                 if (cp->error)
1138                                         return;
1139                                 k->u32 = k->u32 - k2.u32;
1140                                 goto arith_result;
1141                         }
1142                         /* fallthrough */
1143                 case 10:
1144                         if (cp_opt(cp, '*'))
1145                         {
1146                                 cp_expr_unary(cp, &k2);
1147                                 if (cp->error)
1148                                         return;
1149                                 k->u32 = k->u32 * k2.u32;
1150                                 goto arith_result;
1151                         }
1152                         else if (cp_opt(cp, '/'))
1153                         {
1154                                 cp_expr_unary(cp, &k2);
1155                                 if (cp->error)
1156                                         return;
1157                                 if (k2.id > k->id)
1158                                         k->id = k2.id; /* Trivial promotion to unsigned. */
1159                                 if (k2.u32 == 0 ||
1160                                         (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
1161                                 {
1162                                         cp_err(cp, "invalid value");
1163                                         return;
1164                                 }
1165                                 if (k->id == CTID_INT32)
1166                                         k->i32 = k->i32 / k2.i32;
1167                                 else
1168                                         k->u32 = k->u32 / k2.u32;
1169                                 continue;
1170                         }
1171                         else if (cp_opt(cp, '%'))
1172                         {
1173                                 cp_expr_unary(cp, &k2);
1174                                 if (cp->error)
1175                                         return;
1176                                 if (k2.id > k->id)
1177                                         k->id = k2.id; /* Trivial promotion to unsigned. */
1178                                 if (k2.u32 == 0 ||
1179                                         (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
1180                                 {
1181                                         cp_err(cp, "invalid value");
1182                                         return;
1183                                 }
1184                                 if (k->id == CTID_INT32)
1185                                         k->i32 = k->i32 % k2.i32;
1186                                 else
1187                                         k->u32 = k->u32 % k2.u32;
1188                                 continue;
1189                         }
1190                 default:
1191                         return;
1192                 }
1193         }
1194 }
1195 
1196 /* Parse and evaluate unary expression. */
1197 static void cp_expr_unary(CPState *cp, CPValue *k)
1198 {
1199         if (++cp->depth > CPARSE_MAX_DECLDEPTH)
1200         {
1201                 cp_err(cp, "chunk has too many syntax levels");
1202                 return;
1203         }
1204         cp_expr_prefix(cp, k);
1205         if (cp->error)
1206                 return;
1207         cp_expr_postfix(cp, k);
1208         cp->depth--;
1209 }
1210 
1211 /* Parse and evaluate sub-expression. */
1212 static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
1213 {
1214         cp_expr_unary(cp, k);
1215         if (cp->error)
1216                 return;
1217         cp_expr_infix(cp, k, pri);
1218 }
1219 
1220 /* Parse constant integer expression. */
1221 static void cp_expr_kint(CPState *cp, CPValue *k)
1222 {
1223         CType *ct;
1224         cp_expr_sub(cp, k, 0);
1225         if (cp->error)
1226                 return;
1227         ct = ctype_raw(cp->cts, k->id);
1228         if (!ctype_isinteger(ct->info))
1229         {
1230                 cp_err(cp, "invalid value");
1231                 return;
1232         }
1233 }
1234 
1235 /* Parse (non-negative) size expression. */
1236 static CTSize cp_expr_ksize(CPState *cp)
1237 {
1238         CPValue k;
1239         cp_expr_kint(cp, &k);
1240         if (cp->error)
1241                 return CTSIZE_INVALID;
1242         if (k.u32 >= 0x80000000u)
1243         {
1244                 cp_err(cp, "size of C type is unknown or too large");
1245                 return CTSIZE_INVALID;
1246         }
1247         return k.u32;
1248 }
1249 
1250 /* -- Type declaration stack management ----------------------------------- */
1251 
1252 /* Add declaration element behind the insertion position. */
1253 static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
1254 {
1255         CPDeclIdx top = decl->top;
1256         if (top >= CPARSE_MAX_DECLSTACK)
1257         {
1258                 cp_err(decl->cp, "chunk has too many syntax levels");
1259                 return 0;
1260         }
1261         decl->stack[top].info = info;
1262         decl->stack[top].size = size;
1263         decl->stack[top].sib = 0;
1264         decl->stack[top].uv_name = NULL;
1265         // setgcrefnull(decl->stack[top].name);
1266         decl->stack[top].next = decl->stack[decl->pos].next;
1267         decl->stack[decl->pos].next = (CTypeID1)top;
1268         decl->top = top + 1;
1269         return top;
1270 }
1271 
1272 /* Push declaration element before the insertion position. */
1273 static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
1274 {
1275         return (decl->pos = cp_add(decl, info, size));
1276 }
1277 
1278 /* Push or merge attributes. */
1279 static void cp_push_attributes(CPDecl *decl)
1280 {
1281         CType *ct = &decl->stack[decl->pos];
1282         if (ctype_isfunc(ct->info))
1283         { /* Ok to modify in-place. */
1284 #if UC_TARGET_X86
1285                 if ((decl->fattr & CTFP_CCONV))
1286                         ct->info = (ct->info & (CTMASK_NUM | CTF_VARARG | CTMASK_CID)) +
1287                                            (decl->fattr & ~CTMASK_CID);
1288 #endif
1289         }
1290         else
1291         {
1292                 if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
1293                         cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
1294                                         ctype_align(decl->attr));
1295         }
1296 }
1297 
1298 /* Push unrolled type to declaration stack and merge qualifiers. */
1299 static void cp_push_type(CPDecl *decl, CTypeID id)
1300 {
1301         CType *ct = ctype_get(decl->cp->cts, id);
1302         CTInfo info = ct->info;
1303         CTSize size = ct->size;
1304         switch (ctype_type(info))
1305         {
1306         case CT_STRUCT:
1307         case CT_ENUM:
1308                 cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
1309                 if ((decl->attr & CTF_QUAL))
1310                 { /* Push unmerged qualifiers. */
1311                         cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
1312                                         (decl->attr & CTF_QUAL));
1313                         decl->attr &= ~CTF_QUAL;
1314                 }
1315                 break;
1316         case CT_ATTRIB:
1317                 if (ctype_isxattrib(info, CTA_QUAL))
1318                         decl->attr &= ~size;                             /* Remove redundant qualifiers. */
1319                 cp_push_type(decl, ctype_cid(info));     /* Unroll. */
1320                 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
1321                 break;
1322         case CT_ARRAY:
1323                 if ((ct->info & (CTF_VECTOR | CTF_COMPLEX)))
1324                 {
1325                         info |= (decl->attr & CTF_QUAL);
1326                         decl->attr &= ~CTF_QUAL;
1327                 }
1328                 cp_push_type(decl, ctype_cid(info));     /* Unroll. */
1329                 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
1330                 decl->stack[decl->pos].sib = 1;                  /* Mark as already checked and sized. */
1331                 /* Note: this is not copied to the ct->sib in the C type table. */
1332                 break;
1333         case CT_FUNC:
1334                 /* Copy type, link parameters (shared). */
1335                 decl->stack[cp_push(decl, info, size)].sib = ct->sib;
1336                 break;
1337         default:
1338                 /* Copy type, merge common qualifiers. */
1339                 cp_push(decl, info | (decl->attr & CTF_QUAL), size);
1340                 decl->attr &= ~CTF_QUAL;
1341                 break;
1342         }
1343 }
1344 
1345 /* Consume the declaration element chain and intern the C type. */
1346 static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
1347 {
1348         CTypeID id = 0;
1349         CPDeclIdx idx = 0;
1350         CTSize csize = CTSIZE_INVALID;
1351         CTSize cinfo = 0;
1352         do
1353         {
1354                 CType *ct = &decl->stack[idx];
1355                 CTInfo info = ct->info;
1356                 CTInfo size = ct->size;
1357                 /* The cid is already part of info for copies of pointers/functions. */
1358                 idx = ct->next;
1359                 if (ctype_istypedef(info))
1360                 {
1361                         uc_assertCP(id == 0, "typedef not at toplevel");
1362                         id = ctype_cid(info);
1363                         /* Always refetch info/size, since struct/enum may have been completed. */
1364                         cinfo = ctype_get(cp->cts, id)->info;
1365                         csize = ctype_get(cp->cts, id)->size;
1366                         uc_assertCP(ctype_isstruct(cinfo) || ctype_isenum(cinfo),
1367                                                 "typedef of bad type");
1368                 }
1369                 else if (ctype_isfunc(info))
1370                 { /* Intern function. */
1371                         CType *fct;
1372                         CTypeID fid;
1373                         CTypeID sib;
1374                         if (id)
1375                         {
1376                                 CType *refct = ctype_raw(cp->cts, id);
1377                                 /* Reject function or refarray return types. */
1378                                 if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info)) {
1379                                         cp_err(cp, "invalid C type");
1380                                         return 0;
1381                                 }
1382                         }
1383                         /* No intervening attributes allowed, skip forward. */
1384                         while (idx)
1385                         {
1386                                 CType *ctn = &decl->stack[idx];
1387                                 if (!ctype_isattrib(ctn->info))
1388                                         break;
1389                                 idx = ctn->next; /* Skip attribute. */
1390                         }
1391                         sib = ct->sib; /* Next line may reallocate the C type table. */
1392                         fid = uc_ctype_new(cp->cts, &fct);
1393                         csize = CTSIZE_INVALID;
1394                         fct->info = cinfo = info + id;
1395                         fct->size = size;
1396                         fct->sib = sib;
1397                         id = fid;
1398                 }
1399                 else if (ctype_isattrib(info))
1400                 {
1401                         if (ctype_isxattrib(info, CTA_QUAL))
1402                                 cinfo |= size;
1403                         else if (ctype_isxattrib(info, CTA_ALIGN))
1404                                 CTF_INSERT(cinfo, ALIGN, size);
1405                         id = uc_ctype_intern(cp->cts, info + id, size);
1406                         /* Inherit csize/cinfo from original type. */
1407                 }
1408                 else
1409                 {
1410                         if (ctype_isnum(info))
1411                         { /* Handle mode/vector-size attributes. */
1412                                 uc_assertCP(id == 0, "number not at toplevel");
1413                                 if (!(info & CTF_BOOL))
1414                                 {
1415                                         CTSize msize = ctype_msizeP(decl->attr);
1416                                         CTSize vsize = ctype_vsizeP(decl->attr);
1417                                         if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8)))
1418                                         {
1419                                                 CTSize malign = uc_fls(msize);
1420                                                 if (malign > 4)
1421                                                         malign = 4; /* Limit alignment. */
1422                                                 CTF_INSERT(info, ALIGN, malign);
1423                                                 size = msize; /* Override size via mode. */
1424                                         }
1425                                         if (vsize)
1426                                         { /* Vector size set? */
1427                                                 CTSize esize = uc_fls(size);
1428                                                 if (vsize >= esize)
1429                                                 {
1430                                                         /* Intern the element type first. */
1431                                                         id = uc_ctype_intern(cp->cts, info, size);
1432                                                         /* Then create a vector (array) with vsize alignment. */
1433                                                         size = (1u << vsize);
1434                                                         if (vsize > 4)
1435                                                                 vsize = 4; /* Limit alignment. */
1436                                                         if (ctype_align(info) > vsize)
1437                                                                 vsize = ctype_align(info);
1438                                                         info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
1439                                                                                                                 CTALIGN(vsize));
1440                                                 }
1441                                         }
1442                                 }
1443                         }
1444                         else if (ctype_isptr(info))
1445                         {
1446                                 /* Reject pointer/ref to ref. */
1447                                 if (id && ctype_isref(ctype_raw(cp->cts, id)->info)) {
1448                                         cp_err(cp, "invalid C type");
1449                                         return 0;
1450                                 }
1451                                 if (ctype_isref(info))
1452                                 {
1453                                         info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
1454                                         /* No intervening attributes allowed, skip forward. */
1455                                         while (idx)
1456                                         {
1457                                                 CType *ctn = &decl->stack[idx];
1458                                                 if (!ctype_isattrib(ctn->info))
1459                                                         break;
1460                                                 idx = ctn->next; /* Skip attribute. */
1461                                         }
1462                                 }
1463                         }
1464                         else if (ctype_isarray(info))
1465                         { /* Check for valid array size etc. */
1466                                 if (ct->sib == 0)
1467                                 {                                                       /* Only check/size arrays not copied by unroll. */
1468                                         if (ctype_isref(cinfo)) /* Reject arrays of refs. */ {
1469                                                 cp_err(cp, "invalid C type");
1470                                                 return 0;
1471                                         }
1472                                         /* Reject VLS or unknown-sized types. */
1473                                         if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID) {
1474                                                 cp_err(cp, "size of C type is unknown or too large");
1475                                                 return 0;
1476                                         }
1477                                         /* a[] and a[?] keep their invalid size. */
1478                                         if (size != CTSIZE_INVALID)
1479                                         {
1480                                                 uint64_t xsz = (uint64_t)size * csize;
1481                                                 if (xsz >= 0x80000000u) {
1482                                                         cp_err(cp, "size of C type is unknown or too large");
1483                                                         return 0;
1484                                                 }
1485                                                 size = (CTSize)xsz;
1486                                         }
1487                                 }
1488                                 if ((cinfo & CTF_ALIGN) > (info & CTF_ALIGN)) /* Find max. align. */
1489                                         info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN);
1490                                 info |= (cinfo & CTF_QUAL); /* Inherit qual. */
1491                         }
1492                         else
1493                         {
1494                                 uc_assertCP(ctype_isvoid(info), "bad ctype %08x", info);
1495                         }
1496                         csize = size;
1497                         cinfo = info + id;
1498                         id = uc_ctype_intern(cp->cts, info + id, size);
1499                 }
1500         } while (idx);
1501         return id;
1502 }
1503 
1504 /* -- C declaration parser ------------------------------------------------ */
1505 
1506 /* Reset declaration state to declaration specifier. */
1507 static void cp_decl_reset(CPDecl *decl)
1508 {
1509         ucv_put(decl->uv_name);
1510         ucv_put(decl->uv_redir);
1511 
1512         decl->pos = decl->specpos;
1513         decl->top = decl->specpos + 1;
1514         decl->stack[decl->specpos].next = 0;
1515         decl->attr = decl->specattr;
1516         decl->fattr = decl->specfattr;
1517         decl->uv_name = NULL;
1518         decl->uv_redir = NULL;
1519 }
1520 
1521 /* Parse constant initializer. */
1522 /* NYI: FP constants and strings as initializers. */
1523 static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
1524 {
1525         CType *ctt = ctype_get(cp->cts, ctypeid);
1526         CTInfo info;
1527         CTSize size;
1528         CPValue k;
1529         CTypeID constid;
1530         while (ctype_isattrib(ctt->info))
1531         {                                                                       /* Skip attributes. */
1532                 ctypeid = ctype_cid(ctt->info); /* Update ID, too. */
1533                 ctt = ctype_get(cp->cts, ctypeid);
1534         }
1535         info = ctt->info;
1536         size = ctt->size;
1537         if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
1538         {
1539                 cp_err(cp, "invalid C type");
1540                 return 0;
1541         }
1542         cp_check(cp, '=');
1543         if (cp->error)
1544                 return 0;
1545         cp_expr_sub(cp, &k, 0);
1546         if (cp->error)
1547                 return 0;
1548         constid = uc_ctype_new(cp->cts, ctp);
1549         (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST | ctypeid);
1550         k.u32 <<= 8 * (4 - size);
1551         if ((info & CTF_UNSIGNED))
1552                 k.u32 >>= 8 * (4 - size);
1553         else
1554                 k.u32 = (uint32_t)((int32_t)k.u32 >> 8 * (4 - size));
1555         (*ctp)->size = k.u32;
1556         return constid;
1557 }
1558 
1559 /* Parse size in parentheses as part of attribute. */
1560 static CTSize cp_decl_sizeattr(CPState *cp)
1561 {
1562         CTSize sz;
1563         uint32_t oldtmask = cp->tmask;
1564         cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
1565         cp_check(cp, '(');
1566         if (cp->error)
1567                 return 0;
1568         sz = cp_expr_ksize(cp);
1569         if (cp->error)
1570                 return 0;
1571         cp->tmask = oldtmask;
1572         cp_check(cp, ')');
1573         if (cp->error)
1574                 return 0;
1575         return sz;
1576 }
1577 
1578 /* Parse alignment attribute. */
1579 static void cp_decl_align(CPState *cp, CPDecl *decl)
1580 {
1581         CTSize al = 4; /* Unspecified alignment is 16 bytes. */
1582         if (cp->tok == '(')
1583         {
1584                 al = cp_decl_sizeattr(cp);
1585                 if (cp->error)
1586                         return;
1587                 al = al ? uc_fls(al) : 0;
1588         }
1589         CTF_INSERT(decl->attr, ALIGN, al);
1590         decl->attr |= CTFP_ALIGNED;
1591 }
1592 
1593 /* Parse GCC asm("name") redirect. */
1594 static void cp_decl_asm(CPState *cp, unused CPDecl *decl)
1595 {
1596         cp_next(cp);
1597         if (cp->error)
1598                 return;
1599         cp_check(cp, '(');
1600         if (cp->error)
1601                 return;
1602         if (cp->tok == CTOK_STRING)
1603         {
1604                 uc_stringbuf_t *buf = ucv_stringbuf_new();
1605                 // GCstr *str = cp->str;
1606                 ucv_stringbuf_addstr(buf, ucv_string_get(cp->uv_str), ucv_string_length(cp->uv_str));
1607                 while (cp_next(cp) == CTOK_STRING)
1608                 {
1609                         if (cp->error)
1610                                 return;
1611                         ucv_stringbuf_addstr(buf, ucv_string_get(cp->uv_str), ucv_string_length(cp->uv_str));
1612                 }
1613                 decl->uv_redir = ucv_stringbuf_finish(buf);
1614         }
1615         cp_check(cp, ')');
1616         if (cp->error)
1617                 return;
1618 }
1619 
1620 /* Parse GCC __attribute__((mode(...))). */
1621 static void cp_decl_mode(CPState *cp, CPDecl *decl)
1622 {
1623         cp_check(cp, '(');
1624         if (cp->tok == CTOK_IDENT)
1625         {
1626                 const char *s = ucv_string_get(cp->uv_str);
1627                 CTSize sz = 0, vlen = 0;
1628                 if (s[0] == '_' && s[1] == '_')
1629                         s += 2;
1630                 if (*s == 'V')
1631                 {
1632                         s++;
1633                         vlen = *s++ - '';
1634                         if (*s >= '' && *s <= '9')
1635                                 vlen = vlen * 10 + (*s++ - '');
1636                 }
1637                 switch (*s++)
1638                 {
1639                 case 'Q':
1640                         sz = 1;
1641                         break;
1642                 case 'H':
1643                         sz = 2;
1644                         break;
1645                 case 'S':
1646                         sz = 4;
1647                         break;
1648                 case 'D':
1649                         sz = 8;
1650                         break;
1651                 case 'T':
1652                         sz = 16;
1653                         break;
1654                 case 'O':
1655                         sz = 32;
1656                         break;
1657                 default:
1658                         goto bad_size;
1659                 }
1660                 if (*s == 'I' || *s == 'F')
1661                 {
1662                         CTF_INSERT(decl->attr, MSIZEP, sz);
1663                         if (vlen)
1664                                 CTF_INSERT(decl->attr, VSIZEP, uc_fls(vlen * sz));
1665                 }
1666         bad_size:
1667                 cp_next(cp);
1668         }
1669         cp_check(cp, ')');
1670 }
1671 
1672 /* Parse GCC __attribute__((...)). */
1673 static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
1674 {
1675         cp_next(cp);
1676         if (cp->error)
1677                 return;
1678         cp_check(cp, '(');
1679         if (cp->error)
1680                 return;
1681         cp_check(cp, '(');
1682         if (cp->error)
1683                 return;
1684         while (cp->tok != ')')
1685         {
1686                 if (cp->tok == CTOK_IDENT)
1687                 {
1688                         uc_value_t *attrstr = ucv_get(cp->uv_str);
1689                         cp_next(cp);
1690                         if (cp->error)
1691                                 return;
1692                         switch (uc_cparse_case(attrstr,
1693                                                                    "\007aligned"
1694                                                                    "\013__aligned__"
1695                                                                    "\006packed"
1696                                                                    "\012__packed__"
1697                                                                    "\004mode"
1698                                                                    "\010__mode__"
1699                                                                    "\013vector_size"
1700                                                                    "\017__vector_size__"
1701 #if UC_TARGET_X86
1702                                                                    "\007regparm"
1703                                                                    "\013__regparm__"
1704                                                                    "\005cdecl"
1705                                                                    "\011__cdecl__"
1706                                                                    "\010thiscall"
1707                                                                    "\014__thiscall__"
1708                                                                    "\010fastcall"
1709                                                                    "\014__fastcall__"
1710                                                                    "\007stdcall"
1711                                                                    "\013__stdcall__"
1712                                                                    "\012sseregparm"
1713                                                                    "\016__sseregparm__"
1714 #endif
1715                                                                    ))
1716                         {
1717                         case 0:
1718                         case 1: /* aligned */
1719                                 cp_decl_align(cp, decl);
1720                                 break;
1721                         case 2:
1722                         case 3: /* packed */
1723                                 decl->attr |= CTFP_PACKED;
1724                                 break;
1725                         case 4:
1726                         case 5: /* mode */
1727                                 cp_decl_mode(cp, decl);
1728                                 break;
1729                         case 6:
1730                         case 7: /* vector_size */
1731                         {
1732                                 CTSize vsize = cp_decl_sizeattr(cp);
1733                                 if (vsize)
1734                                         CTF_INSERT(decl->attr, VSIZEP, uc_fls(vsize));
1735                         }
1736                         break;
1737 #if UC_TARGET_X86
1738                         case 8:
1739                         case 9: /* regparm */
1740                                 CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1741                                 decl->fattr |= CTFP_CCONV;
1742                                 break;
1743                         case 10:
1744                         case 11: /* cdecl */
1745                                 CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1746                                 decl->fattr |= CTFP_CCONV;
1747                                 break;
1748                         case 12:
1749                         case 13: /* thiscall */
1750                                 CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1751                                 decl->fattr |= CTFP_CCONV;
1752                                 break;
1753                         case 14:
1754                         case 15: /* fastcall */
1755                                 CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1756                                 decl->fattr |= CTFP_CCONV;
1757                                 break;
1758                         case 16:
1759                         case 17: /* stdcall */
1760                                 CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1761                                 decl->fattr |= CTFP_CCONV;
1762                                 break;
1763                         case 18:
1764                         case 19: /* sseregparm */
1765                                 decl->fattr |= CTF_SSEREGPARM;
1766                                 decl->fattr |= CTFP_CCONV;
1767                                 break;
1768 #endif
1769                         default: /* Skip all other attributes. */
1770                                 ucv_put(attrstr);
1771                                 goto skip_attr;
1772                         }
1773                         ucv_put(attrstr);
1774                 }
1775                 else if (cp->tok >= CTOK_FIRSTDECL)
1776                 { /* For __attribute((const)) etc. */
1777                         cp_next(cp);
1778                 skip_attr:
1779                         if (cp_opt(cp, '('))
1780                         {
1781                                 while (cp->tok != ')' && cp->tok != CTOK_EOF)
1782                                 {
1783                                         cp_next(cp);
1784                                         if (cp->error)
1785                                                 return;
1786                                 }
1787                                 cp_check(cp, ')');
1788                                 if (cp->error)
1789                                         return;
1790                         }
1791                 }
1792                 else
1793                 {
1794                         break;
1795                 }
1796                 if (!cp_opt(cp, ','))
1797                         break;
1798         }
1799         cp_check(cp, ')');
1800         if (cp->error)
1801                 return;
1802         cp_check(cp, ')');
1803         if (cp->error)
1804                 return;
1805 }
1806 
1807 /* Parse MSVC __declspec(...). */
1808 static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
1809 {
1810         cp_next(cp);
1811         if (cp->error)
1812                 return;
1813         cp_check(cp, '(');
1814         if (cp->error)
1815                 return;
1816         while (cp->tok == CTOK_IDENT)
1817         {
1818                 uc_value_t *attrstr = ucv_get(cp->uv_str);
1819                 cp_next(cp);
1820                 if (cp->error)
1821                         return;
1822                 if (cp_str_is(attrstr, "align"))
1823                 {
1824                         cp_decl_align(cp, decl);
1825                         if (cp->error)
1826                                 return;
1827                 }
1828                 else
1829                 { /* Ignore all other attributes. */
1830                         if (cp_opt(cp, '('))
1831                         {
1832                                 while (cp->tok != ')' && cp->tok != CTOK_EOF)
1833                                 {
1834                                         cp_next(cp);
1835                                         if (cp->error)
1836                                                 return;
1837                                 }
1838                                 cp_check(cp, ')');
1839                                 if (cp->error)
1840                                         return;
1841                         }
1842                 }
1843                 ucv_put(attrstr);
1844         }
1845         cp_check(cp, ')');
1846         if (cp->error)
1847                 return;
1848 }
1849 
1850 /* Parse declaration attributes (and common qualifiers). */
1851 static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1852 {
1853         for (;;)
1854         {
1855                 switch (cp->tok)
1856                 {
1857                 case CTOK_CONST:
1858                         decl->attr |= CTF_CONST;
1859                         break;
1860                 case CTOK_VOLATILE:
1861                         decl->attr |= CTF_VOLATILE;
1862                         break;
1863                 case CTOK_RESTRICT:
1864                         break; /* Ignore. */
1865                 case CTOK_EXTENSION:
1866                         break; /* Ignore. */
1867                 case CTOK_ATTRIBUTE:
1868                         cp_decl_gccattribute(cp, decl);
1869                         if (cp->error)
1870                                 return;
1871                         continue;
1872                 case CTOK_ASM:
1873                         cp_decl_asm(cp, decl);
1874                         if (cp->error)
1875                                 return;
1876                         continue;
1877                 case CTOK_DECLSPEC:
1878                         cp_decl_msvcattribute(cp, decl);
1879                         if (cp->error)
1880                                 return;
1881                         continue;
1882                 case CTOK_CCDECL:
1883 #if UC_TARGET_X86
1884                         CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1885                         decl->fattr |= CTFP_CCONV;
1886 #endif
1887                         break;
1888                 case CTOK_PTRSZ:
1889 #if UC_64
1890                         CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
1891 #endif
1892                         break;
1893                 default:
1894                         return;
1895                 }
1896                 cp_next(cp);
1897         }
1898 }
1899 
1900 /* Parse struct/union/enum name. */
1901 static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
1902 {
1903         CTypeID sid;
1904         CType *ct;
1905         cp->tmask = CPNS_STRUCT;
1906         cp_next(cp);
1907         cp_decl_attributes(cp, sdecl);
1908         cp->tmask = CPNS_DEFAULT;
1909         if (cp->tok != '{')
1910         {
1911                 if (cp->tok != CTOK_IDENT)
1912                         cp_err_token(cp, CTOK_IDENT);
1913                 if (cp->val.id)
1914                 { /* Name of existing struct/union/enum. */
1915                         sid = cp->val.id;
1916                         ct = cp->ct;
1917                         if ((ct->info ^ info) & (CTMASK_NUM | CTF_UNION)) /* Wrong type. */
1918                                 cp_errmsg(cp, 0, "attempt to redefine '%s'", ucv_string_get(ct->uv_name));
1919                 }
1920                 else
1921                 { /* Create named, incomplete struct/union/enum. */
1922                         if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
1923                                 cp_errmsg(cp, 0, "undeclared or implicit tag '%s'", ucv_string_get(cp->uv_str));
1924                         sid = uc_ctype_new(cp->cts, &ct);
1925                         ct->info = info;
1926                         ct->size = CTSIZE_INVALID;
1927                         ctype_setname(ct, cp->uv_str);
1928                         uc_ctype_addname(cp->cts, ct, sid);
1929                 }
1930                 cp_next(cp);
1931         }
1932         else
1933         { /* Create anonymous, incomplete struct/union/enum. */
1934                 sid = uc_ctype_new(cp->cts, &ct);
1935                 ct->info = info;
1936                 ct->size = CTSIZE_INVALID;
1937         }
1938         if (cp->tok == '{')
1939         {
1940                 if (ct->size != CTSIZE_INVALID || ct->sib)
1941                         cp_errmsg(cp, 0, "attempt to redefine '%s'", ucv_string_get(ct->uv_name));
1942                 ct->sib = 1; /* Indicate the type is currently being defined. */
1943         }
1944         return sid;
1945 }
1946 
1947 /* Determine field alignment. */
1948 static CTSize cp_field_align(unused CPState *cp, unused CType *ct, CTInfo info)
1949 {
1950         CTSize align = ctype_align(info);
1951 #if (UC_TARGET_X86 && !UC_ABI_WIN) || (UC_TARGET_ARM && __APPLE__)
1952         /* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
1953         if (align > 2 && !(info & CTFP_ALIGNED))
1954         {
1955                 if (ctype_isarray(info) && !(info & CTF_VECTOR))
1956                 {
1957                         do
1958                         {
1959                                 ct = ctype_rawchild(cp->cts, ct);
1960                                 info = ct->info;
1961                         } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1962                 }
1963                 if (ctype_isnum(info) || ctype_isenum(info))
1964                         align = 2;
1965         }
1966 #endif
1967         return align;
1968 }
1969 
1970 /* Layout struct/union fields. */
1971 static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1972 {
1973         CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
1974         CTSize maxalign = ctype_align(sattr);
1975         CType *sct = ctype_get(cp->cts, sid);
1976         CTInfo sinfo = sct->info;
1977         CTypeID fieldid = sct->sib;
1978         while (fieldid)
1979         {
1980                 CType *ct = ctype_get(cp->cts, fieldid);
1981                 CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
1982 
1983                 if (ctype_isfield(ct->info) ||
1984                         (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr))
1985                 {
1986                         CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
1987                         CTSize sz;
1988                         CTInfo info = uc_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
1989                         CTSize bsz, csz = 8 * sz;                               /* Field size and container size (in bits). */
1990                         sinfo |= (info & (CTF_QUAL | CTF_VLA)); /* Merge pseudo-qualifiers. */
1991 
1992                         /* Check for size overflow and determine alignment. */
1993                         if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA))
1994                         {
1995                                 if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
1996                                           !(sinfo & CTF_UNION))) {
1997                                         cp_err(cp, "size of C type is unknown or too large");
1998                                         return;
1999                                 }
2000                                 csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
2001                         }
2002                         align = cp_field_align(cp, ct, info);
2003                         if (((attr | sattr) & CTFP_PACKED) ||
2004                                 ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
2005                                 align = ctype_align(attr);
2006                         if (cp->packstack[cp->curpack] < align)
2007                                 align = cp->packstack[cp->curpack];
2008                         if (align > maxalign)
2009                                 maxalign = align;
2010                         amask = (8u << align) - 1;
2011 
2012                         bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
2013                         if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info))
2014                         {
2015                                 bsz = csz;                                              /* Regular fields or subtypes always fill the container. */
2016                                 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
2017                                 ct->size = (bofs >> 3);                 /* Store field offset. */
2018                         }
2019                         else
2020                         { /* Bitfield. */
2021                                 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
2022                                         (!((attr | sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
2023                                         bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
2024 
2025                                 /* Prefer regular field over bitfield. */
2026                                 if (bsz == csz && (bofs & amask) == 0)
2027                                 {
2028                                         ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
2029                                         ct->size = (bofs >> 3); /* Store field offset. */
2030                                 }
2031                                 else
2032                                 {
2033                                         ct->info = CTINFO(CT_BITFIELD,
2034                                                                           (info & (CTF_QUAL | CTF_UNSIGNED | CTF_BOOL)) +
2035                                                                                   (csz << (CTSHIFT_BITCSZ - 3)) + (bsz << CTSHIFT_BITBSZ));
2036 #if UC_BE
2037                                         ct->info += ((csz - (bofs & (csz - 1)) - bsz) << CTSHIFT_BITPOS);
2038 #else
2039                                         ct->info += ((bofs & (csz - 1)) << CTSHIFT_BITPOS);
2040 #endif
2041                                         ct->size = ((bofs & ~(csz - 1)) >> 3); /* Store container offset. */
2042                                 }
2043                         }
2044 
2045                         /* Determine next offset or max. offset. */
2046                         if ((sinfo & CTF_UNION))
2047                         {
2048                                 if (bsz > bmaxofs)
2049                                         bmaxofs = bsz;
2050                         }
2051                         else
2052                         {
2053                                 bofs += bsz;
2054                         }
2055                 } /* All other fields in the chain are already set up. */
2056 
2057                 fieldid = ct->sib;
2058         }
2059 
2060         /* Complete struct/union. */
2061         sct->info = sinfo + CTALIGN(maxalign);
2062         bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
2063         maxalign = (8u << maxalign) - 1;
2064         sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
2065 }
2066 
2067 /* Parse struct/union declaration. */
2068 static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
2069 {
2070         CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
2071         if (cp->error)
2072                 return 0;
2073         if (cp_opt(cp, '{'))
2074         { /* Struct/union definition. */
2075                 CTypeID lastid = sid;
2076                 int lastdecl = 0;
2077                 while (cp->tok != '}')
2078                 {
2079                         CPDecl decl = { 0 };
2080                         CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
2081                         if (cp->error)
2082                                 return 0;
2083                         decl.mode = scl ? CPARSE_MODE_DIRECT : CPARSE_MODE_DIRECT | CPARSE_MODE_ABSTRACT | CPARSE_MODE_FIELD;
2084 
2085                         for (;;)
2086                         {
2087                                 CTypeID ctypeid;
2088 
2089                                 if (lastdecl)
2090                                 {
2091                                         cp_err_token(cp, '}');
2092                                         return 0;
2093                                 }
2094 
2095                                 /* Parse field declarator. */
2096                                 decl.bits = CTSIZE_INVALID;
2097                                 cp_declarator(cp, &decl);
2098                                 if (cp->error)
2099                                         return 0;
2100                                 ctypeid = cp_decl_intern(cp, &decl);
2101                                 if (cp->error)
2102                                         return 0;
2103 
2104                                 if ((scl & CDF_STATIC))
2105                                 { /* Static constant in struct namespace. */
2106                                         CType *ct;
2107                                         CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
2108                                         if (cp->error)
2109                                                 return 0;
2110                                         ctype_get(cp->cts, lastid)->sib = fieldid;
2111                                         lastid = fieldid;
2112                                         ctype_setname(ct, decl.uv_name);
2113                                 }
2114                                 else
2115                                 {
2116                                         CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
2117                                         CType *ct;
2118                                         CTypeID fieldid = uc_ctype_new(cp->cts, &ct); /* Do this first. */
2119                                         CType *tct = ctype_raw(cp->cts, ctypeid);
2120 
2121                                         if (decl.bits == CTSIZE_INVALID)
2122                                         { /* Regular field. */
2123                                                 if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
2124                                                         lastdecl = 1; /* a[] or a[?] must be the last declared field. */
2125 
2126                                                 /* Accept transparent struct/union/enum. */
2127                                                 if (!decl.uv_name)
2128                                                 {
2129                                                         if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
2130                                                                   ctype_isenum(tct->info)))
2131                                                         {
2132                                                                 cp_err_token(cp, CTOK_IDENT);
2133                                                                 return 0;
2134                                                         }
2135                                                         ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
2136                                                         ct->size = ctype_isstruct(tct->info) ? (decl.attr | 0x80000000u) : 0; /* For layout phase. */
2137                                                         goto add_field;
2138                                                 }
2139                                         }
2140                                         else
2141                                         { /* Bitfield. */
2142                                                 bsz = decl.bits;
2143                                                 if (!ctype_isinteger_or_bool(tct->info) ||
2144                                                         (bsz == 0 && decl.uv_name) || 8 * tct->size > CTBSZ_MAX ||
2145                                                         bsz > ((tct->info & CTF_BOOL) ? 1 : 8 * tct->size))
2146                                                 {
2147                                                         cp_errmsg(cp, ':', "invalid value");
2148                                                         return 0;
2149                                                 }
2150                                         }
2151 
2152                                         /* Create temporary field for layout phase. */
2153                                         ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
2154                                         ct->size = decl.attr;
2155                                         if (decl.uv_name)
2156                                                 ctype_setname(ct, decl.uv_name);
2157 
2158                                 add_field:
2159                                         ctype_get(cp->cts, lastid)->sib = fieldid;
2160                                         lastid = fieldid;
2161                                 }
2162                                 cp_decl_reset(&decl);
2163                                 if (!cp_opt(cp, ','))
2164                                         break;
2165                         }
2166                         cp_check(cp, ';');
2167                         if (cp->error)
2168                                 return 0;
2169                 }
2170                 cp_check(cp, '}');
2171                 if (cp->error)
2172                         return 0;
2173                 ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
2174                 cp_decl_attributes(cp, sdecl);           /* Layout phase needs postfix attributes. */
2175                 if (cp->error)
2176                         return 0;
2177                 cp_struct_layout(cp, sid, sdecl->attr);
2178         }
2179         return sid;
2180 }
2181 
2182 /* Parse enum declaration. */
2183 static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
2184 {
2185         CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
2186         if (cp->error)
2187                 return 0;
2188         CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
2189         CTSize esize = 4; /* Only 32 bit enums are supported. */
2190         if (cp_opt(cp, '{'))
2191         { /* Enum definition. */
2192                 CPValue k;
2193                 CTypeID lastid = eid;
2194                 k.u32 = 0;
2195                 k.id = CTID_INT32;
2196                 do
2197                 {
2198                         uc_value_t *name = ucv_get(cp->uv_str);
2199                         if (cp->tok != CTOK_IDENT)
2200                         {
2201                                 cp_err_token(cp, CTOK_IDENT);
2202                                 return 0;
2203                         }
2204                         if (cp->val.id)
2205                         {
2206                                 cp_errmsg(cp, 0, "attempt to redefine '%s'", ucv_string_get(name));
2207                                 return 0;
2208                         }
2209                         cp_next(cp);
2210                         if (cp_opt(cp, '='))
2211                         {
2212                                 cp_expr_kint(cp, &k);
2213                                 if (cp->error)
2214                                         return 0;
2215                                 if (k.id == CTID_UINT32)
2216                                 {
2217                                         /* C99 says that enum constants are always (signed) integers.
2218                                         ** But since unsigned constants like 0x80000000 are quite common,
2219                                         ** those are left as uint32_t.
2220                                         */
2221                                         if (k.i32 >= 0)
2222                                                 k.id = CTID_INT32;
2223                                 }
2224                                 else
2225                                 {
2226                                         /* OTOH it's common practice and even mandated by some ABIs
2227                                         ** that the enum type itself is unsigned, unless there are any
2228                                         ** negative constants.
2229                                         */
2230                                         k.id = CTID_INT32;
2231                                         if (k.i32 < 0)
2232                                                 einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
2233                                 }
2234                         }
2235                         /* Add named enum constant. */
2236                         {
2237                                 CType *ct;
2238                                 CTypeID constid = uc_ctype_new(cp->cts, &ct);
2239                                 ctype_get(cp->cts, lastid)->sib = constid;
2240                                 lastid = constid;
2241                                 ctype_setname(ct, name);
2242                                 ct->info = CTINFO(CT_CONSTVAL, CTF_CONST | k.id);
2243                                 ct->size = k.u32++;
2244                                 if (k.u32 == 0x80000000u)
2245                                         k.id = CTID_UINT32;
2246                                 uc_ctype_addname(cp->cts, ct, constid);
2247                         }
2248                         ucv_put(name);
2249                         if (!cp_opt(cp, ','))
2250                                 break;
2251                 } while (cp->tok != '}'); /* Trailing ',' is ok. */
2252                 cp_check(cp, '}');
2253                 if (cp->error)
2254                         return 0;
2255                 /* Complete enum. */
2256                 ctype_get(cp->cts, eid)->info = einfo;
2257                 ctype_get(cp->cts, eid)->size = esize;
2258         }
2259         return eid;
2260 }
2261 
2262 /* Parse declaration specifiers. */
2263 static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
2264 {
2265         uint32_t cds = 0, sz = 0;
2266         CTypeID tdef = 0;
2267 
2268         decl->cp = cp;
2269         decl->mode = cp->mode;
2270         decl->uv_name = NULL;
2271         decl->uv_redir = NULL;
2272         decl->attr = 0;
2273         decl->fattr = 0;
2274         decl->pos = decl->top = 0;
2275         decl->stack[0].next = 0;
2276 
2277         for (;;)
2278         { /* Parse basic types. */
2279                 cp_decl_attributes(cp, decl);
2280                 if (cp->error)
2281                         return 0;
2282                 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG)
2283                 {
2284                         uint32_t cbit;
2285                         if (cp->ct->size)
2286                         {
2287                                 if (sz)
2288                                         goto end_decl;
2289                                 sz = cp->ct->size;
2290                         }
2291                         cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
2292                         cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
2293                         if (cp->tok >= CTOK_FIRSTSCL)
2294                         {
2295                                 if (!(scl & cbit))
2296                                 {
2297                                         cp_errmsg(cp, cp->tok, "bad storage class");
2298                                         return 0;
2299                                 }
2300                         }
2301                         else if (tdef)
2302                         {
2303                                 goto end_decl;
2304                         }
2305                         cp_next(cp);
2306                         continue;
2307                 }
2308                 if (sz || tdef ||
2309                         (cds & (CDF_SHORT | CDF_LONG | CDF_SIGNED | CDF_UNSIGNED | CDF_COMPLEX)))
2310                         break;
2311                 switch (cp->tok)
2312                 {
2313                 case CTOK_STRUCT:
2314                         tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
2315                         if (cp->error)
2316                                 return 0;
2317                         continue;
2318                 case CTOK_UNION:
2319                         tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
2320                         if (cp->error)
2321                                 return 0;
2322                         continue;
2323                 case CTOK_ENUM:
2324                         tdef = cp_decl_enum(cp, decl);
2325                         if (cp->error)
2326                                 return 0;
2327                         continue;
2328                 case CTOK_IDENT:
2329                         if (ctype_istypedef(cp->ct->info))
2330                         {
2331                                 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
2332                                 cp_next(cp);
2333                                 continue;
2334                         }
2335                         break;
2336                 case '$':
2337                         tdef = cp->val.id;
2338                         cp_next(cp);
2339                         continue;
2340                 default:
2341                         break;
2342                 }
2343                 break;
2344         }
2345 end_decl:
2346 
2347         if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
2348                 tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
2349 
2350         if (tdef)
2351         {
2352                 cp_push_type(decl, tdef);
2353         }
2354         else if ((cds & CDF_VOID))
2355         {
2356                 cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
2357                 decl->attr &= ~CTF_QUAL;
2358         }
2359         else
2360         {
2361                 /* Determine type info and size. */
2362                 CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
2363                 if ((cds & CDF_BOOL))
2364                 {
2365                         if ((cds & ~(CDF_SCL | CDF_BOOL | CDF_INT | CDF_SIGNED | CDF_UNSIGNED)))
2366                         {
2367                                 cp_errmsg(cp, 0, "invalid C type");
2368                                 return 0;
2369                         }
2370                         info |= CTF_BOOL;
2371                         if (!(cds & CDF_SIGNED))
2372                                 info |= CTF_UNSIGNED;
2373                         if (!sz)
2374                         {
2375                                 sz = 1;
2376                         }
2377                 }
2378                 else if ((cds & CDF_FP))
2379                 {
2380                         info = CTINFO(CT_NUM, CTF_FP);
2381                         if ((cds & CDF_LONG))
2382                                 sz = sizeof(long double);
2383                 }
2384                 else if ((cds & CDF_CHAR))
2385                 {
2386                         if ((cds & (CDF_CHAR | CDF_SIGNED | CDF_UNSIGNED)) == CDF_CHAR)
2387                                 info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
2388                 }
2389                 else if ((cds & CDF_SHORT))
2390                 {
2391                         sz = sizeof(short);
2392                 }
2393                 else if ((cds & CDF_LONGLONG))
2394                 {
2395                         sz = 8;
2396                 }
2397                 else if ((cds & CDF_LONG))
2398                 {
2399                         info |= CTF_LONG;
2400                         sz = sizeof(long);
2401                 }
2402                 else if (!sz)
2403                 {
2404                         if (!(cds & (CDF_SIGNED | CDF_UNSIGNED)))
2405                         {
2406                                 cp_errmsg(cp, cp->tok, "declaration specifier expected");
2407                                 return 0;
2408                         }
2409                         sz = sizeof(int);
2410                 }
2411                 uc_assertCP(sz != 0, "basic ctype with zero size");
2412                 info += CTALIGN(uc_fls(sz));     /* Use natural alignment. */
2413                 info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
2414                 cp_push(decl, info, sz);
2415                 decl->attr &= ~CTF_QUAL;
2416         }
2417         decl->specpos = decl->pos;
2418         decl->specattr = decl->attr;
2419         decl->specfattr = decl->fattr;
2420         return (cds & CDF_SCL); /* Return storage class. */
2421 }
2422 
2423 /* Parse array declaration. */
2424 static void cp_decl_array(CPState *cp, CPDecl *decl)
2425 {
2426         CTInfo info = CTINFO(CT_ARRAY, 0);
2427         CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
2428         cp_decl_attributes(cp, decl);
2429         if (cp->error)
2430                 return;
2431         if (cp_opt(cp, '?'))
2432                 info |= CTF_VLA; /* Create variable-length array a[?]. */
2433         else if (cp->tok != ']')
2434         {
2435                 nelem = cp_expr_ksize(cp);
2436                 if (cp->error)
2437                         return;
2438         }
2439         cp_check(cp, ']');
2440         cp_add(decl, info, nelem);
2441 }
2442 
2443 /* Parse function declaration. */
2444 static void cp_decl_func(CPState *cp, CPDecl *fdecl)
2445 {
2446         CTSize nargs = 0;
2447         CTInfo info = CTINFO(CT_FUNC, 0);
2448         CTypeID lastid = 0, anchor = 0;
2449         if (cp->tok != ')')
2450         {
2451                 do
2452                 {
2453                         CPDecl decl = {0};
2454                         CTypeID ctypeid, fieldid;
2455                         CType *ct;
2456                         if (cp_opt(cp, '.'))
2457                         {                                          /* Vararg function. */
2458                                 cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
2459                                 cp_check(cp, '.');
2460                                 info |= CTF_VARARG;
2461                                 break;
2462                         }
2463                         cp_decl_spec(cp, &decl, CDF_REGISTER);
2464                         if (cp->error)
2465                                 return;
2466                         decl.mode = CPARSE_MODE_DIRECT | CPARSE_MODE_ABSTRACT;
2467                         cp_declarator(cp, &decl);
2468                         if (cp->error)
2469                                 return;
2470                         ctypeid = cp_decl_intern(cp, &decl);
2471                         if (cp->error)
2472                                 return;
2473                         ct = ctype_raw(cp->cts, ctypeid);
2474                         if (ctype_isvoid(ct->info))
2475                                 break;
2476                         else if (ctype_isrefarray(ct->info))
2477                                 ctypeid = uc_ctype_intern(cp->cts,
2478                                                                                   CTINFO(CT_PTR, CTALIGN_PTR | ctype_cid(ct->info)), CTSIZE_PTR);
2479                         else if (ctype_isfunc(ct->info))
2480                                 ctypeid = uc_ctype_intern(cp->cts,
2481                                                                                   CTINFO(CT_PTR, CTALIGN_PTR | ctypeid), CTSIZE_PTR);
2482                         /* Add new parameter. */
2483                         fieldid = uc_ctype_new(cp->cts, &ct);
2484                         if (anchor)
2485                                 ctype_get(cp->cts, lastid)->sib = fieldid;
2486                         else
2487                                 anchor = fieldid;
2488                         lastid = fieldid;
2489                         if (decl.uv_name)
2490                                 ctype_setname(ct, decl.uv_name);
2491                         ct->info = CTINFO(CT_FIELD, ctypeid);
2492                         ct->size = nargs++;
2493                         cp_decl_reset(&decl);
2494                 } while (cp_opt(cp, ','));
2495         }
2496         cp_check(cp, ')');
2497         if (cp->error)
2498                 return;
2499         if (cp_opt(cp, '{'))
2500         { /* Skip function definition. */
2501                 int level = 1;
2502                 cp->mode |= CPARSE_MODE_SKIP;
2503                 for (;;)
2504                 {
2505                         if (cp->tok == '{')
2506                                 level++;
2507                         else if (cp->tok == '}' && --level == 0)
2508                                 break;
2509                         else if (cp->tok == CTOK_EOF) {
2510                                 cp_err_token(cp, '}');
2511                                 return;
2512                         }
2513                         cp_next(cp);
2514                 }
2515                 cp->mode &= ~CPARSE_MODE_SKIP;
2516                 cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
2517         }
2518         info |= (fdecl->fattr & ~CTMASK_CID);
2519         fdecl->fattr = 0;
2520         fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
2521 }
2522 
2523 /* Parse declarator. */
2524 static void cp_declarator(CPState *cp, CPDecl *decl)
2525 {
2526         if (++cp->depth > CPARSE_MAX_DECLDEPTH)
2527         {
2528                 cp_err(cp, "chunk has too many syntax levels");
2529                 return;
2530         }
2531 
2532         for (;;)
2533         { /* Head of declarator. */
2534                 if (cp_opt(cp, '*'))
2535                 { /* Pointer. */
2536                         CTSize sz;
2537                         CTInfo info;
2538                         cp_decl_attributes(cp, decl);
2539                         if (cp->error)
2540                                 return;
2541                         sz = CTSIZE_PTR;
2542                         info = CTINFO(CT_PTR, CTALIGN_PTR);
2543 #if UC_64
2544                         if (ctype_msizeP(decl->attr) == 4)
2545                         {
2546                                 sz = 4;
2547                                 info = CTINFO(CT_PTR, CTALIGN(2));
2548                         }
2549 #endif
2550                         info += (decl->attr & (CTF_QUAL | CTF_REF));
2551                         decl->attr &= ~(CTF_QUAL | (CTMASK_MSIZEP << CTSHIFT_MSIZEP));
2552                         cp_push(decl, info, sz);
2553                 }
2554                 else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND))
2555                 { /* Reference. */
2556                         decl->attr &= ~(CTF_QUAL | (CTMASK_MSIZEP << CTSHIFT_MSIZEP));
2557                         cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
2558                 }
2559                 else
2560                 {
2561                         break;
2562                 }
2563         }
2564 
2565         if (cp_opt(cp, '('))
2566         { /* Inner declarator. */
2567                 CPDeclIdx pos;
2568                 cp_decl_attributes(cp, decl);
2569                 if (cp->error)
2570                         return;
2571                 /* Resolve ambiguity between inner declarator and 1st function parameter. */
2572                 if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
2573                         (cp->tok == ')' || cp_istypedecl(cp)))
2574                         goto func_decl;
2575                 pos = decl->pos;
2576                 cp_declarator(cp, decl);
2577                 if (cp->error)
2578                         return;
2579                 cp_check(cp, ')');
2580                 if (cp->error)
2581                         return;
2582                 decl->pos = pos;
2583         }
2584         else if (cp->tok == CTOK_IDENT)
2585         { /* Direct declarator. */
2586                 if (!(decl->mode & CPARSE_MODE_DIRECT))
2587                 {
2588                         cp_err_token(cp, CTOK_EOF);
2589                         return;
2590                 }
2591                 decl->uv_name = ucv_get(cp->uv_str);
2592                 decl->nameid = cp->val.id;
2593                 cp_next(cp);
2594         }
2595         else
2596         { /* Abstract declarator. */
2597                 if (!(decl->mode & CPARSE_MODE_ABSTRACT))
2598                 {
2599                         cp_err_token(cp, CTOK_IDENT);
2600                         return;
2601                 }
2602         }
2603 
2604         for (;;)
2605         { /* Tail of declarator. */
2606                 if (cp_opt(cp, '['))
2607                 { /* Array. */
2608                         cp_decl_array(cp, decl);
2609                         if (cp->error)
2610                                 return;
2611                 }
2612                 else if (cp_opt(cp, '('))
2613                 { /* Function. */
2614                 func_decl:
2615                         cp_decl_func(cp, decl);
2616                         if (cp->error)
2617                                 return;
2618                 }
2619                 else
2620                 {
2621                         break;
2622                 }
2623         }
2624 
2625         if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
2626         {
2627                 decl->bits = cp_expr_ksize(cp);
2628                 if (cp->error)
2629                         return;
2630         }
2631 
2632         /* Process postfix attributes. */
2633         cp_decl_attributes(cp, decl);
2634         if (cp->error)
2635                 return;
2636         cp_push_attributes(decl);
2637 
2638         cp->depth--;
2639 }
2640 
2641 /* Parse an abstract type declaration and return it's C type ID. */
2642 static CTypeID cp_decl_abstract(CPState *cp)
2643 {
2644         CPDecl decl = {0};
2645         cp_decl_spec(cp, &decl, 0);
2646         if (cp->error)
2647                 return 0;
2648         decl.mode = CPARSE_MODE_ABSTRACT;
2649         cp_declarator(cp, &decl);
2650         if (cp->error)
2651                 return 0;
2652         CTypeID rv = cp_decl_intern(cp, &decl);
2653         if (cp->error)
2654                 return 0;
2655         cp_decl_reset(&decl);
2656         return rv;
2657 }
2658 
2659 /* Handle pragmas. */
2660 static void cp_pragma(CPState *cp, size_t pragmaline)
2661 {
2662         cp_next(cp);
2663         if (cp->error)
2664                 return;
2665         if (cp->tok == CTOK_IDENT && cp_str_is(cp->uv_str, "pack"))
2666         {
2667                 cp_next(cp);
2668                 if (cp->error)
2669                         return;
2670                 cp_check(cp, '(');
2671                 if (cp->error)
2672                         return;
2673                 if (cp->tok == CTOK_IDENT)
2674                 {
2675                         if (cp_str_is(cp->uv_str, "push"))
2676                         {
2677                                 if (cp->curpack < CPARSE_MAX_PACKSTACK - 1)
2678                                 {
2679                                         cp->packstack[cp->curpack + 1] = cp->packstack[cp->curpack];
2680                                         cp->curpack++;
2681                                 }
2682                                 else
2683                                 {
2684                                         cp_errmsg(cp, cp->tok, "chunk has too many syntax levels");
2685                                         return;
2686                                 }
2687                         }
2688                         else if (cp_str_is(cp->uv_str, "pop"))
2689                         {
2690                                 if (cp->curpack > 0)
2691                                         cp->curpack--;
2692                         }
2693                         else
2694                         {
2695                                 cp_errmsg(cp, cp->tok, "unexpected symbol");
2696                                 return;
2697                         }
2698                         cp_next(cp);
2699                         if (cp->error)
2700                                 return;
2701                         if (!cp_opt(cp, ','))
2702                                 goto end_pack;
2703                 }
2704                 if (cp->tok == CTOK_INTEGER)
2705                 {
2706                         cp->packstack[cp->curpack] = cp->val.u32 ? uc_fls(cp->val.u32) : 0;
2707                         cp_next(cp);
2708                         if (cp->error)
2709                                 return;
2710                 }
2711                 else
2712                 {
2713                         cp->packstack[cp->curpack] = 255;
2714                 }
2715         end_pack:
2716                 cp_check(cp, ')');
2717                 if (cp->error)
2718                         return;
2719         }
2720         else
2721         { /* Ignore all other pragmas. */
2722                 while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
2723                         cp_next(cp);
2724         }
2725 }
2726 
2727 /* Handle line number. */
2728 static void cp_line(CPState *cp, size_t hashline)
2729 {
2730         size_t newline = cp->val.u32;
2731         /* TODO: Handle file name and include it in error messages. */
2732         while (cp->tok != CTOK_EOF && cp->linenumber == hashline)
2733         {
2734                 cp_next(cp);
2735                 if (cp->error)
2736                         return;
2737         }
2738         cp->linenumber = newline;
2739 }
2740 
2741 /* Parse multiple C declarations of types or extern identifiers. */
2742 static void cp_decl_multi(CPState *cp)
2743 {
2744         int first = 1;
2745         while (cp->tok != CTOK_EOF)
2746         {
2747                 CPDecl decl = {0};
2748                 CPscl scl;
2749                 if (cp_opt(cp, ';'))
2750                 { /* Skip empty statements. */
2751                         first = 0;
2752                         continue;
2753                 }
2754                 if (cp->tok == '#')
2755                 { /* Workaround, since we have no preprocessor, yet. */
2756                         size_t hashline = cp->linenumber;
2757                         CPToken tok = cp_next(cp);
2758                         if (cp->error)
2759                                 return;
2760                         if (tok == CTOK_INTEGER)
2761                         {
2762                                 cp_line(cp, hashline);
2763                                 if (cp->error)
2764                                         return;
2765                                 continue;
2766                         }
2767                         else if (tok == CTOK_IDENT && cp_str_is(cp->uv_str, "line"))
2768                         {
2769                                 if (cp_next(cp) != CTOK_INTEGER) {
2770                                         cp_err_token(cp, tok);
2771                                         return;
2772                                 }
2773                                 cp_line(cp, hashline);
2774                                 if (cp->error)
2775                                         return;
2776                                 continue;
2777                         }
2778                         else if (tok == CTOK_IDENT && cp_str_is(cp->uv_str, "pragma"))
2779                         {
2780                                 cp_pragma(cp, hashline);
2781                                 if (cp->error)
2782                                         return;
2783                                 continue;
2784                         }
2785                         else
2786                         {
2787                                 cp_errmsg(cp, cp->tok, "unexpected symbol");
2788                                 return;
2789                         }
2790                 }
2791                 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF | CDF_EXTERN | CDF_STATIC);
2792                 if (cp->error)
2793                         return;
2794                 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
2795                         ctype_istypedef(decl.stack[0].info))
2796                 {
2797                         CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
2798                         if (ctype_isstruct(info) || ctype_isenum(info))
2799                                 goto decl_end; /* Accept empty declaration of struct/union/enum. */
2800                 }
2801                 for (;;)
2802                 {
2803                         CTypeID ctypeid;
2804                         cp_declarator(cp, &decl);
2805                         if (cp->error)
2806                                 return;
2807                         ctypeid = cp_decl_intern(cp, &decl);
2808                         if (cp->error)
2809                                 return;
2810                         if (decl.uv_name)
2811                         {
2812                                 if (decl.nameid)
2813                                 { /* Redeclaration detected - check compatibility. */
2814                                         CType *existing_ct = ctype_get(cp->cts, decl.nameid);
2815                                         CType *new_ct = ctype_get(cp->cts, ctypeid);
2816 
2817                                         /* Skip extern and attributes to get the actual function type. */
2818                                         CType *existing_func = existing_ct;
2819                                         while (ctype_isextern(existing_func->info) || ctype_isattrib(existing_func->info))
2820                                                 existing_func = ctype_rawchild(cp->cts, existing_func);
2821 
2822                                         /* Unwrap CT_FUNC if needed. */
2823                                         CType *new_func = new_ct;
2824                                         if (ctype_isptr(new_ct->info))
2825                                                 new_func = ctype_rawchild(cp->cts, new_ct);
2826 
2827                                         if (ctype_isfunc(existing_func->info) && ctype_isfunc(new_func->info) &&
2828                                             ctype_func_is_equiv(cp->cts, existing_func, new_func))
2829                                         { /* Compatible: reuse existing type. */
2830                                                 if (!existing_ct->uv_name)
2831                                                         ctype_setname(existing_ct, decl.uv_name);
2832                                                 ctypeid = decl.nameid; /* Use existing ID */
2833                                                 cp->val.id = ctypeid; /* Update parser state */
2834                                                 /* Add to hash table with the name. */
2835                                                 uc_ctype_addname(cp->cts, existing_ct, ctypeid);
2836                                                 /* Record function type ID if func_ids vector is provided */
2837                                                 if (cp->func_ids && (ctype_isfunc(existing_ct->info) ||
2838                                                     (ctype_isextern(existing_ct->info) && ctype_isfunc(ctype_get(cp->cts, ctype_cid(existing_ct->info))->info)))) {
2839                                                         uc_vector_push(cp->func_ids, ctypeid);
2840                                                 }
2841                                         }
2842                                         else
2843                                         { /* Incompatible redeclaration. */
2844                                                 cp_errmsg(cp, 0, "redeclaration of '%s' as different type",
2845                                                           ucv_string_get(decl.uv_name));
2846                                         }
2847                                 }
2848                                 else
2849                                 { /* New declaration. */
2850                                         CType *ct;
2851                                         CTypeID id;
2852                                         if ((scl & CDF_TYPEDEF))
2853                                         { /* Create new typedef. */
2854                                                 id = uc_ctype_new(cp->cts, &ct);
2855                                                 ct->info = CTINFO(CT_TYPEDEF, ctypeid);
2856                                                 goto noredir;
2857                                         }
2858                                         else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info))
2859                                         {
2860                                                 /* Treat both static and extern function declarations as extern. */
2861                                                 ct = ctype_get(cp->cts, ctypeid);
2862                                                 /* We always get new anonymous functions (typedefs are copied). */
2863                                                 uc_assertCP(ct->uv_name == NULL, "unexpected named function");
2864                                                 id = ctypeid; /* Just name it. */
2865                                         }
2866                                         else if ((scl & CDF_STATIC))
2867                                         { /* Accept static constants. */
2868                                                 id = cp_decl_constinit(cp, &ct, ctypeid);
2869                                                 goto noredir;
2870                                         }
2871                                         else
2872                                         { /* External references have extern or no storage class. */
2873                                                 id = uc_ctype_new(cp->cts, &ct);
2874                                                 ct->info = CTINFO(CT_EXTERN, ctypeid);
2875                                         }
2876                                         if (decl.uv_redir)
2877                                         { /* Add attribute for redirected symbol name. */
2878                                                 CType *cta;
2879                                                 CTypeID aid = uc_ctype_new(cp->cts, &cta);
2880                                                 ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
2881                                                 cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
2882                                                 cta->sib = ct->sib;
2883                                                 ct->sib = aid;
2884                                                 ctype_setname(cta, decl.uv_redir);
2885                                         }
2886                                 noredir:
2887                                         ctype_setname(ct, decl.uv_name);
2888                                         uc_ctype_addname(cp->cts, ct, id);
2889 
2890                                         /* Record function type ID if func_ids vector is provided */
2891                                         if (cp->func_ids && (ctype_isfunc(ct->info) ||
2892                                             (ctype_isextern(ct->info) && ctype_isfunc(ctype_get(cp->cts, ctype_cid(ct->info))->info)))) {
2893                                                 uc_vector_push(cp->func_ids, id);
2894                                         }
2895                                 }
2896                         }
2897                         cp_decl_reset(&decl);
2898                         if (!cp_opt(cp, ','))
2899                                 break;
2900                 }
2901         decl_end:
2902                 if (cp->tok == CTOK_EOF && first)
2903                         break; /* May omit ';' for 1 decl. */
2904                 first = 0;
2905                 cp_check(cp, ';');
2906         }
2907 }
2908 
2909 /* Parse a single C type declaration. */
2910 static void cp_decl_single(CPState *cp)
2911 {
2912         CPDecl decl = {0};
2913         cp_decl_spec(cp, &decl, 0);
2914         if (cp->error)
2915                 return;
2916         cp_declarator(cp, &decl);
2917         if (cp->error)
2918                 return;
2919         cp->val.id = cp_decl_intern(cp, &decl);
2920         if (cp->error)
2921                 return;
2922 
2923         CTypeID ctypeid = cp->val.id;
2924 
2925         if (decl.uv_name)
2926         {
2927                 if (decl.nameid)
2928                 { /* Redeclaration detected - check compatibility. */
2929                         CType *existing_ct = ctype_get(cp->cts, decl.nameid);
2930                         CType *new_ct = ctype_get(cp->cts, ctypeid);
2931 
2932                         /* Skip extern and attributes to get the actual function type. */
2933                         CType *existing_func = existing_ct;
2934                         while (ctype_isextern(existing_func->info) || ctype_isattrib(existing_func->info))
2935                                 existing_func = ctype_rawchild(cp->cts, existing_func);
2936 
2937                         /* Unwrap CT_PTR if needed. */
2938                         CType *new_func = new_ct;
2939                         if (ctype_isptr(new_ct->info))
2940                                 new_func = ctype_rawchild(cp->cts, new_ct);
2941 
2942                         if (ctype_isfunc(existing_func->info) && ctype_isfunc(new_func->info) &&
2943                             ctype_func_is_equiv(cp->cts, existing_func, new_func))
2944                         { /* Compatible: reuse existing type. */
2945                                 if (!existing_ct->uv_name)
2946                                         ctype_setname(existing_ct, decl.uv_name);
2947                                 ctypeid = decl.nameid; /* Use existing ID */
2948                                 cp->val.id = ctypeid; /* Update parser state */
2949                                 /* Add to hash table with the name. */
2950                                 uc_ctype_addname(cp->cts, existing_ct, ctypeid);
2951                         }
2952                         else
2953                         { /* Incompatible redeclaration. */
2954                                 cp_errmsg(cp, 0, "redeclaration of '%s' as different type",
2955                                           ucv_string_get(decl.uv_name));
2956                         }
2957                 }
2958                 else
2959                 { /* New declaration. */
2960                         CType *ct;
2961                         CTypeID id;
2962 
2963                         /* Treat both static and extern function declarations as extern. */
2964                         ct = ctype_get(cp->cts, ctypeid);
2965                         /* We always get new anonymous functions (typedefs are copied). */
2966                         uc_assertCP(ct->uv_name == NULL, "unexpected named function");
2967                         id = ctypeid; /* Just name it. */
2968 
2969                         if (ctype_isfunc(ct->info) && decl.uv_redir)
2970                         { /* Add attribute for redirected symbol name. */
2971                                 CType *cta;
2972                                 CTypeID aid = uc_ctype_new(cp->cts, &cta);
2973                                 ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
2974                                 cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
2975                                 cta->sib = ct->sib;
2976                                 ct->sib = aid;
2977                                 ctype_setname(cta, decl.uv_redir);
2978                         }
2979 
2980                         ctype_setname(ct, decl.uv_name);
2981                         uc_ctype_addname(cp->cts, ct, id);
2982                 }
2983         }
2984 
2985         cp_decl_reset(&decl);
2986 
2987         if (cp->tok != CTOK_EOF)
2988                 cp_err_token(cp, CTOK_EOF);
2989 }
2990 
2991 /* ------------------------------------------------------------------------ */
2992 
2993 /* C parser. */
2994 bool uc_cparse(CPState *cp)
2995 {
2996         bool rv = true;
2997 
2998         cp_init(cp);
2999 
3000         if ((cp->mode & CPARSE_MODE_MULTI))
3001                 cp_decl_multi(cp);
3002         else
3003                 cp_decl_single(cp);
3004 
3005         if (cp->uv_param && cp->uv_param != &cp->uv_vm->stack.entries[cp->uv_vm->stack.count])
3006                 cp_err(cp, "wrong number of type parameters");
3007 
3008         uc_assertCP(cp->depth == 0, "unbalanced cparser declaration depth");
3009 
3010         if (cp->error) {
3011                 uc_vm_raise_exception(cp->cts->vm, EXCEPTION_SYNTAX,
3012                         "invalid C type: %s", cp->error);
3013 
3014                 rv = false;
3015         }
3016 
3017         cp_cleanup(cp);
3018 
3019         return rv;
3020 }
3021 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt