瀏覽代碼

ENH: Added Fortran dependency scanner implementation.

Brad King 21 年之前
父節點
當前提交
19f977bad7
共有 5 個文件被更改,包括 886 次插入0 次删除
  1. 384 0
      Source/cmDependsFortran.cxx
  2. 64 0
      Source/cmDependsFortran.h
  3. 203 0
      Source/cmDependsFortranLexer.in.l
  4. 70 0
      Source/cmDependsFortranParser.h
  5. 165 0
      Source/cmDependsFortranParser.y

+ 384 - 0
Source/cmDependsFortran.cxx

@@ -0,0 +1,384 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmDependsFortran.h"
+
+#include "cmSystemTools.h"
+
+#include "cmDependsFortranLexer.h"  /* Interface to lexer object.  */
+#include "cmDependsFortranParser.h" /* Interface to parser object.  */
+
+#include <stack>
+
+//----------------------------------------------------------------------------
+// Parser methods not included in generated interface.
+extern "C"
+{
+  // Get the current buffer processed by the lexer.
+  YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner);
+
+  // The parser entry point.
+  int cmDependsFortranParser_yyparse(yyscan_t);
+}
+
+// Define parser object internal structure.
+struct cmDependsFortranFile
+{
+  FILE* File;
+  YY_BUFFER_STATE Buffer;
+  std::string Directory;
+};
+struct cmDependsFortranParser_s
+{
+  cmDependsFortranParser_s(cmDependsFortran* self);
+  ~cmDependsFortranParser_s();
+
+  // Pointer back to the main class.
+  cmDependsFortran* Self;
+
+  // Lexical scanner instance.
+  yyscan_t Scanner;
+
+  // Stack of open files in the translation unit.
+  std::stack<cmDependsFortranFile> FileStack;
+
+  // Buffer for string literals.
+  std::string TokenString;
+
+  // Flag for whether lexer is reading from inside an interface.
+  int InInterface;
+
+  // Set of provided and required modules.
+  std::set<cmStdString> Provides;
+  std::set<cmStdString> Requires;
+
+  // Set of files included in the translation unit.
+  std::set<cmStdString> Includes;
+};
+
+//----------------------------------------------------------------------------
+cmDependsFortran::cmDependsFortran(const char* dir, const char* targetFile):
+  cmDepends(dir, targetFile),
+  m_SourceFile(),
+  m_IncludePath(0)
+{
+}
+
+//----------------------------------------------------------------------------
+cmDependsFortran::cmDependsFortran(const char* dir, const char* targetFile,
+                                   const char* sourceFile,
+                                   std::vector<std::string> const& includes):
+  cmDepends(dir, targetFile),
+  m_SourceFile(sourceFile),
+  m_IncludePath(&includes)
+{
+}
+
+//----------------------------------------------------------------------------
+cmDependsFortran::~cmDependsFortran()
+{
+}
+
+//----------------------------------------------------------------------------
+bool cmDependsFortran::WriteDependencies(std::ostream& os)
+{
+  // Make sure this is a scanning instance.
+  if(m_SourceFile == "")
+    {
+    cmSystemTools::Error("Cannot scan dependencies without an source file.");
+    return false;
+    }
+  if(!m_IncludePath)
+    {
+    cmSystemTools::Error("Cannot scan dependencies without an include path.");
+    return false;
+    }
+
+  // Create the parser object.
+  cmDependsFortranParser parser(this);
+
+  // Push on the starting file.
+  cmDependsFortranParser_FilePush(&parser, m_SourceFile.c_str());
+
+  // Parse the translation unit.
+  if(cmDependsFortranParser_yyparse(parser.Scanner) != 0)
+    {
+    // Failed to parse the file.  Report failure to write dependencies.
+    return false;
+    }
+
+  // Write the dependencies to the output stream.
+  const std::set<cmStdString>& dependencies = parser.Includes;
+  for(std::set<cmStdString>::const_iterator i=dependencies.begin();
+      i != dependencies.end(); ++i)
+    {
+    os << m_TargetFile.c_str() << ": "
+       << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
+       << std::endl;
+    }
+  os << std::endl;
+
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmDependsFortran::CheckDependencies(std::istream&)
+{
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmDependsFortran::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());
+    }
+  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()))
+      {
+      fileName = fullName;
+      return true;
+      }
+
+    // Search the include path for the file.
+    for(std::vector<std::string>::const_iterator i = m_IncludePath->begin();
+        i != m_IncludePath->end(); ++i)
+      {
+      fullName = *i;
+      fullName += "/";
+      fullName += includeName;
+      if(cmSystemTools::FileExists(fullName.c_str()))
+        {
+        fileName = fullName;
+        return true;
+        }
+      }
+    }
+  return false;
+}
+
+//----------------------------------------------------------------------------
+cmDependsFortranParser_s::cmDependsFortranParser_s(cmDependsFortran* self):
+  Self(self)
+{
+  this->InInterface = 0;
+
+  // Initialize the lexical scanner.
+  cmDependsFortranLexer_yylex_init(&this->Scanner);
+  cmDependsFortranLexer_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 =
+    cmDependsFortranLexer_yy_create_buffer(0, 4, this->Scanner);
+  cmDependsFortranLexer_yy_switch_to_buffer(buffer, this->Scanner);
+}
+
+//----------------------------------------------------------------------------
+cmDependsFortranParser_s::~cmDependsFortranParser_s()
+{
+  cmDependsFortranLexer_yylex_destroy(this->Scanner);
+}
+
+//----------------------------------------------------------------------------
+int cmDependsFortranParser_FilePush(cmDependsFortranParser* 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 = fopen(fname, "rb"))
+    {
+    YY_BUFFER_STATE current =
+      cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner);
+    std::string dir = cmSystemTools::GetParentDirectory(fname);
+    cmDependsFortranFile f = {file, current, dir};
+    YY_BUFFER_STATE buffer =
+      cmDependsFortranLexer_yy_create_buffer(0, 16384, parser->Scanner);
+    cmDependsFortranLexer_yy_switch_to_buffer(buffer, parser->Scanner);
+    parser->FileStack.push(f);
+    return 1;
+    }
+  else
+    {
+    return 0;
+    }
+}
+
+//----------------------------------------------------------------------------
+int cmDependsFortranParser_FilePop(cmDependsFortranParser* 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
+    {
+    cmDependsFortranFile f = parser->FileStack.top(); parser->FileStack.pop();
+    fclose(f.File);
+    YY_BUFFER_STATE current =
+      cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner);
+    cmDependsFortranLexer_yy_delete_buffer(current, parser->Scanner);
+    cmDependsFortranLexer_yy_switch_to_buffer(f.Buffer, parser->Scanner);
+    return 1;
+    }
+}
+
+//----------------------------------------------------------------------------
+int cmDependsFortranParser_Input(cmDependsFortranParser* 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 cmDependsFortranParser_StringStart(cmDependsFortranParser* parser)
+{
+  parser->TokenString = "";
+}
+
+//----------------------------------------------------------------------------
+const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser)
+{
+  return parser->TokenString.c_str();
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
+                                         char c)
+{
+  parser->TokenString += c;
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
+                                           int in)
+{
+  parser->InInterface = in;
+}
+
+//----------------------------------------------------------------------------
+int cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser)
+{
+  return parser->InInterface;
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_Error(cmDependsFortranParser*, 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 cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
+                                    const char* name)
+{
+  parser->Requires.insert(name);
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
+                                        const char* name)
+{
+  // 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->Self->FindIncludeFile(dir.c_str(), name, fullName))
+    {
+    // Found the included file.  Save it in the set of included files.
+    parser->Includes.insert(fullName);
+
+    // Parse it immediately to translate the source inline.
+    cmDependsFortranParser_FilePush(parser, fullName.c_str());
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
+                                       const char* name)
+{
+  parser->Provides.insert(name);
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleDefine(cmDependsFortranParser*, const char*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleUndef(cmDependsFortranParser*, const char*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser*, const char*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser*, const char*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleIf(cmDependsFortranParser*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleElif(cmDependsFortranParser*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleElse(cmDependsFortranParser*)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmDependsFortranParser_RuleEndif(cmDependsFortranParser*)
+{
+}

+ 64 - 0
Source/cmDependsFortran.h

@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmDependsFortran_h
+#define cmDependsFortran_h
+
+#include "cmDepends.h"
+
+/** \class cmDependsFortran
+ * \brief Dependency scanner for Fortran object files.
+ */
+class cmDependsFortran: public cmDepends
+{
+public:
+  /** Checking instances need to know the build directory name and the
+      relative path from the build directory to the target file.  */
+  cmDependsFortran(const char* dir, const char* targetFile);
+
+  /** Scanning need to know the build directory name, the relative
+      path from the build directory to the target file, the source
+      file from which to start scanning, and the include file search
+      path.  */
+  cmDependsFortran(const char* dir, const char* targetFile,
+             const char* sourceFile, std::vector<std::string> const& includes);
+
+  /** Virtual destructor to cleanup subclasses properly.  */
+  virtual ~cmDependsFortran();
+
+  /** Method to find an included file in the include path.  Fortran
+      always searches the directory containing the including source
+      first.  */
+  bool FindIncludeFile(const char* dir, const char* includeName,
+                       std::string& fileName);
+
+protected:
+  // Implement writing/checking methods required by superclass.
+  virtual bool WriteDependencies(std::ostream& os);
+  virtual bool CheckDependencies(std::istream& is);
+
+  // The source file from which to start scanning.
+  std::string m_SourceFile;
+
+  // The include file search path.
+  std::vector<std::string> const* m_IncludePath;
+
+private:
+  cmDependsFortran(cmDependsFortran const&); // Purposely not implemented.
+  void operator=(cmDependsFortran const&); // Purposely not implemented.
+};
+
+#endif

+ 203 - 0
Source/cmDependsFortranLexer.in.l

@@ -0,0 +1,203 @@
+%{
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Portions of this source have been derived from makefdep90 version 2.6.2,
+
+   Copyright (C) 2000,2001 Erik Edelmann <[email protected]>.
+
+  The code was originally distributed under the GPL but permission
+  from the copyright holder has been obtained to distribute this
+  derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run flex like this:
+
+  flex --prefix=cmDependsFortran_yy --header-file=cmDependsFortranLexer.h -ocmDependsFortranLexer.c cmDependsFortranLexer.in.l
+
+Modify cmDependsFortranLexer.c:
+  - remove TABs
+  - add a statement "(void)yyscanner;" to the top of these methods:
+      yy_fatal_error, yyalloc, yyrealloc, yyfree
+  - remove all YY_BREAK lines occurring right after return statements
+
+Modify cmDependsFortranLexer.h:
+  - remove TABs
+  - remove the yy_init_globals function
+  - add these lines around all function declarations:
+      #ifdef __cplusplus
+      extern "C"
+      {
+      #endif
+      ...
+      #ifdef __cplusplus
+      }
+      #endif
+
+*/
+
+#include "cmDependsFortranParser.h" /* Interface to parser object.  */
+
+/* Disable some warnings.  */
+#if defined(_MSC_VER)
+# pragma warning ( disable : 4127 )
+# pragma warning ( disable : 4131 )
+# pragma warning ( disable : 4244 )
+# pragma warning ( disable : 4251 )
+# pragma warning ( disable : 4267 )
+# pragma warning ( disable : 4305 )
+# pragma warning ( disable : 4309 )
+# pragma warning ( disable : 4706 )
+# pragma warning ( disable : 4786 )
+#endif
+
+/* Disable features we do not need. */
+#define YY_NEVER_INTERACTIVE 1
+#define YY_NO_UNISTD_H 1
+#define ECHO
+
+/* Setup the proper yylex declaration.  */
+#define YY_EXTRA_TYPE cmDependsFortranParser*
+#define YY_DECL int cmDependsFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+
+/* Replace the lexer input function.  */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+  { result = cmDependsFortranParser_Input(yyextra, buf, max_size); }
+
+/* Include the set of tokens from the parser.  */
+#include "cmDependsFortranParserTokens.h"
+
+/*--------------------------------------------------------------------------*/
+%}
+
+%option reentrant
+%option noyywrap
+%pointer
+
+%s free_fmt fixed_fmt
+%x str_sq str_dq
+
+%%
+
+\"              {
+  cmDependsFortranParser_StringStart(yyextra);
+  BEGIN(str_dq);
+}
+
+'               {
+  cmDependsFortranParser_StringStart(yyextra);
+  BEGIN(str_sq);
+}
+
+<str_dq>\" |
+<str_sq>'  {
+  yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra));
+  return STRING;
+}
+
+<str_dq,str_sq>&[ \t]*\n |
+<str_dq,str_sq>&[ \t]*\n[ \t]*&  /* Ignore (continued strings, free fmt) */
+
+<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] /*Ignore (cont. strings, fixed fmt) */
+
+<str_dq,str_sq>\n {
+  unput ('\n');
+  BEGIN(INITIAL);
+  return UNTERMINATED_STRING;
+}
+
+<str_sq,str_dq>. {
+  cmDependsFortranParser_StringAppend(yyextra, yytext[0]);
+}
+
+!.*\n                   { return EOSTMT; } /* Treat comments like */
+<fixed_fmt>^[cC*dD].*\n { return EOSTMT; } /* empty lines */
+
+#[ \t]*include  { return CPP_INCLUDE; }
+\$[ \t]*include { return F90PPR_INCLUDE; }
+\?\?[ \t]*include { return COCO_INCLUDE; }
+INCLUDE         { return F_INCLUDE; }
+USE             { return USE; }
+
+END" "*INTERFACE {
+  cmDependsFortranParser_SetInInterface(yyextra, 0);
+}
+INTERFACE        {
+  cmDependsFortranParser_SetInInterface(yyextra, 1);
+}
+
+END" "*MODULE   /* Ignore */
+MODULE          {
+ if(!cmDependsFortranParser_GetInInterface(yyextra))
+   {
+   return MODULE;
+   }
+}
+
+#[ \t]*define   { return CPP_DEFINE; }
+\$[ \t]*DEFINE   { return F90PPR_DEFINE; }
+
+#[ \t]*undef    { return CPP_UNDEF; }
+\$[ \t]*UNDEF   { return F90PPR_UNDEF; }
+
+#[ \t]*ifdef    { return CPP_IFDEF; }
+#[ \t]*ifndef   { return CPP_IFNDEF; }
+#[ \t]*if       { return CPP_IF; }
+#[ \t]*elif     { return CPP_ELIF; }
+#[ \t]*else     { return CPP_ELSE; }
+#[ \t]*endif    { return CPP_ENDIF; }
+
+$[ \t]*ifdef    { return F90PPR_IFDEF; }
+$[ \t]*ifndef   { return F90PPR_IFNDEF; }
+$[ \t]*if       { return F90PPR_IF; }
+$[ \t]*elif     { return F90PPR_ELIF; }
+$[ \t]*else     { return F90PPR_ELSE; }
+$[ \t]*endif    { return F90PPR_ENDIF; }
+
+&[ \t]*\n |
+&[ \t]*\n[ \t]*& /* Ignore */
+
+
+[^ \t\n\r;,!'""']+ { yylvalp->string = strdup(yytext); return WORD; }
+
+;|\n          { return EOSTMT; }
+
+[ \t\r,]         /* Ignore */
+
+.               { return *yytext; }
+
+<<EOF>> {
+ if(!cmDependsFortranParser_FilePop(yyextra))
+   {
+   return YY_NULL;
+   }
+}
+
+%%
+
+/*--------------------------------------------------------------------------*/
+YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
+{
+  /* Hack into the internal flex-generated scanner to get the buffer.  */
+  struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+  return YY_CURRENT_BUFFER;
+}

+ 70 - 0
Source/cmDependsFortranParser.h

@@ -0,0 +1,70 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmDependsFortranParser_h
+#define cmDependsFortranParser_h
+
+/* Forward declare parser object type.  */
+typedef struct cmDependsFortranParser_s cmDependsFortranParser;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Functions to enter/exit #include'd files in order.  */
+int cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
+                                    const char* fname);
+int cmDependsFortranParser_FilePop(cmDependsFortranParser* parser);
+
+/* Callbacks for lexer.  */
+int cmDependsFortranParser_Input(cmDependsFortranParser* parser,
+                                 char* buffer, size_t bufferSize);
+void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser);
+const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser);
+void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
+                                         char c);
+void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
+                                           int in);
+int cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser);
+
+/* Callbacks for parser.  */
+void cmDependsFortranParser_Error(cmDependsFortranParser* parser,
+                                  const char* message);
+void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
+                                    const char* name);
+void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
+                                        const char* name);
+void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
+                                       const char* name);
+void cmDependsFortranParser_RuleDefine(cmDependsFortranParser* parser,
+                                       const char* name);
+void cmDependsFortranParser_RuleUndef(cmDependsFortranParser* parser,
+                                      const char* name);
+void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser* parser,
+                                      const char* name);
+void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser* parser,
+                                       const char* name);
+void cmDependsFortranParser_RuleIf(cmDependsFortranParser* parser);
+void cmDependsFortranParser_RuleElif(cmDependsFortranParser* parser);
+void cmDependsFortranParser_RuleElse(cmDependsFortranParser* parser);
+void cmDependsFortranParser_RuleEndif(cmDependsFortranParser* parser);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif

