source: Sophya/trunk/SophyaPI/PIext/piacmd.cc@ 2268

Last change on this file since 2268 was 2265, checked in by ansari, 23 years ago

Ajout addarca et addfarca: Trace d'arc defini par un angle et dangle + sum/product/mean/sigma ds RPNEvaluator - Reza 14/11/2002

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