0023042: Potential mistakes in (s)printf usage
[occt.git] / src / IFSelect / IFSelect_SessionPilot.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <Standard_Stream.hxx>
19
20 #include <IFSelect_SessionPilot.ixx>
21 #include <IFSelect_Activator.hxx>
22 #include <IFSelect_Selection.hxx>
23 #include <Interface_EntityIterator.hxx>
24 #include <Interface_InterfaceModel.hxx>
25 #include <TColStd_HSequenceOfAsciiString.hxx>
26
27 #include <Interface_Macros.hxx>
28 #include <Message_Messenger.hxx>
29 #include <Message.hxx>
30
31 #include <stdio.h>
32
33 #define MAXWORDS 200
34 #define MAXCARS 1000
35
36 static int initactor = 0;
37 static char* trace;
38
39 static TCollection_AsciiString nulword;
40
41 // Nb Maxi de words : cf thewords et method SetCommandLine
42
43     IFSelect_SessionPilot::IFSelect_SessionPilot (const Standard_CString prompt)
44     : theprompt (prompt) , thewords (0,MAXWORDS-1) , thewordeb (0,MAXWORDS-1)
45 {
46   if (theprompt.Length() == 0) theprompt.AssignCat ("Test-XSTEP>");
47   therecord = Standard_False;  thenbwords = 0;
48   if (initactor) return;  initactor = 1;
49   Add (1,"x");
50   Add (1,"exit");
51   Add (2,"?");
52   Add (2,"xhelp");
53   Add (3,"xcommand");
54   Add (4,"xsource");
55   Add (5,"xstep");
56   Add (6,"xnew");
57   trace = getenv("DEBUGMODE");
58 }
59
60
61     Handle(IFSelect_WorkSession)  IFSelect_SessionPilot::Session () const 
62       {  return thesession;  }
63
64     Handle(IFSelect_WorkLibrary)  IFSelect_SessionPilot::Library () const 
65       {  return thesession->WorkLibrary();  }
66
67     Standard_Boolean  IFSelect_SessionPilot::RecordMode () const 
68       {  return therecord;  }
69
70     void  IFSelect_SessionPilot::SetSession
71   (const Handle(IFSelect_WorkSession)& WS)
72       {  thesession = WS;  }
73
74     void  IFSelect_SessionPilot::SetLibrary
75   (const Handle(IFSelect_WorkLibrary)& WL)
76       {  if (!thesession.IsNull()) thesession->SetLibrary(WL);  }
77
78     void  IFSelect_SessionPilot::SetRecordMode (const Standard_Boolean mode)
79       {  therecord = mode;  }
80
81
82     void  IFSelect_SessionPilot::SetCommandLine
83   (const TCollection_AsciiString& command)
84 {
85   Standard_Integer lc = command.Length();
86   if (lc > 200) cout<<" Commande TRES LONGUE : "<<lc<<" caracteres :"<<endl
87     <<command.ToCString()<<endl;
88   thecommand = command;
89   if (thecommand.Value(lc) <= ' ')  {  thecommand.Remove(lc);  lc --;  }
90   thenbwords = 0;
91   Standard_Integer i, nc = 0;
92   char unarg[MAXCARS];
93   for (i = 1; i <= lc; i ++) {
94     char val = command.Value(i);
95     if (val <= ' ') {
96       if (nc == 0) continue;
97       if (thenbwords >= MAXWORDS) {  unarg[nc] = val;  nc ++;  continue;  }
98       unarg[nc] = '\0';
99       thewords(thenbwords).Clear();  thewords(thenbwords).AssignCat(unarg);
100       if (trace) cout<<"thewords("<<thenbwords<<") ="<<unarg<<endl;
101       thenbwords ++; nc = 0;
102       continue;
103     }
104     if (nc == 0) thewordeb.SetValue (thenbwords,i);
105     if (nc > MAXCARS) {  cout<<"Arg."<<thenbwords<<" > "<<MAXCARS<<" car.s, tronque"<<endl; continue;  }
106     unarg[nc] = val;  nc ++;
107   }
108   if (nc > 0) {
109     unarg[nc] = '\0'; thewords(thenbwords).Clear();
110     thewords(thenbwords).AssignCat(unarg);
111     if (trace) cout<<"thewords("<<thenbwords<<")="<<unarg<<endl<<" .. Fin avec thenbwords="<<thenbwords+1<<endl;
112     thenbwords ++;
113   }
114 /*
115     aligner sur MAXWORDS
116   char l0[80],l1[80],l2[80],l3[80],l4[80],l5[80],l6[80],l7[80],l8[80],l9[80];
117   char m0[80],m1[80],m2[80],m3[80],m4[80],m5[80],m6[80],m7[80],m8[80],m9[80];
118   thenbwords = sscanf
119     (thecommand.ToCString(),"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
120      l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,m0,m1,m2,m3,m4,m5,m6,m7,m8,m9);
121   if (thenbwords <  0) thenbwords = 0;
122   if (thenbwords > MAXWORDS) thenbwords = MAXWORDS;
123   Standard_Integer nb = thewords.Upper();
124   for (i = 0; i <= nb; i ++) thewords(i).Clear();
125   switch (thenbwords) {
126     case 20 : thewords(19).AssignCat(m9);
127     case 19 : thewords(18).AssignCat(m8);
128     case 18 : thewords(17).AssignCat(m7);
129     case 17 : thewords(16).AssignCat(m6);
130     case 16 : thewords(15).AssignCat(m5);
131     case 15 : thewords(14).AssignCat(m4);
132     case 14 : thewords(13).AssignCat(m3);
133     case 13 : thewords(12).AssignCat(m2);
134     case 12 : thewords(11).AssignCat(m1);
135     case 11 : thewords(10).AssignCat(m0);
136     case 10 : thewords(9).AssignCat(l9);
137     case  9 : thewords(8).AssignCat(l8);
138     case  8 : thewords(7).AssignCat(l7);
139     case  7 : thewords(6).AssignCat(l6);
140     case  6 : thewords(5).AssignCat(l5);
141     case  5 : thewords(4).AssignCat(l4);
142     case  4 : thewords(3).AssignCat(l3);
143     case  3 : thewords(2).AssignCat(l2);
144     case  2 : thewords(1).AssignCat(l1);
145     case  1 : thewords(0).AssignCat(l0);
146     default : break;
147   }
148 */
149   thenumrec = 0;
150   theobjrec.Nullify();
151 }
152
153     const TCollection_AsciiString&  IFSelect_SessionPilot::CommandLine () const
154       {  return thecommand;  }
155
156     Standard_CString  IFSelect_SessionPilot::CommandPart
157   (const Standard_Integer numarg) const
158 {
159   if (numarg <= 0) return thecommand.ToCString();
160   if (numarg >= thenbwords) return "";
161   return &(thecommand.ToCString())[thewordeb(numarg)-1];
162 }
163
164     Standard_Integer  IFSelect_SessionPilot::NbWords () const 
165       {  return thenbwords;  }
166
167     const TCollection_AsciiString&  IFSelect_SessionPilot::Word
168   (const Standard_Integer num) const 
169       {  if (num < thenbwords) return thewords(num);  return nulword;  }
170
171     Standard_CString  IFSelect_SessionPilot::Arg
172   (const Standard_Integer num) const 
173       {  return Word(num).ToCString();  }
174
175     Standard_Boolean  IFSelect_SessionPilot::RemoveWord
176   (const Standard_Integer num)
177 {
178   if (num < 0 || num > thenbwords) return Standard_False;
179   Standard_Integer i; // svv Jan11 2000 : porting on DEC
180   for (i = num; i < thenbwords; i ++) {
181     thewords(i).Clear();
182     thewords(i).AssignCat(thewords(i+1).ToCString());
183   }
184   thewords(thenbwords).Clear();
185   thenbwords --;
186 //  Et refaire thecommand. Si num = 0, on supprime le debut (facile)
187   if (num == 0) {
188     thecommand.Remove(1,thewordeb(1));
189   } else {
190 //   Sinon, reconstituer, a partir des words
191     thecommand.Clear();
192     for (i = 0; i < thenbwords; i ++) {
193       if (i > 0) thecommand.AssignCat(" ");
194       thecommand.AssignCat(thewords(i));
195     }
196   }
197
198   return Standard_True;
199 }
200
201     Standard_Integer  IFSelect_SessionPilot::NbCommands () const 
202       {  return thecomlist.Length();  }
203
204     const TCollection_AsciiString&  IFSelect_SessionPilot::Command
205   (const Standard_Integer num) const 
206       {  return thecomlist(num);  }
207
208
209     IFSelect_ReturnStatus  IFSelect_SessionPilot::RecordItem
210   (const Handle(Standard_Transient)& item)
211 {
212   theobjrec = item;
213   return (item.IsNull() ? IFSelect_RetFail : IFSelect_RetDone);
214 }
215
216     Handle(Standard_Transient)  IFSelect_SessionPilot::RecordedItem () const
217       {  return theobjrec;  }
218
219     void  IFSelect_SessionPilot::Clear ()
220       { thecomlist.Clear(); }
221
222
223 //  #######################################################################
224 //  ########        CONTROLE D EXECUTION
225
226
227     IFSelect_ReturnStatus  IFSelect_SessionPilot::ReadScript
228   (const Standard_CString file)
229 {
230   FILE* fic; int lefic = 0;
231   if (file != NULL && file[0] != '\0') {
232     fic = fopen (file,"r");
233     if (fic) lefic = 1;
234     else { cout<<" ...   Script File "<<file<<" not found"<<endl; return IFSelect_RetFail; }
235     cout << " ...   Reading Script File " << file << endl;
236   }
237   else fic = stdin;
238   IFSelect_ReturnStatus stat = IFSelect_RetVoid;
239
240   for (;;) {
241     char ligne[100];
242     if (!lefic) std::cout << theprompt.ToCString();
243     ligne[0] = '\0';
244     fgets(ligne,100,fic);
245     if (feof(fic)) break;
246     if (ligne[0] == '\0') continue;
247 //    On interprete cette commande
248     TCollection_AsciiString command(ligne);
249     if (lefic) cout<<file<<":"<<command;  // le return est dans la ligne ... !
250     stat = Execute(command);
251     if (stat == IFSelect_RetStop) break;
252     if ((stat == IFSelect_RetError || stat == IFSelect_RetFail) && lefic)
253       { cout << " ...   Error in Script File, abandon"<<endl;  break; }
254   }
255   if (!lefic) return IFSelect_RetStop;
256   fclose(fic);
257   cout<<"End of Reading Script File " << file << endl;
258   if (stat == IFSelect_RetError || stat == IFSelect_RetFail) return stat;
259   return IFSelect_RetVoid;        // fin fichier : depiler
260 }
261
262
263 //  On boucle sur la lecture jusqu a une commande de fin ou un EOF
264
265     IFSelect_ReturnStatus  IFSelect_SessionPilot::Perform ()
266 {
267   IFSelect_ReturnStatus stat = IFSelect_RetVoid;
268   if (thenbwords == 0) return stat;
269   if (thewords(0).Value(1) == '#') return stat;  // commentaire
270
271   theobjrec.Nullify();
272 //  Est-ce un nom ?
273
274 //  Commande pour un Acteur
275   Handle(IFSelect_Activator) actor;  Standard_Integer num;
276   if (IFSelect_Activator::Select(thewords(0).ToCString(),num,actor)) {
277     stat = actor->Do(num,this);
278 //  Prise en compte des commandes a resultat
279 //  Ici, resultat non nomme;  Resultat nomme par commande x (plus loin)
280     if (!theobjrec.IsNull()) {
281       thesession->RemoveItem(theobjrec);  //// depannage ?
282       Standard_Boolean addws = thesession->AddItem(theobjrec);
283       if (!addws) { cout<<"Could not add item to session, sorry"<<endl; return IFSelect_RetFail; }
284     }
285
286     if (stat == IFSelect_RetVoid || stat == IFSelect_RetDone) {
287       if (therecord) thecomlist.Append(thecommand);
288     }
289     else if (stat == IFSelect_RetError) cout<<"Error in Command : "<<thecommand<<endl;
290     else if (stat == IFSelect_RetFail) cout << "Execution Failure for : " <<thecommand<<endl;
291     return stat;
292   }
293   cout << " Command : " << thewords(0) << " unknown" << endl;
294   return IFSelect_RetError;    // pas reconnu donc incorrect
295 }
296
297     IFSelect_ReturnStatus  IFSelect_SessionPilot::ExecuteAlias
298   (const TCollection_AsciiString& alias)
299 {
300   if (alias.Length() > 0) thewords(0) = alias;
301   return Perform();
302 }
303
304     IFSelect_ReturnStatus  IFSelect_SessionPilot::Execute
305   (const TCollection_AsciiString& command)
306 {
307   SetCommandLine(command);
308   return Perform();
309 }
310
311     IFSelect_ReturnStatus  IFSelect_SessionPilot::ExecuteCounter
312   (const Handle(IFSelect_SignCounter)& counter, const Standard_Integer numword,
313    const IFSelect_PrintCount mode)
314 {
315   if (counter.IsNull()) return IFSelect_RetError;
316   counter->Clear();
317   if (NbWords() <= numword) counter->AddModel (thesession->Model());
318   else {
319 //   on demande un givelist
320     Handle(TColStd_HSequenceOfTransient) list = thesession->GiveList (CommandPart(numword));
321     if (list.IsNull()) {
322       cout<<"Nothing selected from : "<<CommandPart(numword)<<endl;
323       return IFSelect_RetError;
324     }
325     counter->AddWithGraph (list,thesession->Graph());
326   }
327   counter->PrintList(Message::DefaultMessenger(),thesession->Model(),mode);
328   return IFSelect_RetVoid;
329 }
330
331     Standard_Integer  IFSelect_SessionPilot::Number
332   (const Standard_CString val) const
333 {
334   Standard_Integer num = thesession->NumberFromLabel (val);
335   if (num < 0)  cout<<" Label:"<<val<<" ->"<<-num<<" ent.s, refus"<<endl;
336   return num;
337 }
338
339
340 //  #########################################################################
341 //  ########        ACTIONS SPECIFIQUES DU PILOTE
342
343 #define MAXCOMPERLINE  5
344 #define LENGTHFORCOM  15
345
346     IFSelect_ReturnStatus  IFSelect_SessionPilot::Do
347   (const Standard_Integer number,
348    const Handle(IFSelect_SessionPilot)& session)
349 {
350 //                  Commandes Propres : x, exit, undo, redo, ?, help
351   IFSelect_ReturnStatus  stat = IFSelect_RetVoid;
352   Standard_Integer       argc = NbWords();
353   const Standard_CString arg1 = Word(1).ToCString();
354   Standard_Integer       modhelp = -1;
355   switch (number) {
356     case -1 :                                 //        ****     HELP-XSNEW
357       modhelp = 1;
358       cout<<"  --  Commands candidate for  xsnew  --"<<endl;
359 //  HELP : soit complet (par defaut)  soit limite a xsnew
360     case  0 : {                               //        ****     HELP
361       Handle(TColStd_HSequenceOfAsciiString) list;
362 //    Help complet : on donne la liste des commandes, sans plus (deja pas mal)
363       if (thenbwords <= 1) {
364         list = IFSelect_Activator::Commands(modhelp);
365         Standard_Integer nbcom = 0;
366         Standard_Integer nb = list->Length();
367         cout << " -- Liste des Commands Disponibles --"<<endl;
368         for (Standard_Integer i = 1; i <= nb; i ++) {
369           const TCollection_AsciiString& uncom = list->Value(i);
370           Standard_Integer loncom = uncom.Length();
371           nbcom ++;
372           if (nbcom > MAXCOMPERLINE) { cout<<endl; nbcom = 1; }
373           cout<<" "<<uncom;
374           if (nbcom == MAXCOMPERLINE) continue;
375           for (Standard_Integer j = loncom; j < LENGTHFORCOM; j ++) cout<<" ";
376         }
377         if (nbcom > 0) cout<<endl;
378         cout<<"\nhelp *  liste toutes les commandes avec un help sur chacune\n"
379           <<"help <com> liste la ou les commande debutant par <com>"
380           <<" avec un help sur chacune"<<endl;
381
382 //    Un Help particulier
383       } else {
384         if (thewords(1).IsEqual("*")) list = IFSelect_Activator::Commands(modhelp);
385
386         else list = IFSelect_Activator::Commands(modhelp,thewords(1).ToCString());
387
388         Standard_Integer nb = list->Length();
389         for (Standard_Integer i = 1; i <= nb; i ++) {
390           Handle(IFSelect_Activator) actor;  Standard_Integer num;
391           if (IFSelect_Activator::Select
392               (list->Value(i).ToCString(),num,actor)) {
393             if (IFSelect_Activator::Mode (list->Value(i).ToCString()) == 1)
394               cout<<"[xsnew name] ";
395             cout << list->Value(i) << " : " << actor->Help(num) << endl;
396           }
397         }
398         if (nb == 0 && thenbwords > 1) cout<<" Command "<<Word(1)<<" unknown. "
399           << " help (without command) lists all the commands" << endl;
400       }
401       return IFSelect_RetVoid;
402     }
403     case  1 : return IFSelect_RetStop;        //        ****     Fin de session
404     case  2 : {                               //        ****     HELP
405       return Do(0,this);
406     }
407     case  3 : {                               //        ****     COMMAND
408       if (argc < 2) { cout << "Donner une option :\n"
409          <<"a : analyse une ligne  r : toggle record mode\n"
410          <<"l : list recorded  c : clear  f nom : sauver dans fichier de nom"
411          << endl; return IFSelect_RetVoid; }
412       switch (arg1[0]) {
413         case 'a' : {                          //        ****    command analyse
414           cout<<"Command n0 " << number <<" : "<< session->CommandLine()<<endl;
415           cout<<"Nb Words : " << argc-2 << " :\n";
416           for (Standard_Integer i = 2; i < argc; i ++) {
417             cout << " Word." << i-1 << " : " << session->Word(i) <<endl;
418           }
419           break;
420         }
421         case 'c' : session->Clear();  break;  //        ****    command clear
422         case 'f' : {
423           if (argc < 3) { cout<<"Donner nom de fichier"<<endl; return IFSelect_RetError; }
424           Standard_Integer nb = session->NbCommands();
425           if (nb == 0) { cout<<"Aucune commande enregistree"<<endl; break; }
426           cout << "Nb Commandes enregistrees : " << nb <<endl;
427           ofstream fout(Word(2).ToCString(),ios::out);
428           for (Standard_Integer i = 1; i <= nb; i ++)
429             fout<<session->Command(i)<<endl;
430           break;
431         }
432         case 'l' : {                          //        ****    command list
433           if (session->RecordMode()) cout<<"  -- Record Mode Actif"<<endl;
434           else                       cout<<"  -- Record Mode Inactif"<<endl;
435           Standard_Integer nb = session->NbCommands();
436           cout << "Nb Commandes enregistrees : " << nb << " :"<<endl;
437           for (Standard_Integer i = 1; i <= nb; i ++) {
438             cout<<"  "<<i<<"    "<<session->Command(i)<<endl;
439           }
440           break;
441         }
442         case 'r' : {                          //        ****    command record
443           Standard_Boolean mode = session->RecordMode();
444           if (mode) cout << " -- Record Mode a present Inactif" <<endl;
445           else      cout << " -- Record Mode a present Actif"   <<endl;
446           session->SetRecordMode(!mode);
447           break;
448         }
449         default  : cout << "Option de controle de commande non comprise"<<endl;
450       }
451       return IFSelect_RetVoid;
452     }
453
454     case  4 : {                               //        ****     FILE
455       if (argc < 2) { cout<<"Donner nom de fichier"<<endl; return IFSelect_RetError; }
456       return session->ReadScript
457         (TCollection_AsciiString(session->Word(1)).ToCString());
458 //          On recopie la string parce que Word(1) change tout le temps !
459     }
460
461     case  5 : {                               //        ****     XSTEP
462       if (argc < 2) {
463         cout<<"xstep : prefixe neutre pour toute commande xstep-draw"<<endl
464           <<"xstep command args  equivaut a  command args"<<endl;
465         return Do(2,this);
466       } else {
467         RemoveWord(0);
468         return Perform();
469       }
470     }
471     case  6 : {                               //        ****    XSNEW(variable)
472       if (argc < 3) {
473         cout<<"xsnew nomvar command [args]   creates an item"<<endl
474           <<"  nomvar : name of item (must be a new name) in the session"<<endl;
475         return Do (-1,this);
476       } else {
477
478         theobjrec.Nullify();
479         TCollection_AsciiString name = Word(1);
480 //  Le nom ne doit pas etre deja pris !
481           if (thesession.IsNull()) { cout<<"Command with a Name and no Session defined !"<<endl; return IFSelect_RetFail; }
482 //////    if (thesession->NameIdent(thewords(0).ToCString()) > 0)
483 //////      { cout<<"Command with name:"<<thewords(0)<<", already taken"<<endl; return IFSelect_RetFail; }
484         RemoveWord(0);  RemoveWord(0);
485
486 //  Commande pour un Acteur
487         Handle(IFSelect_Activator) actor;  Standard_Integer num;
488         if (IFSelect_Activator::Select(thewords(0).ToCString(),num,actor)) {
489           theobjrec.Nullify();
490           stat = actor->Do(num,this);
491 //  Prise en compte des commandes a resultat
492           if (!theobjrec.IsNull()) {
493             thesession->RemoveItem(theobjrec);  //// depannage ?
494             Standard_Boolean addws =
495               thesession->AddNamedItem(name.ToCString(),theobjrec);
496             theobjrec.Nullify();
497             if (!addws) { cout<<"Could not add named item:"<<name<<", sorry"<<endl; return IFSelect_RetFail; }
498           }
499           else cout<<"Remark : xsnew with name:"<<name<<" and no result"<<endl;
500
501           return stat;
502         }
503         cout << " Command : " << thewords(0) << " unknown" << endl;
504         return IFSelect_RetError;    // pas reconnu donc incorrect
505       }
506     }
507     default : return IFSelect_RetError;
508   }
509 }
510
511
512
513     Standard_CString  IFSelect_SessionPilot::Help
514   (const Standard_Integer number) const
515 {
516   switch (number) {
517     case  1 : return "exit ou x : Fin de session";
518     case  2 : return "Liste les commandes. ? <titre> : commandes debutant par <titre>";
519     case  3 : return "controle de commande. command tout court pour help complet";
520     case  4 : return "lit les commandes depuis un fichier";
521     case  5 : return "prefixe neutre pour xstep-draw";
522     case  6 : return "creation item : donner nom_item puis commande args";
523     default : return "";
524   }
525 }