From 2dec1060623165057628ee678eb3580351922408 Mon Sep 17 00:00:00 2001 From: albert-github Date: Sun, 9 Mar 2014 18:57:12 +0100 Subject: Bug 625601 - FORTRAN: recognition free versus fixed formatted code The recognition of the type (free or fixed) of Fortran code is not reliable possible. A well known possibility as used with compilers as well is to specify the type of code by means of the extension. With EXTENSION_MAPPING it is possible to select the type of Fortran code, when not explicitly set doxygen tries to guess the type of Fortran code. --- doc/docblocks.doc | 17 +++++++++++++---- src/config.xml | 5 ++++- src/doxygen.cpp | 16 +++++++++------- src/fortrancode.h | 2 +- src/fortrancode.l | 8 +++++--- src/fortranscanner.h | 22 +++++++++++++++++++--- src/fortranscanner.l | 15 +++++++++------ src/util.cpp | 36 +++++++++++++++++++----------------- src/util.h | 2 ++ 9 files changed, 81 insertions(+), 42 deletions(-) diff --git a/doc/docblocks.doc b/doc/docblocks.doc index 6a96588..2cfff9a 100644 --- a/doc/docblocks.doc +++ b/doc/docblocks.doc @@ -460,11 +460,18 @@ settings where overruled. When using doxygen for Fortran code you should set \ref cfg_optimize_for_fortran "OPTIMIZE_FOR_FORTRAN" to \c YES. +The parser tries to guess wheter the source code is fixed format Fortran or +free format Fortran code. This is not always correct, in the later case +one should use \ref cfg_extension_mapping "EXTENSION_MAPPING" to correct this. +By setteing `EXTENSION_MAPPING = f=FortranFixed f90=FortranFree` files with +extension \c f90 are interpreted as fixed format Fortran code and files with +extension \c f are interpreted as free format Fortran code. + For Fortran "!>" or "!<" starts a comment and "!!" or "!>" can be used to continue an one line comment into a multi-line comment. Here is an example of a documented Fortran subroutine: -\verbatim +\code{.f} !> Build the restriction matrix for the aggregation !! method. !! @param aggr information about the aggregates @@ -474,18 +481,20 @@ Here is an example of a documented Fortran subroutine: Type(SpMtx), intent(in) :: A !< our fine level matrix Type(Aggrs), intent(in) :: aggr Type(SpMtx), intent(out) :: Restrict !< Our restriction matrix -\endverbatim + !... + end subroutine +\endcode As an alternative you can also use comments in fixed format code: -\verbatim +\code{.f} C> Function comment C> another line of comment function A(i) C> input parameter integer i end function A -\endverbatim +\endcode \subsection tclblocks Comment blocks in Tcl diff --git a/src/config.xml b/src/config.xml index dcaa372..75b723d 100644 --- a/src/config.xml +++ b/src/config.xml @@ -588,7 +588,10 @@ Go to the next section or return to the Doxygen has a built-in mapping, but you can override or extend it using this tag. The format is ext=language, where \c ext is a file extension, and language is one of the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, - Objective-C, Python, Fortran, VHDL. + Objective-C, Python, Fortran (fixed format Fortran: FortranFixed, + free formatted Fortran: FortranFree, unknown formatted Fortran: Fortran. In + the later case the parser tries to guess whether the code is fixed or free + formatted code, this is the default for Fortran type files), VHDL. For instance to make doxygen treat .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 251f2b4..d6ae5ba 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -9877,13 +9877,15 @@ void initDoxygen() initPreprocessor(); Doxygen::parserManager = new ParserManager; - Doxygen::parserManager->registerParser("c", new CLanguageScanner, TRUE); - Doxygen::parserManager->registerParser("python", new PythonLanguageScanner); - Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner); - Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner); - Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner); - Doxygen::parserManager->registerParser("tcl", new TclLanguageScanner); - Doxygen::parserManager->registerParser("md", new MarkdownFileParser); + Doxygen::parserManager->registerParser("c", new CLanguageScanner, TRUE); + Doxygen::parserManager->registerParser("python", new PythonLanguageScanner); + Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner); + Doxygen::parserManager->registerParser("fortranfree", new FortranLanguageScannerFree); + Doxygen::parserManager->registerParser("fortranfixed", new FortranLanguageScannerFixed); + Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner); + Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner); + Doxygen::parserManager->registerParser("tcl", new TclLanguageScanner); + Doxygen::parserManager->registerParser("md", new MarkdownFileParser); // register any additional parsers here... diff --git a/src/fortrancode.h b/src/fortrancode.h index 8c947e9..2beea69 100644 --- a/src/fortrancode.h +++ b/src/fortrancode.h @@ -28,7 +28,7 @@ void parseFortranCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, - bool collectRefs); + bool collectRefs, FortranKind codeType); void resetFortranCodeParserState(); void codeFreeScanner(); diff --git a/src/fortrancode.l b/src/fortrancode.l index d46a840..8640f15 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -154,11 +154,13 @@ static int bracketCount = 0; // simplified way to know if this is fixed form // duplicate in fortranscanner.l -static bool recognizeFixedForm(const char* contents) +static bool recognizeFixedForm(const char* contents, FortranKind codeType) { int column=0; bool skipLine=FALSE; + if (codeType == FORTRAN_FIXED) return TRUE; + if (codeType == FORTRAN_FREE) return FALSE; for (int i=0;;i++) { column++; @@ -1108,7 +1110,7 @@ void parseFortranCode(CodeOutputInterface &od,const char *className,const QCStri bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, MemberDef *memberDef,bool,Definition *searchCtx, - bool collectXRefs) + bool collectXRefs, FortranKind codeType) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); @@ -1122,7 +1124,7 @@ void parseFortranCode(CodeOutputInterface &od,const char *className,const QCStri g_code = &od; g_inputString = s; g_inputPosition = 0; - g_isFixedForm = recognizeFixedForm((const char*)s); + g_isFixedForm = recognizeFixedForm((const char*)s,codeType); g_currentFontClass = 0; g_needsTermination = FALSE; g_searchCtx = searchCtx; diff --git a/src/fortranscanner.h b/src/fortranscanner.h index a504abc..ec0d312 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -19,6 +19,7 @@ #define SCANNER_FORTRAN_H #include "parserintf.h" +#include "util.h" /** \brief Fortran language parser using state-based lexical scanning. * @@ -27,9 +28,10 @@ class FortranLanguageScanner : public ParserInterface { public: - virtual ~FortranLanguageScanner() {} + FortranLanguageScanner(void) { codeType = FORTRAN_UNKNOWN;} + virtual ~FortranLanguageScanner(void) {} void startTranslationUnit(const char *) {} - void finishTranslationUnit() {} + void finishTranslationUnit(void) {} void parseInput(const char *fileName, const char *fileBuf, Entry *root, @@ -51,8 +53,22 @@ class FortranLanguageScanner : public ParserInterface Definition *searchCtx=0, bool collectXRefs=TRUE ); - void resetCodeParserState(); + void resetCodeParserState(void); void parsePrototype(const char *text); + + FortranKind codeType; +}; + +class FortranLanguageScannerFree : public FortranLanguageScanner +{ + public: + FortranLanguageScannerFree(void) { codeType = FORTRAN_FREE; } +}; + +class FortranLanguageScannerFixed : public FortranLanguageScanner +{ + public: + FortranLanguageScannerFixed(void) { codeType = FORTRAN_FIXED; } }; #endif diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 623f587..f34ad21 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -187,7 +187,7 @@ static InterfaceType ifType = IF_NONE; static bool functionLine = FALSE; static char stringStartSymbol; // single or double quote -static bool parsingPrototype = FALSE; // see parsePrototype() +static bool parsingPrototype = FALSE; // see parsePrototype() //! Accumulated modifiers of current statement, eg variable declaration. static SymbolModifiers currentModifiers; @@ -1313,11 +1313,14 @@ void truncatePrepass(int index) // simplified way to know if this is fixed form // duplicate in fortrancode.l -static bool recognizeFixedForm(const char* contents) +static bool recognizeFixedForm(const char* contents, FortranKind codeType) { int column=0; bool skipLine=FALSE; + if (codeType == FORTRAN_FIXED) return TRUE; + if (codeType == FORTRAN_FREE) return FALSE; + for(int i=0;;i++) { column++; @@ -2243,7 +2246,7 @@ level--; #endif -static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) +static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, FortranKind codeType) { char *tmpBuf = NULL; initParser(); @@ -2263,7 +2266,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) inputFile.setName(fileName); if (inputFile.open(IO_ReadOnly)) { - isFixedForm = recognizeFixedForm(fileBuf); + isFixedForm = recognizeFixedForm(fileBuf,codeType); if (isFixedForm) { @@ -2342,7 +2345,7 @@ void FortranLanguageScanner::parseInput(const char *fileName, printlex(yy_flex_debug, TRUE, __FILE__, fileName); - ::parseMain(fileName,fileBuf,root); + ::parseMain(fileName,fileBuf,root,this->codeType); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -2365,7 +2368,7 @@ void FortranLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, { ::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); + showLineNumbers,searchCtx,collectXRefs,this->codeType); } bool FortranLanguageScanner::needsPreprocessing(const QCString &extension) diff --git a/src/util.cpp b/src/util.cpp index bc93446..9d294f0 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6624,23 +6624,25 @@ static struct Lang2ExtMap } g_lang2extMap[] = { -// language parser parser option - { "idl", "c", SrcLangExt_IDL }, - { "java", "c", SrcLangExt_Java }, - { "javascript", "c", SrcLangExt_JS }, - { "csharp", "c", SrcLangExt_CSharp }, - { "d", "c", SrcLangExt_D }, - { "php", "c", SrcLangExt_PHP }, - { "objective-c", "c", SrcLangExt_ObjC }, - { "c", "c", SrcLangExt_Cpp }, - { "c++", "c", SrcLangExt_Cpp }, - { "python", "python", SrcLangExt_Python }, - { "fortran", "fortran", SrcLangExt_Fortran }, - { "vhdl", "vhdl", SrcLangExt_VHDL }, - { "dbusxml", "dbusxml", SrcLangExt_XML }, - { "tcl", "tcl", SrcLangExt_Tcl }, - { "md", "md", SrcLangExt_Markdown }, - { 0, 0, (SrcLangExt)0 } +// language parser parser option + { "idl", "c", SrcLangExt_IDL }, + { "java", "c", SrcLangExt_Java }, + { "javascript", "c", SrcLangExt_JS }, + { "csharp", "c", SrcLangExt_CSharp }, + { "d", "c", SrcLangExt_D }, + { "php", "c", SrcLangExt_PHP }, + { "objective-c", "c", SrcLangExt_ObjC }, + { "c", "c", SrcLangExt_Cpp }, + { "c++", "c", SrcLangExt_Cpp }, + { "python", "python", SrcLangExt_Python }, + { "fortran", "fortran", SrcLangExt_Fortran }, + { "fortranfree", "fortranfree", SrcLangExt_Fortran }, + { "fortranfixed", "fortranfixed", SrcLangExt_Fortran }, + { "vhdl", "vhdl", SrcLangExt_VHDL }, + { "dbusxml", "dbusxml", SrcLangExt_XML }, + { "tcl", "tcl", SrcLangExt_Tcl }, + { "md", "md", SrcLangExt_Markdown }, + { 0, 0, (SrcLangExt)0 } }; bool updateLanguageMapping(const QCString &extension,const QCString &language) diff --git a/src/util.h b/src/util.h index c3ecad5..5f9a873 100644 --- a/src/util.h +++ b/src/util.h @@ -414,6 +414,8 @@ QCString externalRef(const QCString &relPath,const QCString &ref,bool href); int nextUtf8CharPosition(const QCString &utf8Str,int len,int startPos); const char *writeUtf8Char(FTextStream &t,const char *s); +enum FortranKind { FORTRAN_UNKNOWN = 0, FORTRAN_FREE, FORTRAN_FIXED}; + /** Data associated with a HSV colored image. */ struct ColoredImgDataItem { -- cgit v0.12