summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-08-22 09:59:42 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-08-22 10:00:38 +0200
commit28a403355894f378c87c01043365b85b69737546 (patch)
tree7488d319624de749cceabb0bf7ec0212e610603d
parent37173a7008807f133c92d64109b079ec209a34a2 (diff)
More IO and bug fixes
-rw-r--r--postrun.cpp94
1 files changed, 80 insertions, 14 deletions
diff --git a/postrun.cpp b/postrun.cpp
index 916c65c..78998cf 100644
--- a/postrun.cpp
+++ b/postrun.cpp
@@ -7,6 +7,8 @@
#include <cstdlib>
#include <cstring>
#include <cmath>
+#include <unistd.h>
+#include <fcntl.h>
using namespace std;
@@ -14,6 +16,9 @@ inline bool isword(char c){return isalpha(c)||c=='_'||c=='@'||c=='$';}
inline bool isextword(char c){return isword(c)||isdigit(c);}
inline bool isoperator(char c){return (bool)strchr("+-*/=><!%^{}",c);}
+int g_argc;
+char **g_argv;
+
vector<string> tokenise(istream &stream){
vector<string> tokens;
string token;
@@ -22,7 +27,7 @@ vector<string> tokenise(istream &stream){
while(true){
c=stream.get();
if(!stream)break;
- if(c=='#'){
+ while(c=='#'){
while((c=stream.get())!='\n'&&stream);
c=stream.get();
if(!stream)break;
@@ -221,8 +226,79 @@ const unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string
else cout<<v.intval<<flush;
}},
{"lf",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("lf",0)
cout<<endl;
}},
+ {"getline",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("getline",0)
+ string line;
+ getline(cin,line);
+ if(!cin)S.emplace_back(-1);
+ else S.emplace_back(line);
+ }},
+ {"getc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("getc",0)
+ char c=cin.get();
+ if(!cin)S.emplace_back(-1);
+ else S.emplace_back(string(1,c));
+ }},
+ {"fprint",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("fprint",2)
+ Stackitem file=move(S.back()); S.pop_back();
+ Stackitem v=move(S.back()); S.pop_back();
+ if(file.isstr)throw string("Second argument to 'fprint' not a number");
+ if(v.isstr)write(file.intval,v.strval.data(),v.strval.size());
+ else {
+ string s=to_string(v.intval);
+ write(file.intval,s.data(),s.size());
+ }
+ }},
+ {"flf",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("flf",1)
+ Stackitem file=move(S.back()); S.pop_back();
+ if(file.isstr)throw string("Argument to 'flf' not a number");
+ 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.isstr)throw string("Argument to 'fgetc' not a number");
+ char c;
+ int ret=read(file.intval,&c,1);
+ if(ret==-1)perror("read");
+ if(ret<=0)S.emplace_back(-1);
+ else S.emplace_back(string(1,c));
+ }},
+ {"fopen",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("fopen",2)
+ Stackitem mode=move(S.back()); S.pop_back();
+ Stackitem fname=move(S.back()); S.pop_back();
+ if(!fname.isstr)throw string("First argument to 'fopen' not a string");
+ if(!mode.isstr)throw string("Second argument to 'fopen' not a string");
+ int oflag=0;
+ if(mode.strval.find('r')!=string::npos)oflag|=O_RDONLY;
+ if(mode.strval.find('w')!=string::npos){
+ if(oflag&O_RDONLY)oflag=(oflag&~O_RDONLY)|O_RDWR;
+ else oflag|=O_WRONLY;
+ }
+ if(mode.strval.find('a')!=string::npos)oflag|=O_APPEND;
+ if(mode.strval.find('x')!=string::npos)oflag|=O_EXCL|O_CREAT;
+ if(oflag==0)oflag=O_RDONLY;
+ int ret=open(fname.strval.c_str(),oflag);
+ if(ret<0)perror("open");
+ S.emplace_back(ret);
+ }},
+ {"argc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("argc",0)
+ S.emplace_back(g_argc);
+ }},
+ {"argvget",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("argvget",1)
+ Stackitem idx=move(S.back()); S.pop_back();
+ if(idx.isstr)throw string("Argument to 'argvget' not a number");
+ if(idx.intval<0||idx.intval>=g_argc)throw string("Argument to 'argvget' out of bounds");
+ S.emplace_back(g_argv[idx.intval]);
+ }},
{"dup",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("dup",1)
S.push_back(S.back());
@@ -328,18 +404,6 @@ const unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string
S.back().intval=(int)S.back().strval[0];
S.back().strval="";
}},
- {"getline",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
- BUILTIN_GUARD_STACKSIZE("getline",0)
- string line;
- getline(cin,line);
- if(!cin)S.emplace_back(-1);
- else S.emplace_back(line);
- }},
- {"getc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
- BUILTIN_GUARD_STACKSIZE("getc",0)
- if(!cin)S.emplace_back(-1);
- else S.emplace_back(string(1,cin.get()));
- }},
{"stackdump",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("stackdump",0)
cerr<<"STACKDUMP: ";
@@ -532,10 +596,12 @@ void run(vector<string> T){
}
int main(int argc,char **argv){
- if(argc!=2){
+ if(argc<2){
cerr<<"Call this interpreter with the Postrun source file"<<endl;
return 1;
}
+ g_argc=argc-2;
+ g_argv=argv+2; //skip this executable and the postrun file
ifstream srcf(argv[1]);
if(!srcf){
cerr<<"Could not open file '"<<argv[1]<<"'"<<endl;