0031756: Data Exchange - broken parsing of STEP entity in case of missing last parameter
[occt.git] / src / StepFile / StepFile_Read.cxx
1 // Created on: 1991-08-30
2 // Created by: Christian CAILLET
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //   StepFile_Read
18
19 //   routine assurant l enchainement des operations de lecture d un fichier
20 //   STEP dans un StepModel, en fonction d une cle de reconnaissance
21 //   Retour de la fonction :
22 //     0 si OK  (le StepModel a ete charge)
23 //    -1 si abandon car fichier pas pu etre ouvert
24 //     1 si erreur en cours de lecture
25
26 //   Compilation conditionnelle : concerne les mesures de performances
27
28 #include <stdio.h>
29 #include <iostream> 
30 #include <StepFile_ReadData.hxx>
31 #include <step.tab.hxx>
32
33 #include <Interface_ParamType.hxx>
34 #include <Interface_Protocol.hxx>
35 #include <Interface_Check.hxx>
36 #include <StepData_Protocol.hxx>
37
38 #include <StepData_StepReaderData.hxx>
39 #include <StepData_StepReaderTool.hxx>
40 #include <StepFile_Read.hxx>
41
42 #include <Standard_ErrorHandler.hxx>
43 #include <Standard_Failure.hxx>
44 #include <Interface_InterfaceError.hxx>
45
46 #include <Message_Messenger.hxx>
47 #include <Message.hxx>
48
49 #include <OSD_OpenFile.hxx>
50 #include <OSD_Timer.hxx>
51
52 #ifdef OCCT_DEBUG
53 #define CHRONOMESURE
54 #endif
55
56 //  ##  ##  ##  ##    ON SAURA AU MOINS TRAITER UndefinedEntity  ##  ##  ##  ##
57
58 extern "C" void recfile_modeprint (int mode);  // controle trace recfile
59
60 static Handle(Interface_Check) checkread = new Interface_Check;
61 static Standard_Integer modepr = 1;
62
63 void StepFile_ReadTrace (const Standard_Integer mode)
64 {
65   modepr = mode;   // recfile_modeprint est rappele a chaque lecture de fichier
66 }
67
68 //  ##  ##  ##  ##  ##  ##    Corps de la Routine    ##  ##  ##  ##  ##  ##
69
70 static Interface_ParamType LesTypes[10];   // passage types (recstep/Interface)
71
72 static Standard_Integer StepFile_Read (const char* theName,
73                                        std::istream* theIStream,
74                                        const Handle(StepData_StepModel)& stepmodel,
75                                        const Handle(StepData_Protocol)& protocol,
76                                        const Handle(StepData_FileRecognizer)& recoheader,
77                                        const Handle(StepData_FileRecognizer)& recodata)
78 {
79   StepFile_ReadData aFileDataModel;
80   aFileDataModel.SetModePrint(modepr > 0 ? modepr - 1 : 0);
81   // if stream is not provided, open file stream here
82   std::istream *aStreamPtr = theIStream;
83   std::ifstream aFileStream;
84   if (!aStreamPtr) {
85     OSD_OpenStream(aFileStream, theName, std::ios_base::in | std::ios_base::binary);
86     aStreamPtr = &aFileStream;
87   }
88
89   if (aStreamPtr->bad())
90   {
91     return -1;
92   }
93
94 #ifdef CHRONOMESURE
95   OSD_Timer c;
96   c.Reset();
97   c.Start();
98   Message::SendInfo() << "      ...    Step File Reading : '" << theName << "'";
99 #endif
100   try {
101     OCC_CATCH_SIGNALS
102     int aLetat = 0;
103     step::scanner aScanner(&aFileDataModel, aStreamPtr);
104     aScanner.yyrestart(aStreamPtr);
105     step::parser aParser(&aScanner);
106     aLetat = aParser.parse();
107     if (aLetat != 0) {
108       return 1;
109     }
110   }
111   catch (Standard_Failure const& anException) {
112 #ifdef OCCT_DEBUG
113     Message::SendAlarm() << " ...  Exception Raised while reading Step File : '" << theName << "':\n"
114                          << anException.GetMessageString()
115                          << "    ...";
116 #endif
117     (void)anException;
118     return 1;
119   }
120
121 // Continue reading of file despite of possible fails
122 //  if (checkread->HasFailed()) { lir_file_fin(3); stepread_endinput(newifstream, ficnom);  return 1; }
123 #ifdef CHRONOMESURE
124   {
125     Message_Messenger::StreamBuffer sout = Message::SendInfo();
126     sout << "      ...    STEP File   Read    ...\n";
127     c.Show (sout);
128   }
129 #endif
130
131 //  Creation du StepReaderData
132
133   LesTypes[ArgumentType_Nondef]    = Interface_ParamVoid ;
134   LesTypes[ArgumentType_Sub]       = Interface_ParamSub ;
135   LesTypes[ArgumentType_Ident]     = Interface_ParamIdent ;
136   LesTypes[ArgumentType_Integer]   = Interface_ParamInteger ;
137   LesTypes[ArgumentType_Float]     = Interface_ParamReal ;
138   LesTypes[ArgumentType_Enum]      = Interface_ParamEnum ;
139   LesTypes[ArgumentType_Binary]    = Interface_ParamBinary ;
140   LesTypes[ArgumentType_Text]      = Interface_ParamText ;
141   LesTypes[ArgumentType_Hexa]      = Interface_ParamHexa ;
142   LesTypes[ArgumentType_Misc]      = Interface_ParamMisc ;
143
144   Standard_Integer nbhead, nbrec, nbpar;
145   aFileDataModel.GetFileNbR (&nbhead,&nbrec,&nbpar);  // renvoi par lex/yacc
146   Handle(StepData_StepReaderData) undirec =
147     new StepData_StepReaderData(nbhead,nbrec,nbpar, stepmodel->SourceCodePage());  // creation tableau de records
148
149   for ( Standard_Integer nr = 1; nr <= nbrec; nr ++) {
150     int nbarg; char* ident; char* typrec = 0;
151     aFileDataModel.GetRecordDescription(&ident, &typrec, &nbarg);
152     undirec->SetRecord (nr, ident, typrec, nbarg);
153
154     if (nbarg>0) {
155       ArgumentType typa; char* val;
156       Interface_ParamType newtype;
157       while(aFileDataModel.GetArgDescription (&typa, &val) == 1) {
158         newtype = LesTypes[typa] ;
159         undirec->AddStepParam (nr, val, newtype);
160       }
161     }
162     undirec->InitParams(nr);
163     aFileDataModel.NextRecord();
164   }
165   aFileDataModel.ClearRecorder(1);
166 //  on a undirec pret pour la suite
167
168 #ifdef CHRONOMESURE
169   {
170     Message_Messenger::StreamBuffer sout = Message::SendInfo();
171     sout << "      ... Step File loaded  ...\n";
172     c.Show (sout);
173     sout << "   "<< undirec->NbRecords() << " records (entities,sub-lists,scopes), "<< nbpar << " parameters";
174   }
175 #endif
176
177 //   Analyse : par StepReaderTool
178
179   StepData_StepReaderTool readtool (undirec,protocol);
180   readtool.SetErrorHandle (Standard_True);
181
182   readtool.PrepareHeader(recoheader);  // Header. reco nul -> pour Protocol
183   readtool.Prepare(recodata);          // Data.   reco nul -> pour Protocol
184
185 #ifdef CHRONOMESURE
186   {
187     Message_Messenger::StreamBuffer sout = Message::SendInfo();
188     sout << "      ... Parameters prepared ...\n";
189     c.Show (sout);
190   }
191 #endif
192
193   readtool.LoadModel(stepmodel);
194   if (stepmodel->Protocol().IsNull()) stepmodel->SetProtocol (protocol);
195   aFileDataModel.ClearRecorder(2);
196   
197   readtool.Clear();
198   undirec.Nullify();
199 #ifdef CHRONOMESURE
200   {
201     Message_Messenger::StreamBuffer sout = Message::SendInfo();
202     sout << "      ...   Objets analysed  ...\n";
203     c.Show (sout);
204     Standard_Integer n = stepmodel->NbEntities();
205     sout << "  STEP Loading done : " << n << " Entities";
206   }
207 #endif
208   return 0;
209 }
210
211 Standard_Integer StepFile_Read(const char* theName,
212                                std::istream* theIStream,
213                                const Handle(StepData_StepModel)& stepmodel,
214                                const Handle(StepData_Protocol)& protocol)
215 {
216   Handle(StepData_FileRecognizer) nulreco;
217   return StepFile_Read (theName,theIStream,stepmodel,protocol,nulreco,nulreco);
218 }
219
220 void StepFile_Interrupt (char* mess)
221 {
222 #ifdef OCCT_DEBUG
223   Message_Messenger::StreamBuffer sout = Message::SendInfo();
224   sout << "    ****    StepFile Error : " << mess << "    ****" << std::endl;
225 #endif
226   checkread->AddFail(mess);
227 }