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

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

Amelioration gestion variables ds interpreteur (classe Commander) - Introduction de trois niveaux : Var. interpreteur, env. appli, environnement global + amelioration gestion vecteur au niveau de l'interpreteur - Reza 22/12/2003

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