+ 165 - 0
Source/cmDependsFortranParser.y

@@ -0,0 +1,165 @@
+%{
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*-------------------------------------------------------------------------
+  Portions of this source have been derived from makefdep90 version 2.6.2,
+
+   Copyright (C) 2000,2001 Erik Edelmann <[email protected]>.
+
+  The code was originally distributed under the GPL but permission
+  from the copyright holder has been obtained to distribute this
+  derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmDependsFortran_yy --defines=cmDependsFortranParserTokens.h -ocmDependsFortranParser.c cmDependsFortranParser.y
+
+*/
+
+/* Configure the parser to use a lexer object.  */
+#define YYPARSE_PARAM yyscanner
+#define YYLEX_PARAM yyscanner
+#define YY_DECL int cmDependsFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+#define YYERROR_VERBOSE 1
+#define cmDependsFortran_yyerror(x) \
+        cmDependsFortranError(yyscanner, x)
+
+#include "cmDependsFortranLexer.h"  /* Interface to lexer object.  */
+#include "cmDependsFortranParser.h" /* Interface to parser object.  */
+
+/* Internal utility functions.  */
+static void cmDependsFortranError(yyscan_t yyscanner, const char* message);
+
+%}
+
+/* Generate a reentrant parser object.  */
+%pure_parser
+
+%union {
+  char* string;
+}
+
+%token USE F_INCLUDE MODULE EOSTMT
+%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
+%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
+%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
+%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
+%token UNTERMINATED_STRING
+%token <string> CPP_TOENDL STRING WORD
+
+%%
+
+code: /* empty */ | code stmt ;
+
+stmt:
+  USE WORD other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleUse(parser, $2);
+    free($2);
+    }
+| include STRING other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleInclude(parser, $2);
+    free($2);
+    }
+| CPP_INCLUDE WORD other eostmt /* Ignore */
+| MODULE WORD eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleModule(parser, $2);
+    free($2);
+    }
+| define WORD other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleDefine(parser, $2);
+    free($2);
+    }
+| undef WORD other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleUndef(parser, $2);
+    free($2);
+    }
+| ifdef WORD other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleIfdef(parser, $2);
+    free($2);
+    }
+| ifndef WORD other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleIfndef(parser, $2);
+    free($2);
+    }
+| if other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleIf(parser);
+    }
+| elif other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleElif(parser);
+    }
+| else other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleElse(parser);
+    }
+| endif other eostmt
+    {
+    cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+    cmDependsFortranParser_RuleEndif(parser);
+    }
+| other eostmt /* Ignore */
+;
+
+eostmt: /* empty */ | EOSTMT ;
+include: F_INCLUDE | CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
+define: CPP_DEFINE | F90PPR_DEFINE ;
+undef: CPP_UNDEF | F90PPR_UNDEF ;
+ifdef: CPP_IFDEF | F90PPR_IFDEF ;
+ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
+if: CPP_IF | F90PPR_IF ;
+elif: CPP_ELIF | F90PPR_ELIF ;
+else: CPP_ELSE | F90PPR_ELSE ;
+endif: CPP_ENDIF | F90PPR_ENDIF ;
+other: /* empty */ | other misc_code ;
+
+misc_code:
+  WORD                { free ($1); }
+| STRING              { free ($1); }
+| UNTERMINATED_STRING
+;
+
+%%
+
+/*--------------------------------------------------------------------------*/
+void cmDependsFortranError(yyscan_t yyscanner, const char* message)
+{
+  cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+  cmDependsFortranParser_Error(parser, message);
+}