Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / ktap / userspace / ffi / cparser.c
1 #include <stdarg.h>
2 #include "../cparser.h"
3
4 #define IS_CONST(tok) (IS_LITERAL(tok, "const") || IS_LITERAL(tok, "__const") \
5                         || IS_LITERAL(tok, "__const__"))
6 #define IS_VOLATILE(tok) (IS_LITERAL(tok, "volatile") || \
7                                 IS_LITERAL(tok, "__volatile") || \
8                                 IS_LITERAL(tok, "__volatile__"))
9 #define IS_RESTRICT(tok) (IS_LITERAL(tok, "restrict") || \
10                                 IS_LITERAL(tok, "__restrict") || \
11                                 IS_LITERAL(tok, "__restrict__"))
12
13 #define max(a,b) ((a) < (b) ? (b) : (a))
14 #define min(a,b) ((a) < (b) ? (a) : (b))
15
16
17 enum etoken {
18         /* 0 - 3 */
19         TOK_NIL,
20         TOK_NUMBER,
21         TOK_STRING,
22         TOK_TOKEN,
23
24         /* the order of these values must match the token strings in lex.c */
25
26         /* 4 - 5 */
27         TOK_3_BEGIN,
28         TOK_VA_ARG,
29
30         /* 6 - 14 */
31         TOK_2_BEGIN,
32         TOK_LEFT_SHIFT, TOK_RIGHT_SHIFT, TOK_LOGICAL_AND, TOK_LOGICAL_OR,
33         TOK_LESS_EQUAL, TOK_GREATER_EQUAL, TOK_EQUAL, TOK_NOT_EQUAL,
34
35         /* 15 - 20 */
36         TOK_1_BEGIN,
37         TOK_OPEN_CURLY, TOK_CLOSE_CURLY, TOK_SEMICOLON, TOK_COMMA, TOK_COLON,
38         /* 21 - 30 */
39         TOK_ASSIGN, TOK_OPEN_PAREN, TOK_CLOSE_PAREN, TOK_OPEN_SQUARE, TOK_CLOSE_SQUARE,
40         TOK_DOT, TOK_AMPERSAND, TOK_LOGICAL_NOT, TOK_BITWISE_NOT, TOK_MINUS,
41         /* 31 - 40 */
42         TOK_PLUS, TOK_STAR, TOK_DIVIDE, TOK_MODULUS, TOK_LESS,
43         TOK_GREATER, TOK_BITWISE_XOR, TOK_BITWISE_OR, TOK_QUESTION, TOK_POUND,
44
45         /* 41 - 43 */
46         TOK_REFERENCE = TOK_AMPERSAND,
47         TOK_MULTIPLY = TOK_STAR,
48         TOK_BITWISE_AND = TOK_AMPERSAND,
49 };
50
51 struct token {
52         enum etoken type;
53         int64_t integer;
54         const char *str;
55         size_t size;
56 };
57
58 #define IS_LITERAL(TOK, STR) \
59         (((TOK).size == sizeof(STR) - 1) && \
60                 0 == memcmp((TOK).str, STR, sizeof(STR) - 1))
61
62
63 static int parse_type_name(struct parser *P, char *type_name);
64 static void parse_argument(struct parser *P, struct cp_ctype *ct,
65                 struct token *pname, struct parser *asmname);
66 static int parse_attribute(struct parser *P, struct token *tok,
67                 struct cp_ctype *ct, struct parser *asmname);
68 static int parse_record(struct parser *P, struct cp_ctype *ct);
69 static void instantiate_typedef(struct parser *P, struct cp_ctype *tt,
70                 const struct cp_ctype *ft);
71
72
73 /* the order of tokens _must_ match the order of the enum etoken enum */
74
75 static char tok3[][4] = {
76         "...", /* unused ">>=", "<<=", */
77 };
78
79 static char tok2[][3] = {
80         "<<", ">>", "&&", "||", "<=",
81         ">=", "==", "!=",
82         /* unused "+=", "-=", "*=", "/=", "%=", "&=", "^=",
83          * "|=", "++", "--", "->", "::", */
84 };
85
86 static char tok1[] = {
87         '{', '}', ';', ',', ':',
88         '=', '(', ')', '[', ']',
89         '.', '&', '!', '~', '-',
90         '+', '*', '/', '%', '<',
91         '>', '^', '|', '?', '#'
92 };
93
94
95 /* this function never returns, but it's an idiom to use it in C functions
96  * as return cp_error */
97 void cp_error(const char *err_msg_fmt, ...)
98 {
99         va_list ap;
100
101         fprintf(stderr, "cparser error:\n");
102
103         va_start(ap, err_msg_fmt);
104         vfprintf(stderr, err_msg_fmt, ap);
105         va_end(ap);
106
107         exit(EXIT_FAILURE);
108 }
109
110 static int set_struct_type_name(char *dst, const char *src, int len)
111 {
112         int prefix_len = sizeof("struct ");
113
114         if (len + prefix_len > MAX_TYPE_NAME_LEN)
115                 return -1;
116
117         memset(dst, 0, MAX_TYPE_NAME_LEN);
118         strcpy(dst, "struct ");
119         strncat(dst, src, len);
120
121         return 0;
122 }
123
124 static void increase_ptr_deref_level(struct parser *P, struct cp_ctype *ct)
125 {
126         if (ct->pointers == POINTER_MAX) {
127                 cp_error("maximum number of pointer derefs reached - use a "
128                         "struct to break up the pointers on line %d", P->line);
129         } else {
130                 ct->pointers++;
131                 ct->const_mask <<= 1;
132         }
133 }
134
135 static int next_token(struct parser *P, struct token *tok)
136 {
137         size_t i;
138         const char *s = P->next;
139
140         /* UTF8 BOM */
141         if (s[0] == '\xEF' && s[1] == '\xBB' && s[2] == '\xBF') {
142                 s += 3;
143         }
144
145         /* consume whitespace and comments */
146         for (;;) {
147                 /* consume whitespace */
148                 while (*s == '\t' || *s == '\n' || *s == ' '
149                                 || *s == '\v' || *s == '\r') {
150                         if (*s == '\n') {
151                                 P->line++;
152                         }
153                         s++;
154                 }
155
156                 /* consume comments */
157                 if (*s == '/' && *(s+1) == '/') {
158
159                         s = strchr(s, '\n');
160                         if (!s) {
161                                 cp_error("non-terminated comment");
162                         }
163
164                 } else if (*s == '/' && *(s+1) == '*') {
165                         s += 2;
166
167                         for (;;) {
168                                 if (s[0] == '\0') {
169                                         cp_error("non-terminated comment");
170                                 } else if (s[0] == '*' && s[1] == '/') {
171                                         s += 2;
172                                         break;
173                                 } else if (s[0] == '\n') {
174                                         P->line++;
175                                 }
176                                 s++;
177                         }
178
179                 } else if (*s == '\0') {
180                         tok->type = TOK_NIL;
181                         return 0;
182
183                 } else {
184                         break;
185                 }
186         }
187
188         P->prev = s;
189
190         for (i = 0; i < sizeof(tok3) / sizeof(tok3[0]); i++) {
191                 if (s[0] == tok3[i][0] && s[1] == tok3[i][1] && s[2] == tok3[i][2]) {
192                         tok->type = (enum etoken) (TOK_3_BEGIN + 1 + i);
193                         P->next = s + 3;
194                         goto end;
195                 }
196         }
197
198         for (i = 0; i < sizeof(tok2) / sizeof(tok2[0]); i++) {
199                 if (s[0] == tok2[i][0] && s[1] == tok2[i][1]) {
200                         tok->type = (enum etoken) (TOK_2_BEGIN + 1 + i);
201                         P->next = s + 2;
202                         goto end;
203                 }
204         }
205
206         for (i = 0; i < sizeof(tok1) / sizeof(tok1[0]); i++) {
207                 if (s[0] == tok1[i]) {
208                         tok->type = (enum etoken) (TOK_1_BEGIN + 1 + i);
209                         P->next = s + 1;
210                         goto end;
211                 }
212         }
213
214         if (*s == '.' || *s == '-' || ('0' <= *s && *s <= '9')) {
215                 /* number */
216                 tok->type = TOK_NUMBER;
217
218                 /* split out the negative case so we get the full range of
219                  * bits for unsigned (eg to support 0xFFFFFFFF where
220                  * sizeof(long) == 4 */
221                 if (*s == '-') {
222                         tok->integer = strtol(s, (char**) &s, 0);
223                 } else {
224                         tok->integer = strtoul(s, (char**) &s, 0);
225                 }
226
227                 while (*s == 'u' || *s == 'U' || *s == 'l' || *s == 'L') {
228                         s++;
229                 }
230
231                 P->next = s;
232                 goto end;
233
234         } else if (*s == '\'' || *s == '\"') {
235                 /* "..." or '...' */
236                 char quote = *s;
237                 s++; /* jump over " */
238
239                 tok->type = TOK_STRING;
240                 tok->str = s;
241
242                 while (*s != quote) {
243                         if (*s == '\0' || (*s == '\\' && *(s+1) == '\0')) {
244                                 cp_error("string not finished\n");
245                         }
246                         if (*s == '\\') {
247                                 s++;
248                         }
249                         s++;
250                 }
251
252                 tok->size = s - tok->str;
253                 s++; /* jump over " */
254                 P->next = s;
255                 goto end;
256
257         } else if (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z')
258                         || *s == '_') {
259                 /* tokens */
260                 tok->type = TOK_TOKEN;
261                 tok->str = s;
262
263                 while (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z')
264                                 || *s == '_' || ('0' <= *s && *s <= '9')) {
265                         s++;
266                 }
267
268                 tok->size = s - tok->str;
269                 P->next = s;
270                 goto end;
271         } else {
272                 cp_error("invalid character %d", P->line);
273         }
274
275 end:
276         return 1;
277 }
278
279 static void require_token(struct parser *P, struct token *tok)
280 {
281         if (!next_token(P, tok)) {
282                 cp_error("unexpected end");
283         }
284 }
285
286 static void check_token(struct parser *P, int type, const char *str,
287                                 const char *err, ...)
288 {
289         va_list ap;
290         struct token tok;
291         if (!next_token(P, &tok) || tok.type != type
292                         || (tok.type == TOK_TOKEN && (tok.size != strlen(str)
293                                 || memcmp(tok.str, str, tok.size) != 0))) {
294
295                 va_start(ap, err);
296                 vfprintf(stderr, err, ap);
297                 va_end(ap);
298
299                 exit(EXIT_FAILURE);
300         }
301 }
302
303 static void put_back(struct parser *P) {
304         P->next = P->prev;
305 }
306
307 int64_t calculate_constant(struct parser *P);
308
309 /* parses out the base type of a type expression in a function declaration,
310  * struct definition, typedef etc
311  *
312  * leaves the usr value of the type on the stack
313  */
314 int parse_type(struct parser *P, struct cp_ctype *ct)
315 {
316         struct token tok;
317
318         memset(ct, 0, sizeof(*ct));
319
320         require_token(P, &tok);
321
322         /* get function attributes before the return type */
323         while (parse_attribute(P, &tok, ct, NULL)) {
324                 require_token(P, &tok);
325         }
326
327         /* get const/volatile before the base type */
328         for (;;) {
329                 if (tok.type != TOK_TOKEN) {
330                         cp_error("unexpected value before type name on line %d",
331                                         P->line);
332                         return 0;
333                 } else if (IS_CONST(tok)) {
334                         ct->const_mask = 1;
335                         require_token(P, &tok);
336                 } else if (IS_VOLATILE(tok) || IS_RESTRICT(tok)) {
337                         /* ignored for now */
338                         require_token(P, &tok);
339                 } else {
340                         break;
341                 }
342         }
343
344         /* get base type */
345         if (tok.type != TOK_TOKEN) {
346                 cp_error("unexpected value before type name on line %d", P->line);
347                 return 0;
348         } else if (IS_LITERAL(tok, "struct")) {
349                 ct->type = STRUCT_TYPE;
350                 parse_record(P, ct);
351         } else if (IS_LITERAL(tok, "union")) {
352                 ct->type = UNION_TYPE;
353                 parse_record(P, ct);
354         } else if (IS_LITERAL(tok, "enum")) {
355                 ct->type = ENUM_TYPE;
356                 parse_record(P, ct);
357         } else {
358                 put_back(P);
359
360                 /* lookup type */
361                 struct cp_ctype *lct;
362                 char cur_type_name[MAX_TYPE_NAME_LEN];
363
364                 memset(cur_type_name, 0, MAX_TYPE_NAME_LEN);
365                 parse_type_name(P, cur_type_name);
366                 lct = ctype_lookup_type(cur_type_name);
367                 if (!lct)
368                         cp_error("unknow type: \"%s\"\n", cur_type_name);
369
370                 instantiate_typedef(P, ct, lct);
371         }
372
373         while (next_token(P, &tok)) {
374                 if (tok.type != TOK_TOKEN) {
375                         put_back(P);
376                         break;
377                 } else if (IS_CONST(tok) || IS_VOLATILE(tok)) {
378                         /* ignore for now */
379                 } else {
380                         put_back(P);
381                         break;
382                 }
383         }
384
385         return 0;
386 }
387
388 enum test {TEST};
389
390 /* Parses an enum definition from after the open curly through to the close
391  * curly. Expects the user table to be on the top of the stack
392  */
393 static int parse_enum(struct parser *P, struct cp_ctype *type)
394 {
395         struct token tok;
396         int value = -1;
397
398         /*@TODO clean up this function when enum support is added*/
399         cp_error("TODO: enum not supported!\n");
400
401         for (;;) {
402                 require_token(P, &tok);
403
404                 if (tok.type == TOK_CLOSE_CURLY) {
405                         break;
406                 } else if (tok.type != TOK_TOKEN) {
407                         cp_error("unexpected token in enum at line %d", P->line);
408                         return 0;
409                 }
410                 require_token(P, &tok);
411
412                 if (tok.type == TOK_COMMA || tok.type == TOK_CLOSE_CURLY) {
413                         /* we have an auto calculated enum value */
414                         value++;
415                 } else if (tok.type == TOK_ASSIGN) {
416                         /* we have an explicit enum value */
417                         value = (int) calculate_constant(P);
418                         require_token(P, &tok);
419                 } else {
420                         cp_error("unexpected token in enum at line %d", P->line);
421                         return 0;
422                 }
423
424                 if (tok.type == TOK_CLOSE_CURLY) {
425                         break;
426                 } else if (tok.type != TOK_COMMA) {
427                         cp_error("unexpected token in enum at line %d", P->line);
428                         return 0;
429                 }
430         }
431
432         type->base_size = sizeof(enum test);
433         type->align_mask = sizeof(enum test) - 1;
434
435         return 0;
436 }
437
438 /* Parses a struct from after the open curly through to the close curly. */
439 static int parse_struct(struct parser *P, const struct cp_ctype *ct)
440 {
441         struct token tok;
442
443         /* parse members */
444         for (;;) {
445                 struct cp_ctype mbase;
446
447                 /* see if we're at the end of the struct */
448                 require_token(P, &tok);
449                 if (tok.type == TOK_CLOSE_CURLY) {
450                         break;
451                 } else if (ct->is_variable_struct) {
452                         cp_error("can't have members after a variable sized "
453                                         "member on line %d", P->line);
454                         return -1;
455                 } else {
456                         put_back(P);
457                 }
458
459                 /* members are of the form
460                  * <base type> <arg>, <arg>, <arg>;
461                  * eg struct foo bar, *bar2[2];
462                  * mbase is 'struct foo'
463                  * mtype is '' then '*[2]'
464                  * mname is 'bar' then 'bar2'
465                  */
466
467                 parse_type(P, &mbase);
468
469                 for (;;) {
470                         struct token mname;
471                         struct cp_ctype mt = mbase;
472
473                         memset(&mname, 0, sizeof(mname));
474
475                         if (ct->is_variable_struct) {
476                                 cp_error("can't have members after a variable "
477                                         "sized member on line %d", P->line);
478                                 return -1;
479                         }
480
481                         parse_argument(P, &mt, &mname, NULL);
482
483                         if (!mt.is_defined && (mt.pointers - mt.is_array) == 0) {
484                                 cp_error("member type is undefined on line %d",
485                                                 P->line);
486                                 return -1;
487                         }
488
489                         if (mt.type == VOID_TYPE
490                                         && (mt.pointers - mt.is_array) == 0) {
491                                 cp_error("member type can not be void on line %d",
492                                                 P->line);
493                                 return -1;
494                         }
495
496                         mt.has_member_name = (mname.size > 0);
497                         if (mt.has_member_name) {
498                                 cp_push_ctype_with_name(&mt,
499                                                 mname.str, mname.size);
500                         } else {
501                                 /* @TODO handle unnamed member (houqp) */
502                                 cp_error("TODO: unnamed member not supported.");
503                                 cp_push_ctype(&mt);
504                         }
505
506                         require_token(P, &tok);
507                         if (tok.type == TOK_SEMICOLON) {
508                                 break;
509                         } else if (tok.type != TOK_COMMA) {
510                                 cp_error("unexpected token in struct "
511                                         "definition on line %d", P->line);
512                         }
513                 }
514         }
515
516         return 0;
517 }
518
519 /* copy over attributes that could be specified before the typedef eg
520  * __attribute__(packed) const type_t */
521 static void instantiate_typedef(struct parser *P, struct cp_ctype *tt,
522                 const struct cp_ctype *ft)
523 {
524         struct cp_ctype pt = *tt;
525         *tt = *ft;
526
527         tt->const_mask |= pt.const_mask;
528         tt->is_packed = pt.is_packed;
529
530         if (tt->is_packed) {
531                 tt->align_mask = 0;
532         } else {
533                 /* Instantiate the typedef in the current packing. This may be
534                  * further updated if a pointer is added or another alignment
535                  * attribute is applied. If pt.align_mask is already non-zero
536                  * than an increased alignment via __declspec(aligned(#)) has
537                  * been set. */
538                 tt->align_mask = max(min(P->align_mask, tt->align_mask),
539                                         pt.align_mask);
540         }
541 }
542
543 /* this parses a struct or union starting with the optional
544  * name before the opening brace
545  * leaves the type usr value on the stack */
546 static int parse_record(struct parser *P, struct cp_ctype *ct)
547 {
548         struct token tok;
549         char cur_type_name[MAX_TYPE_NAME_LEN];
550
551         require_token(P, &tok);
552
553         /* name is optional */
554         if (tok.type == TOK_TOKEN) {
555                 /* declaration */
556                 struct cp_ctype *lct;
557
558                 memset(cur_type_name, 0, MAX_TYPE_NAME_LEN);
559                 set_struct_type_name(cur_type_name, tok.str, tok.size);
560 ;
561                 /* lookup the name to see if we've seen this type before */
562                 lct = ctype_lookup_type(cur_type_name);
563
564                 if (!lct) {
565                         /* new type, delay type registration to the end
566                          * of this function */
567                 } else {
568                         /* get the exsting declared type */
569                         if (lct->type != ct->type) {
570                                 cp_error("type '%s' previously declared as '%s'",
571                                         cur_type_name,
572                                         csym_name(ct_ffi_cs(lct)));
573                         }
574
575                         instantiate_typedef(P, ct, lct);
576                 }
577
578                 /* if a name is given then we may be at the end of the string
579                  * eg for ffi.new('struct foo') */
580                 if (!next_token(P, &tok)) {
581                         return 0;
582                 }
583         } else {
584                 /* create a new unnamed record */
585
586                 /*@TODO clean this up after unnamed record support is added */
587                 cp_error("TODO: support unnamed record.\n");
588         }
589
590         if (tok.type != TOK_OPEN_CURLY) {
591                 /* this may just be a declaration or use of the type as an
592                  * argument or member */
593                 put_back(P);
594                 return 0;
595         }
596
597         if (ct->is_defined) {
598                 cp_error("redefinition in line %d", P->line);
599                 return 0;
600         }
601
602         if (ct->type == ENUM_TYPE) {
603                 parse_enum(P, ct);
604         } else {
605                 /* we do a two stage parse, where we parse the content first
606                  * and build up the temp user table. We then iterate over that
607                  * to calculate the offsets and fill out ct_usr. This is so we
608                  * can handle out of order members (eg vtable) and attributes
609                  * specified at the end of the struct. */
610                 parse_struct(P, ct);
611                 /* build symbol for vm */
612                 ct->ffi_cs_id = cp_symbol_build_struct(cur_type_name);
613                 /* save cp_ctype for parser */
614                 cp_ctype_reg_type(cur_type_name, ct);
615         }
616
617         cp_set_defined(ct);
618         return 0;
619 }
620
621 /* parses single or multi work built in types, and pushes it onto the stack */
622 static int parse_type_name(struct parser *P, char *type_name)
623 {
624         struct token tok;
625         int flags = 0;
626
627         enum {
628                 UNSIGNED = 0x01,
629                 SIGNED = 0x02,
630                 LONG = 0x04,
631                 SHORT = 0x08,
632                 INT = 0x10,
633                 CHAR = 0x20,
634                 LONG_LONG = 0x40,
635                 INT8 = 0x80,
636                 INT16 = 0x100,
637                 INT32 = 0x200,
638                 INT64 = 0x400,
639         };
640
641         require_token(P, &tok);
642
643         /* we have to manually decode the builtin types since they can take up
644          * more then one token */
645         for (;;) {
646                 if (tok.type != TOK_TOKEN) {
647                         break;
648                 } else if (IS_LITERAL(tok, "unsigned")) {
649                         flags |= UNSIGNED;
650                 } else if (IS_LITERAL(tok, "signed")) {
651                         flags |= SIGNED;
652                 } else if (IS_LITERAL(tok, "short")) {
653                         flags |= SHORT;
654                 } else if (IS_LITERAL(tok, "char")) {
655                         flags |= CHAR;
656                 } else if (IS_LITERAL(tok, "long")) {
657                         flags |= (flags & LONG) ? LONG_LONG : LONG;
658                 } else if (IS_LITERAL(tok, "int")) {
659                         flags |= INT;
660                 } else if (IS_LITERAL(tok, "__int8")) {
661                         flags |= INT8;
662                 } else if (IS_LITERAL(tok, "__int16")) {
663                         flags |= INT16;
664                 } else if (IS_LITERAL(tok, "__int32")) {
665                         flags |= INT32;
666                 } else if (IS_LITERAL(tok, "__int64")) {
667                         flags |= INT64;
668                 } else if (IS_LITERAL(tok, "register")) {
669                         /* ignore */
670                 } else {
671                         break;
672                 }
673
674                 if (!next_token(P, &tok)) {
675                         break;
676                 }
677         }
678
679         if (flags) {
680                 put_back(P);
681         }
682
683         if (flags & CHAR) {
684                 if (flags & SIGNED) {
685                         strcpy(type_name, "int8_t");
686                 } else if (flags & UNSIGNED) {
687                         strcpy(type_name, "uint8_t");
688                 } else {
689                         if (((char) -1) > 0) {
690                                 strcpy(type_name, "uint8_t");
691                         } else {
692                                 strcpy(type_name, "int8_t");
693                         }
694                 }
695         } else if (flags & INT8) {
696                 strcpy(type_name, (flags & UNSIGNED) ? "uint8_t" : "int8_t");
697         } else if (flags & INT16) {
698                 strcpy(type_name, (flags & UNSIGNED) ? "uint16_t" : "int16_t");
699         } else if (flags & INT32) {
700                 strcpy(type_name, (flags & UNSIGNED) ? "uint32_t" : "int32_t");
701         } else if (flags & INT64) {
702                 strcpy(type_name, (flags & UNSIGNED) ? "uint64_t" : "int64_t");
703         } else if (flags & LONG_LONG) {
704                 strcpy(type_name, (flags & UNSIGNED) ? "uint64_t" : "int64_t");
705         } else if (flags & SHORT) {
706 #define SHORT_TYPE(u) (sizeof(short) == sizeof(int64_t) ? \
707                 u "int64_t" : sizeof(short) == sizeof(int32_t) ? \
708                 u "int32_t" : u "int16_t")
709                 if (flags & UNSIGNED) {
710                         strcpy(type_name, SHORT_TYPE("u"));
711                 } else {
712                         strcpy(type_name, SHORT_TYPE(""));
713                 }
714 #undef SHORT_TYPE
715         } else if (flags & LONG) {
716 #define LONG_TYPE(u) (sizeof(long) == sizeof(int64_t) ? \
717                 u "int64_t" : u "int32_t")
718                 if (flags & UNSIGNED) {
719                         strcpy(type_name, LONG_TYPE("u"));
720                 } else {
721                         strcpy(type_name, LONG_TYPE(""));
722                 }
723 #undef LONG_TYPE
724         } else if (flags) {
725 #define INT_TYPE(u) (sizeof(int) == sizeof(int64_t) ? \
726                 u "int64_t" : sizeof(int) == sizeof(int32_t) ? \
727                 u "int32_t" : u "int16_t")
728                 if (flags & UNSIGNED) {
729                         strcpy(type_name, INT_TYPE("u"));
730                 } else {
731                         strcpy(type_name, INT_TYPE(""));
732                 }
733 #undef INT_TYPE
734         } else {
735                 strncpy(type_name, tok.str, tok.size);
736         }
737
738         return 0;
739 }
740
741 /* parse_attribute parses a token to see if it is an attribute. It may then
742  * parse some following tokens to decode the attribute setting the appropriate
743  * fields in ct. It will return 1 if the token was used (and possibly some
744  * more following it) or 0 if not. If the token was used, the next token must
745  * be retrieved using next_token/require_token. */
746 static int parse_attribute(struct parser *P, struct token *tok,
747                 struct cp_ctype *ct, struct parser *asmname)
748 {
749         if (tok->type != TOK_TOKEN) {
750                 return 0;
751         } else if (asmname && (IS_LITERAL(*tok, "__asm__")
752                                 || IS_LITERAL(*tok, "__asm"))) {
753                 check_token(P, TOK_OPEN_PAREN, NULL,
754                                 "unexpected token after __asm__ on line %d",
755                                 P->line);
756                 *asmname = *P;
757
758                 require_token(P, tok);
759                 while (tok->type == TOK_STRING) {
760                         require_token(P, tok);
761                 }
762
763                 if (tok->type != TOK_CLOSE_PAREN) {
764                         cp_error("unexpected token after __asm__ on line %d",
765                                         P->line);
766                 }
767                 return 1;
768
769         } else if (IS_LITERAL(*tok, "__attribute__")
770                         || IS_LITERAL(*tok, "__declspec")) {
771                 int parens = 1;
772                 check_token(P, TOK_OPEN_PAREN, NULL,
773                                 "expected parenthesis after __attribute__ or "
774                                 "__declspec on line %d", P->line);
775
776                 for (;;) {
777                         require_token(P, tok);
778                         if (tok->type == TOK_OPEN_PAREN) {
779                                 parens++;
780                         } else if (tok->type == TOK_CLOSE_PAREN) {
781                                 if (--parens == 0) {
782                                         break;
783                                 }
784
785                         } else if (tok->type != TOK_TOKEN) {
786                                 /* ignore unknown symbols within parentheses */
787
788                         } else if (IS_LITERAL(*tok, "align") ||
789                                         IS_LITERAL(*tok, "aligned") ||
790                                         IS_LITERAL(*tok, "__aligned__")) {
791                                 unsigned align = 0;
792                                 require_token(P, tok);
793
794                                 switch (tok->type) {
795                                 case TOK_CLOSE_PAREN:
796                                         align = ALIGNED_DEFAULT;
797                                         put_back(P);
798                                         break;
799
800                                 case TOK_OPEN_PAREN:
801                                         require_token(P, tok);
802
803                                         if (tok->type != TOK_NUMBER) {
804                                                 cp_error("expected align(#) "
805                                                         "on line %d", P->line);
806                                         }
807
808                                         switch (tok->integer) {
809                                         case 1: align = 0; break;
810                                         case 2: align = 1; break;
811                                         case 4: align = 3; break;
812                                         case 8: align = 7; break;
813                                         case 16: align = 15; break;
814                                         default:
815                                                 cp_error("unsupported align "
816                                                         "size on line %d",
817                                                         P->line);
818                                         }
819
820                                         check_token(P, TOK_CLOSE_PAREN, NULL,
821                                                 "expected align(#) on line %d",
822                                                 P->line);
823                                         break;
824
825                                 default:
826                                         cp_error("expected align(#) on line %d",
827                                                         P->line);
828                                 }
829
830                                 /* __attribute__(aligned(#)) is only supposed
831                                  * to increase alignment */
832                                 ct->align_mask = max(align, ct->align_mask);
833
834                         } else if (IS_LITERAL(*tok, "packed")
835                                         || IS_LITERAL(*tok, "__packed__")) {
836                                 ct->align_mask = 0;
837                                 ct->is_packed = 1;
838
839                         } else if (IS_LITERAL(*tok, "mode")
840                                         || IS_LITERAL(*tok, "__mode__")) {
841
842                                 check_token(P, TOK_OPEN_PAREN, NULL,
843                                         "expected mode(MODE) on line %d",
844                                         P->line);
845
846                                 require_token(P, tok);
847                                 if (tok->type != TOK_TOKEN) {
848                                         cp_error("expected mode(MODE) on line %d",
849                                                         P->line);
850                                 }
851
852
853                                 struct {char ch; uint16_t v;} a16;
854                                 struct {char ch; uint32_t v;} a32;
855                                 struct {char ch; uint64_t v;} a64;
856
857                                 if (IS_LITERAL(*tok, "QI")
858                                                 || IS_LITERAL(*tok, "__QI__")
859                                                 || IS_LITERAL(*tok, "byte")
860                                                 || IS_LITERAL(*tok, "__byte__")
861                                    ) {
862                                         ct->type = INT8_TYPE;
863                                         ct->base_size = sizeof(uint8_t);
864                                         ct->align_mask = 0;
865
866                                 } else if (IS_LITERAL(*tok, "HI")
867                                                 || IS_LITERAL(*tok, "__HI__")) {
868                                         ct->type = INT16_TYPE;
869                                         ct->base_size = sizeof(uint16_t);
870                                         ct->align_mask = ALIGNOF(a16);
871
872                                 } else if (IS_LITERAL(*tok, "SI")
873                                                 || IS_LITERAL(*tok, "__SI__")
874 #if defined ARCH_X86 || defined ARCH_ARM
875                                                 || IS_LITERAL(*tok, "word")
876                                                 || IS_LITERAL(*tok, "__word__")
877                                                 || IS_LITERAL(*tok, "pointer")
878                                                 || IS_LITERAL(*tok, "__pointer__")
879 #endif
880                                           ) {
881                                         ct->type = INT32_TYPE;
882                                         ct->base_size = sizeof(uint32_t);
883                                         ct->align_mask = ALIGNOF(a32);
884
885                                 } else if (IS_LITERAL(*tok, "DI")
886                                                 || IS_LITERAL(*tok, "__DI__")
887 #if defined ARCH_X64
888                                                 || IS_LITERAL(*tok, "word")
889                                                 || IS_LITERAL(*tok, "__word__")
890                                                 || IS_LITERAL(*tok, "pointer")
891                                                 || IS_LITERAL(*tok, "__pointer__")
892 #endif
893                                           ) {
894                                         ct->type = INT64_TYPE;
895                                         ct->base_size = sizeof(uint64_t);
896                                         ct->align_mask = ALIGNOF(a64);
897
898                                 } else {
899                                         cp_error("unexpected mode on line %d",
900                                                         P->line);
901                                 }
902
903                                 check_token(P, TOK_CLOSE_PAREN, NULL,
904                                         "expected mode(MODE) on line %d", P->line);
905
906                         } else if (IS_LITERAL(*tok, "cdecl")
907                                         || IS_LITERAL(*tok, "__cdecl__")) {
908                                 ct->calling_convention = C_CALL;
909
910                         } else if (IS_LITERAL(*tok, "fastcall")
911                                         || IS_LITERAL(*tok, "__fastcall__")) {
912                                 ct->calling_convention = FAST_CALL;
913
914                         } else if (IS_LITERAL(*tok, "stdcall")
915                                         || IS_LITERAL(*tok, "__stdcall__")) {
916                                 ct->calling_convention = STD_CALL;
917                         }
918                         /* ignore unknown tokens within parentheses */
919                 }
920                 return 1;
921
922         } else if (IS_LITERAL(*tok, "__cdecl")) {
923                 ct->calling_convention = C_CALL;
924                 return 1;
925
926         } else if (IS_LITERAL(*tok, "__fastcall")) {
927                 ct->calling_convention = FAST_CALL;
928                 return 1;
929
930         } else if (IS_LITERAL(*tok, "__stdcall")) {
931                 ct->calling_convention = STD_CALL;
932                 return 1;
933
934         } else if (IS_LITERAL(*tok, "__extension__")
935                         || IS_LITERAL(*tok, "extern")) {
936                 /* ignore */
937                 return 1;
938         } else {
939                 return 0;
940         }
941 }
942
943 /* parses from after the opening paranthesis to after the closing parenthesis */
944 static void parse_function_arguments(struct parser* P, struct cp_ctype* ct)
945 {
946         struct token tok;
947         int args = 0;
948
949         for (;;) {
950                 require_token(P, &tok);
951
952                 if (tok.type == TOK_CLOSE_PAREN)
953                         break;
954
955                 if (args) {
956                         if (tok.type != TOK_COMMA) {
957                                 cp_error("unexpected token in function "
958                                                 "argument %d on line %d",
959                                                 args, P->line);
960                         }
961                         require_token(P, &tok);
962                 }
963
964                 if (tok.type == TOK_VA_ARG) {
965                         ct->has_var_arg = true;
966                         check_token(P, TOK_CLOSE_PAREN, "",
967                                         "unexpected token after ... in "
968                                         "function on line %d",
969                                         P->line);
970                         break;
971                 } else if (tok.type == TOK_TOKEN) {
972                         struct cp_ctype at;
973
974                         put_back(P);
975                         parse_type(P, &at);
976                         parse_argument(P, &at, NULL, NULL);
977
978                         /* array arguments are just treated as their
979                          * base pointer type */
980                         at.is_array = 0;
981
982                         /* check for the c style int func(void) and error
983                          * on other uses of arguments of type void */
984                         if (at.type == VOID_TYPE && at.pointers == 0) {
985                                 if (args) {
986                                         cp_error("can't have argument of type "
987                                                         "void on line %d",
988                                                         P->line);
989                                 }
990
991                                 check_token(P, TOK_CLOSE_PAREN, "",
992                                         "unexpected void in function on line %d",
993                                         P->line);
994                                 break;
995                         }
996                         cp_push_ctype(&at);
997                         args++;
998                 } else {
999                         cp_error("unexpected token in function argument %d "
1000                                         "on line %d", args+1, P->line);
1001                 }
1002         }
1003 }
1004
1005 static int max_bitfield_size(int type)
1006 {
1007         switch (type) {
1008         case BOOL_TYPE:
1009                 return 1;
1010         case INT8_TYPE:
1011                 return 8;
1012         case INT16_TYPE:
1013                 return 16;
1014         case INT32_TYPE:
1015         case ENUM_TYPE:
1016                 return 32;
1017         case INT64_TYPE:
1018                 return 64;
1019         default:
1020                 return -1;
1021         }
1022 }
1023
1024 static struct cp_ctype *parse_argument2(struct parser *P, struct cp_ctype *ct,
1025                 struct token *name, struct parser *asmname);
1026
1027 /* parses from after the first ( in a function declaration or function pointer
1028  * can be one of:
1029  * void foo(...) before ...
1030  * void (foo)(...) before foo
1031  * void (* <>)(...) before <> which is the inner type */
1032 static struct cp_ctype *parse_function(struct parser *P, struct cp_ctype *ct,
1033                                 struct token *name, struct parser *asmname)
1034 {
1035         /* We have a function pointer or a function. The usr table will
1036          * get replaced by the canonical one (if there is one) in
1037          * find_canonical_usr after all the arguments and returns have
1038          * been parsed. */
1039         struct token tok;
1040         struct cp_ctype *ret = ct;
1041
1042         cp_push_ctype(ct);
1043
1044         memset(ct, 0, sizeof(*ct));
1045         ct->base_size = sizeof(void (*)());
1046         ct->align_mask = min(FUNCTION_ALIGN_MASK, P->align_mask);
1047         ct->type = FUNCTION_TYPE;
1048         ct->is_defined = 1;
1049
1050         if (name->type == TOK_NIL) {
1051                 for (;;) {
1052                         require_token(P, &tok);
1053
1054                         if (tok.type == TOK_STAR) {
1055                                 if (ct->type == FUNCTION_TYPE) {
1056                                         ct->type = FUNCTION_PTR_TYPE;
1057                                 } else {
1058                                         increase_ptr_deref_level(P, ct);
1059                                 }
1060                         } else if (parse_attribute(P, &tok, ct, asmname)) {
1061                                 /* parse_attribute sets the appropriate fields */
1062                         } else {
1063                                 /* call parse_argument to handle the inner
1064                                  * contents e.g. the <> in "void (* <>)
1065                                  * (...)". Note that the inner contents can
1066                                  * itself be a function, a function ptr,
1067                                  * array, etc (e.g. "void (*signal(int sig,
1068                                  * void (*func)(int)))(int)" ). */
1069                                 cp_error("TODO: inner function not supported for now.");
1070                                 put_back(P);
1071                                 ct = parse_argument2(P, ct, name, asmname);
1072                                 break;
1073                         }
1074                 }
1075
1076                 check_token(P, TOK_CLOSE_PAREN, NULL,
1077                         "unexpected token in function on line %d", P->line);
1078                 check_token(P, TOK_OPEN_PAREN, NULL,
1079                         "unexpected token in function on line %d", P->line);
1080         }
1081
1082         parse_function_arguments(P, ct);
1083
1084         /*@TODO support for inner function  24.11 2013 (houqp)*/
1085         /* if we have an inner function then set the outer function ptr as its
1086          * return type and return the inner function
1087          * e.g. for void (* <signal(int, void (*)(int))> )(int) inner is
1088          * surrounded by <>, return type is void (*)(int) */
1089
1090         return ret;
1091 }
1092
1093 static struct cp_ctype *parse_argument2(struct parser *P, struct cp_ctype *ct,
1094                                 struct token *name, struct parser *asmname)
1095 {
1096         struct token tok;
1097
1098         for (;;) {
1099                 if (!next_token(P, &tok)) {
1100                         /* we've reached the end of the string */
1101                         break;
1102                 } else if (tok.type == TOK_STAR) {
1103                         increase_ptr_deref_level(P, ct);
1104
1105                         /* __declspec(align(#)) may come before the type in a
1106                          * member */
1107                         if (!ct->is_packed) {
1108                                 ct->align_mask = max(min(PTR_ALIGN_MASK, P->align_mask),
1109                                                         ct->align_mask);
1110                         }
1111                 } else if (tok.type == TOK_REFERENCE) {
1112                         cp_error("NYI: c++ reference types");
1113                         return 0;
1114                 } else if (parse_attribute(P, &tok, ct, asmname)) {
1115                         /* parse attribute has filled out appropriate fields in type */
1116
1117                 } else if (tok.type == TOK_OPEN_PAREN) {
1118                         ct = parse_function(P, ct, name, asmname);
1119                 } else if (tok.type == TOK_OPEN_SQUARE) {
1120                         /* array */
1121                         if (ct->pointers == POINTER_MAX) {
1122                                 cp_error("maximum number of pointer derefs "
1123                                         "reached - use a struct to break up "
1124                                         "the pointers");
1125                         }
1126                         ct->is_array = 1;
1127                         ct->pointers++;
1128                         ct->const_mask <<= 1;
1129                         require_token(P, &tok);
1130
1131                         if (ct->pointers == 1 && !ct->is_defined) {
1132                                 cp_error("array of undefined type on line %d",
1133                                                 P->line);
1134                         }
1135
1136                         if (ct->is_variable_struct || ct->is_variable_array) {
1137                                 cp_error("can't have an array of a variably "
1138                                         "sized type on line %d", P->line);
1139                         }
1140
1141                         if (tok.type == TOK_QUESTION) {
1142                                 ct->is_variable_array = 1;
1143                                 ct->variable_increment = (ct->pointers > 1) ?
1144                                                 sizeof(void*) : ct->base_size;
1145                                 check_token(P, TOK_CLOSE_SQUARE, "",
1146                                         "invalid character in array on line %d",
1147                                         P->line);
1148
1149                         } else if (tok.type == TOK_CLOSE_SQUARE) {
1150                                 ct->array_size = 0;
1151
1152                         } else if (tok.type == TOK_TOKEN && IS_RESTRICT(tok)) {
1153                                 /* odd gcc extension foo[__restrict] for arguments */
1154                                 ct->array_size = 0;
1155                                 check_token(P, TOK_CLOSE_SQUARE, "",
1156                                         "invalid character in array on line %d",
1157                                         P->line);
1158                         } else {
1159                                 int64_t asize;
1160                                 put_back(P);
1161                                 asize = calculate_constant(P);
1162                                 if (asize < 0) {
1163                                         cp_error("array size can not be "
1164                                                 "negative on line %d", P->line);
1165                                         return 0;
1166                                 }
1167                                 ct->array_size = (size_t) asize;
1168                                 check_token(P, TOK_CLOSE_SQUARE, "",
1169                                         "invalid character in array on line %d",
1170                                         P->line);
1171                         }
1172
1173                 } else if (tok.type == TOK_COLON) {
1174                         int64_t bsize = calculate_constant(P);
1175
1176                         if (ct->pointers || bsize < 0
1177                                         || bsize > max_bitfield_size(ct->type)) {
1178                                 cp_error("invalid bitfield on line %d", P->line);
1179                         }
1180
1181                         ct->is_bitfield = 1;
1182                         ct->bit_size = (unsigned) bsize;
1183
1184                 } else if (tok.type != TOK_TOKEN) {
1185                         /* we've reached the end of the declaration */
1186                         put_back(P);
1187                         break;
1188
1189                 } else if (IS_CONST(tok)) {
1190                         ct->const_mask |= 1;
1191
1192                 } else if (IS_VOLATILE(tok) || IS_RESTRICT(tok)) {
1193                         /* ignored for now */
1194
1195                 } else {
1196                         *name = tok;
1197                 }
1198         }
1199
1200         return ct;
1201 }
1202
1203
1204
1205 /* parses after the main base type of a typedef, function argument or
1206  * struct/union member
1207  * eg for const void* bar[3] the base type is void with the subtype so far of
1208  * const, this parses the "* bar[3]" and updates the type argument
1209  *
1210  * type must be as filled out by parse_type
1211  *
1212  * pushes the updated user value on the top of the stack
1213  */
1214 void parse_argument(struct parser *P, struct cp_ctype *ct, struct token *pname,
1215                         struct parser *asmname)
1216 {
1217         struct token tok, name;
1218
1219         memset(&name, 0, sizeof(name));
1220         parse_argument2(P, ct, &name, asmname);
1221
1222         for (;;) {
1223                 if (!next_token(P, &tok)) {
1224                         break;
1225                 } else if (parse_attribute(P, &tok, ct, asmname)) {
1226                         /* parse_attribute sets the appropriate fields */
1227                 } else {
1228                         put_back(P);
1229                         break;
1230                 }
1231         }
1232
1233         if (pname) {
1234                 *pname = name;
1235         }
1236 }
1237
1238 static void parse_typedef(struct parser *P)
1239 {
1240         struct token tok;
1241         struct cp_ctype base_type;
1242         char typedef_name[MAX_TYPE_NAME_LEN];
1243
1244         parse_type(P, &base_type);
1245
1246         for (;;) {
1247                 struct cp_ctype arg_type = base_type;
1248                 struct token name;
1249
1250                 memset(&name, 0, sizeof(name));
1251
1252                 parse_argument(P, &arg_type, &name, NULL);
1253
1254                 if (!name.size) {
1255                         cp_error("Can't have a typedef without a name on line %d",
1256                                         P->line);
1257                 } else if (arg_type.is_variable_array) {
1258                         cp_error("Can't typedef a variable length array on line %d",
1259                                         P->line);
1260                 }
1261
1262                 memset(typedef_name, 0, sizeof(typedef_name));
1263                 strncpy(typedef_name, name.str, name.size);
1264                 /* link typedef name with ctype for parser */
1265                 cp_ctype_reg_type(typedef_name, &arg_type);
1266
1267                 require_token(P, &tok);
1268
1269                 if (tok.type == TOK_SEMICOLON) {
1270                         break;
1271                 } else if (tok.type != TOK_COMMA) {
1272                         cp_error("Unexpected character in typedef on line %d",
1273                                         P->line);
1274                 }
1275         }
1276 }
1277
1278 #define END 0
1279 #define PRAGMA_POP 1
1280
1281 static int parse_root(struct parser *P)
1282 {
1283         struct token tok;
1284
1285         while (next_token(P, &tok)) {
1286                 /* we can have:
1287                  * struct definition
1288                  * enum definition
1289                  * union definition
1290                  * struct/enum/union declaration
1291                  * typedef
1292                  * function declaration
1293                  * pragma pack
1294                  */
1295
1296                 if (tok.type == TOK_SEMICOLON) {
1297                         /* empty semicolon in root continue on */
1298
1299                 } else if (tok.type == TOK_POUND) {
1300
1301                         check_token(P, TOK_TOKEN, "pragma",
1302                                 "unexpected pre processor directive on line %d",
1303                                 P->line);
1304                         check_token(P, TOK_TOKEN, "pack",
1305                                 "unexpected pre processor directive on line %d",
1306                                 P->line);
1307                         check_token(P, TOK_OPEN_PAREN, "",
1308                                 "invalid pack directive on line %d",
1309                                 P->line);
1310                         require_token(P, &tok);
1311
1312                         if (tok.type == TOK_NUMBER) {
1313                                 if (tok.integer != 1 && tok.integer != 2
1314                                                 && tok.integer != 4
1315                                                 && tok.integer != 8
1316                                                 && tok.integer != 16) {
1317                                         cp_error("pack directive with invalid "
1318                                                         "pack size on line %d",
1319                                                         P->line);
1320                                         return 0;
1321                                 }
1322
1323                                 P->align_mask = (unsigned) (tok.integer - 1);
1324                                 check_token(P, TOK_CLOSE_PAREN, "",
1325                                         "invalid pack directive on line %d",
1326                                         P->line);
1327                         } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "push")) {
1328                                 /*int line = P->line;*/
1329                                 unsigned previous_alignment = P->align_mask;
1330
1331                                 check_token(P, TOK_CLOSE_PAREN, "",
1332                                         "invalid pack directive on line %d",
1333                                         P->line);
1334
1335                                 if (parse_root(P) != PRAGMA_POP) {
1336                                         cp_error("reached end of string "
1337                                                 "without a pragma pop to "
1338                                                 "match the push on line %d",
1339                                                 P->line);
1340                                         return 0;
1341                                 }
1342
1343                                 P->align_mask = previous_alignment;
1344
1345                         } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "pop")) {
1346                                 check_token(P, TOK_CLOSE_PAREN, "",
1347                                         "invalid pack directive on line %d",
1348                                                 P->line);
1349                                 return PRAGMA_POP;
1350                         } else {
1351                                 cp_error("invalid pack directive on line %d",
1352                                                 P->line);
1353                                 return 0;
1354                         }
1355                 } else if (tok.type != TOK_TOKEN) {
1356                         cp_error("unexpected character on line %d", P->line);
1357                         return 0;
1358                 } else if (IS_LITERAL(tok, "__extension__")) {
1359                         /* ignore */
1360                         continue;
1361                 } else if (IS_LITERAL(tok, "extern")) {
1362                         /* ignore extern as data and functions can only be
1363                          * extern */
1364                         continue;
1365                 } else if (IS_LITERAL(tok, "typedef")) {
1366                         parse_typedef(P);
1367                 } else if (IS_LITERAL(tok, "static")) {
1368                         /*@TODO we haven't tested static so far */
1369                         cp_error("TODO: support static keyword.\n");
1370                 } else {
1371                         /* type declaration, type definition, or function
1372                          * declaration */
1373                         struct cp_ctype type;
1374                         struct token name;
1375                         struct parser asmname;
1376
1377                         memset(&name, 0, sizeof(name));
1378                         memset(&asmname, 0, sizeof(asmname));
1379
1380                         put_back(P);
1381                         parse_type(P, &type);
1382
1383                         for (;;) {
1384                                 parse_argument(P, &type, &name, &asmname);
1385
1386                                 if (name.size) {
1387                                         /* global/function declaration */
1388                                         cp_symbol_build_func(&type, name.str, name.size);
1389                                         /* @TODO asmname is not used for now
1390                                          * since we are not supporting __asm__
1391                                          * as this point.
1392                                          * might need to bind it with function
1393                                          * name later. */
1394                                 } else {
1395                                         /* type declaration/definition -
1396                                          * already been processed */
1397                                 }
1398                                 require_token(P, &tok);
1399
1400                                 if (tok.type == TOK_SEMICOLON) {
1401                                         break;
1402                                 } else if (tok.type != TOK_COMMA) {
1403                                         cp_error("missing semicolon on line %d",
1404                                                         P->line);
1405                                 }
1406                         }
1407                 }
1408         }
1409
1410         return END;
1411 }
1412
1413 static int64_t calculate_constant2(struct parser *P, struct token *tok);
1414
1415 /* () */
1416 static int64_t calculate_constant1(struct parser *P, struct token *tok)
1417 {
1418         int64_t ret;
1419
1420         if (tok->type == TOK_NUMBER) {
1421                 ret = tok->integer;
1422                 next_token(P, tok);
1423                 return ret;
1424
1425         } else if (tok->type == TOK_TOKEN) {
1426                 /* look up name in constants table */
1427                 cp_error("TODO: support name lookup in constant table\n");
1428                 next_token(P, tok);
1429                 return ret;
1430
1431         } else if (tok->type == TOK_OPEN_PAREN) {
1432                 struct parser before_cast = *P;
1433                 cp_error("TODO: handle open parent token in constant1\n");
1434                 *P = before_cast;
1435                 ret = calculate_constant(P);
1436
1437                 require_token(P, tok);
1438                 if (tok->type != TOK_CLOSE_PAREN) {
1439                         cp_error("error whilst parsing constant at line %d",
1440                                         P->line);
1441                 }
1442
1443                 next_token(P, tok);
1444                 return ret;
1445         } else {
1446                 cp_error("unexpected token whilst parsing constant at line %d",
1447                                 P->line);
1448                 return 0;
1449         }
1450 }
1451
1452 /* ! and ~, unary + and -, and sizeof */
1453 static int64_t calculate_constant2(struct parser *P, struct token *tok)
1454 {
1455         if (tok->type == TOK_LOGICAL_NOT) {
1456                 require_token(P, tok);
1457                 return !calculate_constant2(P, tok);
1458
1459         } else if (tok->type == TOK_BITWISE_NOT) {
1460                 require_token(P, tok);
1461                 return ~calculate_constant2(P, tok);
1462
1463         } else if (tok->type == TOK_PLUS) {
1464                 require_token(P, tok);
1465                 return calculate_constant2(P, tok);
1466
1467         } else if (tok->type == TOK_MINUS) {
1468                 require_token(P, tok);
1469                 return -calculate_constant2(P, tok);
1470
1471         } else if (tok->type == TOK_TOKEN &&
1472                         (IS_LITERAL(*tok, "sizeof")
1473                          || IS_LITERAL(*tok, "alignof")
1474                          || IS_LITERAL(*tok, "__alignof__")
1475                          || IS_LITERAL(*tok, "__alignof"))) {
1476                 cp_error("TODO: support sizeof\n");
1477                 bool issize = IS_LITERAL(*tok, "sizeof");
1478                 struct cp_ctype type;
1479
1480                 require_token(P, tok);
1481                 if (tok->type != TOK_OPEN_PAREN) {
1482                         cp_error("invalid sizeof at line %d", P->line);
1483                 }
1484
1485                 parse_type(P, &type);
1486                 parse_argument(P, &type, NULL, NULL);
1487
1488                 require_token(P, tok);
1489                 if (tok->type != TOK_CLOSE_PAREN) {
1490                         cp_error("invalid sizeof at line %d", P->line);
1491                 }
1492
1493                 next_token(P, tok);
1494
1495                 return issize ? ctype_size(&type) : type.align_mask + 1;
1496
1497         } else {
1498                 return calculate_constant1(P, tok);
1499         }
1500 }
1501
1502 /* binary * / and % (left associative) */
1503 static int64_t calculate_constant3(struct parser *P, struct token *tok)
1504 {
1505         int64_t left = calculate_constant2(P, tok);
1506
1507         for (;;) {
1508                 if (tok->type == TOK_MULTIPLY) {
1509                         require_token(P, tok);
1510                         left *= calculate_constant2(P, tok);
1511
1512                 } else if (tok->type == TOK_DIVIDE) {
1513                         require_token(P, tok);
1514                         left /= calculate_constant2(P, tok);
1515
1516                 } else if (tok->type == TOK_MODULUS) {
1517                         require_token(P, tok);
1518                         left %= calculate_constant2(P, tok);
1519
1520                 } else {
1521                         return left;
1522                 }
1523         }
1524 }
1525
1526 /* binary + and - (left associative) */
1527 static int64_t calculate_constant4(struct parser *P, struct token *tok)
1528 {
1529         int64_t left = calculate_constant3(P, tok);
1530
1531         for (;;) {
1532                 if (tok->type == TOK_PLUS) {
1533                         require_token(P, tok);
1534                         left += calculate_constant3(P, tok);
1535
1536                 } else if (tok->type == TOK_MINUS) {
1537                         require_token(P, tok);
1538                         left -= calculate_constant3(P, tok);
1539
1540                 } else {
1541                         return left;
1542                 }
1543         }
1544 }
1545
1546 /* binary << and >> (left associative) */
1547 static int64_t calculate_constant5(struct parser *P, struct token *tok)
1548 {
1549         int64_t left = calculate_constant4(P, tok);
1550
1551         for (;;) {
1552                 if (tok->type == TOK_LEFT_SHIFT) {
1553                         require_token(P, tok);
1554                         left <<= calculate_constant4(P, tok);
1555
1556                 } else if (tok->type == TOK_RIGHT_SHIFT) {
1557                         require_token(P, tok);
1558                         left >>= calculate_constant4(P, tok);
1559
1560                 } else {
1561                         return left;
1562                 }
1563         }
1564 }
1565
1566 /* binary <, <=, >, and >= (left associative) */
1567 static int64_t calculate_constant6(struct parser *P, struct token *tok)
1568 {
1569         int64_t left = calculate_constant5(P, tok);
1570
1571         for (;;) {
1572                 if (tok->type == TOK_LESS) {
1573                         require_token(P, tok);
1574                         left = (left < calculate_constant5(P, tok));
1575
1576                 } else if (tok->type == TOK_LESS_EQUAL) {
1577                         require_token(P, tok);
1578                         left = (left <= calculate_constant5(P, tok));
1579
1580                 } else if (tok->type == TOK_GREATER) {
1581                         require_token(P, tok);
1582                         left = (left > calculate_constant5(P, tok));
1583
1584                 } else if (tok->type == TOK_GREATER_EQUAL) {
1585                         require_token(P, tok);
1586                         left = (left >= calculate_constant5(P, tok));
1587
1588                 } else {
1589                         return left;
1590                 }
1591         }
1592 }
1593
1594 /* binary ==, != (left associative) */
1595 static int64_t calculate_constant7(struct parser *P, struct token *tok)
1596 {
1597         int64_t left = calculate_constant6(P, tok);
1598
1599         for (;;) {
1600                 if (tok->type == TOK_EQUAL) {
1601                         require_token(P, tok);
1602                         left = (left == calculate_constant6(P, tok));
1603
1604                 } else if (tok->type == TOK_NOT_EQUAL) {
1605                         require_token(P, tok);
1606                         left = (left != calculate_constant6(P, tok));
1607
1608                 } else {
1609                         return left;
1610                 }
1611         }
1612 }
1613
1614 /* binary & (left associative) */
1615 static int64_t calculate_constant8(struct parser *P, struct token *tok)
1616 {
1617         int64_t left = calculate_constant7(P, tok);
1618
1619         for (;;) {
1620                 if (tok->type == TOK_BITWISE_AND) {
1621                         require_token(P, tok);
1622                         left = (left & calculate_constant7(P, tok));
1623
1624                 } else {
1625                         return left;
1626                 }
1627         }
1628 }
1629
1630 /* binary ^ (left associative) */
1631 static int64_t calculate_constant9(struct parser *P, struct token *tok)
1632 {
1633         int64_t left = calculate_constant8(P, tok);
1634
1635         for (;;) {
1636                 if (tok->type == TOK_BITWISE_XOR) {
1637                         require_token(P, tok);
1638                         left = (left ^ calculate_constant8(P, tok));
1639
1640                 } else {
1641                         return left;
1642                 }
1643         }
1644 }
1645
1646 /* binary | (left associative) */
1647 static int64_t calculate_constant10(struct parser *P, struct token *tok)
1648 {
1649         int64_t left = calculate_constant9(P, tok);
1650
1651         for (;;) {
1652                 if (tok->type == TOK_BITWISE_OR) {
1653                         require_token(P, tok);
1654                         left = (left | calculate_constant9(P, tok));
1655
1656                 } else {
1657                         return left;
1658                 }
1659         }
1660 }
1661
1662 /* binary && (left associative) */
1663 static int64_t calculate_constant11(struct parser *P, struct token *tok)
1664 {
1665         int64_t left = calculate_constant10(P, tok);
1666
1667         for (;;) {
1668                 if (tok->type == TOK_LOGICAL_AND) {
1669                         require_token(P, tok);
1670                         left = (left && calculate_constant10(P, tok));
1671
1672                 } else {
1673                         return left;
1674                 }
1675         }
1676 }
1677
1678 /* binary || (left associative) */
1679 static int64_t calculate_constant12(struct parser *P, struct token *tok)
1680 {
1681         int64_t left = calculate_constant11(P, tok);
1682
1683         for (;;) {
1684                 if (tok->type == TOK_LOGICAL_OR) {
1685                         require_token(P, tok);
1686                         left = (left || calculate_constant11(P, tok));
1687
1688                 } else {
1689                         return left;
1690                 }
1691         }
1692 }
1693
1694 /* ternary ?: (right associative) */
1695 static int64_t calculate_constant13(struct parser *P, struct token *tok)
1696 {
1697         int64_t left = calculate_constant12(P, tok);
1698
1699         if (tok->type == TOK_QUESTION) {
1700                 int64_t middle, right;
1701                 require_token(P, tok);
1702                 middle = calculate_constant13(P, tok);
1703                 if (tok->type != TOK_COLON) {
1704                         cp_error("invalid ternery (? :) in constant on line %d",
1705                                         P->line);
1706                 }
1707                 require_token(P, tok);
1708                 right = calculate_constant13(P, tok);
1709                 return left ? middle : right;
1710
1711         } else {
1712                 return left;
1713         }
1714 }
1715
1716 int64_t calculate_constant(struct parser* P)
1717 {
1718         struct token tok;
1719         int64_t ret;
1720         require_token(P, &tok);
1721         ret = calculate_constant13(P, &tok);
1722
1723         if (tok.type != TOK_NIL) {
1724                 put_back(P);
1725         }
1726
1727         return ret;
1728 }
1729
1730 int ffi_cdef(const char *s)
1731 {
1732         struct parser P;
1733
1734         memset(&P, 0, sizeof(struct parser));
1735         P.line = 1;
1736         P.prev = P.next = s;
1737         P.align_mask = DEFAULT_ALIGN_MASK;
1738
1739         if (parse_root(&P) == PRAGMA_POP) {
1740                 cp_error("pragma pop without an associated push on line %d",
1741                                 P.line);
1742         }
1743
1744         return 0;
1745 }
1746
1747 void ffi_cparser_init(void)
1748 {
1749         cp_ctype_init();
1750 }
1751
1752 void ffi_cparser_free(void)
1753 {
1754         cp_ctype_free();
1755 }