source: Sophya/trunk/SophyaLib/SysTools/commander.cc@ 2464

Last change on this file since 2464 was 2464, checked in by ansari, 22 years ago

Correction mineure ds commander.cc - Reza 26/11/2003

File size: 53.5 KB
Line 
1#include "commander.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include <math.h>
6
7#include "strutil.h"
8#include "strutilxx.h"
9#include "srandgen.h"
10
11
12// ------------------------------------------------------------
13// Bloc de commandes (Foreach, ...)
14// Classe CommanderBloc
15// ------------------------------------------------------------
16/*!
17 \class SOPHYA::CommanderBloc
18 \ingroup SysTools
19 Class for internal use by SOPHYA::Commander to handle loops
20*/
21class CommanderBloc {
22public:
23 enum BType { BT_None, BT_ForeachList, BT_ForeachInt, BT_ForeachFloat };
24
25 CommanderBloc(Commander* piac, CommanderBloc* par, string& kw, vector<string>& args);
26 ~CommanderBloc();
27 inline CommanderBloc* Parent() { return(parent); }
28 inline bool CheckOK() { return blkok; }
29 inline void AddLine(string& line)
30 { lines.push_back(line); bloclineid.push_back(lines.size()); }
31 void AddLine(string& line, string& kw);
32 inline void AddBloc(CommanderBloc* blk)
33 { blocs.push_back(blk); bloclineid.push_back(-blocs.size()); }
34 CommanderBloc* Execute();
35 inline int& TestLevel() { return testlevel; }
36 inline int& LoopLevel() { return looplevel; }
37 inline bool CheckBloc()
38 { return ((testlevel == 0)&&(looplevel == 0)&&(!scrdef)); }
39
40protected:
41 Commander* _commander;
42 CommanderBloc* parent;
43 bool blkok; // true -> block OK
44 BType typ; // foreach , integer loop, float loop, test
45 string varname;
46 vector<string> strlist;
47 vector<string> lines;
48 vector<CommanderBloc *> blocs;
49 vector<int> bloclineid;
50 int i1,i2,di;
51 float f1,f2,df;
52 int testlevel; // niveau d'imbrication des if
53 int looplevel; // niveau d'imbrication des for/foreach
54 bool scrdef; // true -> commande defscript ds for/foreach
55};
56
57/* --Methode-- */
58CommanderBloc::CommanderBloc(Commander* piac, CommanderBloc* par, string& kw, vector<string>& args)
59{
60_commander = piac;
61parent = par;
62blkok = false;
63typ = BT_None;
64i1 = 0; i2 = -1; di = 1;
65f1 = 0.; f2 = -1.; df = 1.;
66testlevel = looplevel = 0;
67scrdef = false;
68
69if ((args.size() < 2) || !isalpha((int)args[0][0]) ) return;
70if ((kw != "foreach") && (kw != "for")) return;
71varname = args[0]; // $CHECK$ Variable name should be checked
72//if (isalpha((int)args[1][0]) ) { This is a foreach bloc with string list
73if (kw == "foreach" ) { // This is a foreach bloc with string list
74 if ((args[1] != "(") || (args[args.size()-1] != ")") ) return;
75 for(int kk=2; kk<args.size()-1; kk++) strlist.push_back(args[kk]);
76 typ = BT_ForeachList;
77 blkok = true;
78 }
79else { // This is an integer or float loop
80 size_t l = args[1].length();
81 size_t p = args[1].find(':');
82 size_t pp = args[1].find('.');
83 bool fl = (pp < l) ? true : false; // Float loop or integer loop
84 if (p >= l) return; // Syntaxe error
85 string a1 = args[1].substr(0, p);
86 string aa = args[1].substr(p+1);
87 p = aa.find(':');
88 string a2, a3;
89 bool hasa3 = false;
90 if (p < aa.length() ) {
91 a2 = aa.substr(0,p);
92 a3 = aa.substr(p+1);
93 hasa3 = true;
94 }
95 else a2 = aa;
96 if (fl) {
97 typ = BT_ForeachFloat;
98 blkok = true;
99 f1 = atof(a1.c_str());
100 f2 = atof(a2.c_str());
101 if (hasa3) df = atof(a3.c_str());
102 else df = 1.;
103 }
104 else {
105 typ = BT_ForeachInt;
106 blkok = true;
107 i1 = atoi(a1.c_str());
108 i2 = atoi(a2.c_str());
109 if (hasa3) di = atoi(a3.c_str());
110 else di = 1;
111 }
112 }
113}
114
115/* --Methode-- */
116CommanderBloc::~CommanderBloc()
117{
118for(int k=0; k<blocs.size(); k++) delete blocs[k];
119}
120
121/* --Methode-- */
122void CommanderBloc::AddLine(string& line, string& kw)
123{
124 AddLine(line);
125 if (kw == "if") testlevel++;
126 else if (kw == "endif") testlevel--;
127 else if ((kw == "for") || (kw == "foreach")) looplevel++;
128 else if (kw == "end") looplevel--;
129 else if (kw == "defscript") scrdef = true;
130}
131
132/* --Methode-- */
133CommanderBloc* CommanderBloc::Execute()
134{
135// cout << " DBG * CommanderBloc::Execute() " << typ << " - " << bloclineid.size() <<
136// " I1,I2=" << i1 << " , " << i2 << " , " << di << endl;
137string cmd;
138int k=0;
139int kj=0;
140int kk=0;
141char buff[32];
142int rcc = 0;
143
144int mxloop = _commander->GetMaxLoopLimit();
145
146if (typ == BT_ForeachList) // foreach string loop
147 for(k=0; k<strlist.size(); k++) {
148 cmd = "set " + varname + " '" + strlist[k] + "'";
149 _commander->Interpret(cmd);
150 for(kj=0; kj<bloclineid.size(); kj++) {
151 kk = bloclineid[kj];
152 if (kk > 0) {
153 rcc = _commander->Interpret(lines[kk-1]);
154 if (rcc == 77766) break;
155 }
156 else blocs[-kk-1]->Execute();
157 }
158 if (rcc == 77766) break;
159 }
160else if (typ == BT_ForeachInt) // Integer loop
161 for(int i=i1; i<i2; i+=di) {
162 k++;
163 if ((mxloop>0) && (k > mxloop)) {
164 cout << ">>> Maximum CommanderBloc loop limit ("<< mxloop << ") -> break " << endl;
165 break;
166 }
167 sprintf(buff, " %d", i);
168 cmd = "set " + varname + buff;
169 _commander->Interpret(cmd);
170 for(kj=0; kj<bloclineid.size(); kj++) {
171 kk = bloclineid[kj];
172 if (kk > 0) {
173 rcc = _commander->Interpret(lines[kk-1]);
174 if (rcc == 77766) break;
175 }
176 else blocs[-kk-1]->Execute();
177 }
178 if (rcc == 77766) break;
179 }
180else if (typ == BT_ForeachFloat) // float loop
181 for(float f=f1; f<f2; f+=df) {
182 k++;
183 if ((mxloop>0) && (k > mxloop)) {
184 cout << ">>> Maximum CommanderBloc loop limit ("<< mxloop << ") -> break " << endl;
185 break;
186 }
187 sprintf(buff, " %g", f);
188 cmd = "set " + varname + buff;
189 _commander->Interpret(cmd);
190 for(kj=0; kj<bloclineid.size(); kj++) {
191 kk = bloclineid[kj];
192 if (kk > 0) {
193 rcc = _commander->Interpret(lines[kk-1]);
194 if (rcc == 77766) break;
195 }
196 else blocs[-kk-1]->Execute();
197 }
198 if (rcc == 77766) break;
199 }
200
201return(parent);
202}
203
204// ---------------------------------------------------------------
205// Classe CommanderScript
206// Definition et execution d'un script de Commander
207// script : Une liste de commande Commander - Lors de l'execution,
208// les variables-argument $# $0 $1 sont definies.
209// ---------------------------------------------------------------
210
211/*!
212 \class SOPHYA::CommanderScript
213 \ingroup SysTools
214 Class for internal use by SOPHYA::Commander to handle functions
215 or scripts
216*/
217
218class CommanderScript {
219public:
220 CommanderScript(Commander* piac, string const& name, string const& comm);
221 virtual ~CommanderScript();
222
223 void AddLine(string& line, string& kw);
224 virtual int Execute(vector<string>& args);
225
226 inline string& Name() { return mName; }
227 inline string& Comment() { return mComm; }
228 inline int& TestLevel() { return testlevel; }
229 inline int& LoopLevel() { return looplevel; }
230 inline bool CheckScript()
231 { return ((testlevel == 0)&&(looplevel == 0)&&(!scrdef)&&fgok); }
232
233protected:
234 Commander* _commander;
235 string mName;
236 string mComm;
237 vector<string> lines;
238 int testlevel; // niveau d'imbrication des if
239 int looplevel; // niveau d'imbrication des for/foreach
240 bool scrdef; // true -> commande defscript ds for/foreach
241 bool fgok; // Script name OK
242
243};
244
245/* --Methode-- */
246CommanderScript::CommanderScript(Commander* piac, string const& name,
247 string const& comm)
248{
249_commander = piac;
250testlevel = looplevel = 0;
251scrdef = false;
252mName = name;
253if (!isalpha(name[0])) fgok = false;
254else fgok = true;
255mComm = comm;
256}
257
258/* --Methode-- */
259CommanderScript::~CommanderScript()
260{
261}
262
263/* --Methode-- */
264void CommanderScript::AddLine(string& line, string& kw)
265{
266 if (kw == "if") testlevel++;
267 else if (kw == "endif") testlevel--;
268 else if ((kw == "for") || (kw == "foreach")) looplevel++;
269 else if (kw == "end") looplevel--;
270 else if (kw == "defscript") scrdef = true;
271 lines.push_back(line);
272}
273
274/* --Methode-- */
275int CommanderScript::Execute(vector<string>& args)
276{
277 if (!CheckScript()) return(-1);
278 cout << " CommanderScript::Execute() - Executing script " << Name() << endl;
279 for(int k=0; k<lines.size(); k++) {
280 if (_commander->Interpret(lines[k]) == 77777) break;
281 }
282 return(0);
283}
284
285// ------------------------------------------------------------
286// Classe Commander
287// ------------------------------------------------------------
288typedef void (* DlModuleInitEndFunction) ();
289
290/*!
291 \class SOPHYA::Commander
292 \ingroup SysTools
293 Simple command interpreter with c-shell like syntax and dynamic
294 load capabilities. Can be used to add scripting capabilities
295 to applications
296*/
297
298#define _MAGENTA_ 1
299
300static Commander* cur_commander = NULL;
301/* --Methode-- */
302Commander::Commander()
303{
304system("cp history.pic hisold.pic");
305hist.open("history.pic");
306histon = true;
307trace = false; timing = false;
308gltimer = NULL;
309felevel = 0;
310
311mulinecmd = "";
312mulinefg = false;
313spromptmul = "Cmd> ";
314SetCurrentPrompt(spromptmul);
315curscript = NULL;
316
317CmdBlks.push(NULL);
318list<char> xtx;
319TestsStack.push(xtx);
320curtestresult = true;
321
322// cmdhgrp["All"] = 0;
323
324string kw = "Commander";
325string usage;
326usage = ">>> (Commander) Interpreter's keywords : \n";
327usage += " > set varname string # To set a variable, $varname \n";
328usage += " > get newvarname varname # To set a newvariable, equal to $varname \n";
329usage += " > setol varname patt # Fills varname with object list \n";
330usage += " > unset varname # clear variable definition \n";
331usage += " > rpneval varname RPNExpression # Reverse Polish Notation evaluation \n";
332usage += " > varname = 'string string ...' # To set a variable, $varname \n";
333usage += " > varname = RPNExpression # RPN evaluation / result -> varname \n";
334usage += " > echo string # output string \n";
335usage += " > echo2file filename string # Append the string to the specified file \n";
336usage += " > alias name string # define a command alias \n";
337usage += " > readstdin varname # reads a line from stdin into $varname \n";
338usage += " > foreach varname ( string-list ) # Loop \n";
339usage += " > for varname i1:i2[:di] # Integer loop \n";
340usage += " > for varname f1:f2[:df] # Float loop \n";
341usage += " > end # end loops \n";
342usage += " > if ( test ) then # Conditional test : a == != < > <= >= b \n";
343usage += " > else # Conditional \n";
344usage += " > endif # End of conditional if bloc \n";
345usage += " > break # Delete (clears) all test and loop blocs \n";
346usage += " > return # Stops command execution from a file \n";
347usage += " > defscript endscript # Command script definition \n";
348usage += " > listvars # List of variable names and values \n";
349usage += " > listalias # List of alias names and values \n";
350usage += " > listcommands # List of all known commands \n";
351usage += " > listscripts # List of all known scripts \n";
352usage += " > clearcript # Clear a script definition \n";
353usage += " > exec filename # Execute commands from file \n";
354usage += " > help <command_name> # <command_name> usage info \n";
355usage += " > timingon timingoff traceon traceoff \n";
356string grp = "Commander";
357RegisterHelp(kw, usage, grp);
358
359kw = "RPNEvaluator";
360usage = " Reverse Polish Notation (HP calculator like) expression evaluation \n";
361usage += " >> Stack: \n";
362usage += " ... (4) (3) z=(2) y=(1) x=(0)=Stack.Top() \n";
363usage += " >> Examples: \n";
364usage += " - sin(PI/6): pi 6 / sin \n";
365usage += " - 1*2*...*5: 1 2 3 4 5 product \n";
366usage += " - x=x+y: x = $x $y * \n";
367usage += " >>> Stack operations : \n";
368usage += " print x<>y pop push (duplicate x) \n";
369usage += " >>> Constants (Cst pushed to stack): \n";
370usage += " pi e \n";
371usage += " >>> Arithmetic operators (x,y) --> x@y \n";
372usage += " + - * / % ( (int)y % (int)x )\n";
373usage += " >>> F(X): x --> F(x) \n";
374usage += " chs sqrt sq log log10 exp \n";
375usage += " fabs floor ceil \n";
376usage += " cos sin tan acos asin atan deg2rad rad2deg \n";
377usage += " >>> F(X,Y): (x,y) --> F(x,y) \n";
378usage += " pow atan2 \n";
379usage += " >>> F(): random number generators \n";
380usage += " rand (flat 0..1) norand (normal/gaussian) \n";
381usage += " >>> Stack sum/product/mean/sigma/sigma^2 \n";
382usage += " sum product mean sigma sigma2 sigmean (y->sigma x->mean) \n";
383RegisterHelp(kw, usage, grp);
384
385kw = "autoiniranf";
386usage = "> Automatic random number generator initialisation\n";
387usage += " by Auto_Ini_Ranf(int lp) \n";
388usage += " Usage: autoiniranf";
389RegisterCommand(kw, usage, NULL, grp);
390
391kw = "shell execute";
392usage = "> shell command_string # Execute shell command\n";
393usage += "> cshell command_string # Execute cshell command\n";
394usage += "---Examples:\n";
395usage += " > shell ls\n";
396usage += " > cshell echo '$LD_LIBRARY_PATH'; map2cl -h; ls\n";
397usage += " > shell myfile.csh [arg1] [arg2] [...]\n";
398usage += " (where the first line of \"myfile.csh\" is \"#!/bin/csh\")\n";
399RegisterCommand(kw, usage, NULL, grp);
400
401
402AddInterpreter(this);
403curcmdi = this;
404}
405
406/* --Methode-- */
407Commander::~Commander()
408{
409hist.close();
410if (gltimer) { delete gltimer; gltimer = NULL; }
411Modmap::iterator it;
412for(it = modmap.begin(); it != modmap.end(); it++) {
413 string name = (*it).first + "_end";
414 DlModuleInitEndFunction fend = (*it).second->GetFunction(name);
415 if (fend) fend();
416 delete (*it).second;
417 }
418
419for(ScriptList::iterator sit = mScripts.begin();
420 sit != mScripts.end(); sit++) delete (*sit).second;
421
422if (cur_commander == this) cur_commander = NULL;
423}
424
425/* --Methode-- */
426Commander* Commander::GetInterpreter()
427{
428return(cur_commander);
429}
430
431/* --Methode-- */
432string Commander::Name()
433{
434return("Commander");
435}
436
437/* --Methode-- */
438void Commander::RegisterCommand(string& keyw, string& usage, CmdExecutor * ce, string grp)
439{
440if (!ce) {
441 RegisterHelp(keyw, usage, grp);
442 return;
443 }
444int gid = CheckHelpGrp(grp);
445cmdex cme;
446cme.group = gid;
447cme.us = usage;
448cme.cex = ce;
449cmdexmap[keyw] = cme;
450}
451
452/* --Methode-- */
453void Commander::RegisterHelp(string& keyw, string& usage, string& grp)
454{
455int gid = CheckHelpGrp(grp);
456cmdex cme;
457cme.group = gid;
458cme.us = usage;
459cme.cex = NULL;
460helpexmap[keyw] = cme;
461}
462
463/* --Methode-- */
464int Commander::CheckHelpGrp(string& grp)
465{
466int gid=0;
467CmdHGroup::iterator it = cmdhgrp.find(grp);
468if (it == cmdhgrp.end()) {
469 cmdgrpid++; gid = cmdgrpid;
470 cmdhgrp[grp] = gid;
471 // _helpmgr->AddHelpGroup(grp.c_str(), gid);
472 }
473else gid = (*it).second;
474return(gid);
475}
476
477
478/* --Methode-- */
479void Commander::LoadModule(string& fnameso, string& name)
480{
481PDynLinkMgr * dynlink = new PDynLinkMgr(fnameso, false);
482if (dynlink == NULL) {
483 cerr << "Commander/LoadModule_Error: Pb opening SO " << fnameso << endl;
484 return;
485 }
486string fname = name + "_init";
487DlModuleInitEndFunction finit = dynlink->GetFunction(fname);
488if (!finit) {
489 cerr << "Commander/LoadModule_Error: Pb linking " << fname << endl;
490 return;
491 }
492cout << "Commander/LoadModule_Info: Initialisation module" << name
493 << " " << fname << "() ..." << endl;
494finit();
495modmap[name] = dynlink;
496return;
497}
498
499/* --Methode-- */
500void Commander::AddInterpreter(CmdInterpreter * cl)
501{
502if (!cl) return;
503interpmap[cl->Name()] = cl;}
504
505/* --Methode-- */
506void Commander::SelInterpreter(string& name)
507{
508InterpMap::iterator it = interpmap.find(name);
509if (it == interpmap.end()) return;
510curcmdi = (*it).second;
511}
512
513
514
515/* Fonction */
516static string GetStringFrStdin(Commander* piac)
517{
518char buff[128];
519fgets(buff, 128, stdin);
520buff[127] = '\0';
521return((string)buff);
522}
523
524/* --Methode-- */
525int Commander::Interpret(string& s)
526{
527int rc = 0;
528ScriptList::iterator sit;
529
530// On saute de commandes vides
531size_t l;
532l = s.length();
533if (!mulinefg && (l < 1)) return(0);
534
535// On enregistre les commandes
536if (histon) hist << s << endl;
537
538if (s[0] == '#') return(0); // si c'est un commentaire
539
540// Logique de gestion des lignes suite
541// un \ en derniere position indique la presence d'une ligne suite
542size_t lnb = s.find_last_not_of(' ');
543if (s[lnb] == '\\' ) { // Lignes suite ...
544 mulinecmd += s.substr(0,lnb);
545 if (!mulinefg) {
546 spromptmul = GetCurrentPrompt();
547 SetCurrentPrompt("...? ");
548 mulinefg = true;
549 }
550 return(0);
551}
552
553if (mulinefg) { // Il y avait des lignes suite
554 s = mulinecmd + s;
555 l = s.length();
556 mulinecmd = "";
557 mulinefg = false;
558 SetCurrentPrompt(spromptmul);
559}
560
561// Removing leading blanks
562size_t p,q;
563
564// On enleve le dernier caractere, si celui-ci est \n
565if (s[l-1] == '\n') s[l-1] = '\0';
566p=s.find_first_not_of(" \t");
567if (p < l) s = s.substr(p);
568// >>>> Substitution d'alias (1er mot)
569CmdStrList::iterator it;
570p = 0;
571q = s.find_first_of(" \t");
572l = s.length();
573string w1 = (q < l) ? s.substr(p,q-p) : s.substr(p);
574it = mAliases.find(w1);
575if (it != mAliases.end()) {
576 s = (q < l) ? ((*it).second + s.substr(q)) : (*it).second ;
577 l = s.length();
578 p=s.find_first_not_of(" \t");
579 if (p < l) s = s.substr(p);
580 p = 0;
581 q = s.find_first_of(" ");
582 }
583
584// >>>> Separating keyword
585string toks,kw;
586if (q < l)
587 { kw = s.substr(p,q-p); toks = s.substr(q, l-q); }
588else { kw = s.substr(p,l-p); toks = ""; }
589
590// les mot-cle end else endif doivent etre le seul mot de la ligne
591if ( (kw == "end") || (kw == "else") || (kw == "endif") || (kw == "endscript") ) {
592 size_t ltk = toks.length();
593 if (toks.find_first_not_of(" \t") < ltk) {
594 cerr << "Commander::Interpret()/syntax error near end else endif endscript \n"
595 << "line: " << s << endl;
596 return(1);
597 }
598}
599
600// On verifie si on est en train de definir un script
601if (curscript) {
602 if (kw == "endscript") {
603 if (curscript->CheckScript()) {
604 sit = mScripts.find(curscript->Name());
605 if (sit != mScripts.end()) {
606 cout << "Commander::Interpret() replacing script "
607 << curscript->Name() << endl;
608 CommanderScript* scr = mScripts[curscript->Name()];
609 mScripts.erase(sit);
610 delete scr;
611 }
612 cout << "Commander::Interpret() Script " << curscript->Name()
613 << " defined successfully" << endl;
614 mScripts[curscript->Name()] = curscript;
615 SetCurrentPrompt("Cmd> ");
616 curscript = NULL;
617 return(0);
618 }
619 else {
620 cout << "Commander::Interpret() Error in Script " << curscript->Name()
621 << " definition " << endl;
622 SetCurrentPrompt("Cmd> ");
623 curscript = NULL;
624 return(2);
625 }
626 }
627 else curscript->AddLine(s, kw);
628 return(0);
629}
630// On verifie si nous sommes dans un bloc (for , foreach)
631if (CmdBlks.top() != NULL) { // On est dans un bloc
632 if ( (kw == "for") || (kw == "foreach")) felevel++;
633 else if (kw == "end") felevel--;
634 if (felevel == 0) { // Il faut executer le bloc
635 CommanderBloc* curb = CmdBlks.top();
636 CmdBlks.top() = curb->Parent();
637 SetCurrentPrompt("Cmd> ");
638 if (!curb->CheckBloc()) {
639 cerr << "Commander::Interpret()/syntax error - unbalenced if ... endif"
640 << " within for/foreach bloc ! " << endl;
641 delete curb;
642 return(2);
643 }
644 // cout << " *DBG* Executing bloc " << endl;
645 bool ohv = histon;
646 histon = false;
647 if (curtestresult) {
648 // We push also CommanderBloc and testresult on the stack
649 CmdBlks.push(NULL);
650 list<char> xtx;
651 TestsStack.push(xtx);
652 curb->Execute();
653 // And CommanderBloc and TestResult from the corresponding stacks
654 PopStack(false);
655 }
656 delete curb;
657 histon = ohv;
658 }
659 else CmdBlks.top()->AddLine(s, kw);
660 return(0);
661}
662else if (kw == "end") {
663 cerr << "Commander::Interpret()/syntax error - end outside for/foreach bloc \n"
664 << "line: " << s << endl;
665 return(1);
666}
667
668// Sommes-nous dans un bloc de test if then else
669if (TestsStack.top().size() > 0) { // Nous sommes ds un bloc if
670 if (kw == "else") {
671 if ((*tresit) & 2) {
672 cerr << "Commander::Interpret()/syntax error - multiple else in if bloc \n"
673 << "line: " << s << endl;
674 return(1);
675 }
676 else {
677 const char * npr = ((*tresit)&1) ? "else-F> " : "else-T> ";
678 if ((*tresit)&1) curtestresult = false;
679 SetCurrentPrompt(npr);
680 (*tresit) |= 2;
681 return(0);
682 }
683 }
684 else if (kw == "endif") {
685 list<char>::iterator dbit = tresit;
686 tresit--;
687 TestsStack.top().erase(dbit);
688 const char * npr = "Cmd> ";
689 if (TestsStack.top().size() > 1) {
690 curtestresult = true;
691 list<char>::iterator it;
692 for(it=TestsStack.top().begin(); it!=TestsStack.top().end(); it++) {
693 // Si on n'est pas ds le else et le if est faux
694 if ( !((*it)&2) && !((*it)&1) ) curtestresult = false;
695 // Si on est ds else et le if etait vrai !
696 if ( ((*it)&2) && ((*it)&1) ) curtestresult = false;
697 if (!curtestresult) break;
698 }
699
700 if (!((*tresit)&2))
701 npr = ((*tresit)&1) ? "if-T> " : "if-F> ";
702 else
703 npr = ((*tresit)&1) ? "else-F> " : "else-T> ";
704 }
705 else curtestresult = true;
706 SetCurrentPrompt(npr);
707 return(0);
708 }
709}
710else if ((kw == "else") || (kw == "endif")) {
711 cerr << "Commander::Interpret()/syntax error - else,endif outside if bloc \n"
712 << "line: " << s << endl;
713 return(1);
714}
715
716bool fgcont = true;
717if (TestsStack.top().size() > 0) { // Resultat de if ou else
718 list<char>::iterator it;
719 for(it=TestsStack.top().begin(); it!=TestsStack.top().end(); it++) {
720 // Si on n'est pas ds le else et le if est faux
721 if ( !((*it)&2) && !((*it)&1) ) fgcont = false;
722 // Si on est ds else et le if etait vrai !
723 if ( ((*it)&2) && ((*it)&1) ) fgcont = false;
724 if (!fgcont) break;
725 }
726}
727
728if ((!fgcont) && (kw != "if")) return(0);
729
730
731// Les mots cles break et return peuvent de sortir de boucles/scripts/execfile
732if (kw == "break") return(77766);
733else if (kw == "return") return(77777);
734
735// Nous ne sommes donc pas dans un bloc .... Substitution de variables
736string s2;
737int rcs ;
738
739rcs = SubstituteVars(s, s2);
740if (rcs) {
741 cerr << "Commander::Interpret()/syntax error in SubstituteVars() \n"
742 << "line: " << s << endl;
743 return(rcs);
744}
745// >>>> Separating keyword and tokens
746vector<string> tokens;
747/* decoupage en mots */
748LineToWords(s2, kw, tokens, toks, true);
749
750// Si c'est un for/foreach, on cree un nouveau bloc
751if ((kw == "foreach") || (kw == "for")) {
752 // cout << " *DBG* We got a foreach... " << endl;
753 CommanderBloc* bloc = new CommanderBloc(this, CmdBlks.top(), kw, tokens);
754 if (!bloc->CheckOK()) {
755 cerr << "Commander::Interpret() for/foreach syntax Error ! " << endl;
756 delete bloc;
757 return(1);
758 }
759 felevel++;
760 if (CmdBlks.top()) CmdBlks.top()->AddBloc(bloc);
761 else SetCurrentPrompt("for...> ");
762 CmdBlks.top() = bloc;
763 // cout << " *DBG* New Bloc created ... " << endl;
764 return(0);
765 }
766else if (kw == "if") { // Un test if
767 bool restst = true;
768 int rct = EvaluateTest(tokens, s, restst);
769 if (rct) {
770 cerr << "Commander::Interpret() if syntax Error ! " << "line: " << s << endl;
771 return(1);
772 }
773 char res_tst = (restst) ? 1 : 0;
774 TestsStack.top().push_back(res_tst);
775 if (TestsStack.top().size() == 1) tresit = TestsStack.top().begin();
776 else tresit++;
777 const char * npr = (restst) ? "if-T> " : "if-F> ";
778 SetCurrentPrompt(npr);
779}
780else if ((tokens.size() > 0) && (tokens[0] == "=")) {
781 // x = RPNExpression (Evaluation d'expression RPN)
782 tokens[0] = kw;
783 int rcev = EvalRPNExpr(tokens, s);
784 if (rcev) {
785 cerr << "Commander::Interpret() evaluation (RPN) syntax Error ! " << "line: " << s << endl;
786 return(1);
787 }
788 return(0);
789}
790else if (kw == "defscript") { // definition de script
791 if (tokens.size() > 0) {
792 if (tokens.size() < 2) tokens.push_back("");
793 curscript = new CommanderScript(this, tokens[0], tokens[1]);
794 SetCurrentPrompt("Script...> ");
795 return(0);
796 }
797 else {
798 cerr << "Commander::Interpret() No script name in defscript" << "line: " << s << endl;
799 return(1);
800 }
801}
802else {
803 // Si c'est le nom d'un script
804 sit = mScripts.find(kw);
805 if (sit != mScripts.end()) {
806 bool ohv = histon;
807 histon = false;
808 tokens.insert(tokens.begin(), kw);
809 PushStack(tokens);
810 (*sit).second->Execute(tokens);
811 PopStack(true);
812 histon = ohv;
813 }
814 // Execution de commandes
815 else rc = ExecuteCommandLine(kw, tokens, toks);
816 return(rc);
817}
818// cout << "Commander::Do() DBG KeyW= " << kw << " NbArgs= " << tokens.size() << endl;
819// for(int ii=0; ii<tokens.size(); ii++)
820// cout << "arg[ " << ii << " ] : " << tokens[ii] << endl;
821
822return(0);
823}
824
825
826/* --Methode-- */
827int Commander::LineToWords(string& line, string& kw, vector<string>& tokens,
828 string& toks, bool uq)
829{
830if (line.length() < 1) return(0);
831int nw = 1;
832size_t p = line.find_first_not_of(" ");
833line = line.substr(p);
834p = 0;
835size_t q = line.find_first_of(" ");
836size_t l = line.length();
837
838if (q < l)
839 { kw = line.substr(p,q-p); toks = line.substr(q, l-q); }
840else { kw = line.substr(p,l-p); toks = ""; }
841
842q = 0;
843while (q < l) {
844 p = toks.find_first_not_of(" \t",q+1); // au debut d'un token
845 if (p>=l) break;
846 if ( uq && ((toks[p] == '\'') || (toks[p] == '"')) ) {
847 q = toks.find(toks[p],p+1);
848 if (q>=l) {
849 cerr << "Commander::LineToWords/Syntax Error - Unbalenced quotes " << toks[p] << '.' << endl;
850 return(-1);
851 }
852 p++;
853 }
854 else {
855 q = toks.find_first_of(" \t",p); // la fin du token;
856 }
857 string token = toks.substr(p,q-p);
858 tokens.push_back(token); nw++;
859 }
860
861return(nw);
862}
863
864/* --Methode-- */
865int Commander::SubstituteVars(string & s, string & s2)
866// Variable substitution
867{
868
869int iarr = -1; // index d'element de tableau
870size_t p,q,q2,q3,l;
871
872s2="";
873p = 0;
874l = s.length();
875string vn, vv;
876while (p < l) {
877 iarr = -1;
878 q = s.find('$',p);
879 if (q > l) break;
880 q2 = s.find('\'',p);
881 if ((q2 < l) && (q2 < q)) { // On saute la chaine delimitee par ' '
882 q2 = s.find('\'',q2+1);
883 if (q2 >= l) {
884 cerr << " Syntax error - Unbalenced quotes !!! " << endl;
885 return(1);
886 }
887 s2 += s.substr(p, q2-p+1);
888 p = q2+1; continue;
889 }
890 // cout << "DBG: " << s2 << " p= " << p << " q= " << q << " L= " << l << endl;
891 if ((q>0) && (s[q-1] == '\\')) { // Escape character \$
892 s2 += (s.substr(p,q-1-p) + '$') ; p = q+1;
893 continue;
894 }
895 if (q >= l-1) {
896 cerr << " Syntax error - line ending with $ !!! " << endl;
897 return(2);
898 }
899 vn = "";
900 if ( s[q+1] == '{' ) { // Variable in the form ${name}
901 q2 = s.find('}',q+1);
902 if (q2 >= l) {
903 cerr << " Syntax error - Unbalenced brace {} !!! " << endl;
904 return(3);
905 }
906 vn = s.substr(q+2,q2-q-2);
907 q2++;
908 }
909 else if ( s[q+1] == '(' ) { // Variable in the form $(name)
910 q2 = s.find(')',q+1);
911 if (q2 >= l) {
912 cerr << " Syntax error - Unbalenced parenthesis () !!! " << endl;
913 return(3);
914 }
915 vn = s.substr(q+2,q2-q-2);
916 q2++;
917 }
918 else if ( s[q+1] == '[' ) { // Variable in the form $[varname] -> This is $$varname
919 q2 = s.find(']',q+1);
920 if (q2 >= l) {
921 cerr << " Syntax error - Unbalenced brace [] !!! " << endl;
922 return(4);
923 }
924 vn = s.substr(q+2,q2-q-2);
925 if (!GetVar(vn, vv)) return(5);
926 vn = vv;
927 q2++;
928 }
929 else {
930 q2 = s.find_first_of(" .:+-*/,[](){}&|!$\"'",q+1);
931 if (q2 > l) q2 = l;
932 q3 = q2;
933 vn = s.substr(q+1, q2-q-1);
934 // Si variable de type $varname[index] : element de tableau
935 if ((q2 < l) && (s[q2] == '[') ) {
936 q3 = s.find_first_of("]",q2+1);
937 string sia = s.substr(q2+1, q3-q2-1);
938 if (sia.length() < 1) {
939 cerr << " Syntax error - in $varname[index] : $"
940 << vn << "[" << sia <<"]" << endl;
941 return(4);
942 }
943 if (isalpha(sia[0])) {
944 string sia2;
945 if (!GetVar(sia, sia2) || (sia2.length() < 1)) {
946 cerr << " Syntax error - in $varname[index] : $"
947 << vn << "[" << sia <<"]" << endl;
948 return(4);
949 }
950 sia = sia2;
951 }
952 int rcdia = ctoi(sia.c_str(), &iarr);
953 if (rcdia < 0) {
954 cerr << " Syntax error - in $varname[iarr] : $"
955 << vn << "[" << sia <<"]" << endl;
956 return(4);
957 }
958 }
959 }
960 if (!GetVar(vn, vv)) return(5);
961 if (iarr < 0) {
962 s2 += (s.substr(p, q-p) + vv);
963 p = q2;
964 }
965 else {
966 vector<string> vs;
967 FillVStringFrString(vv, vs);
968 if (iarr >= vs.size()) {
969 cerr << " Substitution error - word index out of range in "
970 << "$varname[iarr] : $" << vn << "[" << iarr <<"]" << endl;
971 return(4);
972 }
973 else s2 += (s.substr(p, q-p) + vs[iarr]);
974 p = q3+1;
975 }
976}
977if (p < l) s2 += s.substr(p);
978
979p = s2.find_first_not_of(" \t");
980if (p < l) s2 = s2.substr(p);
981
982return(0);
983}
984
985/* --Methode-- */
986bool Commander::GetVar(string & vn, string & vv)
987{
988if (vn.length() < 1) {
989 cerr << " Commander::SubstituteVar/Error: length(varname=" << vn << ")<1 !" << endl;
990 vv = ""; return(false);
991}
992// Variable de type $# $0 $1 ... (argument de .pic ou de script)
993int ka = 0;
994if (vn == "#") {
995 if (ArgsStack.empty()) {
996 cerr << " Commander::SubstituteVar/Error: ArgsStack empty ! "
997 << " ($" << vn << ")" << endl;
998 vv = ""; return(false);
999 }
1000 char buff[32];
1001 long an = ArgsStack.top().size();
1002 sprintf(buff,"%ld", an);
1003 vv = buff; return(true);
1004}
1005else if (ctoi(vn.c_str(), &ka) > 0) { // $0 $1 $2 ...
1006 if (ArgsStack.empty()) {
1007 cerr << " Commander::SubstituteVar/Error: ArgsStack empty ! "
1008 << " ($" << vn << ")" << endl;
1009 vv = ""; return(false);
1010 }
1011 if ( (ka < 0) || (ka >= ArgsStack.top().size()) ) {
1012 cerr << " Commander::SubstituteVar/Error: Undefined variable ! "
1013 << " ($" << vn << ")" << endl;
1014 vv = ""; return(false);
1015 }
1016 vv = ArgsStack.top()[ka]; return(true);
1017}
1018else if (vn[0] == '#') { // Variable de type $#vname --> size(vname)
1019 vn = vn.substr(1);
1020 if (!HasVariable(vn) ) {
1021 cerr << " Commander::SubstituteVarError: Undefined variable "
1022 << vn << " ! " << endl;
1023 vv = ""; return(false);
1024 }
1025 vn = GetVariable(vn);
1026 vector<string> vs;
1027 FillVStringFrString(vn, vs);
1028 char buff[32];
1029 sprintf(buff,"%d", (int)vs.size());
1030 vv = buff; return(true);
1031 }
1032else { // variable ordinaire geree par NamedObjMgr
1033 if ( (!HasVariable(vn)) ) {
1034 cerr << " Commander::SubstituteVarError: Undefined variable "
1035 << vn << " ! " << endl;
1036 vv = ""; return(false);
1037 }
1038 vv = GetVariable(vn); return(true);
1039}
1040
1041return(false);
1042}
1043/* --Methode-- */
1044string Commander::GetVariable(string const & key)
1045{
1046 if ((key.length() < 1) || (! isalpha(key[0])) ) {
1047 cout << "Commander::GetVariable( " << key << ") Bad VarName " << endl;
1048 return("");
1049 }
1050 // cout << " DEBUG::GetVar " << variables << endl;
1051 return(variables.GetS(key));
1052}
1053
1054/* --Methode-- */
1055bool Commander::HasVariable(string const & key)
1056{
1057 if ((key.length() < 1) || (! isalpha(key[0])) ) {
1058 cout << "Commander::HasVar( " << key << ") Bad VarName " << endl;
1059 return(false);
1060 }
1061 return(variables.HasKey(key));
1062}
1063
1064/* --Methode-- */
1065bool Commander::SetVar(string const & key, string const & val)
1066{
1067 if ((key.length() < 1) || (! isalpha(key[0])) ) {
1068 cout << "Commander::SetVar( " << key << " ...) Bad VarName " << endl;
1069 return(false);
1070 }
1071 bool fg = variables.HasKey(key);
1072 variables.SetS(key, val);
1073 // cout << " DEBUG::SetVar " << variables << endl;
1074 return fg;
1075}
1076
1077/* --Methode-- */
1078bool Commander::DeleteVar(string const & key)
1079{
1080 if ((key.length() < 1) || (! isalpha(key[0])) ) {
1081 cout << "Commander::DeleteVar( " << key << ") Bad VarName " << endl;
1082 return(false);
1083 }
1084 return(variables.DeleteKey(key));
1085}
1086
1087/* --Methode-- */
1088void Commander::ListVars()
1089{
1090 cout << " ---- Commander::ListVars() List of defined variables ---- "
1091 << endl;
1092 cout << variables;
1093 cout << "---------------------------------------------------------- "
1094 << endl;
1095}
1096
1097/* --Methode-- */
1098string Commander::GetTmpDir()
1099{
1100 return("/tmp");
1101}
1102
1103/* --Methode-- */
1104void Commander::SetCurrentPrompt(const char* pr)
1105{
1106 curprompt = pr;
1107}
1108
1109/* --Methode-- */
1110void Commander::ShowMessage(const char * msg, int att)
1111{
1112 cout << msg ;
1113}
1114
1115
1116
1117/* --Methode-- */
1118int Commander::EvaluateTest(vector<string> & args, string & line, bool & res)
1119{
1120 res = true;
1121 if ((args.size() != 6) || (args[5] != "then") ||
1122 (args[0] != "(") || (args[4] != ")") ) return(1);
1123 if (args[2] == "==") res = (args[1] == args[3]);
1124 else if (args[2] == "!=") res = (args[1] != args[3]);
1125 else if (args[2] == "<")
1126 res = (atof(args[1].c_str()) < atof(args[3].c_str()));
1127 else if (args[2] == ">")
1128 res = (atof(args[1].c_str()) > atof(args[3].c_str()));
1129 else if (args[2] == "<=")
1130 res = (atof(args[1].c_str()) <= atof(args[3].c_str()));
1131 else if (args[2] == ">=")
1132 res = (atof(args[1].c_str()) >= atof(args[3].c_str()));
1133 else return(2);
1134 return(0);
1135}
1136
1137/* Operations sur le stack RPN */
1138inline bool Check_myRPNStack_(stack<double>& s, double& x, string& line)
1139{
1140 if (s.empty()) {
1141 cerr << "Commander::EvalRPNExpr: syntax error / empty RPN stack " << line << endl;
1142 return true;
1143 }
1144 else x = s.top();
1145 return false;
1146}
1147inline bool Check_myRPNStack_(stack<double>& s, double& x, double& y, string& line)
1148{
1149 if (s.size() < 2) {
1150 cerr << "Commander::EvalRPNExpr: syntax error / RPN stack size < 2 " << line << endl;
1151 return true;
1152 }
1153 else {
1154 x = s.top(); s.pop(); y = s.top();
1155 }
1156 return false;
1157}
1158
1159inline void Print_myRPNStack_(stack<double> s)
1160{
1161 if (s.empty())
1162 cout << "Commander::EvalRPNExpr/PrintStack: Empty stack " << endl;
1163 else {
1164 int k = 0;
1165 cout << "Commander::EvalRPNExpr/PrintStack: Size()= " << s.size() << endl;
1166 while( !s.empty() ) {
1167 cout << " " << k << ": " << s.top() << " ";
1168 if (k == 0) cout << " (x) " << endl;
1169 else if (k == 1) cout << " (y) " << endl;
1170 else if (k == 2) cout << " (z) " << endl;
1171 else cout << endl;
1172 s.pop(); k++;
1173 }
1174 }
1175
1176}
1177
1178int Sum_RPNStack_(stack<double>& s, double& sx, double& sx2, string& line)
1179{
1180 sx = sx2 = 0.;
1181 int nn = 0;
1182 double x = 0.;
1183 while( !s.empty() ) {
1184 x = s.top(); s.pop();
1185 sx += x; sx2 += x*x;
1186 nn++;
1187 }
1188 return(nn);
1189}
1190
1191int Product_RPNStack_(stack<double>& s, double& px, string& line)
1192{
1193 px = 1.;
1194 int nn = 0;
1195 double x = 0.;
1196 while( !s.empty() ) {
1197 x = s.top(); s.pop();
1198 px *= x; nn++;
1199 }
1200 return(nn);
1201}
1202
1203/* --Methode-- */
1204int Commander::EvalRPNExpr(vector<string> & args, string & line)
1205{
1206
1207 if (args.size() < 2) {
1208 cerr << "Commander::EvalRPNExpr: syntax error / missing arguments " << line << endl;
1209 return(1);
1210 }
1211 else if (args.size() == 2) {
1212 SetVar(args[0], args[1]);
1213 return(0);
1214 }
1215
1216 double x,y;
1217 x = y = 0.;
1218 stack<double> rpnstack; // Stack des operations en RPN
1219 for(int k=1; k<args.size(); k++) {
1220 // Les 4 operations de base + - * /
1221 if (args[k] == "+") {
1222 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1223 rpnstack.top() = y+x;
1224 }
1225 else if (args[k] == "-") {
1226 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1227 rpnstack.top() = y-x;
1228 }
1229 else if (args[k] == "*") {
1230 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1231 rpnstack.top() = y*x;
1232 }
1233 else if (args[k] == "/") {
1234 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1235 rpnstack.top() = y/x;
1236 }
1237 else if (args[k] == "%") {
1238 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1239 rpnstack.top() = (int)y % (int)x;
1240 }
1241 // Les constantes : e , pi
1242 else if (args[k] == "e") {
1243 rpnstack.push(M_E);
1244 }
1245 else if (args[k] == "pi") {
1246 rpnstack.push(M_PI);
1247 }
1248 // Les fonctions usuelles a 1 argument f(x)
1249 else if (args[k] == "cos") {
1250 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1251 rpnstack.top() = cos(x);
1252 }
1253 else if (args[k] == "sin") {
1254 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1255 rpnstack.top() = sin(x);
1256 }
1257 else if (args[k] == "tan") {
1258 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1259 rpnstack.top() = tan(x);
1260 }
1261 else if (args[k] == "acos") {
1262 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1263 rpnstack.top() = acos(x);
1264 }
1265 else if (args[k] == "asin") {
1266 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1267 rpnstack.top() = asin(x);
1268 }
1269 else if (args[k] == "atan") {
1270 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1271 rpnstack.top() = atan(x);
1272 }
1273 else if (args[k] == "chs") {
1274 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1275 rpnstack.top() = -x;
1276 }
1277 else if (args[k] == "sqrt") {
1278 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1279 rpnstack.top() = sqrt(x);
1280 }
1281 else if (args[k] == "sq") { // x^2
1282 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1283 rpnstack.top() = x*x;
1284 }
1285 else if (args[k] == "log") {
1286 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1287 rpnstack.top() = log(x);
1288 }
1289 else if (args[k] == "log10") {
1290 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1291 rpnstack.top() = log10(x);
1292 }
1293 else if (args[k] == "exp") {
1294 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1295 rpnstack.top() = exp(x);
1296 }
1297 else if (args[k] == "fabs") {
1298 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1299 rpnstack.top() = fabs(x);
1300 }
1301 else if (args[k] == "floor") {
1302 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1303 rpnstack.top() = floor(x);
1304 }
1305 else if (args[k] == "ceil") {
1306 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1307 rpnstack.top() = ceil(x);
1308 }
1309 // trunc et nint vire - ca ne compile pas sous linux - Reza 01/2003
1310 else if (args[k] == "deg2rad") {
1311 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1312 rpnstack.top() = x*M_PI/180.;
1313 }
1314 else if (args[k] == "rad2deg") {
1315 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1316 rpnstack.top() = x*180./M_PI;
1317 }
1318 // Les fonctions usuelles a 2 argument f(x,y)
1319 else if (args[k] == "pow") {
1320 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1321 rpnstack.top() = pow(y,x);
1322 }
1323 else if (args[k] == "atan2") {
1324 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1325 rpnstack.top() = atan2(x,y);
1326 }
1327 // generateur aleatoire
1328 else if (args[k] == "rand") {
1329 double rnd = drand01();
1330 rpnstack.push(rnd);
1331 }
1332 else if (args[k] == "norand") {
1333 double rnd = GauRnd(0., 1.);
1334 rpnstack.push(rnd);
1335 }
1336 // Fonction a N arguments - Somme, produit, etc ...
1337 else if ((args[k] == "sum") || (args[k] == "mean") || (args[k] == "sigmean") ||
1338 (args[k] == "sigma") || (args[k] == "sigma2") ) {
1339 double sx, sx2;
1340 int nn = Sum_RPNStack_(rpnstack, sx, sx2, line);
1341 if (args[k] == "sum") rpnstack.push(sx);
1342 else {
1343 if (nn == 0) {
1344 cerr << "Commander::EvalRPNExpr: mean/sigma error- RPN stack empty: "
1345 << line << endl;
1346 return(1);
1347 }
1348 double fnn = nn;
1349 if ((args[k] == "sigma") || (args[k] == "sigmean"))
1350 rpnstack.push(sqrt(sx2/fnn-(x*x/(fnn*fnn))));
1351 else if ((args[k] == "mean") || (args[k] == "sigmean")) rpnstack.push(sx/fnn);
1352 else rpnstack.push(sx2/fnn-(x*x/(fnn*fnn)));
1353 }
1354 }
1355 else if (args[k] == "product") {
1356 double px;
1357 int nn = Product_RPNStack_(rpnstack, px, line);
1358 if (nn == 0) {
1359 cerr << "Commander::EvalRPNExpr: product error- RPN stack empty: "
1360 << line << endl;
1361 return(1);
1362 }
1363 rpnstack.push(px);
1364 }
1365 // Fonctions de manipulation de stack
1366 else if (args[k] == "print") {
1367 Print_myRPNStack_(rpnstack);
1368 }
1369 else if (args[k] == "x<>y") {
1370 if ( Check_myRPNStack_(rpnstack, x, y, line) ) return(1);
1371 rpnstack.top() = x; rpnstack.push(y);
1372 }
1373 else if (args[k] == "pop") {
1374 rpnstack.pop();
1375 }
1376 else if (args[k] == "push") {
1377 if (rpnstack.empty()) rpnstack.push(0.);
1378 else rpnstack.push(rpnstack.top());
1379 }
1380 // On met un nombre sur le stack
1381 else {
1382 char * esptr;
1383 x = strtod(args[k].c_str(), &esptr);
1384 // if (ctof(args[k].c_str(),&x) < 0) {
1385 if (esptr == args[k].c_str()) {
1386 cerr << "Commander::EvalRPNExpr: syntax error near " << args[k]
1387 << " in expression: \n" << line << endl;
1388 return(2);
1389 }
1390 rpnstack.push(x);
1391 }
1392
1393 }
1394
1395 if ( Check_myRPNStack_(rpnstack, x, line) ) return(1);
1396 char buff[64];
1397 sprintf(buff, "%g", x);
1398 string res = buff;
1399 SetVar(args[0], res);
1400 return(0);
1401}
1402
1403/* --Methode-- */
1404void Commander::PushStack(vector<string>& args)
1405{
1406 // We push the argument list (args) on the stack
1407 ArgsStack.push(args);
1408 // We push also CommanderBloc and testresult on the stack
1409 CmdBlks.push(NULL);
1410 list<char> xtx;
1411 TestsStack.push(xtx);
1412
1413}
1414
1415/* --Methode-- */
1416void Commander::PopStack(bool psta)
1417{
1418 // We remove the argument list (args) from the stack
1419 if (psta) ArgsStack.pop();
1420 // And CommanderBloc and TestResult from the corresponding stacks
1421 CommanderBloc* curb = CmdBlks.top();
1422 while (curb != NULL) {
1423 CommanderBloc* parb = curb->Parent();
1424 delete curb; curb = parb;
1425 }
1426 CmdBlks.pop();
1427 TestsStack.pop();
1428}
1429
1430/* --Methode-- */
1431int Commander::ExecuteCommandLine(string & kw, vector<string> & tokens, string & toks)
1432{
1433int rc = 0;
1434
1435// >>>>>>>>>>> Commande d'interpreteur
1436if (kw == "help") {
1437 if (tokens.size() > 0) cout << GetUsage(tokens[0]) << endl;
1438 else {
1439 string kwh = "Commander";
1440 cout << GetUsage(kwh) << endl;
1441 }
1442 }
1443
1444else if (kw == "set") {
1445 if (tokens.size() < 2) { cout << "Commander::Interpret() Usage: set varname string" << endl; return(0); }
1446 if ((tokens[0].length() < 1) || !isalpha((int)tokens[0][0]) ) {
1447 cerr << "Commander::Interpret()/Error Variable name should start with alphabetic" << endl;
1448 return(0);
1449 }
1450 // string xx = tokens[1];
1451 // for (int kk=2; kk<tokens.size(); kk++) xx += (' ' + tokens[kk] );
1452 SetVar(tokens[0], tokens[1]);
1453 }
1454
1455else if (kw == "getvar") {
1456 if (tokens.size() < 2) { cout << "Commander::Interpret() Usage: getvar newvarname varname" << endl; return(0); }
1457 if (!HasVariable(tokens[1])) {
1458 cerr << "Error - No " << tokens[1] << " Variable " << endl;
1459 return(0);
1460 }
1461 if ((tokens[0].length() < 1) || !isalpha((int)tokens[0][0]) ) {
1462 cerr << "Commander::Interpret()/Error Variable name should start with alphabetic" << endl;
1463 return(0);
1464 }
1465 SetVar(tokens[0], GetVariable(tokens[1]) );
1466 }
1467
1468else if (kw == "alias") {
1469 if (tokens.size() < 2) { cout << "Commander::Interpret() Usage: alias aliasname string" << endl; return(0); }
1470 if ((tokens[0].length() < 1) || !isalpha((int)tokens[0][0]) ) {
1471 cerr << "Commander::Interpret()/Error alias name should start with alphabetic" << endl;
1472 return(0);
1473 }
1474 string xx = tokens[1];
1475 for (int kk=2; kk<tokens.size(); kk++) xx += (' ' + tokens[kk]);
1476 mAliases[tokens[0]] = xx;
1477 }
1478
1479else if (kw == "unset") {
1480 if (tokens.size() < 1) { cout << "Commander::Interpret() Usage: unset varname" << endl; return(0); }
1481 if (HasVariable(tokens[0])) DeleteVar(tokens[0]) ;
1482 else cerr << "Commander::Interpret() No variable with name " << tokens[0] << endl;
1483 }
1484 else if (kw == "rpneval") { // Evaluation d'expression en notation polonaise inverse
1485 return(EvalRPNExpr(tokens, toks));
1486}
1487else if (kw == "echo") {
1488 for (int ii=0; ii<tokens.size(); ii++)
1489 cout << tokens[ii] << " " ;
1490 cout << endl;
1491 }
1492else if (kw == "echo2file") {
1493 if (tokens.size() < 1) {
1494 cout << "Commander::Interpret() Usage: echo2file filename [string ] " << endl;
1495 return(0);
1496 }
1497 ofstream ofs(tokens[0].c_str(), ios::app);
1498 for (int ii=1; ii<tokens.size(); ii++)
1499 ofs << tokens[ii] << " " ;
1500 ofs << endl;
1501 }
1502else if (kw == "readstdin") {
1503 if (tokens.size() < 1) { cout << "Commander::Interpret() Usage: readstdin varname" << endl; return(0); }
1504 if ((tokens[0].length() < 1) || !isalpha((int)tokens[0][0]) ) {
1505 cerr << "Commander::Interpret()/Error Variable name should start with alphabetic" << endl;
1506 return(0);
1507 }
1508 ShowMessage(">>> Reading From StdIn \n", _MAGENTA_);
1509 cout << tokens[0] << " ? " << endl;
1510 SetVar(tokens[0], GetStringFrStdin(this) );
1511 }
1512
1513else if (kw == "listvars") ListVars();
1514else if (kw == "listalias") {
1515 cout << "Commander::Interpret() Alias List , AliasName = Value \n";
1516 CmdStrList::iterator it;
1517 for(it = mAliases.begin(); it != mAliases.end(); it++)
1518 cout << (*it).first << " = " << (*it).second << "\n";
1519 cout << endl;
1520 }
1521else if (kw == "listcommands") {
1522 cout << "---- Commander::Interpret() Command List ----- \n";
1523 CmdExmap::iterator it;
1524 int kc = 0;
1525 for(it = cmdexmap.begin(); it != cmdexmap.end(); it++) {
1526 cout << (*it).first << " ";
1527 kc++;
1528 if (kc >= 5) { cout << "\n"; kc = 0; }
1529 }
1530 cout << endl;
1531 }
1532else if (kw == "listscripts") {
1533 cout << "---- Commander::Interpret() Script List ----- \n";
1534 for(ScriptList::iterator sit = mScripts.begin();
1535 sit != mScripts.end(); sit++)
1536 cout << " Script: " << (*sit).second->Name() << " - "
1537 << (*sit).second->Comment() << endl;
1538}
1539else if (kw == "clearscript") {
1540 if (tokens.size() < 1) {
1541 cout << "Commander::Interpret() Usage: clearscript scriptname" << endl;
1542 return(0);
1543 }
1544 ScriptList::iterator sit = mScripts.find(tokens[0]);
1545 if (sit == mScripts.end()) {
1546 cout << "Commander::Interpret() No script with name" << tokens[0] << endl;
1547 return(0);
1548 }
1549 else {
1550 delete (*sit).second;
1551 mScripts.erase(sit);
1552 cout << "Commander::Interpret() script " << tokens[0] << " cleared" << endl;
1553 return(0);
1554 }
1555}
1556else if (kw == "traceon") { cout << "Commander::Interpret() -> Trace ON mode " << endl; trace = true; }
1557else if (kw == "traceoff") { cout << "Commander::Interpret() -> Trace OFF mode " << endl; trace = false; }
1558else if (kw == "timingon") {
1559 cout << "Commander::Interpret() -> Timing ON mode " << endl;
1560 if (gltimer) delete gltimer; gltimer = new Timer("PIA-CmdInterpreter "); timing = true;
1561 }
1562else if (kw == "timingoff") {
1563 cout << "Commander::Interpret() -> Timing OFF mode " << endl;
1564 if (gltimer) delete gltimer; gltimer = NULL; timing = false;
1565 }
1566else if (kw == "exec") {
1567 if (tokens.size() < 1) { cout << "Commander::Interpret() Usage: exec filename" << endl; return(0); }
1568 ExecFile(tokens[0], tokens);
1569 }
1570else if (kw == "autoiniranf") {
1571 Auto_Ini_Ranf(1);
1572 return(0);
1573}
1574else if (kw == "shell") {
1575 if (tokens.size() < 1) { cout << "Commander::Interpret() Usage: shell cmdline" << endl; return(0); }
1576 string cmd;
1577 for (int ii=0; ii<tokens.size(); ii++)
1578 cmd += (tokens[ii] + ' ');
1579 system(cmd.c_str());
1580 }
1581else if (kw == "cshell") {
1582 if(tokens.size()<1) {cout<<"Commander::Interpret() Usage: cshell cmdline"<<endl; return(0);}
1583 string cmd="";
1584 for(int ii=0;ii<tokens.size();ii++) cmd+=(tokens[ii]+' ');
1585 CShellExecute(cmd);
1586 }
1587
1588// Execution d'une commande enregistree
1589else rc = ExecuteCommand(kw, tokens, toks);
1590
1591if (timing) gltimer->Split();
1592return(rc);
1593}
1594
1595/* --Methode-- */
1596int Commander::ParseLineExecute(string& line, bool qw)
1597 // Si qw == true, on decoupe entre '' ou "" ou espaces
1598{
1599vector<string> tokens;
1600string kw, toks;
1601if (line.length() < 1) return(0);
1602LineToWords(line, kw, tokens, toks, qw);
1603return(ExecuteCommand(kw, tokens, toks));
1604}
1605
1606/* --Methode-- */
1607int Commander::ExecuteCommand(string& keyw, vector<string>& args, string& toks)
1608{
1609 int rc = -1;
1610 CmdExmap::iterator it = cmdexmap.find(keyw);
1611 if (it == cmdexmap.end()) cout << "No such command : " << keyw << " ! " << endl;
1612 else {
1613 if ((*it).second.cex) rc = (*it).second.cex->Execute(keyw, args, toks);
1614 else cout << "Dont know how to execute " << keyw << " ? " << endl;
1615 }
1616 return(rc);
1617}
1618
1619/* --Methode-- */
1620int Commander::ExecFile(string& file, vector<string>& args)
1621{
1622char line_buff[512];
1623FILE *fip;
1624
1625if ( (fip = fopen(file.c_str(),"r")) == NULL ) {
1626 if (file.find('.') >= file.length()) {
1627 cout << "Commander::Exec(): Error opening file " << file << endl;
1628 file += ".pic";
1629 cout << " Trying file " << file << endl;
1630 fip = fopen(file.c_str(),"r");
1631 }
1632 }
1633
1634if(fip == NULL) {
1635 cerr << "Commander::Exec() Error opening file " << file << endl;
1636 hist << "##! Commander::Exec() Error opening file " << file << endl;
1637 return(0);
1638 }
1639
1640// hist << "### Executing commands from " << file << endl;
1641
1642PushStack(args);
1643if (trace) {
1644 ShowMessage("### Executing commands from ", _MAGENTA_);
1645 ShowMessage(file.c_str(), _MAGENTA_);
1646 ShowMessage("\n", _MAGENTA_);
1647 }
1648
1649bool ohv = histon;
1650histon = false;
1651while (fgets(line_buff,511,fip) != NULL)
1652 {
1653 if (trace) ShowMessage(line_buff, _MAGENTA_);
1654 line_buff[strlen(line_buff)-1] = '\0'; /* LF/CR de la fin */
1655 string line(line_buff);
1656 if (Interpret(line) == 77777) break;
1657 }
1658histon = ohv;
1659
1660// hist << "### End of Exec( " << file << " ) " << endl;
1661if (trace) {
1662 ShowMessage("### End of Exec( ", _MAGENTA_);
1663 ShowMessage(file.c_str(), _MAGENTA_);
1664 ShowMessage(" ) \n", _MAGENTA_);
1665 }
1666
1667PopStack(true);
1668
1669return(0);
1670}
1671
1672/* --Methode-- */
1673int Commander::CShellExecute(string cmd)
1674{
1675 if(cmd.size()<=0) return -1;
1676
1677 string fname = GetTmpDir(); fname += "cshell_exec_pia.csh";
1678
1679 string cmdrm = "rm -f " + fname;
1680 system(cmdrm.c_str());
1681
1682 FILE *fip = fopen(fname.c_str(),"w");
1683 if(fip==NULL) {
1684 cout << "Commander/CShellExecute_Error: fopen("<<fname<<") failed"<<endl;
1685 return -2;
1686 }
1687 fprintf(fip,"#!/bin/csh\n\n");
1688 fprintf(fip,"%s\n",cmd.c_str());
1689 fprintf(fip,"\nexit 0\n");
1690 fclose(fip);
1691
1692 cmd = "csh "; cmd += fname;
1693 system(cmd.c_str());
1694
1695 system(cmdrm.c_str());
1696
1697 return 0;
1698}
1699
1700static string* videstr = NULL;
1701/* --Methode-- */
1702string& Commander::GetUsage(const string& kw)
1703{
1704bool fndok = false;
1705CmdExmap::iterator it = cmdexmap.find(kw);
1706if (it == cmdexmap.end()) {
1707 it = helpexmap.find(kw);
1708 if (it != helpexmap.end()) fndok = true;
1709 }
1710 else fndok = true;
1711if (fndok) return( (*it).second.us );
1712// Keyword pas trouve
1713if (videstr == NULL) videstr = new string("");
1714*videstr = "Nothing known about " + kw + " ?? ";
1715return(*videstr);
1716
1717}
1718
1719
1720/* Les definitions suivantes doivent se trouver ds l'en-tete du fichier LaTeX
1721 \newcommand{\piacommand}[1]{
1722 \framebox{\bf \Large #1 } \index{#1} % (Command)
1723 }
1724
1725 \newcommand{\piahelpitem}[1]{
1726 \framebox{\bf \Large #1 } \index{#1} (Help item)
1727 }
1728
1729 \newcommand{\myppageref}[1]{ (p. \pageref{#1} ) }
1730*/
1731
1732// Fonction qui remplace tout caractere non alphanumerique en Z
1733static void check_latex_reflabel(string & prl)
1734{
1735 for(int k=0; k<prl.length(); k++)
1736 if (! isalnum(prl[k]) ) prl[k] = 'Z';
1737}
1738// Fonction qui remplace _ en \_
1739static string check_latex_underscore(string const & mot)
1740{
1741 string rs;
1742 for(int k=0; k<mot.length(); k++) {
1743 if (mot[k] == '_') rs += "\\_";
1744 else rs += mot[k];
1745 }
1746 return rs;
1747}
1748
1749/* --Methode-- */
1750void Commander::HelptoLaTeX(string const & fname)
1751{
1752FILE *fip;
1753if ((fip = fopen(fname.c_str(), "w")) == NULL) {
1754 cout << "Commander::HelptoLaTex_Error: fopen( " << fname << endl;
1755 return;
1756 }
1757
1758fputs("% ----- Liste des groupes de Help ----- \n",fip);
1759fputs("List of {\\bf piapp} on-line Help groups: \n", fip);
1760fputs("\\begin{itemize} \n",fip);
1761string prl;
1762string mol;
1763CmdHGroup::iterator it;
1764for(it = cmdhgrp.begin(); it != cmdhgrp.end(); it++) {
1765 if ((*it).first == "All") continue;
1766 prl = (*it).first; check_latex_reflabel(prl);
1767 mol = check_latex_underscore((*it).first);
1768 fprintf(fip,"\\item {\\bf %s } (p. \\pageref{%s}) \n",
1769 mol.c_str(), prl.c_str());
1770}
1771
1772fputs("\\end{itemize} \n",fip);
1773
1774fputs("\\vspace*{10mm} \n",fip);
1775
1776CmdExmap::iterator ite;
1777fputs("% ----- Liste de toutes les commandes et help item ----- \n",fip);
1778fputs("\\vspace{5mm} \n",fip);
1779// fputs("\\begin{table}[h!] \n", fip);
1780fputs("\\begin{center} \n ", fip);
1781fputs("\\rule{2cm}{1mm} List of {\\bf piapp} Help items \\rule{2cm}{1mm} \\\\ \n", fip);
1782fputs("\\vspace{3mm} \n",fip);
1783fputs("\\begin{tabular}{llllll} \n", fip);
1784int kt = 0;
1785for(ite = helpexmap.begin(); ite != helpexmap.end(); ite++) {
1786 prl = (*ite).first; check_latex_reflabel(prl);
1787 mol = check_latex_underscore((*ite).first);
1788 fprintf(fip,"%s & p. \\pageref{%s} ", mol.c_str(), prl.c_str() );
1789 kt++;
1790 if (kt < 3) fputs(" & ", fip);
1791 else { fputs(" \\\\ \n", fip); kt = 0; }
1792 }
1793if (kt == 1) fputs(" & & & \\\\ \n", fip);
1794else if (kt == 2) fputs(" & \\\\ \n", fip);
1795fputs("\\end{tabular} \n", fip);
1796fputs("\\end{center} \n", fip);
1797//fputs("\\end{table} \n", fip);
1798fputs("\\newpage \n",fip);
1799
1800int gid;
1801for(it = cmdhgrp.begin(); it != cmdhgrp.end(); it++) {
1802 gid = (*it).second;
1803 if (gid == 0) continue;
1804 // fputs("\\begin{table}[h!] \n",fip);
1805 fputs("\\vspace{6mm} \n",fip);
1806 fputs("\\begin{center} \n ", fip);
1807 fprintf(fip, "\\rule{2cm}{1mm} \\makebox[60mm]{{ \\bf %s } help group} \\rule{2cm}{1mm} \\\\ \n",
1808 (*it).first.c_str());
1809 fputs("\\vspace{3mm} \n",fip);
1810 fputs("\\begin{tabular}{llllll} \n", fip);
1811 kt = 0;
1812 for(ite = helpexmap.begin(); ite != helpexmap.end(); ite++) {
1813 if ((*ite).second.group != gid) continue;
1814 prl = (*ite).first; check_latex_reflabel(prl);
1815 mol = check_latex_underscore((*ite).first);
1816 fprintf(fip,"%s & p. \\pageref{%s} ", mol.c_str(), prl.c_str() );
1817 kt++;
1818 if (kt < 3) fputs(" & ", fip);
1819 else { fputs(" \\\\ \n", fip); kt = 0; }
1820 }
1821 for(ite = cmdexmap.begin(); ite != cmdexmap.end(); ite++) {
1822 if ((*ite).second.group != gid) continue;
1823 prl = (*ite).first; check_latex_reflabel(prl);
1824 mol = check_latex_underscore((*ite).first);
1825 fprintf(fip,"%s & p. \\pageref{%s} ", mol.c_str(), prl.c_str() );
1826 kt++;
1827 if (kt < 3) fputs(" & ", fip);
1828 else { fputs(" \\\\ \n", fip); kt = 0; }
1829 }
1830 if (kt == 1) fputs(" & & & \\\\ \n", fip);
1831 else if (kt == 2) fputs(" & \\\\ \n", fip);
1832 fputs("\\end{tabular} \n", fip);
1833 fputs("\\end{center} \n", fip);
1834 // fputs("\\end{table} \n",fip);
1835 // fputs("\\vspace{5mm} \n",fip);
1836}
1837// fputs("\\newline \n",fip);
1838
1839fputs("% ----- Liste des commandes dans chaque groupe ----- \n",fip);
1840fputs("\\newpage \n",fip);
1841
1842for(it = cmdhgrp.begin(); it != cmdhgrp.end(); it++) {
1843 gid = (*it).second;
1844 if (gid == 0) continue;
1845 prl = (*it).first; check_latex_reflabel(prl);
1846 fprintf(fip,"\\subsection{%s} \\label{%s} \n",
1847 (*it).first.c_str(), prl.c_str());
1848 fprintf(fip,"\\noindent \n");
1849 for(ite = helpexmap.begin(); ite != helpexmap.end(); ite++) {
1850 if ((*ite).second.group != gid) continue;
1851 prl = (*ite).first; check_latex_reflabel(prl);
1852 mol = check_latex_underscore((*ite).first);
1853 fprintf(fip,"\\piahelpitem{%s} \\label{%s} \n",
1854 mol.c_str(), prl.c_str());
1855 fputs("\\begin{verbatim} \n",fip);
1856 fprintf(fip,"%s\n", (*ite).second.us.c_str());
1857 fputs("\\end{verbatim} \n",fip);
1858 }
1859 for(ite = cmdexmap.begin(); ite != cmdexmap.end(); ite++) {
1860 if ((*ite).second.group != gid) continue;
1861 prl = (*ite).first; check_latex_reflabel(prl);
1862 mol = check_latex_underscore((*ite).first);
1863 fprintf(fip,"\\piacommand{%s} \\label{%s} \n",
1864 mol.c_str(), prl.c_str());
1865 fputs("\\begin{verbatim} \n",fip);
1866 fprintf(fip,"%s\n", (*ite).second.us.c_str());
1867 fputs("\\end{verbatim} \n",fip);
1868 }
1869}
1870
1871fclose(fip);
1872return;
1873}
1874
1875
1876
Note: See TracBrowser for help on using the repository browser.