From debe32b18739af55899980efe2e8a9d189663bf1 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 6 Mar 2022 15:17:39 +0800 Subject: [PATCH] safer stl/module.nas & add stl/file.nas encapsulated from lib.nas/io --- README.md | 2 +- lib.nas | 8 ++++++++ nasal_builtin.h | 2 ++ stl/file.nas | 26 ++++++++++++++++++++++++++ stl/lib.nas | 8 ++++++++ stl/module.nas | 45 +++++++++++++++++++++++---------------------- test/calc.nas | 4 ++++ 7 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 stl/file.nas diff --git a/README.md b/README.md index 371903c..f8a7684 100644 --- a/README.md +++ b/README.md @@ -710,7 +710,7 @@ dylib.dlclose(dlhandle); `dylib.dlcall` is used to call the function, the first argument is the function address, make sure this argument is vm_obj and type=obj_extern. -`dylib.dlclose` is used to unload the library, at the moment that you call the function, all the function addresses that gotten from it are invalid. +`dylib.dlclose` is used to unload the library, at the moment that you call the function, all the function addresses that got from it are invalid. If get this, Congratulations! diff --git a/lib.nas b/lib.nas index 9a5f952..c51f249 100644 --- a/lib.nas +++ b/lib.nas @@ -154,6 +154,13 @@ var chr=func(code){ return __builtin_chr(code); } +# mut is used to change unmutable strings to mutable. +var mut=func(str){ + if(typeof(str)!="str") + die("mut: \"str\" must be string."); + return str~""; +} + # println has the same function as print. # but it will output a '\n' after using print. var println=func(elems...){ @@ -176,6 +183,7 @@ var io= # same as C fclose. close file by FILE*. close: func(filehandle){return __builtin_close(filehandle);}, # same as C fread. read file by FILE*. + # caution: buf must be a mutable string.use mut("") to get an empty mutable string. read: func(filehandle,buf,len){return __builtin_read(filehandle,buf,len);}, # same as C fwrite. write file by FILE*. write: func(filehandle,str){return __builtin_write(filehandle,str);}, diff --git a/nasal_builtin.h b/nasal_builtin.h index 7004fc9..20f9c45 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -757,6 +757,8 @@ nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) return builtin_err("read","not a correct filehandle"); if(buf.type!=vm_str) return builtin_err("read","\"buf\" must be string"); + if(buf.value.gcobj->unmut) + return builtin_err("read","\"buf\" is not a mutable string"); if(len.type!=vm_num) return builtin_err("read","\"len\" must be number"); if(len.num()<=0 || len.num()>=(1<<30)) diff --git a/stl/file.nas b/stl/file.nas new file mode 100644 index 0000000..cd0e8db --- /dev/null +++ b/stl/file.nas @@ -0,0 +1,26 @@ +# lib file.nas +# ValKmjolnir 2022/3/6 +import("lib.nas"); + +var file={ + SEEK_SET:io.SEEK_SET, + SEEK_CUR:io.SEEK_CUR, + SEEK_END:io.SEEK_END, + new: func(filename,mode="r"){ + var fd=io.open(filename,mode); + return { + close: func(){io.close(fd);}, + read: func(len){ + var buf=mut(""); + io.read(fd,buf,len); + return buf; + }, + write: func(str){return io.write(fd,str);}, + seek: func(pos,whence){return io.seek(fd,pos,whence);}, + tell: func(){return io.tell(fd);}, + readln: func(){return io.readln(fd);}, + stat: func(){return io.stat(filename);}, + eof: func(){return io.eof(fd);} + }; + } +}; \ No newline at end of file diff --git a/stl/lib.nas b/stl/lib.nas index 9a5f952..c51f249 100644 --- a/stl/lib.nas +++ b/stl/lib.nas @@ -154,6 +154,13 @@ var chr=func(code){ return __builtin_chr(code); } +# mut is used to change unmutable strings to mutable. +var mut=func(str){ + if(typeof(str)!="str") + die("mut: \"str\" must be string."); + return str~""; +} + # println has the same function as print. # but it will output a '\n' after using print. var println=func(elems...){ @@ -176,6 +183,7 @@ var io= # same as C fclose. close file by FILE*. close: func(filehandle){return __builtin_close(filehandle);}, # same as C fread. read file by FILE*. + # caution: buf must be a mutable string.use mut("") to get an empty mutable string. read: func(filehandle,buf,len){return __builtin_read(filehandle,buf,len);}, # same as C fwrite. write file by FILE*. write: func(filehandle,str){return __builtin_write(filehandle,str);}, diff --git a/stl/module.nas b/stl/module.nas index e6c8636..3ca222a 100644 --- a/stl/module.nas +++ b/stl/module.nas @@ -11,35 +11,36 @@ var module_call_func=func(fptr,args){ } var extern={ new: func(fptr){ + var isopen=1; return { - fptr:fptr, - isopen:1, - parents:[extern] + close:func(){isopen=0;}, + call:func(args...){ + return (!isopen)? + nil: + module_call_func(fptr,args); + } }; - }, - call: func(args...){ - return (!me.isopen)?nil:module_call_func(me.fptr,args); } }; var module={ + name:nil, new: func(name){ + me.name=name; + var lib=dylib.dlopen(name); + var f={}; return { - name:name, - lib:dylib.dlopen(name), - f:{}, - parents:[module] + get:func(symbol){ + if(contains(f,symbol)) + return f[symbol]; + var fp=extern.new(dylib.dlsym(lib,symbol)); + f[symbol]=fp; + return fp; + }, + close: func(){ + foreach(var i;keys(f)) + f[i].close(); + dylib.dlclose(lib); + } }; - }, - get: func(symbol){ - if(contains(me.f,symbol)) - return me.f[symbol]; - var f=extern.new(dylib.dlsym(me.lib,symbol)); - me.f[symbol]=f; - return f; - }, - close: func(){ - foreach(var i;keys(me.f)) - me.f[i].isopen=0; - dylib.dlclose(me.lib); } }; \ No newline at end of file diff --git a/test/calc.nas b/test/calc.nas index a70fd51..804ef8a 100644 --- a/test/calc.nas +++ b/test/calc.nas @@ -16,8 +16,10 @@ var source=[ ]; var lib=[ + "stl/file.nas ", "stl/lib.nas ", "stl/list.nas ", + "stl/module.nas ", "stl/queue.nas ", "stl/result.nas ", "stl/sort.nas ", @@ -28,6 +30,7 @@ var testfile=[ "test/ascii-art.nas ", "test/auto_crash.nas ", "test/bf.nas ", + "test/bfcolored.nas ", "test/bfconvertor.nas ", "test/bfs.nas ", "test/bigloop.nas ", @@ -53,6 +56,7 @@ var testfile=[ "test/props.nas ", "test/quick_sort.nas ", "test/scalar.nas ", + "test/tetris.nas ", "test/trait.nas ", "test/turingmachine.nas", "test/ycombinator.nas "