• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <string.h>
3 #include <assert.h>
4 #include <errno.h>
5 
6 #define _CFFI_INTERNAL
7 #include "../cffi/parse_c_type.h"
8 
9 
10 enum token_e {
11     TOK_STAR='*',
12     TOK_OPEN_PAREN='(',
13     TOK_CLOSE_PAREN=')',
14     TOK_OPEN_BRACKET='[',
15     TOK_CLOSE_BRACKET=']',
16     TOK_COMMA=',',
17 
18     TOK_START=256,
19     TOK_END,
20     TOK_ERROR,
21     TOK_IDENTIFIER,
22     TOK_INTEGER,
23     TOK_DOTDOTDOT,
24 
25     /* keywords */
26     TOK__BOOL,
27     TOK_CHAR,
28     TOK__COMPLEX,
29     TOK_CONST,
30     TOK_DOUBLE,
31     TOK_ENUM,
32     TOK_FLOAT,
33     //TOK__IMAGINARY,
34     TOK_INT,
35     TOK_LONG,
36     TOK_SHORT,
37     TOK_SIGNED,
38     TOK_STRUCT,
39     TOK_UNION,
40     TOK_UNSIGNED,
41     TOK_VOID,
42     TOK_VOLATILE,
43 
44     TOK_CDECL,
45     TOK_STDCALL,
46 };
47 
48 typedef struct {
49     struct _cffi_parse_info_s *info;
50     const char *input, *p;
51     size_t size;              // the next token is at 'p' and of length 'size'
52     enum token_e kind;
53     _cffi_opcode_t *output;
54     size_t output_index;
55 } token_t;
56 
is_space(char x)57 static int is_space(char x)
58 {
59     return (x == ' ' || x == '\f' || x == '\n' || x == '\r' ||
60             x == '\t' || x == '\v');
61 }
62 
is_ident_first(char x)63 static int is_ident_first(char x)
64 {
65     return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_' ||
66             x == '$');   /* '$' in names is supported here, for the struct
67                             names invented by cparser */
68 }
69 
is_digit(char x)70 static int is_digit(char x)
71 {
72     return ('0' <= x && x <= '9');
73 }
74 
is_hex_digit(char x)75 static int is_hex_digit(char x)
76 {
77     return (('0' <= x && x <= '9') ||
78             ('A' <= x && x <= 'F') ||
79             ('a' <= x && x <= 'f'));
80 }
81 
is_ident_next(char x)82 static int is_ident_next(char x)
83 {
84     return (is_ident_first(x) || is_digit(x));
85 }
86 
get_following_char(token_t * tok)87 static char get_following_char(token_t *tok)
88 {
89     const char *p = tok->p + tok->size;
90     if (tok->kind == TOK_ERROR)
91         return 0;
92     while (is_space(*p))
93         p++;
94     return *p;
95 }
96 
number_of_commas(token_t * tok)97 static int number_of_commas(token_t *tok)
98 {
99     const char *p = tok->p;
100     int result = 0;
101     int nesting = 0;
102     while (1) {
103         switch (*p++) {
104         case ',': result += !nesting; break;
105         case '(': nesting++; break;
106         case ')': if ((--nesting) < 0) return result; break;
107         case 0:   return result;
108         default:  break;
109         }
110     }
111 }
112 
next_token(token_t * tok)113 static void next_token(token_t *tok)
114 {
115     const char *p = tok->p + tok->size;
116     if (tok->kind == TOK_ERROR)
117         return;
118     while (!is_ident_first(*p)) {
119         if (is_space(*p)) {
120             p++;
121         }
122         else if (is_digit(*p)) {
123             tok->kind = TOK_INTEGER;
124             tok->p = p;
125             tok->size = 1;
126             if (p[1] == 'x' || p[1] == 'X')
127                 tok->size = 2;
128             while (is_hex_digit(p[tok->size]))
129                 tok->size++;
130             return;
131         }
132         else if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
133             tok->kind = TOK_DOTDOTDOT;
134             tok->p = p;
135             tok->size = 3;
136             return;
137         }
138         else if (*p) {
139             tok->kind = *p;
140             tok->p = p;
141             tok->size = 1;
142             return;
143         }
144         else {
145             tok->kind = TOK_END;
146             tok->p = p;
147             tok->size = 0;
148             return;
149         }
150     }
151     tok->kind = TOK_IDENTIFIER;
152     tok->p = p;
153     tok->size = 1;
154     while (is_ident_next(p[tok->size]))
155         tok->size++;
156 
157     switch (*p) {
158     case '_':
159         if (tok->size == 5 && !memcmp(p, "_Bool", 5))  tok->kind = TOK__BOOL;
160         if (tok->size == 7 && !memcmp(p,"__cdecl",7))  tok->kind = TOK_CDECL;
161         if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL;
162         if (tok->size == 8 && !memcmp(p,"_Complex",8)) tok->kind = TOK__COMPLEX;
163         break;
164     case 'c':
165         if (tok->size == 4 && !memcmp(p, "char", 4))   tok->kind = TOK_CHAR;
166         if (tok->size == 5 && !memcmp(p, "const", 5))  tok->kind = TOK_CONST;
167         break;
168     case 'd':
169         if (tok->size == 6 && !memcmp(p, "double", 6)) tok->kind = TOK_DOUBLE;
170         break;
171     case 'e':
172         if (tok->size == 4 && !memcmp(p, "enum", 4))   tok->kind = TOK_ENUM;
173         break;
174     case 'f':
175         if (tok->size == 5 && !memcmp(p, "float", 5))  tok->kind = TOK_FLOAT;
176         break;
177     case 'i':
178         if (tok->size == 3 && !memcmp(p, "int", 3))    tok->kind = TOK_INT;
179         break;
180     case 'l':
181         if (tok->size == 4 && !memcmp(p, "long", 4))   tok->kind = TOK_LONG;
182         break;
183     case 's':
184         if (tok->size == 5 && !memcmp(p, "short", 5))  tok->kind = TOK_SHORT;
185         if (tok->size == 6 && !memcmp(p, "signed", 6)) tok->kind = TOK_SIGNED;
186         if (tok->size == 6 && !memcmp(p, "struct", 6)) tok->kind = TOK_STRUCT;
187         break;
188     case 'u':
189         if (tok->size == 5 && !memcmp(p, "union", 5))  tok->kind = TOK_UNION;
190         if (tok->size == 8 && !memcmp(p,"unsigned",8)) tok->kind = TOK_UNSIGNED;
191         break;
192     case 'v':
193         if (tok->size == 4 && !memcmp(p, "void", 4))   tok->kind = TOK_VOID;
194         if (tok->size == 8 && !memcmp(p,"volatile",8)) tok->kind = TOK_VOLATILE;
195         break;
196     }
197 }
198 
parse_error(token_t * tok,const char * msg)199 static int parse_error(token_t *tok, const char *msg)
200 {
201     if (tok->kind != TOK_ERROR) {
202         tok->kind = TOK_ERROR;
203         tok->info->error_location = tok->p - tok->input;
204         tok->info->error_message = msg;
205     }
206     return -1;
207 }
208 
write_ds(token_t * tok,_cffi_opcode_t ds)209 static int write_ds(token_t *tok, _cffi_opcode_t ds)
210 {
211     size_t index = tok->output_index;
212     if (index >= tok->info->output_size) {
213         parse_error(tok, "internal type complexity limit reached");
214         return -1;
215     }
216     tok->output[index] = ds;
217     tok->output_index = index + 1;
218     return index;
219 }
220 
221 #define MAX_SSIZE_T  (((size_t)-1) >> 1)
222 
223 static int parse_complete(token_t *tok);
224 static const char *get_common_type(const char *search, size_t search_len);
225 static int parse_common_type_replacement(token_t *tok, const char *replacement);
226 
parse_sequel(token_t * tok,int outer)227 static int parse_sequel(token_t *tok, int outer)
228 {
229     /* Emit opcodes for the "sequel", which is the optional part of a
230        type declaration that follows the type name, i.e. everything
231        with '*', '[ ]', '( )'.  Returns the entry point index pointing
232        the innermost opcode (the one that corresponds to the complete
233        type).  The 'outer' argument is the index of the opcode outside
234        this "sequel".
235      */
236     int check_for_grouping, abi=0;
237     _cffi_opcode_t result, *p_current;
238 
239  header:
240     switch (tok->kind) {
241     case TOK_STAR:
242         outer = write_ds(tok, _CFFI_OP(_CFFI_OP_POINTER, outer));
243         next_token(tok);
244         goto header;
245     case TOK_CONST:
246         /* ignored for now */
247         next_token(tok);
248         goto header;
249     case TOK_VOLATILE:
250         /* ignored for now */
251         next_token(tok);
252         goto header;
253     case TOK_CDECL:
254     case TOK_STDCALL:
255         /* must be in a function; checked below */
256         abi = tok->kind;
257         next_token(tok);
258         goto header;
259     default:
260         break;
261     }
262 
263     check_for_grouping = 1;
264     if (tok->kind == TOK_IDENTIFIER) {
265         next_token(tok);    /* skip a potential variable name */
266         check_for_grouping = 0;
267     }
268 
269     result = 0;
270     p_current = &result;
271 
272     while (tok->kind == TOK_OPEN_PAREN) {
273         next_token(tok);
274 
275         if (tok->kind == TOK_CDECL || tok->kind == TOK_STDCALL) {
276             abi = tok->kind;
277             next_token(tok);
278         }
279 
280         if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR ||
281                                             tok->kind == TOK_CONST ||
282                                             tok->kind == TOK_VOLATILE ||
283                                             tok->kind == TOK_OPEN_BRACKET)) {
284             /* just parentheses for grouping.  Use a OP_NOOP to simplify */
285             int x;
286             assert(p_current == &result);
287             x = tok->output_index;
288             p_current = tok->output + x;
289 
290             write_ds(tok, _CFFI_OP(_CFFI_OP_NOOP, 0));
291 
292             x = parse_sequel(tok, x);
293             result = _CFFI_OP(_CFFI_GETOP(0), x);
294         }
295         else {
296             /* function type */
297             int arg_total, base_index, arg_next, flags=0;
298 
299             if (abi == TOK_STDCALL) {
300                 flags = 2;
301                 /* note that an ellipsis below will overwrite this flags,
302                    which is the goal: variadic functions are always cdecl */
303             }
304             abi = 0;
305 
306             if (tok->kind == TOK_VOID && get_following_char(tok) == ')') {
307                 next_token(tok);
308             }
309 
310             /* (over-)estimate 'arg_total'.  May return 1 when it is really 0 */
311             arg_total = number_of_commas(tok) + 1;
312 
313             *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
314             p_current = tok->output + tok->output_index;
315 
316             base_index = write_ds(tok, _CFFI_OP(_CFFI_OP_FUNCTION, 0));
317             if (base_index < 0)
318                 return -1;
319             /* reserve (arg_total + 1) slots for the arguments and the
320                final FUNCTION_END */
321             for (arg_next = 0; arg_next <= arg_total; arg_next++)
322                 if (write_ds(tok, _CFFI_OP(0, 0)) < 0)
323                     return -1;
324 
325             arg_next = base_index + 1;
326 
327             if (tok->kind != TOK_CLOSE_PAREN) {
328                 while (1) {
329                     int arg;
330                     _cffi_opcode_t oarg;
331 
332                     if (tok->kind == TOK_DOTDOTDOT) {
333                         flags = 1;   /* ellipsis */
334                         next_token(tok);
335                         break;
336                     }
337                     arg = parse_complete(tok);
338                     switch (_CFFI_GETOP(tok->output[arg])) {
339                     case _CFFI_OP_ARRAY:
340                     case _CFFI_OP_OPEN_ARRAY:
341                         arg = _CFFI_GETARG(tok->output[arg]);
342                         /* fall-through */
343                     case _CFFI_OP_FUNCTION:
344                         oarg = _CFFI_OP(_CFFI_OP_POINTER, arg);
345                         break;
346                     default:
347                         oarg = _CFFI_OP(_CFFI_OP_NOOP, arg);
348                         break;
349                     }
350                     assert(arg_next - base_index <= arg_total);
351                     tok->output[arg_next++] = oarg;
352                     if (tok->kind != TOK_COMMA)
353                         break;
354                     next_token(tok);
355                 }
356             }
357             tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, flags);
358         }
359 
360         if (tok->kind != TOK_CLOSE_PAREN)
361             return parse_error(tok, "expected ')'");
362         next_token(tok);
363     }
364 
365     if (abi != 0)
366         return parse_error(tok, "expected '('");
367 
368     while (tok->kind == TOK_OPEN_BRACKET) {
369         *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
370         p_current = tok->output + tok->output_index;
371 
372         next_token(tok);
373         if (tok->kind != TOK_CLOSE_BRACKET) {
374             size_t length;
375             int gindex;
376             char *endptr;
377 
378             switch (tok->kind) {
379 
380             case TOK_INTEGER:
381                 errno = 0;
382                 if (sizeof(length) > sizeof(unsigned long)) {
383 #ifdef MS_WIN32
384 # ifdef _WIN64
385                     length = _strtoui64(tok->p, &endptr, 0);
386 # else
387                     abort();  /* unreachable */
388 # endif
389 #else
390                     length = strtoull(tok->p, &endptr, 0);
391 #endif
392                 }
393                 else
394                     length = strtoul(tok->p, &endptr, 0);
395                 if (endptr != tok->p + tok->size)
396                     return parse_error(tok, "invalid number");
397                 if (errno == ERANGE || length > MAX_SSIZE_T)
398                     return parse_error(tok, "number too large");
399                 break;
400 
401             case TOK_IDENTIFIER:
402                 gindex = search_in_globals(tok->info->ctx, tok->p, tok->size);
403                 if (gindex >= 0) {
404                     const struct _cffi_global_s *g;
405                     g = &tok->info->ctx->globals[gindex];
406                     if (_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT_INT ||
407                         _CFFI_GETOP(g->type_op) == _CFFI_OP_ENUM) {
408                         int neg;
409                         struct _cffi_getconst_s gc;
410                         gc.ctx = tok->info->ctx;
411                         gc.gindex = gindex;
412                         neg = ((int(*)(struct _cffi_getconst_s*))g->address)
413                             (&gc);
414                         if (neg == 0 && gc.value > MAX_SSIZE_T)
415                             return parse_error(tok,
416                                                "integer constant too large");
417                         if (neg == 0 || gc.value == 0) {
418                             length = (size_t)gc.value;
419                             break;
420                         }
421                         if (neg != 1)
422                             return parse_error(tok, "disagreement about"
423                                                " this constant's value");
424                     }
425                 }
426                 /* fall-through to the default case */
427             default:
428                 return parse_error(tok, "expected a positive integer constant");
429             }
430 
431             next_token(tok);
432 
433             write_ds(tok, _CFFI_OP(_CFFI_OP_ARRAY, 0));
434             write_ds(tok, (_cffi_opcode_t)length);
435         }
436         else
437             write_ds(tok, _CFFI_OP(_CFFI_OP_OPEN_ARRAY, 0));
438 
439         if (tok->kind != TOK_CLOSE_BRACKET)
440             return parse_error(tok, "expected ']'");
441         next_token(tok);
442     }
443 
444     *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), outer);
445     return _CFFI_GETARG(result);
446 }
447 
search_sorted(const char * const * base,size_t item_size,int array_len,const char * search,size_t search_len)448 static int search_sorted(const char *const *base,
449                          size_t item_size, int array_len,
450                          const char *search, size_t search_len)
451 {
452     int left = 0, right = array_len;
453     const char *baseptr = (const char *)base;
454 
455     while (left < right) {
456         int middle = (left + right) / 2;
457         const char *src = *(const char *const *)(baseptr + middle * item_size);
458         int diff = strncmp(src, search, search_len);
459         if (diff == 0 && src[search_len] == '\0')
460             return middle;
461         else if (diff >= 0)
462             right = middle;
463         else
464             left = middle + 1;
465     }
466     return -1;
467 }
468 
469 #define MAKE_SEARCH_FUNC(FIELD)                                         \
470   static                                                                \
471   int search_in_##FIELD(const struct _cffi_type_context_s *ctx,         \
472                         const char *search, size_t search_len)          \
473   {                                                                     \
474       return search_sorted(&ctx->FIELD->name, sizeof(*ctx->FIELD),      \
475                            ctx->num_##FIELD, search, search_len);       \
476   }
477 
478 MAKE_SEARCH_FUNC(globals)
MAKE_SEARCH_FUNC(struct_unions)479 MAKE_SEARCH_FUNC(struct_unions)
480 MAKE_SEARCH_FUNC(typenames)
481 MAKE_SEARCH_FUNC(enums)
482 
483 #undef MAKE_SEARCH_FUNC
484 
485 
486 static
487 int search_standard_typename(const char *p, size_t size)
488 {
489     if (size < 6 || p[size-2] != '_' || p[size-1] != 't')
490         return -1;
491 
492     switch (p[4]) {
493 
494     case '1':
495         if (size == 8 && !memcmp(p, "uint16", 6)) return _CFFI_PRIM_UINT16;
496         if (size == 8 && !memcmp(p, "char16", 6)) return _CFFI_PRIM_CHAR16;
497         break;
498 
499     case '2':
500         if (size == 7 && !memcmp(p, "int32", 5)) return _CFFI_PRIM_INT32;
501         break;
502 
503     case '3':
504         if (size == 8 && !memcmp(p, "uint32", 6)) return _CFFI_PRIM_UINT32;
505         if (size == 8 && !memcmp(p, "char32", 6)) return _CFFI_PRIM_CHAR32;
506         break;
507 
508     case '4':
509         if (size == 7 && !memcmp(p, "int64", 5)) return _CFFI_PRIM_INT64;
510         break;
511 
512     case '6':
513         if (size == 8 && !memcmp(p, "uint64", 6)) return _CFFI_PRIM_UINT64;
514         if (size == 7 && !memcmp(p, "int16", 5)) return _CFFI_PRIM_INT16;
515         break;
516 
517     case '8':
518         if (size == 7 && !memcmp(p, "uint8", 5)) return _CFFI_PRIM_UINT8;
519         break;
520 
521     case 'a':
522         if (size == 8 && !memcmp(p, "intmax", 6)) return _CFFI_PRIM_INTMAX;
523         break;
524 
525     case 'e':
526         if (size == 7 && !memcmp(p, "ssize", 5)) return _CFFI_PRIM_SSIZE;
527         break;
528 
529     case 'f':
530         if (size == 11 && !memcmp(p, "int_fast8",   9)) return _CFFI_PRIM_INT_FAST8;
531         if (size == 12 && !memcmp(p, "int_fast16", 10)) return _CFFI_PRIM_INT_FAST16;
532         if (size == 12 && !memcmp(p, "int_fast32", 10)) return _CFFI_PRIM_INT_FAST32;
533         if (size == 12 && !memcmp(p, "int_fast64", 10)) return _CFFI_PRIM_INT_FAST64;
534         break;
535 
536     case 'i':
537         if (size == 9 && !memcmp(p, "ptrdiff", 7)) return _CFFI_PRIM_PTRDIFF;
538         break;
539 
540     case 'l':
541         if (size == 12 && !memcmp(p, "int_least8",  10)) return _CFFI_PRIM_INT_LEAST8;
542         if (size == 13 && !memcmp(p, "int_least16", 11)) return _CFFI_PRIM_INT_LEAST16;
543         if (size == 13 && !memcmp(p, "int_least32", 11)) return _CFFI_PRIM_INT_LEAST32;
544         if (size == 13 && !memcmp(p, "int_least64", 11)) return _CFFI_PRIM_INT_LEAST64;
545         break;
546 
547     case 'm':
548         if (size == 9 && !memcmp(p, "uintmax", 7)) return _CFFI_PRIM_UINTMAX;
549         break;
550 
551     case 'p':
552         if (size == 9 && !memcmp(p, "uintptr", 7)) return _CFFI_PRIM_UINTPTR;
553         break;
554 
555     case 'r':
556         if (size == 7 && !memcmp(p, "wchar", 5)) return _CFFI_PRIM_WCHAR;
557         break;
558 
559     case 't':
560         if (size == 8 && !memcmp(p, "intptr", 6)) return _CFFI_PRIM_INTPTR;
561         break;
562 
563     case '_':
564         if (size == 6 && !memcmp(p, "size", 4)) return _CFFI_PRIM_SIZE;
565         if (size == 6 && !memcmp(p, "int8", 4)) return _CFFI_PRIM_INT8;
566         if (size >= 12) {
567             switch (p[10]) {
568             case '1':
569                 if (size == 14 && !memcmp(p, "uint_least16", 12)) return _CFFI_PRIM_UINT_LEAST16;
570                 break;
571             case '2':
572                 if (size == 13 && !memcmp(p, "uint_fast32", 11)) return _CFFI_PRIM_UINT_FAST32;
573                 break;
574             case '3':
575                 if (size == 14 && !memcmp(p, "uint_least32", 12)) return _CFFI_PRIM_UINT_LEAST32;
576                 break;
577             case '4':
578                 if (size == 13 && !memcmp(p, "uint_fast64", 11)) return _CFFI_PRIM_UINT_FAST64;
579                 break;
580             case '6':
581                 if (size == 14 && !memcmp(p, "uint_least64", 12)) return _CFFI_PRIM_UINT_LEAST64;
582                 if (size == 13 && !memcmp(p, "uint_fast16", 11)) return _CFFI_PRIM_UINT_FAST16;
583                 break;
584             case '8':
585                 if (size == 13 && !memcmp(p, "uint_least8", 11)) return _CFFI_PRIM_UINT_LEAST8;
586                 break;
587             case '_':
588                 if (size == 12 && !memcmp(p, "uint_fast8", 10)) return _CFFI_PRIM_UINT_FAST8;
589                 break;
590             default:
591                 break;
592             }
593         }
594         break;
595 
596     default:
597         break;
598     }
599     return -1;
600 }
601 
602 
parse_complete(token_t * tok)603 static int parse_complete(token_t *tok)
604 {
605     unsigned int t0;
606     _cffi_opcode_t t1;
607     _cffi_opcode_t t1complex;
608     int modifiers_length, modifiers_sign;
609 
610  qualifiers:
611     switch (tok->kind) {
612     case TOK_CONST:
613         /* ignored for now */
614         next_token(tok);
615         goto qualifiers;
616     case TOK_VOLATILE:
617         /* ignored for now */
618         next_token(tok);
619         goto qualifiers;
620     default:
621         ;
622     }
623 
624     modifiers_length = 0;
625     modifiers_sign = 0;
626  modifiers:
627     switch (tok->kind) {
628 
629     case TOK_SHORT:
630         if (modifiers_length != 0)
631             return parse_error(tok, "'short' after another 'short' or 'long'");
632         modifiers_length--;
633         next_token(tok);
634         goto modifiers;
635 
636     case TOK_LONG:
637         if (modifiers_length < 0)
638             return parse_error(tok, "'long' after 'short'");
639         if (modifiers_length >= 2)
640             return parse_error(tok, "'long long long' is too long");
641         modifiers_length++;
642         next_token(tok);
643         goto modifiers;
644 
645     case TOK_SIGNED:
646         if (modifiers_sign)
647             return parse_error(tok, "multiple 'signed' or 'unsigned'");
648         modifiers_sign++;
649         next_token(tok);
650         goto modifiers;
651 
652     case TOK_UNSIGNED:
653         if (modifiers_sign)
654             return parse_error(tok, "multiple 'signed' or 'unsigned'");
655         modifiers_sign--;
656         next_token(tok);
657         goto modifiers;
658 
659     default:
660         break;
661     }
662 
663     t1complex = 0;
664 
665     if (modifiers_length || modifiers_sign) {
666 
667         switch (tok->kind) {
668 
669         case TOK_VOID:
670         case TOK__BOOL:
671         case TOK_FLOAT:
672         case TOK_STRUCT:
673         case TOK_UNION:
674         case TOK_ENUM:
675         case TOK__COMPLEX:
676             return parse_error(tok, "invalid combination of types");
677 
678         case TOK_DOUBLE:
679             if (modifiers_sign != 0 || modifiers_length != 1)
680                 return parse_error(tok, "invalid combination of types");
681             next_token(tok);
682             t0 = _CFFI_PRIM_LONGDOUBLE;
683             break;
684 
685         case TOK_CHAR:
686             if (modifiers_length != 0)
687                 return parse_error(tok, "invalid combination of types");
688             modifiers_length = -2;
689             /* fall-through */
690         case TOK_INT:
691             next_token(tok);
692             /* fall-through */
693         default:
694             if (modifiers_sign >= 0)
695                 switch (modifiers_length) {
696                 case -2: t0 = _CFFI_PRIM_SCHAR; break;
697                 case -1: t0 = _CFFI_PRIM_SHORT; break;
698                 case 1:  t0 = _CFFI_PRIM_LONG; break;
699                 case 2:  t0 = _CFFI_PRIM_LONGLONG; break;
700                 default: t0 = _CFFI_PRIM_INT; break;
701                 }
702             else
703                 switch (modifiers_length) {
704                 case -2: t0 = _CFFI_PRIM_UCHAR; break;
705                 case -1: t0 = _CFFI_PRIM_USHORT; break;
706                 case 1:  t0 = _CFFI_PRIM_ULONG; break;
707                 case 2:  t0 = _CFFI_PRIM_ULONGLONG; break;
708                 default: t0 = _CFFI_PRIM_UINT; break;
709                 }
710         }
711         t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, t0);
712     }
713     else {
714         switch (tok->kind) {
715         case TOK_INT:
716             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT);
717             break;
718         case TOK_CHAR:
719             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_CHAR);
720             break;
721         case TOK_VOID:
722             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_VOID);
723             break;
724         case TOK__BOOL:
725             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_BOOL);
726             break;
727         case TOK_FLOAT:
728             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT);
729             t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOATCOMPLEX);
730             break;
731         case TOK_DOUBLE:
732             t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE);
733             t1complex = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLECOMPLEX);
734             break;
735         case TOK_IDENTIFIER:
736         {
737             const char *replacement;
738             int n = search_in_typenames(tok->info->ctx, tok->p, tok->size);
739             if (n >= 0) {
740                 t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n);
741                 break;
742             }
743             n = search_standard_typename(tok->p, tok->size);
744             if (n >= 0) {
745                 t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n);
746                 break;
747             }
748             replacement = get_common_type(tok->p, tok->size);
749             if (replacement != NULL) {
750                 n = parse_common_type_replacement(tok, replacement);
751                 if (n < 0)
752                     return parse_error(tok, "internal error, please report!");
753                 t1 = _CFFI_OP(_CFFI_OP_NOOP, n);
754                 break;
755             }
756             return parse_error(tok, "undefined type name");
757         }
758         case TOK_STRUCT:
759         case TOK_UNION:
760         {
761             int n, kind = tok->kind;
762             next_token(tok);
763             if (tok->kind != TOK_IDENTIFIER)
764                 return parse_error(tok, "struct or union name expected");
765 
766             n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size);
767             if (n < 0) {
768                 if (kind == TOK_STRUCT && tok->size == 8 &&
769                         !memcmp(tok->p, "_IO_FILE", 8))
770                     n = _CFFI__IO_FILE_STRUCT;
771                 else
772                     return parse_error(tok, "undefined struct/union name");
773             }
774             else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION)
775                       != 0) ^ (kind == TOK_UNION))
776                 return parse_error(tok, "wrong kind of tag: struct vs union");
777 
778             t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n);
779             break;
780         }
781         case TOK_ENUM:
782         {
783             int n;
784             next_token(tok);
785             if (tok->kind != TOK_IDENTIFIER)
786                 return parse_error(tok, "enum name expected");
787 
788             n = search_in_enums(tok->info->ctx, tok->p, tok->size);
789             if (n < 0)
790                 return parse_error(tok, "undefined enum name");
791 
792             t1 = _CFFI_OP(_CFFI_OP_ENUM, n);
793             break;
794         }
795         default:
796             return parse_error(tok, "identifier expected");
797         }
798         next_token(tok);
799     }
800     if (tok->kind == TOK__COMPLEX)
801     {
802         if (t1complex == 0)
803             return parse_error(tok, "_Complex type combination unsupported");
804         t1 = t1complex;
805         next_token(tok);
806     }
807 
808     return parse_sequel(tok, write_ds(tok, t1));
809 }
810 
811 
812 static
parse_c_type_from(struct _cffi_parse_info_s * info,size_t * output_index,const char * input)813 int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index,
814                       const char *input)
815 {
816     int result;
817     token_t token;
818 
819     token.info = info;
820     token.kind = TOK_START;
821     token.input = input;
822     token.p = input;
823     token.size = 0;
824     token.output = info->output;
825     token.output_index = *output_index;
826 
827     next_token(&token);
828     result = parse_complete(&token);
829 
830     *output_index = token.output_index;
831     if (token.kind != TOK_END)
832         return parse_error(&token, "unexpected symbol");
833     return result;
834 }
835 
836 static
parse_c_type(struct _cffi_parse_info_s * info,const char * input)837 int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
838 {
839     size_t output_index = 0;
840     return parse_c_type_from(info, &output_index, input);
841 }
842 
843 static
parse_common_type_replacement(token_t * tok,const char * replacement)844 int parse_common_type_replacement(token_t *tok, const char *replacement)
845 {
846     return parse_c_type_from(tok->info, &tok->output_index, replacement);
847 }
848