authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-03 15:59:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-03 16:00:14-07:00
logad3f98c615e688387c2d3580321ab17965b21378
tree41d6b7c5cee74b53fe112bbd1d7726925028f610
parent174e58a05f94eaee6e04e858d916d28d3f5be3b7

parseh command, parses a C .h file and produces extern decls


6 files changed, 502 insertions(+), 82 deletions(-)

CMakeLists.txt+5
...@@ -16,6 +16,9 @@ find_package(llvm)...@@ -16,6 +16,9 @@ find_package(llvm)
16include_directories(${LLVM_INCLUDE_DIRS})16include_directories(${LLVM_INCLUDE_DIRS})
17link_directories(${LLVM_LIBDIRS})17link_directories(${LLVM_LIBDIRS})
1818
19find_package(clang)
20include_directories(${CLANG_INCLUDE_DIR})
21
19include_directories(22include_directories(
20 ${CMAKE_SOURCE_DIR}23 ${CMAKE_SOURCE_DIR}
21 ${CMAKE_BINARY_DIR}24 ${CMAKE_BINARY_DIR}
...@@ -33,6 +36,7 @@ set(ZIG_SOURCES...@@ -33,6 +36,7 @@ set(ZIG_SOURCES
33 "${CMAKE_SOURCE_DIR}/src/util.cpp"36 "${CMAKE_SOURCE_DIR}/src/util.cpp"
34 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"37 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
35 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"38 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
39 "${CMAKE_SOURCE_DIR}/src/parseh.cpp"
36)40)
3741
38set(TEST_SOURCES42set(TEST_SOURCES
...@@ -64,6 +68,7 @@ set_target_properties(zig PROPERTIES...@@ -64,6 +68,7 @@ set_target_properties(zig PROPERTIES
64 COMPILE_FLAGS ${EXE_CFLAGS})68 COMPILE_FLAGS ${EXE_CFLAGS})
65target_link_libraries(zig LINK_PUBLIC69target_link_libraries(zig LINK_PUBLIC
66 ${LLVM_LIBRARIES}70 ${LLVM_LIBRARIES}
71 ${CLANG_LIBRARY}
67)72)
68install(TARGETS zig DESTINATION bin)73install(TARGETS zig DESTINATION bin)
6974
cmake/Findclang.cmake created+16
...@@ -0,0 +1,16 @@
1# Copyright (c) 2015 Andrew Kelley
2# This file is MIT licensed.
3# See http://opensource.org/licenses/MIT
4
5# CLANG_FOUND
6# CLANG_INCLUDE_DIR
7# CLANG_LIBRARY
8
9find_path(CLANG_INCLUDE_DIR NAMES clang-c/Index.h)
10
11find_library(CLANG_LIBRARY NAMES clang)
12
13include(FindPackageHandleStandardArgs)
14find_package_handle_standard_args(CLANG DEFAULT_MSG CLANG_LIBRARY CLANG_INCLUDE_DIR)
15
16mark_as_advanced(CLANG_INCLUDE_DIR CLANG_LIBRARY)
src/buffer.hpp+6
...@@ -59,6 +59,7 @@ static inline void buf_deinit(Buf *buf) {...@@ -59,6 +59,7 @@ static inline void buf_deinit(Buf *buf) {
59}59}
6060
61static inline void buf_init_from_mem(Buf *buf, const char *ptr, int len) {61static inline void buf_init_from_mem(Buf *buf, const char *ptr, int len) {
62 assert(len >= 0);
62 buf->list.resize(len + 1);63 buf->list.resize(len + 1);
63 memcpy(buf_ptr(buf), ptr, len);64 memcpy(buf_ptr(buf), ptr, len);
64 buf->list.at(buf_len(buf)) = 0;65 buf->list.at(buf_len(buf)) = 0;
...@@ -73,6 +74,7 @@ static inline void buf_init_from_buf(Buf *buf, Buf *other) {...@@ -73,6 +74,7 @@ static inline void buf_init_from_buf(Buf *buf, Buf *other) {
73}74}
7475
75static inline Buf *buf_create_from_mem(const char *ptr, int len) {76static inline Buf *buf_create_from_mem(const char *ptr, int len) {
77 assert(len >= 0);
76 Buf *buf = allocate<Buf>(1);78 Buf *buf = allocate<Buf>(1);
77 buf_init_from_mem(buf, ptr, len);79 buf_init_from_mem(buf, ptr, len);
78 return buf;80 return buf;
...@@ -82,6 +84,10 @@ static inline Buf *buf_create_from_str(const char *str) {...@@ -82,6 +84,10 @@ static inline Buf *buf_create_from_str(const char *str) {
82 return buf_create_from_mem(str, strlen(str));84 return buf_create_from_mem(str, strlen(str));
83}85}
8486
87static inline Buf *buf_create_from_buf(Buf *buf) {
88 return buf_create_from_mem(buf_ptr(buf), buf_len(buf));
89}
90
85static inline Buf *buf_slice(Buf *in_buf, int start, int end) {91static inline Buf *buf_slice(Buf *in_buf, int start, int end) {
86 assert(in_buf->list.length);92 assert(in_buf->list.length);
87 assert(start >= 0);93 assert(start >= 0);
src/main.cpp+106-82
...@@ -10,15 +10,17 @@...@@ -10,15 +10,17 @@
10#include "codegen.hpp"10#include "codegen.hpp"
11#include "os.hpp"11#include "os.hpp"
12#include "error.hpp"12#include "error.hpp"
13#include "parseh.hpp"
1314
14#include <stdio.h>15#include <stdio.h>
1516
16static int usage(const char *arg0) {17static int usage(const char *arg0) {
17 fprintf(stderr, "Usage: %s [command] [options] target\n"18 fprintf(stderr, "Usage: %s [command] [options]\n"
18 "Commands:\n"19 "Commands:\n"
19 " build create executable, object, or library from target\n"20 " build create executable, object, or library from target\n"
20 " version print version number and exit\n"21 " version print version number and exit\n"
21 "Optional Options:\n"22 " parseh convert a c header file to zig extern declarations\n"
23 "Command: build target\n"
22 " --release build with optimizations on and debug protection off\n"24 " --release build with optimizations on and debug protection off\n"
23 " --static output will be statically linked\n"25 " --static output will be statically linked\n"
24 " --strip exclude debug symbols\n"26 " --strip exclude debug symbols\n"
...@@ -27,11 +29,15 @@ static int usage(const char *arg0) {...@@ -27,11 +29,15 @@ static int usage(const char *arg0) {
27 " --output [file] override destination path\n"29 " --output [file] override destination path\n"
28 " --verbose turn on compiler debug output\n"30 " --verbose turn on compiler debug output\n"
29 " --color [auto|off|on] enable or disable colored error messages\n"31 " --color [auto|off|on] enable or disable colored error messages\n"
32 "Command: parseh target\n"
33 " -isystem [dir] add additional search path for other .h files\n"
34 " -dirafter [dir] same as -isystem but do it last\n"
35 " -B[prefix] set the C compiler data path\n"
30 , arg0);36 , arg0);
31 return EXIT_FAILURE;37 return EXIT_FAILURE;
32}38}
3339
34static int version(void) {40static int version(const char *arg0, int argc, char **argv) {
35 printf("%s\n", ZIG_VERSION_STRING);41 printf("%s\n", ZIG_VERSION_STRING);
36 return EXIT_SUCCESS;42 return EXIT_SUCCESS;
37}43}
...@@ -48,62 +54,11 @@ struct Build {...@@ -48,62 +54,11 @@ struct Build {
48 ErrColor color;54 ErrColor color;
49};55};
5056
51static int build(const char *arg0, Build *b) {57static int build(const char *arg0, int argc, char **argv) {
52 int err;58 int err;
53
54 if (!b->in_file)
55 return usage(arg0);
56
57 Buf in_file_buf = BUF_INIT;
58 buf_init_from_str(&in_file_buf, b->in_file);
59
60 Buf root_source_dir = BUF_INIT;
61 Buf root_source_code = BUF_INIT;
62 Buf root_source_name = BUF_INIT;
63 if (buf_eql_str(&in_file_buf, "-")) {
64 os_get_cwd(&root_source_dir);
65 if ((err = os_fetch_file(stdin, &root_source_code))) {
66 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
67 return 1;
68 }
69 buf_init_from_str(&root_source_name, "");
70 } else {
71 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
72 if ((err = os_fetch_file_path(buf_create_from_str(b->in_file), &root_source_code))) {
73 fprintf(stderr, "unable to open '%s': %s\n", b->in_file, err_str(err));
74 return 1;
75 }
76 }
77
78 CodeGen *g = codegen_create(&root_source_dir);
79 codegen_set_build_type(g, b->release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
80 codegen_set_strip(g, b->strip);
81 codegen_set_is_static(g, b->is_static);
82 if (b->out_type != OutTypeUnknown)
83 codegen_set_out_type(g, b->out_type);
84 if (b->out_name)
85 codegen_set_out_name(g, buf_create_from_str(b->out_name));
86 codegen_set_verbose(g, b->verbose);
87 codegen_set_errmsg_color(g, b->color);
88 codegen_add_root_code(g, &root_source_name, &root_source_code);
89 codegen_link(g, b->out_file);
90
91 return 0;
92}
93
94enum Cmd {
95 CmdNone,
96 CmdBuild,
97 CmdVersion,
98};
99
100int main(int argc, char **argv) {
101 char *arg0 = argv[0];
102
103 Build b = {0};59 Build b = {0};
104 Cmd cmd = CmdNone;
10560
106 for (int i = 1; i < argc; i += 1) {61 for (int i = 0; i < argc; i += 1) {
107 char *arg = argv[i];62 char *arg = argv[i];
108 if (arg[0] == '-' && arg[1] == '-') {63 if (arg[0] == '-' && arg[1] == '-') {
109 if (strcmp(arg, "--release") == 0) {64 if (strcmp(arg, "--release") == 0) {
...@@ -148,40 +103,109 @@ int main(int argc, char **argv) {...@@ -148,40 +103,109 @@ int main(int argc, char **argv) {
148 return usage(arg0);103 return usage(arg0);
149 }104 }
150 }105 }
151 } else if (cmd == CmdNone) {106 } else if (!b.in_file) {
152 if (strcmp(arg, "build") == 0) {107 b.in_file = arg;
153 cmd = CmdBuild;108 } else {
154 } else if (strcmp(arg, "version") == 0) {109 return usage(arg0);
155 cmd = CmdVersion;110 }
111 }
112
113 if (!b.in_file)
114 return usage(arg0);
115
116 Buf in_file_buf = BUF_INIT;
117 buf_init_from_str(&in_file_buf, b.in_file);
118
119 Buf root_source_dir = BUF_INIT;
120 Buf root_source_code = BUF_INIT;
121 Buf root_source_name = BUF_INIT;
122 if (buf_eql_str(&in_file_buf, "-")) {
123 os_get_cwd(&root_source_dir);
124 if ((err = os_fetch_file(stdin, &root_source_code))) {
125 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
126 return 1;
127 }
128 buf_init_from_str(&root_source_name, "");
129 } else {
130 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
131 if ((err = os_fetch_file_path(buf_create_from_str(b.in_file), &root_source_code))) {
132 fprintf(stderr, "unable to open '%s': %s\n", b.in_file, err_str(err));
133 return 1;
134 }
135 }
136
137 CodeGen *g = codegen_create(&root_source_dir);
138 codegen_set_build_type(g, b.release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
139 codegen_set_strip(g, b.strip);
140 codegen_set_is_static(g, b.is_static);
141 if (b.out_type != OutTypeUnknown)
142 codegen_set_out_type(g, b.out_type);
143 if (b.out_name)
144 codegen_set_out_name(g, buf_create_from_str(b.out_name));
145 codegen_set_verbose(g, b.verbose);
146 codegen_set_errmsg_color(g, b.color);
147 codegen_add_root_code(g, &root_source_name, &root_source_code);
148 codegen_link(g, b.out_file);
149
150 return 0;
151}
152
153static int parseh(const char *arg0, int argc, char **argv) {
154 char *in_file = nullptr;
155 ZigList<const char *> clang_argv = {0};
156 for (int i = 0; i < argc; i += 1) {
157 char *arg = argv[i];
158 if (arg[0] == '-') {
159 if (arg[1] == 'I') {
160 clang_argv.append(arg);
161 } else if (strcmp(arg, "-isystem") == 0) {
162 if (i + 1 >= argc) {
163 return usage(arg0);
164 }
165 clang_argv.append("-isystem");
166 clang_argv.append(argv[i + 1]);
167 } else if (arg[1] == 'B') {
168 clang_argv.append(arg);
156 } else {169 } else {
157 fprintf(stderr, "Unrecognized command: %s\n", arg);170 fprintf(stderr, "unrecognized argument: %s", arg);
158 return usage(arg0);171 return usage(arg0);
159 }172 }
173 } else if (!in_file) {
174 in_file = arg;
160 } else {175 } else {
161 switch (cmd) {176 return usage(arg0);
162 case CmdNone:
163 zig_unreachable();
164 case CmdBuild:
165 if (!b.in_file) {
166 b.in_file = arg;
167 } else {
168 return usage(arg0);
169 }
170 break;
171 case CmdVersion:
172 return usage(arg0);
173 }
174 }177 }
175 }178 }
179 if (!in_file) {
180 fprintf(stderr, "missing target argument");
181 return usage(arg0);
182 }
183
184 parse_h_file(in_file, &clang_argv, stdout);
185 return 0;
186}
176187
177 switch (cmd) {188int main(int argc, char **argv) {
178 case CmdNone:189 char *arg0 = argv[0];
190 int (*cmd)(const char *, int, char **) = nullptr;
191 for (int i = 1; i < argc; i += 1) {
192 char *arg = argv[i];
193 if (arg[0] == '-' && arg[1] == '-') {
179 return usage(arg0);194 return usage(arg0);
180 case CmdBuild:195 } else {
181 return build(arg0, &b);196 if (strcmp(arg, "build") == 0) {
182 case CmdVersion:197 cmd = build;
183 return version();198 } else if (strcmp(arg, "version") == 0) {
199 cmd = version;
200 } else if (strcmp(arg, "parseh") == 0) {
201 cmd = parseh;
202 } else {
203 fprintf(stderr, "Unrecognized command: %s\n", arg);
204 return usage(arg0);
205 }
206 return cmd(arg0, argc - i - 1, &argv[i + 1]);
207 }
184 }208 }
185209
186 zig_unreachable();210 return usage(arg0);
187}211}
src/parseh.cpp created+351
...@@ -0,0 +1,351 @@
1#include "parseh.hpp"
2
3#include <clang-c/Index.h>
4
5#include <string.h>
6
7struct Arg {
8 Buf name;
9 Buf *type;
10};
11
12struct Fn {
13 Buf name;
14 Buf *return_type;
15 Arg *args;
16 int arg_count;
17};
18
19struct ParseH {
20 FILE *f;
21 ZigList<Fn *> fn_list;
22 Fn *cur_fn;
23 int arg_index;
24 int cur_indent;
25};
26
27static const int indent_size = 4;
28
29static bool str_has_prefix(const char *str, const char *prefix) {
30 while (*prefix) {
31 if (*str && *str == *prefix) {
32 str += 1;
33 prefix += 1;
34 } else {
35 return false;
36 }
37 }
38 return true;
39}
40
41static const char *prefixes_stripped(CXType type) {
42 CXString name = clang_getTypeSpelling(type);
43 const char *c_name = clang_getCString(name);
44
45 static const char *prefixes[] = {
46 "struct ",
47 "enum ",
48 "const ",
49 };
50
51start_over:
52
53 for (int i = 0; i < array_length(prefixes); i += 1) {
54 const char *prefix = prefixes[i];
55 if (str_has_prefix(c_name, prefix)) {
56 c_name += strlen(prefix);
57 goto start_over;
58 }
59 }
60 return c_name;
61}
62
63static Buf *to_zig_type(CXType raw_type) {
64 CXType canonical = clang_getCanonicalType(raw_type);
65 switch (canonical.kind) {
66 case CXType_Invalid:
67 zig_unreachable();
68 case CXType_Unexposed:
69 zig_panic("clang C api insufficient");
70 case CXType_Void:
71 return buf_create_from_str("void");
72 case CXType_Bool:
73 return buf_create_from_str("bool");
74 case CXType_SChar:
75 return buf_create_from_str("i8");
76 case CXType_Char_U:
77 case CXType_Char_S:
78 case CXType_UChar:
79 return buf_create_from_str("u8");
80 case CXType_WChar:
81 zig_panic("TODO");
82 case CXType_Char16:
83 zig_panic("TODO");
84 case CXType_Char32:
85 zig_panic("TODO");
86 case CXType_UShort:
87 return buf_create_from_str("c_ushort");
88 case CXType_UInt:
89 return buf_create_from_str("c_uint");
90 case CXType_ULong:
91 return buf_create_from_str("c_ulong");
92 case CXType_ULongLong:
93 return buf_create_from_str("c_ulonglong");
94 case CXType_UInt128:
95 zig_panic("TODO");
96 case CXType_Short:
97 return buf_create_from_str("c_short");
98 case CXType_Int:
99 return buf_create_from_str("c_int");
100 case CXType_Long:
101 return buf_create_from_str("c_long");
102 case CXType_LongLong:
103 return buf_create_from_str("c_longlong");
104 case CXType_Int128:
105 zig_panic("TODO");
106 case CXType_Float:
107 return buf_create_from_str("f32");
108 case CXType_Double:
109 return buf_create_from_str("f64");
110 case CXType_LongDouble:
111 return buf_create_from_str("f128");
112 case CXType_NullPtr:
113 zig_panic("TODO");
114 case CXType_Overload:
115 zig_panic("TODO");
116 case CXType_Dependent:
117 zig_panic("TODO");
118 case CXType_ObjCId:
119 zig_panic("TODO");
120 case CXType_ObjCClass:
121 zig_panic("TODO");
122 case CXType_ObjCSel:
123 zig_panic("TODO");
124 case CXType_Complex:
125 zig_panic("TODO");
126 case CXType_Pointer:
127 {
128 CXType pointee_type = clang_getPointeeType(canonical);
129 Buf *pointee_buf = to_zig_type(pointee_type);
130 if (clang_isConstQualifiedType(pointee_type)) {
131 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
132 } else {
133 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));
134 }
135 }
136 case CXType_BlockPointer:
137 zig_panic("TODO");
138 case CXType_LValueReference:
139 zig_panic("TODO");
140 case CXType_RValueReference:
141 zig_panic("TODO");
142 case CXType_Record:
143 {
144 const char *name = prefixes_stripped(canonical);
145 return buf_sprintf("%s", name);
146 }
147 case CXType_Enum:
148 {
149 const char *name = prefixes_stripped(canonical);
150 return buf_sprintf("%s", name);
151 }
152 case CXType_Typedef:
153 zig_panic("TODO");
154 case CXType_ObjCInterface:
155 zig_panic("TODO");
156 case CXType_ObjCObjectPointer:
157 zig_panic("TODO");
158 case CXType_FunctionNoProto:
159 zig_panic("TODO");
160 case CXType_FunctionProto:
161 zig_panic("TODO");
162 case CXType_ConstantArray:
163 zig_panic("TODO");
164 case CXType_Vector:
165 zig_panic("TODO");
166 case CXType_IncompleteArray:
167 zig_panic("TODO");
168 case CXType_VariableArray:
169 zig_panic("TODO");
170 case CXType_DependentSizedArray:
171 zig_panic("TODO");
172 case CXType_MemberPointer:
173 zig_panic("TODO");
174 }
175
176 zig_unreachable();
177}
178
179static bool is_storage_class_export(CX_StorageClass storage_class) {
180 switch (storage_class) {
181 case CX_SC_Invalid:
182 zig_unreachable();
183 case CX_SC_None:
184 case CX_SC_Extern:
185 case CX_SC_Auto:
186 return true;
187 case CX_SC_Static:
188 case CX_SC_PrivateExtern:
189 case CX_SC_OpenCLWorkGroupLocal:
190 case CX_SC_Register:
191 return false;
192 }
193 zig_unreachable();
194}
195
196static void begin_fn(ParseH *p) {
197 assert(!p->cur_fn);
198 p->cur_fn = allocate<Fn>(1);
199}
200
201static void end_fn(ParseH *p) {
202 if (p->cur_fn) {
203 p->fn_list.append(p->cur_fn);
204 p->cur_fn = nullptr;
205 }
206}
207
208static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
209 ParseH *p = (ParseH*)client_data;
210 enum CXCursorKind kind = clang_getCursorKind(cursor);
211 CXString name = clang_getCursorSpelling(cursor);
212
213 switch (kind) {
214 case CXCursor_FunctionDecl:
215 {
216 CX_StorageClass storage_class = clang_Cursor_getStorageClass(cursor);
217 if (!is_storage_class_export(storage_class))
218 return CXChildVisit_Continue;
219
220 end_fn(p);
221 begin_fn(p);
222
223 CXType fn_type = clang_getCursorType(cursor);
224 if (clang_isFunctionTypeVariadic(fn_type)) {
225 zig_panic("TODO support variadic function");
226 }
227 if (clang_getFunctionTypeCallingConv(fn_type) != CXCallingConv_C) {
228 zig_panic("TODO support non c calling convention");
229 }
230 CXType return_type = clang_getResultType(fn_type);
231 p->cur_fn->return_type = to_zig_type(return_type);
232
233 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));
234
235 p->cur_fn->arg_count = clang_getNumArgTypes(fn_type);
236 p->cur_fn->args = allocate<Arg>(p->cur_fn->arg_count);
237
238 for (int i = 0; i < p->cur_fn->arg_count; i += 1) {
239 CXType param_type = clang_getArgType(fn_type, i);
240 p->cur_fn->args[i].type = to_zig_type(param_type);
241 }
242
243 p->arg_index = 0;
244
245 return CXChildVisit_Recurse;
246 }
247 case CXCursor_ParmDecl:
248 {
249 assert(p->cur_fn);
250 assert(p->arg_index < p->cur_fn->arg_count);
251 buf_init_from_str(&p->cur_fn->args[p->arg_index].name, clang_getCString(name));
252 p->arg_index += 1;
253 return CXChildVisit_Continue;
254 }
255 case CXCursor_UnexposedAttr:
256 case CXCursor_CompoundStmt:
257 case CXCursor_FieldDecl:
258 return CXChildVisit_Continue;
259 default:
260 return CXChildVisit_Recurse;
261 }
262}
263
264static void print_indent(ParseH *p) {
265 for (int i = 0; i < p->cur_indent; i += 1) {
266 fprintf(p->f, " ");
267 }
268}
269
270void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FILE *f) {
271 ParseH parse_h = {0};
272 ParseH *p = &parse_h;
273 p->f = f;
274 CXTranslationUnit tu;
275 CXIndex index = clang_createIndex(1, 0);
276
277 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
278 if (ZIG_PARSEH_CFLAGS) {
279 Buf tmp_buf = {0};
280 char *start = ZIG_PARSEH_CFLAGS;
281 char *space = strstr(start, " ");
282 while (space) {
283 if (space - start > 0) {
284 buf_init_from_mem(&tmp_buf, start, space - start);
285 clang_argv->append(buf_ptr(buf_create_from_buf(&tmp_buf)));
286 }
287 start = space + 1;
288 space = strstr(start, " ");
289 }
290 buf_init_from_str(&tmp_buf, start);
291 clang_argv->append(buf_ptr(buf_create_from_buf(&tmp_buf)));
292 }
293
294 clang_argv->append(nullptr);
295
296 enum CXErrorCode err_code;
297 if ((err_code = clang_parseTranslationUnit2(index, target_path,
298 clang_argv->items, clang_argv->length - 1,
299 NULL, 0, CXTranslationUnit_None, &tu)))
300 {
301 zig_panic("parse translation unit failure");
302 }
303
304
305 unsigned diag_count = clang_getNumDiagnostics(tu);
306
307 if (diag_count > 0) {
308 for (unsigned i = 0; i < diag_count; i += 1) {
309 CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);
310 CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);
311
312 CXFile file;
313 unsigned line, column, offset;
314 clang_getSpellingLocation(location, &file, &line, &column, &offset);
315 CXString text = clang_getDiagnosticSpelling(diagnostic);
316 CXString file_name = clang_getFileName(file);
317 fprintf(stderr, "%s line %u, column %u: %s\n", clang_getCString(file_name),
318 line, column, clang_getCString(text));
319 }
320
321 exit(1);
322 }
323
324
325 CXCursor cursor = clang_getTranslationUnitCursor(tu);
326 clang_visitChildren(cursor, fn_visitor, p);
327 end_fn(p);
328
329 if (p->fn_list.length) {
330 fprintf(f, "extern {\n");
331 p->cur_indent += indent_size;
332 for (int fn_i = 0; fn_i < p->fn_list.length; fn_i += 1) {
333 Fn *fn = p->fn_list.at(fn_i);
334 print_indent(p);
335 fprintf(p->f, "fn %s(", buf_ptr(&fn->name));
336 for (int arg_i = 0; arg_i < fn->arg_count; arg_i += 1) {
337 Arg *arg = &fn->args[arg_i];
338 fprintf(p->f, "%s: %s", buf_ptr(&arg->name), buf_ptr(arg->type));
339 if (arg_i + 1 < fn->arg_count) {
340 fprintf(p->f, ", ");
341 }
342 }
343 fprintf(p->f, ")");
344 if (!buf_eql_str(fn->return_type, "void")) {
345 fprintf(p->f, " -> %s", buf_ptr(fn->return_type));
346 }
347 fprintf(p->f, ";\n");
348 }
349 fprintf(f, "}\n");
350 }
351}
src/parseh.hpp created+18
...@@ -0,0 +1,18 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8
9#ifndef ZIG_PARSEH_HPP
10#define ZIG_PARSEH_HPP
11
12#include "buffer.hpp"
13
14#include <stdio.h>
15
16void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FILE *f);
17
18#endif