| 1 | import os |
| 2 | |
| 3 | const cheaders_manual_stdlib_vexe = @VEXE |
| 4 | |
| 5 | const cheaders_manual_stdlib_vroot = os.real_path(@VMODROOT) |
| 6 | |
| 7 | const cheaders_manual_stdlib_varargs_source = os.join_path(cheaders_manual_stdlib_vroot, |
| 8 | 'vlib/v/gen/c/testdata/c_varargs.vv') |
| 9 | |
| 10 | const cheaders_manual_stdlib_stdio_source = os.join_path(cheaders_manual_stdlib_vroot, |
| 11 | 'vlib/v/tests/c_shadowed_c_fn_call_test.v') |
| 12 | |
| 13 | fn 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(__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 |
| 51 | assert generated_c.contains('#elif defined(__TINYC__) && (defined(_WIN32) || defined(_WIN64))'), generated_c |
| 52 | 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 |
| 53 | assert generated_c.contains('FILE* __cdecl __iob_func(void);'), generated_c |
| 54 | assert generated_c.contains('extern FILE (*_imp___iob)[];'), generated_c |
| 55 | assert generated_c.contains('#define stdout (&__iob_func()[1])'), generated_c |
| 56 | 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 |
| 57 | 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 |
| 58 | 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 |
| 59 | assert generated_c.contains('#elif defined(__NetBSD__) || 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 |
| 60 | 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 |
| 61 | 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 |
| 62 | assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)'), generated_c |
| 63 | 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 |
| 64 | 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 |
| 65 | } |
| 66 | |
| 67 | fn test_android_prelude_uses_bionic_file_decls() { |
| 68 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_android_${os.getpid()}') |
| 69 | os.mkdir_all(tmp_dir)! |
| 70 | defer { |
| 71 | os.rmdir_all(tmp_dir) or {} |
| 72 | } |
| 73 | source_path := os.join_path(tmp_dir, 'android.v') |
| 74 | output_path := os.join_path(tmp_dir, 'android.c') |
| 75 | os.write_file(source_path, 'fn main() {\n\tprintln("hi")\n}\n')! |
| 76 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -os android -apk -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 77 | res := os.execute(cmd) |
| 78 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 79 | generated_c := os.read_file(output_path)!.replace('\r\n', '\n') |
| 80 | assert generated_c.contains('#elif defined(__BIONIC__)\nstruct __sFILE;\ntypedef struct __sFILE FILE;\nextern FILE* stdin;\nextern FILE* stdout;\nextern FILE* stderr;'), generated_c |
| 81 | assert !generated_c.contains('extern FILE __sF[];'), generated_c |
| 82 | assert !generated_c.contains('#elif defined(__BIONIC__)\ntypedef struct _IO_FILE FILE;'), generated_c |
| 83 | } |
| 84 | |
| 85 | fn test_vinix_prelude_leaves_stdio_and_stdlib_to_vinix_stubs() { |
| 86 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_vinix_${os.getpid()}') |
| 87 | os.mkdir_all(tmp_dir)! |
| 88 | defer { |
| 89 | os.rmdir_all(tmp_dir) or {} |
| 90 | } |
| 91 | source_path := os.join_path(tmp_dir, 'vinix.v') |
| 92 | output_path := os.join_path(tmp_dir, 'vinix.c') |
| 93 | os.write_file(source_path, |
| 94 | ['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') + |
| 95 | '\n')! |
| 96 | 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)}' |
| 97 | res := os.execute(cmd) |
| 98 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 99 | generated_c := os.read_file(output_path)!.replace('\r\n', '\n') |
| 100 | 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 |
| 101 | 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 |
| 102 | assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)'), generated_c |
| 103 | assert generated_c.contains('extern void printf_panic(charptr _d1, ... );'), generated_c |
| 104 | assert !generated_c.contains('extern void printf_panic(charptr _d1, Array_voidptr _d2);'), generated_c |
| 105 | assert !generated_c.contains('extern void text_start();'), generated_c |
| 106 | assert !generated_c.contains('extern voidptr __builtin_return_address(int _d1);'), generated_c |
| 107 | assert !generated_c.contains('builtin__unbuffer_stdout();'), generated_c |
| 108 | } |
| 109 | |
| 110 | fn test_msvc_windows_prelude_uses_msvc_crt_headers() { |
| 111 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_msvc_windows_${os.getpid()}') |
| 112 | os.mkdir_all(tmp_dir)! |
| 113 | defer { |
| 114 | os.rmdir_all(tmp_dir) or {} |
| 115 | } |
| 116 | source_path := os.join_path(tmp_dir, 'hello.v') |
| 117 | output_path := os.join_path(tmp_dir, 'hello.c') |
| 118 | os.write_file(source_path, 'fn main() {\n\tprintln("hi")\n}\n')! |
| 119 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc msvc -os windows -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 120 | res := os.execute(cmd) |
| 121 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 122 | generated_c := os.read_file(output_path)!.replace('\r\n', '\n') |
| 123 | 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 |
| 124 | assert !generated_c.contains('V_CRT_IMPORT'), generated_c |
| 125 | assert !generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\ntypedef struct _iobuf FILE;'), generated_c |
| 126 | assert generated_c.contains('#ifndef va_copy\n\t#define va_copy(dest, src) ((dest) = (src))\n#endif\n#ifndef _TRUNCATE'), generated_c |
| 127 | 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 |
| 128 | assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)\n// mingw-w64 stdio.h declares these as static __mingw_ovr inline overrides'), generated_c |
| 129 | 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 |
| 130 | assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);'), generated_c |
| 131 | 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 |
| 132 | assert generated_c.contains('#include <windows.h>'), generated_c |
| 133 | } |
| 134 | |
| 135 | fn test_msvc_windows_splits_large_string_const_literals() { |
| 136 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_msvc_long_string_${os.getpid()}') |
| 137 | os.mkdir_all(tmp_dir)! |
| 138 | defer { |
| 139 | os.rmdir_all(tmp_dir) or {} |
| 140 | } |
| 141 | long_text := 'a'.repeat(25000) |
| 142 | source_path := os.join_path(tmp_dir, 'long_string.v') |
| 143 | output_path := os.join_path(tmp_dir, 'long_string.c') |
| 144 | os.write_file(source_path, |
| 145 | "const long_literal = '${long_text}'\n\nfn main() {\n\tassert long_literal.len == ${long_text.len}\n}\n")! |
| 146 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc msvc -os windows -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 147 | res := os.execute(cmd) |
| 148 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 149 | generated_c := os.read_file(output_path)!.replace('\r\n', '\n') |
| 150 | marker := 'long_literal = _S(' |
| 151 | start := generated_c.index(marker) or { |
| 152 | assert false, generated_c |
| 153 | return |
| 154 | } |
| 155 | line := generated_c[start..].all_before(');') |
| 156 | assert line.contains('" "'), line |
| 157 | assert !line.contains('a'.repeat(20000)), line |
| 158 | } |
| 159 | |
| 160 | fn test_manual_stdio_decls_do_not_conflict_with_later_stdio_includes() { |
| 161 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_${os.getpid()}') |
| 162 | os.mkdir_all(tmp_dir)! |
| 163 | defer { |
| 164 | os.rmdir_all(tmp_dir) or {} |
| 165 | } |
| 166 | output_path := os.join_path(tmp_dir, 'shadowed_c_fn_call_test') |
| 167 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(cheaders_manual_stdlib_stdio_source)}' |
| 168 | res := os.execute(cmd) |
| 169 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 170 | } |
| 171 | |
| 172 | fn test_manual_stdio_decls_allow_headerless_perror_declarations() { |
| 173 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_perror_${os.getpid()}') |
| 174 | os.mkdir_all(tmp_dir)! |
| 175 | defer { |
| 176 | os.rmdir_all(tmp_dir) or {} |
| 177 | } |
| 178 | source_path := os.join_path(tmp_dir, 'c_perror.v') |
| 179 | os.write_file(source_path, |
| 180 | |
| 181 | ['fn C.perror(message &char)', '', 'fn main() {', "\tC.perror(c'')", '}'].join('\n') + '\n')! |
| 182 | output_path := os.join_path(tmp_dir, 'c_perror') |
| 183 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 184 | res := os.execute(cmd) |
| 185 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 186 | } |
| 187 | |
| 188 | fn test_manual_stdio_decls_allow_headerless_rand_declarations() { |
| 189 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_rand_${os.getpid()}') |
| 190 | os.mkdir_all(tmp_dir)! |
| 191 | defer { |
| 192 | os.rmdir_all(tmp_dir) or {} |
| 193 | } |
| 194 | source_path := os.join_path(tmp_dir, 'c_rand.v') |
| 195 | os.write_file(source_path, |
| 196 | ['fn C.rand() int', 'fn C.srand(seed u32)', '', 'fn main() {', '\tC.srand(1)', '\t_ = C.rand()', '}'].join('\n') + |
| 197 | '\n')! |
| 198 | output_path := os.join_path(tmp_dir, 'c_rand') |
| 199 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 200 | res := os.execute(cmd) |
| 201 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 202 | } |
| 203 | |
| 204 | fn test_manual_stdio_decls_allow_rand_max_macro_usage() { |
| 205 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_rand_max_${os.getpid()}') |
| 206 | os.mkdir_all(tmp_dir)! |
| 207 | defer { |
| 208 | os.rmdir_all(tmp_dir) or {} |
| 209 | } |
| 210 | source_path := os.join_path(tmp_dir, 'c_rand_max.v') |
| 211 | os.write_file(source_path, |
| 212 | ['const rand_max = C.RAND_MAX', '', 'fn main() {', '\tassert rand_max > 0', '}'].join('\n') + |
| 213 | '\n')! |
| 214 | output_path := os.join_path(tmp_dir, 'c_rand_max') |
| 215 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 216 | res := os.execute(cmd) |
| 217 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 218 | } |
| 219 | |
| 220 | fn test_manual_stdio_decls_allow_direct_atof_calls() { |
| 221 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_atof_${os.getpid()}') |
| 222 | os.mkdir_all(tmp_dir)! |
| 223 | defer { |
| 224 | os.rmdir_all(tmp_dir) or {} |
| 225 | } |
| 226 | source_path := os.join_path(tmp_dir, 'c_atof.v') |
| 227 | os.write_file(source_path, ['fn main() {', "\t_ = C.atof(c'1.25')", '}'].join('\n') + '\n')! |
| 228 | output_path := os.join_path(tmp_dir, 'c_atof') |
| 229 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 230 | res := os.execute(cmd) |
| 231 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 232 | } |
| 233 | |
| 234 | fn test_manual_stdio_decls_allow_translated_direct_abs_calls() { |
| 235 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_abs_${os.getpid()}') |
| 236 | os.mkdir_all(tmp_dir)! |
| 237 | defer { |
| 238 | os.rmdir_all(tmp_dir) or {} |
| 239 | } |
| 240 | source_path := os.join_path(tmp_dir, 'c_abs.v') |
| 241 | os.write_file(source_path, ['fn main() {', '\t_ = C.abs(-7)', '}'].join('\n') + '\n')! |
| 242 | output_path := os.join_path(tmp_dir, 'c_abs') |
| 243 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -cc clang -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 244 | res := os.execute(cmd) |
| 245 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 246 | } |
| 247 | |
| 248 | fn test_manual_stdio_decls_allow_translated_direct_strdup_calls() { |
| 249 | $if windows { |
| 250 | return |
| 251 | } |
| 252 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_strdup_${os.getpid()}') |
| 253 | os.mkdir_all(tmp_dir)! |
| 254 | defer { |
| 255 | os.rmdir_all(tmp_dir) or {} |
| 256 | } |
| 257 | source_path := os.join_path(tmp_dir, 'c_strdup.v') |
| 258 | os.write_file(source_path, ['fn main() {', "\t_ = C.strdup(c'abc')", '}'].join('\n') + '\n')! |
| 259 | output_path := os.join_path(tmp_dir, 'c_strdup') |
| 260 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 261 | res := os.execute(cmd) |
| 262 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 263 | } |
| 264 | |
| 265 | fn test_manual_stdio_decls_allow_translated_direct_strncmp_calls() { |
| 266 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_strncmp_${os.getpid()}') |
| 267 | os.mkdir_all(tmp_dir)! |
| 268 | defer { |
| 269 | os.rmdir_all(tmp_dir) or {} |
| 270 | } |
| 271 | source_path := os.join_path(tmp_dir, 'c_strncmp.v') |
| 272 | os.write_file(source_path, |
| 273 | |
| 274 | ['fn main() {', "\t_ = C.strncmp(c'abc', c'abd', 2)", '}'].join('\n') + '\n')! |
| 275 | output_path := os.join_path(tmp_dir, 'c_strncmp') |
| 276 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -translated -cc clang -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 277 | res := os.execute(cmd) |
| 278 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 279 | } |
| 280 | |
| 281 | fn test_c_prelude_ctype_decls_do_not_conflict_with_later_ctype_includes() { |
| 282 | $if !linux { |
| 283 | return |
| 284 | } |
| 285 | tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_ctype_${os.getpid()}') |
| 286 | os.mkdir_all(tmp_dir)! |
| 287 | defer { |
| 288 | os.rmdir_all(tmp_dir) or {} |
| 289 | } |
| 290 | source_path := os.join_path(tmp_dir, 'c_ctype.v') |
| 291 | os.write_file(source_path, |
| 292 | ['fn C.__ctype_b_loc() &&u16', '', 'fn main() {', '\tC.__ctype_b_loc()', '}'].join('\n') + |
| 293 | '\n')! |
| 294 | output_path := os.join_path(tmp_dir, 'c_ctype') |
| 295 | cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc clang -show-c-output -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' |
| 296 | res := os.execute(cmd) |
| 297 | assert res.exit_code == 0, '${cmd}\n${res.output}' |
| 298 | } |
| 299 | |