/* * NIST STEP Core Class Library * clstepcore/sdaiApplication_instance.cc * July, 1997 * K. C. Morris * David Sauder * Development of this software was funded by the United States Government, * and is not subject to copyright. */ /* $Id: sdaiApplication_instance.cc,v 1.3 2003/06/06 17:07:35 gcosmo Exp $ */ //static char rcsid[] ="$Id: sdaiApplication_instance.cc,v 1.3 2003/06/06 17:07:35 gcosmo Exp $"; #include //#include #include #include #include SCLP23(Application_instance) NilSTEPentity; /****************************************************************** ** Functions for manipulating entities ** KNOWN BUGs: the SCLP23(Application_instance) is not aware of the STEPfile; ** therefore it can not read comments which may be embedded in the instance. ** The following are known problems: ** -- does not handle comments embedded in an instance ==> bombs ** -- ignores embedded entities ==> does not bomb ** -- error reporting does not include line number information **/ SCLP23(Application_instance)::SCLP23_NAME(Application_instance) () : _cur(0), STEPfile_id(0), p21Comment(0), headMiEntity(0), nextMiEntity(0), _complex(0) { } SCLP23(Application_instance)::SCLP23_NAME(Application_instance) (int fileid, int complex) : _cur(0), STEPfile_id(fileid), p21Comment(0), headMiEntity(0), nextMiEntity(0), _complex (complex) { } SCLP23(Application_instance)::~SCLP23_NAME(Application_instance) () { STEPattribute * next =0; ResetAttributes (); while (next = NextAttribute ()) delete next; if(MultipleInheritance()) { delete nextMiEntity; } delete p21Comment; /* // this is not necessary since each will call delete on its // own nextMiEntity - DAS SCLP23(Application_instance) * nextMI = nextMiEntity; SCLP23(Application_instance) * nextMItrail = 0; while(nextMI) { nextMItrail = nextMI; nextMI = nextMI->nextMiEntity; // this is ok since STEPattribute doesn't explicitly delete its attr delete nextMItrail; } */ } #ifdef PART26 //SCLP26(Application_instance_ptr) IDL_Application_instance_ptr SCLP23(Application_instance)::create_TIE() { G4cout << "ERROR SCLP23(Application_instance)::create_TIE() called." << G4endl; return 0; } #endif SCLP23(Application_instance) * SCLP23(Application_instance)::Replicate() { char errStr[BUFSIZ]; if(IsComplex()) { G4cerr << "STEPcomplex::Replicate() should be called: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; sprintf(errStr, "SCLP23(Application_instance)::Replicate(): %s - entity #%d.\n", "Programming ERROR - STEPcomplex::Replicate() should be called", STEPfile_id); _error.AppendToDetailMsg(errStr); _error.AppendToUserMsg(errStr); _error.GreaterSeverity(SEVERITY_BUG); return S_ENTITY_NULL; } else { #ifdef __OSTORE__ SCLP23(Application_instance) *seNew = eDesc->NewSTEPentity(os_database::of(this)); #else SCLP23(Application_instance) *seNew = eDesc->NewSTEPentity(); #endif seNew -> CopyAs (this); return seNew; } } void SCLP23(Application_instance)::AddP21Comment(const char *s, int replace) { if(replace) { delete p21Comment; p21Comment = 0; } if(s) { if(!p21Comment) { #ifdef __OSTORE__ p21Comment = new (os_segment::of(this), SCLstring::get_os_typespec()) SCLstring; #else p21Comment = new SCLstring; #endif } else p21Comment->set_null(); p21Comment->Append( s ); } } void SCLP23(Application_instance)::AddP21Comment(SCLstring &s, int replace) { if(replace) { delete p21Comment; p21Comment = 0; } if(!s.is_null()) { if(!p21Comment) { #ifdef __OSTORE__ p21Comment = new (os_segment::of(this), SCLstring::get_os_typespec()) SCLstring; #else p21Comment = new SCLstring; #endif } else p21Comment->set_null(); p21Comment->Append( s.chars() ); } } void SCLP23(Application_instance)::STEPwrite_reference (std::ostream& out) { out << "#" << STEPfile_id; } const char * SCLP23(Application_instance)::STEPwrite_reference (SCLstring &buf) { char tmp[64]; sprintf ( tmp,"#%d", STEPfile_id); buf = tmp; return buf.chars(); } void SCLP23(Application_instance)::AppendMultInstance(SCLP23(Application_instance) *se) { if(nextMiEntity == 0) nextMiEntity = se; else { SCLP23(Application_instance) *link = nextMiEntity; SCLP23(Application_instance) *linkTrailing = 0; while(link) { linkTrailing = link; link = link->nextMiEntity; } linkTrailing->nextMiEntity = se; } } // BUG implement this SCLP23(Application_instance) * SCLP23(Application_instance)::GetMiEntity(char *EntityName) { SCLstring s1, s2; const EntityDescLinkNode *edln = 0; const EntityDescriptor *ed = eDesc; // compare up the *leftmost* parent path while(ed) { if( !strcmp( StrToLower(ed->Name(),s1), StrToLower(EntityName,s2) ) ) return this; // return this parent path edln = (EntityDescLinkNode *)( ed->Supertypes().GetHead() ); if(edln) ed = edln->EntityDesc(); else ed = 0; } // search alternate parent path since didn't find it in this one. if(nextMiEntity) return nextMiEntity->GetMiEntity(EntityName); return 0; } #ifdef __OSTORE__ void Application_instance_access_hook_in(void *object, enum os_access_reason reason, void *user_data, void *start_range, void *end_range) { G4cout << "ObjectStore called non-member function Application_instance Access_hook" << G4endl; SCLP23(Application_instance) *ent = (SCLP23(Application_instance) *)object; G4cout << "STEPfile_id: " << ent->STEPfile_id << G4endl; ent->Access_hook_in(object, reason, user_data, start_range, end_range); // SdaiEb_person *ent = (SdaiEb_person *)object; // SdaiEb_person_access_hook_in(object, reason, user_data, // start_range, end_range); } void SCLP23(Application_instance)::Access_hook_in(void *object, enum os_access_reason reason, void *user_data, void *start_range, void *end_range) { SCLP23(Application_instance) *ent = (SCLP23(Application_instance) *)object; G4cout << "****WARNING: virtual SCLP23(Application_instance)::Access_hook_in() called" << G4endl; ent->Access_hook_in(object, reason, user_data, start_range, end_range); } #endif STEPattribute * SCLP23(Application_instance)::GetSTEPattribute (const char * nm) { if (!nm) return 0; STEPattribute *a =0; ResetAttributes(); while ((a = NextAttribute () ) && strcmp (nm, a ->Name())) ; // keep going until no more attributes or attribute is found return a; } STEPattribute * SCLP23(Application_instance)::MakeRedefined (STEPattribute *redefiningAttr, const char * nm) { // find the attribute being redefined STEPattribute * a = GetSTEPattribute (nm); // assign its pointer to the redefining attribute if (a) a->RedefiningAttr(redefiningAttr); return a; } STEPattribute * SCLP23(Application_instance)::MakeDerived (const char * nm) { STEPattribute * a = GetSTEPattribute (nm); if (a) a ->Derive (); return a; } void SCLP23(Application_instance)::CopyAs (SCLP23(Application_instance) * other) { int numAttrs = AttributeCount(); ResetAttributes(); other -> ResetAttributes(); STEPattribute *this_attr = 0; STEPattribute *other_attr = 0; while((this_attr = NextAttribute()) && numAttrs) { other_attr = other -> NextAttribute(); this_attr -> ShallowCopy(other_attr); numAttrs--; } } const char * SCLP23(Application_instance)::EntityName( const char *schnm) const { return eDesc->Name( schnm ); } /***************************************************************** Checks if a given SCLP23(Application_instance) is the same type as this one ****************************************************************/ const EntityDescriptor* SCLP23(Application_instance)::IsA(const EntityDescriptor *ed) const { return (eDesc->IsA(ed)); } /****************************************************************** // Checks the validity of the current attribute values for the entity ******************************************************************/ Severity SCLP23(Application_instance)::ValidLevel(ErrorDescriptor *error, InstMgr *im, int clearError) { ErrorDescriptor err; if(clearError) ClearError(); int n = attributes.list_length(); SCLstring tmp; for (int i = 0 ; i < n; i++) { if( !(attributes[i].aDesc->AttrType() == AttrType_Redefining) ) error->GreaterSeverity(attributes[i].ValidLevel( attributes[i].asStr(tmp), &err, im, 0)); } return error->severity(); } /****************************************************************** // clears all attr's errors ******************************************************************/ void SCLP23(Application_instance)::ClearAttrError() { int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { attributes[i].Error().ClearErrorMsg(); } } /****************************************************************** // clears entity's error and optionally all attr's errors ******************************************************************/ void SCLP23(Application_instance)::ClearError(int clearAttrs) { _error.ClearErrorMsg(); if(clearAttrs) ClearAttrError(); } /****************************************************************** ******************************************************************/ /* void SCLP23(Application_instance)::EnforceOptionality(int on) { Enforcement e; if(on) e = ENFORCE_OPTIONALITY; else e = ENFORCE_OFF; Error().enforcement(e); int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { attributes[i].Error().enforcement(e); } } */ /****************************************************************** ** Procedure: beginSTEPwrite ** Parameters: std::ostream& out -- stream to write to ** Returns: ** Side Effects: writes out the SCOPE section for an entity ** Status: stub ******************************************************************/ void SCLP23(Application_instance)::beginSTEPwrite(std::ostream& out) { out << "begin STEPwrite ... \n" ; out.flush(); int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { if (attributes[i].Type () == ENTITY_TYPE && *(attributes[i].ptr.c) != S_ENTITY_NULL) (*(attributes[i].ptr.c)) -> STEPwrite(); } } /****************************************************************** ** Procedure: STEPwrite ** Parameters: std::ostream& out -- stream to write to ** Returns: ** Side Effects: writes out the data associated with an instance in STEP format ** Problems: does not print out the SCOPE section of an entity ** ******************************************************************/ void SCLP23(Application_instance)::STEPwrite(std::ostream& out, const char *currSch, int writeComments) { SCLstring tmp; if(writeComments && p21Comment && !p21Comment->is_null() ) out << p21Comment->chars(); out << "#" << STEPfile_id << "=" << StrToUpper(EntityName( currSch ), tmp) << "("; int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { if( !(attributes[i].aDesc->AttrType() == AttrType_Redefining) ) { if (i > 0) out << ","; (attributes[i]).STEPwrite( out, currSch ); } } out << ");\n"; } void SCLP23(Application_instance)::endSTEPwrite(std::ostream& out) { out << "end STEPwrite ... \n" ; out.flush(); } void SCLP23(Application_instance)::WriteValuePairs(std::ostream& out, const char *currSch, int writeComments, int mixedCase) { /* const EntityDescriptorList &edl = eDesc->Supertypes(); EntityDescItr &edi((EntityDescriptorList &)(eDesc->Supertypes())); int count = 1; const EntityDescriptor * ed = 0; while(ed = edi.NextEntityDesc()) { if(count > 1) { out << "&"; } out << ed->Name(); count++; } */ // const AttrDescriptorList& adl = ed->ExplicitAttr(); /* out << "Attributes are: " << G4endl; edi.ResetItr(); AttrDescItr *adi = 0; const AttrDescriptor * ad; while(ed = edi.NextEntityDesc()) { adi = new AttrDescItr((AttrDescriptorList&)ed->ExplicitAttr()); ad = 0; while(ad = adi->NextAttrDesc()) { out << ed->Name() << "." << ad->Name() << G4endl; } delete adi; } out << G4endl; out << "finished writing attribute names." << G4endl; edi.ResetItr(); */ SCLstring s; // out << eDesc->QualifiedName(s) << G4endl; SCLstring tmp, tmp2; if(writeComments && p21Comment && !p21Comment->is_null() ) out << p21Comment->chars(); if(mixedCase) { out << "#" << STEPfile_id << " " << eDesc->QualifiedName(s) << G4endl; } else { out << "#" << STEPfile_id << " " << StrToUpper(eDesc->QualifiedName(s),tmp) << G4endl; } int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { if( !(attributes[i].aDesc->AttrType() == AttrType_Redefining) ) { // if (i > 0) out << ","; if(mixedCase) { out << "\t" << attributes[i].aDesc->Owner().Name(s) << "." << attributes[i].aDesc->Name() << " "; } else { out << "\t" << StrToUpper(attributes[i].aDesc->Owner().Name(s),tmp) << "." << StrToUpper(attributes[i].aDesc->Name(),tmp2) << " "; } (attributes[i]).STEPwrite( out, currSch ); out << G4endl; } } out << G4endl; } /****************************************************************** ** Procedure: STEPwrite ** Problems: does not print out the SCOPE section of an entity ** ******************************************************************/ const char * SCLP23(Application_instance)::STEPwrite(SCLstring &buf, const char *currSch) { buf.set_null(); char instanceInfo[BUFSIZ]; SCLstring tmp; sprintf(instanceInfo, "#%d=%s(", STEPfile_id, (char *)StrToUpper( EntityName( currSch ), tmp ) ); buf.Append(instanceInfo); int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { if( !(attributes[i].aDesc->AttrType() == AttrType_Redefining) ) { if (i > 0) buf.Append( ',' ); attributes[i].asStr( tmp, currSch ) ; buf.Append (tmp); } } buf.Append( ");" ); return buf.chars(); } void SCLP23(Application_instance)::PrependEntityErrMsg() { char errStr[BUFSIZ]; errStr[0] = '\0'; if(_error.severity() == SEVERITY_NULL) { // if there is not an error already sprintf(errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName()); _error.PrependToDetailMsg(errStr); } } /****************************************************************** ** Procedure: SCLP23(Application_instance)::STEPread_error ** Parameters: char c -- character which caused error ** int i -- index of attribute which caused error ** std::istream& in -- input stream for recovery ** Returns: ** Description: reports the error found, reads until it finds the end of an ** instance. i.e. a close quote followed by a semicolon optionally having ** whitespace between them. ******************************************************************/ void SCLP23(Application_instance)::STEPread_error(char c, int i, std::istream& in) { char errStr[BUFSIZ]; errStr[0] = '\0'; if(_error.severity() == SEVERITY_NULL) { // if there is not an error already sprintf(errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName()); _error.PrependToDetailMsg(errStr); } /* sprintf(errStr, " for instance #%d : %s\n", STEPfile_id, EntityName());*/ /* _error.AppendToDetailMsg(errStr);*/ if ( (i >= 0) && (i < attributes.list_length())) // i is an attribute { Error ().GreaterSeverity (SEVERITY_WARNING); sprintf(errStr, " invalid data before type \'%s\'\n", attributes[i].TypeName()); _error.AppendToDetailMsg(errStr); } else { Error ().GreaterSeverity (SEVERITY_INPUT_ERROR); _error.AppendToDetailMsg(" No more attributes were expected.\n"); } SCLstring tmp; STEPwrite (tmp); // STEPwrite writes to a static buffer inside function sprintf(errStr, " The invalid instance to this point looks like :\n%s\n", tmp.chars() ); _error.AppendToDetailMsg(errStr); // _error.AppendToDetailMsg(" data lost looking for end of entity:"); // scan over the rest of the instance and echo it // G4cerr << " ERROR Trying to find the end of the ENTITY to recover...\n"; // G4cerr << " skipping the following input:\n"; #ifdef OBSOLETE in.clear(); int foundEnd = 0; tmp = ""; // Search until a close paren is found followed by (skipping optional // whitespace) a semicolon while( in.good() && !foundEnd ) { while ( in.good() && (c != ')') ) { in.get(c); tmp.Append(c); // G4cerr << c; } if(in.good() && (c == ')') ) { in >> std::ws; // skip whitespace in.get(c); tmp.Append(c); // G4cerr << c; // G4cerr << "\n"; if(c == ';') { foundEnd = 1; } } } _error.AppendToDetailMsg( tmp.chars() ); #endif sprintf (errStr, "\nfinished reading #%d\n", STEPfile_id); _error.AppendToDetailMsg(errStr); return; } /****************************************************************** ** Procedure: STEPread ** Returns: Severity, error information ** SEVERITY_NULL - no errors ** SEVERITY_USERMSG - checked as much as possible, could still ** be error - e.g. entity didn't match base entity type. ** SEVERITY_INCOMPLETE - data is missing and required. ** SEVERITY_WARNING - errors, but can recover ** <= SEVERITY_INPUT_ERROR - fatal error, can't recover ** Description: reads the values for an entity from an input stream ** in STEP file format starting at the open paren and ** ending with the semi-colon ** Parameters: int id ** int idIncrement ** InstMgr instances ** std::istream& in ** Side Effects: gobbles up input stream ** Status: ******************************************************************/ Severity SCLP23(Application_instance)::STEPread(int id, int idIncr, InstMgr * instance_set, std::istream& in, const char *currSch, int useTechCor) { STEPfile_id = id; char c ='\0'; char errStr[BUFSIZ]; errStr[0] = '\0'; Severity severe; int i = 0; ClearError(1); in >> std::ws; in >> c; // read the open paren if( c != '(' ) { PrependEntityErrMsg(); _error.AppendToDetailMsg( " Missing initial open paren... Trying to recover.\n"); in.putback(c); // assume you can recover by reading 1st attr value } in >> std::ws; int n = attributes.list_length(); if( n == 0) // no attributes { in >> c; // look for the close paren if( c == ')' ) return _error.severity(); } for (i = 0 ; i < n; i++) { if( attributes[i].aDesc->AttrType() == AttrType_Redefining ) { in >> std::ws; c = in.peek(); if(!useTechCor) // i.e. use pre-technical corrigendum encoding { in >> c; // read what should be the '*' in >> std::ws; if(c == '*') { in >> c; // read the delimiter i.e. ',' or ')' } else { severe = SEVERITY_INCOMPLETE; PrependEntityErrMsg(); // adds entity info if necessary // set the severity for this entity _error.GreaterSeverity(severe); sprintf (errStr, " %s : ", attributes[i].Name()); _error.AppendToDetailMsg(errStr); // add attr name _error.AppendToDetailMsg( "Since using pre-technical corrigendum... missing asterisk for redefined attr.\n"); _error.AppendToUserMsg( "Since using pre-technical corrigendum... missing asterisk for redefined attr. "); } /* if( ! ( (c == ',') || (c == ')') ) ) { // input is not a delimiter - an error PrependEntityErrMsg(); _error.AppendToDetailMsg( "Delimiter expected after redefined asterisk attribute encoding (since using pre-technical corregendum.\n"); CheckRemainingInput(in, &_error, "ENTITY", ",)"); if(!in.good()) return _error.severity(); if(_error.severity() <= SEVERITY_INPUT_ERROR) { // STEPread_error(c,i,in); return _error.severity(); } } */ } else // using technical corrigendum { // should be nothing to do except loop again unless... // if at end need to have read the closing paren. if(c == ')') // assume you are at the end so read last char in >> c; G4cout << "Entity #" << STEPfile_id << " skipping redefined attribute " << attributes[i].aDesc->Name() << G4endl << G4endl << std::flush; } // increment counter to read following attr since these attrs // aren't written or read => there won't be a delimiter either // i++; } else { attributes[i].STEPread(in, instance_set, idIncr, currSch); in >> c; // read the , or ) following the attr read severe = attributes[i].Error().severity(); if(severe <= SEVERITY_USERMSG) { // if there is some type of error PrependEntityErrMsg(); // set the severity for this entity _error.GreaterSeverity(severe); sprintf (errStr, " %s : ", attributes[i].Name()); _error.AppendToDetailMsg(errStr); // add attr name _error.AppendToDetailMsg((char *) // add attr error attributes[i].Error().DetailMsg()); _error.AppendToUserMsg((char*)attributes[i].Error().UserMsg()); } } /* if(severe <= SEVERITY_INPUT_ERROR) { // attribute\'s error is non-recoverable // I believe if this error occurs then you cannot recover // TODO: can you just read to the next comma and try to continue ? STEPread_error(c,i,in); return _error.severity(); } */ // if technical corrigendum redefined, input is at next attribute value // if pre-technical corrigendum redefined, don't process if ( (!( attributes[i].aDesc->AttrType() == AttrType_Redefining ) || !useTechCor) && ! ((c == ',') || (c == ')' )) ) { // input is not a delimiter PrependEntityErrMsg(); _error.AppendToDetailMsg( "Delimiter expected after attribute value.\n"); if(!useTechCor) { _error.AppendToDetailMsg( "I.e. since using pre-technical corrigendum, redefined "); _error.AppendToDetailMsg( "attribute is mapped as an asterisk so needs delimiter.\n"); } CheckRemainingInput(in, &_error, "ENTITY", ",)"); if(!in.good()) return _error.severity(); if(_error.severity() <= SEVERITY_INPUT_ERROR) { // STEPread_error(c,i,in); return _error.severity(); } } else if(c == ')') { while (i < n-1) { i++; // check if following attributes are redefined if( !(attributes[i].aDesc->AttrType() == AttrType_Redefining) ) { PrependEntityErrMsg(); _error.AppendToDetailMsg("Missing attribute value[s].\n"); // recoverable error _error.GreaterSeverity(SEVERITY_WARNING); return _error.severity(); } i++; } return _error.severity(); } } STEPread_error(c,i,in); // code fragment imported from STEPread_error // for some currently unknown reason it was commented out of STEPread_error errStr[0] = '\0'; in.clear(); int foundEnd = 0; SCLstring tmp; tmp = ""; // Search until a close paren is found followed by (skipping optional // whitespace) a semicolon while( in.good() && !foundEnd ) { while ( in.good() && (c != ')') ) { in.get(c); tmp.Append(c); // G4cerr << c; } if(in.good() && (c == ')') ) { in >> std::ws; // skip whitespace in.get(c); tmp.Append(c); // G4cerr << c; // G4cerr << "\n"; if(c == ';') { foundEnd = 1; } } } _error.AppendToDetailMsg( tmp.chars() ); sprintf (errStr, "\nfinished reading #%d\n", STEPfile_id); _error.AppendToDetailMsg(errStr); // end of imported code return _error.severity(); } /////////////////////////////////////////////////////////////////////////////// // read an entity reference and return a pointer to the SCLP23(Application_instance) /////////////////////////////////////////////////////////////////////////////// SCLP23(Application_instance) * ReadEntityRef(std::istream &in, ErrorDescriptor *err, char *tokenList, InstMgr * instances, int addFileId) { char c; char errStr[BUFSIZ]; errStr[0] = '\0'; in >> std::ws; in >> c; switch (c) { case '@': err->AppendToDetailMsg( "Use of @ instead of # to identify entity.\n"); err->GreaterSeverity(SEVERITY_WARNING); // no break statement here on purpose case '#': { int id = -1; // int n = 0; in >> id; if (in.fail ()) // there's been an error in input { // in.clear(); sprintf(errStr,"Invalid entity reference value.\n"); err->AppendToDetailMsg(errStr); err->AppendToUserMsg(errStr); err->GreaterSeverity(SEVERITY_WARNING); CheckRemainingInput(in, err, "Entity Reference", tokenList); return S_ENTITY_NULL; } else // found an entity id { // check to make sure garbage does not follow the id CheckRemainingInput(in, err, "Entity Reference", tokenList); id += addFileId; if (!instances) { G4cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; sprintf(errStr, "STEPread_reference(): %s - entity #%d %s.\n", "BUG - cannot read reference without the InstMgr", id, "is unknown"); err->AppendToDetailMsg(errStr); err->AppendToUserMsg(errStr); err->GreaterSeverity(SEVERITY_BUG); return S_ENTITY_NULL; } // lookup which object has id as its instance id SCLP23(Application_instance)* inst; /* If there is a ManagerNode it should have a SCLP23(Application_instance) */ MgrNode* mn =0; mn = instances->FindFileId(id); if (mn) { inst = mn->GetSTEPentity() ; if (inst) { return (inst); } else { G4cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; sprintf(errStr, "STEPread_reference(): %s - entity #%d %s.\n", "BUG - MgrNode::GetSTEPentity returned NULL pointer", id, "is unknown"); err->AppendToDetailMsg(errStr); err->AppendToUserMsg(errStr); err->GreaterSeverity(SEVERITY_BUG); return S_ENTITY_NULL; } } else { sprintf(errStr,"Reference to non-existent ENTITY #%d.\n", id); err->AppendToDetailMsg(errStr); err->AppendToUserMsg(errStr); err->GreaterSeverity(SEVERITY_WARNING); return S_ENTITY_NULL; } } } default: { in.putback(c); // read past garbage up to delim in tokenList // if tokenList is null it will not read anything CheckRemainingInput(in, err, "Entity Reference", tokenList); return S_ENTITY_NULL; } } } /////////////////////////////////////////////////////////////////////////////// // same as above but reads from a const char * /////////////////////////////////////////////////////////////////////////////// SCLP23(Application_instance) * ReadEntityRef(const char * s, ErrorDescriptor *err, char *tokenList, InstMgr * instances, int addFileId) { std::istrstream in((char *)s); return ReadEntityRef(in, err, tokenList, instances, addFileId); } /////////////////////////////////////////////////////////////////////////////// // return SEVERITY_NULL if se's entity type matches the supplied entity type /////////////////////////////////////////////////////////////////////////////// Severity EntityValidLevel(SCLP23(Application_instance) *se, const TypeDescriptor *ed, // entity type that entity se needs // to match. (this must be an // EntityDescriptor) ErrorDescriptor *err) { char messageBuf [BUFSIZ]; messageBuf[0] = '\0'; if( !ed || (ed->NonRefType() != ENTITY_TYPE) ) { err->GreaterSeverity(SEVERITY_BUG); sprintf(messageBuf, " BUG: EntityValidLevel() called with %s", "missing or invalid EntityDescriptor\n"); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); G4cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; return SEVERITY_BUG; } if(!se || (se == S_ENTITY_NULL)) { err->GreaterSeverity(SEVERITY_BUG); sprintf(messageBuf, " BUG: EntityValidLevel() called with null pointer %s\n", "for SCLP23(Application_instance) argument."); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); G4cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; return SEVERITY_BUG; } // DAVE: Can an entity be used in an Express TYPE so that this // EntityDescriptor would have type REFERENCE_TYPE -- it looks like NO else if(se->eDesc) { // is se a descendant of ed? if ( se->eDesc->IsA(ed) ) { return SEVERITY_NULL; } else { if(se->IsComplex()) { // This way assumes that the complex has all it's parts i.e. the // complete hierarchy so it should be able to find ed's part if // it is an ed. STEPcomplex *sc = ((STEPcomplex *)se)->sc; if(sc->EntityExists(ed->Name())) return SEVERITY_NULL; /* */ // This way checks to see if it is an ed based on the dictionary // It is much less efficient but does not depend on the instance // having all the parts it needs to be valid. /* STEPcomplex *sc = ((STEPcomplex *)se)->sc; while (sc) { if( sc->eDesc->IsA(ed) ) return SEVERITY_NULL; sc = sc->sc; } */ } err->GreaterSeverity(SEVERITY_WARNING); sprintf(messageBuf, " Entity #%d exists but is not a %s or descendant.\n", se->STEPfile_id, ed->Name()); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); return SEVERITY_WARNING; } } else { err->GreaterSeverity(SEVERITY_BUG); sprintf(messageBuf, " BUG: EntityValidLevel(): SCLP23(Application_instance) #%d has a %s", se->STEPfile_id, "missing or invalid EntityDescriptor\n"); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); G4cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; return SEVERITY_BUG; } } /////////////////////////////////////////////////////////////////////////////// // return 1 if attrValue has the equivalent of a null value. /////////////////////////////////////////////////////////////////////////////// int SetErrOnNull (const char *attrValue, ErrorDescriptor *error) { // DAVE: Is this needed will sscanf return 1 if assignment suppression is used? char scanBuf[BUFSIZ]; scanBuf[0] = '\0'; int numFound = sscanf((char *)attrValue," %s", scanBuf); if (numFound == EOF) { /* if(Nullable()) { error->GreaterSeverity (SEVERITY_NULL); } else { error->GreaterSeverity (SEVERITY_INCOMPLETE); } */ error->GreaterSeverity (SEVERITY_INCOMPLETE); return 1; } return 0; } /////////////////////////////////////////////////////////////////////////////// // return SEVERITY_NULL if attrValue has a valid entity reference // This function accepts an entity reference in two forms that is with or // without the # sign: e.g. either #23 or 23 will be read. // If non-whitespace characters follow the entity reference an error is set. /////////////////////////////////////////////////////////////////////////////// Severity EntityValidLevel(const char *attrValue, // string contain entity ref const TypeDescriptor *ed, // entity type that entity in // attrValue (if it exists) needs // to match. (this must be an // EntityDescriptor) ErrorDescriptor *err, InstMgr *im, int clearError) { char tmp [BUFSIZ]; tmp[0] = '\0'; char messageBuf [BUFSIZ]; messageBuf[0] = '\0'; if(clearError) err->ClearErrorMsg(); /* // the problem with doing this is that it will require having a # in front // of the entity ref. SCLP23(Application_instance) se = ReadEntityRef(attrValue, err, 0, im, 0); return EntityValidLevel(se, ed, err); */ int fileId; MgrNode *mn = 0; // check for both forms: #id or id int found1 = sscanf((char *)attrValue, " #%d %s", &fileId, tmp); int found2 = sscanf((char *)attrValue, " %d %s", &fileId, tmp); if( (found1 > 0) || (found2 > 0) ) { if ( (found1 == 2) || (found2 == 2) ) { sprintf(messageBuf, " Attribute's Entity Reference %s is %s data \'%s\'.\n", attrValue, "followed by invalid", tmp); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); err->GreaterSeverity(SEVERITY_WARNING); } mn = im->FindFileId(fileId); if(mn) { SCLP23(Application_instance) *se = mn->GetSTEPentity(); return EntityValidLevel(se, ed, err); } else { sprintf(messageBuf, " Attribute's Entity Reference %s does not exist.\n", attrValue); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); err->GreaterSeverity(SEVERITY_WARNING); return SEVERITY_WARNING; } } // if the attrValue contains no value return if (SetErrOnNull (attrValue, err)) return err->severity(); sprintf(messageBuf, "Invalid attribute entity reference value: '%s'.\n", attrValue); err->AppendToUserMsg(messageBuf); err->AppendToDetailMsg(messageBuf); err->GreaterSeverity(SEVERITY_WARNING); return SEVERITY_WARNING; } /****************************************************************** ** Procedure: NextAttribute ** Parameters: ** Returns: reference to an attribute pointer ** Description: used to cycle through the list of attributes ** Side Effects: increments the current position in the attribute list ** Status: untested 7/31/90 ******************************************************************/ STEPattribute * SCLP23(Application_instance)::NextAttribute () { int i = AttributeCount (); ++_cur; if (i < _cur) return 0; return &attributes [_cur-1]; } int SCLP23(Application_instance)::AttributeCount () { return attributes.list_length (); } #ifdef OBSOLETE Severity SCLP23(Application_instance)::ReadAttrs(int id, int addFileId, class InstMgr * instance_set, std::istream& in) { char c ='\0'; char errStr[BUFSIZ]; errStr[0] = '\0'; Severity severe; ClearError(1); int n = attributes.list_length(); for (int i = 0 ; i < n; i++) { attributes[i].STEPread(in, instance_set, addFileId); severe = attributes[i].Error().severity(); if(severe <= SEVERITY_USERMSG) { // if there\'s some type of error if(_error.severity() == SEVERITY_NULL) { // if there is not an error already sprintf(errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName()); _error.PrependToDetailMsg(errStr); } // set the severity for this entity sprintf (errStr, " %s : ", attributes[i].Name()); _error.AppendToDetailMsg(errStr); _error.GreaterSeverity(severe); _error.AppendToDetailMsg((char *) attributes[i].Error().DetailMsg()); _error.AppendToUserMsg((char *)attributes[i].Error().UserMsg()); } /* if(severe <= SEVERITY_INPUT_ERROR) { // attribute\'s error is non-recoverable // I believe if this error occurs then you cannot recover // TODO: can you just read to the next comma and try to continue ? STEPread_error(c,i,in); return _error.severity(); } */ in >> c; if ( ! ((c == ',') || (c == ')' ))) { // input is not a delimiter if(_error.severity() == SEVERITY_NULL) { // if there is not an error already sprintf(errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName()); _error.PrependToDetailMsg(errStr); } _error.AppendToDetailMsg( "delimiter expected after attribute value.\n"); CheckRemainingInput(in, &_error, "ENTITY", ",)"); if(!in.good()) return _error.severity(); if(_error.severity() <= SEVERITY_INPUT_ERROR) { STEPread_error(c,i,in); return _error.severity(); } } else if(c == ')') { in >> std::ws; char z = in.peek(); if (z == ';') { in.get(c); return _error.severity(); } } } if(c != ')' ) { STEPread_error(c,i,in); return _error.severity(); } return SEVERITY_NULL; } #endif