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