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