v2 / vlib / builtin / panicing.c.v
172 lines · 163 sloc · 4.7 KB · da76f5588e022410b2c6e32749b54b9ce3a4ae91
Raw
1module builtin
2
3// panic_debug private function that V uses for panics, -cg/-g is passed
4// recent versions of tcc print nicer backtraces automatically
5// Note: the duplication here is because tcc_backtrace should be called directly
6// inside the panic functions.
7@[noreturn]
8fn panic_debug(line_no int, file string, mod string, fn_name string, s string) {
9 // Note: the order here is important for a stabler test output
10 // module is less likely to change than function, etc...
11 // During edits, the line number will change most frequently,
12 // so it is last
13 $if freestanding {
14 bare_panic(s)
15 } $else {
16 // vfmt off
17 // Note: be carefull to not allocate here, avoid string interpolation
18 flush_stdout()
19 eprintln('================ V panic ================')
20 eprint(' module: '); eprintln(mod)
21 eprint(' function: '); eprint(fn_name); eprintln('()')
22 eprint(' message: '); eprintln(s)
23 eprint(' file: '); eprint(file); eprint(':');
24 C.fprintf(C.stderr, c'%d\n', line_no)
25 eprint(' v hash: '); eprintln(vcurrent_hash())
26 $if !vinix {
27 eprint(' pid: '); C.fprintf(C.stderr, c'%p\n', voidptr(v_getpid()))
28 eprint(' tid: '); C.fprintf(C.stderr, c'%p\n', voidptr(v_gettid()))
29 }
30 eprintln('=========================================')
31 flush_stdout()
32 // vfmt on
33 $if exit_after_panic_message ? {
34 C.exit(1)
35 } $else $if no_backtrace ? {
36 C.exit(1)
37 } $else {
38 $if tinyc {
39 $if panics_break_into_debugger ? {
40 break_if_debugger_attached()
41 } $else {
42 C.tcc_backtrace(c'Backtrace')
43 }
44 C.exit(1)
45 }
46 $if use_libbacktrace ? {
47 $if openbsd {
48 print_backtrace_skipping_top_frames(1)
49 } $else {
50 eprint_libbacktrace(1)
51 }
52 } $else {
53 print_backtrace_skipping_top_frames(1)
54 }
55 $if panics_break_into_debugger ? {
56 break_if_debugger_attached()
57 }
58 C.exit(1)
59 }
60 }
61 C.exit(1)
62 for {}
63}
64
65// panic_option_not_set is called by V, when you use option error propagation in your main function.
66// It ends the program with a panic.
67@[noreturn]
68pub fn panic_option_not_set(s string) {
69 panic('option not set (' + s + ')')
70}
71
72// panic_result_not_set is called by V, when you use result error propagation in your main function
73// It ends the program with a panic.
74@[noreturn]
75pub fn panic_result_not_set(s string) {
76 panic('result not set (' + s + ')')
77}
78
79// panic prints a nice error message, then exits the process with exit code of 1.
80// It also shows a backtrace on most platforms.
81@[noreturn]
82pub fn panic(s string) {
83 // Note: be careful to not use string interpolation here:
84 $if freestanding {
85 bare_panic(s)
86 } $else {
87 // vfmt off
88 flush_stdout()
89 eprint('V panic: ')
90 eprintln(s)
91 eprint(' v hash: ')
92 eprintln(vcurrent_hash())
93 $if !vinix {
94 eprint(' pid: '); C.fprintf(C.stderr, c'%p\n', voidptr(v_getpid()))
95 eprint(' tid: '); C.fprintf(C.stderr, c'%p\n', voidptr(v_gettid()))
96 }
97 flush_stdout()
98 // vfmt on
99 $if exit_after_panic_message ? {
100 C.exit(1)
101 } $else $if no_backtrace ? {
102 C.exit(1)
103 } $else {
104 $if tinyc {
105 $if panics_break_into_debugger ? {
106 break_if_debugger_attached()
107 } $else {
108 C.tcc_backtrace(c'Backtrace')
109 }
110 C.exit(1)
111 }
112 $if use_libbacktrace ? {
113 $if openbsd {
114 print_backtrace_skipping_top_frames(1)
115 } $else {
116 eprint_libbacktrace(1)
117 }
118 } $else {
119 print_backtrace_skipping_top_frames(1)
120 }
121 $if panics_break_into_debugger ? {
122 break_if_debugger_attached()
123 }
124 C.exit(1)
125 }
126 }
127 C.exit(1)
128 for {}
129}
130
131// return a C-API error message matching to `errnum`
132pub fn c_error_number_str(errnum int) string {
133 mut err_msg := ''
134 $if freestanding {
135 err_msg = 'error ' + errnum.str()
136 } $else {
137 $if !vinix {
138 c_msg := C.strerror(errnum)
139 err_msg = string{
140 str: &u8(c_msg)
141 len: int(unsafe { C.strlen(c_msg) })
142 is_lit: 1
143 }
144 }
145 }
146 return err_msg
147}
148
149// panic_n prints an error message, followed by the given number, then exits the process with exit code of 1.
150@[noreturn]
151pub fn panic_n(s string, number1 i64) {
152 panic(s + impl_i64_to_string(number1))
153}
154
155// panic_n2 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
156@[noreturn]
157pub fn panic_n2(s string, number1 i64, number2 i64) {
158 panic(s + impl_i64_to_string(number1) + ', ' + impl_i64_to_string(number2))
159}
160
161// panic_n3 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
162@[noreturn]
163fn panic_n3(s string, number1 i64, number2 i64, number3 i64) {
164 panic(s + impl_i64_to_string(number1) + ', ' + impl_i64_to_string(number2) + ', ' +
165 impl_i64_to_string(number3))
166}
167
168// panic with a C-API error message matching `errnum`
169@[noreturn]
170pub fn panic_error_number(basestr string, errnum int) {
171 panic(basestr + c_error_number_str(errnum))
172}
173