diff options
author | Brad King <brad.king@kitware.com> | 2015-07-22 18:03:00 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2015-07-27 13:45:36 (GMT) |
commit | eebe732bb61bb69f50edae9b7fb171266b216752 (patch) | |
tree | 59d94fa526a28bc0a28bd837eddf5b6a031fc738 /Source/cmFortranParserImpl.cxx | |
parent | fd1944580266c3c84234b28e2102fc787ed5c00d (diff) | |
download | CMake-eebe732bb61bb69f50edae9b7fb171266b216752.zip CMake-eebe732bb61bb69f50edae9b7fb171266b216752.tar.gz CMake-eebe732bb61bb69f50edae9b7fb171266b216752.tar.bz2 |
cmFortranParser: Factor out of cmDependsFortran
Move the main parser class and method implementations out of
cmDependsFortran.cxx and into separate source files.
Diffstat (limited to 'Source/cmFortranParserImpl.cxx')
-rw-r--r-- | Source/cmFortranParserImpl.cxx | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx new file mode 100644 index 0000000..a09c5459 --- /dev/null +++ b/Source/cmFortranParserImpl.cxx @@ -0,0 +1,408 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmFortranParser.h" + +#include "cmSystemTools.h" +#include <assert.h> + +//---------------------------------------------------------------------------- +bool cmFortranParser_s::FindIncludeFile(const char* dir, + const char* includeName, + std::string& fileName) +{ + // If the file is a full path, include it directly. + if(cmSystemTools::FileIsFullPath(includeName)) + { + fileName = includeName; + return cmSystemTools::FileExists(fileName.c_str(), true); + } + else + { + // Check for the file in the directory containing the including + // file. + std::string fullName = dir; + fullName += "/"; + fullName += includeName; + if(cmSystemTools::FileExists(fullName.c_str(), true)) + { + fileName = fullName; + return true; + } + + // Search the include path for the file. + for(std::vector<std::string>::const_iterator i = + this->IncludePath.begin(); i != this->IncludePath.end(); ++i) + { + fullName = *i; + fullName += "/"; + fullName += includeName; + if(cmSystemTools::FileExists(fullName.c_str(), true)) + { + fileName = fullName; + return true; + } + } + } + return false; +} + +//---------------------------------------------------------------------------- +cmFortranParser_s +::cmFortranParser_s(std::vector<std::string> const& includes, + std::set<std::string> const& defines, + cmFortranSourceInfo& info): + IncludePath(includes), PPDefinitions(defines), Info(info) +{ + this->InInterface = 0; + this->InPPFalseBranch = 0; + + // Initialize the lexical scanner. + cmFortran_yylex_init(&this->Scanner); + cmFortran_yyset_extra(this, this->Scanner); + + // Create a dummy buffer that is never read but is the fallback + // buffer when the last file is popped off the stack. + YY_BUFFER_STATE buffer = + cmFortran_yy_create_buffer(0, 4, this->Scanner); + cmFortran_yy_switch_to_buffer(buffer, this->Scanner); +} + +//---------------------------------------------------------------------------- +cmFortranParser_s::~cmFortranParser_s() +{ + cmFortran_yylex_destroy(this->Scanner); +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_FilePush(cmFortranParser* parser, + const char* fname) +{ + // Open the new file and push it onto the stack. Save the old + // buffer with it on the stack. + if(FILE* file = cmsys::SystemTools::Fopen(fname, "rb")) + { + YY_BUFFER_STATE current = + cmFortranLexer_GetCurrentBuffer(parser->Scanner); + std::string dir = cmSystemTools::GetParentDirectory(fname); + cmFortranFile f(file, current, dir); + YY_BUFFER_STATE buffer = + cmFortran_yy_create_buffer(0, 16384, parser->Scanner); + cmFortran_yy_switch_to_buffer(buffer, parser->Scanner); + parser->FileStack.push(f); + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_FilePop(cmFortranParser* parser) +{ + // Pop one file off the stack and close it. Switch the lexer back + // to the next one on the stack. + if(parser->FileStack.empty()) + { + return 0; + } + else + { + cmFortranFile f = parser->FileStack.top(); parser->FileStack.pop(); + fclose(f.File); + YY_BUFFER_STATE current = + cmFortranLexer_GetCurrentBuffer(parser->Scanner); + cmFortran_yy_delete_buffer(current, parser->Scanner); + cmFortran_yy_switch_to_buffer(f.Buffer, parser->Scanner); + return 1; + } +} + +//---------------------------------------------------------------------------- +int cmFortranParser_Input(cmFortranParser* parser, + char* buffer, size_t bufferSize) +{ + // Read from the file on top of the stack. If the stack is empty, + // the end of the translation unit has been reached. + if(!parser->FileStack.empty()) + { + FILE* file = parser->FileStack.top().File; + return (int)fread(buffer, 1, bufferSize, file); + } + return 0; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_StringStart(cmFortranParser* parser) +{ + parser->TokenString = ""; +} + +//---------------------------------------------------------------------------- +const char* cmFortranParser_StringEnd(cmFortranParser* parser) +{ + return parser->TokenString.c_str(); +} + +//---------------------------------------------------------------------------- +void cmFortranParser_StringAppend(cmFortranParser* parser, + char c) +{ + parser->TokenString += c; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_SetInInterface(cmFortranParser* parser, + bool in) +{ + if(parser->InPPFalseBranch) + { + return; + } + + parser->InInterface = in; +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_GetInInterface(cmFortranParser* parser) +{ + return parser->InInterface; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_SetOldStartcond(cmFortranParser* parser, + int arg) +{ + parser->OldStartcond = arg; +} + +//---------------------------------------------------------------------------- +int cmFortranParser_GetOldStartcond(cmFortranParser* parser) +{ + return parser->OldStartcond; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_Error(cmFortranParser*, const char*) +{ + // If there is a parser error just ignore it. The source will not + // compile and the user will edit it. Then dependencies will have + // to be regenerated anyway. +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleUse(cmFortranParser* parser, + const char* name) +{ + if(!parser->InPPFalseBranch) + { + parser->Info.Requires.insert(cmSystemTools::LowerCase(name) ); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleInclude(cmFortranParser* parser, + const char* name) +{ + if(parser->InPPFalseBranch) + { + return; + } + + // If processing an include statement there must be an open file. + assert(!parser->FileStack.empty()); + + // Get the directory containing the source in which the include + // statement appears. This is always the first search location for + // Fortran include files. + std::string dir = parser->FileStack.top().Directory; + + // Find the included file. If it cannot be found just ignore the + // problem because either the source will not compile or the user + // does not care about depending on this included source. + std::string fullName; + if(parser->FindIncludeFile(dir.c_str(), name, fullName)) + { + // Found the included file. Save it in the set of included files. + parser->Info.Includes.insert(fullName); + + // Parse it immediately to translate the source inline. + cmFortranParser_FilePush(parser, fullName.c_str()); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleModule(cmFortranParser* parser, + const char* name) +{ + if(!parser->InPPFalseBranch && !parser->InInterface) + { + parser->Info.Provides.insert(cmSystemTools::LowerCase(name)); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleDefine(cmFortranParser* parser, + const char* macro) +{ + if(!parser->InPPFalseBranch) + { + parser->PPDefinitions.insert(macro); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleUndef(cmFortranParser* parser, + const char* macro) +{ + if(!parser->InPPFalseBranch) + { + std::set<std::string>::iterator match; + match = parser->PPDefinitions.find(macro); + if(match != parser->PPDefinitions.end()) + { + parser->PPDefinitions.erase(match); + } + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIfdef(cmFortranParser* parser, + const char* macro) +{ + // A new PP branch has been opened + parser->SkipToEnd.push(false); + + if (parser->InPPFalseBranch) + { + parser->InPPFalseBranch++; + } + else if(parser->PPDefinitions.find(macro) == parser->PPDefinitions.end()) + { + parser->InPPFalseBranch=1; + } + else + { + parser->SkipToEnd.top() = true; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIfndef(cmFortranParser* parser, + const char* macro) +{ + // A new PP branch has been opened + parser->SkipToEnd.push(false); + + if (parser->InPPFalseBranch) + { + parser->InPPFalseBranch++; + } + else if(parser->PPDefinitions.find(macro) != parser->PPDefinitions.end()) + { + parser->InPPFalseBranch = 1; + } + else + { + // ignore other branches + parser->SkipToEnd.top() = true; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIf(cmFortranParser* parser) +{ + /* Note: The current parser is _not_ able to get statements like + * #if 0 + * #if 1 + * #if MYSMBOL + * #if defined(MYSYMBOL) + * #if defined(MYSYMBOL) && ... + * right. The same for #elif. Thus in + * #if SYMBOL_1 + * .. + * #elif SYMBOL_2 + * ... + * ... + * #elif SYMBOL_N + * .. + * #else + * .. + * #endif + * _all_ N+1 branches are considered. If you got something like this + * #if defined(MYSYMBOL) + * #if !defined(MYSYMBOL) + * use + * #ifdef MYSYMBOL + * #ifndef MYSYMBOL + * instead. + */ + + // A new PP branch has been opened + // Never skip! See note above. + parser->SkipToEnd.push(false); +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleElif(cmFortranParser* parser) +{ + /* Note: There are parser limitations. See the note at + * cmFortranParser_RuleIf(..) + */ + + // Always taken unless an #ifdef or #ifndef-branch has been taken + // already. If the second condition isn't meet already + // (parser->InPPFalseBranch == 0) correct it. + if(!parser->SkipToEnd.empty() && + parser->SkipToEnd.top() && !parser->InPPFalseBranch) + { + parser->InPPFalseBranch = 1; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleElse(cmFortranParser* parser) +{ + // if the parent branch is false do nothing! + if(parser->InPPFalseBranch > 1) + { + return; + } + + // parser->InPPFalseBranch is either 0 or 1. We change it depending on + // parser->SkipToEnd.top() + if(!parser->SkipToEnd.empty() && + parser->SkipToEnd.top()) + { + parser->InPPFalseBranch = 1; + } + else + { + parser->InPPFalseBranch = 0; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleEndif(cmFortranParser* parser) +{ + if(!parser->SkipToEnd.empty()) + { + parser->SkipToEnd.pop(); + } + + // #endif doesn't know if there was a "#else" in before, so it + // always decreases InPPFalseBranch + if(parser->InPPFalseBranch) + { + parser->InPPFalseBranch--; + } +} |