diff options
Diffstat (limited to 'functions.cpp')
-rw-r--r-- | functions.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/functions.cpp b/functions.cpp index 4e67bfa..91f6ba9 100644 --- a/functions.cpp +++ b/functions.cpp @@ -10,6 +10,9 @@ #include <cassert> #include <unistd.h> #include <fcntl.h> +#include <termios.h> +#include <sys/time.h> +#include <sys/select.h> #include "runtime.h" @@ -20,6 +23,20 @@ extern char **g_argv; #define BUILTIN_GUARD_STACKSIZE(nm,sz) {if(S.size()<(sz))throw string("Builtin '" nm "' needs " #sz " stack item")+(sz==1?"":"s");} +struct Fdinfo{ + bool read,write; + bool open; + + Fdinfo(void):read(false),write(false),open(false){} + Fdinfo(bool _r,bool _w,bool _o):read(_r),write(_w),open(_o){} +}; + +unordered_map<int,Fdinfo> fdtable={ + {0,{true,false,false}}, + {0,{false,true,false}}, + {0,{false,true,false}} +}; + stack<unordered_map<string,pair<Stackitem,bool>>> scopestack; //Each stack frame contains the variables local to the stack frame. The bool is //whether it was already present in the previous frame, and the Stackitem @@ -191,6 +208,8 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack Stackitem file=move(S.back()); S.pop_back(); Stackitem v=move(S.back()); S.pop_back(); if(file.type!=SIT_INT)throw string("Second argument to 'fprint' not a number"); + if(!fdtable[file.intval].open||!fdtable[file.intval].write) + throw string("File not open or not writable in 'fprint'"); if(v.type==SIT_STR)write(file.intval,v.strval.data(),v.strval.size()); else { string s=to_string(v); @@ -201,12 +220,16 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack BUILTIN_GUARD_STACKSIZE("flf",1) Stackitem file=move(S.back()); S.pop_back(); if(file.type!=SIT_INT)throw string("Argument to 'flf' not a number"); + if(!fdtable[file.intval].open||!fdtable[file.intval].write) + throw string("File not open or not writable in 'flf'"); write(file.intval,"\n",1); }}, {"fgetc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ BUILTIN_GUARD_STACKSIZE("fgetc",1) Stackitem file=move(S.back()); S.pop_back(); if(file.type!=SIT_INT)throw string("Argument to 'fgetc' not a number"); + if(!fdtable[file.intval].open||!fdtable[file.intval].read) + throw string("File not open or not readable in 'fgetc'"); char c; int ret=read(file.intval,&c,1); if(ret==-1)perror("read"); @@ -230,8 +253,20 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack if(oflag==0)oflag=O_RDONLY; int ret=open(fname.strval.c_str(),oflag); if(ret<0)perror("open"); + fdtable[ret].read=(oflag&(O_RDONLY|O_RDWR))!=0; + fdtable[ret].write=(oflag&(O_WRONLY|O_RDWR))!=0; + fdtable[ret].open=true; S.emplace_back(ret); }}, + {"fclose",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("fclose",1) + Stackitem file=move(S.back()); S.pop_back(); + if(file.type!=SIT_INT)throw string("Argument to 'fclose' not a number"); + if(!fdtable[file.intval].open) + throw string("File not open in 'fclose'"); + fdtable.erase(file.intval); + if(close(file.intval))perror("close"); + }}, {"argc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ BUILTIN_GUARD_STACKSIZE("argc",0) S.emplace_back(g_argc); @@ -522,6 +557,77 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack const int rval=rand(); S.emplace_back(rval%(to.intval-from.intval)+from.intval); }}, + {"sys_select",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("sys_select",4); + const Stackitem timeoutstk=move(S.back()); S.pop_back(); + const Stackitem erstk=move(S.back()); S.pop_back(); + const Stackitem wrstk=move(S.back()); S.pop_back(); + const Stackitem rdstk=move(S.back()); S.pop_back(); + if(rdstk.type!=SIT_ARR)throw string("First argument to 'sys_select' not an array"); + if(wrstk.type!=SIT_ARR)throw string("Second argument to 'sys_select' not an array"); + if(erstk.type!=SIT_ARR)throw string("Third argument to 'sys_select' not an array"); + if(timeoutstk.type!=SIT_INT)throw string("Fourth argument to 'sys_select' not a number"); + fd_set rd,wr,er; + FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&er); + int mxf=0; + for(const Stackitem &si : rdstk.arrval){ + if(!fdtable[si.intval].read) + throw string("File in read array to 'sys_select' not readable"); + FD_SET(si.intval,&rd); + if(si.intval>mxf)mxf=si.intval; + } + for(const Stackitem &si : wrstk.arrval){ + if(!fdtable[si.intval].write) + throw string("File in read array to 'sys_select' not writable"); + FD_SET(si.intval,&wr); + if(si.intval>mxf)mxf=si.intval; + } + for(const Stackitem &si : erstk.arrval){ + FD_SET(si.intval,&er); + if(si.intval>mxf)mxf=si.intval; + } + struct timeval *timeout,start,end; + if(timeoutstk.intval<0)timeout=NULL; + else { + timeout=new struct timeval; + timeout->tv_sec=timeoutstk.intval/1000000; + timeout->tv_usec=timeoutstk.intval%1000000; + } + gettimeofday(&start,NULL); + select(mxf+1,&rd,&wr,&er,timeout); + gettimeofday(&end,NULL); + const int timetaken=(end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec; + delete timeout; + Stackitem rdstk2,wrstk2,erstk2; + rdstk2.type=SIT_ARR; wrstk2.type=SIT_ARR; erstk2.type=SIT_ARR; + for(const Stackitem &si : rdstk.arrval) + if(FD_ISSET(si.intval,&rd))rdstk2.arrval.push_back(si.intval); + for(const Stackitem &si : wrstk.arrval) + if(FD_ISSET(si.intval,&wr))wrstk2.arrval.push_back(si.intval); + for(const Stackitem &si : erstk.arrval) + if(FD_ISSET(si.intval,&er))erstk2.arrval.push_back(si.intval); + S.push_back(move(rdstk2)); + S.push_back(move(wrstk2)); + S.push_back(move(erstk2)); + if(timeoutstk.intval<0||timetaken>=timeoutstk.intval||(rdstk2.arrval.size()==0&&wrstk2.arrval.size()==0&&erstk2.arrval.size()==0))S.emplace_back(0); + else S.emplace_back(timeoutstk.intval-timetaken); + }}, + {"sys_rawmode",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("sys_rawmode",0); + struct termios old={0}; + if(tcgetattr(0,&old)<0)perror("tcgetattr"); + old.c_lflag&=~ICANON; + old.c_lflag&=~ECHO; + if(tcsetattr(0,TCSANOW,&old)<0)perror("tcsetattr"); + }}, + {"sys_unrawmode",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("sys_unrawmode",0); + struct termios old={0}; + if(tcgetattr(0,&old)<0)perror("tcgetattr"); + old.c_lflag|=ICANON; + old.c_lflag|=ECHO; + if(tcsetattr(0,TCSANOW,&old)<0)perror("tcsetattr"); + }}, {"sleep",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ BUILTIN_GUARD_STACKSIZE("sleep",1) if(S.back().type!=SIT_INT)throw string("Argument to 'sleep' not a number"); |