HepLib
Loading...
Searching...
No Matches
Process.cpp
Go to the documentation of this file.
1
6#include "BASIC.h"
7#include <fstream>
8
9inline bool file_exists(const char* fn) {
10 return (access(fn,F_OK)!=-1);
11}
12
13namespace HepLib {
14
15 //-----------------------------------------------------------
16 // Fermat Class
17 //-----------------------------------------------------------
18 #define ENTER endl<<endl<<endl
19
21
22 void Fermat::Exit() {
23 if(getpid()!=pid) return;
24 if(inited) {
25 ostringstream script;
26 script << "&q;" << endl << "&x;" << ENTER;
27 string istr = script.str();
28 write(P2C[1], istr.c_str(), istr.length());
29 int st;
30 waitpid(fpid, &st, WUNTRACED);
31 inited = false;
32 exited = true;
33 }
34 }
35
36 void Fermat::Init(string fer_path) {
37 if(inited) return;
38 inited = true;
39 pid = getpid();
40
41 if (pipe(P2C)==-1 || pipe(C2P)==-1) {
42 throw Error("pipe failed in Fermat::Init.");
43 }
44
45 fpid = fork();
46 if (fpid == 0) { // child process
47 if(setpgid(0,0)) throw Error("setpgid failed in Fermat::Init.");
48 close(P2C[1]);
49 close(C2P[0]);
50 dup2(C2P[1], 1);
51 close(C2P[1]);
52 dup2(P2C[0], 0);
53 close(P2C[0]);
54 execlp(fer_path.c_str(), fer_path.c_str(), NULL);
55 exit(0);
56 }
57
58 // parent process
59 close(P2C[0]); // P2C[1] for write
60 close(C2P[1]); // C2P[0] for read
61
62 ostringstream script;
63 script << "&(_d=90000);" << endl; // width of the display on the window
64 script << "&d" << endl << "0;" << endl; // off floating point representation
65 script << "&(_t=0);" << endl; // off a certain fast probabalistic algorithm
66 script << "&(t=0);" << endl; // off timing
67 script << "&(_s=0);" << endl;
68 script << "&(_o=1000);" << endl; // http://home.bway.net/lewis/fer64mono.html
69 script << "&(M=' ');" << endl; // prompt
70 script << "!('" << Sentinel << "');" << ENTER;
71 string istr = script.str();
72 write(P2C[1], istr.c_str(), istr.length());
73
74 string ostr;
75 int n = 1024;
76 char buffer[n+1]; // make sure the last one is '\0'
77 int nio;
78 while(true) {
79 for(int i=0; i<n+1; i++) buffer[i] = '\0';
80 nio = read(C2P[0], buffer, n);
81 if(nio>0) ostr += buffer;
82 else throw Error(ostr);
83 auto cpos = ostr.find(Sentinel);
84 if(cpos!=string::npos) {
85 const char* WhiteSpace = " \t\v\r\n";
86 auto lpos = ostr.find_last_not_of(WhiteSpace);
87 if(ostr[lpos]!='0') read(C2P[0], buffer, n); // last 0, due to Sentinel
88 ostr.erase(cpos);
89 break;
90 }
91 }
92
93 string_replace_all(ostr, "*** entry > 30 or < 5 means turn off mono multiply.", "");
94 string_replace_all(ostr, "*** Fermat Warning. Early exit from mod_multivar_Chinese.", "");
95 if(ostr.find("***")!=string::npos) {
96 cout << "Fermat script: " << endl << istr << endl << endl;
97 throw Error(ostr.c_str());
98 }
99 }
100
101 // out string still contains the last number
102 string Fermat::Execute(string expr) {
103 if(exited) throw Error("Fermat has already exited.");
104 if(getpid() != pid) throw Error("Fermat: can not Execute on child process.");
105 ostringstream script;
106 script << expr << endl;
107 script << "!('" << Sentinel << "')" << ENTER;
108 string istr = script.str();
109 write(P2C[1], istr.c_str(), istr.length());
110
111 string ostr;
112 int n = buffer_size;
113 char buffer[n+1]; // make sure the last one is '\0'
114 int nio;
115 while(true) {
116 for(int i=0; i<n+1; i++) buffer[i] = '\0';
117 nio = read(C2P[0], buffer, n);
118 if(nio>0) ostr += buffer;
119 else throw Error(ostr);
120 auto cpos = ostr.find(Sentinel);
121 if(cpos!=string::npos) {
122 const char* WhiteSpace = " \t\v\r\n";
123 auto lpos = ostr.find_last_not_of(WhiteSpace);
124 if(ostr[lpos]!='0') read(C2P[0], buffer, n); // last 0, due to Sentinel
125 ostr.erase(cpos);
126 break;
127 }
128 }
129 string_replace_all(ostr, "`", "");
130 string_trim(ostr);
131
132 if(ostr.find("***")!=string::npos) {
133 cout << endl << expr << endl << endl;
134 throw Error(ostr.c_str());
135 }
136 return ostr;
137 }
138
139 //-----------------------------------------------------------
140 // Form Class
141 //-----------------------------------------------------------
143
144 void Form::Exit() {
145 if(getpid()!=pid) return;
146 if(inited && !exited) {
147 string exit_cmd = "\n.end\n" + Prompt +"\n";
148 write(io[0][1], exit_cmd.c_str(), exit_cmd.length());
149 char buffer[8];
150 read(io[1][0], buffer, 8);
151 int st;
152 waitpid(fpid, &st, WUNTRACED);
153 }
154 inited = false;
155 exited = true;
156 }
157
158 void Form::Init(string form_path) {
159 if(inited) return;
160 inited = true;
161 pid = getpid();
162
163 if (pipe(io[0])==-1 || pipe(io[1])==-1 || pipe(stdo)==-1) {
164 inited = false;
165 exited = true;
166 throw Error("pipe failed in Form::Init.");
167 }
168
169 fpid = fork();
170 if (fpid == 0) {
171 if(setpgid(0,0)) throw Error("setpgid failed in Form::Init.");
172 close(io[0][1]);
173 close(io[1][0]);
174 close(stdo[0]);
175 dup2(stdo[1], 1);
176
177 auto cpid = getpid(); // current process id
178 ostringstream oss;
179 oss << "init-" << cpid << ".frm";
180
181 std::ofstream ofs;
182 ofs.open(oss.str().c_str(), ios::out);
183 if (!ofs) {
184 inited = false;
185 exited = true;
186 throw Error("failed to open init.frm file!");
187 }
188 ofs << "Off Statistics;" << endl;
189 ofs << "#ifndef `PIPES_'" << endl;
190 ofs << " #message \"No pipes found\";" << endl;
191 ofs << " .end;" << endl;
192 ofs << "#endif" << endl;
193 ofs << "#if (`PIPES_' <= 0)" << endl;
194 ofs << " #message \"No pipes found\";" << endl;
195 ofs << " .end;" << endl;
196 ofs << "#endif" << endl;
197 ofs << "#procedure put(mexp)" << endl;
198 ofs << " Format Nospaces;" << endl;
199 ofs << " ON NoSpacesInNumbers;" << endl;
200 ofs << " #write \""<<Sentinel<<"\\n\"" << endl;
201 ofs << " #toexternal \"%E\", `mexp'" << endl;
202 ofs << " #toexternal \""<<Sentinel<<"\"" << endl;
203 ofs << " #toexternal \"\\n\"" << endl;
204 ofs << "#endprocedure" << endl;
205 ofs << "#setexternal `PIPE1_';" << endl;
206 ofs << "#toexternal \"OK\"" << endl;
207 ofs << "Local [o]=0;" << endl;
208 ofs << ".sort" << endl;
209 ofs << "Format Mathematica;" << endl;
210 ofs << "#prompt \"" << Prompt << "\"" << endl;
211 ofs << "#fromexternal-" << endl;
212 ofs << ".end" << endl;
213 ofs.close();
214
215 execlp(form_path.c_str(), form_path.c_str(),
216 "-pipe",
217 (to_string(io[0][0])+","+to_string(io[1][1])).c_str(),
218 "-M", ("init-"+to_string(cpid)).c_str(),
219 NULL);
220 exit(0);
221 }
222
223 close(io[0][0]);
224 close(io[1][1]);
225 close(stdo[1]);
226
227 char buffer[1024];
228 read(io[1][0], buffer, sizeof(buffer));
229 char* p = strstr(buffer, "\n");
230 if(p==NULL){
231 inited = false;
232 exited = true;
233 cout << "the return is: <|" << buffer << "|>" << endl;
234 throw Error("Init Failed: Expect a Line break!");
235 }
236 sprintf(p, ",%d\n\n", fpid);
237 write(io[0][1], buffer, strlen(buffer));
238 read(io[1][0], buffer, sizeof(buffer));
239 p = strstr(buffer, "OK");
240 if(p==NULL || p!=buffer) {
241 inited = false;
242 exited = true;
243 throw Error("Init Failed: Expect OK!");
244 }
245
246 ostringstream oss;
247 oss << "init-" << fpid << ".frm";
248 if(file_exists(oss.str().c_str())) remove(oss.str().c_str());
249
250 if(true) { // read the terminal output
251 string estr;
252 int n = 1024;
253 char buffer[n+1]; // make sure the last one is '\0'
254 int nio;
255 while(true) {
256 for(int i=0; i<n+1; i++) buffer[i] = '\0';
257 nio = read(stdo[0], buffer, n);
258 if(nio>0) estr += buffer;
259 auto cpos = estr.find(Sentinel);
260 if(cpos!=string::npos) break;
261 cpos = estr.find("-->");
262 if(cpos!=string::npos) {
263 inited = false;
264 exited = true;
265 throw Error(estr);
266 }
267 }
268 }
269 }
270
271 string Form::Execute(const string & script, const string & out_var) {
272 if(exited) throw Error("Form has already exited.");
273 if(getpid() != pid) throw Error("Form: can not Execute on child process.");
274 string istr = script;
275 istr += "\n.sort\n#call put(";
276 istr += out_var;
277 istr += ")\n.sort\n";
278 istr += Prompt + "\n"; // prompt
279
280 write(io[0][1], istr.c_str(), istr.length());
281
282 string ostr;
283 int n = buffer_size;
284 char buffer[n+1]; // make sure the last one is '\0'
285 int nio;
286
287 string estr;
288 while(true) {
289 for(int i=0; i<n+1; i++) buffer[i] = '\0';
290 nio = read(stdo[0], buffer, n);
291 if(nio>0) estr += buffer;
292 auto cpos = estr.find("-->");
293 if(cpos!=string::npos) {
294 inited = false;
295 exited = true;
296 throw Error(estr);
297 }
298 cpos = estr.find(Sentinel);
299 if(cpos!=string::npos) break;
300 }
301
302 while(true) {
303 for(int i=0; i<n+1; i++) buffer[i] = '\0';
304 nio = read(io[1][0], buffer, n);
305 if(nio>0) ostr += buffer;
306 else {
307 string estr;
308 while(true) {
309 for(int i=0; i<n+1; i++) buffer[i] = '\0';
310 nio = read(stdo[0], buffer, n);
311 if(nio<=0) break;
312 estr += buffer;
313 }
314 inited = false;
315 exited = true;
316 throw Error(estr.c_str());
317 }
318 auto cpos = ostr.find(Sentinel);
319 if(cpos!=string::npos) {
320 ostr.replace(cpos, Sentinel.length(), "");
321 break;
322 }
323 }
324
325 return ostr;
326 }
327
328
329}
Basic header file.
bool file_exists(const char *fn)
Definition Process.cpp:9
#define ENTER
Definition Process.cpp:18
class used to wrap error message
Definition BASIC.h:242
static int buffer_size
Definition BASIC.h:800
string Sentinel
Definition BASIC.h:801
void Init(string fer_path="fer64")
Definition Process.cpp:36
string Execute(string)
Definition Process.cpp:102
void Exit()
Definition Process.cpp:144
string Sentinel
Definition BASIC.h:823
void Init(string form_path="form")
Definition Process.cpp:158
static int buffer_size
Definition BASIC.h:822
string Prompt
Definition BASIC.h:824
string Execute(const string &script, const string &out_var="[o]")
Definition Process.cpp:271
HepLib namespace.
Definition BASIC.cpp:17
bool file_exists(string fn)
Definition BASIC.h:289
void string_replace_all(string &str, const string &from, const string &to)
void string_trim(string &str)