authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-08 23:12:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-08 23:22:25-07:00
log4eff5f114b463ddd887665129f2e1d29b0f13b7f
tree10535aff8fa5cdb95c57f595537167d471d4c705
parentface8d65a85e9b6184d9eb7c3d5b345090350b27

parseh: better results for stdio.h


1 files changed, 191 insertions(+), 10 deletions(-)

src/parseh.cpp+191-10
...@@ -12,6 +12,11 @@...@@ -12,6 +12,11 @@
1212
13#include <string.h>13#include <string.h>
1414
15struct TypeDef {
16 Buf alias;
17 Buf target;
18};
19
15struct Arg {20struct Arg {
16 Buf name;21 Buf name;
17 Buf *type;22 Buf *type;
...@@ -25,11 +30,26 @@ struct Fn {...@@ -25,11 +30,26 @@ struct Fn {
25 bool is_variadic;30 bool is_variadic;
26};31};
2732
33struct Field {
34 Buf name;
35 Buf *type;
36};
37
38struct Struct {
39 Buf name;
40 ZigList<Field*> fields;
41 bool have_def;
42};
43
28struct ParseH {44struct ParseH {
29 CXTranslationUnit tu;45 CXTranslationUnit tu;
30 FILE *f;46 FILE *f;
31 ZigList<Fn *> fn_list;47 ZigList<Fn *> fn_list;
48 ZigList<Struct *> struct_list;
49 ZigList<TypeDef *> type_def_list;
50 ZigList<Struct *> incomplete_struct_list;
32 Fn *cur_fn;51 Fn *cur_fn;
52 Struct *cur_struct;
33 int arg_index;53 int arg_index;
34 int cur_indent;54 int cur_indent;
35 CXSourceRange range;55 CXSourceRange range;
...@@ -38,6 +58,16 @@ struct ParseH {...@@ -38,6 +58,16 @@ struct ParseH {
3858
39static const int indent_size = 4;59static const int indent_size = 4;
4060
61static bool have_struct_def(ParseH *p, Buf *name) {
62 for (int i = 0; i < p->struct_list.length; i += 1) {
63 Struct *struc = p->struct_list.at(i);
64 if (struc->fields.length > 0 && buf_eql_buf(&struc->name, name)) {
65 return true;
66 }
67 }
68 return false;
69}
70
41static bool str_has_prefix(const char *str, const char *prefix) {71static bool str_has_prefix(const char *str, const char *prefix) {
42 while (*prefix) {72 while (*prefix) {
43 if (*str && *str == *prefix) {73 if (*str && *str == *prefix) {
...@@ -81,6 +111,24 @@ static void print_location(ParseH *p) {...@@ -81,6 +111,24 @@ static void print_location(ParseH *p) {
81 fprintf(stderr, "%s line %u, column %u\n", clang_getCString(file_name), line, column);111 fprintf(stderr, "%s line %u, column %u\n", clang_getCString(file_name), line, column);
82}112}
83113
114static bool resolves_to_void(ParseH *p, CXType raw_type) {
115 if (raw_type.kind == CXType_Unexposed) {
116 CXType canonical = clang_getCanonicalType(raw_type);
117 if (canonical.kind == CXType_Unexposed)
118 zig_panic("clang C api insufficient");
119 else
120 return resolves_to_void(p, canonical);
121 }
122 if (raw_type.kind == CXType_Void) {
123 return true;
124 } else if (raw_type.kind == CXType_Typedef) {
125 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
126 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
127 return resolves_to_void(p, underlying_type);
128 }
129 return false;
130}
131
84static Buf *to_zig_type(ParseH *p, CXType raw_type) {132static Buf *to_zig_type(ParseH *p, CXType raw_type) {
85 if (raw_type.kind == CXType_Unexposed) {133 if (raw_type.kind == CXType_Unexposed) {
86 CXType canonical = clang_getCanonicalType(raw_type);134 CXType canonical = clang_getCanonicalType(raw_type);
...@@ -94,15 +142,16 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {...@@ -94,15 +142,16 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {
94 case CXType_Unexposed:142 case CXType_Unexposed:
95 zig_unreachable();143 zig_unreachable();
96 case CXType_Void:144 case CXType_Void:
97 return buf_create_from_str("void");145 zig_panic("void type encountered");
98 case CXType_Bool:146 case CXType_Bool:
99 return buf_create_from_str("bool");147 return buf_create_from_str("bool");
100 case CXType_SChar:148 case CXType_SChar:
101 return buf_create_from_str("i8");149 return buf_create_from_str("c_schar");
150 case CXType_UChar:
151 return buf_create_from_str("c_uchar");
102 case CXType_Char_U:152 case CXType_Char_U:
103 case CXType_Char_S:153 case CXType_Char_S:
104 case CXType_UChar:154 return buf_create_from_str("c_char");
105 return buf_create_from_str("u8");
106 case CXType_WChar:155 case CXType_WChar:
107 print_location(p);156 print_location(p);
108 zig_panic("TODO wchar");157 zig_panic("TODO wchar");
...@@ -153,7 +202,12 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {...@@ -153,7 +202,12 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {
153 case CXType_Pointer:202 case CXType_Pointer:
154 {203 {
155 CXType pointee_type = clang_getPointeeType(raw_type);204 CXType pointee_type = clang_getPointeeType(raw_type);
156 Buf *pointee_buf = to_zig_type(p, pointee_type);205 Buf *pointee_buf;
206 if (resolves_to_void(p, pointee_type)) {
207 pointee_buf = buf_create_from_str("u8");
208 } else {
209 pointee_buf = to_zig_type(p, pointee_type);
210 }
157 if (clang_isConstQualifiedType(pointee_type)) {211 if (clang_isConstQualifiedType(pointee_type)) {
158 return buf_sprintf("*const %s", buf_ptr(pointee_buf));212 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
159 } else {213 } else {
...@@ -192,7 +246,11 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {...@@ -192,7 +246,11 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {
192 } else {246 } else {
193 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);247 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
194 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);248 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
195 return to_zig_type(p, underlying_type);249 if (resolves_to_void(p, underlying_type)) {
250 return buf_create_from_str("u8");
251 } else {
252 return buf_create_from_str(name);
253 }
196 }254 }
197 }255 }
198 case CXType_ConstantArray:256 case CXType_ConstantArray:
...@@ -205,7 +263,7 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {...@@ -205,7 +263,7 @@ static Buf *to_zig_type(ParseH *p, CXType raw_type) {
205 case CXType_FunctionProto:263 case CXType_FunctionProto:
206 fprintf(stderr, "warning: TODO function proto\n");264 fprintf(stderr, "warning: TODO function proto\n");
207 print_location(p);265 print_location(p);
208 return buf_create_from_str("*const u8");266 return buf_create_from_str("u8");
209 case CXType_FunctionNoProto:267 case CXType_FunctionNoProto:
210 print_location(p);268 print_location(p);
211 zig_panic("TODO function no proto");269 zig_panic("TODO function no proto");
...@@ -277,6 +335,51 @@ static enum CXChildVisitResult visit_fn_children(CXCursor cursor, CXCursor paren...@@ -277,6 +335,51 @@ static enum CXChildVisitResult visit_fn_children(CXCursor cursor, CXCursor paren
277 }335 }
278}336}
279337
338static enum CXChildVisitResult visit_struct_children(CXCursor cursor, CXCursor parent, CXClientData client_data) {
339 ParseH *p = (ParseH*)client_data;
340 enum CXCursorKind kind = clang_getCursorKind(cursor);
341
342 switch (kind) {
343 case CXCursor_FieldDecl:
344 {
345 assert(p->cur_struct);
346 CXString name = clang_getCursorSpelling(cursor);
347 Field *field = allocate<Field>(1);
348 buf_init_from_str(&field->name, clang_getCString(name));
349 CXType cursor_type = clang_getCursorType(cursor);
350 field->type = to_zig_type(p, cursor_type);
351
352 p->cur_struct->fields.append(field);
353
354 return CXChildVisit_Continue;
355 }
356 default:
357 return CXChildVisit_Recurse;
358 }
359}
360
361static bool handle_struct_cursor(ParseH *p, CXCursor cursor, const char *name, bool expect_name) {
362 p->cur_struct = allocate<Struct>(1);
363
364 buf_init_from_str(&p->cur_struct->name, name);
365
366 bool got_name = (buf_len(&p->cur_struct->name) != 0);
367 if (expect_name != got_name)
368 return false;
369
370 clang_visitChildren(cursor, visit_struct_children, p);
371
372 if (p->cur_struct->fields.length > 0) {
373 p->struct_list.append(p->cur_struct);
374 } else {
375 p->incomplete_struct_list.append(p->cur_struct);
376 }
377
378 p->cur_struct = nullptr;
379
380 return true;
381}
382
280383
281static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {384static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
282 ParseH *p = (ParseH*)client_data;385 ParseH *p = (ParseH*)client_data;
...@@ -306,7 +409,9 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl...@@ -306,7 +409,9 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
306 p->cur_fn->is_variadic = clang_isFunctionTypeVariadic(fn_type);409 p->cur_fn->is_variadic = clang_isFunctionTypeVariadic(fn_type);
307410
308 CXType return_type = clang_getResultType(fn_type);411 CXType return_type = clang_getResultType(fn_type);
309 p->cur_fn->return_type = to_zig_type(p, return_type);412 if (!resolves_to_void(p, return_type)) {
413 p->cur_fn->return_type = to_zig_type(p, return_type);
414 }
310415
311 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));416 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));
312417
...@@ -330,7 +435,44 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl...@@ -330,7 +435,44 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
330 case CXCursor_CompoundStmt:435 case CXCursor_CompoundStmt:
331 case CXCursor_FieldDecl:436 case CXCursor_FieldDecl:
332 case CXCursor_TypedefDecl:437 case CXCursor_TypedefDecl:
333 return CXChildVisit_Continue;438 {
439 CXType underlying_type = clang_getTypedefDeclUnderlyingType(cursor);
440
441 if (resolves_to_void(p, underlying_type)) {
442 return CXChildVisit_Continue;
443 }
444
445 if (underlying_type.kind == CXType_Unexposed) {
446 underlying_type = clang_getCanonicalType(underlying_type);
447 }
448 bool skip_typedef;
449 if (underlying_type.kind == CXType_Unexposed) {
450 fprintf(stderr, "warning: unexposed type\n");
451 print_location(p);
452 skip_typedef = true;
453 } else if (underlying_type.kind == CXType_Record) {
454 CXCursor decl_cursor = clang_getTypeDeclaration(underlying_type);
455 skip_typedef = handle_struct_cursor(p, decl_cursor, clang_getCString(name), false);
456 } else {
457 skip_typedef = false;
458 }
459
460 if (!skip_typedef) {
461 CXType typedef_type = clang_getCursorType(cursor);
462 TypeDef *type_def = allocate<TypeDef>(1);
463 buf_init_from_str(&type_def->alias, prefixes_stripped(typedef_type));
464 buf_init_from_buf(&type_def->target, to_zig_type(p, underlying_type));
465 p->type_def_list.append(type_def);
466 }
467
468 return CXChildVisit_Continue;
469 }
470 case CXCursor_StructDecl:
471 {
472 handle_struct_cursor(p, cursor, clang_getCString(name), true);
473
474 return CXChildVisit_Continue;
475 }
334 default:476 default:
335 return CXChildVisit_Recurse;477 return CXChildVisit_Recurse;
336 }478 }
...@@ -401,6 +543,44 @@ void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FI...@@ -401,6 +543,44 @@ void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FI
401 CXCursor cursor = clang_getTranslationUnitCursor(p->tu);543 CXCursor cursor = clang_getTranslationUnitCursor(p->tu);
402 clang_visitChildren(cursor, fn_visitor, p);544 clang_visitChildren(cursor, fn_visitor, p);
403545
546 for (int struct_i = 0; struct_i < p->struct_list.length; struct_i += 1) {
547 Struct *struc = p->struct_list.at(struct_i);
548 fprintf(f, "struct %s {\n", buf_ptr(&struc->name));
549 p->cur_indent += indent_size;
550 for (int field_i = 0; field_i < struc->fields.length; field_i += 1) {
551 Field *field = struc->fields.at(field_i);
552 print_indent(p);
553 fprintf(f, "%s: %s,\n", buf_ptr(&field->name), buf_ptr(field->type));
554 }
555
556 p->cur_indent -= indent_size;
557 fprintf(f, "}\n\n");
558 }
559
560 int total_typedef_count = p->type_def_list.length;
561 for (int i = 0; i < p->incomplete_struct_list.length; i += 1) {
562 Struct *struc = p->incomplete_struct_list.at(i);
563 struc->have_def = have_struct_def(p, &struc->name);
564 total_typedef_count += (int)!struc->have_def;
565 }
566
567 if (total_typedef_count) {
568 for (int i = 0; i < p->incomplete_struct_list.length; i += 1) {
569 Struct *struc = p->incomplete_struct_list.at(i);
570 if (struc->have_def)
571 continue;
572
573 fprintf(f, "struct %s;\n", buf_ptr(&struc->name));
574 }
575
576 for (int type_def_i = 0; type_def_i < p->type_def_list.length; type_def_i += 1) {
577 TypeDef *type_def = p->type_def_list.at(type_def_i);
578 fprintf(f, "type %s = %s;\n", buf_ptr(&type_def->alias), buf_ptr(&type_def->target));
579 }
580
581 fprintf(f, "\n");
582 }
583
404 if (p->fn_list.length) {584 if (p->fn_list.length) {
405 fprintf(f, "extern {\n");585 fprintf(f, "extern {\n");
406 p->cur_indent += indent_size;586 p->cur_indent += indent_size;
...@@ -419,11 +599,12 @@ void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FI...@@ -419,11 +599,12 @@ void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FI
419 fprintf(p->f, "...");599 fprintf(p->f, "...");
420 }600 }
421 fprintf(p->f, ")");601 fprintf(p->f, ")");
422 if (!buf_eql_str(fn->return_type, "void")) {602 if (fn->return_type) {
423 fprintf(p->f, " -> %s", buf_ptr(fn->return_type));603 fprintf(p->f, " -> %s", buf_ptr(fn->return_type));
424 }604 }
425 fprintf(p->f, ";\n");605 fprintf(p->f, ";\n");
426 }606 }
607 p->cur_indent -= indent_size;
427 fprintf(f, "}\n");608 fprintf(f, "}\n");
428 }609 }
429}610}