userspace/ffi/cparser.c - ktap

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. #include <stdarg.h>
  2. #include "../cparser.h"

  3. #define IS_CONST(tok) (IS_LITERAL(tok, "const") || IS_LITERAL(tok, "__const") \
  4.             || IS_LITERAL(tok, "__const__"))
  5. #define IS_VOLATILE(tok) (IS_LITERAL(tok, "volatile") || \
  6.                 IS_LITERAL(tok, "__volatile") || \
  7.                 IS_LITERAL(tok, "__volatile__"))
  8. #define IS_RESTRICT(tok) (IS_LITERAL(tok, "restrict") || \
  9.                 IS_LITERAL(tok, "__restrict") || \
  10.                 IS_LITERAL(tok, "__restrict__"))

  11. #define max(a,b) ((a) < (b) ? (b) : (a))
  12. #define min(a,b) ((a) < (b) ? (a) : (b))


  13. enum etoken {
  14.     /* 0 - 3 */
  15.     TOK_NIL,
  16.     TOK_NUMBER,
  17.     TOK_STRING,
  18.     TOK_TOKEN,

  19.     /* the order of these values must match the token strings in lex.c */

  20.     /* 4 - 5 */
  21.     TOK_3_BEGIN,
  22.     TOK_VA_ARG,

  23.     /* 6 - 14 */
  24.     TOK_2_BEGIN,
  25.     TOK_LEFT_SHIFT, TOK_RIGHT_SHIFT, TOK_LOGICAL_AND, TOK_LOGICAL_OR,
  26.     TOK_LESS_EQUAL, TOK_GREATER_EQUAL, TOK_EQUAL, TOK_NOT_EQUAL,

  27.     /* 15 - 20 */
  28.     TOK_1_BEGIN,
  29.     TOK_OPEN_CURLY, TOK_CLOSE_CURLY, TOK_SEMICOLON, TOK_COMMA, TOK_COLON,
  30.     /* 21 - 30 */
  31.     TOK_ASSIGN, TOK_OPEN_PAREN, TOK_CLOSE_PAREN, TOK_OPEN_SQUARE, TOK_CLOSE_SQUARE,
  32.     TOK_DOT, TOK_AMPERSAND, TOK_LOGICAL_NOT, TOK_BITWISE_NOT, TOK_MINUS,
  33.     /* 31 - 40 */
  34.     TOK_PLUS, TOK_STAR, TOK_DIVIDE, TOK_MODULUS, TOK_LESS,
  35.     TOK_GREATER, TOK_BITWISE_XOR, TOK_BITWISE_OR, TOK_QUESTION, TOK_POUND,

  36.     /* 41 - 43 */
  37.     TOK_REFERENCE = TOK_AMPERSAND,
  38.     TOK_MULTIPLY = TOK_STAR,
  39.     TOK_BITWISE_AND = TOK_AMPERSAND,
  40. };

  41. struct token {
  42.     enum etoken type;
  43.     int64_t integer;
  44.     const char *str;
  45.     size_t size;
  46. };

  47. #define IS_LITERAL(TOK, STR) \
  48.     (((TOK).size == sizeof(STR) - 1) && \
  49.         0 == memcmp((TOK).str, STR, sizeof(STR) - 1))


  50. static int parse_type_name(struct parser *P, char *type_name);
  51. static void parse_argument(struct parser *P, struct cp_ctype *ct,
  52.         struct token *pname, struct parser *asmname);
  53. static int parse_attribute(struct parser *P, struct token *tok,
  54.         struct cp_ctype *ct, struct parser *asmname);
  55. static int parse_record(struct parser *P, struct cp_ctype *ct);
  56. static void instantiate_typedef(struct parser *P, struct cp_ctype *tt,
  57.         const struct cp_ctype *ft);


  58. /* the order of tokens _must_ match the order of the enum etoken enum */

  59. static char tok3[][4] = {
  60.     "...", /* unused ">>=", "<<=", */
  61. };

  62. static char tok2[][3] = {
  63.     "<<", ">>", "&&", "||", "<=",
  64.     ">=", "==", "!=",
  65.     /* unused "+=", "-=", "*=", "/=", "%=", "&=", "^=",
  66.      * "|=", "++", "--", "->", "::", */
  67. };

  68. static char tok1[] = {
  69.     '{', '}', ';', ',', ':',
  70.     '=', '(', ')', '[', ']',
  71.     '.', '&', '!', '~', '-',
  72.     '+', '*', '/', '%', '<',
  73.     '>', '^', '|', '?', '#'
  74. };


  75. /* this function never returns, but it's an idiom to use it in C functions
  76. * as return cp_error */
  77. void cp_error(const char *err_msg_fmt, ...)
  78. {
  79.     va_list ap;

  80.     fprintf(stderr, "cparser error:\n");

  81.     va_start(ap, err_msg_fmt);
  82.     vfprintf(stderr, err_msg_fmt, ap);
  83.     va_end(ap);

  84.     exit(EXIT_FAILURE);
  85. }

  86. static int set_type_name(char *dst, unsigned type, const char *src, int len)
  87. {
  88.     int prefix_len;
  89.     char *prefix = NULL;

  90.     if (type == STRUCT_TYPE)
  91.         prefix = "struct ";
  92.     else if (type == UNION_TYPE)
  93.         prefix = "union ";
  94.     else
  95.         cp_error("Only set type name for struct or union\n");
  96.     prefix_len = sizeof(prefix);

  97.     if (len + prefix_len > MAX_TYPE_NAME_LEN)
  98.         return -1;

  99.     memset(dst, 0, MAX_TYPE_NAME_LEN);
  100.     strcpy(dst, prefix);
  101.     strncat(dst, src, len);

  102.     return 0;
  103. }

  104. static void increase_ptr_deref_level(struct parser *P, struct cp_ctype *ct)
  105. {
  106.     if (ct->pointers == POINTER_MAX) {
  107.         cp_error("maximum number of pointer derefs reached - use a "
  108.             "struct to break up the pointers on line %d", P->line);
  109.     } else {
  110.         ct->pointers++;
  111.         ct->const_mask <<= 1;
  112.     }
  113. }

  114. static int next_token(struct parser *P, struct token *tok)
  115. {
  116.     size_t i;
  117.     const char *s = P->next;

  118.     /* UTF8 BOM */
  119.     if (s[0] == '\xEF' && s[1] == '\xBB' && s[2] == '\xBF') {
  120.         s += 3;
  121.     }

  122.     /* consume whitespace and comments */
  123.     for (;;) {
  124.         /* consume whitespace */
  125.         while (*s == '\t' || *s == '\n' || *s == ' '
  126.                 || *s == '\v' || *s == '\r') {
  127.             if (*s == '\n') {
  128.                 P->line++;
  129.             }
  130.             s++;
  131.         }

  132.         /* consume comments */
  133.         if (*s == '/' && *(s+1) == '/') {

  134.             s = strchr(s, '\n');
  135.             if (!s) {
  136.                 cp_error("non-terminated comment");
  137.             }

  138.         } else if (*s == '/' && *(s+1) == '*') {
  139.             s += 2;

  140.             for (;;) {
  141.                 if (s[0] == '\0') {
  142.                     cp_error("non-terminated comment");
  143.                 } else if (s[0] == '*' && s[1] == '/') {
  144.                     s += 2;
  145.                     break;
  146.                 } else if (s[0] == '\n') {
  147.                     P->line++;
  148.                 }
  149.                 s++;
  150.             }

  151.         } else if (*s == '\0') {
  152.             tok->type = TOK_NIL;
  153.             return 0;

  154.         } else {
  155.             break;
  156.         }
  157.     }

  158.     P->prev = s;

  159.     for (i = 0; i < sizeof(tok3) / sizeof(tok3[0]); i++) {
  160.         if (s[0] == tok3[i][0] && s[1] == tok3[i][1] && s[2] == tok3[i][2]) {
  161.             tok->type = (enum etoken) (TOK_3_BEGIN + 1 + i);
  162.             P->next = s + 3;
  163.             goto end;
  164.         }
  165.     }

  166.     for (i = 0; i < sizeof(tok2) / sizeof(tok2[0]); i++) {
  167.         if (s[0] == tok2[i][0] && s[1] == tok2[i][1]) {
  168.             tok->type = (enum etoken) (TOK_2_BEGIN + 1 + i);
  169.             P->next = s + 2;
  170.             goto end;
  171.         }
  172.     }

  173.     for (i = 0; i < sizeof(tok1) / sizeof(tok1[0]); i++) {
  174.         if (s[0] == tok1[i]) {
  175.             tok->type = (enum etoken) (TOK_1_BEGIN + 1 + i);
  176.             P->next = s + 1;
  177.             goto end;
  178.         }
  179.     }

  180.     if (*s == '.' || *s == '-' || ('0' <= *s && *s <= '9')) {
  181.         /* number */
  182.         tok->type = TOK_NUMBER;

  183.         /* split out the negative case so we get the full range of
  184.          * bits for unsigned (eg to support 0xFFFFFFFF where
  185.          * sizeof(long) == 4 */
  186.         if (*s == '-') {
  187.             tok->integer = strtol(s, (char**) &s, 0);
  188.         } else {
  189.             tok->integer = strtoul(s, (char**) &s, 0);
  190.         }

  191.         while (*s == 'u' || *s == 'U' || *s == 'l' || *s == 'L') {
  192.             s++;
  193.         }

  194.         P->next = s;
  195.         goto end;

  196.     } else if (*s == '\'' || *s == '\"') {
  197.         /* "..." or '...' */
  198.         char quote = *s;
  199.         s++; /* jump over " */

  200.         tok->type = TOK_STRING;
  201.         tok->str = s;

  202.         while (*s != quote) {
  203.             if (*s == '\0' || (*s == '\\' && *(s+1) == '\0')) {
  204.                 cp_error("string not finished\n");
  205.             }
  206.             if (*s == '\\') {
  207.                 s++;
  208.             }
  209.             s++;
  210.         }

  211.         tok->size = s - tok->str;
  212.         s++; /* jump over " */
  213.         P->next = s;
  214.         goto end;

  215.     } else if (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z')
  216.             || *s == '_') {
  217.         /* tokens */
  218.         tok->type = TOK_TOKEN;
  219.         tok->str = s;

  220.         while (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z')
  221.                 || *s == '_' || ('0' <= *s && *s <= '9')) {
  222.             s++;
  223.         }

  224.         tok->size = s - tok->str;
  225.         P->next = s;
  226.         goto end;
  227.     } else {
  228.         cp_error("invalid character %d", P->line);
  229.     }

  230. end:
  231.     return 1;
  232. }

  233. static void require_token(struct parser *P, struct token *tok)
  234. {
  235.     if (!next_token(P, tok)) {
  236.         cp_error("unexpected end");
  237.     }
  238. }

  239. static void check_token(struct parser *P, int type, const char *str,
  240.                 const char *err, ...)
  241. {
  242.     va_list ap;
  243.     struct token tok;
  244.     if (!next_token(P, &tok) || tok.type != type
  245.             || (tok.type == TOK_TOKEN && (tok.size != strlen(str)
  246.                 || memcmp(tok.str, str, tok.size) != 0))) {

  247.         va_start(ap, err);
  248.         vfprintf(stderr, err, ap);
  249.         va_end(ap);

  250.         exit(EXIT_FAILURE);
  251.     }
  252. }

  253. static void put_back(struct parser *P) {
  254.     P->next = P->prev;
  255. }

  256. int64_t calculate_constant(struct parser *P);

  257. /* parses out the base type of a type expression in a function declaration,
  258. * struct definition, typedef etc
  259. *
  260. * leaves the usr value of the type on the stack
  261. */
  262. int parse_type(struct parser *P, struct cp_ctype *ct)
  263. {
  264.     struct token tok;

  265.     memset(ct, 0, sizeof(*ct));

  266.     require_token(P, &tok);

  267.     /* get function attributes before the return type */
  268.     while (parse_attribute(P, &tok, ct, NULL)) {
  269.         require_token(P, &tok);
  270.     }

  271.     /* get const/volatile before the base type */
  272.     for (;;) {
  273.         if (tok.type != TOK_TOKEN) {
  274.             cp_error("unexpected value before type name on line %d",
  275.                     P->line);
  276.             return 0;
  277.         } else if (IS_CONST(tok)) {
  278.             ct->const_mask = 1;
  279.             require_token(P, &tok);
  280.         } else if (IS_VOLATILE(tok) || IS_RESTRICT(tok)) {
  281.             /* ignored for now */
  282.             require_token(P, &tok);
  283.         } else {
  284.             break;
  285.         }
  286.     }

  287.     /* get base type */
  288.     if (tok.type != TOK_TOKEN) {
  289.         cp_error("unexpected value before type name on line %d", P->line);
  290.         return 0;
  291.     } else if (IS_LITERAL(tok, "struct")) {
  292.         ct->type = STRUCT_TYPE;
  293.         parse_record(P, ct);
  294.     } else if (IS_LITERAL(tok, "union")) {
  295.         ct->type = UNION_TYPE;
  296.         parse_record(P, ct);
  297.     } else if (IS_LITERAL(tok, "enum")) {
  298.         ct->type = ENUM_TYPE;
  299.         parse_record(P, ct);
  300.     } else {
  301.         put_back(P);

  302.         /* lookup type */
  303.         struct cp_ctype *lct;
  304.         char cur_type_name[MAX_TYPE_NAME_LEN];

  305.         memset(cur_type_name, 0, MAX_TYPE_NAME_LEN);
  306.         parse_type_name(P, cur_type_name);
  307.         lct = ctype_lookup_type(cur_type_name);
  308.         if (!lct)
  309.             cp_error("unknow type: \"%s\"\n", cur_type_name);

  310.         instantiate_typedef(P, ct, lct);
  311.     }

  312.     while (next_token(P, &tok)) {
  313.         if (tok.type != TOK_TOKEN) {
  314.             put_back(P);
  315.             break;
  316.         } else if (IS_CONST(tok) || IS_VOLATILE(tok)) {
  317.             /* ignore for now */
  318.         } else {
  319.             put_back(P);
  320.             break;
  321.         }
  322.     }

  323.     return 0;
  324. }

  325. enum test {TEST};

  326. /* Parses an enum definition from after the open curly through to the close
  327. * curly. Expects the user table to be on the top of the stack
  328. */
  329. static int parse_enum(struct parser *P, struct cp_ctype *type)
  330. {
  331.     struct token tok;
  332.     int value = -1;

  333.     /*@TODO clean up this function when enum support is added*/
  334.     cp_error("TODO: enum not supported!\n");

  335.     for (;;) {
  336.         require_token(P, &tok);

  337.         if (tok.type == TOK_CLOSE_CURLY) {
  338.             break;
  339.         } else if (tok.type != TOK_TOKEN) {
  340.             cp_error("unexpected token in enum at line %d", P->line);
  341.             return 0;
  342.         }
  343.         require_token(P, &tok);

  344.         if (tok.type == TOK_COMMA || tok.type == TOK_CLOSE_CURLY) {
  345.             /* we have an auto calculated enum value */
  346.             value++;
  347.         } else if (tok.type == TOK_ASSIGN) {
  348.             /* we have an explicit enum value */
  349.             value = (int) calculate_constant(P);
  350.             require_token(P, &tok);
  351.         } else {
  352.             cp_error("unexpected token in enum at line %d", P->line);
  353.             return 0;
  354.         }

  355.         if (tok.type == TOK_CLOSE_CURLY) {
  356.             break;
  357.         } else if (tok.type != TOK_COMMA) {
  358.             cp_error("unexpected token in enum at line %d", P->line);
  359.             return 0;
  360.         }
  361.     }

  362.     type->base_size = sizeof(enum test);
  363.     type->align_mask = sizeof(enum test) - 1;

  364.     return 0;
  365. }

  366. /* Parses a struct from after the open curly through to the close curly. */
  367. static int parse_struct(struct parser *P, const struct cp_ctype *ct)
  368. {
  369.     struct token tok;

  370.     /* parse members */
  371.     for (;;) {
  372.         struct cp_ctype mbase;

  373.         /* see if we're at the end of the struct */
  374.         require_token(P, &tok);
  375.         if (tok.type == TOK_CLOSE_CURLY) {
  376.             break;
  377.         } else if (ct->is_variable_struct) {
  378.             cp_error("can't have members after a variable sized "
  379.                     "member on line %d", P->line);
  380.             return -1;
  381.         } else {
  382.             put_back(P);
  383.         }

  384.         /* members are of the form
  385.          * <base type> <arg>, <arg>, <arg>;
  386.          * eg struct foo bar, *bar2[2];
  387.          * mbase is 'struct foo'
  388.          * mtype is '' then '*[2]'
  389.          * mname is 'bar' then 'bar2'
  390.          */

  391.         parse_type(P, &mbase);

  392.         for (;;) {
  393.             struct token mname;
  394.             struct cp_ctype mt = mbase;

  395.             memset(&mname, 0, sizeof(mname));

  396.             if (ct->is_variable_struct) {
  397.                 cp_error("can't have members after a variable "
  398.                     "sized member on line %d", P->line);
  399.                 return -1;
  400.             }

  401.             parse_argument(P, &mt, &mname, NULL);

  402.             if (!mt.is_defined && (mt.pointers - mt.is_array) == 0) {
  403.                 cp_error("member type is undefined on line %d",
  404.                         P->line);
  405.                 return -1;
  406.             }

  407.             if (mt.type == VOID_TYPE
  408.                     && (mt.pointers - mt.is_array) == 0) {
  409.                 cp_error("member type can not be void on line %d",
  410.                         P->line);
  411.                 return -1;
  412.             }

  413.             mt.has_member_name = (mname.size > 0);
  414.             if (mt.has_member_name) {
  415.                 cp_push_ctype_with_name(&mt,
  416.                         mname.str, mname.size);
  417.             } else {
  418.                 cp_push_ctype(&mt);
  419.             }

  420.             require_token(P, &tok);
  421.             if (tok.type == TOK_SEMICOLON) {
  422.                 break;
  423.             } else if (tok.type != TOK_COMMA) {
  424.                 cp_error("unexpected token in struct "
  425.                     "definition on line %d", P->line);
  426.             }
  427.         }
  428.     }

  429.     return 0;
  430. }

  431. /* copy over attributes that could be specified before the typedef eg
  432. * __attribute__(packed) const type_t */
  433. static void instantiate_typedef(struct parser *P, struct cp_ctype *tt,
  434.         const struct cp_ctype *ft)
  435. {
  436.     struct cp_ctype pt = *tt;
  437.     *tt = *ft;

  438.     tt->const_mask |= pt.const_mask;
  439.     tt->is_packed = pt.is_packed;

  440.     if (tt->is_packed) {
  441.         tt->align_mask = 0;
  442.     } else {
  443.         /* Instantiate the typedef in the current packing. This may be
  444.          * further updated if a pointer is added or another alignment
  445.          * attribute is applied. If pt.align_mask is already non-zero
  446.          * than an increased alignment via __declspec(aligned(#)) has
  447.          * been set. */
  448.         tt->align_mask = max(min(P->align_mask, tt->align_mask),
  449.                     pt.align_mask);
  450.     }
  451. }

  452. /* this parses a struct or union starting with the optional
  453. * name before the opening brace
  454. * leaves the type usr value on the stack */
  455. static int parse_record(struct parser *P, struct cp_ctype *ct)
  456. {
  457.     struct token tok;
  458.     char cur_type_name[MAX_TYPE_NAME_LEN];
  459.     int has_name;

  460.     require_token(P, &tok);

  461.     /* name is optional */
  462.     memset(cur_type_name, 0, MAX_TYPE_NAME_LEN);
  463.     if (tok.type == TOK_TOKEN) {
  464.         /* declaration */
  465.         struct cp_ctype *lct;

  466.         set_type_name(cur_type_name, ct->type, tok.str, tok.size);

  467.         /* lookup the name to see if we've seen this type before */
  468.         lct = ctype_lookup_type(cur_type_name);

  469.         if (!lct) {
  470.             /* new type, delay type registration to the end
  471.              * of this function */
  472.             ct->ffi_base_cs_id = ct->ffi_cs_id = -1;
  473.         } else {
  474.             /* get the exsting declared type */
  475.             if (lct->type != ct->type) {
  476.                 cp_error("type '%s' previously declared as '%s'",
  477.                     cur_type_name,
  478.                     csym_name(ct_ffi_cs(lct)));
  479.             }

  480.             instantiate_typedef(P, ct, lct);
  481.         }

  482.         /* if a name is given then we may be at the end of the string
  483.          * eg for ffi.new('struct foo') */
  484.         if (!next_token(P, &tok)) {
  485.             return 0;
  486.         }
  487.         has_name = 1;
  488.     } else {
  489.         char anon_name[MAX_TYPE_NAME_LEN];
  490.         /* create a new unnamed record */
  491.         sprintf(anon_name, "%d line", P->line);
  492.         set_type_name(cur_type_name, ct->type,
  493.                 anon_name, strlen(anon_name));
  494.         ct->ffi_base_cs_id = ct->ffi_cs_id = -1;
  495.         has_name = 0;
  496.     }

  497.     if (tok.type != TOK_OPEN_CURLY) {
  498.         /* this may just be a declaration or use of the type as an
  499.          * argument or member */
  500.         put_back(P);
  501.         if (!has_name)
  502.             cp_error("noname record type declaration\n");

  503.         /* build symbol for vm */
  504.         ct->ffi_base_cs_id =
  505.             cp_symbol_build_fake_record(cur_type_name, ct->type);
  506.         ct->ffi_cs_id = ct->ffi_base_cs_id;
  507.         return 0;
  508.     }

  509.     if (ct->is_defined) {
  510.         cp_error("redefinition in line %d", P->line);
  511.         return 0;
  512.     }

  513.     if (ct->type == ENUM_TYPE) {
  514.         parse_enum(P, ct);
  515.         cp_set_defined(ct);
  516.     } else {
  517.         int start_top = ctype_stack_top();
  518.         /* we do a two stage parse, where we parse the content first
  519.          * and build up the temp user table. We then iterate over that
  520.          * to calculate the offsets and fill out ct_usr. This is so we
  521.          * can handle out of order members (eg vtable) and attributes
  522.          * specified at the end of the struct. */
  523.         parse_struct(P, ct);
  524.         cp_set_defined(ct);
  525.         /* build symbol for vm */
  526.         ct->ffi_base_cs_id = cp_symbol_build_record(
  527.                 cur_type_name, ct->type, start_top);
  528.         ct->ffi_cs_id = ct->ffi_base_cs_id;
  529.         /* save cp_ctype for parser */
  530.         cp_ctype_reg_type(cur_type_name, ct);
  531.     }

  532.     return 0;
  533. }

  534. /* parses single or multi work built in types, and pushes it onto the stack */
  535. static int parse_type_name(struct parser *P, char *type_name)
  536. {
  537.     struct token tok;
  538.     int flags = 0;

  539.     enum {
  540.         UNSIGNED = 0x01,
  541.         SIGNED = 0x02,
  542.         LONG = 0x04,
  543.         SHORT = 0x08,
  544.         INT = 0x10,
  545.         CHAR = 0x20,
  546.         LONG_LONG = 0x40,
  547.         INT8 = 0x80,
  548.         INT16 = 0x100,
  549.         INT32 = 0x200,
  550.         INT64 = 0x400,
  551.     };

  552.     require_token(P, &tok);

  553.     /* we have to manually decode the builtin types since they can take up
  554.      * more then one token */
  555.     for (;;) {
  556.         if (tok.type != TOK_TOKEN) {
  557.             break;
  558.         } else if (IS_LITERAL(tok, "unsigned")) {
  559.             flags |= UNSIGNED;
  560.         } else if (IS_LITERAL(tok, "signed")) {
  561.             flags |= SIGNED;
  562.         } else if (IS_LITERAL(tok, "short")) {
  563.             flags |= SHORT;
  564.         } else if (IS_LITERAL(tok, "char")) {
  565.             flags |= CHAR;
  566.         } else if (IS_LITERAL(tok, "long")) {
  567.             flags |= (flags & LONG) ? LONG_LONG : LONG;
  568.         } else if (IS_LITERAL(tok, "int")) {
  569.             flags |= INT;
  570.         } else if (IS_LITERAL(tok, "__int8")) {
  571.             flags |= INT8;
  572.         } else if (IS_LITERAL(tok, "__int16")) {
  573.             flags |= INT16;
  574.         } else if (IS_LITERAL(tok, "__int32")) {
  575.             flags |= INT32;
  576.         } else if (IS_LITERAL(tok, "__int64")) {
  577.             flags |= INT64;
  578.         } else if (IS_LITERAL(tok, "register")) {
  579.             /* ignore */
  580.         } else {
  581.             break;
  582.         }

  583.         if (!next_token(P, &tok)) {
  584.             break;
  585.         }
  586.     }

  587.     if (flags) {
  588.         put_back(P);
  589.     }

  590.     if (flags & CHAR) {
  591.         if (flags & SIGNED) {
  592.             strcpy(type_name, "int8_t");
  593.         } else if (flags & UNSIGNED) {
  594.             strcpy(type_name, "uint8_t");
  595.         } else {
  596.             if (((char) -1) > 0) {
  597.                 strcpy(type_name, "uint8_t");
  598.             } else {
  599.                 strcpy(type_name, "int8_t");
  600.             }
  601.         }
  602.     } else if (flags & INT8) {
  603.         strcpy(type_name, (flags & UNSIGNED) ? "uint8_t" : "int8_t");
  604.     } else if (flags & INT16) {
  605.         strcpy(type_name, (flags & UNSIGNED) ? "uint16_t" : "int16_t");
  606.     } else if (flags & INT32) {
  607.         strcpy(type_name, (flags & UNSIGNED) ? "uint32_t" : "int32_t");
  608.     } else if (flags & INT64) {
  609.         strcpy(type_name, (flags & UNSIGNED) ? "uint64_t" : "int64_t");
  610.     } else if (flags & LONG_LONG) {
  611.         strcpy(type_name, (flags & UNSIGNED) ? "uint64_t" : "int64_t");
  612.     } else if (flags & SHORT) {
  613. #define SHORT_TYPE(u) (sizeof(short) == sizeof(int64_t) ? \
  614.         u "int64_t" : sizeof(short) == sizeof(int32_t) ? \
  615.         u "int32_t" : u "int16_t")
  616.         if (flags & UNSIGNED) {
  617.             strcpy(type_name, SHORT_TYPE("u"));
  618.         } else {
  619.             strcpy(type_name, SHORT_TYPE(""));
  620.         }
  621. #undef SHORT_TYPE
  622.     } else if (flags & LONG) {
  623. #define LONG_TYPE(u) (sizeof(long) == sizeof(int64_t) ? \
  624.         u "int64_t" : u "int32_t")
  625.         if (flags & UNSIGNED) {
  626.             strcpy(type_name, LONG_TYPE("u"));
  627.         } else {
  628.             strcpy(type_name, LONG_TYPE(""));
  629.         }
  630. #undef LONG_TYPE
  631.     } else if (flags) {
  632. #define INT_TYPE(u) (sizeof(int) == sizeof(int64_t) ? \
  633.         u "int64_t" : sizeof(int) == sizeof(int32_t) ? \
  634.         u "int32_t" : u "int16_t")
  635.         if (flags & UNSIGNED) {
  636.             strcpy(type_name, INT_TYPE("u"));
  637.         } else {
  638.             strcpy(type_name, INT_TYPE(""));
  639.         }
  640. #undef INT_TYPE
  641.     } else {
  642.         strncpy(type_name, tok.str, tok.size);
  643.     }

  644.     return 0;
  645. }

  646. /* parse_attribute parses a token to see if it is an attribute. It may then
  647. * parse some following tokens to decode the attribute setting the appropriate
  648. * fields in ct. It will return 1 if the token was used (and possibly some
  649. * more following it) or 0 if not. If the token was used, the next token must
  650. * be retrieved using next_token/require_token. */
  651. static int parse_attribute(struct parser *P, struct token *tok,
  652.         struct cp_ctype *ct, struct parser *asmname)
  653. {
  654.     if (tok->type != TOK_TOKEN) {
  655.         return 0;
  656.     } else if (asmname && (IS_LITERAL(*tok, "__asm__")
  657.                 || IS_LITERAL(*tok, "__asm"))) {
  658.         check_token(P, TOK_OPEN_PAREN, NULL,
  659.                 "unexpected token after __asm__ on line %d",
  660.                 P->line);
  661.         *asmname = *P;

  662.         require_token(P, tok);
  663.         while (tok->type == TOK_STRING) {
  664.             require_token(P, tok);
  665.         }

  666.         if (tok->type != TOK_CLOSE_PAREN) {
  667.             cp_error("unexpected token after __asm__ on line %d",
  668.                     P->line);
  669.         }
  670.         return 1;

  671.     } else if (IS_LITERAL(*tok, "__attribute__")
  672.             || IS_LITERAL(*tok, "__declspec")) {
  673.         int parens = 1;
  674.         check_token(P, TOK_OPEN_PAREN, NULL,
  675.                 "expected parenthesis after __attribute__ or "
  676.                 "__declspec on line %d", P->line);

  677.         for (;;) {
  678.             require_token(P, tok);
  679.             if (tok->type == TOK_OPEN_PAREN) {
  680.                 parens++;
  681.             } else if (tok->type == TOK_CLOSE_PAREN) {
  682.                 if (--parens == 0) {
  683.                     break;
  684.                 }

  685.             } else if (tok->type != TOK_TOKEN) {
  686.                 /* ignore unknown symbols within parentheses */

  687.             } else if (IS_LITERAL(*tok, "align") ||
  688.                     IS_LITERAL(*tok, "aligned") ||
  689.                     IS_LITERAL(*tok, "__aligned__")) {
  690.                 unsigned align = 0;
  691.                 require_token(P, tok);

  692.                 switch (tok->type) {
  693.                 case TOK_CLOSE_PAREN:
  694.                     align = ALIGNED_DEFAULT;
  695.                     put_back(P);
  696.                     break;

  697.                 case TOK_OPEN_PAREN:
  698.                     require_token(P, tok);

  699.                     if (tok->type != TOK_NUMBER) {
  700.                         cp_error("expected align(#) "
  701.                             "on line %d", P->line);
  702.                     }

  703.                     switch (tok->integer) {
  704.                     case 1: align = 0; break;
  705.                     case 2: align = 1; break;
  706.                     case 4: align = 3; break;
  707.                     case 8: align = 7; break;
  708.                     case 16: align = 15; break;
  709.                     default:
  710.                         cp_error("unsupported align "
  711.                             "size on line %d",
  712.                             P->line);
  713.                     }

  714.                     check_token(P, TOK_CLOSE_PAREN, NULL,
  715.                         "expected align(#) on line %d",
  716.                         P->line);
  717.                     break;

  718.                 default:
  719.                     cp_error("expected align(#) on line %d",
  720.                             P->line);
  721.                 }

  722.                 /* __attribute__(aligned(#)) is only supposed
  723.                  * to increase alignment */
  724.                 ct->align_mask = max(align, ct->align_mask);

  725.             } else if (IS_LITERAL(*tok, "packed")
  726.                     || IS_LITERAL(*tok, "__packed__")) {
  727.                 ct->align_mask = 0;
  728.                 ct->is_packed = 1;

  729.             } else if (IS_LITERAL(*tok, "mode")
  730.                     || IS_LITERAL(*tok, "__mode__")) {

  731.                 check_token(P, TOK_OPEN_PAREN, NULL,
  732.                     "expected mode(MODE) on line %d",
  733.                     P->line);

  734.                 require_token(P, tok);
  735.                 if (tok->type != TOK_TOKEN) {
  736.                     cp_error("expected mode(MODE) on line %d",
  737.                             P->line);
  738.                 }


  739.                 struct {char ch; uint16_t v;} a16;
  740.                 struct {char ch; uint32_t v;} a32;
  741.                 struct {char ch; uint64_t v;} a64;

  742.                 if (IS_LITERAL(*tok, "QI")
  743.                         || IS_LITERAL(*tok, "__QI__")
  744.                         || IS_LITERAL(*tok, "byte")
  745.                         || IS_LITERAL(*tok, "__byte__")
  746.                    ) {
  747.                     ct->type = INT8_TYPE;
  748.                     ct->base_size = sizeof(uint8_t);
  749.                     ct->align_mask = 0;

  750.                 } else if (IS_LITERAL(*tok, "HI")
  751.                         || IS_LITERAL(*tok, "__HI__")) {
  752.                     ct->type = INT16_TYPE;
  753.                     ct->base_size = sizeof(uint16_t);
  754.                     ct->align_mask = ALIGNOF(a16);

  755.                 } else if (IS_LITERAL(*tok, "SI")
  756.                         || IS_LITERAL(*tok, "__SI__")
  757. #if defined ARCH_X86 || defined ARCH_ARM
  758.                         || IS_LITERAL(*tok, "word")
  759.                         || IS_LITERAL(*tok, "__word__")
  760.                         || IS_LITERAL(*tok, "pointer")
  761.                         || IS_LITERAL(*tok, "__pointer__")
  762. #endif
  763.                       ) {
  764.                     ct->type = INT32_TYPE;
  765.                     ct->base_size = sizeof(uint32_t);
  766.                     ct->align_mask = ALIGNOF(a32);

  767.                 } else if (IS_LITERAL(*tok, "DI")
  768.                         || IS_LITERAL(*tok, "__DI__")
  769. #if defined ARCH_X64
  770.                         || IS_LITERAL(*tok, "word")
  771.                         || IS_LITERAL(*tok, "__word__")
  772.                         || IS_LITERAL(*tok, "pointer")
  773.                         || IS_LITERAL(*tok, "__pointer__")
  774. #endif
  775.                       ) {
  776.                     ct->type = INT64_TYPE;
  777.                     ct->base_size = sizeof(uint64_t);
  778.                     ct->align_mask = ALIGNOF(a64);

  779.                 } else {
  780.                     cp_error("unexpected mode on line %d",
  781.                             P->line);
  782.                 }

  783.                 check_token(P, TOK_CLOSE_PAREN, NULL,
  784.                     "expected mode(MODE) on line %d", P->line);

  785.             } else if (IS_LITERAL(*tok, "cdecl")
  786.                     || IS_LITERAL(*tok, "__cdecl__")) {
  787.                 ct->calling_convention = C_CALL;

  788.             } else if (IS_LITERAL(*tok, "fastcall")
  789.                     || IS_LITERAL(*tok, "__fastcall__")) {
  790.                 ct->calling_convention = FAST_CALL;

  791.             } else if (IS_LITERAL(*tok, "stdcall")
  792.                     || IS_LITERAL(*tok, "__stdcall__")) {
  793.                 ct->calling_convention = STD_CALL;
  794.             }
  795.             /* ignore unknown tokens within parentheses */
  796.         }
  797.         return 1;

  798.     } else if (IS_LITERAL(*tok, "__cdecl")) {
  799.         ct->calling_convention = C_CALL;
  800.         return 1;

  801.     } else if (IS_LITERAL(*tok, "__fastcall")) {
  802.         ct->calling_convention = FAST_CALL;
  803.         return 1;

  804.     } else if (IS_LITERAL(*tok, "__stdcall")) {
  805.         ct->calling_convention = STD_CALL;
  806.         return 1;

  807.     } else if (IS_LITERAL(*tok, "__extension__")
  808.             || IS_LITERAL(*tok, "extern")) {
  809.         /* ignore */
  810.         return 1;
  811.     } else {
  812.         return 0;
  813.     }
  814. }

  815. /* parses from after the opening paranthesis to after the closing parenthesis */
  816. static void parse_function_arguments(struct parser* P, struct cp_ctype* ct)
  817. {
  818.     struct token tok;
  819.     int args = 0;

  820.     for (;;) {
  821.         require_token(P, &tok);

  822.         if (tok.type == TOK_CLOSE_PAREN)
  823.             break;

  824.         if (args) {
  825.             if (tok.type != TOK_COMMA) {
  826.                 cp_error("unexpected token in function "
  827.                         "argument %d on line %d",
  828.                         args, P->line);
  829.             }
  830.             require_token(P, &tok);
  831.         }

  832.         if (tok.type == TOK_VA_ARG) {
  833.             ct->has_var_arg = true;
  834.             check_token(P, TOK_CLOSE_PAREN, "",
  835.                     "unexpected token after ... in "
  836.                     "function on line %d",
  837.                     P->line);
  838.             break;
  839.         } else if (tok.type == TOK_TOKEN) {
  840.             struct cp_ctype at;

  841.             put_back(P);
  842.             parse_type(P, &at);
  843.             parse_argument(P, &at, NULL, NULL);

  844.             /* array arguments are just treated as their
  845.              * base pointer type */
  846.             at.is_array = 0;

  847.             /* check for the c style int func(void) and error
  848.              * on other uses of arguments of type void */
  849.             if (at.type == VOID_TYPE && at.pointers == 0) {
  850.                 if (args) {
  851.                     cp_error("can't have argument of type "
  852.                             "void on line %d",
  853.                             P->line);
  854.                 }

  855.                 check_token(P, TOK_CLOSE_PAREN, "",
  856.                     "unexpected void in function on line %d",
  857.                     P->line);
  858.                 break;
  859.             }
  860.             cp_push_ctype(&at);
  861.             args++;
  862.         } else {
  863.             cp_error("unexpected token in function argument %d "
  864.                     "on line %d", args+1, P->line);
  865.         }
  866.     }
  867. }

  868. static int max_bitfield_size(int type)
  869. {
  870.     switch (type) {
  871.     case BOOL_TYPE:
  872.         return 1;
  873.     case INT8_TYPE:
  874.         return 8;
  875.     case INT16_TYPE:
  876.         return 16;
  877.     case INT32_TYPE:
  878.     case ENUM_TYPE:
  879.         return 32;
  880.     case INT64_TYPE:
  881.         return 64;
  882.     default:
  883.         return -1;
  884.     }
  885. }

  886. static struct cp_ctype *parse_argument2(struct parser *P, struct cp_ctype *ct,
  887.         struct token *name, struct parser *asmname);

  888. /* parses from after the first ( in a function declaration or function pointer
  889. * can be one of:
  890. * void foo(...) before ...
  891. * void (foo)(...) before foo
  892. * void (* <>)(...) before <> which is the inner type */
  893. static struct cp_ctype *parse_function(struct parser *P, struct cp_ctype *ct,
  894.                 struct token *name, struct parser *asmname)
  895. {
  896.     /* We have a function pointer or a function. The usr table will
  897.      * get replaced by the canonical one (if there is one) in
  898.      * find_canonical_usr after all the arguments and returns have
  899.      * been parsed. */
  900.     struct token tok;
  901.     struct cp_ctype *ret = ct;

  902.     cp_push_ctype(ct);

  903.     memset(ct, 0, sizeof(*ct));
  904.     ct->base_size = sizeof(void (*)());
  905.     ct->align_mask = min(FUNCTION_ALIGN_MASK, P->align_mask);
  906.     ct->type = FUNCTION_TYPE;
  907.     ct->is_defined = 1;

  908.     if (name->type == TOK_NIL) {
  909.         for (;;) {
  910.             require_token(P, &tok);

  911.             if (tok.type == TOK_STAR) {
  912.                 if (ct->type == FUNCTION_TYPE) {
  913.                     ct->type = FUNCTION_PTR_TYPE;
  914.                 } else {
  915.                     increase_ptr_deref_level(P, ct);
  916.                 }
  917.             } else if (parse_attribute(P, &tok, ct, asmname)) {
  918.                 /* parse_attribute sets the appropriate fields */
  919.             } else {
  920.                 /* call parse_argument to handle the inner
  921.                  * contents e.g. the <> in "void (* <>)
  922.                  * (...)". Note that the inner contents can
  923.                  * itself be a function, a function ptr,
  924.                  * array, etc (e.g. "void (*signal(int sig,
  925.                  * void (*func)(int)))(int)" ). */
  926.                 cp_error("TODO: inner function not supported for now.");
  927.                 put_back(P);
  928.                 ct = parse_argument2(P, ct, name, asmname);
  929.                 break;
  930.             }
  931.         }

  932.         check_token(P, TOK_CLOSE_PAREN, NULL,
  933.             "unexpected token in function on line %d", P->line);
  934.         check_token(P, TOK_OPEN_PAREN, NULL,
  935.             "unexpected token in function on line %d", P->line);
  936.     }

  937.     parse_function_arguments(P, ct);

  938.     /*@TODO support for inner function  24.11 2013 (houqp)*/
  939.     /* if we have an inner function then set the outer function ptr as its
  940.      * return type and return the inner function
  941.      * e.g. for void (* <signal(int, void (*)(int))> )(int) inner is
  942.      * surrounded by <>, return type is void (*)(int) */

  943.     return ret;
  944. }

  945. static struct cp_ctype *parse_argument2(struct parser *P, struct cp_ctype *ct,
  946.                 struct token *name, struct parser *asmname)
  947. {
  948.     struct token tok;

  949.     for (;;) {
  950.         if (!next_token(P, &tok)) {
  951.             /* we've reached the end of the string */
  952.             break;
  953.         } else if (tok.type == TOK_STAR) {
  954.             increase_ptr_deref_level(P, ct);

  955.             /* __declspec(align(#)) may come before the type in a
  956.              * member */
  957.             if (!ct->is_packed) {
  958.                 ct->align_mask = max(min(PTR_ALIGN_MASK, P->align_mask),
  959.                             ct->align_mask);
  960.             }
  961.         } else if (tok.type == TOK_REFERENCE) {
  962.             cp_error("NYI: c++ reference types");
  963.             return 0;
  964.         } else if (parse_attribute(P, &tok, ct, asmname)) {
  965.             /* parse attribute has filled out appropriate fields in type */

  966.         } else if (tok.type == TOK_OPEN_PAREN) {
  967.             ct = parse_function(P, ct, name, asmname);
  968.         } else if (tok.type == TOK_OPEN_SQUARE) {
  969.             /* array */
  970.             if (ct->pointers == POINTER_MAX) {
  971.                 cp_error("maximum number of pointer derefs "
  972.                     "reached - use a struct to break up "
  973.                     "the pointers");
  974.             }
  975.             ct->is_array = 1;
  976.             ct->pointers++;
  977.             ct->const_mask <<= 1;
  978.             require_token(P, &tok);

  979.             if (ct->pointers == 1 && !ct->is_defined) {
  980.                 cp_error("array of undefined type on line %d",
  981.                         P->line);
  982.             }

  983.             if (ct->is_variable_struct || ct->is_variable_array) {
  984.                 cp_error("can't have an array of a variably "
  985.                     "sized type on line %d", P->line);
  986.             }

  987.             if (tok.type == TOK_QUESTION) {
  988.                 ct->is_variable_array = 1;
  989.                 ct->variable_increment = (ct->pointers > 1) ?
  990.                         sizeof(void*) : ct->base_size;
  991.                 check_token(P, TOK_CLOSE_SQUARE, "",
  992.                     "invalid character in array on line %d",
  993.                     P->line);

  994.             } else if (tok.type == TOK_CLOSE_SQUARE) {
  995.                 ct->array_size = 0;

  996.             } else if (tok.type == TOK_TOKEN && IS_RESTRICT(tok)) {
  997.                 /* odd gcc extension foo[__restrict] for arguments */
  998.                 ct->array_size = 0;
  999.                 check_token(P, TOK_CLOSE_SQUARE, "",
  1000.                     "invalid character in array on line %d",
  1001.                     P->line);
  1002.             } else {
  1003.                 int64_t asize;
  1004.                 put_back(P);
  1005.                 asize = calculate_constant(P);
  1006.                 if (asize < 0) {
  1007.                     cp_error("array size can not be "
  1008.                         "negative on line %d", P->line);
  1009.                     return 0;
  1010.                 }
  1011.                 ct->array_size = (size_t) asize;
  1012.                 check_token(P, TOK_CLOSE_SQUARE, "",
  1013.                     "invalid character in array on line %d",
  1014.                     P->line);
  1015.             }

  1016.         } else if (tok.type == TOK_COLON) {
  1017.             int64_t bsize = calculate_constant(P);

  1018.             if (ct->pointers || bsize < 0
  1019.                     || bsize > max_bitfield_size(ct->type)) {
  1020.                 cp_error("invalid bitfield on line %d", P->line);
  1021.             }

  1022.             ct->is_bitfield = 1;
  1023.             ct->bit_size = (unsigned) bsize;

  1024.         } else if (tok.type != TOK_TOKEN) {
  1025.             /* we've reached the end of the declaration */
  1026.             put_back(P);
  1027.             break;

  1028.         } else if (IS_CONST(tok)) {
  1029.             ct->const_mask |= 1;

  1030.         } else if (IS_VOLATILE(tok) || IS_RESTRICT(tok)) {
  1031.             /* ignored for now */

  1032.         } else {
  1033.             *name = tok;
  1034.         }
  1035.     }

  1036.     return ct;
  1037. }



  1038. /* parses after the main base type of a typedef, function argument or
  1039. * struct/union member
  1040. * eg for const void* bar[3] the base type is void with the subtype so far of
  1041. * const, this parses the "* bar[3]" and updates the type argument
  1042. *
  1043. * type must be as filled out by parse_type
  1044. *
  1045. * pushes the updated user value on the top of the stack
  1046. */
  1047. void parse_argument(struct parser *P, struct cp_ctype *ct, struct token *pname,
  1048.             struct parser *asmname)
  1049. {
  1050.     struct token tok, name;

  1051.     memset(&name, 0, sizeof(name));
  1052.     parse_argument2(P, ct, &name, asmname);

  1053.     for (;;) {
  1054.         if (!next_token(P, &tok)) {
  1055.             break;
  1056.         } else if (parse_attribute(P, &tok, ct, asmname)) {
  1057.             /* parse_attribute sets the appropriate fields */
  1058.         } else {
  1059.             put_back(P);
  1060.             break;
  1061.         }
  1062.     }

  1063.     if (pname) {
  1064.         *pname = name;
  1065.     }
  1066. }

  1067. static void parse_typedef(struct parser *P)
  1068. {
  1069.     struct token tok;
  1070.     struct cp_ctype base_type;
  1071.     char typedef_name[MAX_TYPE_NAME_LEN];

  1072.     parse_type(P, &base_type);

  1073.     for (;;) {
  1074.         struct cp_ctype arg_type = base_type;
  1075.         struct token name;

  1076.         memset(&name, 0, sizeof(name));

  1077.         parse_argument(P, &arg_type, &name, NULL);

  1078.         if (!name.size) {
  1079.             cp_error("Can't have a typedef without a name on line %d",
  1080.                     P->line);
  1081.         } else if (arg_type.is_variable_array) {
  1082.             cp_error("Can't typedef a variable length array on line %d",
  1083.                     P->line);
  1084.         }

  1085.         memset(typedef_name, 0, sizeof(typedef_name));
  1086.         strncpy(typedef_name, name.str, name.size);
  1087.         /* link typedef name with ctype for parser */
  1088.         cp_ctype_reg_type(typedef_name, &arg_type);

  1089.         require_token(P, &tok);

  1090.         if (tok.type == TOK_SEMICOLON) {
  1091.             break;
  1092.         } else if (tok.type != TOK_COMMA) {
  1093.             cp_error("Unexpected character in typedef on line %d",
  1094.                     P->line);
  1095.         }
  1096.     }
  1097. }

  1098. #define END 0
  1099. #define PRAGMA_POP 1

  1100. static int parse_root(struct parser *P)
  1101. {
  1102.     struct token tok;

  1103.     while (next_token(P, &tok)) {
  1104.         /* we can have:
  1105.          * struct definition
  1106.          * enum definition
  1107.          * union definition
  1108.          * struct/enum/union declaration
  1109.          * typedef
  1110.          * function declaration
  1111.          * pragma pack
  1112.          */

  1113.         if (tok.type == TOK_SEMICOLON) {
  1114.             /* empty semicolon in root continue on */

  1115.         } else if (tok.type == TOK_POUND) {

  1116.             check_token(P, TOK_TOKEN, "pragma",
  1117.                 "unexpected pre processor directive on line %d",
  1118.                 P->line);
  1119.             check_token(P, TOK_TOKEN, "pack",
  1120.                 "unexpected pre processor directive on line %d",
  1121.                 P->line);
  1122.             check_token(P, TOK_OPEN_PAREN, "",
  1123.                 "invalid pack directive on line %d",
  1124.                 P->line);
  1125.             require_token(P, &tok);

  1126.             if (tok.type == TOK_NUMBER) {
  1127.                 if (tok.integer != 1 && tok.integer != 2
  1128.                         && tok.integer != 4
  1129.                         && tok.integer != 8
  1130.                         && tok.integer != 16) {
  1131.                     cp_error("pack directive with invalid "
  1132.                             "pack size on line %d",
  1133.                             P->line);
  1134.                     return 0;
  1135.                 }

  1136.                 P->align_mask = (unsigned) (tok.integer - 1);
  1137.                 check_token(P, TOK_CLOSE_PAREN, "",
  1138.                     "invalid pack directive on line %d",
  1139.                     P->line);
  1140.             } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "push")) {
  1141.                 /*int line = P->line;*/
  1142.                 unsigned previous_alignment = P->align_mask;

  1143.                 check_token(P, TOK_CLOSE_PAREN, "",
  1144.                     "invalid pack directive on line %d",
  1145.                     P->line);

  1146.                 if (parse_root(P) != PRAGMA_POP) {
  1147.                     cp_error("reached end of string "
  1148.                         "without a pragma pop to "
  1149.                         "match the push on line %d",
  1150.                         P->line);
  1151.                     return 0;
  1152.                 }

  1153.                 P->align_mask = previous_alignment;

  1154.             } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "pop")) {
  1155.                 check_token(P, TOK_CLOSE_PAREN, "",
  1156.                     "invalid pack directive on line %d",
  1157.                         P->line);
  1158.                 return PRAGMA_POP;
  1159.             } else {
  1160.                 cp_error("invalid pack directive on line %d",
  1161.                         P->line);
  1162.                 return 0;
  1163.             }
  1164.         } else if (tok.type != TOK_TOKEN) {
  1165.             cp_error("unexpected character on line %d", P->line);
  1166.             return 0;
  1167.         } else if (IS_LITERAL(tok, "__extension__")) {
  1168.             /* ignore */
  1169.             continue;
  1170.         } else if (IS_LITERAL(tok, "extern")) {
  1171.             /* ignore extern as data and functions can only be
  1172.              * extern */
  1173.             continue;
  1174.         } else if (IS_LITERAL(tok, "typedef")) {
  1175.             parse_typedef(P);
  1176.         } else if (IS_LITERAL(tok, "static")) {
  1177.             /*@TODO we haven't tested static so far */
  1178.             cp_error("TODO: support static keyword.\n");
  1179.         } else {
  1180.             /* type declaration, type definition, or function
  1181.              * declaration */
  1182.             struct cp_ctype type;
  1183.             struct token name;
  1184.             struct parser asmname;

  1185.             memset(&name, 0, sizeof(name));
  1186.             memset(&asmname, 0, sizeof(asmname));

  1187.             put_back(P);
  1188.             parse_type(P, &type);

  1189.             for (;;) {
  1190.                 parse_argument(P, &type, &name, &asmname);

  1191.                 if (name.size) {
  1192.                     /* global/function declaration */
  1193.                     cp_symbol_build_func(&type, name.str, name.size);
  1194.                     /* @TODO asmname is not used for now
  1195.                      * since we are not supporting __asm__
  1196.                      * as this point.
  1197.                      * might need to bind it with function
  1198.                      * name later. */
  1199.                 } else {
  1200.                     /* type declaration/definition -
  1201.                      * already been processed */
  1202.                 }
  1203.                 require_token(P, &tok);

  1204.                 if (tok.type == TOK_SEMICOLON) {
  1205.                     break;
  1206.                 } else if (tok.type != TOK_COMMA) {
  1207.                     cp_error("missing semicolon on line %d",
  1208.                             P->line);
  1209.                 }
  1210.             }
  1211.         }
  1212.     }

  1213.     return END;
  1214. }

  1215. static int64_t calculate_constant2(struct parser *P, struct token *tok);

  1216. /* () */
  1217. static int64_t calculate_constant1(struct parser *P, struct token *tok)
  1218. {
  1219.     int64_t ret;

  1220.     if (tok->type == TOK_NUMBER) {
  1221.         ret = tok->integer;
  1222.         next_token(P, tok);
  1223.         return ret;

  1224.     } else if (tok->type == TOK_TOKEN) {
  1225.         /* look up name in constants table */
  1226.         cp_error("TODO: support name lookup in constant table\n");
  1227.         next_token(P, tok);
  1228.         return ret;

  1229.     } else if (tok->type == TOK_OPEN_PAREN) {
  1230.         struct parser before_cast = *P;
  1231.         cp_error("TODO: handle open parent token in constant1\n");
  1232.         *P = before_cast;
  1233.         ret = calculate_constant(P);

  1234.         require_token(P, tok);
  1235.         if (tok->type != TOK_CLOSE_PAREN) {
  1236.             cp_error("error whilst parsing constant at line %d",
  1237.                     P->line);
  1238.         }

  1239.         next_token(P, tok);
  1240.         return ret;
  1241.     } else {
  1242.         cp_error("unexpected token whilst parsing constant at line %d",
  1243.                 P->line);
  1244.         return 0;
  1245.     }
  1246. }

  1247. /* ! and ~, unary + and -, and sizeof */
  1248. static int64_t calculate_constant2(struct parser *P, struct token *tok)
  1249. {
  1250.     if (tok->type == TOK_LOGICAL_NOT) {
  1251.         require_token(P, tok);
  1252.         return !calculate_constant2(P, tok);

  1253.     } else if (tok->type == TOK_BITWISE_NOT) {
  1254.         require_token(P, tok);
  1255.         return ~calculate_constant2(P, tok);

  1256.     } else if (tok->type == TOK_PLUS) {
  1257.         require_token(P, tok);
  1258.         return calculate_constant2(P, tok);

  1259.     } else if (tok->type == TOK_MINUS) {
  1260.         require_token(P, tok);
  1261.         return -calculate_constant2(P, tok);

  1262.     } else if (tok->type == TOK_TOKEN &&
  1263.             (IS_LITERAL(*tok, "sizeof")
  1264.              || IS_LITERAL(*tok, "alignof")
  1265.              || IS_LITERAL(*tok, "__alignof__")
  1266.              || IS_LITERAL(*tok, "__alignof"))) {
  1267.         cp_error("TODO: support sizeof\n");
  1268.         bool issize = IS_LITERAL(*tok, "sizeof");
  1269.         struct cp_ctype type;

  1270.         require_token(P, tok);
  1271.         if (tok->type != TOK_OPEN_PAREN) {
  1272.             cp_error("invalid sizeof at line %d", P->line);
  1273.         }

  1274.         parse_type(P, &type);
  1275.         parse_argument(P, &type, NULL, NULL);

  1276.         require_token(P, tok);
  1277.         if (tok->type != TOK_CLOSE_PAREN) {
  1278.             cp_error("invalid sizeof at line %d", P->line);
  1279.         }

  1280.         next_token(P, tok);

  1281.         return issize ? ctype_size(&type) : type.align_mask + 1;

  1282.     } else {
  1283.         return calculate_constant1(P, tok);
  1284.     }
  1285. }

  1286. /* binary * / and % (left associative) */
  1287. static int64_t calculate_constant3(struct parser *P, struct token *tok)
  1288. {
  1289.     int64_t left = calculate_constant2(P, tok);

  1290.     for (;;) {
  1291.         if (tok->type == TOK_MULTIPLY) {
  1292.             require_token(P, tok);
  1293.             left *= calculate_constant2(P, tok);

  1294.         } else if (tok->type == TOK_DIVIDE) {
  1295.             require_token(P, tok);
  1296.             left /= calculate_constant2(P, tok);

  1297.         } else if (tok->type == TOK_MODULUS) {
  1298.             require_token(P, tok);
  1299.             left %= calculate_constant2(P, tok);

  1300.         } else {
  1301.             return left;
  1302.         }
  1303.     }
  1304. }

  1305. /* binary + and - (left associative) */
  1306. static int64_t calculate_constant4(struct parser *P, struct token *tok)
  1307. {
  1308.     int64_t left = calculate_constant3(P, tok);

  1309.     for (;;) {
  1310.         if (tok->type == TOK_PLUS) {
  1311.             require_token(P, tok);
  1312.             left += calculate_constant3(P, tok);

  1313.         } else if (tok->type == TOK_MINUS) {
  1314.             require_token(P, tok);
  1315.             left -= calculate_constant3(P, tok);

  1316.         } else {
  1317.             return left;
  1318.         }
  1319.     }
  1320. }

  1321. /* binary << and >> (left associative) */
  1322. static int64_t calculate_constant5(struct parser *P, struct token *tok)
  1323. {
  1324.     int64_t left = calculate_constant4(P, tok);

  1325.     for (;;) {
  1326.         if (tok->type == TOK_LEFT_SHIFT) {
  1327.             require_token(P, tok);
  1328.             left <<= calculate_constant4(P, tok);

  1329.         } else if (tok->type == TOK_RIGHT_SHIFT) {
  1330.             require_token(P, tok);
  1331.             left >>= calculate_constant4(P, tok);

  1332.         } else {
  1333.             return left;
  1334.         }
  1335.     }
  1336. }

  1337. /* binary <, <=, >, and >= (left associative) */
  1338. static int64_t calculate_constant6(struct parser *P, struct token *tok)
  1339. {
  1340.     int64_t left = calculate_constant5(P, tok);

  1341.     for (;;) {
  1342.         if (tok->type == TOK_LESS) {
  1343.             require_token(P, tok);
  1344.             left = (left < calculate_constant5(P, tok));

  1345.         } else if (tok->type == TOK_LESS_EQUAL) {
  1346.             require_token(P, tok);
  1347.             left = (left <= calculate_constant5(P, tok));

  1348.         } else if (tok->type == TOK_GREATER) {
  1349.             require_token(P, tok);
  1350.             left = (left > calculate_constant5(P, tok));

  1351.         } else if (tok->type == TOK_GREATER_EQUAL) {
  1352.             require_token(P, tok);
  1353.             left = (left >= calculate_constant5(P, tok));

  1354.         } else {
  1355.             return left;
  1356.         }
  1357.     }
  1358. }

  1359. /* binary ==, != (left associative) */
  1360. static int64_t calculate_constant7(struct parser *P, struct token *tok)
  1361. {
  1362.     int64_t left = calculate_constant6(P, tok);

  1363.     for (;;) {
  1364.         if (tok->type == TOK_EQUAL) {
  1365.             require_token(P, tok);
  1366.             left = (left == calculate_constant6(P, tok));

  1367.         } else if (tok->type == TOK_NOT_EQUAL) {
  1368.             require_token(P, tok);
  1369.             left = (left != calculate_constant6(P, tok));

  1370.         } else {
  1371.             return left;
  1372.         }
  1373.     }
  1374. }

  1375. /* binary & (left associative) */
  1376. static int64_t calculate_constant8(struct parser *P, struct token *tok)
  1377. {
  1378.     int64_t left = calculate_constant7(P, tok);

  1379.     for (;;) {
  1380.         if (tok->type == TOK_BITWISE_AND) {
  1381.             require_token(P, tok);
  1382.             left = (left & calculate_constant7(P, tok));

  1383.         } else {
  1384.             return left;
  1385.         }
  1386.     }
  1387. }

  1388. /* binary ^ (left associative) */
  1389. static int64_t calculate_constant9(struct parser *P, struct token *tok)
  1390. {
  1391.     int64_t left = calculate_constant8(P, tok);

  1392.     for (;;) {
  1393.         if (tok->type == TOK_BITWISE_XOR) {
  1394.             require_token(P, tok);
  1395.             left = (left ^ calculate_constant8(P, tok));

  1396.         } else {
  1397.             return left;
  1398.         }
  1399.     }
  1400. }

  1401. /* binary | (left associative) */
  1402. static int64_t calculate_constant10(struct parser *P, struct token *tok)
  1403. {
  1404.     int64_t left = calculate_constant9(P, tok);

  1405.     for (;;) {
  1406.         if (tok->type == TOK_BITWISE_OR) {
  1407.             require_token(P, tok);
  1408.             left = (left | calculate_constant9(P, tok));

  1409.         } else {
  1410.             return left;
  1411.         }
  1412.     }
  1413. }

  1414. /* binary && (left associative) */
  1415. static int64_t calculate_constant11(struct parser *P, struct token *tok)
  1416. {
  1417.     int64_t left = calculate_constant10(P, tok);

  1418.     for (;;) {
  1419.         if (tok->type == TOK_LOGICAL_AND) {
  1420.             require_token(P, tok);
  1421.             left = (left && calculate_constant10(P, tok));

  1422.         } else {
  1423.             return left;
  1424.         }
  1425.     }
  1426. }

  1427. /* binary || (left associative) */
  1428. static int64_t calculate_constant12(struct parser *P, struct token *tok)
  1429. {
  1430.     int64_t left = calculate_constant11(P, tok);

  1431.     for (;;) {
  1432.         if (tok->type == TOK_LOGICAL_OR) {
  1433.             require_token(P, tok);
  1434.             left = (left || calculate_constant11(P, tok));

  1435.         } else {
  1436.             return left;
  1437.         }
  1438.     }
  1439. }

  1440. /* ternary ?: (right associative) */
  1441. static int64_t calculate_constant13(struct parser *P, struct token *tok)
  1442. {
  1443.     int64_t left = calculate_constant12(P, tok);

  1444.     if (tok->type == TOK_QUESTION) {
  1445.         int64_t middle, right;
  1446.         require_token(P, tok);
  1447.         middle = calculate_constant13(P, tok);
  1448.         if (tok->type != TOK_COLON) {
  1449.             cp_error("invalid ternery (? :) in constant on line %d",
  1450.                     P->line);
  1451.         }
  1452.         require_token(P, tok);
  1453.         right = calculate_constant13(P, tok);
  1454.         return left ? middle : right;

  1455.     } else {
  1456.         return left;
  1457.     }
  1458. }

  1459. int64_t calculate_constant(struct parser* P)
  1460. {
  1461.     struct token tok;
  1462.     int64_t ret;
  1463.     require_token(P, &tok);
  1464.     ret = calculate_constant13(P, &tok);

  1465.     if (tok.type != TOK_NIL) {
  1466.         put_back(P);
  1467.     }

  1468.     return ret;
  1469. }

  1470. void cp_init_parser(struct parser *P, const char *s)
  1471. {
  1472.     memset(P, 0, sizeof(struct parser));
  1473.     P->line = 1;
  1474.     P->prev = P->next = s;
  1475.     P->align_mask = DEFAULT_ALIGN_MASK;
  1476. }

  1477. /* used for ffi.cdef */
  1478. int ffi_parse_cdef(const char *s)
  1479. {
  1480.     struct parser P;

  1481.     cp_init_parser(&P, s);
  1482.     if (parse_root(&P) == PRAGMA_POP) {
  1483.         cp_error("pragma pop without an associated push on line %d",
  1484.                 P.line);
  1485.     }

  1486.     return 0;
  1487. }

  1488. /* used for ffi.new */
  1489. void ffi_parse_new(const char *s, struct cp_ctype *ct)
  1490. {
  1491.     struct parser P;

  1492.     cp_init_parser(&P, s);
  1493.     parse_type(&P, ct);
  1494.     parse_argument(&P, ct, NULL, NULL);
  1495.     cp_update_csym_in_ctype(ct);
  1496. }

  1497. int ffi_lookup_csymbol_id_by_name(const char *s)
  1498. {
  1499.     struct parser P;
  1500.     struct cp_ctype ct;

  1501.     cp_init_parser(&P, s);
  1502.     parse_type(&P, &ct);
  1503.     cp_update_csym_in_ctype(&ct);
  1504.     return ct.ffi_cs_id;
  1505. }

  1506. void ffi_cparser_init(void)
  1507. {
  1508.     cp_ctype_init();
  1509. }

  1510. void ffi_cparser_free(void)
  1511. {
  1512.     cp_ctype_free();
  1513. }