builtin: do not use unsafe sprintf/vsprintf functions
parent
7e139b5384
commit
c21e976cad
|
@ -195,28 +195,3 @@ pub fn is_atty(fd int) int {
|
||||||
return C.isatty(fd)
|
return C.isatty(fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn C.va_start()
|
|
||||||
fn C.va_end()
|
|
||||||
fn C.vsnprintf() int
|
|
||||||
fn C.vsprintf() int
|
|
||||||
|
|
||||||
pub fn str2_(fmt charptr, ...) string {
|
|
||||||
argptr := C.va_list{}
|
|
||||||
C.va_start(argptr, fmt)
|
|
||||||
len := C.vsnprintf(0, 0, fmt, argptr) + 1
|
|
||||||
C.va_end(argptr)
|
|
||||||
buf := malloc(len)
|
|
||||||
C.va_start(argptr, fmt)
|
|
||||||
C.vsprintf(charptr(buf), fmt, argptr)
|
|
||||||
C.va_end(argptr)
|
|
||||||
//#ifdef DEBUG_ALLOC
|
|
||||||
// puts("_STR:");
|
|
||||||
// puts(buf);
|
|
||||||
//#endif
|
|
||||||
return tos2(buf)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -110,24 +110,35 @@ fn (v &V) generate_hot_reload_code() {
|
||||||
cgen.genln('
|
cgen.genln('
|
||||||
|
|
||||||
void lfnmutex_print(char *s){
|
void lfnmutex_print(char *s){
|
||||||
if(0){
|
#if 0
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s);
|
fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
')
|
')
|
||||||
if v.pref.os != .windows {
|
if v.pref.os != .windows {
|
||||||
cgen.genln('
|
cgen.genln('
|
||||||
|
#define _POSIX_C_SOURCE 1
|
||||||
|
#include <limits.h>
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
void* live_lib = 0;
|
void* live_lib = 0;
|
||||||
|
|
||||||
int load_so(byteptr path) {
|
int load_so(byteptr path) {
|
||||||
char cpath[1024];
|
char cpath[PATH_MAX] = {0};
|
||||||
sprintf(cpath,"./%s", path);
|
int res = snprintf(cpath, sizeof (cpath), "./%s", path);
|
||||||
|
if (res >= sizeof (cpath)) {
|
||||||
|
fprintf (stderr, "path is too long");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
//printf("load_so %s\\n", cpath);
|
//printf("load_so %s\\n", cpath);
|
||||||
if (live_lib) dlclose(live_lib);
|
if (live_lib) dlclose(live_lib);
|
||||||
live_lib = dlopen(cpath, RTLD_LAZY);
|
live_lib = dlopen(cpath, RTLD_LAZY);
|
||||||
if (!live_lib) {
|
if (!live_lib) {
|
||||||
puts("open failed");
|
fprintf(stderr, "open failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +149,11 @@ int load_so(byteptr path) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cgen.genln('
|
cgen.genln('
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
void pthread_mutex_lock(HANDLE *m) {
|
void pthread_mutex_lock(HANDLE *m) {
|
||||||
WaitForSingleObject(*m, INFINITE);
|
WaitForSingleObject(*m, INFINITE);
|
||||||
}
|
}
|
||||||
|
@ -146,14 +162,19 @@ void pthread_mutex_unlock(HANDLE *m) {
|
||||||
ReleaseMutex(*m);
|
ReleaseMutex(*m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* live_lib=0;
|
void* live_lib = NULL;
|
||||||
int load_so(byteptr path) {
|
int load_so(byteptr path) {
|
||||||
char cpath[1024];
|
char cpath[PATH_MAX];
|
||||||
sprintf(cpath, "./%s", path);
|
int res = snprintf(cpath, sizeof (cpath), "./%s", path);
|
||||||
|
if (res >= sizeof(cpath)) {
|
||||||
|
puts("path is too long\\n");
|
||||||
|
exit(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (live_lib) FreeLibrary(live_lib);
|
if (live_lib) FreeLibrary(live_lib);
|
||||||
live_lib = LoadLibraryA(cpath);
|
live_lib = LoadLibraryA(cpath);
|
||||||
if (!live_lib) {
|
if (!live_lib) {
|
||||||
puts("open failed");
|
puts("open failed\\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -167,9 +188,9 @@ int load_so(byteptr path) {
|
||||||
|
|
||||||
int _live_reloads = 0;
|
int _live_reloads = 0;
|
||||||
void reload_so() {
|
void reload_so() {
|
||||||
char new_so_base[1024];
|
char new_so_base[PATH_MAX] = {0};
|
||||||
char new_so_name[1024];
|
char new_so_name[PATH_MAX] = {0};
|
||||||
char compile_cmd[1024];
|
char compile_cmd[PATH_MAX] = {0};
|
||||||
int last = os__file_last_mod_unix(tos2("$file"));
|
int last = os__file_last_mod_unix(tos2("$file"));
|
||||||
while (1) {
|
while (1) {
|
||||||
// TODO use inotify
|
// TODO use inotify
|
||||||
|
@ -179,22 +200,22 @@ void reload_so() {
|
||||||
_live_reloads++;
|
_live_reloads++;
|
||||||
|
|
||||||
//v -o bounce -shared bounce.v
|
//v -o bounce -shared bounce.v
|
||||||
sprintf(new_so_base, ".tmp.%d.${file_base}", _live_reloads);
|
snprintf(new_so_base, sizeof (new_so_base), ".tmp.%d.${file_base}", _live_reloads);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// We have to make this directory becuase windows WILL NOT
|
// We have to make this directory becuase windows WILL NOT
|
||||||
// do it for us
|
// do it for us
|
||||||
os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/")));
|
os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/")));
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
sprintf(new_so_name, "%s.dll", new_so_base);
|
snprintf(new_so_name, sizeof (new_so_name), "%s.dll", new_so_base);
|
||||||
#else
|
#else
|
||||||
sprintf(new_so_name, "%s.so", new_so_base);
|
snprintf(new_so_name, sizeof (new_so_name), "%s.so", new_so_base);
|
||||||
#endif
|
#endif
|
||||||
sprintf(compile_cmd, "$vexe $msvc -o %s -solive -shared $file", new_so_base);
|
snprintf(compile_cmd, sizeof (compile_cmd), "$vexe $msvc -o %s -solive -shared $file", new_so_base);
|
||||||
os__system(tos2(compile_cmd));
|
os__system(tos2(compile_cmd));
|
||||||
|
|
||||||
if( !os__exists(tos2(new_so_name)) ) {
|
if( !os__exists(tos2(new_so_name)) ) {
|
||||||
fprintf(stderr, "Errors while compiling $file\\n");
|
puts("Errors while compiling $file\\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
const (
|
||||||
|
vexe = os.getenv('VEXE')
|
||||||
|
source_file = os.join_path(os.temp_dir(), 'generated_live_program.v')
|
||||||
|
output_file = os.join_path(os.temp_dir(), 'generated_live_program.output.txt')
|
||||||
|
live_program_source = "
|
||||||
|
module main
|
||||||
|
import time
|
||||||
|
|
||||||
|
[live]
|
||||||
|
fn pmessage() {
|
||||||
|
println('ORIGINAL')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println('START')
|
||||||
|
for i := 0; i<6*100; i++ {
|
||||||
|
pmessage()
|
||||||
|
time.sleep_ms(10)
|
||||||
|
}
|
||||||
|
println('END')
|
||||||
|
}
|
||||||
|
"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
fn testsuite_begin(){
|
||||||
|
if os.user_os() != 'linux' && os.getenv('FORCE_LIVE_TEST').len == 0 {
|
||||||
|
eprintln('Testing the runtime behaviour of -live mode,')
|
||||||
|
eprintln('is reliable only on Linux for now.')
|
||||||
|
eprintln('You can still do it by setting FORCE_LIVE_TEST=1 .')
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
os.write_file(source_file, live_program_source)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testsuite_end(){
|
||||||
|
os.rm( source_file )
|
||||||
|
eprintln('source: $source_file')
|
||||||
|
eprintln('output: $output_file')
|
||||||
|
$if !windows {
|
||||||
|
os.system('cat $output_file')
|
||||||
|
}
|
||||||
|
println('---------------------------------------------------------------------------')
|
||||||
|
output_lines := os.read_lines( output_file ) or {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mut histogram := map[string]int
|
||||||
|
for line in output_lines {
|
||||||
|
histogram[line] = histogram[line] + 1
|
||||||
|
}
|
||||||
|
for k,v in histogram {
|
||||||
|
println('> found ${k} $v times.')
|
||||||
|
}
|
||||||
|
println('---------------------------------------------------------------------------')
|
||||||
|
assert histogram['START'] > 0
|
||||||
|
assert histogram['END'] > 0
|
||||||
|
assert histogram['CHANGED'] + histogram['ANOTHER'] > 0
|
||||||
|
assert histogram['ORIGINAL'] > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_source(new string){
|
||||||
|
time.sleep_ms(250)
|
||||||
|
eprintln('> change ORIGINAL to: $new')
|
||||||
|
os.write_file(source_file,live_program_source.replace('ORIGINAL', new))
|
||||||
|
time.sleep_ms(1000)
|
||||||
|
eprintln('> done.')
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
fn test_live_program_can_be_compiled(){
|
||||||
|
cmd := '$vexe -live run $source_file > $output_file &'
|
||||||
|
eprintln('Compiling and running with: $cmd')
|
||||||
|
res := os.system(cmd)
|
||||||
|
eprintln('... running in the background')
|
||||||
|
time.sleep_ms(3000)
|
||||||
|
assert res == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_live_program_can_be_changed_1(){
|
||||||
|
change_source('CHANGED')
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_live_program_can_be_changed_2(){
|
||||||
|
change_source('ANOTHER')
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_live_program_has_ended(){
|
||||||
|
time.sleep_ms(10*1000)
|
||||||
|
assert true
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ pub fn parse_rfc2822(s string) ?Time {
|
||||||
mm := pos / 3 + 1
|
mm := pos / 3 + 1
|
||||||
mut tmstr := byteptr(0)
|
mut tmstr := byteptr(0)
|
||||||
unsafe { tmstr = malloc(s.len * 2) }
|
unsafe { tmstr = malloc(s.len * 2) }
|
||||||
count := C.sprintf(charptr(tmstr), '%s-%02d-%s %s', fields[3].str, mm,
|
count := C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, mm,
|
||||||
fields[1].str, fields[4].str)
|
fields[1].str, fields[4].str)
|
||||||
|
|
||||||
t := parse(tos(tmstr, count)) or {
|
t := parse(tos(tmstr, count)) or {
|
||||||
|
|
Loading…
Reference in New Issue