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

Last change on this file since 2598 was 2598, checked in by ansari, 21 years ago

Documentation (ajoutee ou completee) pour les classes du module SysTools - Reza 11 Aout 2004

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