| 1 | import os |
| 2 | |
| 3 | const c_variadic_vexe = @VEXE |
| 4 | const c_variadic_tests_dir = os.dir(@FILE) |
| 5 | const c_variadic_v3_dir = os.dir(c_variadic_tests_dir) |
| 6 | const c_variadic_vlib_dir = os.dir(c_variadic_v3_dir) |
| 7 | const c_variadic_v3_src = os.join_path(c_variadic_v3_dir, 'v3.v') |
| 8 | |
| 9 | fn c_variadic_build_v3() string { |
| 10 | v3_bin := os.join_path(os.temp_dir(), 'v3_c_variadic_test_${os.getpid()}') |
| 11 | os.rm(v3_bin) or {} |
| 12 | build := |
| 13 | os.execute('${c_variadic_vexe} -gc none -path "${c_variadic_vlib_dir}|@vlib|@vmodules" -o ${v3_bin} ${c_variadic_v3_src}') |
| 14 | assert build.exit_code == 0, build.output |
| 15 | return v3_bin |
| 16 | } |
| 17 | |
| 18 | fn c_variadic_call_lines(generated string, names []string) []string { |
| 19 | mut lines := []string{} |
| 20 | for line in generated.split_into_lines() { |
| 21 | for name in names { |
| 22 | if line.contains('${name}(') { |
| 23 | lines << line |
| 24 | break |
| 25 | } |
| 26 | } |
| 27 | } |
| 28 | return lines |
| 29 | } |
| 30 | |
| 31 | fn test_c_variadic_calls_emit_real_args_without_v_pack_array() { |
| 32 | v3_bin := c_variadic_build_v3() |
| 33 | src := os.join_path(os.temp_dir(), 'v3_c_variadic_${os.getpid()}.v') |
| 34 | os.write_file(src, "module main |
| 35 | |
| 36 | struct C.FILE {} |
| 37 | |
| 38 | fn C.printf(fmt &char, args ...voidptr) int |
| 39 | fn C.fprintf(stream &C.FILE, fmt &char, args ...voidptr) int |
| 40 | fn C.sscanf(input &char, fmt &char, args ...voidptr) int |
| 41 | fn C.fflush(stream &C.FILE) int |
| 42 | |
| 43 | __global C.stderr &C.FILE |
| 44 | |
| 45 | fn sum(xs ...int) int { |
| 46 | mut total := 0 |
| 47 | for x in xs { |
| 48 | total += x |
| 49 | } |
| 50 | return total |
| 51 | } |
| 52 | |
| 53 | fn main() { |
| 54 | C.printf(&c'plain\\n') |
| 55 | C.printf(&c'name=%s count=%d\\n', &c'ok', 7) |
| 56 | C.fprintf(C.stderr, &c'err=%d\\n', 9) |
| 57 | C.fflush(C.stderr) |
| 58 | mut a := 0 |
| 59 | mut b := 0 |
| 60 | C.sscanf(&c'12 34', &c'%d %d', &a, &b) |
| 61 | println(int_str(a + b + sum(1, 2, 3))) |
| 62 | } |
| 63 | ") or { |
| 64 | panic(err) |
| 65 | } |
| 66 | bin := os.join_path(os.temp_dir(), 'v3_c_variadic_${os.getpid()}') |
| 67 | compile := os.execute('${v3_bin} ${src} -b c -o ${bin}') |
| 68 | assert compile.exit_code == 0, compile.output |
| 69 | run := os.execute(bin) |
| 70 | assert run.exit_code == 0, run.output |
| 71 | assert run.output.contains('plain'), run.output |
| 72 | assert run.output.contains('name=ok count=7'), run.output |
| 73 | assert run.output.trim_space().ends_with('52'), run.output |
| 74 | |
| 75 | generated := os.read_file(bin + '.c') or { panic(err) } |
| 76 | c_lines := c_variadic_call_lines(generated, ['printf', 'fprintf', 'sscanf']) |
| 77 | assert c_lines.len >= 4, generated |
| 78 | for line in c_lines { |
| 79 | assert !line.contains('__varargs_'), line |
| 80 | } |
| 81 | assert generated.contains('printf("plain\\n");'), generated |
| 82 | assert generated.contains('printf("name=%s count=%d\\n", "ok", 7);'), generated |
| 83 | assert generated.contains('fprintf(stderr, "err=%d\\n", 9);'), generated |
| 84 | assert generated.contains('sscanf("12 34", "%d %d", &a, &b);'), generated |
| 85 | assert generated.contains('__varargs_'), generated |
| 86 | } |
| 87 | |