0023148: Error in stepstrcmp
[occt.git] / src / StepData / StepData_StepReaderData.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 //    abv 09.04.99 S4136: eliminate parameter step.readaccept.void
19 //    sln 04,10.2001. BUC61003. Prevent exception which may occur during reading of complex entity (if entity's items are not in alphabetical order)
20 #include <StepData_StepReaderData.ixx>
21 #include <StepData_StepModel.hxx>
22 #include <Interface_FileParameter.hxx>
23 #include <Interface_ParamList.hxx>
24 #include <Message_Messenger.hxx>
25 #include <Message.hxx>
26 #include <Interface_Static.hxx>
27 #include <Interface_Macros.hxx>
28
29 #include <TColStd_SequenceOfInteger.hxx>
30 #include <TColStd_HArray1OfInteger.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_IndexedMapOfInteger.hxx>
33 #include <TCollection_HAsciiString.hxx>
34
35 #include <TColStd_HArray1OfTransient.hxx>
36 #include <TColStd_HArray1OfReal.hxx>
37 #include <Interface_HArray1OfHAsciiString.hxx>
38 #include <StepData_SelectMember.hxx>
39 #include <StepData_SelectNamed.hxx>
40 #include <StepData_SelectReal.hxx>
41 #include <StepData_SelectInt.hxx>
42 #include <TColStd_HSequenceOfReal.hxx>
43 #include <StepData_SelectArrReal.hxx>
44
45 #include <stdio.h>
46
47
48 // Le Header est constitue d entites analogues dans leur principe a celles
49 // du Data, a ceci pres qu elles sont sans identifieur, et ne peuvent ni
50 // referencer, ni etre referencees (que ce soit avec Header ou avec Data)
51 // Ainsi, dans StepReaderData, le Header est constitue des "thenbhead" 1res Entites
52
53
54 //  #########################################################################
55 //  ....   Creation et Acces de base aux donnees atomiques du fichier    ....
56
57 typedef TCollection_HAsciiString String;
58 typedef Handle(TCollection_HAsciiString) Handle(String);
59 static char txtmes[200];  // plus commode que redeclarer partout
60
61
62 static Standard_Boolean initstr = Standard_False;
63
64 #define Maxlst 64
65 //static TCollection_AsciiString subl[Maxlst];          // Maxlst : minimum 10
66
67 static Standard_Integer acceptvoid = 0;
68
69 // ----------  Fonctions Utilitaires  ----------
70
71 //=======================================================================
72 //function : CleanText
73 //purpose  : 
74 //=======================================================================
75 static void CleanText (const Handle(TCollection_HAsciiString)& val)
76 {
77   Standard_Integer n = val->Length();    // avant reduction
78   val->Remove(n);
79   val->Remove(1);
80 //  Ne pas oublier de traiter les caracteres speciaux
81   for (Standard_Integer i = n-2; i > 0; i --) {
82     char uncar = val->Value(i);
83     if (uncar == '\n')
84       {      val->Remove(i);      if (i < n-2) uncar = val->Value(i);  }
85     if (uncar == '\'' && i < n-2) {
86       if (val->Value(i+1) == '\'')  {  val->Remove(i+1);    continue;  }
87     }
88     if (uncar == '\\' && i < n-2) {
89       if (val->Value(i+1) == '\\')  {  val->Remove(i+1);    continue;  }
90     }
91     else if (uncar == '\\' && i < n-3) {
92       if (val->Value(i+2) == '\\') {
93         if (val->Value(i+1) == 'N')
94           {  val->SetValue(i,'\n');    val->Remove(i+1,2);  continue;  }
95         if (val->Value(i+1) == 'T')
96           {  val->SetValue(i,'\t');    val->Remove(i+1,2);  continue;  }
97       }
98     }
99   }
100 }
101
102 //  -------------  METHODES  -------------
103
104 //=======================================================================
105 //function : StepData_StepReaderData
106 //purpose  : 
107 //=======================================================================
108
109 StepData_StepReaderData::StepData_StepReaderData
110   (const Standard_Integer nbheader, const Standard_Integer nbtotal,
111    const Standard_Integer nbpar)
112 : Interface_FileReaderData (nbtotal,nbpar), theidents (1,nbtotal),
113   thetypes (1,nbtotal) //, themults (1,nbtotal)
114 {
115 //  char textnum[10];
116   thenbscop = 0;  thenbents = 0;  thelastn = 0;  thenbhead = nbheader;
117   //themults.Init(0);
118   thecheck = new Interface_Check;
119 //:S4136  acceptvoid = Interface_Static::IVal("step.readaccept.void");
120   if (initstr) return;
121   //for (Standard_Integer i = 0; i < Maxlst; i ++) {
122   //  sprintf(textnum,"$%d",i+1);
123   //  subl[i].AssignCat(textnum);
124   //}
125   initstr = Standard_True;
126 }
127
128
129 //=======================================================================
130 //function : SetRecord
131 //purpose  : 
132 //=======================================================================
133
134 void StepData_StepReaderData::SetRecord (const Standard_Integer num,
135                                          const Standard_CString ident,
136                                          const Standard_CString type,
137                                          const Standard_Integer /* nbpar */)
138 {
139   Standard_Integer numlst;
140 /*
141   if (strcmp(type,"/ * (SUB) * /") == 0) {    // defini dans recfile.pc
142     thetypes.SetValue (num,sublist);
143   } else {
144     thenbents ++;   // total de termes propres du fichier
145     thetypes.SetValue(num,TCollection_AsciiString(type));
146 //    if (strcmp(ident,"SCOPE") != 0) thenbscop ++;  // ?? a verifier
147   }
148 */
149   if (type[0] != '(') thenbents ++;   // total de termes propres du fichier
150   
151   //thetypes.ChangeValue(num).SetValue(1,type); gka memory
152   //============================================
153   Standard_Integer index = 0;
154   TCollection_AsciiString strtype(type);
155   if(thenametypes.Contains(type))
156     index = thenametypes.FindIndex(strtype);
157   else index = thenametypes.Add(strtype);
158   thetypes.ChangeValue(num) = index;
159   //===========================================
160     
161   if (ident[0] == '$') {
162     if (strlen(ident) > 2) numlst = atoi(&ident[1]);
163     else numlst = ident[1] - 48;
164     if (thelastn < numlst) thelastn = numlst;    // plus fort n0 de sous-liste
165     theidents.SetValue(num,-2-numlst);
166   } else if (ident[0] == '#') {
167     numlst = atoi(&ident[1]);
168     theidents.SetValue(num,numlst);
169     if (numlst == 0 && num > thenbhead) {
170 //    Header, ou bien Type Complexe ...
171 //    Si Type Complexe, retrouver Type Precedent (on considere que c est rare)
172 //    On chaine le type precedent sur le suivant
173 //    VERIFICATION que les types sont en ordre alphabetique
174       for (Standard_Integer prev = num-1; prev > thenbhead; prev --) {
175         if (theidents(prev) >= 0) {
176
177           //themults.SetValue(prev,num);
178           themults.Bind(prev,num);
179           if(thenametypes.FindKey(thetypes.Value(num)).IsLess(thenametypes.FindKey(thetypes.Value(prev)))) {
180           //if (thetypes.Value(num).IsLess(thetypes.Value(prev))) 
181
182 //  ERREUR : Type complexe pas en ordre alphabetique. On enregistre.
183             TCollection_AsciiString errm("Complex Type incorrect : ");
184             errm.AssignCat(thenametypes.FindKey(thetypes.Value(prev)));
185             errm.AssignCat(" / ");
186             errm.AssignCat(thenametypes.FindKey(thetypes.Value(num)));
187             errm.AssignCat(" ... ");
188             thecheck->AddFail(errm.ToCString(),"Complex Type incorrect : ");
189 //  On Affiche a l ecran, le plus de donnees possibles
190             while (theidents(prev) <= 0) {
191               prev --;  if (prev <= 0) break;
192             }
193             Handle(Message_Messenger) sout = Message::DefaultMessenger();
194             sout << "  ***  Error on Record " << num << " (on " << NbRecords()
195               << " -> " << num*100/NbRecords() << " % in File)  ***";
196             if (prev > 0) sout << "  Ident #" << theidents(prev);
197             sout << "\n" << errm << endl;
198           }
199           break;
200         }
201       }
202     }
203   }
204   else if (!strcmp(ident,"SCOPE")) {
205     theidents.SetValue(num,-1); // SCOPE
206     thenbscop ++;
207   }
208   else if (!strcmp(ident,"ENDSCOPE")) theidents.SetValue(num,-2);  // ENDSCOPE
209 //      Reste 0
210
211  // InitParams(num);
212 }
213
214
215 //=======================================================================
216 //function : AddStepParam
217 //purpose  : 
218 //=======================================================================
219
220 void StepData_StepReaderData::AddStepParam (const Standard_Integer num,
221                                             const Standard_CString aval,
222                                             const Interface_ParamType atype,
223                                             const Standard_Integer nument)
224 {
225   if (atype == Interface_ParamSub) {
226     Standard_Integer numid = 0;
227     if (aval[2] != '\0') {
228       numid = atoi(&aval[1]);
229 //      if (numid <= Maxlst) Interface_FileReaderData::AddParam
230 //      (num,subl[numid-1].ToCString(),atype,numid);
231       Interface_FileReaderData::AddParam (num,aval,atype,numid);
232     } else {
233       char *numlstchar = (char *)(aval+1);
234       numid = (*numlstchar) - 48;  // -48 ('0') -1 (adresse [] depuis 0)
235 //      Interface_FileReaderData::AddParam (num,subl[numid].ToCString(),atype,numid);
236       Interface_FileReaderData::AddParam (num,aval,atype,numid);
237     }
238   } else if (atype == Interface_ParamIdent) {
239     Standard_Integer numid = atoi(&aval[1]);
240     Interface_FileReaderData::AddParam (num,aval,atype,numid);
241   } else {
242     Interface_FileReaderData::AddParam (num,aval,atype,nument);
243   }
244
245 //  Interface_FileReaderData::AddParam (num,parval,atype,numid);
246 }
247
248
249 //=======================================================================
250 //function : RecordType
251 //purpose  : 
252 //=======================================================================
253
254 const TCollection_AsciiString& StepData_StepReaderData::RecordType
255   (const Standard_Integer num) const
256 {
257   return thenametypes.FindKey(thetypes.Value(num));  
258 }
259
260
261 //=======================================================================
262 //function : CType
263 //purpose  : 
264 //=======================================================================
265
266 Standard_CString StepData_StepReaderData::CType(const Standard_Integer num) const
267 {
268   return thenametypes.FindKey(thetypes.Value(num)).ToCString();
269 }
270
271
272 //=======================================================================
273 //function : RecordIdent
274 //purpose  : 
275 //=======================================================================
276
277 Standard_Integer StepData_StepReaderData::RecordIdent (const Standard_Integer num) const
278 {
279   return theidents(num);
280 }
281
282
283 //  ########################################################################
284 //  ....       Aides a la lecture des parametres, adaptees a STEP       ....
285
286
287 //=======================================================================
288 //function : SubListNumber
289 //purpose  : 
290 //=======================================================================
291
292 Standard_Integer StepData_StepReaderData::SubListNumber (const Standard_Integer num,
293                                                          const Standard_Integer nump,
294                                                          const Standard_Boolean aslast) const
295 {
296   if (nump == 0 || nump > NbParams(num)) return 0;
297   const Interface_FileParameter& FP = Param(num,nump);
298   if (FP.ParamType() != Interface_ParamSub) return 0;
299   if (aslast)  {  if(nump != NbParams(num)) return 0;  }
300   return FP.EntityNumber();
301 }
302
303
304 //=======================================================================
305 //function : IsComplex
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Boolean StepData_StepReaderData::IsComplex(const Standard_Integer num) const
310 {
311   //return (themults(num) != 0);
312   return themults.IsBound(num);
313 }
314
315
316 //=======================================================================
317 //function : ComplexType
318 //purpose  : 
319 //=======================================================================
320
321 void  StepData_StepReaderData::ComplexType(const Standard_Integer num,
322                                            TColStd_SequenceOfAsciiString& types) const
323 {
324   if (theidents(num) < 0) return;
325   for (Standard_Integer i = num; i > 0; i = NextForComplex(i)) {
326     types.Append(RecordType(i));
327   }
328 }
329
330
331 //=======================================================================
332 //function : NextForComplex
333 //purpose  : 
334 //=======================================================================
335
336 Standard_Integer StepData_StepReaderData::NextForComplex
337   (const Standard_Integer num) const
338 {
339   Standard_Integer next =0;
340   if(themults.IsBound(num))
341     next = themults.Find(num);
342   return next;
343 }
344
345
346 //=======================================================================
347 //function : stepstrcmp
348 //purpose  : 
349 //=======================================================================
350 static Standard_Boolean stepstrcmp(const Standard_CString type,
351                                    const Standard_CString name)
352 {
353 //  name peut etre d un tenant ou de deux : auquel cas il a une partie LONGUE
354 //  et une partie COURTE separees par un blanc
355 //  Attention : False pour dire OK, True sinon (car remplace strcmp)
356   Standard_Integer i,j = 0; Standard_Boolean res = Standard_False;
357   for (i = 0; name[i] != '\0' && type[i] != '\0' && !res ; i ++) {
358     if (name[i] == ' ' && type[i] == '\0') { j = i; break; }
359     if (type[i] != name[i]) res = Standard_True;
360   }
361   if (!res || (j == 0)) return res;
362 //  Pas trouve et un blanc suit : on continue
363   for (i = j+1; name[i] != '\0'; i ++) {
364     if (type[i-j-1] != name[i]) return Standard_True;
365   }
366   return Standard_False;
367 }
368
369
370 //=======================================================================
371 //function : NamedForComplex
372 //purpose  : 
373 //=======================================================================
374
375 Standard_Boolean  StepData_StepReaderData::NamedForComplex
376   (const Standard_CString name, const Standard_Integer num0,
377    Standard_Integer& num, Handle(Interface_Check)& ach) const
378 {
379   //Standard_Boolean stat = Standard_True;
380   Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num));
381   // sln 04,10.2001. BUC61003. if(n==0) the next  function is not called in order to avoid exception
382   if ((n!=0) && (!stepstrcmp (RecordType(n).ToCString(),name)))
383     {  num = n;  return Standard_True;  }
384   
385   if (n == 0) /*stat =*/ NamedForComplex (name,num0,n,ach);  // on a rembobine
386 //  Pas dans l ordre alphabetique : boucler
387   Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
388   sprintf (txtmes,errmess->ToCString(),num0,name);
389   for (n = num0; n > 0; n = NextForComplex(n)) {
390     if (!stepstrcmp (RecordType(n).ToCString(),name))  {
391       num = n;
392       errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order");
393       sprintf (txtmes,errmess->ToCString(),num0,name);
394       ach->AddWarning(txtmes,errmess->ToCString());
395       return Standard_False;
396     }
397   }
398   num = 0;
399   errmess = new String("Complex Record n0.%d, member type %s not found");
400   sprintf (txtmes,errmess->ToCString(),num0,name);
401   ach->AddFail (txtmes,errmess->ToCString());
402   return Standard_False;
403 }
404
405 //  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
406
407
408 //=======================================================================
409 //function : CheckNbParams
410 //purpose  : 
411 //=======================================================================
412
413 Standard_Boolean StepData_StepReaderData::CheckNbParams(const Standard_Integer num,
414                                                         const Standard_Integer nbreq,
415                                                         Handle(Interface_Check)& ach,
416                                                         const Standard_CString mess) const
417 {
418   if (NbParams(num) == nbreq) return Standard_True;
419   Handle(String) errmess;
420   if (mess[0] == '\0') errmess = new String("Count of Parameters is not %d");
421   else errmess = new String("Count of Parameters is not %d for %s");
422   sprintf (txtmes,errmess->ToCString(),nbreq,mess);
423   ach->AddFail (txtmes,errmess->ToCString());
424   return Standard_False;
425 }
426
427
428 //=======================================================================
429 //function : ReadSubList
430 //purpose  : 
431 //=======================================================================
432
433 Standard_Boolean StepData_StepReaderData::ReadSubList(const Standard_Integer num,
434                                                       const Standard_Integer nump,
435                                                       const Standard_CString mess,
436                                                       Handle(Interface_Check)& ach,
437                                                       Standard_Integer& numsub,
438                                                       const Standard_Boolean optional,
439                                                       const Standard_Integer /* lenmin */,
440                                                       const Standard_Integer /* lenmax */) const
441 {
442   numsub = SubListNumber (num,nump,Standard_False);
443   if (numsub > 0) return Standard_True;
444 //  Si optionel indefini, on passe l eponge
445   numsub = 0;
446   Standard_Boolean isvoid = (Param(num,nump).ParamType() == Interface_ParamVoid);
447   if (isvoid && optional) return Standard_False;
448
449   Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
450   sprintf (txtmes,errmess->ToCString(),nump,mess);
451   if (acceptvoid && isvoid)  ach->AddWarning(txtmes,errmess->ToCString());
452   else  {  ach->AddFail(txtmes,errmess->ToCString()); return Standard_False;  }
453   return Standard_True;
454 }
455
456
457 //  ...   Facilites pour LateBinding
458
459
460 //=======================================================================
461 //function : ReadSub
462 //purpose  : 
463 //=======================================================================
464
465 Standard_Integer StepData_StepReaderData::ReadSub(const Standard_Integer numsub,
466                                                   const Standard_CString mess,
467                                                   Handle(Interface_Check)& ach,
468                                                   const Handle(StepData_PDescr)& descr,
469                                                   Handle(Standard_Transient)& val) const
470 {
471   Standard_Integer nbp = NbParams(numsub);
472   if (nbp == 0) return 0;    // liste vide = Handle Null
473   const TCollection_AsciiString& rectyp = RecordType (numsub);
474   if (nbp == 1 && rectyp.ToCString()[0] != '(') {
475     //  c est un type avec un parametre -> SelectNamed
476     //  cf ReadSelect mais ici, on est deja sur le contenu du parametre
477     Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
478     val = sn;
479     sn->SetName (rectyp.ToCString());
480     if (ReadAny (numsub,1,mess,ach,descr,sn)) return sn->Kind();
481     else return 0;
482   }
483
484   //  cas courant : faire un HArray1 de ... de ... de quoi au fait
485   const Interface_FileParameter& FP0 = Param(numsub,1);
486   Interface_ParamType FT, FT0 = FP0.ParamType();
487   Standard_CString str = FP0.CValue();
488   Handle(TColStd_HArray1OfTransient) htr;
489   Handle(TColStd_HArray1OfInteger)   hin;
490   Handle(TColStd_HArray1OfReal)      hre;
491   Handle(Interface_HArray1OfHAsciiString)  hst;
492   Standard_Integer kod = 0;
493   switch (FT0) {
494     case Interface_ParamMisc    : return -1;
495     case Interface_ParamInteger : kod = 1;  break;
496     case Interface_ParamReal    : kod = 5;  break;
497     case Interface_ParamIdent   : kod = 7;  break;
498     case Interface_ParamVoid    : kod = 0;  break;
499     case Interface_ParamText    : kod = 6;  break;
500     case Interface_ParamEnum    : kod = 4;  break;  // a confirmer(logical)
501       /*      kod = 4;
502               if ( str[0] == '.' && str[2] == '.' && str[3] == '\0' &&
503               (str[1] == 'T' || str[1] == 'F' || str[1] == 'U') ) kod = 3;
504               break; */ // svv #2
505     case Interface_ParamLogical : return -1;
506     case Interface_ParamSub     : kod = 0;  break;
507     case Interface_ParamHexa    : return -1;
508     case Interface_ParamBinary  : return -1;
509     default :  return -1;
510   }
511   if (kod == 1 || kod == 3) { hin = new TColStd_HArray1OfInteger (1,nbp); val = hin; }
512   else if (kod == 5) { hre = new TColStd_HArray1OfReal   (1,nbp); val = hre; }
513   else if (kod == 6) { hst = new Interface_HArray1OfHAsciiString (1,nbp); val = hst; }
514   else            { htr = new TColStd_HArray1OfTransient (1,nbp); val = htr; }
515 //  Attention : si type variable, faudra changer son fusil d epaule -> htr
516
517   for (Standard_Integer ip = 1; ip <= nbp; ip ++) {
518     const Interface_FileParameter& FP = Param(numsub,ip);
519     str = FP.CValue();
520     FT  = FP.ParamType();
521     switch (kod) {
522       case 1 : {
523         if (FT != Interface_ParamInteger) { kod = 0; break; }
524         hin->SetValue (ip,atoi(str));   break;
525       }
526       case 2 :
527       case 3 : {
528         if (FT != Interface_ParamEnum)    { kod = 0; break; }
529         if      (!strcmp(str,".F.")) hin->SetValue (ip,0);
530         else if (!strcmp(str,".T.")) hin->SetValue (ip,1);
531         else if (!strcmp(str,".U.")) hin->SetValue (ip,2);
532         else    kod = 0;
533         break;
534       }
535       case 4 : {
536         if (FT != Interface_ParamEnum)    { kod = 0; break; }
537         Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
538         sn->SetEnum (-1,str);
539         htr->SetValue (ip,sn);  break;
540       }
541       case 5 : {
542         if (FT != Interface_ParamReal)    { kod = 0; break; }
543         hre->SetValue (ip,Interface_FileReaderData::Fastof(str));   break;
544       }
545       case 6 : {
546         if (FT != Interface_ParamText)    { kod = 0; break; }
547         Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
548         CleanText (txt);  hst->SetValue (ip,txt);  break;
549       }
550       case 7 : {
551         Handle(Standard_Transient) ent = BoundEntity (FP.EntityNumber());
552         htr->SetValue (ip,ent);  break;
553       }
554       default : break;
555     }
556 //    Restent les autres cas ... tout est possible. cf le type du Param
557     if (kod > 0) continue;
558 //    Il faut passer au transient ...
559     if (htr.IsNull()) {
560       htr = new TColStd_HArray1OfTransient (1,nbp);  val = htr;
561       Standard_Integer jp;      
562       if (!hin.IsNull()) {
563         for (jp = 1; jp < ip; jp ++) {
564           Handle(StepData_SelectInt) sin = new StepData_SelectInt;
565           sin->SetInt (hin->Value(jp));
566           htr->SetValue (jp,sin);
567         }
568       }
569       if (!hre.IsNull()) {
570         for (jp = 1; jp < ip; jp ++) {
571           Handle(StepData_SelectReal) sre = new StepData_SelectReal;
572           sre->SetReal (hre->Value(jp));
573           htr->SetValue (jp,sre);
574         }
575       }
576       if (!hst.IsNull()) {
577         for (jp = 1; jp < ip; jp ++) {
578           htr->SetValue (jp,hst->Value(jp));
579         }
580       }
581     }
582 //    A present, faut y aller : lire le champ et le mettre en place
583 //    Ce qui suit ressemble fortement a ReadAny ...
584
585     switch (FT) {
586     case Interface_ParamMisc : break;
587     case Interface_ParamInteger : {
588       Handle(StepData_SelectInt) sin = new StepData_SelectInt;
589       sin->SetInteger (atoi(str));
590       htr->SetValue (ip,sin); break;
591     }
592     case Interface_ParamReal : {
593       Handle(StepData_SelectReal) sre = new StepData_SelectReal;
594       sre->SetReal (Interface_FileReaderData::Fastof(str));   break;
595       //htr->SetValue (ip,sre); break; svv #2: unreachable
596     }
597     case Interface_ParamIdent : htr->SetValue (ip,BoundEntity (FP.EntityNumber()));  break;
598     case Interface_ParamVoid : break;
599     case Interface_ParamEnum : {
600       Handle(StepData_SelectInt)   sin;
601       Handle(StepData_SelectNamed) sna;
602       Standard_Integer logic = -1;
603 // PTV 16.09.2000
604 // set the default value of StepData_Logical
605       StepData_Logical slog = StepData_LUnknown;
606       if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') {
607         if (str[1] == 'F')       {  slog = StepData_LFalse;    logic = 0;  }
608         else if (str[1] == 'T')  {  slog = StepData_LTrue;     logic = 1;  }
609         else if (str[1] == 'U')  {  slog = StepData_LUnknown;  logic = 2;  }
610       }
611       if (logic >= 0)
612         { sin = new StepData_SelectInt; sin->SetLogical(slog); htr->SetValue(ip,sin); }
613       else { sna = new StepData_SelectNamed;
614              sna->SetEnum (logic,str); htr->SetValue (ip,sna);  }
615       break;
616     }
617     case Interface_ParamLogical : break;
618     case Interface_ParamText : {
619       Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
620       CleanText (txt);  htr->SetValue (ip,txt);  break;
621     }
622     case Interface_ParamSub  : {
623       Handle(Standard_Transient) sub;
624       Standard_Integer nent = FP.EntityNumber();
625       Standard_Integer kind = ReadSub (nent,mess,ach,descr,sub);   if (kind < 0) break;
626       htr->SetValue(ip,sub);  break;
627     }
628     case Interface_ParamHexa : break;
629     case Interface_ParamBinary  : break;
630     default                  : break;
631     }
632     return -1;
633   }
634   return 8;  // pour Any
635 }
636
637
638 //=======================================================================
639 //function : ReadMember
640 //purpose  : 
641 //=======================================================================
642
643 Standard_Boolean StepData_StepReaderData::ReadMember(const Standard_Integer num,
644                                                      const Standard_Integer nump,
645                                                      const Standard_CString mess,
646                                                      Handle(Interface_Check)& ach,
647                                                      Handle(StepData_SelectMember)& val) const
648 {
649   Handle(Standard_Transient) v = val;
650   Handle(StepData_PDescr) nuldescr;
651   if (v.IsNull()) return ReadAny (num,nump,mess,ach,nuldescr,val);
652   Standard_Boolean res = ReadAny (num,nump,mess,ach,nuldescr,v);
653   if (v == val) return res;
654   //   changement -> refus
655   Handle(String) errmess =
656     new String("Parameter n0.%d (%s) : does not match SELECT clause");
657   sprintf (txtmes,errmess->ToCString(),nump,mess);
658   ach->AddFail(txtmes,errmess->ToCString());
659   return Standard_False;
660 }
661
662
663 //=======================================================================
664 //function : ReadField
665 //purpose  : 
666 //=======================================================================
667
668 Standard_Boolean StepData_StepReaderData::ReadField(const Standard_Integer num,
669                                                     const Standard_Integer nump,
670                                                     const Standard_CString mess,
671                                                     Handle(Interface_Check)& ach,
672                                                     const Handle(StepData_PDescr)& descr,
673                                                     StepData_Field& fild) const
674 {
675   const Interface_FileParameter& FP = Param(num,nump);
676   Standard_CString str = FP.CValue();
677   Standard_Boolean OK = Standard_True;
678   Standard_Integer nent, kind;
679   Handle(TCollection_HAsciiString) txt;
680   Handle(Standard_Transient) sub;
681   Interface_ParamType FT = FP.ParamType();
682   switch (FT) {
683     case Interface_ParamMisc    : OK = Standard_False;  break;
684     case Interface_ParamInteger : fild.SetInteger (atoi(str)); break;
685     case Interface_ParamReal    :
686       fild.SetReal (Interface_FileReaderData::Fastof(str));   break;
687     case Interface_ParamIdent   :
688       nent = FP.EntityNumber();
689       if (nent > 0) fild.SetEntity (BoundEntity(nent));
690       break;
691     case Interface_ParamVoid    :  break;
692     case Interface_ParamText    :
693       txt = new TCollection_HAsciiString(str);
694       CleanText (txt);  fild.Set (txt);  break;
695     case Interface_ParamEnum    :
696       if      (!strcmp(str,".T.")) fild.SetLogical (StepData_LTrue);
697       else if (!strcmp(str,".F.")) fild.SetLogical (StepData_LFalse);
698       else if (!strcmp(str,".U.")) fild.SetLogical (StepData_LUnknown);
699       else    fild.SetEnum (-1,str);
700       break;
701     case Interface_ParamLogical : OK = Standard_False;  break;
702     case Interface_ParamSub     :
703       nent = FP.EntityNumber();
704       kind = ReadSub (nent,mess,ach,descr,sub);   if (kind < 0) break;
705       fild.Clear(kind);  fild.Set (sub);      break;
706     case Interface_ParamHexa    : OK = Standard_False;  break;
707     case Interface_ParamBinary  : OK = Standard_False;  break;
708     default :  OK = Standard_False;  break;
709   }
710
711   if (!OK) {
712     if (!strcmp(str,"*")) fild.SetDerived();
713   }
714   return Standard_True;
715 }
716
717
718 //=======================================================================
719 //function : ReadList
720 //purpose  : 
721 //=======================================================================
722
723 Standard_Boolean StepData_StepReaderData::ReadList(const Standard_Integer num,
724                                                    Handle(Interface_Check)& ach,
725                                                    const Handle(StepData_ESDescr)& descr,
726                                                    StepData_FieldList& list) const
727 {
728   // controler nbs egaux
729   Standard_Integer i,nb = list.NbFields();
730   if (!CheckNbParams (num,nb,ach,descr->TypeName())) return Standard_False;
731   for (i = 1; i <= nb; i ++) {
732     Handle(StepData_PDescr) pde = descr->Field(i);
733     StepData_Field& fild = list.CField(i);
734     ReadField (num,i,pde->Name(),ach,pde,fild);
735   }
736   return Standard_True;
737 }
738
739
740 //=======================================================================
741 //function : ReadAny
742 //purpose  : 
743 //=======================================================================
744
745 Standard_Boolean StepData_StepReaderData::ReadAny(const Standard_Integer num,
746                                                   const Standard_Integer nump,
747                                                   const Standard_CString mess,
748                                                   Handle(Interface_Check)& ach,
749                                                   const Handle(StepData_PDescr)& descr,
750                                                   Handle(Standard_Transient)& val) const
751 {
752   const Interface_FileParameter& FP = Param(num,nump);
753   Standard_CString    str = FP.CValue();
754   Interface_ParamType FT  = FP.ParamType();
755
756 //    A present, faut y aller : lire le champ et le mettre en place
757   switch (FT) {
758     case Interface_ParamMisc : break;
759     case Interface_ParamInteger : {
760       if (!val.IsNull()) {
761         DeclareAndCast(StepData_SelectMember,sm,val);
762         sm->SetInteger(atoi(str));
763         return Standard_True;
764       }
765       Handle(StepData_SelectInt) sin = new StepData_SelectInt;
766       sin->SetInteger (atoi(str));
767       val = sin;
768       return Standard_True;
769     }
770     case Interface_ParamReal : {
771       if (!val.IsNull()) {
772         DeclareAndCast(StepData_SelectMember,sm,val);
773         sm->SetReal (Interface_FileReaderData::Fastof(str));
774         return Standard_True;
775       }
776       Handle(StepData_SelectReal) sre = new StepData_SelectReal;
777       sre->SetReal (Interface_FileReaderData::Fastof(str));
778       val = sre;
779       return Standard_True;
780     }
781     case Interface_ParamIdent   : {
782       Standard_Integer nent = FP.EntityNumber();
783       if (nent > 0) val = BoundEntity(nent);
784       return (!val.IsNull());
785     }
786     case Interface_ParamVoid  : break;
787     case Interface_ParamEnum : {
788       Handle(StepData_SelectMember) sm;
789       if (!val.IsNull())  sm = GetCasted(StepData_SelectMember,val);
790       Handle(StepData_SelectInt)   sin;
791       Handle(StepData_SelectNamed) sna;
792       Standard_Integer logic = -1;
793
794       // PTV 16.09.2000
795       // set the default value of StepData_Logical
796       StepData_Logical slog = StepData_LUnknown;
797       if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') {
798         if (str[1] == 'F')       {  slog = StepData_LFalse;    logic = 0;  }
799         else if (str[1] == 'T')  {  slog = StepData_LTrue;     logic = 1;  }
800         else if (str[1] == 'U')  {  slog = StepData_LUnknown;  logic = 2;  }
801       }
802       if (logic >= 0)  {
803         if (!sm.IsNull()) sm->SetLogical(slog);
804         else {
805           sin = new StepData_SelectInt; val = sin;
806           sin->SetLogical(slog);
807         }
808       }
809       else {
810         if (!sm.IsNull()) sm->SetEnum (logic,str);
811         else {
812           sna = new StepData_SelectNamed;  val = sna;  // Named sans nom...
813           sna->SetEnum (logic,str);
814         }
815       }        // -> Select general
816       return Standard_True;
817     }
818     case Interface_ParamLogical : break;
819     case Interface_ParamText : {
820       Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
821       CleanText (txt);
822
823       // PDN May 2000: for reading SOURCE_ITEM (external references)
824       if (!val.IsNull()) {
825         DeclareAndCast(StepData_SelectMember,sm,val);
826         sm->SetString (txt->ToCString());
827         return Standard_True;
828       }
829       
830       val = txt;
831       return Standard_True;
832     }
833     case Interface_ParamSub     : {
834       Standard_Integer numsub = SubListNumber (num,nump,Standard_False);
835       Standard_Integer nbp = NbParams(numsub);
836       if (nbp == 0) return Standard_False;    // liste vide = Handle Null
837       const TCollection_AsciiString& rectyp = RecordType (numsub);
838       if (nbp == 1 && rectyp.ToCString()[0] != '(') {
839         //  SelectNamed because Field !!!
840         // skl 15.01.2003 (for members with array of real)
841         DeclareAndCast(StepData_SelectArrReal,sma,val);
842         if(!sma.IsNull()) {
843           Standard_Integer numsub2 = SubListNumber (numsub,1,Standard_False);
844           Standard_Integer nbp2 = NbParams(numsub2);
845           if(nbp2>1) {
846             if( Param(numsub2,1).ParamType() == Interface_ParamReal ) {
847               if (!sma->SetName (rectyp.ToCString())) return Standard_False;
848               Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal;
849               for(Standard_Integer i=1; i<=nbp2; i++) {
850                 if( Param(numsub2,i).ParamType() != Interface_ParamReal ) continue;
851                 Handle(StepData_SelectReal) sm1 = new StepData_SelectReal;
852                 if( !ReadAny(numsub2,i,mess,ach,descr,sm1) ) continue;
853                 aSeq->Append(sm1->Real());
854               }
855               Handle(TColStd_HArray1OfReal) anArr = new TColStd_HArray1OfReal(1,aSeq->Length());
856               for(Standard_Integer nr=1; nr<=aSeq->Length(); nr++) {
857                 anArr->SetValue(nr,aSeq->Value(nr));
858               }
859               sma->SetArrReal(anArr);
860               return Standard_True;
861             }
862           }
863         }
864         DeclareAndCast(StepData_SelectMember,sm,val);
865         if (sm.IsNull()) {
866           sm = new StepData_SelectNamed;
867           val = sm;
868         }
869         if (!sm->SetName (rectyp.ToCString())) return Standard_False;  // loupe
870         return ReadAny (numsub,1,mess,ach,descr,val);
871       }
872     }
873     default                  : break;
874   }
875   return Standard_False;
876 }
877
878
879 //  ....
880
881
882 //=======================================================================
883 //function : ReadXY
884 //purpose  : 
885 //=======================================================================
886
887 Standard_Boolean StepData_StepReaderData::ReadXY(const Standard_Integer num,
888                                                  const Standard_Integer nump,
889                                                  const Standard_CString mess,
890                                                  Handle(Interface_Check)& ach,
891                                                  Standard_Real& X, Standard_Real& Y) const
892 {
893   Handle(String) errmess;  // Null si pas d erreur
894   Standard_Integer numsub = SubListNumber(num,nump,Standard_False);
895   if (numsub != 0) {
896     if (NbParams(numsub) == 2) {
897       const Interface_FileParameter& FPX = Param(numsub,1);
898       if (FPX.ParamType() == Interface_ParamReal)  X =
899         Interface_FileReaderData::Fastof(FPX.CValue());
900       else errmess = new String("Parameter n0.%d (%s) : (X,Y) X not a Real");
901
902       const Interface_FileParameter& FPY = Param(numsub,2);
903       if (FPY.ParamType() == Interface_ParamReal)  Y = 
904         Interface_FileReaderData::Fastof( FPY.CValue());
905       else errmess = new String("Parameter n0.%d (%s) : (X,Y) Y not a Real");
906
907     }
908     else errmess = new String("Parameter n0.%d (%s) : (X,Y) has not 2 params");
909   }
910   else errmess = new String("Parameter n0.%d (%s) : (X,Y) not a SubList");
911
912   if (errmess.IsNull()) return Standard_True;
913   sprintf (txtmes,errmess->ToCString(),nump,mess);
914   ach->AddFail(txtmes,errmess->ToCString());
915   return Standard_False;
916 }
917
918
919 //=======================================================================
920 //function : ReadXYZ
921 //purpose  : 
922 //=======================================================================
923
924 Standard_Boolean StepData_StepReaderData::ReadXYZ(const Standard_Integer num,
925                                                   const Standard_Integer nump,
926                                                   const Standard_CString mess,
927                                                   Handle(Interface_Check)& ach,
928                                                   Standard_Real& X, Standard_Real& Y,
929                                                   Standard_Real& Z) const
930 {
931   Handle(String) errmess;  // Null si pas d erreur
932   Standard_Integer numsub = SubListNumber(num,nump,Standard_False);
933   if (numsub != 0) {
934     if (NbParams(numsub) == 3) {
935       const Interface_FileParameter& FPX = Param(numsub,1);
936       if (FPX.ParamType() == Interface_ParamReal)  X =
937         Interface_FileReaderData::Fastof(FPX.CValue());
938       else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) X not a Real");
939
940       const Interface_FileParameter& FPY = Param(numsub,2);
941       if (FPY.ParamType() == Interface_ParamReal)  Y =
942         Interface_FileReaderData::Fastof(FPY.CValue());
943       else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Y not a Real");
944
945       const Interface_FileParameter& FPZ = Param(numsub,3);
946       if (FPZ.ParamType() == Interface_ParamReal)  Z =
947         Interface_FileReaderData::Fastof(FPZ.CValue());
948       else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Z not a Real");
949
950     }
951     else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) has not 3 params");
952   }
953   else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) not a SubList");
954
955   if (errmess.IsNull()) return Standard_True;
956   sprintf (txtmes,errmess->ToCString(),nump,mess);
957   ach->AddFail(txtmes,errmess->ToCString());
958   return Standard_False;
959 }
960
961
962 //=======================================================================
963 //function : ReadReal
964 //purpose  : 
965 //=======================================================================
966
967 Standard_Boolean StepData_StepReaderData::ReadReal(const Standard_Integer num,
968                                                    const Standard_Integer nump,
969                                                    const Standard_CString mess,
970                                                    Handle(Interface_Check)& ach,
971                                                    Standard_Real& val) const
972 {
973   Handle(String) errmess;  // Null si pas d erreur
974   if (nump > 0 && nump <= NbParams(num)) {
975     const Interface_FileParameter& FP = Param(num,nump);
976     if (FP.ParamType() == Interface_ParamReal)  val =
977       Interface_FileReaderData::Fastof(FP.CValue());
978     else errmess = new String("Parameter n0.%d (%s) not a Real");
979   }
980   else errmess = new String("Parameter n0.%d (%s) absent");
981
982   if (errmess.IsNull()) return Standard_True;
983   sprintf (txtmes,errmess->ToCString(),nump,mess);
984   ach->AddFail(txtmes,errmess->ToCString());
985   return Standard_False;
986 }
987
988
989 //  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
990
991
992 //=======================================================================
993 //function : ReadEntity
994 //purpose  : 
995 //=======================================================================
996
997 Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
998                                                      const Standard_Integer nump,
999                                                      const Standard_CString mess,
1000                                                      Handle(Interface_Check)& ach,
1001                                                      const Handle(Standard_Type)& atype,
1002                                                      Handle(Standard_Transient)& ent) const
1003 {
1004   Handle(String) errmess;  // Null si pas d erreur
1005   Standard_Boolean warn = Standard_False;
1006   if (nump > 0 && nump <= NbParams(num)) {
1007     const Interface_FileParameter& FP = Param(num,nump);
1008     Standard_Integer nent = FP.EntityNumber();
1009     if (FP.ParamType() == Interface_ParamIdent) {
1010       warn = (acceptvoid > 0);
1011       if (nent > 0) {
1012         Handle(Standard_Transient) entent = BoundEntity(nent);
1013         if (entent.IsNull() || !entent->IsKind(atype))
1014           errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
1015         else ent = entent;
1016       }
1017       else errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
1018     }
1019     else {
1020       if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True;
1021       errmess = new String("Parameter n0.%d (%s) not an Entity");
1022     }
1023   }
1024   else {
1025     warn = (acceptvoid > 0);
1026     errmess = new String("Parameter n0.%d (%s) absent");
1027   }
1028
1029   if (errmess.IsNull()) return Standard_True;
1030   sprintf (txtmes,errmess->ToCString(),nump,mess);
1031   if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1032   else ach->AddFail(txtmes,errmess->ToCString());
1033   return Standard_False;
1034 }
1035
1036
1037 //=======================================================================
1038 //function : ReadEntity
1039 //purpose  : 
1040 //=======================================================================
1041
1042 Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
1043                                                      const Standard_Integer nump,
1044                                                      const Standard_CString mess,
1045                                                      Handle(Interface_Check)& ach,
1046                                                      StepData_SelectType& sel) const
1047 {
1048   Handle(String) errmess;  // Null si pas d erreur
1049   Standard_Boolean warn = Standard_False;
1050   if (nump > 0 && nump <= NbParams(num)) {
1051     const Interface_FileParameter& FP = Param(num,nump);
1052     Standard_Integer nent = FP.EntityNumber();
1053     if (FP.ParamType() == Interface_ParamIdent) {
1054       warn = (acceptvoid > 0);
1055       if (nent > 0) {
1056         Handle(Standard_Transient) entent = BoundEntity(nent);
1057         if (!sel.Matches(entent))
1058           errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
1059         else
1060           sel.SetValue(entent);
1061       }
1062       else
1063         errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
1064     }
1065     else if (FP.ParamType() == Interface_ParamVoid) {
1066       if (acceptvoid) warn = Standard_True;
1067       errmess = new String("Parameter n0.%d (%s) not an Entity");
1068     }
1069     else {
1070       // Cas restant : on s interesse en fait au SelectMember ...
1071       Handle(Standard_Transient) sm = sel.NewMember();
1072       // SelectMember qui assure ce role. Peut etre specialise
1073       if (!ReadAny (num,nump,mess,ach,sel.Description(),sm))
1074         errmess = new String("Parameter n0.%d (%s) : could not be read");
1075       if (!sel.Matches(sm))
1076         errmess = new String("Parameter n0.%d (%s) : illegal parameter type");
1077       else
1078         sel.SetValue(sm);
1079     }
1080   }
1081   else {
1082     warn = (acceptvoid > 0);
1083     errmess = new String("Parameter n0.%d (%s) absent");
1084   }
1085
1086   if (errmess.IsNull()) return Standard_True;
1087   sprintf (txtmes,errmess->ToCString(),nump,mess);
1088   if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1089   else ach->AddFail(txtmes,errmess->ToCString());
1090   return Standard_False;
1091 }
1092
1093
1094 //  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
1095
1096
1097 //=======================================================================
1098 //function : ReadInteger
1099 //purpose  : 
1100 //=======================================================================
1101
1102 Standard_Boolean StepData_StepReaderData::ReadInteger(const Standard_Integer num,
1103                                                       const Standard_Integer nump,
1104                                                       const Standard_CString mess,
1105                                                       Handle(Interface_Check)& ach,
1106                                                       Standard_Integer& val) const
1107 {
1108   Handle(String) errmess;  // Null si pas d erreur
1109   if (nump > 0 && nump <= NbParams(num)) {
1110     const Interface_FileParameter& FP = Param(num,nump);
1111     if (FP.ParamType() == Interface_ParamInteger)  val = atoi(FP.CValue());
1112     else errmess = new String("Parameter n0.%d (%s) not an Integer");
1113   }
1114   else errmess = new String("Parameter n0.%d (%s) absent");
1115
1116   if (errmess.IsNull()) return Standard_True;
1117   sprintf (txtmes,errmess->ToCString(),nump,mess);
1118   ach->AddFail(txtmes,errmess->ToCString());
1119   return Standard_False;
1120 }
1121
1122
1123 //=======================================================================
1124 //function : ReadBoolean
1125 //purpose  : 
1126 //=======================================================================
1127
1128 Standard_Boolean StepData_StepReaderData::ReadBoolean(const Standard_Integer num,
1129                                                       const Standard_Integer nump,
1130                                                       const Standard_CString mess,
1131                                                       Handle(Interface_Check)& ach,
1132                                                       Standard_Boolean& flag) const
1133 {
1134   Handle(String) errmess;  // Null si pas d erreur
1135   if (nump > 0 && nump <= NbParams(num)) {
1136     const Interface_FileParameter& FP = Param(num,nump);
1137     if (FP.ParamType() == Interface_ParamEnum) {
1138       Standard_CString txt = FP.CValue();
1139       if      (!strcmp(txt,".T.")) flag = Standard_True;
1140       else if (!strcmp(txt,".F.")) flag = Standard_False;
1141       else errmess = new String("Parameter n0.%d (%s) : Incorrect Boolean Value");
1142     }
1143     else errmess = new String("Parameter n0.%d (%s) not a Boolean");
1144   }
1145   else errmess = new String("Parameter n0.%d (%s) absent");
1146
1147   if (errmess.IsNull()) return Standard_True;
1148   sprintf (txtmes,errmess->ToCString(),nump,mess);
1149   ach->AddFail(txtmes,errmess->ToCString());
1150   return Standard_False;
1151 }
1152
1153
1154 //=======================================================================
1155 //function : ReadLogical
1156 //purpose  : 
1157 //=======================================================================
1158
1159 Standard_Boolean StepData_StepReaderData::ReadLogical(const Standard_Integer num,
1160                                                       const Standard_Integer nump,
1161                                                       const Standard_CString mess,
1162                                                       Handle(Interface_Check)& ach,
1163                                                       StepData_Logical& flag) const
1164 {
1165   Handle(String) errmess;  // Null si pas d erreur
1166   if (nump > 0 && nump <= NbParams(num)) {
1167     const Interface_FileParameter& FP = Param(num,nump);
1168     if (FP.ParamType() == Interface_ParamEnum) {
1169       Standard_CString txt = FP.CValue();
1170       if      (!strcmp(txt,".T.")) flag = StepData_LTrue;
1171       else if (!strcmp(txt,".F.")) flag = StepData_LFalse;
1172       else if (!strcmp(txt,".U.")) flag = StepData_LUnknown;
1173       else errmess = new String("Parameter n0.%d (%s) : Incorrect Logical Value");
1174     }
1175     else errmess = new String("Parameter n0.%d (%s) not a Logical");
1176   }
1177   else errmess = new String("Parameter n0.%d (%s) absent");
1178
1179   if (errmess.IsNull()) return Standard_True;
1180   sprintf (txtmes,errmess->ToCString(),nump,mess);
1181   ach->AddFail(txtmes,errmess->ToCString());
1182   return Standard_False;
1183 }
1184
1185
1186 //=======================================================================
1187 //function : ReadString
1188 //purpose  : 
1189 //=======================================================================
1190
1191 Standard_Boolean StepData_StepReaderData::ReadString(const Standard_Integer num,
1192                                                      const Standard_Integer nump,
1193                                                      const Standard_CString mess,
1194                                                      Handle(Interface_Check)& ach,
1195                                                      Handle(TCollection_HAsciiString)& val) const
1196 {
1197   Handle(String) errmess;  // Null si pas d erreur
1198   Standard_Boolean warn = Standard_False;
1199   if (nump > 0 && nump <= NbParams(num)) {
1200     const Interface_FileParameter& FP = Param(num,nump);
1201     if (FP.ParamType() == Interface_ParamText) {
1202       /*Standard_CString anStr = FP.CValue();
1203       if(strlen(anStr) < 3)
1204         val = new TCollection_HAsciiString("");
1205       else {
1206         val = new TCollection_HAsciiString(FP.CValue());
1207         CleanText (val);
1208       }*/
1209       val = new TCollection_HAsciiString(FP.CValue());
1210       CleanText (val);
1211     } else {
1212       if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True;
1213       errmess = new String("Parameter n0.%d (%s) not a quoted String");
1214     }
1215   }
1216   else errmess = new String("Parameter n0.%d (%s) absent");
1217
1218   if (errmess.IsNull()) return Standard_True;
1219   sprintf (txtmes,errmess->ToCString(),nump,mess);
1220   if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1221   else ach->AddFail(txtmes,errmess->ToCString());
1222   return Standard_False;
1223 }
1224
1225
1226 //=======================================================================
1227 //function : ReadEnumParam
1228 //purpose  : 
1229 //=======================================================================
1230
1231 Standard_Boolean StepData_StepReaderData::ReadEnumParam(const Standard_Integer num,
1232                                                         const Standard_Integer nump,
1233                                                         const Standard_CString mess,
1234                                                         Handle(Interface_Check)& ach,
1235                                                         Standard_CString& text) const
1236 {
1237   Handle(String) errmess;  // Null si pas d erreur
1238   Standard_Boolean warn = Standard_False;
1239   if (nump > 0 && nump <= NbParams(num)) {
1240     const Interface_FileParameter& FP = Param(num,nump);
1241     if (FP.ParamType() == Interface_ParamEnum) {
1242       text = FP.CValue();
1243       warn = (acceptvoid > 0);
1244     } else if (FP.ParamType() == Interface_ParamVoid) {
1245       errmess =
1246         new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
1247       warn = (acceptvoid > 0);
1248     }
1249     else errmess = new String("Parameter n0.%d (%s) not an Enumeration");
1250   }
1251   else errmess = new String("Parameter n0.%d (%s) absent");
1252
1253   if (errmess.IsNull()) return Standard_True;
1254   sprintf (txtmes,errmess->ToCString(),nump,mess);
1255   if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1256   else ach->AddFail(txtmes,errmess->ToCString());
1257   return Standard_False;
1258 }
1259
1260
1261 //=======================================================================
1262 //function : FailEnumValue
1263 //purpose  : 
1264 //=======================================================================
1265
1266 void  StepData_StepReaderData::FailEnumValue(const Standard_Integer /* num */,
1267                                              const Standard_Integer nump,
1268                                              const Standard_CString mess,
1269                                              Handle(Interface_Check)& ach) const
1270 {
1271   Handle(String) errmess =
1272     new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
1273   sprintf (txtmes,errmess->ToCString(),nump,mess);
1274   ach->AddFail(txtmes,errmess->ToCString());
1275 }
1276
1277
1278 //=======================================================================
1279 //function : ReadEnum
1280 //purpose  : 
1281 //=======================================================================
1282
1283 Standard_Boolean StepData_StepReaderData::ReadEnum(const Standard_Integer num,
1284                                                    const Standard_Integer nump,
1285                                                    const Standard_CString mess,
1286                                                    Handle(Interface_Check)& ach,
1287                                                    const StepData_EnumTool& enumtool,
1288                                                    Standard_Integer& val) const
1289 {
1290 //  reprendre avec ReadEnumParam ?
1291   Handle(String) errmess;  // Null si pas d erreur
1292   Standard_Boolean warn = Standard_False;
1293   if (nump > 0 && nump <= NbParams(num)) {
1294     const Interface_FileParameter& FP = Param(num,nump);
1295     if (FP.ParamType() == Interface_ParamEnum) {
1296       val = enumtool.Value (FP.CValue());
1297       if (val >= 0) return Standard_True;
1298       else errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
1299       warn = (acceptvoid > 0);
1300     }
1301     else if (FP.ParamType() == Interface_ParamVoid) {
1302       val = enumtool.NullValue();
1303       if (val < 0) errmess =
1304         new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
1305       warn = (acceptvoid > 0);
1306     }
1307     else errmess = new String("Parameter n0.%d (%s) not an Enumeration");
1308   }
1309   else errmess = new String("Parameter n0.%d (%s) absent");
1310
1311   if (errmess.IsNull()) return Standard_True;
1312   sprintf (txtmes,errmess->ToCString(),nump,mess);
1313   if (warn)
1314     ach->AddWarning(txtmes,errmess->ToCString());
1315   else 
1316     ach->AddFail(txtmes,errmess->ToCString());
1317   return Standard_False;
1318 }
1319
1320
1321 //=======================================================================
1322 //function : ReadTypedParam
1323 //purpose  : 
1324 //=======================================================================
1325
1326 Standard_Boolean StepData_StepReaderData::ReadTypedParam(const Standard_Integer num,
1327                                                          const Standard_Integer nump,
1328                                                          const Standard_Boolean mustbetyped,
1329                                                          const Standard_CString mess,
1330                                                          Handle(Interface_Check)& ach,
1331                                                          Standard_Integer& numr,
1332                                                          Standard_Integer& numrp,
1333                                                          TCollection_AsciiString& typ) const
1334 {
1335   Handle(String) errmess;  // Null si pas d erreur
1336   if (nump > 0 && nump <= NbParams(num)) {
1337     const Interface_FileParameter& FP = Param(num,nump);
1338     if (FP.ParamType() != Interface_ParamSub) {
1339       //    Pas une sous-liste : OK si admis
1340       numr = num;  numrp = nump;  typ.Clear();
1341       if (mustbetyped) {
1342         errmess = new String("Parameter n0.%d (%s) : single, not typed");
1343         sprintf (txtmes,errmess->ToCString(),nump,mess);
1344         ach->AddFail(txtmes,errmess->ToCString());
1345         return Standard_False;
1346       }
1347       return Standard_True;
1348     }
1349     numr = FP.EntityNumber();  numrp = 1;
1350     if (NbParams(numr) != 1) errmess =
1351       new String("Parameter n0.%d (%s) : SubList, not typed");
1352     typ = RecordType(numr);
1353   }
1354   else errmess = new String("Parameter n0.%d (%s) absent");
1355
1356   if (errmess.IsNull()) return Standard_True;
1357   sprintf (txtmes,errmess->ToCString(),nump,mess);
1358   ach->AddFail(txtmes,errmess->ToCString());
1359   return Standard_False;
1360 }
1361
1362
1363 //=======================================================================
1364 //function : CheckDerived
1365 //purpose  : 
1366 //=======================================================================
1367
1368 Standard_Boolean StepData_StepReaderData::CheckDerived(const Standard_Integer num,
1369                                                        const Standard_Integer nump,
1370                                                        const Standard_CString mess,
1371                                                        Handle(Interface_Check)& ach,
1372                                                        const Standard_Boolean errstat) const
1373 {
1374   Handle(String) errmess;  // Null si pas d erreur
1375   Standard_Boolean warn = !errstat;
1376   if (nump > 0 && nump <= NbParams(num)) {
1377     if (!strcmp(Param(num,nump).CValue(),"*")) return Standard_True;
1378     else errmess = new String("Parameter n0.%d (%s) not Derived");
1379     if (acceptvoid) warn = Standard_True;
1380   }
1381   else errmess = new String("Parameter n0.%d (%s) absent");
1382
1383   if (errmess.IsNull()) return Standard_True;
1384   sprintf (txtmes,errmess->ToCString(),nump,mess);
1385   if (warn) ach->AddWarning (txtmes,errmess->ToCString());
1386   else      ach->AddFail    (txtmes,errmess->ToCString());
1387   return Standard_False;
1388 }
1389
1390
1391 //  #########################################################################
1392 // ....     Methodes specifiques (demandees par FileReaderData)     .... //
1393
1394
1395 //=======================================================================
1396 //function : NbEntities
1397 //purpose  : 
1398 //=======================================================================
1399
1400 Standard_Integer StepData_StepReaderData::NbEntities () const  // redefined
1401 {
1402   return thenbents;
1403 }
1404
1405
1406 //=======================================================================
1407 //function : FindNextRecord
1408 //purpose  : 
1409 //=======================================================================
1410
1411 Standard_Integer StepData_StepReaderData::FindNextRecord
1412   (const Standard_Integer num) const
1413 {
1414   // retourne, sur un numero d enregistrement donne (par num), le suivant qui
1415   // definit une entite, ou 0 si c est fini :
1416   // passe le Header (nbhend premiers records) et
1417   // saute les enregistrements SCOPE et ENDSCOPE et les SOUS-LISTES
1418
1419   if (num < 0) return 0 ;
1420   Standard_Integer num1 = num + 1 ; if (num == 0) num1 = thenbhead + 1;
1421   Standard_Integer max = NbRecords() ;
1422
1423   while (num1 <= max ) {
1424     if (theidents(num1) > 0) return num1;
1425
1426     // SCOPE,ENDSCOPE et Sous-Liste ont un identifieur fictif: -1,-2 respectivement
1427     // et SUBLIST ont un negatif. Seule une vraie entite a un Ident positif
1428     num1 ++ ;
1429   }
1430   return 0;
1431 }
1432
1433
1434 //=======================================================================
1435 //function : FindEntityNumber
1436 //purpose  : 
1437 //=======================================================================
1438
1439 Standard_Integer StepData_StepReaderData::FindEntityNumber(const Standard_Integer num,
1440                                                            const Standard_Integer id) const
1441 {
1442   //  Soit un "Id" : recherche dans les Parametres de type Ident de <num>,
1443   //  si un d eux designe #Id justement. Si oui, retourne son EntityNumber
1444   if (num == 0) return 0;
1445   Standard_Integer nb = NbParams(num);
1446   for (Standard_Integer i = 1; i <= nb; i ++) {
1447     const Interface_FileParameter& FP = Param(num,i);
1448     if (FP.ParamType() != Interface_ParamIdent) continue;
1449     Standard_Integer ixp = atoi( &FP.CValue()[1] );
1450     if (ixp == id) return FP.EntityNumber();
1451   }
1452   return 0;    // ici, pas trouve
1453 }
1454
1455
1456 //  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
1457 // ....         La fonction qui suit merite une attention speciale        ....
1458
1459
1460 //  Cette methode precharge les EntityNumbers dans les Params : ils designent
1461 //  les Entites proprement dites dans la liste lue par BoundEntity
1462 //  Interet : adresse de meme les sous-listes (Num->no record dans le Direc)
1463 //  resultat exploite par ParamEntity et ParamNumber
1464
1465 //  En l absence de SCOPE, ou si les "ident" sont strictement ordonnes, a coup
1466 //  sur ils ne sont pas dupliques, on peut utiliser une IndexedMap en toute
1467 //  confiance. Sinon, il faut balayer dans le fichier, mais avec les SCOPES
1468 //  cela va beaucoup plus vite (s ils sont assez gros) : on s y retrouve.
1469
1470 // Pour la recherche par balayage, On opere en plusieurs etapes
1471 // Avant toute chose, le chargement a deja fait une preparation : les idents
1472 // (Entity, SubList) sont deja en entiers (rapidite de lecture), en particulier
1473 // dans les EntityNumber : ainsi, on lit cet ident, on le traite, et on remet
1474 // a la place un vrai numero de Record
1475 //
1476 // D abord, on passe le directory en table d entiers,  sous-listes expurgees
1477 // en // , table inverse vers cette table, car les sous-listes peuvent par
1478 // contre designer des objets ...
1479
1480 // Pour les sous-listes, on exploite leur mode de construction : elles sont
1481 // enregistrees AVANT d etre referencees. Un tableau "subn" note donc pour
1482 // chaque numero de sous-liste (relatif a une entite qui suit, et reference
1483 // par elle ou une autre sous-liste qui suit egalement), son n0 de record
1484 // REMARQUE : ceci marche aussi pour le Header, traite par l occasion
1485
1486
1487 //=======================================================================
1488 //function : SetEntityNumbers
1489 //purpose  : 
1490 //=======================================================================
1491
1492 void StepData_StepReaderData::SetEntityNumbers(const Standard_Boolean withmap)
1493 {
1494   Handle(Message_Messenger) sout = Message::DefaultMessenger();
1495 //   Passe initiale : Resolution directe par Map
1496 //   si tout passe (pas de collision), OK. Sinon, autres passes a prevoir
1497 //   On resoud du meme coup les sous-listes
1498   Standard_Integer nbdirec = NbRecords() ;
1499   TColStd_Array1OfInteger subn(0, thelastn);
1500
1501   Standard_Boolean pbmap = Standard_False;        // au moins un conflit
1502   Standard_Integer nbmap = 0;
1503   TColStd_IndexedMapOfInteger imap(thenbents);
1504   TColStd_Array1OfInteger indm(0, nbdirec);    // Index Map -> Record Number (seulement si map)
1505
1506   Standard_Integer num; // svv Jan11 2000 : porting on DEC
1507   for (num = 1 ; num <= nbdirec ; num ++) {
1508     Standard_Integer ident = theidents(num);
1509     if (ident > 0) {      // Ident normal -> Map ?
1510 //  Map : si Recouvrement, l inhiber. Sinon, noter index
1511       Standard_Integer indmap = imap.Add(ident);
1512       if (indmap <= nbmap) {
1513         indmap = imap.FindIndex(ident);    // plus sur
1514         indm(indmap) = -1;      // Map -> pb
1515         pbmap = Standard_True;
1516 //  pbmap signifie qu une autre passe sera necessaire ...
1517       } else {
1518         nbmap = indmap;
1519         indm(indmap) = num;      // Map ->ident
1520       }
1521     }
1522   }
1523
1524   for (num = 1 ; num <= nbdirec ; num ++) {
1525     Standard_Integer ident = theidents(num);
1526     if (ident < -2) subn(-(ident+2)) = num;  // toujours a jour ...
1527
1528     Standard_Integer nba = NbParams(num) ;
1529     Standard_Integer nda = (num == 1 ? 0 : ParamFirstRank(num-1));
1530     
1531     for (Standard_Integer na = nba ; na > 0 ; na --) {
1532 //    On traite : les sous-listes (sf subn), les idents (si Map dit OK ...)
1533       Interface_FileParameter& FP = ChangeParameter (nda+na);
1534 //      Interface_FileParameter& FP = ChangeParam (num,na);
1535       Interface_ParamType letype = FP.ParamType();
1536       if (letype == Interface_ParamSub) {
1537         Standard_Integer numsub = FP.EntityNumber();
1538         if (numsub > thelastn) {
1539           sout<<"Bad Sub.N0, Record "<<num<<" Param "<<na<<":$"<<numsub<<endl;
1540           continue;
1541         }
1542         FP.SetEntityNumber(subn(numsub));
1543       } else if (letype == Interface_ParamIdent) {
1544         Standard_Integer id = FP.EntityNumber();
1545         Standard_Integer indmap = imap.FindIndex(id);
1546         if (indmap > 0) {                  // la map a trouve
1547           Standard_Integer num0 = indm(indmap);
1548           if (num0 > 0) FP.SetEntityNumber(num0);  // ET VOILA, on a resolu
1549           else FP.SetEntityNumber(-id);   // CONFLIT -> faudra resoudre ...
1550         } else {                          // NON RESOLU, si pas pbmap, le dire
1551           FP.SetEntityNumber(-id);
1552           if (pbmap) continue;            // pbmap : on se retrouvera
1553           char failmess[100];
1554 //  ...  Construire le Check  ...
1555           sprintf(failmess,
1556             "Unresolved Reference, Ent.Id.#%d Param.n0 %d (Id.#%d)",
1557                   ident,na,id);
1558           thecheck->AddFail(failmess,"Unresolved Reference");
1559 //  ...  Et sortir message un peu plus complet
1560           sout << "*** ERR StepReaderData *** Pour Entite #"<< ident
1561             << "\n    Type:" << RecordType(num)
1562             << "  Param.n0 " << na << ": #" << id << " Non trouve" << endl ;
1563         }      // FIN  Mapping
1564       }        // FIN  Traitement Reference
1565     }          // FIN  Boucle Parametres
1566   }            // FIN  Boucle Repertoires
1567
1568   if (!pbmap) {
1569     return;
1570   }
1571   sout << " --  2nd pass required --";
1572
1573   Standard_Integer nbseq = thenbents+2*thenbscop;
1574   TColStd_Array1OfInteger inds(0, nbseq);   // n0 Record/Entite
1575   TColStd_Array1OfInteger indi(0, nbseq);   // Idents/scopes
1576   TColStd_Array1OfInteger indr(0, nbdirec); // inverse de nds
1577   Handle(TColStd_HArray1OfInteger) indx;    // pour EXPORT (silya)
1578
1579   imap.Clear();
1580   Standard_Boolean iamap = withmap;               // (par defaut True)
1581   nbmap = 0;
1582
1583   TColStd_SequenceOfInteger scopile;  // chainage des scopes note par pile
1584   Standard_Integer nr = 0 ;
1585   for (num = 1 ; num <= nbdirec ; num ++) {
1586     Standard_Integer ident = theidents(num);
1587     if (ident < -2) {             // SOUS-LISTE (cas le plus courant)
1588       indr(num) = nr + 1;         // recherche basee sur nr (objet qui suit)
1589     } else if (ident >= 0) {      // Ident normal
1590       nr ++;  inds(nr) = num;  indi(nr) = ident; indr(num) = nr;
1591       if (ident > 0) {   // et non (iamap && ident > 0)
1592 //  Map : si Recouvrement, l inhiber. Sinon, noter index
1593         Standard_Integer indmap = imap.Add(ident);
1594         if (indmap <= nbmap) {
1595           Standard_Boolean errorscope = Standard_False;
1596           indmap = imap.FindIndex(ident);    // plus sur
1597           pbmap = Standard_True;
1598           if (thenbscop == 0) errorscope = Standard_True;
1599 //  Numeros identiques alors quilnya pas de SCOPE ? ERREUR !
1600 //  (Bien sur, silya des SCOPES, on passe au travers, mais bon...)
1601           else {
1602 //  Silya des SCOPES, tachons d y voir de plus pres pour signaler un probleme
1603 //  Erreur si MEME groupe SCOPE
1604 //  ATTENTION, on recherche, non dans tous les records, mais dans les records
1605 //    CHAINES, cf nr et non num (pas de sous-liste, chainage scope-endscope)
1606             Standard_Integer fromscope  = nr;
1607             Standard_Integer toscope    = indm(indmap);
1608             if (toscope < 0) toscope = -toscope;
1609             while (1) {
1610               fromscope --;    // iteration de base
1611               if (fromscope <= toscope) {
1612                 errorscope = Standard_True;  // BANG, on est dessus
1613                 break;
1614               }
1615               Standard_Integer idtest = indi(fromscope);
1616               if (idtest >=  0) continue;  // le suivant (enfin, le precedent)
1617               if (idtest == -1) break;     // pas meme niveau, donc c est OK
1618               if (idtest == -3) {
1619                 fromscope = inds(fromscope);
1620                 if (fromscope < toscope) break;  // on sort, pas en meme niveau
1621               }
1622             }
1623           }
1624           if (errorscope) {
1625 //  On est dedans : le signaler
1626             char ligne[80];
1627             sprintf(ligne,"Ident defined SEVERAL TIMES : #%d",ident);
1628             thecheck->AddFail(ligne,"Ident defined SEVERAL TIMES : #%d");
1629             sout << "StepReaderData:SetEntityNumbers, " << ligne << endl;
1630           }
1631           if (indm(indmap) > 0) indm(indmap) = -indm(indmap);  // Pas pour Map
1632 //  Cas Normal pour la Map
1633         } else {
1634           nbmap = indmap;
1635           indm(indmap) = nr;      // Map ->(indm)->inds
1636         }
1637       }
1638     } else if (ident == -1) {     // SCOPE
1639       nr ++;  inds(nr) = num;  indi(nr) = -1;    indr(num) = 0;
1640       scopile.Append(nr) ;
1641     } else if (ident == -2) {     // ENDSCOPE
1642       Standard_Integer nscop = scopile.Last() ;     // chainage SCOPE-ENDSCOPE
1643       scopile.Remove(scopile.Length()) ;
1644       nr ++; inds(nr) = nscop; indi(nr) = -3; indr(num) = 0; inds(nscop) = nr;
1645       if (NbParams(num) > 0) {
1646 //  EXPORT : traitement special greffe sur celui de SCOPE (sans le perturber)
1647         if (indx.IsNull()) {
1648     indx = new TColStd_HArray1OfInteger(0, nbseq);
1649     for (Standard_Integer ixp = 0; ixp <= nbseq; ixp ++) indx->ChangeValue(ixp) = 0;
1650         }
1651   indx->ChangeValue(nr) = num;  indx->ChangeValue(nscop) = num;
1652       }
1653     } else if (ident == 0) {      // HEADER
1654       indr(num) = 0;
1655     }
1656   }
1657
1658 //  ..    Resolution des EXPORT, silyena et silya besoin    ..
1659 //  Pour chaque valeur de EXPORT qui n a pas ete resolue par la MAP,
1660 //  determiner sa position locale par recherche en arriere depuis ENDSCOPE
1661   if ((!iamap || pbmap) && !indx.IsNull()) {
1662     for (nr = 0; nr <= nbseq; nr ++) {
1663       if (indx->Value(nr) == 0 && indi(nr) != -3) continue;  // ENDSCOPE + EXPORT
1664       num = indx->Value(nr);
1665       Standard_Integer nba = NbParams(num);
1666       for (Standard_Integer na = 1; na <= nba; na ++) {
1667         Interface_FileParameter& FP = ChangeParam (num,na);
1668         if (FP.ParamType() != Interface_ParamIdent) continue;
1669         Standard_Integer id = - FP.EntityNumber();
1670         if (id < 0) continue;    // deja resolu en tete
1671 /*      if (imap.Contains(id)) {            et voila
1672           FP.SetEntityNumber(indm(imap.FindIndex(id)));
1673           continue;
1674         }    */
1675
1676 //  Recherche du Id demande : si EXPORT imbrique, deja resolu mais il faut
1677 //  regarder ! (inutile par contre d aller y voir : c est deja fait, car
1678 //  un EXPORT imbrique a ete traite AVANT celui qui imbrique)
1679         Standard_Integer n0 = nr-1 ;
1680         if (indi(n0) == -3) n0 --;         // si on suit juste un ENDSCOPE
1681         while (n0  > 0) {
1682           Standard_Integer irec = indi(n0);
1683           if (irec == id) {                // trouve
1684             FP.SetEntityNumber(inds(n0));
1685             break ;
1686           }
1687           if (irec == -1) break;           // SCOPE : fin de ce SCOPE/ENDSCOPE
1688           if (irec == -3) {
1689 //  gare a EXPORT : si un EXPORT detient Id, noter son Numero deja calcule
1690 //  Attention : Id a lire depuis CValue  car EntityNumber deja resolu
1691       Standard_Integer nok = FindEntityNumber (indx->Value(n0),id);
1692             if (nok > 0) {
1693               FP.SetEntityNumber(nok);
1694               break;
1695             }
1696             n0 = inds(n0);   // ENDSCOPE ou EXPORT infructueux : le sauter
1697           }      // fin traitement sur un ENDSCOPE ou EXPORT
1698           n0 -- ;
1699         }        // fin resolution d un Parametre EXPORT
1700       }          // fin resolution de la liste d un EXPORT
1701     }            // fin bouclage sur les EXPORT
1702   }
1703
1704 //  Exploitation de la table : bouclage porte sur la table
1705
1706 //  Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
1707 //  basee sur la constitution des sous-listes
1708   Standard_Integer maxsubpil = 30;  // pile simulee avec un Array : tres fort
1709   Handle(TColStd_HArray1OfInteger) subpile =  // ... gagne de la memoire ...
1710     new TColStd_HArray1OfInteger (1,maxsubpil);
1711   Standard_Integer nbsubpil = 0;              // ... et tellement plus rapide !
1712
1713   for (num = 1 ; num <= nbdirec ; num ++) {
1714     nr = indr(num);
1715     if (nr == 0) continue;  //    pas un objet ou une sous-liste
1716     Standard_Integer nba = NbParams(num) ;
1717     for (Standard_Integer na = nba ; na > 0 ; na --) {
1718 //  On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
1719 //  Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
1720
1721       Interface_FileParameter& FP = ChangeParam (num,na);
1722       Interface_ParamType letype = FP.ParamType();
1723       if (letype == Interface_ParamSub) {
1724 //  parametre type sous-liste : numero de la sous-liste lu par depilement
1725         FP.SetEntityNumber(subpile->Value(nbsubpil));
1726         nbsubpil --;   //       subpile->Remove(nbsubpil);
1727
1728       } else if (letype == Interface_ParamIdent) {
1729 //  parametre type ident (reference une entite) : chercher ident demande
1730         Standard_Integer id = - FP.EntityNumber();
1731         if (id < 0) continue;    // deja resolu en tete
1732
1733 // Voila : on va chercher id dans ndi; algorithme de balayage
1734         Standard_Integer pass, sens, nok,  n0,irec;     pass = sens = nok = 0;
1735         if (!iamap) pass = 1;                  // si map non disponible
1736         while (pass < 3) {
1737           pass ++ ;
1738 //    MAP disponible
1739           if (pass == 1) {                     // MAP DISPONIBLE
1740             Standard_Integer indmap = imap.FindIndex(id);
1741             if (indmap > 0) {                  // la map a trouve
1742               nok = indm(indmap);
1743               if (nok < 0) continue;           // CONFLIT -> faut resoudre ...
1744               break;
1745             }
1746             else continue;
1747           }
1748 //    1re Passe : REMONTEE -> Debut fichier
1749           if (sens == 0 && nr > 1) {
1750             n0 = nr-1 ;
1751             if (indi(n0) == -3) n0 --;         // si on suit juste un ENDSCOPE
1752             while (n0  > 0) {
1753               irec = indi(n0);
1754               if (irec == id) {                // trouve
1755                 nok = n0 ; break ;
1756               }
1757 //    ENDSCOPE : Attention a EXPORT sinon sauter
1758               if (irec == -3) {
1759                 if (indx.IsNull()) n0 = inds(n0);
1760                 else {
1761 //    EXPORT, il faut regarder
1762       nok = FindEntityNumber (indx->Value(n0),id);
1763                   if (nok > 0) break;
1764                   n0 = inds(n0);               // ENDSCOPE : le sauter
1765                 }
1766               }
1767               n0 -- ;
1768             }
1769 //    2me Passe : DESCENTE -> Fin fichier
1770           } else if (nr < nbseq) {             // descente -> fin fichier
1771             n0 = nr+1 ;
1772             while (n0 <= nbseq) {
1773               irec = indi(n0);
1774               if (irec == id) {                // trouve
1775                 nok = n0 ; break ;
1776               }
1777 //    SCOPE : Attention a EXPORT sinon sauter
1778               if (irec == -1) {
1779                 if (indx.IsNull()) n0 = inds(n0);
1780                 else {
1781 //    EXPORT, il faut regarder
1782       nok = FindEntityNumber (indx->Value(n0),id);
1783                   if (nok > 0) break;
1784                   n0 = inds(n0);               // SCOPE : le sauter
1785                 }
1786               }
1787               n0 ++ ;
1788             }
1789           }
1790           if (nok > 0) break ;
1791           sens = 1 - sens ;      // passe suivante
1792         }
1793                                  // ici on a nok, numero trouve
1794         if (nok > 0) {
1795           Standard_Integer num0 = inds(nok);
1796           FP.SetEntityNumber(num0);  // ET VOILA, on a resolu
1797
1798                                  // pas trouve : le signaler
1799         } else {
1800 //  Alimenter le Check ...  Pour cela, determiner n0 Entite et Ident
1801           char failmess[100];
1802           Standard_Integer nument = 0;
1803           Standard_Integer n0ent; // svv Jan11 2000 : porting on DEC
1804           for (n0ent = 1; n0ent <= nr; n0ent ++) {
1805             if (indi(n0ent) > 0) nument ++;
1806           }
1807           Standard_Integer ident = RecordIdent(num);
1808           if (ident < 0) {
1809             for (n0ent = num + 1; n0ent <= nbdirec; n0ent ++) {
1810               ident = RecordIdent(n0ent); if (ident > 0) break;
1811             }
1812           }
1813 //  ...  Construire le Check  ...
1814           sprintf(failmess,
1815             "Unresolved Reference, Ent.n0 %d (Id.#%d) Param.n0 %d (Id.#%d)",
1816                   nument,ident,na,id);
1817           thecheck->AddFail(failmess,"Unresolved Reference");
1818 //  ...  Et sortir message un peu plus complet
1819           sout << "*** ERR StepReaderData *** Pour Entite "<<nument
1820             <<", a "<< (nr*100)/nbseq<<"% de DATA : #"<< ident
1821             << "\n    Type:" << RecordType(num)
1822             << "  Param.n0 " << na << ": #" << id << " Non trouve" << endl ;
1823           FP.SetEntityNumber(0);  // -> Reference non resolue
1824         }
1825       }
1826     }
1827 //  Si ce record est lui-meme une sous-liste, empiler !
1828     if (inds(nr) != num) {
1829       if (nbsubpil >= maxsubpil) {
1830         maxsubpil = maxsubpil+30;
1831         Handle(TColStd_HArray1OfInteger) newsubpil =
1832           new TColStd_HArray1OfInteger (1,maxsubpil);
1833         for (Standard_Integer bidpil = 1; bidpil <= maxsubpil - 30; bidpil ++)
1834           newsubpil->SetValue(bidpil,subpile->Value(bidpil));
1835         subpile = newsubpil;
1836       }
1837       nbsubpil ++;
1838       subpile->SetValue(nbsubpil,num);      // Append(num);
1839     }
1840   }
1841 }
1842
1843
1844 //  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
1845 //  ....             Gestion du Header : Preparation, lecture             ....
1846
1847
1848 //=======================================================================
1849 //function : FindNextHeaderRecord
1850 //purpose  : 
1851 //=======================================================================
1852
1853 Standard_Integer StepData_StepReaderData::FindNextHeaderRecord
1854   (const Standard_Integer num) const
1855 {
1856 // retourne, sur un numero d enregistrement donne (par num), le suivant qui
1857 // definit une entite, ou 0 si c est fini :
1858 // Opere comme FindNextRecord mais ne balaie que le Header
1859
1860   if (num < 0) return 0 ;
1861   Standard_Integer num1 = num + 1 ;
1862   Standard_Integer max = thenbhead;
1863
1864   while (num1 <= max ) {
1865 // SCOPE,ENDSCOPE et Sous-Liste ont un identifieur negatif
1866 // Ne retenir que les Idents positifs ou nuls (nul : pas d Ident dans Header)
1867     if ( RecordIdent(num1) >= 0) return num1 ;
1868     num1 ++ ;
1869   }
1870   return 0;
1871 }
1872
1873
1874 //=======================================================================
1875 //function : PrepareHeader
1876 //purpose  : 
1877 //=======================================================================
1878
1879 void StepData_StepReaderData::PrepareHeader ()
1880 {
1881 // Resolution des references : ne concerne que les sous-listes
1882 //  deja faite par SetEntityNumbers donc pas de souci a se faire
1883
1884 /*
1885 // Algorithme repris et adapte de SetEntityNumbers
1886 //  Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
1887 //  basee sur la constitution des sous-listes
1888   TColStd_SequenceOfInteger subpile;
1889   Standard_Integer nbsubpil = 0;     // profondeur de pile mais plus rapide ...
1890
1891   for (Standard_Integer num = 1 ; num <= thenbhead ; num ++) {
1892     Standard_Integer nba = NbParams(num) ;
1893     for (Standard_Integer na = nba ; na > 0 ; na --) {
1894 ..  On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
1895 ..  Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
1896
1897       Interface_FileParameter& FP = ChangeParam(num,na);
1898       Interface_ParamType letype = FP.ParamType();
1899       if (letype == Interface_ParamSub) {
1900 ..  parametre type sous-liste : numero de la sous-liste lu par depilement
1901         FP.SetEntityNumber(subpile.Last());
1902 .. ..        SetParam(num,na,FP);
1903         subpile.Remove(nbsubpil);
1904         nbsubpil --;
1905       }
1906     }
1907 .. Si c est une sous-liste, empiler
1908     if (RecordIdent(num) < -2) {
1909       subpile.Append(num);
1910       nbsubpil ++;
1911     }
1912   }
1913 */
1914 }
1915
1916
1917 //=======================================================================
1918 //function : GlobalCheck
1919 //purpose  : 
1920 //=======================================================================
1921
1922 const Handle(Interface_Check)  StepData_StepReaderData::GlobalCheck () const
1923 {
1924   return thecheck;
1925 }