checker: warn if C.m* or C.s* functions are called outside unsafe blocks (#5869)
parent
1a5236e53d
commit
a74cbf55c7
|
@ -73,7 +73,9 @@ fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array {
|
|||
cap: cap_
|
||||
}
|
||||
// TODO Write all memory functions (like memcpy) in V
|
||||
C.memcpy(arr.data, c_array, len * elm_size)
|
||||
unsafe {
|
||||
C.memcpy(arr.data, c_array, len * elm_size)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
|
@ -125,7 +127,9 @@ pub fn (a array) repeat(count int) array {
|
|||
for i in 0..count {
|
||||
if a.len > 0 && a.element_size == sizeof(array) {
|
||||
ary := array{}
|
||||
C.memcpy(&ary, a.data, sizeof(array))
|
||||
unsafe {
|
||||
C.memcpy(&ary, a.data, sizeof(array))
|
||||
}
|
||||
ary_clone := ary.clone()
|
||||
unsafe {
|
||||
C.memcpy(arr.get_unsafe(i * a.len), &ary_clone, a.len * a.element_size)
|
||||
|
@ -516,7 +520,9 @@ pub fn copy(dst, src []byte) int {
|
|||
if dst.len > 0 && src.len > 0 {
|
||||
mut min := 0
|
||||
min = if dst.len < src.len { dst.len } else { src.len }
|
||||
C.memcpy(byteptr(dst.data), src[..min].data, dst.element_size * min)
|
||||
unsafe {
|
||||
C.memcpy(byteptr(dst.data), src[..min].data, dst.element_size * min)
|
||||
}
|
||||
return min
|
||||
}
|
||||
return 0
|
||||
|
|
|
@ -150,7 +150,7 @@ pub fn malloc(n int) byteptr {
|
|||
nr_mallocs++
|
||||
return res
|
||||
} $else {
|
||||
ptr := C.malloc(n)
|
||||
ptr := unsafe {C.malloc(n)}
|
||||
if ptr == 0 {
|
||||
panic('malloc($n) failed')
|
||||
}
|
||||
|
@ -177,12 +177,14 @@ TODO
|
|||
[unsafe_fn]
|
||||
pub fn v_realloc(b byteptr, n u32) byteptr {
|
||||
$if prealloc {
|
||||
new_ptr := malloc(int(n))
|
||||
size := 0 //malloc_size(b)
|
||||
C.memcpy(new_ptr, b, size)
|
||||
return new_ptr
|
||||
unsafe {
|
||||
new_ptr := malloc(int(n))
|
||||
size := 0 //malloc_size(b)
|
||||
C.memcpy(new_ptr, b, size)
|
||||
return new_ptr
|
||||
}
|
||||
} $else {
|
||||
ptr := C.realloc(b, n)
|
||||
ptr := unsafe {C.realloc(b, n)}
|
||||
if ptr == 0 {
|
||||
panic('realloc($n) failed')
|
||||
}
|
||||
|
@ -217,8 +219,10 @@ pub fn memdup(src voidptr, sz int) voidptr {
|
|||
if sz == 0 {
|
||||
return vcalloc(1)
|
||||
}
|
||||
mem := malloc(sz)
|
||||
return C.memcpy(mem, src, sz)
|
||||
unsafe {
|
||||
mem := malloc(sz)
|
||||
return C.memcpy(mem, src, sz)
|
||||
}
|
||||
}
|
||||
|
||||
fn v_ptr_free(ptr voidptr) {
|
||||
|
|
|
@ -62,7 +62,9 @@ const (
|
|||
fn builtin_init() {
|
||||
if is_atty(1) > 0 {
|
||||
C.SetConsoleMode(C.GetStdHandle(C.STD_OUTPUT_HANDLE), C.ENABLE_PROCESSED_OUTPUT | 0x0004) // enable_virtual_terminal_processing
|
||||
C.setbuf(C.stdout, 0)
|
||||
unsafe {
|
||||
C.setbuf(C.stdout, 0)
|
||||
}
|
||||
}
|
||||
add_unhandled_exception_handler()
|
||||
}
|
||||
|
|
|
@ -125,7 +125,8 @@ fn C.mktime() int
|
|||
fn C.gettimeofday() int
|
||||
|
||||
|
||||
fn C.sleep() int
|
||||
[trusted_fn]
|
||||
fn C.sleep(int) int
|
||||
|
||||
|
||||
fn C.usleep() int
|
||||
|
@ -152,9 +153,11 @@ fn C.tolower() int
|
|||
fn C.toupper() int
|
||||
|
||||
|
||||
[trusted_fn]
|
||||
fn C.getchar() int
|
||||
|
||||
|
||||
[trusted_fn]
|
||||
fn C.strerror(int) charptr
|
||||
|
||||
|
||||
|
|
|
@ -88,7 +88,9 @@ fn fast_string_eq(a, b string) bool {
|
|||
if a.len != b.len {
|
||||
return false
|
||||
}
|
||||
return C.memcmp(a.str, b.str, b.len) == 0
|
||||
unsafe {
|
||||
return C.memcmp(a.str, b.str, b.len) == 0
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic array with very low growth factor
|
||||
|
@ -502,11 +504,13 @@ pub fn (d DenseArray) clone() DenseArray {
|
|||
cap: d.cap
|
||||
len: d.len
|
||||
deletes: d.deletes
|
||||
keys: &string(malloc(int(d.cap * sizeof(string))))
|
||||
values: byteptr(malloc(int(d.cap * u32(d.value_bytes))))
|
||||
keys: unsafe {&string(malloc(int(d.cap * sizeof(string))))}
|
||||
values: unsafe {byteptr(malloc(int(d.cap * u32(d.value_bytes))))}
|
||||
}
|
||||
unsafe {
|
||||
C.memcpy(res.keys, d.keys, d.cap * sizeof(string))
|
||||
C.memcpy(res.values, d.values, d.cap * u32(d.value_bytes))
|
||||
}
|
||||
C.memcpy(res.keys, d.keys, d.cap * sizeof(string))
|
||||
C.memcpy(res.values, d.values, d.cap * u32(d.value_bytes))
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,9 @@ fn opt_ok(data voidptr, size int) Option {
|
|||
res := Option{
|
||||
ok: true
|
||||
}
|
||||
C.memcpy(res.data, data, size)
|
||||
unsafe {
|
||||
C.memcpy(res.data, data, size)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,9 @@ fn (mut m SortedMap) set(key string, value voidptr) {
|
|||
}
|
||||
parent.split_child(child_index, mut node)
|
||||
if key == parent.keys[child_index] {
|
||||
C.memcpy(parent.values[child_index], value, m.value_bytes)
|
||||
unsafe {
|
||||
C.memcpy(parent.values[child_index], value, m.value_bytes)
|
||||
}
|
||||
return
|
||||
}
|
||||
node = if key < parent.keys[child_index] {
|
||||
|
@ -91,7 +93,9 @@ fn (mut m SortedMap) set(key string, value voidptr) {
|
|||
mut i := 0
|
||||
for i < node.len && key > node.keys[i] { i++ }
|
||||
if i != node.len && key == node.keys[i] {
|
||||
C.memcpy(node.values[i], value, m.value_bytes)
|
||||
unsafe {
|
||||
C.memcpy(node.values[i], value, m.value_bytes)
|
||||
}
|
||||
return
|
||||
}
|
||||
if isnil(node.children) {
|
||||
|
@ -103,7 +107,9 @@ fn (mut m SortedMap) set(key string, value voidptr) {
|
|||
}
|
||||
node.keys[j + 1] = key
|
||||
node.values[j + 1] = malloc(m.value_bytes)
|
||||
C.memcpy(node.values[j + 1], value, m.value_bytes)
|
||||
unsafe {
|
||||
C.memcpy(node.values[j + 1], value, m.value_bytes)
|
||||
}
|
||||
node.len++
|
||||
m.len++
|
||||
return
|
||||
|
@ -150,7 +156,9 @@ fn (m SortedMap) get(key string, out voidptr) bool {
|
|||
mut i := node.len - 1
|
||||
for i >= 0 && key < node.keys[i] { i-- }
|
||||
if i != -1 && key == node.keys[i] {
|
||||
C.memcpy(out, node.values[i], m.value_bytes)
|
||||
unsafe {
|
||||
C.memcpy(out, node.values[i], m.value_bytes)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if isnil(node.children) {
|
||||
|
|
|
@ -66,8 +66,9 @@ pub mut:
|
|||
len int
|
||||
}
|
||||
|
||||
[unsafe_fn]
|
||||
pub fn vstrlen(s byteptr) int {
|
||||
return C.strlen(charptr(s))
|
||||
return unsafe {C.strlen(charptr(s))}
|
||||
}
|
||||
|
||||
// Converts a C string to a V string.
|
||||
|
@ -107,14 +108,14 @@ pub fn tos3(s charptr) string {
|
|||
}
|
||||
return string{
|
||||
str: byteptr(s)
|
||||
len: C.strlen(s)
|
||||
len: unsafe {C.strlen(s)}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tos_lit(s charptr) string {
|
||||
return string{
|
||||
str: byteptr(s)
|
||||
len: C.strlen(s)
|
||||
len: unsafe {C.strlen(s)}
|
||||
is_lit: 1
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +372,9 @@ fn (s string) eq(a string) bool {
|
|||
if s.len != a.len {
|
||||
return false
|
||||
}
|
||||
return C.memcmp(s.str, a.str, a.len) == 0
|
||||
unsafe {
|
||||
return C.memcmp(s.str, a.str, a.len) == 0
|
||||
}
|
||||
}
|
||||
|
||||
// !=
|
||||
|
@ -1379,7 +1382,9 @@ pub fn (s string) bytes() []byte {
|
|||
return []
|
||||
}
|
||||
mut buf := []byte{ len:s.len }
|
||||
C.memcpy(buf.data, s.str, s.len)
|
||||
unsafe {
|
||||
C.memcpy(buf.data, s.str, s.len)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
|
|
|
@ -32,11 +32,15 @@ pub fn setenv(name string, value string, overwrite bool) int {
|
|||
$if windows {
|
||||
format := '$name=$value'
|
||||
if overwrite {
|
||||
return C._putenv(format.str)
|
||||
unsafe {
|
||||
return C._putenv(format.str)
|
||||
}
|
||||
}
|
||||
return -1
|
||||
} $else {
|
||||
return C.setenv(charptr(name.str), charptr(value.str), overwrite)
|
||||
unsafe {
|
||||
return C.setenv(charptr(name.str), charptr(value.str), overwrite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,9 @@ pub:
|
|||
// it supports windows for regular files but it doesn't matter if you use owner, group or others when checking permissions on windows
|
||||
pub fn inode(path string) FileMode {
|
||||
mut attr := C.stat{}
|
||||
C.stat(charptr(path.str), &attr)
|
||||
unsafe {
|
||||
C.stat(charptr(path.str), &attr)
|
||||
}
|
||||
|
||||
mut typ := FileType.regular
|
||||
if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFDIR) {
|
||||
|
|
37
vlib/os/os.v
37
vlib/os/os.v
|
@ -140,14 +140,16 @@ pub fn (mut f File) flush() {
|
|||
// file_size returns the size of the file located in `path`.
|
||||
pub fn file_size(path string) int {
|
||||
mut s := C.stat{}
|
||||
$if windows {
|
||||
$if tinyc {
|
||||
C.stat(charptr(path.str), voidptr(&s))
|
||||
unsafe {
|
||||
$if windows {
|
||||
$if tinyc {
|
||||
C.stat(charptr(path.str), &s)
|
||||
} $else {
|
||||
C._wstat(path.to_wide(), voidptr(&s))
|
||||
}
|
||||
} $else {
|
||||
C._wstat(path.to_wide(), voidptr(&s))
|
||||
C.stat(charptr(path.str), &s)
|
||||
}
|
||||
} $else {
|
||||
C.stat(charptr(path.str), voidptr(&s))
|
||||
}
|
||||
return s.st_size
|
||||
}
|
||||
|
@ -193,7 +195,9 @@ pub fn cp(old, new string) ? {
|
|||
}
|
||||
}
|
||||
from_attr := C.stat{}
|
||||
C.stat(charptr(old.str), &from_attr)
|
||||
unsafe {
|
||||
C.stat(charptr(old.str), &from_attr)
|
||||
}
|
||||
if C.chmod(charptr(new.str), from_attr.st_mode) < 0 {
|
||||
return error_with_code('failed to set permissions for $new', int(-1))
|
||||
}
|
||||
|
@ -444,9 +448,13 @@ pub fn system(cmd string) int {
|
|||
$if windows {
|
||||
// overcome bug in system & _wsystem (cmd) when first char is quote `"`
|
||||
wcmd := if cmd.len > 1 && cmd[0] == `"` && cmd[1] != `"` { '"$cmd"' } else { cmd }
|
||||
ret = C._wsystem(wcmd.to_wide())
|
||||
unsafe {
|
||||
ret = C._wsystem(wcmd.to_wide())
|
||||
}
|
||||
} $else {
|
||||
ret = C.system(charptr(cmd.str))
|
||||
unsafe {
|
||||
ret = C.system(charptr(cmd.str))
|
||||
}
|
||||
}
|
||||
if ret == -1 {
|
||||
print_c_errno()
|
||||
|
@ -1095,7 +1103,7 @@ pub fn is_dir(path string) bool {
|
|||
return false
|
||||
} $else {
|
||||
statbuf := C.stat{}
|
||||
if C.stat(charptr(path.str), &statbuf) != 0 {
|
||||
if unsafe {C.stat(charptr(path.str), &statbuf)} != 0 {
|
||||
return false
|
||||
}
|
||||
// ref: https://code.woboq.org/gcc/include/sys/stat.h.html
|
||||
|
@ -1231,8 +1239,11 @@ pub fn walk(path string, f fn(path string)) {
|
|||
return
|
||||
}
|
||||
|
||||
[unsafe_fn]
|
||||
pub fn signal(signum int, handler voidptr) {
|
||||
C.signal(signum, handler)
|
||||
unsafe {
|
||||
C.signal(signum, handler)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fork() int {
|
||||
|
@ -1260,7 +1271,9 @@ pub fn wait() int {
|
|||
pub fn file_last_mod_unix(path string) int {
|
||||
attr := C.stat{}
|
||||
// # struct stat attr;
|
||||
C.stat(charptr(path.str), &attr)
|
||||
unsafe {
|
||||
C.stat(charptr(path.str), &attr)
|
||||
}
|
||||
// # stat(path.str, &attr);
|
||||
return attr.st_mtime
|
||||
// # return attr.st_mtime ;
|
||||
|
|
|
@ -121,7 +121,7 @@ pub fn mkdir(path string) ?bool {
|
|||
}
|
||||
}
|
||||
*/
|
||||
r := C.mkdir(charptr(apath.str), 511)
|
||||
r := unsafe {C.mkdir(charptr(apath.str), 511)}
|
||||
if r == -1 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ pub fn parse_rfc2822(s string) ?Time {
|
|||
mm := pos / 3 + 1
|
||||
mut tmstr := byteptr(0)
|
||||
unsafe { tmstr = malloc(s.len * 2) }
|
||||
count := C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, mm,
|
||||
fields[1].str, fields[4].str)
|
||||
count := unsafe {C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, mm,
|
||||
fields[1].str, fields[4].str)}
|
||||
|
||||
return parse(tos(tmstr, count))
|
||||
}
|
||||
|
@ -67,10 +67,10 @@ pub fn parse_iso8601(s string) ?Time {
|
|||
mut offset_hour := 0
|
||||
mut offset_min := 0
|
||||
|
||||
count := C.sscanf(charptr(s.str), "%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d", &year, &month, &day,
|
||||
count := unsafe {C.sscanf(charptr(s.str), "%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d", &year, &month, &day,
|
||||
&time_char, &hour, &minute,
|
||||
&second, &mic_second, &plus_min,
|
||||
&offset_hour, &offset_min)
|
||||
&offset_hour, &offset_min)}
|
||||
|
||||
if count != 11 {
|
||||
return error('Invalid 8601 format')
|
||||
|
|
|
@ -1096,12 +1096,16 @@ pub fn (stmt Stmt) position() token.Position {
|
|||
// field table.Field.default_expr, which should be ast.Expr
|
||||
pub fn fe2ex(x table.FExpr) Expr {
|
||||
res := Expr{}
|
||||
C.memcpy(&res, &x, sizeof(Expr))
|
||||
unsafe {
|
||||
C.memcpy(&res, &x, sizeof(Expr))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn ex2fe(x Expr) table.FExpr {
|
||||
res := table.FExpr{}
|
||||
C.memcpy(&res, &x, sizeof(table.FExpr))
|
||||
unsafe {
|
||||
C.memcpy(&res, &x, sizeof(table.FExpr))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -1128,6 +1128,12 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
if f.is_deprecated {
|
||||
c.warn('function `$f.name` has been deprecated', call_expr.pos)
|
||||
}
|
||||
if f.is_unsafe && !c.inside_unsafe &&
|
||||
f.language == .c && f.name[2] in [`m`, `s`] && f.mod == 'builtin' {
|
||||
// builtin C.m*, C.s* only - temp
|
||||
c.warn('function `$f.name` must be called from an `unsafe` block',
|
||||
call_expr.pos)
|
||||
}
|
||||
if f.is_generic && f.return_type.has_flag(.generic) {
|
||||
rts := c.table.get_type_symbol(f.return_type)
|
||||
if rts.kind == .struct_ {
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
vlib/v/checker/tests/pointer_arithmetic_should_be_checked.v:4:6: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
2 | v := 5
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
| ~~
|
||||
5 | p += 2
|
||||
6 | _ := v
|
||||
vlib/v/checker/tests/pointer_arithmetic_should_be_checked.v:5:7: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
5 | p += 2
|
||||
| ~~
|
||||
6 | _ := v
|
||||
7 | }
|
||||
vlib/v/checker/tests/pointer_arithmetic_should_be_checked.v:11:14: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
9 | fn test_ptr_infix() {
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
| ^
|
||||
12 | q = q + 3
|
||||
13 | _ := q
|
||||
vlib/v/checker/tests/pointer_arithmetic_should_be_checked.v:12:9: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
12 | q = q + 3
|
||||
| ^
|
||||
13 | _ := q
|
||||
14 | _ := v
|
||||
vlib/v/checker/tests/pointer_arithmetic_should_be_checked.v:24:7: error: method `S1.f` must be called from an `unsafe` block
|
||||
22 | fn test_funcs() {
|
||||
23 | s := S1{}
|
||||
24 | s.f()
|
||||
| ~~~
|
||||
25 | }
|
|
@ -0,0 +1,13 @@
|
|||
vlib/v/checker/tests/unsafe_c_calls_should_be_checked.v:3:16: error: function `C.malloc` must be called from an `unsafe` block
|
||||
1 |
|
||||
2 | fn test_c() {
|
||||
3 | mut p := C.malloc(4)
|
||||
| ~~~~~~~~~
|
||||
4 | s := 'hope'
|
||||
5 | C.memcpy(p, s.str, 4)
|
||||
vlib/v/checker/tests/unsafe_c_calls_should_be_checked.v:5:7: error: function `C.memcpy` must be called from an `unsafe` block
|
||||
3 | mut p := C.malloc(4)
|
||||
4 | s := 'hope'
|
||||
5 | C.memcpy(p, s.str, 4)
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
6 | }
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
fn test_c() {
|
||||
mut p := C.malloc(4)
|
||||
s := 'hope'
|
||||
C.memcpy(p, s.str, 4)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
vlib/v/checker/tests/unsafe_pointer_arithmetic_should_be_checked.v:4:6: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
2 | v := 5
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
| ~~
|
||||
5 | p += 2
|
||||
6 | _ := v
|
||||
vlib/v/checker/tests/unsafe_pointer_arithmetic_should_be_checked.v:5:7: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
5 | p += 2
|
||||
| ~~
|
||||
6 | _ := v
|
||||
7 | }
|
||||
vlib/v/checker/tests/unsafe_pointer_arithmetic_should_be_checked.v:11:14: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
9 | fn test_ptr_infix() {
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
| ^
|
||||
12 | q = q + 3
|
||||
13 | _ := q
|
||||
vlib/v/checker/tests/unsafe_pointer_arithmetic_should_be_checked.v:12:9: error: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
12 | q = q + 3
|
||||
| ^
|
||||
13 | _ := q
|
||||
14 | _ := v
|
||||
vlib/v/checker/tests/unsafe_pointer_arithmetic_should_be_checked.v:24:7: error: method `S1.f` must be called from an `unsafe` block
|
||||
22 | fn test_funcs() {
|
||||
23 | s := S1{}
|
||||
24 | s.f()
|
||||
| ~~~
|
||||
25 | }
|
|
@ -620,7 +620,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
if word.len != 2 {
|
||||
verror('opcodes format: xx xx xx xx')
|
||||
}
|
||||
b := C.strtol(charptr(word.str), 0, 16)
|
||||
b := unsafe {C.strtol(charptr(word.str), 0, 16)}
|
||||
// b := word.byte()
|
||||
// println('"$word" $b')
|
||||
g.write8(b)
|
||||
|
|
|
@ -132,7 +132,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
p.top_level_statement_start()
|
||||
start_pos := p.tok.position()
|
||||
is_deprecated := 'deprecated' in p.attrs
|
||||
is_unsafe := 'unsafe_fn' in p.attrs
|
||||
mut is_unsafe := 'unsafe_fn' in p.attrs
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
if is_pub {
|
||||
p.next()
|
||||
|
@ -141,6 +141,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
p.open_scope()
|
||||
// C. || JS.
|
||||
language := if p.tok.kind == .name && p.tok.lit == 'C' {
|
||||
is_unsafe = !('trusted_fn' in p.attrs)
|
||||
table.Language.c
|
||||
} else if p.tok.kind == .name && p.tok.lit == 'JS' {
|
||||
table.Language.js
|
||||
|
|
|
@ -27,7 +27,9 @@ pub const (
|
|||
pub fn vhash() string {
|
||||
mut buf := [50]byte
|
||||
buf[0] = 0
|
||||
C.snprintf(charptr(buf), 50, '%s', C.V_COMMIT_HASH)
|
||||
unsafe {
|
||||
C.snprintf(charptr(buf), 50, '%s', C.V_COMMIT_HASH)
|
||||
}
|
||||
return tos_clone(buf)
|
||||
}
|
||||
|
||||
|
@ -97,7 +99,9 @@ pub fn githash(should_get_from_filesystem bool) string {
|
|||
}
|
||||
mut buf := [50]byte
|
||||
buf[0] = 0
|
||||
C.snprintf(charptr(buf), 50, '%s', C.V_CURRENT_COMMIT_HASH)
|
||||
unsafe {
|
||||
C.snprintf(charptr(buf), 50, '%s', C.V_CURRENT_COMMIT_HASH)
|
||||
}
|
||||
return tos_clone(buf)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue