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