From 2a952e107509cbc743b351e32663bfc8c6df9211 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Tue, 29 Dec 2015 13:17:37 +0100 Subject: add sys_select (WIP) and fix source from stdin --- functions.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ postrun.cpp | 30 +++++++++++------ runtime.cpp | 16 +++++++-- 3 files changed, 139 insertions(+), 13 deletions(-) diff --git a/functions.cpp b/functions.cpp index 4e67bfa..91f6ba9 100644 --- a/functions.cpp +++ b/functions.cpp @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #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 fdtable={ + {0,{true,false,false}}, + {0,{false,true,false}}, + {0,{false,true,false}} +}; + stack>> 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&,unordered_map&,unordered_map &S,unordered_map &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&,unordered_map &S,unordered_map &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 &S,unordered_map &variables){ BUILTIN_GUARD_STACKSIZE("argc",0) S.emplace_back(g_argc); @@ -522,6 +557,77 @@ unordered_map&,unordered_map &S,unordered_map &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 &S,unordered_map &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 &S,unordered_map &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 &S,unordered_map &variables){ BUILTIN_GUARD_STACKSIZE("sleep",1) if(S.back().type!=SIT_INT)throw string("Argument to 'sleep' not a number"); diff --git a/postrun.cpp b/postrun.cpp index 2c3c97f..c880337 100644 --- a/postrun.cpp +++ b/postrun.cpp @@ -11,6 +11,8 @@ using namespace std; int g_argc; char **g_argv; +bool input_is_stdin=false; + string readfile(ifstream stream){ stream.seekg(0,ios::end); size_t len=stream.tellg(); @@ -26,24 +28,30 @@ int main(int argc,char **argv){ cerr<<"Call this interpreter with the Postrun source file"< tokens=tokenise(srcf); - //for(const string &tok : tokens)cerr<<'['< tokens; + if(strcmp(argv[1],"-")==0){ + tokens=tokenise(cin); + input_is_stdin=true; + } else { + srcf.open(argv[1]); + if(!srcf){ + cerr<<"Could not open file '"< #include #include +#include #include "runtime.h" +extern bool input_is_stdin; + using namespace std; inline bool isword(char c){return isalpha(c)||c=='_'||c=='@'||c=='$';} @@ -94,8 +97,8 @@ vector tokenise(istream &stream){ while(c=='#'){ while((c=stream.get())!='\n'&&stream); c=stream.get(); - if(!stream)break; } + if(!stream)break; if(isdigit(c)){ if(token.size()==0){ token="#"; @@ -149,7 +152,7 @@ vector tokenise(istream &stream){ token+=c; } } else if(isspace(c)); - else throw string("Invalid character found in source: '")+c+'\''; + else throw string("Invalid character found in source: '")+c+"' ("+to_string((int)(unsigned char)c)+')'; } } if(token.size())tokens.push_back(move(token)); @@ -346,4 +349,13 @@ void run(vector T){ //third pass, evaluate code runpasseval(T,S,functions,variables,jumpmap); + + if(!input_is_stdin){ + //restore canonical mode, since the code might have changed it to raw mode + 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"); + } } -- cgit v1.2.3-54-g00ecf