v4 / vlib / v / gen / c / cheaders_manual_stdlib_decls_test.v
303 lines · 281 sloc · 21.93 KB · cef604a26a2dce90ca65f4a13a68a8e7598b7e00
Raw
1import os
2
3const cheaders_manual_stdlib_vexe = @VEXE
4
5const cheaders_manual_stdlib_vroot = os.real_path(@VMODROOT)
6
7const cheaders_manual_stdlib_varargs_source = os.join_path(cheaders_manual_stdlib_vroot,
8 'vlib/v/gen/c/testdata/c_varargs.vv')
9
10const cheaders_manual_stdlib_stdio_source = os.join_path(cheaders_manual_stdlib_vroot,
11 'vlib/v/tests/c_shadowed_c_fn_call_test.v')
12
13fn test_default_c_prelude_uses_manual_stdio_stdlib_string_and_stdarg_decls() {
14 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o - ${os.quoted_path(cheaders_manual_stdlib_varargs_source)}'
15 res := os.execute(cmd)
16 assert res.exit_code == 0, '${cmd}\n${res.output}'
17 generated_c := res.output.replace('\r\n', '\n')
18 assert generated_c.contains('typedef struct _iobuf FILE;'), generated_c
19 assert generated_c.contains('typedef struct __sFILE FILE;'), generated_c
20 assert generated_c.contains('typedef struct _IO_FILE FILE;'), generated_c
21 assert generated_c.contains('typedef __builtin_va_list va_list;'), generated_c
22 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL vfprintf(FILE *stream, const char *format, va_list ap);'), generated_c
23
24 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL vsnprintf(char *str, size_t size, const char *format, va_list ap);'), generated_c
25 assert generated_c.contains('#if defined(_WIN32) || defined(_WIN64)\nV_CRT_LINKAGE int V_CRT_CALL _fileno(FILE *stream);\nV_CRT_LINKAGE FILE * V_CRT_CALL _wfopen(const unsigned short *filename, const unsigned short *mode);\nV_CRT_LINKAGE int V_CRT_CALL _wremove(const unsigned short *path);\nV_CRT_LINKAGE void * V_CRT_CALL _aligned_malloc(size_t size, size_t alignment);\nV_CRT_LINKAGE void * V_CRT_CALL _aligned_realloc(void *memory, size_t size, size_t alignment);\nV_CRT_LINKAGE void V_CRT_CALL _aligned_free(void *memory);\nV_CRT_LINKAGE unsigned short * V_CRT_CALL _wgetenv(const unsigned short *varname);\nV_CRT_LINKAGE int V_CRT_CALL _wputenv(const unsigned short *envstring);\n#endif'), generated_c
26
27 assert generated_c.contains('V_CRT_LINKAGE void V_CRT_CALL perror(const char *str);'), generated_c
28 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL mkstemp(char *stemplate);'), generated_c
29 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL strcmp(const char *left, const char *right);'), generated_c
30 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL strncmp(const char *left, const char *right, size_t n);'), generated_c
31 assert generated_c.contains('V_CRT_LINKAGE char * V_CRT_CALL strstr(const char *haystack, const char *needle);'), generated_c
32 assert generated_c.contains('#if !defined(_WIN32) && !defined(_WIN64) && !defined(__BIONIC__)'), generated_c
33 assert generated_c.contains('V_CRT_LINKAGE char * V_CRT_CALL strdup(const char *str);'), generated_c
34 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL rand(void);'), generated_c
35 assert generated_c.contains('V_CRT_LINKAGE void V_CRT_CALL srand(unsigned int seed);'), generated_c
36 assert generated_c.contains('RAND_MAX = 2147483647'), generated_c
37 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL abs(int n);'), generated_c
38 assert generated_c.contains('V_CRT_LINKAGE double V_CRT_CALL atof(const char *str);'), generated_c
39 assert generated_c.contains('extern FILE* stdout;'), generated_c
40 assert generated_c.contains('#define stdout (__acrt_iob_func(1))'), generated_c
41 assert generated_c.contains('#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus)\n// Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep\n// noexcept specifiers consistent'), generated_c
42 assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n\t#define V_CRT_LINKAGE __declspec(dllimport)\n\t#define V_CRT_CALL VCALLCONV(cdecl)\n#else\n\t#define V_CRT_LINKAGE\n\t#define V_CRT_CALL\n#endif'), generated_c
43 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);'), generated_c
44 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap);'), generated_c
45 assert generated_c.contains('V_CRT_LINKAGE void * V_CRT_CALL _aligned_malloc(size_t size, size_t alignment);'), generated_c
46 assert generated_c.contains('V_CRT_LINKAGE void * V_CRT_CALL _aligned_realloc(void *memory, size_t size, size_t alignment);'), generated_c
47 assert generated_c.contains('V_CRT_LINKAGE void V_CRT_CALL _aligned_free(void *memory);'), generated_c
48 assert generated_c.contains('V_CRT_LINKAGE unsigned short * V_CRT_CALL _wgetenv(const unsigned short *varname);'), generated_c
49 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _wputenv(const unsigned short *envstring);'), generated_c
50 assert generated_c.contains('#elif (defined(__MINGW32__) || defined(__MINGW64__)) && defined(__V_GCC__)\n// mingw-w64 stdio.h provides fprintf/vfprintf as static inline overrides\n// when __USE_MINGW_ANSI_STDIO is enabled, so use the system declarations\n// instead of the manual formatted-stdio prototypes below.\n#include <stdarg.h>\n#include <stdio.h>\n#elif defined(__MINGW32__) || defined(__MINGW64__) || (defined(__clang__) && (defined(_WIN32) || defined(_WIN64)))'), generated_c
51 assert generated_c.contains('#elif defined(__MINGW32__) || defined(__MINGW64__) || (defined(__clang__) && (defined(_WIN32) || defined(_WIN64)))\ntypedef struct _iobuf FILE;\nFILE* __cdecl __acrt_iob_func(unsigned index);\n#define stdin (__acrt_iob_func(0))\n#define stdout (__acrt_iob_func(1))\n#define stderr (__acrt_iob_func(2))'), generated_c
52 assert generated_c.contains('#elif defined(__TINYC__) && (defined(_WIN32) || defined(_WIN64))'), generated_c
53 assert generated_c.contains('#ifndef _FILE_DEFINED\nstruct _iobuf {\n\tchar *_ptr;\n\tint _cnt;\n\tchar *_base;\n\tint _flag;\n\tint _file;\n\tint _charbuf;\n\tint _bufsiz;\n\tchar *_tmpfname;\n};\ntypedef struct _iobuf FILE;\n#define _FILE_DEFINED'), generated_c
54 assert generated_c.contains('FILE* __cdecl __iob_func(void);'), generated_c
55 assert generated_c.contains('extern FILE (*_imp___iob)[];'), generated_c
56 assert generated_c.contains('#define stdout (&__iob_func()[1])'), generated_c
57 assert generated_c.contains('#elif defined(__vinix__)\ntypedef struct __file FILE;\nextern FILE* stdin;\nextern FILE* stdout;\nextern FILE* stderr;\nstruct __thread_data;\nstruct __threadattr;'), generated_c
58 assert generated_c.contains('#if defined(__STDC_HOSTED__) && __STDC_HOSTED__ && defined(__has_include) && __has_include(<pthread.h>)\n#include <pthread.h>\n#else\ntypedef struct __thread_data *pthread_t;\n#endif\ntypedef __builtin_va_list va_list;'), generated_c
59 assert generated_c.contains('#if defined(__APPLE__) || defined(__FreeBSD__)\ntypedef struct __sFILE FILE;\nextern FILE* __stdinp;\nextern FILE* __stdoutp;\nextern FILE* __stderrp;\n#define stdin __stdinp\n#define stdout __stdoutp\n#define stderr __stderrp'), generated_c
60 assert generated_c.contains('#elif defined(__DragonFly__)\ntypedef struct __sFILE FILE;\nextern FILE* __stdinp;\nextern FILE* __stdoutp;\nextern FILE* __stderrp;\n#define stdin __stdinp\n#define stdout __stdoutp\n#define stderr __stderrp'), generated_c
61 assert generated_c.contains('#elif defined(__NetBSD__)\n// NetBSD exposes stdin/stdout/stderr as macros into a single `__sF[3]`\n// array whose element size (sizeof(FILE)) depends on the platform and libc\n// version, so we cannot forward-declare them. The FreeBSD-style\n// `__stdinp/__stdoutp/__stderrp` symbols also do not exist on NetBSD (see\n// vlang/v#27190). Defer to the system headers for FILE, the stdio streams,\n// and the libc prototypes that would otherwise clash with the\n// `__restrict`-qualified declarations in NetBSD libc.\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>'), generated_c
62 assert generated_c.contains('#elif defined(__TINYC__) && (defined(__FreeBSD__) || defined(__OpenBSD__))\n// TinyCC reports a hard redefinition error if system OpenSSL pulls in\n// <stdarg.h> after V has provided its own va_start macro. Include it first,\n// but keep V manual FILE declarations on these BSD libc variants.\n#include <stdarg.h>\n#if defined(__FreeBSD__)\ntypedef struct __sFILE FILE;\nextern FILE* __stdinp;\nextern FILE* __stdoutp;\nextern FILE* __stderrp;\n#define stdin __stdinp\n#define stdout __stdoutp\n#define stderr __stderrp'), generated_c
63 assert generated_c.contains('#else\ntypedef struct __sFILE FILE;\n#ifndef _STDFILES_DECLARED\n\t#define _STDFILES_DECLARED\nstruct __sFstub { long _stub; };\nextern struct __sFstub __stdin[];\nextern struct __sFstub __stdout[];\nextern struct __sFstub __stderr[];\n#endif\n#define stdin ((struct __sFILE *)__stdin)\n#define stdout ((struct __sFILE *)__stdout)\n#define stderr ((struct __sFILE *)__stderr)\n#endif\n#elif (defined(__MINGW32__) || defined(__MINGW64__)) && defined(__V_GCC__)'), generated_c
64 assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus) && !defined(__NetBSD__)'), generated_c
65 assert generated_c.contains('#elif defined(__OpenBSD__)\ntypedef struct __sFILE FILE;\n#ifndef _STDFILES_DECLARED\n\t#define _STDFILES_DECLARED\nstruct __sFstub { long _stub; };\nextern struct __sFstub __stdin[];\nextern struct __sFstub __stdout[];\nextern struct __sFstub __stderr[];\n#endif\n#define stdin ((struct __sFILE *)__stdin)\n#define stdout ((struct __sFILE *)__stdout)\n#define stderr ((struct __sFILE *)__stderr)'), generated_c
66 assert generated_c.contains('#elif defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU_LIBRARY__) && !defined(__BIONIC__) && !defined(__UCLIBC__)\ntypedef struct _IO_FILE FILE;\n// musl exposes the stdio streams as `FILE *const`, so match that to stay\n// compatible with later <stdio.h> includes from headers like miniz.h.\nextern FILE* const stdin;\nextern FILE* const stdout;\nextern FILE* const stderr'), generated_c
67 assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)'), generated_c
68 assert generated_c.contains('#if defined(__vinix__)\nV_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, size_t size, FILE *stream);\n#else\nV_CRT_LINKAGE char * V_CRT_CALL fgets(char *str, int size, FILE *stream);'), generated_c
69 assert generated_c.contains('#if defined(__vinix__)\nV_CRT_LINKAGE int V_CRT_CALL strcmp(char *left, char *right);\nV_CRT_LINKAGE int V_CRT_CALL strncmp(char *left, char *right, size_t n);\n#else\nV_CRT_LINKAGE int V_CRT_CALL strcmp(const char *left, const char *right);'), generated_c
70}
71
72fn test_android_prelude_uses_bionic_file_decls() {
73 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_android_${os.getpid()}')
74 os.mkdir_all(tmp_dir)!
75 defer {
76 os.rmdir_all(tmp_dir) or {}
77 }
78 source_path := os.join_path(tmp_dir, 'android.v')
79 output_path := os.join_path(tmp_dir, 'android.c')
80 os.write_file(source_path, 'fn main() {\n\tprintln("hi")\n}\n')!
81 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -os android -apk -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
82 res := os.execute(cmd)
83 assert res.exit_code == 0, '${cmd}\n${res.output}'
84 generated_c := os.read_file(output_path)!.replace('\r\n', '\n')
85 assert generated_c.contains('#elif defined(__BIONIC__)\nstruct __sFILE;\ntypedef struct __sFILE FILE;\nextern FILE* stdin;\nextern FILE* stdout;\nextern FILE* stderr;'), generated_c
86 assert !generated_c.contains('extern FILE __sF[];'), generated_c
87 assert !generated_c.contains('#elif defined(__BIONIC__)\ntypedef struct _IO_FILE FILE;'), generated_c
88}
89
90fn test_vinix_prelude_leaves_stdio_and_stdlib_to_vinix_stubs() {
91 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_vinix_${os.getpid()}')
92 os.mkdir_all(tmp_dir)!
93 defer {
94 os.rmdir_all(tmp_dir) or {}
95 }
96 source_path := os.join_path(tmp_dir, 'vinix.v')
97 output_path := os.join_path(tmp_dir, 'vinix.c')
98 os.write_file(source_path,
99 ['fn C.printf_panic(charptr, ...voidptr)', 'fn C.text_start()', 'fn C.__builtin_return_address(int) voidptr', '', 'fn main() {', "\tC.printf_panic(c'%d', voidptr(1))", '\t_ = voidptr(C.text_start)', '\t_ = C.__builtin_return_address(0)', '}'].join('\n') +
100 '\n')!
101 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -os vinix -d no_backtrace -gc none -manualfree -enable-globals -nofloat -experimental -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
102 res := os.execute(cmd)
103 assert res.exit_code == 0, '${cmd}\n${res.output}'
104 generated_c := os.read_file(output_path)!.replace('\r\n', '\n')
105 assert generated_c.contains('#elif defined(__vinix__)\ntypedef struct __file FILE;\nextern FILE* stdin;\nextern FILE* stdout;\nextern FILE* stderr;\nstruct __thread_data;\nstruct __threadattr;'), generated_c
106 assert generated_c.contains('#if defined(__STDC_HOSTED__) && __STDC_HOSTED__ && defined(__has_include) && __has_include(<pthread.h>)\n#include <pthread.h>\n#else\ntypedef struct __thread_data *pthread_t;\n#endif\ntypedef __builtin_va_list va_list;'), generated_c
107 assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)'), generated_c
108 assert generated_c.contains('extern void printf_panic(charptr _d1, ... );'), generated_c
109 assert !generated_c.contains('extern void printf_panic(charptr _d1, Array_voidptr _d2);'), generated_c
110 assert !generated_c.contains('extern void text_start();'), generated_c
111 assert !generated_c.contains('extern voidptr __builtin_return_address(int _d1);'), generated_c
112 assert !generated_c.contains('builtin__unbuffer_stdout();'), generated_c
113}
114
115fn test_msvc_windows_prelude_uses_msvc_crt_headers() {
116 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_msvc_windows_${os.getpid()}')
117 os.mkdir_all(tmp_dir)!
118 defer {
119 os.rmdir_all(tmp_dir) or {}
120 }
121 source_path := os.join_path(tmp_dir, 'hello.v')
122 output_path := os.join_path(tmp_dir, 'hello.c')
123 os.write_file(source_path, 'fn main() {\n\tprintln("hi")\n}\n')!
124 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc msvc -os windows -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
125 res := os.execute(cmd)
126 assert res.exit_code == 0, '${cmd}\n${res.output}'
127 generated_c := os.read_file(output_path)!.replace('\r\n', '\n')
128 assert generated_c.contains('#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus)\n// Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep\n// noexcept specifiers consistent'), generated_c
129 assert !generated_c.contains('V_CRT_IMPORT'), generated_c
130 assert !generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\ntypedef struct _iobuf FILE;'), generated_c
131 assert generated_c.contains('#ifndef va_copy\n\t#define va_copy(dest, src) ((dest) = (src))\n#endif\n#ifndef _TRUNCATE'), generated_c
132 assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n\t#define V_CRT_LINKAGE __declspec(dllimport)\n\t#define V_CRT_CALL VCALLCONV(cdecl)\n#else\n\t#define V_CRT_LINKAGE\n\t#define V_CRT_CALL\n#endif'), generated_c
133 assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus) && !defined(__NetBSD__)\n// mingw-w64 stdio.h declares these as static __mingw_ovr inline overrides'), generated_c
134 assert generated_c.contains('#if !((defined(__MINGW32__) || defined(__MINGW64__)) && !defined(__clang__))\nV_CRT_LINKAGE int V_CRT_CALL vfprintf(FILE *stream, const char *format, va_list ap);'), generated_c
135 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);'), generated_c
136 assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap);'), generated_c
137 assert generated_c.contains('#include <windows.h>'), generated_c
138}
139
140fn test_msvc_windows_splits_large_string_const_literals() {
141 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_msvc_long_string_${os.getpid()}')
142 os.mkdir_all(tmp_dir)!
143 defer {
144 os.rmdir_all(tmp_dir) or {}
145 }
146 long_text := 'a'.repeat(25000)
147 source_path := os.join_path(tmp_dir, 'long_string.v')
148 output_path := os.join_path(tmp_dir, 'long_string.c')
149 os.write_file(source_path,
150 "const long_literal = '${long_text}'\n\nfn main() {\n\tassert long_literal.len == ${long_text.len}\n}\n")!
151 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc msvc -os windows -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
152 res := os.execute(cmd)
153 assert res.exit_code == 0, '${cmd}\n${res.output}'
154 generated_c := os.read_file(output_path)!.replace('\r\n', '\n')
155 marker := 'long_literal = _S('
156 start := generated_c.index(marker) or {
157 assert false, generated_c
158 return
159 }
160 line := generated_c[start..].all_before(');')
161 assert line.contains('" "'), line
162 assert !line.contains('a'.repeat(20000)), line
163}
164
165fn test_manual_stdio_decls_do_not_conflict_with_later_stdio_includes() {
166 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_${os.getpid()}')
167 os.mkdir_all(tmp_dir)!
168 defer {
169 os.rmdir_all(tmp_dir) or {}
170 }
171 output_path := os.join_path(tmp_dir, 'shadowed_c_fn_call_test')
172 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(cheaders_manual_stdlib_stdio_source)}'
173 res := os.execute(cmd)
174 assert res.exit_code == 0, '${cmd}\n${res.output}'
175}
176
177fn test_manual_stdio_decls_allow_headerless_perror_declarations() {
178 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_perror_${os.getpid()}')
179 os.mkdir_all(tmp_dir)!
180 defer {
181 os.rmdir_all(tmp_dir) or {}
182 }
183 source_path := os.join_path(tmp_dir, 'c_perror.v')
184 os.write_file(source_path,
185
186 ['fn C.perror(message &char)', '', 'fn main() {', "\tC.perror(c'')", '}'].join('\n') + '\n')!
187 output_path := os.join_path(tmp_dir, 'c_perror')
188 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
189 res := os.execute(cmd)
190 assert res.exit_code == 0, '${cmd}\n${res.output}'
191}
192
193fn test_manual_stdio_decls_allow_headerless_rand_declarations() {
194 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_rand_${os.getpid()}')
195 os.mkdir_all(tmp_dir)!
196 defer {
197 os.rmdir_all(tmp_dir) or {}
198 }
199 source_path := os.join_path(tmp_dir, 'c_rand.v')
200 os.write_file(source_path,
201 ['fn C.rand() int', 'fn C.srand(seed u32)', '', 'fn main() {', '\tC.srand(1)', '\t_ = C.rand()', '}'].join('\n') +
202 '\n')!
203 output_path := os.join_path(tmp_dir, 'c_rand')
204 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
205 res := os.execute(cmd)
206 assert res.exit_code == 0, '${cmd}\n${res.output}'
207}
208
209fn test_manual_stdio_decls_allow_rand_max_macro_usage() {
210 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_rand_max_${os.getpid()}')
211 os.mkdir_all(tmp_dir)!
212 defer {
213 os.rmdir_all(tmp_dir) or {}
214 }
215 source_path := os.join_path(tmp_dir, 'c_rand_max.v')
216 os.write_file(source_path,
217 ['const rand_max = C.RAND_MAX', '', 'fn main() {', '\tassert rand_max > 0', '}'].join('\n') +
218 '\n')!
219 output_path := os.join_path(tmp_dir, 'c_rand_max')
220 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
221 res := os.execute(cmd)
222 assert res.exit_code == 0, '${cmd}\n${res.output}'
223}
224
225fn test_manual_stdio_decls_allow_direct_atof_calls() {
226 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_atof_${os.getpid()}')
227 os.mkdir_all(tmp_dir)!
228 defer {
229 os.rmdir_all(tmp_dir) or {}
230 }
231 source_path := os.join_path(tmp_dir, 'c_atof.v')
232 os.write_file(source_path, ['fn main() {', "\t_ = C.atof(c'1.25')", '}'].join('\n') + '\n')!
233 output_path := os.join_path(tmp_dir, 'c_atof')
234 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
235 res := os.execute(cmd)
236 assert res.exit_code == 0, '${cmd}\n${res.output}'
237}
238
239fn test_manual_stdio_decls_allow_translated_direct_abs_calls() {
240 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_abs_${os.getpid()}')
241 os.mkdir_all(tmp_dir)!
242 defer {
243 os.rmdir_all(tmp_dir) or {}
244 }
245 source_path := os.join_path(tmp_dir, 'c_abs.v')
246 os.write_file(source_path, ['fn main() {', '\t_ = C.abs(-7)', '}'].join('\n') + '\n')!
247 output_path := os.join_path(tmp_dir, 'c_abs')
248 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -cc clang -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
249 res := os.execute(cmd)
250 assert res.exit_code == 0, '${cmd}\n${res.output}'
251}
252
253fn test_manual_stdio_decls_allow_translated_direct_strdup_calls() {
254 $if windows {
255 return
256 }
257 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_strdup_${os.getpid()}')
258 os.mkdir_all(tmp_dir)!
259 defer {
260 os.rmdir_all(tmp_dir) or {}
261 }
262 source_path := os.join_path(tmp_dir, 'c_strdup.v')
263 os.write_file(source_path, ['fn main() {', "\t_ = C.strdup(c'abc')", '}'].join('\n') + '\n')!
264 output_path := os.join_path(tmp_dir, 'c_strdup')
265 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
266 res := os.execute(cmd)
267 assert res.exit_code == 0, '${cmd}\n${res.output}'
268}
269
270fn test_manual_stdio_decls_allow_translated_direct_strncmp_calls() {
271 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_strncmp_${os.getpid()}')
272 os.mkdir_all(tmp_dir)!
273 defer {
274 os.rmdir_all(tmp_dir) or {}
275 }
276 source_path := os.join_path(tmp_dir, 'c_strncmp.v')
277 os.write_file(source_path,
278
279 ['fn main() {', "\t_ = C.strncmp(c'abc', c'abd', 2)", '}'].join('\n') + '\n')!
280 output_path := os.join_path(tmp_dir, 'c_strncmp')
281 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -cc clang -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
282 res := os.execute(cmd)
283 assert res.exit_code == 0, '${cmd}\n${res.output}'
284}
285
286fn test_c_prelude_ctype_decls_do_not_conflict_with_later_ctype_includes() {
287 $if !linux {
288 return
289 }
290 tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_ctype_${os.getpid()}')
291 os.mkdir_all(tmp_dir)!
292 defer {
293 os.rmdir_all(tmp_dir) or {}
294 }
295 source_path := os.join_path(tmp_dir, 'c_ctype.v')
296 os.write_file(source_path,
297 ['fn C.__ctype_b_loc() &&u16', '', 'fn main() {', '\tC.__ctype_b_loc()', '}'].join('\n') +
298 '\n')!
299 output_path := os.join_path(tmp_dir, 'c_ctype')
300 cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc clang -show-c-output -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}'
301 res := os.execute(cmd)
302 assert res.exit_code == 0, '${cmd}\n${res.output}'
303}
304