Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

PropertyCompiler.cpp

Go to the documentation of this file.
00001 // $Header: /nfs/slac/g/glast/ground/cvs/GaudiSvc/src/JobOptionsSvc/PropertyCompiler.cpp,v 1.1.1.3 2001/04/18 18:32:50 tlindner Exp $
00002 
00003 // PropertyCompiler:
00004 //
00005 // 1.) get tokens
00006 // 2.) get NTS and TS
00007 // 3.) create Property-Objects
00008 
00009 //
00010 // Changes 9/3/2001 By M.Frank:
00011 // - Add value-of operator '@' to assign a job option the value of another option
00012 //   Usage:
00013 //        MyAlg.OutputLevel = @MessageSvc.OutputLevel;
00014 //        ApplicationMgr.TopAlgs += { @ApplicationMgr.ExtSvc };
00015 //   Note:
00016 //        The value-of of a vector addresses the elements, not the vector itself.
00017 // - Allow reset of vector lists to empty lists.
00018 //   Usage:
00019 //        ApplicationMgr.TopAlgs += {};
00020 //
00021 //
00022 #ifdef _WIN32
00023 #pragma warning( disable : 4786 )
00024 #endif
00025 // STL include files 
00026 #include <iostream>
00027 #include <strstream>
00028 #include <fstream>
00029 #include <string>
00030 #include <vector>
00031 
00032 #include "PropertyCompiler.h"
00033 #include "GaudiKernel/xtoa.h"
00034 #include "GaudiKernel/Property.h"
00035 
00036 #ifdef WIN32
00037    static const bool win_32=true;
00038 #else
00039    static const bool win_32=false;
00040 #endif
00041 
00042 // ---- LEXICAL ANALYZER ----
00043 
00048 PropertyCompiler::PropertyCompiler(std::string sourcefile, MsgStream& my_log, JobOptionsCatalogue& my_Cat, PropertyCompiler* parent)
00049 : m_log(&my_log), m_Cat(&my_Cat)
00050 {
00051    if ( 0 != parent )   {
00052      includeFiles = parent->includeFiles;
00053      unitsDefined = parent->unitsDefined;
00054      units        = parent->units;
00055      hasParent    = true;
00056    }
00057    else   {
00058      includeFiles = new std::vector <std::string>();
00059      units        = new UnitsExtension();
00060      unitsDefined = false;
00061      hasParent    = false;
00062    }
00063 
00064    // Resolve include-File
00065    sourcefile=resolveEnv(sourcefile);
00074    // put include-file into list with includes
00075    m_errorCount=0;m_warningCount=0;
00076    m_srcName=sourcefile;
00077    m_sy=BOFSy;                            // Begin of File
00078    // BUG-Fix #009: First line with comments is not printed out!
00079    m_error=false; 
00080    // EOBF
00081 
00082    m_in=new std::ifstream(sourcefile.c_str());
00083    if (m_in->fail())
00084    {
00085       *m_log << endreq << MSG::ERROR << "Error #001: Specified property-file " << sourcefile 
00086              << " does not exists or can not be opened! " << endreq;
00087       m_errorCount++;
00088       return;
00089    } // if
00090    
00091    for(std::vector<std::string>::iterator i = includeFiles->begin(); i != includeFiles->end(); i++ )  {
00092      if (sourcefile == *i)       {           // File already included!
00093          *m_log << endreq << MSG::WARNING << "Warning #001: Specified property-file " 
00094                 << sourcefile << " was already included by another property-file! " << endreq;
00095          m_warningCount++;
00096          return;
00097      } // if
00098    } // for
00099    includeFiles->push_back(sourcefile);         // File not included yet! 
00100 } // Constructor
00101 
00102 
00105 PropertyCompiler::~PropertyCompiler()
00106 {
00107   if ( !hasParent )   {
00108     delete includeFiles;
00109     delete units;
00110   }
00111   units = 0;
00112   includeFiles = 0;
00113   m_in->close();
00114 } // Destructor
00115 
00118 std::string PropertyCompiler::resolveEnv(const std::string& sourcefile)    {
00119    std::string originalName = sourcefile;
00120    std::string environmentVar="";
00121    std::string resolvedFile  ="";
00122    bool        inEnvironmentVar=false;
00123    bool        unixStyle       =false;
00124    unsigned int i;
00125   
00126    // resolve environment-settings
00127    // search for special character $ or %
00128    for (i=0;i<sourcefile.length();i++)   {
00129      if (sourcefile[i]=='$')      {           // read in until end or next /
00130          inEnvironmentVar = true;
00131          unixStyle        = true;
00132       }
00133       else if (sourcefile[i]=='%')      {
00134          inEnvironmentVar = (!inEnvironmentVar);
00135          unixStyle = false;
00136       }
00137       else if (inEnvironmentVar)      {
00138          if ((sourcefile[i]=='/') || (sourcefile[i]=='\\'))         {
00139             if (unixStyle)                // character which shows that end of environment-variable is reached
00140                inEnvironmentVar=false;
00141                                           // under NT these characters can be part of variable!
00142          } // if
00143          if (inEnvironmentVar)
00144             environmentVar=environmentVar+sourcefile[i];
00145       } // else if     
00146       else      {
00147          resolvedFile = resolvedFile + sourcefile[i];
00148       }
00149 
00150       if ((! inEnvironmentVar) && (environmentVar!=""))      {
00151          char* resFile;
00152          resFile = ::getenv(environmentVar.c_str());
00153          if (resFile==0)    {
00154            return originalName;
00155          }
00156          else   {
00157            resolvedFile=resolvedFile + resFile;
00158          }
00159          if (unixStyle)         {
00160             resolvedFile=resolvedFile+'/';         // add missing end-character!
00161             unixStyle=false;
00162          }
00163          environmentVar="";
00164       }
00165    } // for
00166 
00167    if ((inEnvironmentVar) && (environmentVar!="") && (unixStyle))   {
00168       // was at the end of the string!
00169       char* resFile;
00170 
00171       resFile = getenv(environmentVar.c_str());
00172       if (resFile==0)
00173          return originalName;
00174       else
00175          resolvedFile=resolvedFile + resFile;
00176 
00177       environmentVar="";
00178       unixStyle=false;
00179       inEnvironmentVar=false;
00180    } // if
00181 
00182    if (inEnvironmentVar)
00183       // ERROR!
00184       return originalName;
00185 
00186    return resolvedFile;
00187 }
00188 
00189 
00192 void PropertyCompiler::newCh()
00193 {
00194    char readedSrcChar='\0';
00195 
00196    if (m_cnr < m_srcLine.length())
00197    {
00198       m_cnr=m_cnr+1;
00199       m_ch=m_srcLine[m_cnr-1];                       // -1 because m_in C++ strings begins with 0!
00200    } // if
00201    else                                              // have to read next line
00202    {
00203       if (m_compiledLine=="")                        // Check first, if printout of compilation-code
00204          m_compiledLine='\n'+m_srcLine;              // is possible... (only if statement is compiled)
00205       else 
00206          m_compiledLine=m_compiledLine+'\n'+m_srcLine;    // not printed out yet, add new statement!
00207 
00208       if (! m_in->eof())                                // read next line
00209       {
00210          m_srcLine="";
00211          while ((readedSrcChar != '\n') && (! m_in->eof()))  {
00212             readedSrcChar='\0';
00213             m_in->get(readedSrcChar);
00214             if ((readedSrcChar != '\n') && (! m_in->eof()))
00215                m_srcLine=m_srcLine+readedSrcChar;
00216          } // while 
00217          m_lnr=m_lnr+1;
00218          m_cnr=0;
00219          m_ch='\n';
00220       } // if
00221       else
00222       {
00223          m_ch=0;                                          // EOF is detected.
00224       } // else
00225    } // else
00226 } // newCh
00227 
00228 
00232 std::string PropertyCompiler::newSy()   {
00233    if (m_sy==noSy)               // There was already an error before from which compiler could not recover!
00234       return "";
00235 
00236    std::string numberStr="";
00237    std::string stringStr="";
00238    std::string identifierStr="";
00239 
00240    // Output-relevant: m_error-Indicator of Line and Column...
00241    m_tokenlnr=m_lnr;
00242    m_tokencnr=m_cnr+1;                              // because character of next token not read yet!
00243 
00244    while ((m_ch==' ') || (m_ch==9) || (m_ch=='\n') || (m_ch=='\r'))   // overread blanks, tabs and newlines
00245    {
00246       newCh();
00247    } // while
00248 
00249    if (m_ch=='/')                                 // overread possible comments
00250    {
00251       char oldCh=' ';
00252       int inComment=0;     // 0: no comment
00253                            // 1: /*...*/ comment
00254                            // 2: // comment
00255 
00256       newCh();
00257       if (m_ch=='*')
00258       {
00259          inComment=1;
00260          newCh();
00261       } // if
00262       else if (m_ch=='/')
00263       {
00264          inComment=2;
00265          newCh();
00266       } // else if
00267 
00268       while (inComment != 0)
00269       {
00270          // BUG-FIX #008: Compiler hangs up if // is m_in last line or /* not terminated by */
00271          if (m_ch==0)
00272          {
00273             inComment=0;
00274             m_sy=EOFSy;
00275             return "";
00276          } // if
00277          // EOBF
00278 
00279          if ((inComment==1) && (oldCh=='*') && (m_ch=='/'))
00280          {
00281             inComment=0;
00282          } // if
00283          else if ((inComment==2) && (m_ch=='\n'))
00284          {
00285             inComment=0;
00286          } // else if
00287          oldCh=m_ch; 
00288          newCh();
00289       } // while
00290       return newSy();                             // Restart Symbol detection by recursive call!
00291    } // if
00292                    
00293    if (m_ch==0)                                   // EOF detected!
00294    {
00295       m_sy=EOFSy;
00296    } // if
00297    else if (m_ch=='=')                            // Assign-Symbol detected.
00298    {
00299       m_sy=assignSy;
00300       newCh();
00301    } // else if
00302    else if (m_ch==';')                            // Semicolon-Symbol detected.
00303    {
00304       m_sy=semicolonSy;
00305       newCh();
00306    } // else if
00307    else if (m_ch==',')                            // Comma-Symbol detected.
00308    {
00309       m_sy=commaSy;
00310       newCh();
00311    } // else if
00312    else if (m_ch=='-')
00313    {
00314       m_sy=minusSy;
00315       newCh();
00316    } // else if
00317    else if (m_ch=='{')
00318    {
00319       m_sy=vectorStartSy;
00320       newCh();
00321    } // else if
00322    else if (m_ch=='+')
00323    {
00324       newCh();
00325       if (m_ch=='=')
00326       {
00327          m_sy=appendSy;
00328          newCh();
00329       }
00330       else
00331          m_sy=plusSy;
00332    } // else if
00333    else if (m_ch=='}')
00334    {
00335       m_sy=vectorEndSy;
00336       newCh();
00337    } // else if
00338    else if (m_ch=='"')                            // String-Symbol detected.
00339    {
00340       m_sy=stringSy;
00341       newCh();
00342       while (m_ch!='"')
00343       {
00344          stringStr += m_ch;
00345          newCh();
00346          while (m_ch=='\n')
00347             newCh();
00348 
00349          if (m_ch==0) // EOF -> final " is missing!!!
00350          {
00351             *m_log << endreq << MSG::ERROR << "Error #006 in line " << m_tokenlnr 
00352                    << " at column " << m_tokencnr-1 << ": String not terminated by \" " << endreq;
00353             m_errorCount++;
00354             m_error=true;
00355             m_ch='"';                             // add missing " to get out of loop!
00356             m_sy=EOFSy;
00357          } // if
00358       } // while
00359       newCh();
00360       return stringStr;
00361    } // else if
00362    else if ((m_ch>='0') && (m_ch<='9'))                 // Number-Symbol detected.
00363    {
00364       m_sy=numberSy;
00365       while ((m_ch>='0') && (m_ch<='9'))
00366       {
00367          numberStr=numberStr+m_ch;
00368          newCh();
00369       } // while
00370       return numberStr;
00371    } // else if
00372    else if (m_ch=='.')                                // Dot-Symbol detected.
00373    {
00374       m_sy=dotSy;
00375       newCh();
00376    } // else if
00377    else if ( ((m_ch>='A') && (m_ch<='Z')) ||             
00378              ((m_ch>='_') && (m_ch<='z')) )          // Identifier-Symbol detected.
00379    {
00380       m_sy=identifierSy;
00381       while (((m_ch>='0') && (m_ch<='9')) || ((m_ch>='A') && (m_ch<='Z')) || ((m_ch>='_') && (m_ch<='z')))
00382       {
00383          identifierStr=identifierStr+m_ch;
00384          newCh();
00385       } // while
00386 
00387       if ((identifierStr=="true") || (identifierStr=="false"))  // boolean-Symbol detected.
00388       {
00389          m_sy=booleanSy;
00390       } // recognizes boolean-type!
00391       return identifierStr;
00392    } // else if   
00393    else if (m_ch=='#')                                          // special functions
00394    {
00395       newCh();
00396       while (((m_ch>='0') && (m_ch<='9')) || ((m_ch>='A') && (m_ch<='Z')) || ((m_ch>='_') && (m_ch<='z')))
00397       {
00398          identifierStr=identifierStr+m_ch;
00399          newCh();
00400       } // while
00401       if (identifierStr=="include")
00402          m_sy=includeSy;
00403       else if (identifierStr=="ifdef")
00404          m_sy=ifDefSy;
00405       else if (identifierStr=="ifndef")
00406          m_sy=ifNDefSy;
00407       else if (identifierStr=="endif")
00408          m_sy=endIfSy;
00409       else if (identifierStr=="else")
00410          m_sy=elseSy;
00411       else if (identifierStr=="units")
00412          m_sy=unitsSy;
00413       else
00414          m_sy=noSy;
00415    } // else if
00416    else if (m_ch=='$')   {
00417      identifierStr = m_ch;
00418      newCh();
00419      while (((m_ch>='0') && (m_ch<='9')) || ((m_ch>='A') && (m_ch<='Z')) || ((m_ch>='_') && (m_ch<='z')))    {
00420        identifierStr += m_ch;
00421        newCh();
00422      } // while
00423      m_sy = envSy;
00424      return identifierStr;
00425    }
00426    else if (m_ch=='@')   {
00427      identifierStr = m_ch;
00428      newCh();
00429      while (((m_ch>='0') && (m_ch<='9')) || ((m_ch>='A') && (m_ch<='Z')) || ((m_ch>='_') && (m_ch<='z')) || m_ch=='.' )    {
00430        identifierStr += m_ch;
00431        newCh();
00432      } // while
00433      m_sy = propSy;
00434      return identifierStr;
00435    }
00436    else   {
00437       m_sy=noSy;
00438    } // else
00439 
00440    return "";       // if nothing other is returned before then returned zero-string
00441 } // NewSymbol
00442 
00443 
00444 // ---- PARSER / Syntax Analyzer ----
00448 bool PropertyCompiler::isNextEntryPoint() 
00449 {
00450    if (m_sy==semicolonSy)
00451    {
00452       newSy();
00453       return true;
00454    } // if
00455    return false;
00456 } // isNextEntryPoint
00457 
00458 
00462 PropertyCompiler::Symbols PropertyCompiler::getValueType(std::string& valueStr)   {
00463    Symbols value=noSy;
00464    std::string returnValue;
00465    bool negation=false;
00466 
00467    if (m_sy==stringSy)     {                       // STRING
00468      newSy();
00469      value=stringSy;
00470    } // if
00471    else if (m_sy == envSy )   {
00472      newSy();
00473      value = envSy;
00474    }
00475    else if (m_sy == propSy )   {
00476      newSy();
00477      value = propSy;
00478    }
00479    else if (m_sy==booleanSy)    {                  // BOOLEAN
00480       newSy();
00481       value=booleanSy;
00482    } // else if
00483    else if (m_sy==minusSy)   {
00484       returnValue=newSy();
00485       if (m_sy!=numberSy)
00486          m_sy=noSy;
00487       else      {
00488          negation=true;
00489          // BUG-Fix #015: Negative values are not represented correctly!
00490          valueStr='-'+returnValue;
00491       } // else
00492    } // else if
00493    
00494    if (m_sy==numberSy)      {                 // INTEGER or REAL
00495       returnValue=newSy();
00496       value=numberSy;
00497       if (m_sy==dotSy)     {                      // dot indicates REAL-Type!
00498          // REAL-Value
00499          returnValue=newSy();
00500          value=realSy;
00501          if (m_sy==numberSy)    {                // optional: digits after dot!
00502             valueStr=valueStr+"."+returnValue;   // generate in valueStr the real-Type
00503             returnValue=newSy();
00504          } // if
00505       } // if
00506 
00507       // BUG-Fix #011: Introducing scientific numbers
00508       if ((m_sy==identifierSy) && ((returnValue=="e") || (returnValue=="E")) )      {
00509          // scientific integer detected
00510          returnValue=newSy();
00511          if (m_sy==numberSy)    {
00512             valueStr=valueStr+"e"+returnValue;  // generate scientifc number
00513             newSy();
00514          }
00515          else     {
00516             m_sy=noSy;
00517          } // else
00518       } // if
00519       // EOBF
00520 
00521       // Introducing units!
00522       else if (m_sy==identifierSy) {
00523         // possible definition of unit...
00524         if (units->existsUnit(returnValue)) {
00525           if (value==numberSy) {
00526             int calculatedValue = atoi(valueStr.c_str());
00527             calculatedValue = (int)(calculatedValue * units->getFactor(returnValue));
00528             std::strstream valstr;
00529             valstr << calculatedValue << std::ends;
00530             valueStr = valstr.str( );
00531           }
00532           else if (value==realSy) {
00533             double calculatedValue = atof(valueStr.c_str());
00534             calculatedValue = calculatedValue * units->getFactor(returnValue);
00535             int decnr, sign;
00536             char* buffer = _ecvt(calculatedValue,40,&decnr,&sign);
00537             valueStr = buffer;
00538             valueStr = valueStr.insert(decnr,".");
00539           }
00540           else {
00541             m_sy=noSy;
00542           }
00543           newSy();
00544         }
00545         else {
00546           m_sy=noSy;
00547         }
00548       }
00549    } // else if
00550    
00551    else if (m_sy==dotSy)    {                   // dot indicates REAL-Type! .98;
00552       returnValue=newSy();
00553       if (m_sy==numberSy)      {
00554          value=realSy;
00555          valueStr=valueStr+"."+returnValue;     // generate m_in valueStr the real-Type
00556          returnValue=newSy();
00557 
00558          // BUG-Fix #011: Introducing scientific numbers
00559          if ((m_sy==identifierSy) && ((returnValue=="e") || (returnValue=="E")) )   {
00560             // scientific integer detected
00561             returnValue=newSy();
00562             if (m_sy==numberSy)    {
00563                valueStr=valueStr+"e"+returnValue;  // generate scientifc number
00564                newSy();
00565             } // if
00566             else    {
00567                m_sy=noSy;
00568             } // else
00569          } // if
00570          // EOBF
00571          // Introducing units
00572          else if (m_sy==identifierSy) {
00573            // possible definition of unit...
00574            if (units->existsUnit(returnValue)) {
00575              if (value==numberSy) {
00576                int calculatedValue = atoi(valueStr.c_str());
00577                calculatedValue = (int)(calculatedValue * units->getFactor(returnValue));
00578                std::strstream valstr;
00579                valstr << calculatedValue << std::ends;
00580                valueStr = valstr.str( );
00581              }
00582              else if (value==realSy) {
00583                double calculatedValue = atof(valueStr.c_str());
00584                calculatedValue = calculatedValue * units->getFactor(returnValue);
00585                int decnr, sign;
00586                char* buffer = _ecvt(calculatedValue,40,&decnr,&sign);
00587                valueStr = buffer;
00588                valueStr = valueStr.insert(decnr,".");
00589              }
00590              else {
00591                m_sy=noSy;
00592              }
00593              newSy();
00594            }
00595            else {
00596              m_sy=noSy;
00597            }
00598          }
00599       } // if
00600       else                                      // dot only: misplaced dot!
00601          value=noSy;
00602    } // else if
00603 
00604    return value;
00605 } // getValueType
00606 
00607 void PropertyCompiler::ignorePlatformDependendLines()   {
00608    while ((m_sy!=endIfSy) && (m_sy!=elseSy) && (m_sy!=EOFSy))
00609       newSy();
00610 }
00611 
00612 void PropertyCompiler::getEntryPointOfDependendLines()    {
00613    while ((m_sy!=endIfSy) && (m_sy!=EOFSy))
00614       newSy();
00615 }
00616 
00617 
00621 StatusCode PropertyCompiler::checkSyntax()    {
00622    std::string returnValue;
00623    std::string objName;
00624    std::string propName;
00625    std::string valueStr;
00626    std::string newName;
00627    Symbols     oldType;
00628    Symbols     valueType;
00629    Operations  operation;
00630    bool        elsePathValid=false;
00631    // Synatx is: identifier identifier value
00632    // whereas value can be a stringSy, a numberSy, a numberSy. (REAL), a numberSy.numberSy (REAL), a Vector
00633 
00634    objName=newSy();                // get first Symbol... must be an identifier-Symbol (Object) or an include!
00635 
00636    while (m_sy != EOFSy )   {
00637       // Print compiled statement out if m_error-free!
00638       if ((! m_error) && (m_compiledLine!=""))   {
00639          if (m_compiledLine.find(";",0)== std::string::npos)   // no statement so far, print out comments!
00640          {
00641             *m_log << MSG::INFO << m_compiledLine;
00642             m_compiledLine="";
00643          } // if
00644          else     {
00645             std::string output=m_compiledLine.substr(0, m_compiledLine.find_last_of(";",0));
00646             *m_log << MSG::INFO << output;
00647             
00648             m_compiledLine.erase(0, m_compiledLine.find_last_of(";",0));
00649          } // else
00650       } // if
00651 
00652       // if error, then do not print out compiled statement which contains the error.
00653       if (m_error)      {
00654          // BUG-FIX: Missing Comment after wrong statement.
00655          if ( (m_compiledLine.find("//",0)!=m_compiledLine.npos) &&
00656               (m_compiledLine.find("//",0) < (m_compiledLine.find(";",0))) )
00657          {
00658             m_compiledLine.erase(0, m_compiledLine.find("//",0));
00659          }
00660          else if ( (m_compiledLine.find("/*",0)!=m_compiledLine.npos) &&
00661               (m_compiledLine.find("/*",0) < (m_compiledLine.find(";",0))) )
00662          {
00663             m_compiledLine.erase(0, m_compiledLine.find("/*",0));
00664          }
00665          else
00666          {
00667             if (m_compiledLine.find(";",0)==m_compiledLine.npos)           // missing ;
00668                m_compiledLine="";
00669             else
00670             {
00671                m_compiledLine.erase(0, m_compiledLine.find(";",0)+1);
00672             } // else
00673          }
00674       }
00675 
00676       m_error=false;
00677 
00678       // first symbol must be an identifier (Object), an include-Symbol or any
00679       // special-definition-Statement!
00680       if ((m_sy!=identifierSy) && (m_sy!=includeSy) && (m_sy!=ifDefSy) &&
00681           (m_sy!=ifNDefSy) && (m_sy!=endIfSy) && (m_sy!=elseSy) && m_sy!=unitsSy)
00682       {
00683          *m_log << endreq << MSG::ERROR << "Error #002 in line " << m_tokenlnr 
00684                 << " at column " << m_tokencnr-1 << ": Object expected!" << endreq;
00685          m_errorCount++;
00686          m_error=true;
00687          objName="";
00688       } // if
00689 
00690       // handle include of units...
00691       if (m_sy==unitsSy) {
00692         returnValue = newSy();
00693         if (m_sy != stringSy) {
00694           *m_log << endreq << MSG::ERROR << "Error #020 in line " << m_tokenlnr
00695                  << " at column " << m_tokencnr-1 << ": syntax error: #units \"filename\"!" << endreq;
00696           m_errorCount++;
00697           m_error=true;
00698         }
00699 
00700         m_compiledLine="";
00701 
00702         objName = newSy();
00703         if (m_sy==semicolonSy)        {
00704           *m_log << endreq << MSG::ERROR << "Error #008 in line " << m_tokenlnr << " at column " << m_tokencnr-1
00705                  << ": syntax error: #units doesn't end with a ';'!" << endreq;
00706           m_errorCount++;
00707           m_error=true;
00708           newSy();
00709         } // if
00710 
00711         if (unitsDefined==true) {
00712           *m_log << endreq << MSG::WARNING << "Warning #021 in line " << m_tokenlnr
00713                  << " at column " << m_tokencnr-1 << ": An unit-definition file was already included before! Definition was skipped!" << endreq;
00714           m_warningCount++;
00715           
00716         }
00717         else {
00718           // SEMANTIC ACTION: Read unit-table
00719           returnValue = resolveEnv(returnValue);
00720           if (units->getUnits(returnValue)) {
00721             unitsDefined = true;
00722           }
00723           else {
00724             *m_log << endreq << MSG::ERROR << "Error #022 in line " << m_tokenlnr << " at column " << m_tokencnr-1
00725                    << ": cannot open unit-definition file " << returnValue << endreq;
00726             m_errorCount++;
00727             m_error=true;
00728           }
00729         }
00730         continue;
00731       } // if
00732         
00733       // handle include ...
00734       if (m_sy==includeSy)    {
00735          returnValue=newSy();
00736          if (m_sy!=stringSy)   {
00737             *m_log << endreq << MSG::ERROR << "Error #007 in line " << m_tokenlnr 
00738                    << " at column " << m_tokencnr-1 << ": syntax error: #include \"filename\"!" <<endreq;
00739             m_errorCount++;
00740             m_error=true;
00741          } // if
00742          
00743          m_compiledLine="";      // avoid output of #include-statement!!!
00744          
00745          objName=newSy();
00746          if (m_sy==semicolonSy)    {
00747             *m_log << endreq << MSG::ERROR << "Error #008 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00748                    << ": syntax error: #include doesn't end with a ';'!" << endreq;
00749             m_errorCount++;
00750             m_error=true;
00751             newSy();
00752          } // if
00753 
00754          // SEMANTIC ACTION: PROCESS INCLUDE!!!
00755          // Include detected: Include other file by generating and executing a new compiler-object
00756          if (! m_error)   {
00757             *m_log << MSG::INFO << "// --> Including file " << returnValue << "\n";
00758             PropertyCompiler *pc=new PropertyCompiler(returnValue, *m_log, *m_Cat, this);
00759             if (! pc->startCompiler().isSuccess())   {    // BUG-Fix #014...
00760                // Error message was printed out before... tell this instance that there was a error!
00761                m_errorCount++;
00762                m_error=true;
00763             }
00764 
00765             // If you want to print out also the #include-statement uncomment following lines...
00766             /*if (pc->startCompiler() != 0)
00767             {
00768                m_error=true;
00769             }*/
00770 
00771             *m_log << MSG::INFO << "// <-- End of including file " << returnValue << "\n";
00772             delete pc;
00773          } // if
00774          // END OF SEMANTIC ACTION
00775          continue;
00776       } // if
00777 
00778 // handle #ifdef-Statement
00779       if (m_sy==ifDefSy)      {
00780          returnValue=newSy();     // read in next symbol!
00781 
00782          if (m_sy!=identifierSy)     {
00783             *m_log << endreq << MSG::ERROR << "Error #017 in line " << m_tokenlnr 
00784                    << " at column " << m_tokencnr-1 << ": syntax error: #ifdef not followed by an identifier!" <<endreq;
00785             getEntryPointOfDependendLines();
00786             m_errorCount++;
00787             m_error=true;
00788          } // if
00789          
00790          if (returnValue!="WIN32")     {
00791             *m_log << endreq << MSG::ERROR << "Error #018 in line " << m_tokenlnr 
00792                    << " at column " << m_tokencnr-1 << ": syntax error: identifier in #ifdef not known!" <<endreq;
00793             getEntryPointOfDependendLines();
00794             m_errorCount++;
00795             m_error=true;
00796          } // if
00797 
00798          if ((returnValue=="WIN32") && (! win_32))   {    // only for Win-NT!!!
00799             if (! m_error)     {
00800                ignorePlatformDependendLines();
00801                elsePathValid=true;
00802             }
00803          }
00804          m_compiledLine="";      // avoid output of #ifdef-statement!!!
00805          
00806          objName=newSy();
00807          if (m_sy==semicolonSy)    {
00808             *m_log << endreq << MSG::ERROR << "Error #019 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00809                    << ": syntax error: #ifdef doesn't end with a ';'!" << endreq;
00810             m_errorCount++;
00811             m_error=true;
00812             newSy();
00813          } // if
00814          continue;
00815       } // if
00816 
00817 // handle #ifndef-Statement
00818       if (m_sy==ifNDefSy)    {
00819          returnValue=newSy();     // read in next symbol!
00820 
00821          if (m_sy!=identifierSy)   {
00822             *m_log << endreq << MSG::ERROR << "Error #017 in line " << m_tokenlnr 
00823                    << " at column " << m_tokencnr-1 << ": syntax error: #ifndef not followed by an identifier!" <<endreq;
00824             getEntryPointOfDependendLines();
00825             m_errorCount++;
00826             m_error=true;
00827          } // if
00828          
00829          if (returnValue!="WIN32")    {
00830             *m_log << endreq << MSG::ERROR << "Error #018 in line " << m_tokenlnr 
00831                    << " at column " << m_tokencnr-1 << ": syntax error: identifier in #ifndef not known!" <<endreq;
00832             getEntryPointOfDependendLines();
00833             m_errorCount++;
00834             m_error=true;
00835          } // if
00836 
00837          if ((returnValue=="WIN32") && (win_32))   {    // only for Non-Win-NT!!!
00838             if (! m_error)    {
00839                ignorePlatformDependendLines();
00840                elsePathValid=true;
00841             }
00842          }
00843          m_compiledLine="";      // avoid output of #ifndef-statement!!!
00844          
00845          objName=newSy();
00846          if (m_sy==semicolonSy)     {
00847             *m_log << endreq << MSG::ERROR << "Error #019 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00848                    << ": syntax error: #ifndef doesn't end with a ';'!" << endreq;
00849             m_errorCount++;
00850             m_error=true;
00851             newSy();
00852          } // if
00853          continue;
00854       } // if
00855 
00856 // handle #else-Statement
00857       if ( m_sy == elseSy )      {
00858          objName=newSy();
00859          if (m_sy==semicolonSy)         {
00860             *m_log << endreq << MSG::ERROR << "Error #019 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00861                    << ": syntax error: #else doesn't end with a ';'!" << endreq;
00862             m_errorCount++;
00863             m_error=true;
00864             newSy();
00865          } // if
00866 
00867          if (! elsePathValid)    {   // do not process else-path!
00868             if (! m_error)    {
00869                ignorePlatformDependendLines();
00870             }
00871          }
00872          m_compiledLine="";      // avoid output of #else-statement!!!
00873          
00874          elsePathValid=false;
00875          continue;
00876       } // if
00877 
00878 // handle #endif-Statement
00879       if ( m_sy==endIfSy)      {
00880          m_compiledLine="";      // avoid output of #endif-statement!!!
00881          
00882          objName=newSy();
00883          if (m_sy==semicolonSy)      {
00884             *m_log << endreq << MSG::ERROR << "Error #019 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00885                    << ": syntax error: #endif doesn't end with a ';'!" << endreq;
00886             m_errorCount++;
00887             m_error=true;
00888             newSy();
00889          } // if
00890          continue;
00891       } // if
00892       
00893       newName=objName;
00894       objName="";              // for the first assignment
00895  
00896       while (m_sy==identifierSy)      {
00897          objName=objName+newName;
00898          newSy();
00899          if (m_sy==semicolonSy)
00900             break;  
00901 
00902          if (m_sy==dotSy)         {
00903             newName="."+newSy();
00904             if (m_sy==semicolonSy)
00905                break;
00906          } // else
00907       } // while
00908 
00909       if (objName.find(".")==objName.npos)        // no dot in identifier!!!
00910       {
00911          *m_log << endreq << MSG::ERROR << "Error #003 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00912                 << ": Object and Property must be divided by a '.'!" << endreq;
00913          m_errorCount++;
00914          m_error=true;
00915       } // if
00916       if (isNextEntryPoint())
00917          continue;
00918 
00919       if (objName!="")
00920          objName.erase(objName.find_last_of("."), objName.length());
00921       newName.erase(0,1);
00922       propName=newName;
00923 
00924       operation=noOperation;
00925       if (m_sy==assignSy)
00926         operation=assign;
00927       else if (m_sy==appendSy)
00928         operation=append;
00929 
00930       if (operation==noOperation)   {
00931          *m_log << endreq << MSG::ERROR << "Error #005 in line " << m_tokenlnr << " at column " << m_tokencnr-1 
00932                 << ": syntax error: missing operator '=' or '+='!" << endreq;
00933          m_errorCount++;
00934          m_error=true;
00935       } // if
00936 
00937       returnValue=newSy();
00938       if (isNextEntryPoint())
00939          continue;
00940       
00941       // --- VECTOR-Recognition:
00942       // --- by finding { start recognition of a vector, values seperated by commas and terminated
00943       //     by a } and a semicolon!
00944       // --- without finding { only recognize a new single value followed by a semicolon
00945       std::vector<std::string> propValues;
00946       bool isArrayProp = false;
00947       if (m_sy==vectorStartSy)      {
00948         returnValue = newSy();
00949         returnValue = resolveEnv(returnValue);
00950         valueType   = getValueType(returnValue);
00951         oldType     = valueType;
00952         isArrayProp = true;
00953         if ( valueType == stringSy )    {
00954           propValues.push_back("\""+returnValue+"\"");
00955         }
00956         else if (valueType == booleanSy)   {
00957           propValues.push_back((::toupper(returnValue[0]) == 'T' || returnValue[0] == '1') ? "1" : "0" );
00958         }
00959         else if (valueType!=noSy)   {
00960           propValues.push_back(returnValue);
00961         }
00962         if (m_sy==commaSy)   {
00963           while ((m_sy!=identifierSy) && (m_sy!=EOFSy) && (m_sy!=semicolonSy) && (m_sy!=vectorEndSy))    {
00964             returnValue = newSy();
00965             returnValue = resolveEnv(returnValue);
00966             valueType=getValueType(returnValue);
00967             if ( valueType == stringSy )    {
00968               propValues.push_back("\""+returnValue+"\"");
00969             }
00970             else if (valueType == booleanSy)   {
00971               propValues.push_back((::toupper(returnValue[0]) == 'T' || returnValue[0] == '1') ? "1" : "0" );
00972             }
00973             else    {
00974               propValues.push_back(returnValue);
00975             }
00976             if ((m_sy!=commaSy) && (m_sy!=identifierSy) && (m_sy!=EOFSy) && (m_sy!=semicolonSy) && (m_sy!=vectorEndSy))    {
00977               *m_log << endreq << MSG::ERROR << "Error #009 in line " << m_tokenlnr << " at column " 
00978                      << m_tokencnr << ": syntax error: Values in vector must be sperated with ','!" << endreq;
00979               m_errorCount++;
00980               m_error=true;
00981             } // if
00982           } // while
00983         } // if
00984         if (m_sy!=vectorEndSy)   {
00985           *m_log << endreq << MSG::ERROR << "Error #010 in line " << m_tokenlnr << " at column " 
00986                  << m_tokencnr << ": syntax error: Vector must end with a closing braket '}'!" << endreq;
00987           m_errorCount++;
00988           m_error=true;
00989         }
00990         newSy();
00991       } // if (m_sy==vectorStartSy)
00992       else    {
00993          returnValue = resolveEnv(returnValue);
00994          valueType=getValueType(returnValue);
00995          oldType=valueType;
00996 
00997          if (valueType==noSy)  {
00998             *m_log << endreq << MSG::ERROR << "Error #015 in line " << m_tokenlnr << " at column " 
00999                    << m_tokencnr << ": Value(s) expected!" << endreq;
01000             m_errorCount++;
01001             m_error=true;
01002             newSy();
01003             returnValue="";
01004          } // if
01005          else if ( valueType == stringSy )    {
01006            propValues.push_back("\""+returnValue+"\"");
01007          }
01008          else if (valueType == booleanSy)   {
01009            propValues.push_back((::toupper(returnValue[0]) == 'T' || returnValue[0] == '1') ? "1" : "0" );
01010          }
01011          else   {
01012            propValues.push_back(returnValue);
01013          }
01014       } // else
01015 
01016       if (m_sy!=semicolonSy)  {
01017          *m_log << endreq << MSG::ERROR << "Error #011 in line " << m_tokenlnr << " at column " 
01018                 << m_tokencnr << ": syntax error: missing ';'!" << endreq;
01019          m_errorCount++;
01020          m_error=true;
01021       } // if
01022       // BUG-Fix #004: else removed!
01023 
01024       // SEMANTIC ACTION: Commit generated property-Entry to JobOptionsCataloge, if no error in statement
01025       if (!m_error)    {
01026         // If there was no error, commit new properties to JobOptionsCatalogue!!!
01027         // SEMANTIC ACTION: Prepare new Property-Entry for JobOptionsCataloge with readed vector
01028         if ( propValues.size() == 0 )   {
01029           switch ( operation )    {
01030           case assign:  
01031             operation = clear;
01032             break;
01033           case append:
01034             operation = noOperation;
01035             break;
01036           default:
01037             break;
01038           }
01039         }
01040         std::vector<const Property*>* myOpts = 0;
01041         switch( operation )    {
01042         case append:
01043         case assign:   
01044         case clear:
01045           if ( m_Cat->optionsOf(objName, myOpts).isSuccess() )   {
01046             std::vector<const Property*>::iterator itr;
01047             for ( itr=myOpts->begin(); itr!=myOpts->end(); itr++ )   {
01048               if ((*itr)->name() == propName )    {
01049                 switch ( operation )    {
01050                 case append:     {
01051                     const StringArrayProperty* sap = 
01052                       dynamic_cast<const StringArrayProperty*> (*itr);
01053                     if ( sap != 0 )    {
01054                       std::vector<std::string> res = sap->value();
01055                       for ( unsigned int it = 0; it < propValues.size(); it++ )    
01056                         res.push_back(propValues[it]);
01057                       propValues = res;
01058                     }
01059                   }
01060                   break;
01061                 default:
01062                   break;
01063                 }
01064                 myOpts->erase(itr);           // Delete existing property
01065                 break;
01066               }
01067             }
01068           }
01069           if ( isArrayProp )    {
01070             m_Cat->addOption( objName, new StringArrayProperty(propName, propValues));
01071           }
01072           else  {
01073             m_Cat->addOption( objName, new StringProperty(propName, propValues[0]));
01074           }
01075           break;
01076         default:
01077           break;
01078         }
01079       } // if
01080       // END OF SEMANTIC ACTION
01081 
01082       objName=newSy();
01083 
01084       if (isNextEntryPoint())
01085          continue;
01086 
01087       if (m_sy==noSy)      {
01088          m_error=true;
01089          m_errorCount++;
01090          *m_log << endreq << MSG::ERROR << "Error #000 in line " << m_tokenlnr << " at column " << m_tokencnr 
01091                 << ": \nFatal compiler error!"
01092                 << "\nThis Error can have several reasons:\n"
01093                 << "* The job-option-file contains invalid characters\n"
01094                 << "* The job-option-file is not valid\n"
01095                 << "* The property-compiler could not recover from previous error\n"
01096                 << "* Memory or Disk-problem\n"
01097                 << "\n\nCompiler will now try to recover.\n"
01098                 << "WARNING: ONE OR MORE LINES ARE IGNORED AND NOT PRINTED OUT BY THE COMPILER.\n"
01099                 << "PLEASE CHECK MANUALLY STATEMENTS BEFORE AND AFTER ERROR-POSITION!!!\n\n" << endreq;
01100          //return StatusCode::FAILURE;
01101 
01102          m_sy=BOFSy;          // Try to recover!!!
01103          newCh();
01104 
01105          objName=newSy();
01106          while ( (m_sy!=semicolonSy) && (m_sy!=EOFSy) )     {
01107             newSy();
01108             if (m_sy==noSy)    {
01109                m_sy=BOFSy;    // Try to recover!!!
01110                newCh();
01111             } // if
01112          }
01113          if (m_sy==EOFSy)
01114             return StatusCode::FAILURE;
01115 
01116          m_compiledLine="";
01117          objName=newSy();  // Compiler recoverd from previous error!
01118          continue;
01119       } // if
01120 
01121    } // while
01122 
01123    // BUG-FIX #003: Last line is not printed out after compilation
01124    // Reason: Compilation breaks at EOF, last line contains EOF!
01125    if ((! m_error) && (m_compiledLine!=""))   {
01126       *m_log << MSG::INFO << m_compiledLine << "\n";
01127       m_compiledLine="";
01128    } // if
01129 
01130    if (m_error)
01131       m_compiledLine="";
01132    // EOBF
01133 
01134    if (m_errorCount != 0)   {
01135       *m_log << MSG::INFO << m_errorCount << " error(s) in file " << m_srcName << endreq;
01136       return StatusCode::FAILURE;
01137    }
01138 
01139    return StatusCode::SUCCESS;                                 // no errors!
01140 } // CheckSyntax
01141 
01142 
01143 
01144 // ---- START COMPILER ----
01148 StatusCode PropertyCompiler::startCompiler()
01149 {
01150    if ((m_errorCount!=0) || (m_warningCount!=0))
01151       return StatusCode::FAILURE;                    // Constructor failed!!!
01152 
01153    // start initialization for compile-run
01154    m_srcLine="";
01155    m_compiledLine="";
01156    m_lnr=0;
01157    m_cnr=0;
01158    m_errorCount=0;
01159    newCh();
01160    StatusCode result=checkSyntax();
01161    return result;
01162 } // startCompiler
01163 

Generated at Wed Nov 21 12:22:31 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000