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 >
C/C++ Source or Header  |  1994-10-03  |  22KB  |  747 lines

  1.  
  2. /*
  3. * NIST STEP Core Class Library
  4. * clstepcore/STEPentity.cc
  5. * February, 1994
  6. * K. C. Morris
  7. * David Sauder
  8.  
  9. * Development of this software was funded by the United States Government,
  10. * and is not subject to copyright.
  11. */
  12.  
  13. /* $Id: STEPentity.cc,v 2.0.1.2 1994/05/10 21:03:10 kc Exp $ */
  14.  
  15. //static char rcsid[] ="$Id: STEPentity.cc,v 2.0.1.2 1994/05/10 21:03:10 kc Exp $";
  16.  
  17. #include <Sentity.h>
  18. #include <instmgr.h>
  19.  
  20. STEPentity NilSTEPentity;
  21.  
  22. /******************************************************************
  23. **      Functions for manipulating entities
  24.  
  25. **  KNOWN BUGs:  the STEPentity is not aware of the STEPfile; therefore
  26. **    it can not read comments which may be embedded in the instance.
  27. **    The following are known problems:
  28. **    -- does not handle comments embedded in an instance ==> bombs
  29. **    -- ignores embedded entities ==> does not bomb 
  30. **    -- error reporting does not include line number information  
  31. **/
  32.  
  33. STEPentity::STEPentity ()  
  34. :  _cur (0), STEPfile_id (0) 
  35. {
  36. }    
  37.  
  38. STEPentity::~STEPentity ()  
  39. {
  40.   STEPattribute * next =0;
  41.   ResetAttributes ();
  42.   while (next = NextAttribute ())  
  43.     delete next;
  44. }
  45.  
  46. STEPentity *STEPentity::Replicate()
  47. {
  48.     STEPentity *seNew = EntityDescriptor->NewSTEPentity();
  49.     seNew -> CopyAs (this);
  50.     return seNew;
  51. }
  52.  
  53. void 
  54. STEPentity::STEPwrite_reference (ostream& out)
  55. {  
  56.   out << "#" << STEPfile_id; 
  57. }
  58.  
  59. const char * 
  60. STEPentity::STEPwrite_reference (SCLstring &buf)
  61. {  
  62.     char tmp[64];
  63.     sprintf ( tmp,"#%d", STEPfile_id);
  64.     buf = tmp;
  65.     return buf.chars();
  66. }
  67.  
  68. STEPattribute * 
  69. STEPentity::GetSTEPattribute (const char * nm)
  70. {
  71.   if (!nm) return 0;
  72.   STEPattribute *a =0;
  73.  
  74.   ResetAttributes();    
  75.   while ((a = NextAttribute () )
  76.      && strcmp (nm, a ->Name()))
  77.     ;  // keep going untill no more attribute or attribute found
  78.  
  79.   return a;
  80. }
  81.  
  82. STEPattribute * 
  83. STEPentity::MakeDerived (const char * nm)
  84. {
  85.   STEPattribute * a = GetSTEPattribute (nm);
  86.   if (a)  a ->Derive ();
  87.   return a;
  88. }
  89.  
  90. void
  91. STEPentity::CopyAs (STEPentity * other)  
  92. {
  93.     int numAttrs = AttributeCount();
  94.     ResetAttributes();    
  95.     other -> ResetAttributes();    
  96.  
  97.     STEPattribute *this_attr = 0;
  98.     STEPattribute *other_attr = 0;
  99.     while((this_attr = NextAttribute()) && numAttrs)
  100.     {
  101.     other_attr = other -> NextAttribute();
  102.     this_attr -> ShallowCopy(other_attr);
  103.     numAttrs--;
  104.     }
  105. }
  106.  
  107. /******************************************************************
  108. // Checks the validity of the current attribute values for the entity
  109.  ******************************************************************/
  110.  
  111. Severity STEPentity::ValidLevel(ErrorDescriptor *error, InstMgr *im, 
  112.                      int clearError)
  113. {
  114.     ErrorDescriptor err;
  115.     if(clearError)
  116.     ClearError();
  117.     int n = attributes.list_length();
  118.     SCLstring tmp;
  119.     for (register int i = 0 ; i < n; i++) {
  120.     error->GreaterSeverity(attributes[i].ValidLevel(attributes[i].asStr(tmp),
  121.                             &err, im, 0));
  122.     }
  123.     return error->severity();
  124. }
  125.  
  126. /******************************************************************
  127.     // clears all attr's errors
  128.  ******************************************************************/
  129. void STEPentity::ClearAttrError()
  130. {
  131.     int n = attributes.list_length();
  132.     for (register int i = 0 ; i < n; i++) {
  133.     attributes[i].Error().ClearErrorMsg();
  134.     }
  135. }
  136.  
  137. /******************************************************************
  138.     // clears entity's error and optionally all attr's errors
  139.  ******************************************************************/
  140.  
  141. void STEPentity::ClearError(int clearAttrs)
  142. {
  143.     _error.ClearErrorMsg();
  144.     if(clearAttrs)
  145.     ClearAttrError();
  146.  
  147. /******************************************************************
  148.  ******************************************************************/
  149.  
  150. /*
  151. void STEPentity::EnforceOptionality(int on) 
  152. {
  153.     Enforcement e;
  154.     if(on) e = ENFORCE_OPTIONALITY;
  155.     else   e = ENFORCE_OFF;
  156.  
  157.     Error().enforcement(e); 
  158.     int n = attributes.list_length();
  159.     for (int i = 0 ; i < n; i++) {
  160.     attributes[i].Error().enforcement(e); 
  161.     }
  162. }
  163. */
  164. /******************************************************************
  165.  ** Procedure:  beginSTEPwrite
  166.  ** Parameters:  ostream& out -- stream to write to
  167.  ** Returns:  
  168.  ** Side Effects:  writes out the SCOPE section for an entity
  169.  ** Status:  stub 
  170.  ******************************************************************/
  171.  
  172. void STEPentity::beginSTEPwrite(ostream& out)
  173. {
  174.     out << "begin STEPwrite ... \n" ;
  175.     out.flush();
  176.     
  177.     int n = attributes.list_length();
  178.     for (register int i = 0 ; i < n; i++) {
  179.     if (attributes[i].Type () == ENTITY_TYPE
  180.         && *(attributes[i].ptr.c) != S_ENTITY_NULL)
  181.         (*(attributes[i].ptr.c)) -> STEPwrite();
  182.     }
  183. }
  184.  
  185. /******************************************************************
  186.  ** Procedure:  STEPwrite
  187.  ** Parameters:  ostream& out -- stream to write to
  188.  ** Returns:  
  189.  ** Side Effects:  writes out the data associated with an instance 
  190.                    in STEP format
  191.  ** Problems:  does not print out the SCOPE section of an entity
  192.  **
  193.  ******************************************************************/
  194.  
  195. void STEPentity::STEPwrite(ostream& out)
  196. {
  197.     SCLstring tmp;
  198.     out << "#" << STEPfile_id << "=" << StrToUpper (EntityName(), tmp) << "(";
  199.     int n = attributes.list_length();
  200.  
  201.     for (register int i = 0 ; i < n; i++) {
  202.     (attributes[i]).STEPwrite(out);
  203.     if (i < n-1) out << ",";
  204.     }
  205.     out << ");\n";
  206. }
  207.  
  208. void STEPentity::endSTEPwrite(ostream& out)
  209. {
  210.     out << "end STEPwrite ... \n" ;
  211.     out.flush();
  212. }
  213.  
  214.  
  215. /******************************************************************
  216.  ** Procedure:  STEPwrite
  217.  ** Problems:  does not print out the SCOPE section of an entity
  218.  **
  219.  ******************************************************************/
  220.  
  221. const char * 
  222. STEPentity::STEPwrite(SCLstring &buf)
  223. {
  224.     buf.set_null();
  225.  
  226.     char instanceInfo[BUFSIZ];
  227.     
  228.     SCLstring tmp;
  229.     sprintf(instanceInfo, "#%d=%s(", STEPfile_id, 
  230.         (char *)StrToUpper( EntityName(), tmp ) );
  231.     buf.Append(instanceInfo);
  232.  
  233.     int n = attributes.list_length();
  234.  
  235.     for (register int i = 0 ; i < n; i++) {
  236.       attributes[i].asStr(tmp) ;
  237.       buf.Append (tmp);
  238.     if (i < n-1) {
  239.         buf.Append( ',' );
  240.     }
  241.     }    
  242.     buf.Append( ");" );
  243.     return buf.chars();
  244. }
  245.  
  246. /******************************************************************
  247.  ** Procedure:  STEPentity::STEPread_error
  248.  ** Parameters:  char c --  character which caused error
  249.  **     int i --  index of attribute which caused error
  250.  **     istream& in  --  input stream for recovery
  251.  ** Returns:  
  252.  ** Description:  reports the error found, reads until it finds the end of an
  253.  **     instance. i.e. a close quote followed by a semicolon optionally having
  254.  **     whitespace between them.
  255.  ******************************************************************/
  256. void
  257. STEPentity::STEPread_error(char c, int i, istream& in)
  258. {
  259.     char errStr[BUFSIZ];
  260.     errStr[0] = '\0';
  261.  
  262. /*    sprintf(errStr, " for instance #%d : %s\n", STEPfile_id, EntityName());*/
  263. /*    _error.AppendToDetailMsg(errStr);*/
  264.  
  265.     if ( (i >= 0) && (i < attributes.list_length()))  // i is an attribute 
  266.     {
  267.       Error ().GreaterSeverity (SEVERITY_WARNING);
  268.       sprintf(errStr, "  invalid data for type \'%s\'\n", 
  269.           attributes[i].TypeName()); 
  270.       _error.AppendToDetailMsg(errStr);
  271.     }
  272.     else
  273.       {
  274.     Error ().GreaterSeverity (SEVERITY_INPUT_ERROR);
  275.     _error.AppendToDetailMsg("  No more attributes were expected.\n");
  276.       }
  277.  
  278.     SCLstring tmp;
  279.     STEPwrite (tmp);  // STEPwrite writes to a static buffer inside function
  280.     sprintf(errStr, 
  281.         "  The invalid instance to this point looks like :\n%s\n", 
  282.         tmp.chars() );
  283.     _error.AppendToDetailMsg(errStr);
  284.     
  285.     _error.AppendToDetailMsg("  data lost looking for end of entity:");
  286.  
  287.     //  scan over the rest of the instance and echo it
  288. //    cerr << "  ERROR Trying to find the end of the ENTITY to recover...\n";
  289. //    cerr << "  skipping the following input:\n";
  290.  
  291.     in.clear();
  292.     int foundEnd = 0;
  293.     tmp = "";
  294.  
  295.     // Search until a close paren is found followed by (skipping optional 
  296.     // whitespace) a semicolon
  297.     while( in.good() && !foundEnd )
  298.     {
  299.     while ( in.good() && (c != ')') )  
  300.     {
  301.         in.get(c);
  302.         tmp.Append(c);
  303. //        cerr << c;
  304.     }
  305.     if(in.good() && (c == ')') )
  306.     {
  307.         in >> ws; // skip whitespace
  308.         in.get(c);
  309.         tmp.Append(c);
  310. //        cerr << c;
  311. //        cerr << "\n";
  312.         if(c == ';')
  313.         {
  314.         foundEnd = 1;
  315.         }
  316.     }
  317.     }
  318.     _error.AppendToDetailMsg( tmp.chars() );
  319.     sprintf (errStr, "\nfinished reading #%d\n", STEPfile_id);
  320.     _error.AppendToDetailMsg(errStr);
  321.     return;
  322. }
  323.  
  324. /******************************************************************
  325.  ** Procedure:  STEPread
  326.  ** Returns:    Severity, error information
  327.  **             SEVERITY_NULL - no errors
  328.  **             SEVERITY_USERMSG - checked as much as possible, could still 
  329.  **            be error - e.g. entity didn't match base entity type.
  330.  **             SEVERITY_INCOMPLETE - data is missing and required.
  331.  **             SEVERITY_WARNING - errors, but can recover
  332.  **             <= SEVERITY_INPUT_ERROR - fatal error, can't recover
  333.  ** Description:  reads the values for an entity from an input stream
  334.  **               in STEP file format starting at the open paren and
  335.  **               ending with the semi-colon
  336.  ** Parameters:  int id
  337.  **              int idIncrement
  338.  **              InstMgr instances
  339.  **              istream& in
  340.  ** Side Effects:  gobbles up input stream
  341.  ** Status:
  342.  ******************************************************************/
  343.  
  344. Severity
  345. STEPentity::STEPread(int id,  int idIncr, InstMgr * instance_set, istream& in)
  346. {
  347.     STEPfile_id = id;
  348.     char c ='\0';
  349.     char errStr[BUFSIZ];
  350.     errStr[0] = '\0';
  351.     Severity severe;
  352.  
  353.     ClearError(1);
  354.  
  355.     int n = attributes.list_length();
  356.     for (register int i = 0 ; i < n; i++) {
  357.         attributes[i].STEPread(in, instance_set, idIncr);
  358.  
  359.     severe = attributes[i].Error().severity();
  360.  
  361.         if(severe <= SEVERITY_USERMSG)
  362.     {  // if there\'s some type of error
  363.         if(_error.severity() == SEVERITY_NULL)
  364.         {  //  if there is not an error already
  365.         sprintf(errStr, "\nERROR:  ENTITY #%d %s\n", GetFileId(), 
  366.             EntityName());
  367.         _error.PrependToDetailMsg(errStr);
  368.         }
  369.         // set the severity for this entity
  370.         sprintf (errStr, "  %s :  ", attributes[i].Name());
  371.         _error.AppendToDetailMsg(errStr);
  372.         _error.GreaterSeverity(severe);
  373.         _error.AppendToDetailMsg((char *)
  374.                      attributes[i].Error().DetailMsg());
  375.         _error.AppendToUserMsg((char *)attributes[i].Error().UserMsg());
  376.  
  377.     }
  378. /*
  379.     if(severe <= SEVERITY_INPUT_ERROR)
  380.     {    // attribute\'s error is non-recoverable 
  381.         // I believe if this error occurs then you cannot recover
  382.  
  383.       //  TODO: can you just read to the next comma and try to continue ?
  384.         STEPread_error(c,i,in);
  385.         return _error.severity();
  386.     }
  387. */
  388.     in >> c;
  389.     if ( ! ((c == ',') || (c == ')' ))) { //  input is not a delimiter
  390.         if(_error.severity() == SEVERITY_NULL)
  391.         {  //  if there is not an error already
  392.         sprintf(errStr, "\nERROR:  ENTITY #%d %s\n", GetFileId(), 
  393.             EntityName());
  394.         _error.PrependToDetailMsg(errStr);
  395.         }
  396.         _error.AppendToDetailMsg(
  397.                 "delimiter expected after attribute value.\n");
  398.         CheckRemainingInput(in, &_error, "ENTITY", ",)");
  399.         if(!in.good())
  400.         return _error.severity();
  401.         if(_error.severity() <= SEVERITY_INPUT_ERROR)
  402.         {
  403.         STEPread_error(c,i,in);
  404.         return _error.severity();
  405.         }
  406.     }
  407.     else if(c == ')')
  408.     {
  409.         char z = in.peek();
  410.         if (z == ';')
  411.         {
  412.         in.get(c);
  413.         return _error.severity();
  414.         }
  415.     }
  416.     }
  417.     if(c != ')' )
  418.     {
  419.     STEPread_error(c,i,in);
  420.     return _error.severity();
  421.     }
  422.     in >> ws;
  423.     in >> c;
  424.     if (c != ';')
  425.     {
  426.     STEPread_error(c,i,in);
  427.     return _error.severity();
  428.     }
  429.     return _error.severity();
  430. }
  431.  
  432.  
  433. ///////////////////////////////////////////////////////////////////////////////
  434. // read an entity reference and return a pointer to the STEPentity
  435. ///////////////////////////////////////////////////////////////////////////////
  436.  
  437. STEPentity *
  438. ReadEntityRef(istream &in, ErrorDescriptor *err, char *tokenList, 
  439.           InstMgr * instances, int addFileId)
  440. {
  441.     char c;
  442.     char errStr[BUFSIZ];
  443.     errStr[0] = '\0';
  444.     
  445.     in >> ws;
  446.     in >> c;
  447.     switch (c)
  448.     {
  449.       case '@':
  450.         err->AppendToDetailMsg(
  451.                 "Use of @ instead of # to identify entity.\n");
  452.         err->GreaterSeverity(SEVERITY_WARNING);
  453.         // no break statement here on purpose
  454.       case '#':
  455.     {
  456.         int id = -1; 
  457.         int n = 0;
  458.         in >>  id;
  459.         if (in.fail ())  //  there's been an error in input
  460.         {
  461. //        in.clear();
  462.         sprintf(errStr,"Invalid entity reference value.\n");
  463.         err->AppendToDetailMsg(errStr);
  464.         err->AppendToUserMsg(errStr);
  465.         err->GreaterSeverity(SEVERITY_WARNING);
  466.         CheckRemainingInput(in, err, "Entity Reference", tokenList);
  467.         return S_ENTITY_NULL;
  468.         }
  469.         else // found an entity id
  470.         {
  471.         // check to make sure garbage does not follow the id
  472.         CheckRemainingInput(in, err, "Entity Reference", tokenList);
  473.  
  474.         id += addFileId;
  475.         if (!instances)
  476.         {
  477.             cerr << "Internal error:  " << __FILE__ <<  __LINE__
  478.              << "\n" << _POC_ "\n";
  479.             sprintf(errStr, 
  480.                 "STEPread_reference(): %s - entity #%d %s.\n",
  481.                 "BUG - cannot read reference without the InstMgr", 
  482.                  id, "is unknown");
  483.             err->AppendToDetailMsg(errStr);
  484.             err->AppendToUserMsg(errStr);
  485.             err->GreaterSeverity(SEVERITY_BUG);
  486.             return S_ENTITY_NULL;
  487.         }
  488.     
  489.         //  lookup which object has id as its instance id
  490.         STEPentity* inst;
  491.         /* If there is a ManagerNode it should have a STEPentity */
  492.         MgrNode* mn =0;
  493.         mn = instances->FindFileId(id);
  494.         if (mn)
  495.         {
  496.             inst =  mn->GetSTEPentity() ;
  497.             if (inst) { return (inst); }
  498.             else
  499.             {
  500.             cerr << "Internal error:  " << __FILE__ <<  __LINE__
  501.                  << "\n" << _POC_ "\n";
  502.             sprintf(errStr, 
  503.                 "STEPread_reference(): %s - entity #%d %s.\n",
  504.               "BUG - MgrNode::GetSTEPentity returned NULL pointer",
  505.                 id, "is unknown");
  506.             err->AppendToDetailMsg(errStr);
  507.             err->AppendToUserMsg(errStr);
  508.             err->GreaterSeverity(SEVERITY_BUG);
  509.             return S_ENTITY_NULL;
  510.             }
  511.         }
  512.         else
  513.         {
  514.             sprintf(errStr,"Reference to non-existent ENTITY #%d.\n", 
  515.                 id);
  516.             err->AppendToDetailMsg(errStr);
  517.             err->AppendToUserMsg(errStr);
  518.             err->GreaterSeverity(SEVERITY_WARNING);
  519.             return S_ENTITY_NULL;
  520.         }
  521.         }
  522.     }
  523.       default:
  524.     {
  525.         in.putback(c);
  526.         // read past garbage up to delim in tokenList
  527.         // if tokenList is null it will not read anything
  528.         CheckRemainingInput(in, err, "Entity Reference", tokenList);
  529.         return S_ENTITY_NULL;
  530.     }
  531.     }
  532. }
  533.  
  534. ///////////////////////////////////////////////////////////////////////////////
  535. // same as above but reads from a const char *
  536. ///////////////////////////////////////////////////////////////////////////////
  537.  
  538. STEPentity *
  539. ReadEntityRef(const char * s, ErrorDescriptor *err, char *tokenList, 
  540.           InstMgr * instances, int addFileId)
  541. {
  542.     istrstream in((char *)s);
  543.     return ReadEntityRef(in, err, tokenList, instances, addFileId);
  544. }
  545.  
  546. ///////////////////////////////////////////////////////////////////////////////
  547. // return SEVERITY_NULL if se's entity type matches the supplied entity type
  548. ///////////////////////////////////////////////////////////////////////////////
  549.  
  550. Severity 
  551. EntityValidLevel(STEPentity *se, 
  552.          const TypeDescriptor *ed, // entity type that entity se needs 
  553.                        // to match. (this must be an
  554.                        // EntityDescriptor)
  555.          ErrorDescriptor *err)
  556. {
  557.     char messageBuf [BUFSIZ];
  558.     messageBuf[0] = '\0';
  559.  
  560.     if( !ed || (ed->NonRefType() != ENTITY_TYPE) )
  561.     {
  562.     err->GreaterSeverity(SEVERITY_BUG);
  563.     sprintf(messageBuf, 
  564.         " BUG: EntityValidLevel() called with %s", 
  565.         "missing or invalid EntityDescriptor\n");
  566.     err->AppendToUserMsg(messageBuf);
  567.     err->AppendToDetailMsg(messageBuf);
  568.     cerr << "Internal error:  " << __FILE__ <<  __LINE__
  569.            << "\n" << _POC_ "\n";
  570.     return SEVERITY_BUG;
  571.     }
  572.     if(!se || (se == S_ENTITY_NULL))
  573.     {
  574.     err->GreaterSeverity(SEVERITY_BUG);
  575.     sprintf(messageBuf, 
  576.         " BUG: EntityValidLevel() called with null pointer %s\n", 
  577.         "for STEPentity argument.");
  578.     err->AppendToUserMsg(messageBuf);
  579.     err->AppendToDetailMsg(messageBuf);
  580.     cerr << "Internal error:  " << __FILE__ <<  __LINE__
  581.            << "\n" << _POC_ "\n";
  582.     return SEVERITY_BUG;
  583.     }
  584.  
  585.     // DAVE: Can an entity be used in an Express TYPE so that this 
  586.     // EntityDescriptor would have type REFERENCE_TYPE -- it looks like NO
  587.  
  588.     else if(se->EntityDescriptor)
  589.     {
  590.     // is se a descendant of ed?
  591.     if ( se->EntityDescriptor->IsA(ed) )
  592.     {
  593.         return SEVERITY_NULL;
  594.     }
  595.     else
  596.     {
  597.         err->GreaterSeverity(SEVERITY_WARNING);
  598.         sprintf(messageBuf,
  599.             " Entity #%d exists but is not a %s or descendant.\n", 
  600.             se->STEPfile_id, ed->Name());
  601.         err->AppendToUserMsg(messageBuf);
  602.         err->AppendToDetailMsg(messageBuf);
  603.         return SEVERITY_WARNING;
  604.     }
  605.     }
  606.     else
  607.     {
  608.     err->GreaterSeverity(SEVERITY_BUG);
  609.     sprintf(messageBuf, 
  610.         " BUG: EntityValidLevel(): STEPentity #%d has a %s", 
  611.         se->STEPfile_id, "missing or invalid EntityDescriptor\n");
  612.     err->AppendToUserMsg(messageBuf);
  613.     err->AppendToDetailMsg(messageBuf);
  614.     cerr << "Internal error:  " << __FILE__ <<  __LINE__
  615.            << "\n" << _POC_ "\n";
  616.     return SEVERITY_BUG;
  617.     }
  618. }
  619.  
  620. ///////////////////////////////////////////////////////////////////////////////
  621. // return 1 if attrValue has the equivalent of a null value.
  622. ///////////////////////////////////////////////////////////////////////////////
  623.  
  624. int 
  625. SetErrOnNull  (const char *attrValue, ErrorDescriptor *error)
  626. {
  627. // DAVE: Is this needed will sscanf return 1 if assignment suppression is used?
  628.     char scanBuf[BUFSIZ];
  629.     scanBuf[0] = '\0';
  630.  
  631.     int numFound = sscanf((char *)attrValue," %s", scanBuf);
  632.     if (numFound == EOF) {
  633. /*
  634.     if(Nullable()) {
  635.         error->GreaterSeverity (SEVERITY_NULL);
  636.     }
  637.     else {
  638.         error->GreaterSeverity (SEVERITY_INCOMPLETE);
  639.     }
  640. */
  641.     error->GreaterSeverity (SEVERITY_INCOMPLETE);
  642.     return 1;
  643.     }
  644.     return 0;
  645. }
  646.  
  647. ///////////////////////////////////////////////////////////////////////////////
  648. // return SEVERITY_NULL if attrValue has a valid entity reference
  649. // This function accepts an entity reference in two forms that is with or 
  650. // without the # sign: e.g. either #23 or 23 will be read.
  651. // If non-whitespace characters follow the entity reference an error is set.
  652. ///////////////////////////////////////////////////////////////////////////////
  653.  
  654. Severity 
  655. EntityValidLevel(const char *attrValue, // string contain entity ref
  656.          const TypeDescriptor *ed, // entity type that entity in 
  657.                        // attrValue (if it exists) needs 
  658.                        // to match. (this must be an
  659.                        // EntityDescriptor)
  660.            ErrorDescriptor *err, InstMgr *im, int clearError)
  661. {
  662.     char tmp [BUFSIZ];
  663.     tmp[0] = '\0';
  664.     char messageBuf [BUFSIZ];
  665.     messageBuf[0] = '\0';
  666.  
  667.     if(clearError)
  668.     err->ClearErrorMsg();
  669.  
  670. /*
  671.   // the problem with doing this is that it will require having a # in front
  672.   // of the entity ref.
  673.     STEPentity se = ReadEntityRef(attrValue, err, 0, im, 0);
  674.     return EntityValidLevel(se, ed, err);
  675. */
  676.  
  677.     int fileId;
  678.     MgrNode *mn = 0;
  679.  
  680.     // check for both forms:  #id or id
  681.     int found1 = sscanf((char *)attrValue, " #%d %s", &fileId, tmp);
  682.     int found2 = sscanf((char *)attrValue, " %d %s", &fileId, tmp);
  683.  
  684.     if( (found1 > 0) || (found2 > 0) )
  685.     {
  686.     if ( (found1 == 2) || (found2 == 2) )
  687.     {
  688.         sprintf(messageBuf, 
  689.            " Attribute's Entity Reference %s is %s data \'%s\'.\n",
  690.             attrValue, "followed by invalid", tmp);
  691.         err->AppendToUserMsg(messageBuf);
  692.         err->AppendToDetailMsg(messageBuf);
  693.         err->GreaterSeverity(SEVERITY_WARNING);
  694.     }
  695.     mn = im->FindFileId(fileId);
  696.     if(mn)
  697.     {
  698.         STEPentity *se = mn->GetSTEPentity();
  699.         return EntityValidLevel(se, ed, err);
  700.     }
  701.     else { 
  702.         sprintf(messageBuf, 
  703.            " Attribute's Entity Reference %s does not exist.\n",
  704.             attrValue);
  705.         err->AppendToUserMsg(messageBuf);
  706.         err->AppendToDetailMsg(messageBuf);
  707.         err->GreaterSeverity(SEVERITY_WARNING);
  708.         return SEVERITY_WARNING;
  709.     }
  710.     }
  711.  
  712.     // if the attrValue contains no value return
  713.     if (SetErrOnNull (attrValue, err))
  714.     return err->severity();
  715.  
  716.     sprintf(messageBuf, "Invalid attribute entity reference value: '%s'.\n", 
  717.         attrValue);
  718.     err->AppendToUserMsg(messageBuf);
  719.     err->AppendToDetailMsg(messageBuf);
  720.     err->GreaterSeverity(SEVERITY_WARNING);
  721.     return SEVERITY_WARNING;
  722. }
  723.  
  724. /******************************************************************
  725.  ** Procedure:  NextAttribute
  726.  ** Parameters:  
  727.  ** Returns:  reference to an attribute pointer
  728.  ** Description:  used to cycle through the list of attributes
  729.  ** Side Effects:  increments the current position in the attribute list
  730.  ** Status:   7/31/90
  731.  ******************************************************************/
  732.  
  733. STEPattribute *
  734. STEPentity::NextAttribute ()  {
  735.     int i = AttributeCount ();
  736.     ++_cur;
  737.     if (i < _cur) return 0;
  738.     return &attributes [_cur-1];
  739.  
  740. }
  741.     
  742. int 
  743. STEPentity::AttributeCount ()  {
  744.     return  attributes.list_length ();
  745. }
  746.