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
/
SENTITY.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-03
|
22KB
|
747 lines
/*
* NIST STEP Core Class Library
* clstepcore/STEPentity.cc
* February, 1994
* K. C. Morris
* David Sauder
* Development of this software was funded by the United States Government,
* and is not subject to copyright.
*/
/* $Id: STEPentity.cc,v 2.0.1.2 1994/05/10 21:03:10 kc Exp $ */
//static char rcsid[] ="$Id: STEPentity.cc,v 2.0.1.2 1994/05/10 21:03:10 kc Exp $";
#include <Sentity.h>
#include <instmgr.h>
STEPentity NilSTEPentity;
/******************************************************************
** Functions for manipulating entities
** KNOWN BUGs: the STEPentity 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
**/
STEPentity::STEPentity ()
: _cur (0), STEPfile_id (0)
{
}
STEPentity::~STEPentity ()
{
STEPattribute * next =0;
ResetAttributes ();
while (next = NextAttribute ())
delete next;
}
STEPentity *STEPentity::Replicate()
{
STEPentity *seNew = EntityDescriptor->NewSTEPentity();
seNew -> CopyAs (this);
return seNew;
}
void
STEPentity::STEPwrite_reference (ostream& out)
{
out << "#" << STEPfile_id;
}
const char *
STEPentity::STEPwrite_reference (SCLstring &buf)
{
char tmp[64];
sprintf ( tmp,"#%d", STEPfile_id);
buf = tmp;
return buf.chars();
}
STEPattribute *
STEPentity::GetSTEPattribute (const char * nm)
{
if (!nm) return 0;
STEPattribute *a =0;
ResetAttributes();
while ((a = NextAttribute () )
&& strcmp (nm, a ->Name()))
; // keep going untill no more attribute or attribute found
return a;
}
STEPattribute *
STEPentity::MakeDerived (const char * nm)
{
STEPattribute * a = GetSTEPattribute (nm);
if (a) a ->Derive ();
return a;
}
void
STEPentity::CopyAs (STEPentity * 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--;
}
}
/******************************************************************
// Checks the validity of the current attribute values for the entity
******************************************************************/
Severity STEPentity::ValidLevel(ErrorDescriptor *error, InstMgr *im,
int clearError)
{
ErrorDescriptor err;
if(clearError)
ClearError();
int n = attributes.list_length();
SCLstring tmp;
for (register int i = 0 ; i < n; i++) {
error->GreaterSeverity(attributes[i].ValidLevel(attributes[i].asStr(tmp),
&err, im, 0));
}
return error->severity();
}
/******************************************************************
// clears all attr's errors
******************************************************************/
void STEPentity::ClearAttrError()
{
int n = attributes.list_length();
for (register int i = 0 ; i < n; i++) {
attributes[i].Error().ClearErrorMsg();
}
}
/******************************************************************
// clears entity's error and optionally all attr's errors
******************************************************************/
void STEPentity::ClearError(int clearAttrs)
{
_error.ClearErrorMsg();
if(clearAttrs)
ClearAttrError();
}
/******************************************************************
******************************************************************/
/*
void STEPentity::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: ostream& out -- stream to write to
** Returns:
** Side Effects: writes out the SCOPE section for an entity
** Status: stub
******************************************************************/
void STEPentity::beginSTEPwrite(ostream& out)
{
out << "begin STEPwrite ... \n" ;
out.flush();
int n = attributes.list_length();
for (register 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: 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 STEPentity::STEPwrite(ostream& out)
{
SCLstring tmp;
out << "#" << STEPfile_id << "=" << StrToUpper (EntityName(), tmp) << "(";
int n = attributes.list_length();
for (register int i = 0 ; i < n; i++) {
(attributes[i]).STEPwrite(out);
if (i < n-1) out << ",";
}
out << ");\n";
}
void STEPentity::endSTEPwrite(ostream& out)
{
out << "end STEPwrite ... \n" ;
out.flush();
}
/******************************************************************
** Procedure: STEPwrite
** Problems: does not print out the SCOPE section of an entity
**
******************************************************************/
const char *
STEPentity::STEPwrite(SCLstring &buf)
{
buf.set_null();
char instanceInfo[BUFSIZ];
SCLstring tmp;
sprintf(instanceInfo, "#%d=%s(", STEPfile_id,
(char *)StrToUpper( EntityName(), tmp ) );
buf.Append(instanceInfo);
int n = attributes.list_length();
for (register int i = 0 ; i < n; i++) {
attributes[i].asStr(tmp) ;
buf.Append (tmp);
if (i < n-1) {
buf.Append( ',' );
}
}
buf.Append( ");" );
return buf.chars();
}
/******************************************************************
** Procedure: STEPentity::STEPread_error
** Parameters: char c -- character which caused error
** int i -- index of attribute which caused error
** 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
STEPentity::STEPread_error(char c, int i, istream& in)
{
char errStr[BUFSIZ];
errStr[0] = '\0';
/* 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 for 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
// cerr << " ERROR Trying to find the end of the ENTITY to recover...\n";
// cerr << " skipping the following input:\n";
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);
// cerr << c;
}
if(in.good() && (c == ')') )
{
in >> ws; // skip whitespace
in.get(c);
tmp.Append(c);
// cerr << c;
// cerr << "\n";
if(c == ';')
{
foundEnd = 1;
}
}
}
_error.AppendToDetailMsg( tmp.chars() );
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
** istream& in
** Side Effects: gobbles up input stream
** Status:
******************************************************************/
Severity
STEPentity::STEPread(int id, int idIncr, InstMgr * instance_set, istream& in)
{
STEPfile_id = id;
char c ='\0';
char errStr[BUFSIZ];
errStr[0] = '\0';
Severity severe;
ClearError(1);
int n = attributes.list_length();
for (register int i = 0 ; i < n; i++) {
attributes[i].STEPread(in, instance_set, idIncr);
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 == ')')
{
char z = in.peek();
if (z == ';')
{
in.get(c);
return _error.severity();
}
}
}
if(c != ')' )
{
STEPread_error(c,i,in);
return _error.severity();
}
in >> ws;
in >> c;
if (c != ';')
{
STEPread_error(c,i,in);
return _error.severity();
}
return _error.severity();
}
///////////////////////////////////////////////////////////////////////////////
// read an entity reference and return a pointer to the STEPentity
///////////////////////////////////////////////////////////////////////////////
STEPentity *
ReadEntityRef(istream &in, ErrorDescriptor *err, char *tokenList,
InstMgr * instances, int addFileId)
{
char c;
char errStr[BUFSIZ];
errStr[0] = '\0';
in >> 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)
{
cerr << "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
STEPentity* inst;
/* If there is a ManagerNode it should have a STEPentity */
MgrNode* mn =0;
mn = instances->FindFileId(id);
if (mn)
{
inst = mn->GetSTEPentity() ;
if (inst) { return (inst); }
else
{
cerr << "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 *
///////////////////////////////////////////////////////////////////////////////
STEPentity *
ReadEntityRef(const char * s, ErrorDescriptor *err, char *tokenList,
InstMgr * instances, int addFileId)
{
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(STEPentity *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);
cerr << "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 STEPentity argument.");
err->AppendToUserMsg(messageBuf);
err->AppendToDetailMsg(messageBuf);
cerr << "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->EntityDescriptor)
{
// is se a descendant of ed?
if ( se->EntityDescriptor->IsA(ed) )
{
return SEVERITY_NULL;
}
else
{
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(): STEPentity #%d has a %s",
se->STEPfile_id, "missing or invalid EntityDescriptor\n");
err->AppendToUserMsg(messageBuf);
err->AppendToDetailMsg(messageBuf);
cerr << "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.
STEPentity 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)
{
STEPentity *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: 7/31/90
******************************************************************/
STEPattribute *
STEPentity::NextAttribute () {
int i = AttributeCount ();
++_cur;
if (i < _cur) return 0;
return &attributes [_cur-1];
}
int
STEPentity::AttributeCount () {
return attributes.list_length ();
}