source: Sophya/trunk/SophyaPI/PIext/cxxexecutor.cc@ 1224

Last change on this file since 1224 was 1224, checked in by ercodmgr, 25 years ago

Ajout de cxxexecutor (Execution C++ en ligne ds piapp) - CMV+Reza 11/10/2000

  • Property svn:executable set to *
File size: 15.4 KB
RevLine 
[1224]1#include "cxxexecutor.h"
2
3#include <typeinfo>
4
5#include "dvlist.h"
6
7#include "nomgadapter.h"
8#include "pistdimgapp.h"
9
10
11
12/* --Methode-- */
13CxxExecutor::CxxExecutor(PIACmd *mpiac, PIStdImgApp* /* app */)
14 : mCompOpt(""), mLinkOpt(""), mMyLibs("")
15{
16mUserCode.resize(0);
17mIncList.resize(0);
18mCallArgs.resize(0);
19
20NamedObjMgr omg;
21
22// On enregistre les nouvelles commandes
23string hgrp = "CxxExecutorCmd";
24string usage,kw;
25
26kw = "c++exec";
27usage = "c++exec: Execute the following c++ user code\n";
28usage+= "Usage: c++exec c++ user code";
29mpiac->RegisterCommand(kw, usage, this, hgrp);
30
31kw = "c++execfrf";
32usage = "c++execfrf: Execute c++ user code contained in a file\n";
33usage+= "Usage: c++execfrf fileuser.cc";
34mpiac->RegisterCommand(kw, usage, this, hgrp);
35
36kw = "c++args";
37usage = "c++args: Define user function arguments\n";
38usage+= "Usage: c++args arg1 arg2 arg3 ...";
39mpiac->RegisterCommand(kw, usage, this, hgrp);
40
41kw = "c++create";
42usage = "c++create: create a file to be used by spiapp\n";
43usage+= "Usage: c++create file.cc func c++ user code...\n";
44mpiac->RegisterCommand(kw, usage, this, hgrp);
45
46kw = "c++createfrf";
47usage = "c++createfrf: create a file \"file.cc\"to be used by spiapp\n";
48usage+= " with a user file \"fileuser.cc\"\n";
49usage+= "Usage: c++createfrf file.cc func fileuser.cc\n";
50mpiac->RegisterCommand(kw, usage, this, hgrp);
51
52kw = "c++compile";
53usage = "c++compile: compile a file (file.cc -> file.so)\n";
54usage+= "Usage: c++compile file\n";
55usage+= "Warning: give \"file\" or \"file.so\" to create \"file.so\" from \"file.cc\"\n";
56usage+= " : to be used before c++link";
57mpiac->RegisterCommand(kw, usage, this, hgrp);
58
59kw = "c++link";
60usage = "c++link: link function \"func\" in file.so to spiapp\n";
61usage+= "Usage: c++link file.so func";
62mpiac->RegisterCommand(kw, usage, this, hgrp);
63
64kw = "c++include";
65usage = "c++include: give personnal includes to be used\n";
66usage+= "Usage: c++include myinc1.h myinc2.h ...\n";
67usage+= "Warning: to be used before c++create... c++exec...";
68mpiac->RegisterCommand(kw, usage, this, hgrp);
69
70kw = "c++compileopt";
71usage = "c++compileopt: give additionnal compile options\n";
72usage+= "Usage: c++compileopt -g -O5 -IMy_Inc_Dir ...\n";
73usage+= "Warning: to be used before c++compile";
74mpiac->RegisterCommand(kw, usage, this, hgrp);
75
76kw = "c++linkopt";
77usage = "c++linkopt: give additionnal link options\n";
78usage+= "Usage: c++linkopt -g -O5 ...";
79usage+= "Warning: to be used before c++compile";
80mpiac->RegisterCommand(kw, usage, this, hgrp);
81
82kw = "c++mylibs";
83usage = "c++mylibs: give additionnal libraries\n";
84usage+= "Usage: c++mylibs -LMy_Lib_Dir -lmylib1 -lmylib2 ...";
85usage+= "Warning: to be used before c++compile";
86mpiac->RegisterCommand(kw, usage, this, hgrp);
87
88kw = "c++setvar";
89usage = "c++setvar: Setting test variable \n";
90usage+= "c++setvar varname varcontent ";
91mpiac->RegisterCommand(kw, usage, this, hgrp);
92
93kw = "c++getvar";
94usage = "c++getvar: Getting test variable content\n";
95usage+= "c++getvar varname ";
96mpiac->RegisterCommand(kw, usage, this, hgrp);
97
98kw = "c++varlist";
99usage = "c++getvar: Printing test variable list\n";
100usage+= "c++varlist ";
101mpiac->RegisterCommand(kw, usage, this, hgrp);
102
103}
104
105/* --Methode-- */
106CxxExecutor::~CxxExecutor()
107{
108}
109
110/* --Methode-- */
111int CxxExecutor::Execute(string& kw, vector<string>& tokens)
112{
113int rc=0;
114if(kw == "c++exec" || kw == "c++execfrf") {
115 if(tokens.size()<1) {
116 cout<<"Usage: c++exec c++ user code"<<endl;
117 cout<<"Usage: c++execfrf fileuser.cc"<<endl;
118 return(1);
119 }
120 if(kw == "c++exec") rc = FillUserCode(tokens,0);
121 if(kw == "c++execfrf") rc = FillUserCode(tokens[0]);
122 if(rc) return(1);
123 rc = CrFile(); if(rc) return(1);
124 rc = Compile(); if(rc) return(1);
125 rc = Link(); if(rc) return(1);
126 rc = Call(); if(rc) return(1);
127
128} else if(kw == "c++args") {
129 mCallArgs.resize(0);
130 if(tokens.size()>=1)
131 for(uint_4 i=0;i<tokens.size();i++) mCallArgs.push_back(tokens[i]);
132
133} else if(kw == "c++create") {
134 if(tokens.size()<3) {
135 cout<<"Usage: c++create file.cc func c++ user code ..."<<endl;
136 return(1);
137 }
138 rc = FillUserCode(tokens,2); if(rc) return(1);
139 rc = CrFile(tokens[0],tokens[1]); if(rc) return(1);
140
141} else if(kw == "c++createfrf") {
142 if(tokens.size()<3) {
143 cout<<"Usage: c++createfrf file.cc func fileuser.cc"<<endl;
144 return(1);
145 }
146 rc = FillUserCode(tokens[2]); if(rc) return(1);
147 rc = CrFile(tokens[0],tokens[1]); if(rc) return(1);
148
149} else if(kw == "c++compile") {
150 if(tokens.size()>=1) rc = Compile(tokens[0]);
151 else rc = Compile();
152 if(rc) return(1);
153
154} else if(kw == "c++link") {
155 if(tokens.size()>=2) rc = Link(tokens[0],tokens[1]);
156 else if(tokens.size()>=1) rc = Link(tokens[0]);
157 else rc = Link();
158 if(rc) return(1);
159
160} else if(kw == "c++include") {
161 mIncList.resize(0);
162 if(tokens.size()>=1)
163 for(uint_4 i=0;i<tokens.size();i++) mIncList.push_back(tokens[i]);
164
165} else if(kw == "c++compileopt") {
166 mCompOpt = "";
167 if(tokens.size()>=1) {
168 for(uint_4 i=0;i<tokens.size();i++) mCompOpt += tokens[i] + " ";
169 }
170
171} else if(kw == "c++linkopt") {
172 mLinkOpt = "";
173 if(tokens.size()>=1) {
174 for(uint_4 i=0;i<tokens.size();i++) mLinkOpt += tokens[i] + " ";
175 }
176
177} else if(kw == "c++mylibs") {
178 mMyLibs = "";
179 if(tokens.size()>=1) {
180 for(uint_4 i=0;i<tokens.size();i++) mMyLibs += tokens[i] + " ";
181 }
182
183} else if(kw == "c++setvar") {
184 if(tokens.size()<2) {
185 cerr << " Usage: c++setvar varname varcontent " << endl;
186 return(1);
187 }
188 string varcont = tokens[1];
189 if(tokens.size()>2)
190 for(uint_4 i=2;i<tokens.size();i++) varcont += " " + tokens[i] ;
191 NamedObjMgr omg;
192 omg.SetVar(tokens[0], varcont);
193} else if(kw == "c++getvar") {
194 if(tokens.size()<1) {
195 cerr << " Usage: c++getvar varname " << endl;
196 return(1);
197 }
198 NamedObjMgr omg;
199 cout << "c++getvar(" << tokens[0] << ")=" << omg.GetVar(tokens[0]) << endl;
200} else if(kw == "c++varlist") {
201 NamedObjMgr omg;
202 cout << omg.GetVarList();
203}
204
205
206return(0);
207}
208
209/* --Methode-- */
210int CxxExecutor::CrFile(string cfilename,string func)
211{
212ofstream os(cfilename.c_str(),ios::out);
213if(!os) {
214 cout<<"CxxExecutor::CrFile: unable to open "<<cfilename<<endl;
215 return 1;
216}
217
218PutInclude(os);
219os<<endl;
220
221PutIncludeUser(os);
222os<<endl;
223
224os<<"extern \"C\" {"<<endl;
225os<<" int "<<func<<"( vector<string>& args );"<<endl;
226os<<"}"<<endl<<endl;
227os<<"int "<<func<<"( vector<string>& args )"<<endl;
228os<<"{"<<endl;
229os<<"// Some definitions to help using spiapp;"<<endl;
230os<<"NamedObjMgr omg;"<<endl;
231os<<"Services2NObjMgr& srvo = *omg.GetServiceObj();"<<endl;
232os<<"//omg.AddObj(OBJECT* object,string nom_object);"<<endl;
233os<<endl;
234
235PutObject(os);
236os<<endl;
237
238PutVar(os);
239os<<endl;
240
241PutUserCode(os);
242os<<endl;
243
244os<<endl;
245os<<"return 0;"<<endl;
246os<<"}"<<endl;
247
248cout<<"File "<<cfilename<<" for function "<<func<<" created"<<endl;
249return 0;
250}
251
252/* --Methode-- */
253void CxxExecutor::PutInclude(ofstream& os)
254{
255os<<"#include \"machdefs.h\""<<endl
256 <<endl
257
258 <<"//---- System et stdc++ include files"<<endl
259 <<"#include <stdio.h>"<<endl
260 <<"#include <stdlib.h>"<<endl
261 <<"#include <math.h>"<<endl
262 <<"#include <ctype.h>"<<endl
263 <<"#include <string.h>"<<endl
264 <<"#include <iostream.h>"<<endl
265 <<"#include <fstream.h>"<<endl
266 <<"#include <complex>"<<endl
267 <<endl
268
269 <<"#include <typeinfo>"<<endl
270 <<"#include <string>"<<endl
271 <<"#include <vector>"<<endl
272 <<"#include <map>"<<endl
273 <<"#include <functional>"<<endl
274 <<"#include <list>"<<endl
275 <<endl
276
277 <<"//---- Sophya include files"<<endl
278 <<"#include \"systools.h\""<<endl
279 <<"#include \"ntools.h\""<<endl
280 <<"#include \"array.h\""<<endl
281 <<"#include \"histats.h\""<<endl
282 <<endl
283
284 <<"//---- Spiapp include files"<<endl
285 <<"#include \"nobjmgr.h\""<<endl
286 <<"#include \"servnobjm.h\""<<endl
287 <<endl
288
289 <<"#define KeepObj(obj) ___nomobj = #obj; omg.AddObj(obj,___nomobj);"<<endl
290 <<"#define KeepVar(var) ___nomobj = #var; omg.GetVarList().Get(___nomobj) = var ;"<<endl
291 <<endl;
292
293return;
294}
295
296/* --Methode-- */
297void CxxExecutor::PutIncludeUser(ofstream& os)
298{
299if(mIncList.size()<1) return;
300for(uint_4 i=0;i<mIncList.size();i++)
301 os<<"#include \""<<mIncList[i]<<"\""<<endl;
302}
303
304/* --Methode-- */
305void CxxExecutor::PutObject(ofstream& os)
306{
307NamedObjMgr omg;
308NObjMgrAdapter* objmgrad;
309vector<string> objlist;
310string patt = "*";
311omg.GetObjList(patt,objlist);
312int nobjs = objlist.size();
313
314os<<"//-------------- Object List --------------"<<endl;
315os<<"//Number of objects = "<<nobjs<<endl;
316os<<"string ___nomobj;"<<endl<<endl;
317if(nobjs<=0) return;
318
319string dir,nobj,stmp,obtype;
320for(int i=0;i<nobjs;i++) {
321 objmgrad = omg.GetObjAdapter(objlist[i]);
322 omg.ParseObjectName(objlist[i],dir,nobj);
323 obtype = objmgrad->GetDataObjType();
324 stmp = "___" + nobj;
325
326 os<<"___nomobj = \""<<nobj<<"\";"<<endl;
327 os<<obtype<<"* "<<stmp
328 <<" = dynamic_cast< "<<obtype<<" * >(omg.GetObj(___nomobj));"<<endl;
329 os<<"if("<<stmp<<"==NULL) throw NullPtrError"
330 <<"(\"CxxExecutor::PutObject: Non existing object "<<nobj
331 <<"... please update file\");"<<endl;
332 os<<obtype<<"& "<<nobj<<" = (*"<<stmp<<");"<<endl<<endl;
333}
334
335return;
336}
337
338/* --Methode-- */
339void CxxExecutor::PutVar(ofstream& os)
340{
341os<<"//-------------- Variable List --------------"<<endl;
342NamedObjMgr omg;
343DVList& varlist = omg.GetVarList();
344// varlist.Show(); varlist.Print();
345DVList::ValList::const_iterator it;
346for(it=varlist.Begin(); it!=varlist.End(); it++) {
347 string key = (*it).first;
348 os<<"___nomobj = \""<<key<<"\";"<<endl;
349 os<<"MuTyV & "<<key<<" = omg.GetVarList().Get(___nomobj);"<<endl;
350}
351
352}
353
354/* --Methode-- */
355void CxxExecutor::PutUserCode(ofstream& os)
356{
357os<<"//--------------------------------------------//"<<endl;
358os<<"//------------- Code utilisateur -------------//"<<endl;
359os<<"//--------------------------------------------//"<<endl;
360os<<endl;
361if(mUserCode.size()<1) return;
362for(uint_4 i=0;i<mUserCode.size();i++) os<<mUserCode[i]<<endl;
363}
364
365/* --Methode-- */
366int CxxExecutor::FillUserCode(vector<string>& usercode,uint_4 first)
367// - first is the first position in the vector<> where the code starts
368{
369mUserCode.resize(0);
370uint_4 nus = usercode.size();
371if(nus<=first) {
372 cout<<"CxxExecutor::FillUserCode: no user code"<<endl;
373 return 1;
374}
375string dum = "";
376// On ajoute un blanc pour les chaines de caracteres contenant des blancs
377for(uint_4 i=first;i<nus;i++) dum += " " + usercode[i];
378// Tout dans une seule ligne pour eviter les pbs (cf au bas du fichier)
379mUserCode.push_back(dum);
380cout<<"User code filled from standard input"<<endl;
381return 0;
382}
383
384/* --Methode-- */
385int CxxExecutor::FillUserCode(string filename)
386{
387mUserCode.resize(0);
388
389ifstream is(filename.c_str());
390if(!is) {
391 cout<<"CxxExecutor::FillUserCode: unable to open "<<filename<<endl;
392 return 1;
393}
394
395int nline = 4096; // Au plus 4096 characters par ligne!
396char *str = new char[nline+2];
397while(is)
398 {is.getline(str,nline); mUserCode.push_back((string) str);}
399delete [] str;
400if(mUserCode.size()<=0) {
401 return 2;
402 cout<<"CxxExecutor::FillUserCode: no user code"<<endl;
403}
404
405cout<<"User code filled from file"<<filename<<endl;
406return 0;
407}
408
409/* --Methode-- */
410int CxxExecutor::Compile(string rootfilename)
411{
412string fc = rootfilename + ".cc";
413string fl = rootfilename + ".so";
414cout<<"Compile: "<<rootfilename<<endl;
415int rc = 0;
416rc = CrMakefile();
417if(rc) return(1);
418string make = "make -f cxx_spiapp_Makefile";
419 make += " CXXFLAGS=\"" + mCompOpt + "\"";
420 make += " LDFLAGS=\"" + mLinkOpt + "\"";
421 make += " MYLIBS=\"" + mMyLibs + "\"";
422 make += " " + rootfilename;
423rc = system(make.c_str());
424if(rc)
425 {cout<<"CxxExecutor::Compile : \n"<<make<<" Failed"<<endl;
426 return 1000+rc;}
427return 0;
428}
429
430/* --Methode-- */
431int CxxExecutor::CrMakefile(void)
432{
433ofstream os("cxx_spiapp_Makefile",ios::out);
434if(!os)
435 {cout<<"CxxExecutor::CrMakefile: unable to open file for Makefile"<<endl;
436 return 1;}
437//---------------------------------------------------------------------
438os<<"MODULEDECCXXFLAGS := -msg_quiet"<<endl;
439os<<"include $(DPCBASEREP)/Include/MakefileUser.h"<<endl;
440os<<"MYLIBS ="<<endl;
441os<<"LIBS = -L$(SLB) -lPI -lextsophya -lsophya -lm"<<endl;
442os<<"ifeq ($(MACHEROS),OSF1)"<<endl;
443os<<"LIBS := $(LIBS) -lfor"<<endl;
444os<<"endif"<<endl;
445os<<"ifeq ($(MACHEROS),Linux)"<<endl;
446os<<"LIBS := $(LIBS) -ldl -lf2c"<<endl;
447os<<"endif"<<endl;
448os<<"%.so:$(OBJ)%.o"<<endl;
449os<<"%:%.cc"<<endl;
450os<<"%:%.o"<<endl;
451os<<"%.o:%.cc"<<endl;
452os<<"%.o:%.c"<<endl;
453os<<"%:%.c"<<endl;
454os<<endl;
455os<<".PRECIOUS: %.so"<<endl;
456os<<endl;
457os<<"%:%.so"<<endl;
458os<<"\t"<<"echo $@ \" made (.so) \""<<endl;
459os<<"%.so:$(OBJ)%.o"<<endl;
460os<<"\t"<<"$(LINK.cc) -shared -o $@ $< $(LIBS) $(MYLIBS)"<<endl;
461os<<"$(OBJ)%.o:%.cc"<<endl;
462os<<"\t"<<"$(COMPILE.cc) -o $@ $<"<<endl;
463os<<"$(OBJ)%.o:%.c"<<endl;
464os<<"\t"<<"$(COMPILE.c) -c $(CFLAGS) $(USERFLAGS) -o $@ $<"<<endl;
465//---------------------------------------------------------------------
466return 0;
467}
468
469/* --Methode-- */
470int CxxExecutor::Link(string libname,string func)
471{
472NamedObjMgr omg;
473PIACmd* mpiac = omg.GetImgApp()->CmdInterpreter();
474string key("link");
475vector<string> arg; arg.push_back(libname); arg.push_back(func);
476int rc = mpiac->ExecuteCommand(key,arg);
477cout<<"Link from "<<libname<<" for function "<<func
478 <<" (rc="<<rc<<")"<<endl;
479return 0;
480}
481
482/* --Methode-- */
483int CxxExecutor::Call(string func)
484{
485NamedObjMgr omg;
486PIACmd* mpiac = omg.GetImgApp()->CmdInterpreter();
487string key("call");
488vector<string> arg; arg.push_back(func);
489if(mCallArgs.size()>0)
490 for(int i=0;i<mCallArgs.size();i++) arg.push_back(mCallArgs[i]);
491mpiac->ExecuteCommand(key,arg);
492return 0;
493}
494
495/* --Methode-- DO NOT DELETE.... cmv property !!!
496int CxxExecutor::FillUserCode(vector<string>& usercode,uint_4 first)
497// - first is the first position in the vector<> where the code starts
498{
499mUserCode.resize(0);
500uint_4 nus = usercode.size();
501if(nus<=first) {
502 cout<<"CxxExecutor::FillUserCode: no user code"<<endl;
503 return 1;
504}
505// **** 1er probleme ****
506// - Pour la lisibilite et eviter les bugs avec les chaines de caracteres
507// contenant des blancs, on ne casse les lignes qu'apres un ";" a condition
508// qu'il ne soit pas dans une chaine de caracteres c'est a dire
509// entoure de "....;....".
510// - Attention aux " dans les chaines de caracteres: "...\"..."
511// - Bugs non-gere pour les tortures: ".....\\" suivi par une autre
512// chaine de caracteres qui contient un ';'
513// ex: cout<<"aaa\\"; cout<<"blabla;blabla";
514// **** 2ieme probleme ****
515// - Le decodeur de ligne va couper les commentaires qui contiennent des blancs:
516// "salut ca va" --> tokens[0]="salut tokens[1]=ca tokens[2]=va" --> "salutcava"
517// - On contourne partiellement le pb en ajoutant un blanc en debut des tokens[]
518// identifies comme etant dans une chaine de caracteres (mais impossible de gerer
519// si il y a plusieurs blancs!): "salut ca va" -> "salut ca va"
520// **** Conclusion ****
521// Pour ecrire du code sophistique, le faire dans un fichier
522string dum = "";
523bool lastchar = false;
524bool comment = false;
525for(uint_4 i=first;i<nus;i++) {
526 const char* str = usercode[i].c_str();
527 size_t lstr= strlen(str);
528 for(uint_4 j=0;j<lstr;j++) {
529 // debut de mot dans un commentaire -> ajouter un blanc
530 if(j==0 && comment) dum += " ";
531 // on arrive sur un " : debut ou fin commentaire? inactif (\")?
532 if(str[j]=='"') {
533 if(j==0) comment = (comment) ? false: true;
534 else {if(str[j-1]!='\\') comment = (comment) ? false: true;}
535 }
536 dum += str[j];
537 if( i==nus-1 && j==lstr-1 ) lastchar = true;
538 // On charge la string "dum" si : 1-/ on a un ";"
539 // 2-/ c'est le dernier charactere
540 if((str[j]==';' && !comment) || lastchar)
541 {mUserCode.push_back(dum); dum = "";}
542 }
543}
544cout<<"User code filled from standard input"<<endl;
545return 0;
546}
547*/
548
Note: See TracBrowser for help on using the repository browser.