home *** CD-ROM | disk | FTP | other *** search
/ ftptest.leeds.ac.uk / 2015.02.ftptest.leeds.ac.uk.tar / ftptest.leeds.ac.uk / bionet / CAE-GROUP / SCL-WIN3x / SCL.EXE / SFILE.CPP < prev    next >
C/C++ Source or Header  |  1994-10-05  |  64KB  |  2,386 lines

  1.  
  2. /*
  3. * NIST STEP Core Class Library
  4. * cleditor/STEPfile.cc
  5. * February, 1994
  6. * Peter Carr
  7. * K. C. Morris
  8. * David Sauder
  9.  
  10. * Development of this software was funded by the United States Government,
  11. * and is not subject to copyright.
  12. */
  13.  
  14. /* $Id: STEPfile.cc,v 2.0.1.5 1994/05/10 21:10:23 kc Exp $ */ 
  15.  
  16. /********************************************************************
  17.  TODO LIST:
  18.  - ReadHeader doesn't merge the information from more than one instance 
  19.    of the same entity type name. i.e. it doesn't merge info from multiple files
  20.  - ReadWorkingFile does not handle references to entities which
  21.    aren't in the working session file. for other *incomplete* instances,
  22.    it prints error messages to cerr which may not need to be printed. It 
  23.    doesn't keep track of the incomplete instances, it just puts them on the
  24.    list according to the symbol which precedes them in the working session 
  25.    file
  26. **********************************************************************/
  27. #include <sfile.h>
  28. #include <STEPstring.h>
  29.  
  30. /***************************
  31. function:     SetFileName
  32. returns:      (const char*) The new file name for the class.
  33. parameters:   (const char*) The file name to be set.
  34. description:
  35.    This function sets the (char*)_fileName member variable to an
  36.    absolute path name to a directory on the file system. If newName
  37.    cannot be resolved to a file, then an empty char* is returned.
  38. side effects: STEPfile::_fileName value may change.
  39. ***************************/
  40. const char *
  41. STEPfile::SetFileName (const char* newName) 
  42. {
  43.     char tmp[32];
  44.     const char* path = tmp;
  45.  
  46.     //  if a newName is not given or is the same as the old, use the old name
  47.     if ((!newName) || (!strcmp (newName, "")) || (newName == _fileName) )
  48.     return FileName (); 
  49.     
  50.     path = newName;
  51.     if (!path)  
  52.       {
  53.       _error.AppendToUserMsg("Cannot Load Directory.\n");
  54.       return (char*)0;
  55.       }
  56.       
  57.     delete [] _fileName;
  58.     _fileName = new char[strlen(newName)+1];
  59.     if (!_fileName)  {
  60.     _error.AppendToUserMsg("free store exhausted.\n");
  61.     return (char*)0;
  62.     }
  63.     strcpy(_fileName, newName); 
  64.     return _fileName;
  65. }
  66.  
  67. /***************************
  68. function:     ReadHeader
  69. returns:      Severity
  70. parameters:   (istream&) The input stream from which the file is read.
  71. description:
  72.    This function reads in the header section of an exchange file. It
  73.    can read it in either version (N279) or (Part 21, July 1992). It
  74.    parses the header section, popluates the _headerInstances, and
  75.    returns an error descriptor.
  76.    It expects to find the "HEADER;" symbol at the beginning of the
  77.    istream.
  78. side effects: The function  gobbles all characters up to and including the
  79.    next "ENDSEC;" from in. 
  80.    The STEPfile::_headerInstances may change.
  81. ***************************/
  82.  
  83. Severity 
  84. STEPfile::ReadHeader (istream& in) 
  85. {
  86.     InstMgr *im = new InstMgr;
  87.     STEPentity* obj;
  88.     Severity objsev = SEVERITY_NULL;
  89.     
  90.     int endsec = 0;
  91.     int userDefined = 0;
  92.     int fileid;
  93.     SCLstring keywd;
  94.     char c = '\0';
  95.     char buf [BUFSIZ];
  96.  
  97.     SCLstring strbuf;
  98.  
  99.     ReadTokenSeparator(in);
  100.     // Read and gobble all 'junk' up to "HEADER;"
  101.     if (!FindHeaderSection(in)) 
  102.       {  delete im; return SEVERITY_INPUT_ERROR;  }
  103.  
  104.     //read the header instances
  105.     while (!endsec)
  106.       {
  107.       ReadTokenSeparator(in);
  108.       if (in.eof()) 
  109.         {
  110.         _error.AppendToDetailMsg("End of file reached in reading header section.\n");
  111.         _error.GreaterSeverity(SEVERITY_EXIT);
  112.         delete im;
  113.         return SEVERITY_EXIT;
  114.         }
  115.       
  116.       //check for user defined instances
  117.       //if it is userDefined, the '!' does not get put back on the istream
  118.       in.get(c);
  119.       if (c == '!') { userDefined = 1; }
  120.       else          { in.putback(c);   }
  121.       
  122.       //get the entity keyword
  123.       keywd = GetKeyword(in,";( /\\");
  124.       ReadTokenSeparator(in);
  125.  
  126.       //check for "ENDSEC"
  127.       if (!strncmp(keywd,"ENDSEC",7)) 
  128.         { 
  129.         //get the token delimiter
  130.         in.get(c); //should be ';'
  131.         endsec = 1; break; //from while-loop
  132.         }
  133.       else 
  134.         { //create and read the header instance 
  135.         
  136.         //check for '(' and read it
  137.         ReadTokenSeparator(in);
  138.         in.get(c);
  139.         if (c != '(') 
  140.           {
  141.               ++_errorCount;
  142.               SkipInstance(in, strbuf);
  143.               cerr << "Unable to create header section entity: \'" <<
  144.               keywd << "\'.\ndata lost: " <<
  145.                   strbuf << "\n";
  146.               
  147.               _error.GreaterSeverity(SEVERITY_WARNING);
  148.               break; //to start of while-loop
  149.           }
  150.         
  151.         //create header instance
  152.         buf[0]= '\0';
  153.         if (_fileType == VERSION_OLD) {
  154.             strcpy(buf,"N279_");
  155.             strncat(buf,keywd, BUFSIZ-7);
  156.         }
  157.         else { strncpy (buf, keywd, BUFSIZ);  }
  158.         
  159.         if (userDefined) 
  160.           {
  161.               //create user defined header instance
  162.               // BUG: user defined entities are ignored
  163.               //obj = _headerUserDefined->ObjCreate (buf);
  164.               //objsev = AppendEntityErrorMsg( &(obj->Error()) );
  165.  
  166.             SkipInstance(in, strbuf);
  167.               cerr << "User defined entity in header section " <<
  168.               "is ignored.\n\tdata lost: !" <<  buf << strbuf << "\n";
  169.               _error.GreaterSeverity(SEVERITY_WARNING);
  170.               break; //from while loop
  171.           }
  172.         else //not userDefined
  173.           {
  174.               obj = _headerRegistry->ObjCreate (buf);
  175.           }
  176.         
  177.         //read header instance
  178.         if (!obj || (obj == ENTITY_NULL) )
  179.           {
  180.               ++_errorCount;
  181.               SkipInstance(in, strbuf);
  182.               cerr << "Unable to create header section entity: \'" <<
  183.               keywd << "\'.\n\tdata lost: " << strbuf << "\n";
  184.               _error.GreaterSeverity(SEVERITY_WARNING);
  185.           }
  186.         else //not ENTITY_NULL
  187.              //read the header instance
  188.           {
  189.             //check obj's Error Descriptor
  190.             objsev = AppendEntityErrorMsg( &(obj->Error()) );
  191.  
  192.             //set file_id to reflect the appropriate Header Section Entity
  193.             switch (_fileType) 
  194.               {
  195.               case VERSION_OLD:
  196.             fileid = HeaderIdOld(keywd);
  197.             break;
  198.               default:
  199.             fileid = HeaderId(keywd);
  200.             break;                
  201.               }
  202.               
  203.             //read the values from the istream
  204.             objsev = obj->STEPread(fileid,0,(InstMgr*)0,in);
  205.             
  206.             //check to see if object was successfully read
  207.             AppendEntityErrorMsg( &(obj->Error()) );
  208.             //append to header instance manager
  209.             im->Append(obj, completeSE);
  210.           }
  211.         }
  212.       
  213.       }
  214.     
  215.     if (_fileType == VERSION_OLD) {
  216.       InstMgr * tmp = HeaderConvertToNew(*im);
  217.       delete im;
  218.       im = tmp;
  219.     }
  220.     HeaderVerifyInstances(im);
  221.     HeaderMergeInstances(im);  // handles delete for im
  222.  
  223.     return _error.severity();
  224. }
  225.  
  226.  
  227. /***************************
  228. function:     HeaderConvertToNew
  229. returns:      (InstMgr*) List of instances of header section entities
  230.                          which semantically conform to the new version
  231.                          of the exchange file format.
  232. parameters:   (InstMgr&) List of instances of header section entities
  233.                          which semantically conform to the old version
  234.                          of the exchange file format.
  235. description:
  236.    This function converts the instances of the given InstMgr from the 
  237.    old STEPfile format to the new file format. The InstMgr must
  238.    contain only instances of header section entities, and those entities 
  239.    must be numbered in a specific way.
  240.  
  241.       OLD FORMAT (N279)
  242.  
  243.    #1=FILE_IDENTIFICATION
  244.    #2=FILE_DESCRIPTION
  245.    #3=IMP_LEVEL
  246.    #4=CLASSIFICATION
  247.    #5=MAXSIG   
  248.  
  249. side effects: This function allocates memory for an InstMgr using a
  250.    call to the new operator.  
  251.    It also removes some instances from oldinst.
  252. ***************************/
  253. InstMgr*
  254. STEPfile::HeaderConvertToNew(InstMgr& oldinst) 
  255. {
  256.     InstMgr* imtmp = new InstMgr; 
  257.     STEPentity* oldse;
  258.     
  259.     int count = 0;
  260.     
  261. // FILE_NAME <== (N279)FILE_IDENTIFICATION
  262.     p21DIS_File_name * fn = 0;
  263.     oldse = oldinst.GetSTEPentity("N279_File_Identification",0);
  264.     if (oldse == ENTITY_NULL) 
  265.       {
  266.       cerr << "Warning: STEPfile::HeaderConvertToNew. Unable to get " <<
  267.           "\'File_Identification\' from header instance manager.\n";
  268.       fn = (p21DIS_File_name *) HeaderDefaultFileName();
  269.       }
  270.     else 
  271.       {
  272.       
  273.       s_N279_file_identification * fi;
  274.       fi = (s_N279_file_identification*) oldse;
  275.       
  276.       fn = new p21DIS_File_name;
  277.       
  278.       fn->name(fi->file_name());     //STRING <- STRING
  279.       fn->time_stamp(fi->date());    //STRING <- STRING
  280.       //fn->author(fi->author());      
  281.         //LIST OF STRING <- LIST OF STRING
  282.       (fn->author()).ShallowCopy(fi->author());
  283.         //LIST OF STRING <- LIST OF STRING
  284.       (fn->organization()).ShallowCopy(fi->organization());
  285.       fn->preprocessor_version(fi->preprocessor_version()); //STRING
  286.       fn->originating_system(fi->originating_system());     //STRING
  287.       fn->authorisation("");         //STRING
  288.       fn->STEPfile_id = HeaderId("File_Name");
  289.  
  290.       oldinst.Delete(fi);
  291.       }
  292.     
  293.     imtmp->Append(fn, completeSE);
  294.     
  295. // FILE_DESCRIPTION <== (N279)FILE_DESCRIPTION & (N279)IMP_LEVEL
  296.    p21DIS_File_description * fd = new p21DIS_File_description;
  297.     // Get the (N279) File_Description Instance
  298.     oldse = oldinst.GetSTEPentity("N279_File_Description",0);
  299.     s_N279_file_description * ofd = (s_N279_file_description*)oldse;
  300.     if (oldse != ENTITY_NULL) 
  301.       {
  302. //  DAVE, is there a new way TODO this?
  303.       // copy a STEPstring value into a StringAggregate
  304.       const char* tmpstr = ofd->description();
  305.       int len = strlen(tmpstr) + 2;      
  306.       char *str = new char[len];
  307.       str[0]='\'';  str[1]='\0';
  308.       strncat(str,tmpstr,len);  
  309.       strncat(str,"\'",len);
  310.       StringNode * sn = new StringNode(str);
  311.       fd->description().AddNode(sn);
  312.       oldinst.Delete(ofd);
  313.       delete [] str;
  314.       }
  315.     else 
  316.       {
  317.       StringNode * sn = new StringNode("");
  318.       fd->description().AddNode(sn);
  319.       }
  320.     
  321.     // Get the (N279) Imp_Level Instance
  322.     oldse = oldinst.GetSTEPentity("N279_Imp_Level",0);
  323.     s_N279_imp_level * il = (s_N279_imp_level*)oldse;
  324.     if (oldse != ENTITY_NULL) 
  325.       {
  326.       fd->implementation_level(il->implementation_level());
  327.       oldinst.Delete(il);
  328.       }
  329.     else 
  330.       {
  331.       fd->implementation_level("");
  332.       }
  333.     fd->STEPfile_id = HeaderId("File_Description");
  334.     imtmp->Append(fd, completeSE);
  335.  
  336. // FILE_SCHEMA <== default values
  337.     // There is no entity for the file_schema in the old version
  338.     // Therefore, the schema_identifiers list is left empty
  339.     imtmp->Append(HeaderDefaultFileSchema(), completeSE);
  340.  
  341.  
  342. //append any extra instances from oldinst onto imtmp
  343.     for (register int n = oldinst.InstanceCount() - 1; n>=0; --n) 
  344.       {
  345.       imtmp->Append(oldinst.GetSTEPentity(oldinst[n]),completeSE);
  346.       }
  347.     
  348.     return imtmp;    
  349. }
  350.  
  351.  
  352. /***************************
  353. Verify the instances read from the header section of an exchange file.
  354. If some required instances aren't present, then create them,
  355. and populate them with default values.
  356. The required instances are:
  357.   #1 = FILE_NAME
  358.   #2 = FILE_DESCRIPTION
  359.   #3 = FILE_SCHEMA
  360. ***************************/
  361. Severity
  362. STEPfile::HeaderVerifyInstances(InstMgr* im)
  363. {
  364.     int err = 0;
  365.     int fileid;
  366.     STEPentity* obj;
  367.     
  368.     //check File_Name
  369.     fileid = HeaderId("File_Name");
  370.     if (!(im->FindFileId(fileid))) 
  371.       {
  372.       ++err;
  373.       cerr << "FILE_NAME instance not found in header section\n";
  374.       // create a File_Name entity and assign default values
  375.       obj = HeaderDefaultFileName();
  376.       im->Append(obj,completeSE);
  377.       }
  378.  
  379.     //check File_Description
  380.     fileid = HeaderId("File_Description");
  381.     if (!(im->FindFileId(fileid))) 
  382.       {
  383.       ++err;
  384.       cerr << "FILE_DESCRIPTION instance not found in header section\n";
  385.       // create a File_Description entity and assign default values
  386.       obj = HeaderDefaultFileDescription();
  387.       im->Append(obj,completeSE);
  388.       }
  389.  
  390.     //check File_Schema
  391.     fileid = HeaderId("File_Schema");
  392.     if (!(im->FindFileId(fileid))) 
  393.       {
  394.       ++err;
  395.       cerr << "FILE_SCHEMA instance not found in header section\n";
  396.       // create a File_Schema entity and read in default values
  397.       obj = HeaderDefaultFileSchema();
  398.       im->Append(obj,completeSE);
  399.       }
  400.  
  401.     if (!err) return SEVERITY_NULL;
  402.     _error.AppendToUserMsg("Missing required entity in header section.\n");
  403.     _error.GreaterSeverity(SEVERITY_WARNING);
  404.     return SEVERITY_WARNING;
  405. }
  406.  
  407. STEPentity* 
  408. STEPfile::HeaderDefaultFileName() 
  409. {
  410.     p21DIS_File_name * fn = new p21DIS_File_name;
  411.  
  412.     fn->name("");
  413.     fn->time_stamp("");
  414.     fn->author().StrToVal("", &_error, 
  415.               fn->attributes[2].
  416.               AttrDescriptor -> DomainType (), 
  417.               _headerInstances);
  418.     fn->organization().StrToVal("", &_error, 
  419.                    fn->attributes[3].
  420.                 AttrDescriptor -> DomainType (), 
  421.                 _headerInstances);
  422.     fn->preprocessor_version("");
  423.     fn->originating_system("");
  424.     fn->authorisation("");
  425.  
  426.     fn->STEPfile_id = HeaderId ("File_Name");
  427.  
  428.     return fn;
  429. }
  430.  
  431. STEPentity* 
  432. STEPfile::HeaderDefaultFileDescription() 
  433. {
  434.    p21DIS_File_description * fd = new p21DIS_File_description;
  435.     
  436.     fd->implementation_level("");
  437.  
  438.     fd->STEPfile_id = HeaderId ("File_Description");
  439.  
  440.     return fd;
  441. }
  442.  
  443. STEPentity*
  444. STEPfile::HeaderDefaultFileSchema() 
  445. {
  446.     p21DIS_File_schema * fs = new p21DIS_File_schema;
  447.     
  448.     fs->schema_identifiers().StrToVal("", &_error, 
  449.                       fs->attributes[0].
  450.                 AttrDescriptor -> DomainType (), 
  451.                       _headerInstances);
  452.  
  453.     fs->STEPfile_id = HeaderId ("File_Schema");
  454.  
  455.     return fs;
  456. }
  457.  
  458.  
  459.  
  460. /***************************
  461. This function has an effect when more than one file
  462. is being read into a working session.
  463.  
  464. This function manages space allocation for the Instance
  465. Manager for the header instances. If the instances in im are
  466. copied onto the instances of _headerInstances, then im is
  467. deleted. Otherwise no space is deleted.
  468.  
  469. Append the values of the given instance manager onto the _headerInstances.
  470. If the _headerInstances contain no instances, then copy the instances
  471. from im onto the _headerInstances.
  472. This only works for an instance manager which contains the following
  473. header section entites. The file id numbers are important.
  474.  
  475.   #1 = FILE_NAME
  476.   #2 = FILE_DESCRIPTION
  477.   #3 = FILE_SCHEMA
  478.   #4 = CLASSIFICATION (this entity is optional in the header section)
  479. ***************************/
  480. void
  481. STEPfile::HeaderMergeInstances(InstMgr* im)
  482. {
  483.     STEPentity* se = 0; 
  484.     STEPentity* from = 0;
  485.     STEPentity* to = 0;
  486.     
  487.     int idnum;
  488.  
  489.     //check for _headerInstances
  490.     if (!_headerInstances) {
  491.       _headerInstances = im;
  492.       return;
  493.     }
  494.  
  495.     if (_headerInstances->InstanceCount() < 4) 
  496.       {
  497.       delete _headerInstances;
  498.       _headerInstances = im;
  499.       return;
  500.       }
  501.     
  502.     //checking for _headerInstances::FILE_NAME
  503.     idnum = HeaderId("File_Name");
  504.     if(se = _headerInstances->GetSTEPentity(_headerInstances->FindFileId(idnum))) 
  505.       {
  506.       from = im->GetSTEPentity(im->FindFileId(idnum));
  507.  
  508.       // name: 
  509.       // time_stamp: keep the newer time_stamp
  510.       // author: append the list of authors
  511.       // organization: append the organization list
  512.       // preprocessor_version: 
  513.       // originating_system: 
  514.       // authorization:
  515.       }
  516.     else  // No current File_Name instance
  517.       {
  518.       from = im->GetSTEPentity(im->FindFileId(idnum));
  519.       _headerInstances->Append(from,completeSE);
  520.       }
  521.  
  522.     //checking for _headerInstances::FILE_DESCRIPTION
  523.     idnum = HeaderId("File_Description");
  524.     if(se = _headerInstances->GetSTEPentity(_headerInstances->FindFileId(idnum))) 
  525.       {
  526.       from = im->GetSTEPentity(im->FindFileId(idnum));
  527.       
  528.       //description
  529.       //implementation_level
  530.       }
  531.     else 
  532.       {
  533.       from = im->GetSTEPentity(im->FindFileId(idnum));
  534.       _headerInstances->Append(from,completeSE);
  535.       }
  536.  
  537.     //checking for _headerInstances::FILE_SCHEMA
  538.     idnum = HeaderId("File_Schema");
  539.     if(se = _headerInstances->GetSTEPentity(_headerInstances->FindFileId(idnum))) 
  540.       {
  541.       from = im->GetSTEPentity(im->FindFileId(idnum));
  542.       
  543.       //description
  544.       //implementation_level
  545.       }
  546.     else 
  547.       {
  548.       from = im->GetSTEPentity(im->FindFileId(idnum));
  549.       _headerInstances->Append(from,completeSE);
  550.       }
  551.  
  552.     delete im;
  553.     return;
  554. }    
  555.     
  556.       
  557.  
  558.  
  559.  
  560. /***************************
  561. ***************************/
  562. int
  563. STEPfile::ReadData1(istream& in)
  564. {
  565.     
  566.     char buf[BUFSIZ];
  567.     char *b = buf;
  568.     char c;
  569.     int instance_count =0;
  570.     _errorCount = 0;  // reset error count
  571.     _warningCount = 0;  // reset error count
  572.     
  573.     *b = '\0';
  574.  
  575.     //  starts at the data section
  576.     STEPentity * obj;
  577.  
  578.     ReadTokenSeparator (in);
  579.     in >> c;
  580.     
  581.     //  PASS 1:  create instances
  582.     while (c == ENTITY_NAME_DELIM && in.good ()) 
  583.       {
  584.       obj =  CreateInstance (in);
  585.       if (obj != ENTITY_NULL) 
  586.         {
  587.         if (obj->Error().severity() < SEVERITY_NULL) 
  588.           {  ++_errorCount; obj->Error().ClearErrorMsg();   }
  589.         
  590.         instances ().Append (obj,newSE);
  591.         ++instance_count;
  592.         }
  593.       else 
  594.         {  
  595.           ++_errorCount;   
  596.         }
  597.  
  598.       if (_errorCount > _maxErrorCount) 
  599.         {
  600.         _error.AppendToUserMsg("Warning: Too Many Errors in File. Read function aborted.\n");
  601.         cerr << Error().UserMsg();
  602.         cerr << Error().DetailMsg();
  603.         Error().ClearErrorMsg();
  604.         Error().severity(SEVERITY_EXIT);
  605.         return instance_count;
  606.         }
  607.       
  608.       ReadTokenSeparator (in);
  609.       in >> c;
  610.       }
  611.     if (_errorCount) 
  612.       {
  613.       sprintf(buf,
  614.       "STEPfile::ReadExchangeFile: Unable to create %d instances.\n\tIn first pass through DATA section. Check for invalid entity types.\n",
  615.       _errorCount);
  616.       _error.AppendToUserMsg(buf);
  617.       _error.GreaterSeverity(SEVERITY_WARNING);
  618.       }
  619.     if (!in.good ())
  620.       _error.AppendToUserMsg ("Error in input file.\n");
  621.     
  622.     return instance_count;
  623. }
  624.  
  625. int
  626. STEPfile::ReadWorkingData1 (istream& in)
  627. {
  628.     _errorCount = 0;  // reset error count
  629.     _warningCount = 0;  // reset error count
  630.  
  631.     char errbuf[BUFSIZ];
  632.     SCLstring tmpbuf;
  633.     char c;
  634.     int instance_count =0;
  635.     
  636.     //  PASS 1:  create instances
  637.     STEPentity * obj;
  638.     stateEnum inst_state;
  639.  
  640.     int endsec = 0;
  641.     while (!endsec)
  642.       {
  643.       //check for end of file
  644.       if (in.eof()) 
  645.         {
  646.         _error.AppendToUserMsg(
  647.         "Error: in ReadWorkingData1. end of file reached.\n");
  648.         return instance_count;
  649.         }
  650.  
  651.       //check error count
  652.       if (_errorCount > _maxErrorCount) 
  653.         {
  654.         cerr << 
  655.         "Warning: Too Many Errors in File. Read function aborted.\n";
  656.         cerr << Error().UserMsg();
  657.         cerr << Error().DetailMsg();
  658.         Error().ClearErrorMsg();
  659.         Error().severity(SEVERITY_EXIT);
  660.         return instance_count;
  661.         }
  662.  
  663.       inst_state = noStateSE;
  664.       ReadTokenSeparator (in);
  665.       in.get(c);
  666.       
  667.       switch (c) 
  668.         {
  669.           case wsSaveComplete:
  670.         in >> c;
  671.         if (c == ENTITY_NAME_DELIM) 
  672.             inst_state = completeSE;
  673.         break;
  674.         
  675.           case wsSaveIncomplete:
  676.         in >> c;
  677.         if (c == ENTITY_NAME_DELIM) 
  678.             inst_state = incompleteSE;
  679.         break;
  680.         
  681.           case wsDelete:
  682.         in >> c;
  683.         if (c == ENTITY_NAME_DELIM) 
  684.             inst_state = deleteSE;
  685.         break;
  686.  
  687.           case wsNew:
  688.         in >> c;
  689.         if (c == ENTITY_NAME_DELIM) 
  690.             inst_state = newSE;
  691.         break;
  692.  
  693.           case 'E':
  694.         // "ENDSEC;" expected
  695.         in.putback(c);
  696.         endsec = 1;
  697.         if (_errorCount) 
  698.           {
  699.               sprintf(errbuf,"%d error(s) in second pass of DATA section.\n",_errorCount);
  700.               _error.AppendToUserMsg(errbuf);
  701.           }
  702.  
  703.         return instance_count;
  704.  
  705.           default:
  706.         cerr << "Error: in ReadWorkingData1. Unexpected input. \'" <<
  707.             c << "\'\n";
  708.         endsec = 1;
  709.         return instance_count;
  710.         }
  711.  
  712.       switch (inst_state)  
  713.         {
  714.           case  noStateSE:
  715.             SkipInstance(in,tmpbuf);
  716.         cerr << "Error: in ReadWorkingData1.\n\tunexpected character was: " << c << "\n\tattempt to recover, data lost: " << tmpbuf << "\n";
  717.         break;
  718.         
  719.           case  deleteSE:
  720.         // things marked for deletion are deleted
  721.         SkipInstance(in,tmpbuf);
  722.         break;
  723.     
  724.           default:  // everything else is created
  725.         obj = CreateInstance (in);
  726.         if (obj != ENTITY_NULL) 
  727.           {
  728.               if (obj->Error().severity() < SEVERITY_WARNING) 
  729.             { ++_errorCount; }
  730.               else if (obj->Error().severity() < SEVERITY_NULL) 
  731.             { ++_warningCount; }
  732.               instances ().Append(obj, inst_state);
  733.               ++instance_count;
  734.           }
  735.         else { ++_errorCount; }
  736.  
  737.         break;
  738.         }
  739.       }
  740.     
  741.     return instance_count;
  742. }
  743.  
  744. /******************************************************************
  745.  ** Procedure:  ReadData2
  746.  ** Parameters:  istream
  747.  ** Returns:  number of valid instances read
  748.  ** Description:  reads in the data portion of the instances 
  749.  **               in an exchange file
  750.  ******************************************************************/
  751.  
  752. int
  753. STEPfile::ReadData2 (istream& in)
  754. {
  755.     _errorCount = 0;  // reset error count
  756.     _warningCount = 0;  // reset error count
  757.     char c;
  758.     int valid_insts =0;
  759.     STEPentity * obj = ENTITY_NULL;
  760.  
  761.     ReadTokenSeparator(in);
  762.  
  763.     in >> c ;
  764.     
  765.     //  PASS 2:  read data 
  766.     while (c == ENTITY_NAME_DELIM && in.good ()) 
  767.       {
  768.       obj =  ReadInstance (in);
  769.       if (_errorCount > _maxErrorCount) 
  770.         {
  771.         _error.AppendToUserMsg("Warning: Too Many Errors in File. Read function aborted.\n");
  772.         cerr << Error().UserMsg();
  773.         cerr << Error().DetailMsg();
  774.         Error().ClearErrorMsg();
  775.         Error().severity(SEVERITY_EXIT);
  776.         return valid_insts;
  777.         }
  778.  
  779.       if (obj == ENTITY_NULL)
  780.         ++_warningCount;  // the object doesn\'t exist
  781.       else if (obj->Error().severity() != SEVERITY_NULL) 
  782.             // there was a problem in the instance
  783.         ++_errorCount;
  784.       else  
  785.         //  the instance is ok
  786.         ++valid_insts;
  787.       
  788.       ReadTokenSeparator (in);
  789.       in.get (c);
  790.       }
  791.     in.putback(c);  
  792.     return valid_insts;
  793. }
  794.  
  795. int
  796. STEPfile::ReadWorkingData2 (istream& in)
  797. {
  798.     _errorCount = 0;  // reset error count
  799.     _warningCount = 0;  // reset error count
  800.     
  801.     char c;
  802.     SCLstring tmpbuf;
  803.     int total_instances =0;
  804.     STEPentity * obj = ENTITY_NULL;
  805.  
  806.     //  PASS 2:  read data 
  807.     int endsec = 0;
  808.     while (!endsec) 
  809.       {
  810.       //check error count
  811.       if (_errorCount > _maxErrorCount) 
  812.         {
  813.         cerr << 
  814.         "Warning: Too Many Errors in File. Read function aborted.\n";
  815.         cerr << Error().UserMsg();
  816.         cerr << Error().DetailMsg();
  817.         Error().ClearErrorMsg();
  818.         Error().severity(SEVERITY_EXIT);
  819.         return total_instances;
  820.         }
  821.  
  822.       ReadTokenSeparator (in);
  823.       in.get(c);
  824.       
  825.       switch (c) 
  826.         {
  827.           case wsSaveComplete:
  828.           case wsSaveIncomplete:
  829.           case wsNew:
  830.         ReadTokenSeparator (in);
  831.         //read in the '#'
  832.         in.get(c);
  833.         
  834.         obj = ReadInstance (in);
  835.         if (obj != ENTITY_NULL)
  836.           {
  837.               if (obj->Error().severity() < SEVERITY_WARNING) 
  838.             { ++_errorCount; }
  839.               else if (obj->Error().severity() < SEVERITY_NULL) 
  840.             { ++_warningCount; }
  841.               ++total_instances;
  842.           }
  843.         else 
  844.           { ++_errorCount; }
  845.         break;
  846.  
  847.           case wsDelete:
  848.         // things marked for deletion are deleted
  849.         SkipInstance(in,tmpbuf);
  850.         break;
  851.         
  852.           case 'E':
  853.         //should be  "ENDSEC;"
  854.         endsec = 1;
  855.         in.putback(c);
  856.         return total_instances;
  857.  
  858.           default:
  859.         tmpbuf.Append ("Error: in ReadWorkingData2.\n\tUnexpected character in input: \'");
  860.         tmpbuf.Append (c);
  861.         tmpbuf.Append ("\'.\n");
  862.         _error.AppendToUserMsg(tmpbuf);
  863.         return total_instances;
  864.         }
  865.       }
  866.     return total_instances;
  867. }
  868.  
  869.  
  870. int
  871. STEPfile::FindDataSection (istream& in)  
  872. {
  873.     char buf[BUFSIZ];
  874.     char *b = buf;
  875.     *b = '\0';
  876.  
  877.     ReadTokenSeparator(in);
  878.     //  find the data section
  879.     while ( !(b = strstr (buf, "DATA")))  
  880.       { 
  881.       if (in.eof()) 
  882.         {
  883.         _error.AppendToUserMsg("Can't find \"DATA;\" section.");
  884.         return 0; //ERROR_WARNING
  885.         }
  886.       in.getline (buf, BUFSIZ, ';'); // reads but does not store the ;
  887.       }
  888.     return 1;
  889. }
  890.  
  891. int
  892. STEPfile::FindHeaderSection (istream& in)  
  893. {
  894.     char buf[BUFSIZ];
  895.     char *b = buf;
  896.     int rval =0;
  897.     
  898.     *b = '\0';
  899.     
  900.     ReadTokenSeparator(in);
  901.     //  find the header section
  902.     while ( !(b = strstr (buf, "HEADER")))  
  903.     { 
  904.     if (in.eof()) 
  905.     {
  906.         _error.AppendToUserMsg(
  907.             "Error: Unable to find HEADER section. File not read.\n");
  908.         _error.GreaterSeverity(SEVERITY_INPUT_ERROR);
  909.         return 0;
  910.     }
  911.     in.getline(buf, BUFSIZ, ';'); // reads but does not store the ;
  912.     }
  913.     return 1;
  914. }
  915.  
  916. /******************************
  917. This function recursively reads through token separators
  918. from an istream. It returns a value of zero when a token
  919. separator is not the next thing on the istream.
  920. The token separators are blanks, explicit print control directives,
  921. and comments.
  922. Part 21 considers the blank to be the space character, 
  923. but this function considers blanks to be the return value of isspace(c)
  924. ******************************/
  925. int
  926. STEPfile::ReadTokenSeparator(istream& in)
  927. {
  928.     char c;
  929.     if (in.eof()) 
  930.       {
  931.       //BUG: no error message is reported
  932.       return 0;
  933.       }
  934.     in.get(c);
  935.     if (isspace(c)) return ReadTokenSeparator(in);
  936.     in.putback(c);
  937.     switch (c) 
  938.       {
  939.     case '/':
  940.       in.get(c);
  941.       char d;
  942.       in.get(d);
  943.       if (d == '*') 
  944.         {
  945.         ReadCommentTail (d, in);
  946.         return ReadTokenSeparator(in);
  947.         }
  948.       else 
  949.         {
  950.         in.putback(d);
  951.         in.putback(c);
  952.         return (0);
  953.         }
  954.       
  955.       break;
  956.     case '\\':
  957.       ReadPcd(in);
  958.       return ReadTokenSeparator(in);
  959.     default:
  960.       return (0);
  961.       }
  962. }
  963.  
  964. /***************************
  965. This function returns a null terminated const char* for the
  966. characters read from the istream up to, but not including
  967. the first character found in the set of delimiters, or the 
  968. whitespace character. It leaves the delimiter on the istream.
  969.  
  970. The string is returned in a static buffer, so it will change 
  971. the next time the function is called.
  972.  
  973. Keywords are special strings of characters indicating the instance
  974. of an entity of a specific type. They shall consist of uppercase letters, 
  975. digits, underscore characters, and possibly an exclamation mark. 
  976. The "!" shall appear only once, and only as the first character.
  977. ***************************/
  978. const char* 
  979. STEPfile::GetKeyword(istream& in, const char* delims)
  980. {
  981.     char c;
  982.     int sz = 1;
  983.     static SCLstring str;
  984.  
  985.     str = "";
  986.     in.get(c);
  987.     while (  !((isspace(c)) || (strchr(delims,c)) )  )
  988.       {
  989.       //check to see if the char is valid
  990.       if (!( (isupper(c)) ||
  991.              (isdigit(c)) ||
  992.              (c == '_')   ||
  993.              (c == '-')   ||    //for reading 'ISO-10303-21'
  994.              ((c == '!') && (sz == 1)) ) )
  995.         {
  996.                 cerr << "Error: Invalid character \'" << c <<
  997.             "\' in STEPfile::GetKeyword.\nkeyword was: " <<
  998.             str << "\n";
  999.         _error.GreaterSeverity(SEVERITY_WARNING);
  1000.         in.putback(c);
  1001.         return str;
  1002.         }
  1003.       if (!in.good()) break;  //BUG: should do something on eof()
  1004.       str.Append (c);
  1005.       ++sz;
  1006.       in.get(c);
  1007.       }
  1008.     in.putback(c);
  1009.     return str;
  1010. }
  1011.  
  1012. /*************************** 
  1013. * SkipInstance reads in an instance terminated with \';\'.  it copies
  1014. * what is read to the SCLstring inst.  
  1015. ***************************/
  1016.  
  1017. Severity
  1018. STEPfile::SkipInstance (istream& in, SCLstring&  inst)
  1019. {
  1020.   char c =0;
  1021.  
  1022.   while (in.good ()) {
  1023.     ErrorDescriptor errs;
  1024.     SdaiString tmp;
  1025.     in >> c;
  1026.     switch (c)  {
  1027.     case ';':  //  end of instance reached
  1028.       return SEVERITY_NULL;
  1029.  
  1030.     case '\'':  // get past the string
  1031.       in.putback (c);
  1032.       tmp.STEPread (in, &errs);
  1033.       inst.Append (tmp);
  1034.       break;
  1035.  
  1036.     case '\0':  // problem in input ?
  1037.       return SEVERITY_INPUT_ERROR;
  1038.  
  1039.     default:
  1040.       inst.Append (c);
  1041.     }
  1042.   }
  1043.   return SEVERITY_INPUT_ERROR;
  1044. }
  1045.  
  1046. /***************************
  1047. ***************************/
  1048. void
  1049. STEPfile::ReadComment(istream& in) 
  1050. {
  1051.     char c = '\0';
  1052.     in >> c;
  1053.     while (isspace (c))  in >> c;
  1054.  
  1055.     // it's not a comment
  1056.     if (c != '/')
  1057.       {
  1058.       in.putback(c);
  1059.       return;
  1060.       }
  1061.  
  1062.     in.get(c);
  1063.     if (c != '*')
  1064.       {
  1065.       in.putback ('/');
  1066.       in.putback (c);
  1067.       return;
  1068.       }
  1069.  
  1070.     ReadCommentTail (c, in);
  1071.     ReadWhiteSpace (in);
  1072.     
  1073. }
  1074.  
  1075. /***************************
  1076. ***************************/
  1077. void
  1078. STEPfile::ReadCommentTail(char c, istream& in) 
  1079. {
  1080.     while (c != '*') in.get (c);
  1081.     in.get(c);
  1082.     if (c == '/') return;
  1083.     else ReadCommentTail(c, in);
  1084. }    
  1085.  
  1086. /***************************
  1087.  ** Read a Print Control Directive from the istream
  1088.  ** "\F\" == formfeed
  1089.  ** "\N\" == newline
  1090.  ***************************/
  1091. Severity
  1092. STEPfile::ReadPcd(istream& in) 
  1093. {
  1094.     char c;
  1095.     in.get(c);
  1096.     if (c == '\\') { 
  1097.     in.get(c);
  1098.     if (c == 'F' || c == 'N') 
  1099.       {
  1100.           in.get(c);
  1101.           if (c == '\\') { in.get(c); return SEVERITY_NULL; }
  1102.       }
  1103.     }
  1104.     cerr << "Print control directive expected.\n";
  1105.     return SEVERITY_WARNING;
  1106. }
  1107.  
  1108.  
  1109. /***************************
  1110.  description:
  1111.     This function creates an instance based on the KEYWORD
  1112.     read from the istream.
  1113.     It expects an ENTITY_NAME (int) from the first set of
  1114.     characters on the istream. If the (int) is not found,
  1115.     ENTITY_NULL is returned.
  1116.  
  1117.   side effects:
  1118.     The function leaves the istream set to the end of the stream 
  1119.     of characters representing the ENTITY_INSTANCE. It attempts to
  1120.     recover on errors by reading up to and including the next ';'.
  1121.  
  1122. an ENTITY_INSTANCE consists of:
  1123.    '#'(int)'=' [SCOPE] SIMPLE_RECORD ';' ||
  1124.    '#'(int)'=' [SCOPE] SUBSUPER_RECORD ';'
  1125. The '#' is read from the istream before CreateInstance is called.
  1126. ***************************/
  1127. STEPentity *
  1128. STEPfile::CreateInstance(istream& in) 
  1129. {
  1130.     char errbuf[BUFSIZ];
  1131.     SCLstring tmpbuf;
  1132.     char objnm [BUFSIZ];
  1133.     char c;
  1134.     int fileid = -1;
  1135.     STEPentityH * scopelist =0;
  1136.     int n =0;
  1137.     STEPentity* obj;
  1138.  
  1139.     ReadTokenSeparator(in);
  1140.     
  1141.     in >> fileid;
  1142.     fileid = IncrementFileId(fileid);
  1143.     if (instances ().FindFileId(fileid)) 
  1144.       {
  1145.     SkipInstance(in, tmpbuf);
  1146.       cerr <<  "ERROR: instance with id: " << fileid <<
  1147.           " already exists.\n\tdata lost: " << tmpbuf << "\n";
  1148.       return ENTITY_NULL;
  1149.       }
  1150.     
  1151.     ReadTokenSeparator(in);
  1152.     
  1153.     in.get (c);
  1154.     if (c != '=') 
  1155.       {
  1156.       //ERROR: '=' expected
  1157.     SkipInstance(in, tmpbuf);
  1158.       sprintf(errbuf,
  1159.          "ERROR: instance #%d. \'=\' expected.\n\tdata lost: %s\n",
  1160.          fileid, (const char *) tmpbuf);
  1161.       _error.AppendToUserMsg(errbuf);
  1162.       return ENTITY_NULL;
  1163.       }
  1164.  
  1165.     ReadTokenSeparator(in);
  1166.  
  1167.     //peek at the next character on the istream
  1168.     in.get(c);
  1169.     in.putback(c);
  1170.     
  1171.     //check for optional "&SCOPE" construct
  1172.     if (c == '&') 
  1173.       {
  1174.     Severity s = CreateScopeInstances(in, &scopelist);
  1175.       if (s < SEVERITY_WARNING) 
  1176.         {  return ENTITY_NULL;  }
  1177.       ReadTokenSeparator(in);
  1178.       in.get(c);
  1179.       in.putback(c);
  1180.       }
  1181.  
  1182.     //check for subtype/supertype record
  1183.     if (c == '(') 
  1184.       {  //  TODO:  implement complex inheritance
  1185.       CreateSubSuperInstance(in,fileid);
  1186.       ReadTokenSeparator(in);
  1187.       in.get(c);
  1188.       in.putback(c);
  1189.       return ENTITY_NULL;
  1190.       }
  1191.  
  1192.     // check for User Defined Entity
  1193.     int userDefined = 0;
  1194.     if (c == '!') 
  1195.       {
  1196.       userDefined = 1;
  1197.       in.get(c);
  1198.       }
  1199.     
  1200.     // read keyword (entity type name)
  1201.     //keywd = GetKeyword(in,"(",BUFSIZ);
  1202.     in.get(c);
  1203.     while (c != '(') // reads in object name including any white space
  1204.       {
  1205.       objnm [n++] = c;
  1206.       in.get (c);
  1207.       }
  1208.     objnm [n] = '\0';
  1209.     while (isspace (objnm[--n])) objnm[n] = '\0';
  1210.     n = 0;
  1211.     
  1212.     //create the instance using the Registry object
  1213.     if (userDefined) 
  1214.       {
  1215.     SkipInstance(in, tmpbuf);
  1216.       cerr << "Warning: #" << fileid << ". User Defined Entity in DATA section ignored.\n\tdata lost: \'!" << objnm << "\': " << tmpbuf << "\n";
  1217.       return ENTITY_NULL;
  1218.       }
  1219.     else 
  1220.       {
  1221.       obj = reg ().ObjCreate (objnm);
  1222.       }
  1223.     
  1224.     if (obj == ENTITY_NULL) 
  1225.       {
  1226.       // above the stream was read until the open paren was found so
  1227.       // put it back for the error message.
  1228.       in.putback(c);
  1229.       SkipInstance(in, tmpbuf);
  1230.       cerr << "ERROR:  ENTITY #" << fileid
  1231.            << ".  Unknown ENTITY type \'" 
  1232.           << objnm << "\'.\n\tdata lost: " << tmpbuf << "\n\n";
  1233.       return ENTITY_NULL;
  1234.       }
  1235.     obj -> STEPfile_id = fileid;
  1236.     AppendEntityErrorMsg( &(obj->Error()) );
  1237.     
  1238.     //  scan values
  1239.     SkipInstance(in, tmpbuf);
  1240.     
  1241.     ReadTokenSeparator (in);
  1242.     return obj;
  1243. }    
  1244.  
  1245.  
  1246. /**************************************************
  1247.  description:
  1248.     This function reads the SCOPE list for an entity instance,
  1249.     creates each instance on the scope list, and appending each
  1250.     instance to the instance manager.
  1251.  side-effects:
  1252.     It first searches for "&SCOPE" and reads all characters
  1253.     from the istream up to and including "ENDSCOPE"
  1254.  returns: ErrorDescriptor
  1255.     >= SEVERITY_WARNING: the istream was read up to and including the
  1256.                       "ENDSCOPE" and the export list /#1, ... #N/
  1257.     <  SEVERITY_WARNING: the istream was read up to and including the next ";"
  1258.     < SEVERITY_BUG: fatal
  1259. **************************************************/
  1260. Severity
  1261. STEPfile::CreateScopeInstances(istream& in, STEPentityH ** scopelist)
  1262. {
  1263.     Severity rval = SEVERITY_NULL;
  1264.     STEPentity * se;
  1265.     char errbuf[BUFSIZ];
  1266.     SCLstring tmpbuf;
  1267.     char c;
  1268.     int exportid;
  1269.     STEPentityH inscope [BUFSIZ];  int i =0;
  1270.     SCLstring keywd;    
  1271.  
  1272.     keywd = GetKeyword(in," \n\t/\\#;");
  1273.     if (strncmp(keywd,"&SCOPE",6)) 
  1274.       {
  1275.     //ERROR: "&SCOPE" expected
  1276.     //TODO: should attempt to recover by reading through ENDSCOPE
  1277.     //currently recovery is attempted by reading through next ";" 
  1278.     SkipInstance(in, tmpbuf);
  1279.     cerr << "ERROR: " << "\'&SCOPE\' expected." <<
  1280.       "\n\tdata lost: " << tmpbuf << "\n";
  1281.     return SEVERITY_INPUT_ERROR;
  1282.       }
  1283.  
  1284.     ReadTokenSeparator(in);
  1285.     
  1286.     in.get(c);
  1287.     while (c == '#') 
  1288.       {
  1289.     se = CreateInstance (in);
  1290.     if (se != ENTITY_NULL) 
  1291.       {
  1292.         //TODO:  apply scope information to se
  1293.         //  Add se to scopelist
  1294.         if (i < BUFSIZ) {
  1295.           inscope [i] = se;
  1296.           ++i;
  1297.         }
  1298.         //append the se to the instance manager
  1299.         instances ().Append (se,newSE);
  1300.       }
  1301.     else 
  1302.       {
  1303.         //ERROR: instance in SCOPE not created
  1304.         rval = SEVERITY_WARNING;
  1305.         SkipInstance(in, tmpbuf);
  1306.         cerr << "instance in SCOPE not created.\n\tdata lost: " 
  1307.          << tmpbuf << "\n";
  1308.         ++_errorCount;
  1309.       }
  1310.       
  1311.       ReadTokenSeparator(in);
  1312.       in.get(c);
  1313.       }
  1314.     in.putback(c);
  1315.     *scopelist = new STEPentityH [i];
  1316.     while (i > 0)  *scopelist [--i] = inscope [i];
  1317.  
  1318.     //check for "ENDSCOPE"
  1319.     keywd = GetKeyword(in," \t\n/\\#;"); 
  1320.     if (strncmp(keywd,"ENDSCOPE",8)) 
  1321.       {
  1322.       //ERROR: "ENDSCOPE" expected
  1323.     SkipInstance(in, tmpbuf);
  1324.     cerr << "ERROR: " << "\'ENDSCOPE\' expected."
  1325.          << "\n\tdata lost: " << tmpbuf << "\n";
  1326.     ++_errorCount;
  1327.     return SEVERITY_INPUT_ERROR;
  1328.       }
  1329.  
  1330.     //check for export list
  1331.     ReadTokenSeparator(in);
  1332.     in.get(c);
  1333.     in.putback (c);
  1334.     if (c == '/') 
  1335.       {
  1336.       //read export list
  1337.       in.get(c);
  1338.       c = ',';
  1339.       while (c == ',') 
  1340.         {
  1341.         ReadTokenSeparator(in);
  1342.         in.get(c);
  1343.         if (c!='#')  {  } //ERROR
  1344.         in >> exportid;
  1345.         //TODO: nothing is done with the idnums on the export list
  1346.         ReadTokenSeparator(in);
  1347.         in.get(c);
  1348.         }
  1349.       if (c != '/') 
  1350.         {
  1351.         //ERROR: '/' expected while reading export list
  1352.           SkipInstance(in, tmpbuf);
  1353.           cerr << "ERROR:  \'/\' expected in export list.\n\tdata lost: " << tmpbuf << "\n";
  1354.           ++_errorCount;
  1355.           rval =  SEVERITY_INPUT_ERROR;
  1356.         }
  1357.       ReadTokenSeparator(in);
  1358.       }
  1359.     return rval;    
  1360. }
  1361.  
  1362. Severity
  1363. STEPfile::CreateSubSuperInstance(istream& in, int fileid)
  1364. {
  1365.   SCLstring tmpstr;
  1366.     char errbuf[BUFSIZ];
  1367.   SkipInstance(in, tmpstr);
  1368.     sprintf(errbuf,"ERROR: ENTITY #%d. \n"
  1369.         "  Reading of subtype/supertype instance not yet implemented.\n"
  1370.         "  Instance ignored.  Data lost: \n\t%s\n",
  1371.         fileid,(const char *) tmpstr);
  1372.     cerr << errbuf;
  1373.     return SEVERITY_WARNING;
  1374. }
  1375.  
  1376. /**************************************************
  1377.  description:
  1378.     This function reads the SCOPE list for an entity instance,
  1379.     and reads the values for each instance from the istream.
  1380.  side-effects:
  1381.     It first searches for "&SCOPE" and reads all characters
  1382.     from the istream up to and including "ENDSCOPE"
  1383. **************************************************/
  1384. Severity
  1385. STEPfile::ReadScopeInstances (istream& in)
  1386. {
  1387.     Severity rval = SEVERITY_NULL;
  1388.     STEPentity * se;
  1389.     SCLstring tmpbuf;
  1390.     char c;
  1391.     int exportid;
  1392.     SCLstring keywd;    
  1393.     
  1394.     keywd = GetKeyword(in," \n\t/\\#;");
  1395.     if (strncmp(keywd,"&SCOPE",6)) 
  1396.       {
  1397.       //ERROR: "&SCOPE" expected
  1398.     SkipInstance(in, tmpbuf);
  1399.     cerr << "\'&SCOPE\' expected.\n\tdata lost: " << tmpbuf << "\n";
  1400.     ++_errorCount;
  1401.     return SEVERITY_WARNING;
  1402.       }
  1403.  
  1404.     ReadTokenSeparator(in);
  1405.     
  1406.     in.get(c);
  1407.     while (c == '#') 
  1408.       {
  1409.       se = ReadInstance (in);
  1410.       if (se != ENTITY_NULL) 
  1411.         {
  1412.         //apply scope information to se
  1413.         //TODO: not yet implemented
  1414.         }
  1415.       else 
  1416.         {
  1417.         //ERROR: unable to read instance in SCOPE
  1418.         rval = SEVERITY_WARNING;
  1419.         }
  1420.       
  1421.       ReadTokenSeparator(in);
  1422.       in.get(c);
  1423.       }
  1424.     in.putback(c);
  1425.     
  1426.     //check for "ENDSCOPE"
  1427.     keywd = GetKeyword(in," \t\n/\\#;");
  1428.     if (strncmp(keywd,"ENDSCOPE",8)) 
  1429.       {
  1430.     //ERROR: "ENDSCOPE" expected
  1431.     SkipInstance(in, tmpbuf);
  1432.     cerr << " \'ENDSCOPE\' expected.\n\tdata lost: " << tmpbuf << "\n";
  1433.     ++_errorCount;
  1434.     return SEVERITY_WARNING;
  1435.       }
  1436.  
  1437.     //check for export list
  1438.     ReadTokenSeparator(in);
  1439.     in.get(c);
  1440.     in.putback (c);
  1441.     if (c == '/') 
  1442.       {
  1443.       //read through export list
  1444.       in.get(c);  c = ',';
  1445.       while (c == ',') 
  1446.         {
  1447.         ReadTokenSeparator(in);
  1448.         in.get(c);
  1449.         in >> exportid;
  1450.         ReadTokenSeparator(in);
  1451.         in.get(c);
  1452.         }
  1453.       if (c != '/') 
  1454.         {
  1455.         //ERROR: '/' expected while reading export list
  1456.           SkipInstance(in, tmpbuf);
  1457.           cerr << " \'/\' expected while reading export list.\n\tdata lost: "
  1458.            << tmpbuf << "\n";
  1459.           ++_errorCount;
  1460.           rval =  SEVERITY_WARNING;
  1461.         }
  1462.       ReadTokenSeparator(in);
  1463.       }
  1464.     return rval;
  1465. }
  1466.  
  1467. Severity
  1468. STEPfile::ReadSubSuperInstance (istream& in)
  1469. {
  1470.   SCLstring tmp;
  1471.   SkipInstance(in, tmp);
  1472.   return SEVERITY_NULL;
  1473. }
  1474.  
  1475.     
  1476.  
  1477.  
  1478. /*****************************************************
  1479.  description:
  1480.  This function populates a STEPentity with the values read from 
  1481.  the istream.
  1482.  
  1483.  This function must keeps track of error messages encountered when
  1484.  reading the STEPentity. It passes STEPentity error information onto
  1485.  the STEPfile ErrorDescriptor.
  1486. *****************************************************/
  1487. STEPentity *
  1488. STEPfile::ReadInstance(istream& in)
  1489. {
  1490.     Severity sev = SEVERITY_NULL;
  1491.     char errbuf[BUFSIZ];
  1492.     SCLstring tmpbuf;
  1493.     char objnm [BUFSIZ];
  1494.     char c;
  1495.     int fileid;
  1496.     int n =0;
  1497.     STEPentity* obj = ENTITY_NULL;
  1498.  
  1499.     ReadComment(in);
  1500.     
  1501.     in >> fileid;
  1502.     fileid = IncrementFileId(fileid);
  1503.  
  1504.     //  check to see that instance was created on PASS 1
  1505.     MgrNode * node = instances ().FindFileId(fileid);
  1506.     if ((!node) || ((obj =  node -> GetSTEPentity ()) == ENTITY_NULL))
  1507.       {
  1508.     SCLstring strbuf;
  1509.       SkipInstance(in, strbuf);
  1510.       cerr << "\nWARNING: in 2nd pass instance #" << fileid <<
  1511.           " not found.\n";
  1512.       return ENTITY_NULL;
  1513.       }
  1514.     else if ((_fileType != WORKING_SESSION) && (node->CurrState() != newSE))
  1515.       {
  1516.     SCLstring strbuf;
  1517.     SkipInstance(in,strbuf);
  1518.       cerr << "Ignoring duplicate instance with id: " << fileid <<
  1519.           ".\n\tdata lost: " << strbuf << "\n";
  1520.       return ENTITY_NULL;
  1521.       }
  1522.     
  1523.     ReadTokenSeparator(in);
  1524.     
  1525.     in.get (c);
  1526.     if (c != '=') 
  1527.       {
  1528.       //ERROR: '=' expected
  1529.     SkipInstance(in, tmpbuf);
  1530.       sprintf(errbuf,
  1531.       "Error reading instance #%d. \'=\' expected.\n\tdata lost: %s\n",
  1532.           fileid, (const char *) tmpbuf);
  1533.       _error.AppendToUserMsg(errbuf);
  1534.       return ENTITY_NULL;
  1535.       }
  1536.  
  1537.     ReadTokenSeparator(in);
  1538.  
  1539.     //peek at the next character on the istream
  1540.     in.get(c);
  1541.     in.putback(c);
  1542.  
  1543.     //check for optional "&SCOPE" construct
  1544.     if (c == '&') 
  1545.       {
  1546.       ReadScopeInstances(in);
  1547.       ReadTokenSeparator(in);
  1548.       in.get(c);
  1549.       in.putback(c);
  1550.       }
  1551.  
  1552.     //check for subtype/supertype record
  1553.     if (c == '(') 
  1554.       {
  1555.       STEPentity* subse = 0;
  1556.       //TODO: this function is not working
  1557.       ReadSubSuperInstance(in);
  1558.       return ENTITY_NULL;
  1559.       }
  1560.  
  1561.     ReadTokenSeparator(in);
  1562.     in.get(c);
  1563.     
  1564.     // check for User Defined Entity
  1565.     int userDefined = 0;
  1566.     if (c == '!') { userDefined = 1; in.get(c);   }
  1567.     
  1568.     
  1569.     // read entity name
  1570.     while (c != '(') // reads in object name including any white space
  1571.       {
  1572.       objnm [n++] = c;
  1573.       in.get (c);
  1574.       }
  1575.     objnm [n] = '\0';
  1576.     while (isspace (objnm[--n])) objnm[n] = '\0';
  1577.  
  1578.     int idIncrNum = FileIdIncr();
  1579.  
  1580.     //  read values
  1581.     if (userDefined) 
  1582.       {
  1583.     SkipInstance(in, tmpbuf);
  1584.       cerr << "WARNING: #" << fileid << 
  1585.           ". Ignoring User defined entity.\n\tdata lost: !"
  1586.           << objnm << tmpbuf << "\n";
  1587.       ++_warningCount;
  1588.       return ENTITY_NULL;
  1589.       }
  1590.     
  1591.     // NOTE: this function is called for all FileTypes 
  1592.     // (WORKING_SESSION included)
  1593.  
  1594.     sev = obj->STEPread (fileid, idIncrNum, &instances (), in);
  1595.     AppendEntityErrorMsg( &(obj->Error()) );
  1596.  
  1597.     if (obj == ENTITY_NULL) 
  1598.       {
  1599.       node->ChangeState(noStateSE);
  1600.       // unable to read entity 
  1601.       return ENTITY_NULL;
  1602.       }
  1603.  
  1604.     //set the node's state, 
  1605.     //and set the STEPfile:_error (based on the type of file being read)
  1606.     switch (sev) 
  1607.       {
  1608.     case SEVERITY_NULL:
  1609.     case SEVERITY_USERMSG:
  1610.       node->ChangeState(completeSE);
  1611.       break;
  1612.       
  1613.     case SEVERITY_WARNING:
  1614.     case SEVERITY_INPUT_ERROR:
  1615.     case SEVERITY_BUG:
  1616.  
  1617.     case SEVERITY_INCOMPLETE:
  1618.       if( (_fileType == VERSION_CURRENT) || (_fileType == VERSION_OLD) ) 
  1619.         {
  1620.         cerr << "ERROR in EXCHANGE FILE: incomplete instance #" 
  1621.              << obj -> STEPfile_id << ".\n";
  1622.         node->ChangeState(incompleteSE);
  1623.         }
  1624.       else 
  1625.         {
  1626.         if (node->CurrState() == completeSE) 
  1627.           {
  1628.               sprintf(errbuf,"WARNING in WORKING FILE: changing instance #%d state from completeSE to incompleteSE.\n",fileid);
  1629.               _error.AppendToUserMsg(errbuf);
  1630.               node->ChangeState(incompleteSE);
  1631.           }
  1632.         }
  1633.       break;
  1634.       
  1635.     case SEVERITY_EXIT:
  1636.     case SEVERITY_DUMP:
  1637.     case SEVERITY_MAX:
  1638.       node->ChangeState(noStateSE);
  1639.       break;
  1640.       
  1641.     default:
  1642.       break;
  1643.       }
  1644.  
  1645.     // check ErrorDesc severity and set the state for MgrNode *node
  1646.     // according to completeSE or incompleteSE
  1647.     // watch how you set it based on whether you are reading an 
  1648.     // exchange or working file.
  1649.     
  1650.     return obj;
  1651.     
  1652. }
  1653.  
  1654.  
  1655.  
  1656. /******************************************************
  1657. This function uses the C library function system to issue
  1658. a shell command which checks for the existence of the 
  1659. file name and creates a backup file if the file exists.
  1660. The system command takes a string, which must be a valid
  1661. sh command. The command is:
  1662.    if (test -f filename) then mv filename filename.bak; fi
  1663.  
  1664. BUG: doesn't check to see if the backup command works.
  1665.      the results of the system call are not used by the
  1666.      by this function
  1667. ******************************************************/
  1668. void
  1669. STEPfile::MakeBackupFile() 
  1670. {
  1671.   static int i =1;
  1672.     char backup_call [2*BUFSIZ];
  1673.     char backup_file [BUFSIZ];
  1674.  
  1675. //  sprintf (backup_file, "%s.%d", FileName(), ++i);
  1676.   sprintf (backup_file, "%s.bak", FileName());
  1677.  
  1678.   sprintf (backup_call, 
  1679.        "if ( %s )"
  1680.        " then copy %s %s ;",
  1681.        FileName(),
  1682.        FileName(), backup_file);
  1683.  
  1684. //  if (i > 4)   
  1685. //    sprintf (backup_call + strlen (backup_call), "rm %s.%d ; ", FileName (), i -2);
  1686.   
  1687.   _error.AppendToDetailMsg ("Making backup file: ");
  1688.   _error.AppendToDetailMsg (backup_file);
  1689.     _error.AppendToDetailMsg("\n");
  1690.     
  1691. /*
  1692.     strcpy (backup_call, "if (test -f ");
  1693.     strcat (backup_call, FileName());
  1694.     strcat (backup_call, ") then mv ");
  1695.     strcat (backup_call, FileName());
  1696.     strcat (backup_call, " ");
  1697.     strcat (backup_call, FileName());
  1698.     strcat (backup_call, ".bak ; fi ", ++i);
  1699.  
  1700.     _error.AppendToDetailMsg("Making backup file: executing system call:\n\t");
  1701.     _error.AppendToDetailMsg(backup_call);
  1702.     _error.AppendToDetailMsg("\n");
  1703.     system(backup_call);
  1704.     */
  1705. }
  1706.     
  1707.  
  1708. /***************************
  1709. ***************************/
  1710. Severity
  1711. STEPfile::WriteExchangeFile(ostream& out, int validate) 
  1712. {
  1713.     Severity rval = SEVERITY_NULL;
  1714.     SetFileType(VERSION_CURRENT);
  1715.     _error.ClearErrorMsg();
  1716.  
  1717.     if (validate) {
  1718.     rval = instances ().VerifyInstances(_error);
  1719.     _error.GreaterSeverity(rval);
  1720.     if (rval < SEVERITY_USERMSG) 
  1721.       {
  1722.           _error.AppendToUserMsg("Unable to verify instances. File not written. Try saving as working session file.");
  1723.           _error.GreaterSeverity(SEVERITY_INCOMPLETE);
  1724.           return rval;
  1725.       }
  1726.     }
  1727.     
  1728.     out << FILE_DELIM << "\n";
  1729.     WriteHeader(out);
  1730.     WriteData(out);
  1731.     out << END_FILE_DELIM << "\n";
  1732.     return rval;
  1733. }
  1734.  
  1735. /***************************
  1736. ***************************/
  1737. Severity
  1738. STEPfile::WriteExchangeFile(const char* filename, int validate)
  1739. {
  1740.     Severity rval = SEVERITY_NULL;
  1741.     
  1742.     if (validate) {
  1743.     rval = instances ().VerifyInstances(_error);
  1744.     _error.GreaterSeverity(rval);
  1745.     if (rval < SEVERITY_USERMSG) 
  1746.       {
  1747.           _error.AppendToUserMsg("Unable to verify instances. File wasn't opened. Try saving as working session file.\n");
  1748.           _error.GreaterSeverity(SEVERITY_INCOMPLETE);
  1749.           return rval;
  1750.       }
  1751.     }
  1752.     
  1753.     ostream* out =  OpenOutputFile(filename);
  1754.     if (_error.severity() < SEVERITY_WARNING) return _error.severity();
  1755.     rval = WriteExchangeFile(*out, 0);
  1756.     CloseOutputFile(out);
  1757.     return rval;
  1758.  
  1759. /***************************
  1760. This function returns an integer value for
  1761. the file id for a header section entity,
  1762. based on a given entity name.
  1763.  
  1764. This function may change the value of the 
  1765. STEPfile member variable: _headerId
  1766.  
  1767. The header section entities must be numbered in the following manner:
  1768.  
  1769. #1=FILE_NAME
  1770. #2=FILE_DESCRIPTION
  1771. #3=FILE_SCHEMA
  1772. #4=CLASSIFICATION
  1773. ***************************/
  1774. int
  1775. STEPfile::HeaderId (const char* name)
  1776. {
  1777. /* // default initialization doesn't work DAS PORT
  1778.     char* nms[3] = { 
  1779.     "FILE_DESCRIPTION\0",
  1780.     "FILE_NAME\0",
  1781.     "FILE_SCHEMA\0",
  1782.     };
  1783. */
  1784.     const char* nms[3];
  1785.     nms[0] = "FILE_DESCRIPTION";
  1786.     nms[1] = "FILE_NAME";
  1787.     nms[2] = "FILE_SCHEMA";
  1788.     nms[3] = 0;
  1789.     
  1790.     SCLstring tmp;
  1791.     for (register int i = 0; i < 3; ++i)
  1792.     {
  1793.     if (!strcmp( (char *)StrToUpper( name, tmp ), nms[i] ) )
  1794.         return i;
  1795.     }
  1796.     return ++_headerId;
  1797. }    
  1798.  
  1799. /***************************
  1800. ***************************/
  1801. int
  1802. STEPfile::HeaderIdOld (const char* name)
  1803. {
  1804. /*
  1805.     char* nms[5] = 
  1806.       {
  1807.       "FILE_IDENTIFICATION\0", 
  1808.       "FILE_DESCRIPTION\0",
  1809.       "IMP_LEVEL\0",
  1810.       "CLASSIFICATION\0",
  1811.       "MAXSIG\0"
  1812.       };
  1813. */
  1814.     const char* nms[5];
  1815.     nms[0] = "FILE_IDENTIFICATION", 
  1816.     nms[1] = "FILE_DESCRIPTION";
  1817.     nms[2] = "IMP_LEVEL";
  1818.     nms[3] = "CLASSIFICATION";
  1819.     nms[4] = "MAXSIG";
  1820.     
  1821.     SCLstring tmp;
  1822.     for (register int i=0; i<5; ++i)
  1823.       {
  1824.       if (!strcmp( (char *)StrToUpper( name, tmp ), nms[i] ) )
  1825.           return ++i;
  1826.       }
  1827.     return ++_headerId;
  1828. }    
  1829.  
  1830.  
  1831. /***************************
  1832. ***************************/
  1833. void
  1834. STEPfile::WriteHeader(ostream& out) 
  1835. {
  1836.     out << "HEADER;\n";
  1837.  
  1838.     WriteHeaderInstanceFileDescription(out);
  1839.     WriteHeaderInstanceFileName(out);
  1840.     WriteHeaderInstanceFileSchema(out);
  1841.     
  1842.     // Write the rest of the header instances
  1843.     STEPentity* se;
  1844.     int n = _headerInstances->InstanceCount();
  1845.     for (register int i =0; i < n; ++i) 
  1846.       {
  1847.       se = (*_headerInstances)[i]->GetSTEPentity();
  1848.       if (!((se->FileId() == HeaderId("File_Name")) ||
  1849.           (se->FileId() == HeaderId("File_Description")) ||
  1850.           (se->FileId() == HeaderId("File_Schema"))))
  1851.           WriteHeaderInstance((*_headerInstances)[i] -> GetSTEPentity(), out );
  1852.       }
  1853.     out << "ENDSEC;\n";
  1854. }
  1855.  
  1856. /***************************
  1857. ***************************/
  1858. void
  1859. STEPfile::WriteHeaderInstance(STEPentity* obj, ostream& out)
  1860. {
  1861.     SCLstring tmp;
  1862.     out << StrToUpper( obj->EntityName(), tmp ) << "(";
  1863.     int n = obj->attributes.list_length();
  1864.     for (register int i = 0; i < n; ++i) 
  1865.       {
  1866.       (obj->attributes[i]).STEPwrite(out);
  1867.       if (i < n-1) out << ",";
  1868.       }
  1869.     out << ");\n";
  1870. }
  1871.  
  1872. /***************************
  1873. ***************************/
  1874. void
  1875. STEPfile::WriteHeaderInstanceFileName (ostream& out)
  1876. {
  1877. // Get the FileName instance from _headerInstances
  1878.     STEPentity* se = _headerInstances->GetSTEPentity("File_Name",0);
  1879.     if (se == ENTITY_NULL) 
  1880.       {
  1881.       // ERROR: no File_Name instance in _headerInstances
  1882.       // create a File_Name instance
  1883. //      (p21DIS_File_name*)se = HeaderDefaultFileName();
  1884.       se = (STEPentity *)HeaderDefaultFileName();
  1885.       }
  1886.  
  1887. //set some of the attribute values at time of output
  1888.     p21DIS_File_name * fn = (p21DIS_File_name*)se;
  1889.  
  1890. /* I'm not sure this is a good idea that Peter did but I'll leave around - DAS
  1891.     // write time_stamp (as specified in ISO Standard 8601)
  1892.     // output the current system time to the file, using the following format:
  1893.     // example: '1994-04-12 15:27:46'
  1894.     // for Calendar Date, 12 April 1994, 27 minute 46 seconds past 15 hours
  1895. */
  1896.     time_t t = time(NULL);
  1897.     struct tm *timeptr = localtime(&t);
  1898.     char time_buf[26];
  1899.     strftime(time_buf,26,"%Y-%m-%d %H:%M:%S",timeptr);
  1900.     //s_String  s = fn->time_stamp();
  1901.     //strncpy((char*)s,time_buf,27);
  1902.     fn->time_stamp(time_buf);
  1903.  
  1904. //output the values to the file
  1905.     WriteHeaderInstance(se, out);
  1906.     
  1907. }
  1908.  
  1909.  
  1910. /**************************************************
  1911.   DAVE, should this section be deleted now?
  1912.  
  1913.     p21DIS_File_name * fn;
  1914.     int fileid = HeaderId("File_Name");
  1915.     MgrNode * mn = _headerInstances->FindFileId(fileid);
  1916.     if (!mn) 
  1917.     {
  1918.     // ERROR: no File_Name instance in _headerInstances
  1919.     // create a File_Name instance
  1920.     (STEPentity*)fn = HeaderDefaultFileName();
  1921.     }
  1922.     else 
  1923.       {
  1924.       (STEPentity*)fn = _headerInstances->GetSTEPentity(mn);
  1925.       }
  1926.  
  1927. // Write the values for the FileName instance to the ostream    
  1928.     SCLstring tmp;
  1929.     out << StrToUpper (fn->EntityName()) << "(";
  1930.  
  1931.     // write name
  1932.     //out << "\'" << (char*)fn->name() << "\',";
  1933.     STEPstring * s = new STEPstring((char*)fn->name());
  1934.     s->STEPwrite(out);
  1935.     delete s;
  1936.     out << ",";
  1937.  
  1938.     // write time_stamp (as specified in ISO Standard 8601)
  1939.     // output the current system time to the file, using the following format:
  1940.     // example: '1994-04-12 15:27:46'
  1941.     // for Calendar Date, 12 April 1994, 27 minute 46 seconds past 15 hours
  1942.     time_t t = time(NULL);
  1943.     struct tm *timeptr = localtime(&t);
  1944.     char time_buf[26];
  1945.     strftime(time_buf,26,"%Y-%m-%d %H:%M:%S",timeptr);
  1946.     out << '\'' << time_buf << "\',";
  1947.     
  1948.     // write author
  1949.     fn->author().STEPwrite(out);
  1950.     out << ",";
  1951.     
  1952.     // write organization
  1953.     fn->organization().STEPwrite(out);
  1954.     out << ",";
  1955.     
  1956.     // write preprocessor_version
  1957.     s = new STEPstring((char*)fn->preprocessor_version());
  1958.     s->STEPwrite(out);
  1959.     delete s;
  1960.     out << ",";
  1961.     
  1962.     // write originating_system
  1963.     s = new STEPstring((char*)fn->originating_system());
  1964.     s->STEPwrite(out);
  1965.     delete s;
  1966.     out << ",";
  1967.     
  1968.     // write authorization
  1969.     s = new STEPstring((char*)fn->authorization());
  1970.     s->STEPwrite(out);
  1971.     delete s;
  1972.     out << ");\n";
  1973.     
  1974. }
  1975. **************************************************/
  1976.  
  1977.  
  1978. void
  1979. STEPfile::WriteHeaderInstanceFileDescription (ostream& out) 
  1980. {
  1981. // Get the FileDescription instance from _headerInstances
  1982.     STEPentity *se = _headerInstances->GetSTEPentity("File_Description",0);
  1983.     if (se == ENTITY_NULL) 
  1984.       {
  1985.       // ERROR: no File_Name instance in _headerInstances
  1986.       // create a File_Name instance
  1987. //      (s_File_Description*)se = HeaderDefaultFileDescription();
  1988.       se = (STEPentity*)HeaderDefaultFileDescription();
  1989.       }
  1990.  
  1991.     WriteHeaderInstance(se, out);
  1992.     
  1993. /**************************************************
  1994.  
  1995.    p21DIS_File_description * fd;
  1996.     int fileid = HeaderId("File_Description");
  1997.     MgrNode * mn = _headerInstances->FindFileId(fileid);
  1998.     if (!mn) 
  1999.       {
  2000.       // ERROR: no File_Description instance in _headerInstances
  2001.       // create a File_Description instance
  2002.       (STEPentity*)fd = HeaderDefaultFileDescription();
  2003.       }
  2004.     else 
  2005.       {
  2006.       (STEPentity*)fd = _headerInstances->GetSTEPentity(mn);
  2007.       }
  2008. // Write the values for the FileDescription instance to the ostream    
  2009.     out << StrToUpper (fd->EntityName()) << "(";
  2010.  
  2011.     //write description
  2012.     fd->description().STEPwrite(out,&_error,a_16DESCRIPTION);
  2013.     out << ",";
  2014.     
  2015.     //write implementation_level
  2016.     STEPstring *s = new STEPstring((char*)fd->implementation_level());
  2017.     s->STEPwrite(out);
  2018.     delete s;
  2019.     out << ");\n";
  2020.  
  2021. **************************************************/    
  2022. }
  2023.  
  2024. void
  2025. STEPfile::WriteHeaderInstanceFileSchema (ostream& out) 
  2026. {
  2027. // Get the FileName instance from _headerInstances
  2028.     STEPentity *se = _headerInstances->GetSTEPentity("File_Schema",0);
  2029.     if (se == ENTITY_NULL) 
  2030.       {
  2031.       // ERROR: no File_Name instance in _headerInstances
  2032.       // create a File_Name instance
  2033. //      (p21DIS_File_schema*)se = HeaderDefaultFileSchema();
  2034.       se = (STEPentity*) HeaderDefaultFileSchema();
  2035.       }
  2036.  
  2037.     WriteHeaderInstance(se, out);
  2038.  
  2039. /**************************************************    
  2040.  
  2041.     p21DIS_File_schema * fs;
  2042.     int fileid = HeaderId("File_Schema");
  2043.     MgrNode * mn = _headerInstances->FindFileId(fileid);
  2044.     if (!mn) 
  2045.       {
  2046.       // ERROR: no File_Schema instance in _headerInstances
  2047.       // create a File_Schema instance
  2048.       (STEPentity*)fs = HeaderDefaultFileSchema();
  2049.       }
  2050.     else 
  2051.       {
  2052.       (STEPentity*)fs = _headerInstances->GetSTEPentity(mn);
  2053.       }
  2054. // Write the values for the FileName instance to the ostream    
  2055.     out << StrToUpper (fs->EntityName()) << "(";
  2056.  
  2057.     // write schema_identifiers
  2058.     fs->schema_identifiers().STEPwrite(out);
  2059.     out << ");\n";
  2060. **************************************************/
  2061.  
  2062. }
  2063.  
  2064.  
  2065. /***************************
  2066. ***************************/
  2067.  
  2068. void
  2069. STEPfile::WriteData(ostream& out)
  2070. {
  2071.     out << "DATA;\n";
  2072.  
  2073.     int n = instances ().InstanceCount();
  2074.     for (register int i = 0; i < n; ++i) 
  2075.     instances ()[i] -> GetSTEPentity() -> STEPwrite(out);
  2076.       
  2077.     out << "ENDSEC;\n";
  2078. }    
  2079.  
  2080. Severity 
  2081. STEPfile::AppendFile (istream* in) 
  2082. {
  2083.     Severity rval = SEVERITY_NULL;
  2084.     char errbuf[BUFSIZ];
  2085.     
  2086.     SetFileIdIncrement ();
  2087.     int total_insts =0,  valid_insts =0;
  2088.     int exchange_file = -1;
  2089.     
  2090.     ReadTokenSeparator(*in);
  2091.     SCLstring keywd = GetKeyword(*in, "; #");
  2092.     // get the delimiter off the istream
  2093.     char c;
  2094.     in->get(c);
  2095.     
  2096.     if (!strncmp(keywd, "ISO-10303-21",strlen(keywd))) 
  2097.       {
  2098.       exchange_file = 1;
  2099.       SetFileType(VERSION_CURRENT);
  2100.       }
  2101.     else if (!strncmp(keywd, "STEP",strlen(keywd))) 
  2102.       {
  2103.       _error.AppendToUserMsg("Reading Old Version of exchange file.\n");
  2104.       _error.GreaterSeverity(SEVERITY_USERMSG);
  2105.       
  2106.       exchange_file = 1;
  2107.       SetFileType(VERSION_OLD);
  2108.       }
  2109.     else if (!strncmp(keywd, "STEP_WORKING_SESSION",strlen(keywd))) 
  2110.       {
  2111.       exchange_file = 0;
  2112.       if (_fileType != WORKING_SESSION) 
  2113.         {
  2114.         _error.AppendToUserMsg("Warning: Reading in file as Working Session file.\n");
  2115.         _error.GreaterSeverity(SEVERITY_WARNING);
  2116.         }
  2117.       SetFileType(WORKING_SESSION);
  2118.       }
  2119.     
  2120.     else 
  2121.       {
  2122.       sprintf(errbuf,"Faulty input at beginning of file. \"ISO-10303-21;\" or \"STEP;\" or \"STEP_WORKING_SESSION;\" expected. File not read: %s\n",FileName());
  2123.       _error.AppendToUserMsg(errbuf);
  2124.       _error.GreaterSeverity(SEVERITY_INPUT_ERROR);
  2125.       return SEVERITY_INPUT_ERROR;
  2126.       }
  2127.  
  2128.     cout << "Reading Data from " << FileName () << "...\n";
  2129.  
  2130.     //  Read header
  2131.     rval = ReadHeader(*in);
  2132.     cout << "\nHEADER read:";
  2133.     if (rval < SEVERITY_WARNING)
  2134.       {
  2135.       sprintf(errbuf,"Error: non-recoverable error in reading header section. There were %d errors encountered. Rest of file is ignored.\n",_errorCount);
  2136.       _error.AppendToUserMsg(errbuf);
  2137.       return rval;
  2138.       }
  2139.     else if (rval != SEVERITY_NULL) {
  2140.       sprintf(errbuf, "  %d  ERRORS\t  %d  WARNINGS\n\n",
  2141.           _errorCount, _warningCount);
  2142.       cout << errbuf;
  2143.     }
  2144.     else cout << endl;
  2145.     
  2146.     if (!FindDataSection (*in))
  2147.       {
  2148.       _error.AppendToUserMsg("Error: Unable to find DATA section delimiter. Data section not read. Rest of file ignored.\n");
  2149.       return SEVERITY_INPUT_ERROR;
  2150.       }
  2151.  
  2152.     //  PASS 1
  2153.     _errorCount = 0;
  2154.     switch (_fileType) 
  2155.       {
  2156.     case VERSION_CURRENT:
  2157.     case VERSION_OLD:
  2158.     case VERSION_UNKNOWN:
  2159.       total_insts = ReadData1 (*in);
  2160.       break;
  2161.       
  2162.     case WORKING_SESSION:
  2163.       total_insts = ReadWorkingData1 (*in);
  2164.       break;
  2165.       }
  2166.  
  2167.     cout << "\nFIRST PASS complete:  " << total_insts << " instances created.\n";
  2168.     sprintf(errbuf,
  2169.         "  %d  ERRORS\t  %d  WARNINGS\n\n",
  2170.         _errorCount, _warningCount);
  2171.     cout << errbuf;
  2172.  
  2173.     //  PASS 2
  2174.     //  This would be nicer if you didn't actually have to close the
  2175.     //  file but could just reposition the pointer back to the
  2176.     //  beginning of the data section.  It looks like you can do this
  2177.     //  with the GNU File class, but that class doesn't have the
  2178.     //  operator >> overloaded which is used to do the rest of the
  2179.     //  parsing.  SO we are using istreams and this works, but could
  2180.     //  be better.
  2181.  
  2182.     _errorCount = 0;  // reset the error count so you\'re not counting things twice
  2183. //    delete in; // yikes -- deleted by caller
  2184.     istream * in2;
  2185.     if (! ((in2 = OpenInputFile ()) && (in2 -> good ())) )
  2186.       {  //  if the stream is not readable, there's an error
  2187.       _error.AppendToUserMsg ("Cannot open file for 2nd pass -- No data read.\n");
  2188. //      return total_insts;
  2189.       CloseInputFile(in2);
  2190.       return SEVERITY_INPUT_ERROR;
  2191.       }
  2192.     if (!FindDataSection (*in2))
  2193.       {
  2194.       _error.AppendToUserMsg("Error: Unable to find DATA section delimiterin second pass. Data section not read. Rest of file ignored.\n");
  2195.       CloseInputFile(in2);
  2196.       return  SEVERITY_INPUT_ERROR;
  2197.       }
  2198.     
  2199.     switch (_fileType) 
  2200.       {
  2201.     case VERSION_CURRENT:
  2202.     case VERSION_OLD:
  2203.     case VERSION_UNKNOWN:
  2204.       valid_insts = ReadData2 (*in2);
  2205.       break;
  2206.       
  2207.     case WORKING_SESSION:
  2208.       valid_insts = ReadWorkingData2 (*in2);
  2209.       break;
  2210.       }
  2211.  
  2212.     //check for "ENDSEC;"
  2213.     ReadTokenSeparator(*in2);
  2214.     keywd = GetKeyword(*in2,";");
  2215.     if ( strncmp (keywd, "ENDSEC;",strlen(keywd)) || !in2 -> good () )  
  2216.       {
  2217.     _error.AppendToUserMsg("Unknown value in DATA section. Terminated parsing.\n\tvalue was: %s\n");
  2218.     _error.AppendToUserMsg(keywd); 
  2219.     _error.GreaterSeverity(SEVERITY_WARNING);
  2220.       }
  2221.  
  2222.     if (total_insts != valid_insts)  
  2223.       {
  2224.       sprintf(errbuf,"%d invalid instances in file: %s\n",
  2225.          total_insts - valid_insts, FileName());
  2226.       _error.AppendToUserMsg(errbuf);
  2227.       CloseInputFile(in2);
  2228.       return _error.GreaterSeverity(SEVERITY_WARNING);
  2229.       }
  2230.  
  2231.     cout << "\nSECOND PASS complete:  " << valid_insts << " instances valid.\n"; 
  2232.     sprintf(errbuf,
  2233.         "  %d  ERRORS\t  %d  WARNINGS\n\n",
  2234.         _errorCount, _warningCount);
  2235.     _error.AppendToUserMsg(errbuf);
  2236.     cout << errbuf;
  2237.     
  2238.  
  2239.     //check for "ENDSTEP;" || "END-ISO-10303-21;"
  2240.  
  2241.     if (in2 -> good()) 
  2242.       {
  2243.       ReadTokenSeparator (*in2);
  2244.       keywd = GetKeyword (*in2,";");
  2245.       //yank the ";" from the istream
  2246.       //if (';' == in2->peek()) in2->get();
  2247.       char c; in2->get(c); if (c == ';') ;
  2248.       }
  2249.     
  2250.     if ((strncmp (keywd, END_FILE_DELIM,strlen(keywd))) || !(in2 -> good ())) 
  2251.       {  
  2252.       _error.AppendToUserMsg(END_FILE_DELIM);
  2253.       _error.AppendToUserMsg(" missing at end of file.\n");
  2254.       CloseInputFile(in2);
  2255.       return _error.GreaterSeverity(SEVERITY_WARNING); 
  2256.       }
  2257.     CloseInputFile(in2);
  2258.     cout << "Finished reading file.\n\n";
  2259.     return SEVERITY_NULL;
  2260. }
  2261.  
  2262.  
  2263.  
  2264.     
  2265. /***************************
  2266. ***************************/
  2267. Severity
  2268. STEPfile::WriteWorkingFile(ostream& out)
  2269. {
  2270.     SetFileType (WORKING_SESSION);
  2271.     _error.ClearErrorMsg();
  2272.  
  2273.     if (instances ().VerifyInstances(_error) < SEVERITY_INCOMPLETE) 
  2274.       {
  2275.       _error.AppendToUserMsg("WARNING: some invalid instances written to working session file. Data may have been lost.");
  2276.       _error.GreaterSeverity(SEVERITY_INCOMPLETE);
  2277.       }
  2278.     
  2279.     out << FILE_DELIM << "\n";
  2280.     WriteHeader(out);
  2281.  
  2282.     WriteWorkingData(out);
  2283.     out << END_FILE_DELIM << "\n";
  2284.     SetFileType();
  2285.  
  2286.     return _error.severity ();
  2287. }
  2288.  
  2289. /***************************
  2290. ***************************/
  2291. Severity
  2292. STEPfile::WriteWorkingFile(const char* filename) 
  2293. {
  2294.     _error.ClearErrorMsg();
  2295.     ostream* out =  OpenOutputFile(filename);
  2296.     if (_error.severity() < SEVERITY_WARNING) return _error.severity();
  2297.     Severity rval = WriteWorkingFile(*out);
  2298.     CloseOutputFile(out);
  2299.  
  2300.     return rval;
  2301. }
  2302.  
  2303.  
  2304. /***************************
  2305. ***************************/
  2306. void
  2307. STEPfile::WriteWorkingData(ostream& out) 
  2308. {
  2309.     out << "DATA;\n";
  2310. //    STEPentity* se;
  2311.     int n = instances ().InstanceCount();
  2312.     for (register int i = 0; i < n; ++i) {
  2313.     switch ((instances ()[i])->CurrState()) 
  2314.       {
  2315.         case deleteSE:
  2316.           out << wsDelete;
  2317.           (instances ()[i])->GetSTEPentity()->STEPwrite(out);
  2318.           break;
  2319.         case completeSE:
  2320.           out << wsSaveComplete;
  2321.           (instances ()[i])->GetSTEPentity()->STEPwrite(out);
  2322.           break;
  2323.         case incompleteSE:
  2324.           out << wsSaveIncomplete;
  2325.           (instances ()[i])->GetSTEPentity()->STEPwrite(out);
  2326.           break;
  2327.         case newSE:
  2328.           out << wsNew;
  2329.           (instances ()[i])->GetSTEPentity()->STEPwrite(out);
  2330.           break;
  2331.         case noStateSE:
  2332.           _error.AppendToUserMsg("no state information for this node\n");
  2333.           break;
  2334.       }
  2335.     }
  2336.     out << "ENDSEC;\n";
  2337. }
  2338.  
  2339. /**************************************************
  2340.  description:
  2341.     This function sends messages to 'cerr'
  2342.     based on the values in the given ErrorDescriptor (e), which is
  2343.     supposed to be from a STEPentity object, being manipulated by one
  2344.     of the STEPfile member functions.
  2345.  
  2346.     The given error descriptor's messages are then cleared.
  2347.  
  2348.     The STEPfile's error descriptor is set no lower than SEVERITY_WARNING.
  2349.     
  2350. **************************************************/
  2351. Severity
  2352. STEPfile::AppendEntityErrorMsg(ErrorDescriptor *e) 
  2353. {
  2354.     ErrorDescriptor* ed = e;
  2355.     
  2356.     Severity sev = ed->severity();
  2357.  
  2358.     if ((sev < SEVERITY_MAX) || (sev > SEVERITY_NULL)) 
  2359.       {
  2360.       //ERROR: something wrong with ErrorDescriptor
  2361.       //_error.AppendToDetailMsg("Error: in AppendEntityErrorMsg(ErrorDesriptor& e). Incomplete ErrorDescriptor, unable to report error message in STEPentity.\n");
  2362.       _error.GreaterSeverity(SEVERITY_WARNING);
  2363.       return SEVERITY_BUG;
  2364.       }
  2365.     
  2366.     switch (sev) 
  2367.       {
  2368.     case SEVERITY_NULL:
  2369.       return SEVERITY_NULL;
  2370.  
  2371.     default:
  2372.     {
  2373. //      cerr << e->UserMsg();
  2374.       cerr << e->DetailMsg();
  2375.       e->ClearErrorMsg();
  2376.       
  2377.       if (sev < SEVERITY_USERMSG)   { ++_errorCount;  }
  2378.       if (sev < SEVERITY_WARNING)   { sev = SEVERITY_WARNING;  }
  2379.       
  2380.       _error.GreaterSeverity(sev);
  2381.       return sev;
  2382.     }
  2383.       }
  2384. }
  2385.