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