Commit 115c6c02 authored by dimitri's avatar dimitri

Release-1.5.3-20070815

parent a56b6170
DOXYGEN Version 1.5.3
DOXYGEN Version 1.5.3-20070815
Please read the installation section of the manual
(http://www.doxygen.org/install.html) for instructions.
--------
Dimitri van Heesch (27 July 2007)
Dimitri van Heesch (15 August 2007)
DOXYGEN Version 1.5.3
DOXYGEN Version 1.5.3_20070815
Please read INSTALL for compilation instructions.
......@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives.
Enjoy,
Dimitri van Heesch (dimitri@stack.nl) (27 July 2007)
Dimitri van Heesch (dimitri@stack.nl) (15 August 2007)
......@@ -20,7 +20,7 @@ doxygen_version_minor=5
doxygen_version_revision=3
#NOTE: Setting version_mmn to "NO" will omit mmn info from the package.
doxygen_version_mmn=NO
doxygen_version_mmn=20070815
bin_dirs=`echo $PATH | sed -e "s/:/ /g"`
......
......@@ -93,12 +93,12 @@ or
Some people like to make their comment blocks more visible in the
documentation. For this purpose you can use the following:
\verbatim
/************************************************
/********************************************//**
* ... text
***********************************************/
\endverbatim
(note the 2 slashes to end the normal comment block and start a special comment block).
or
......
......@@ -95,9 +95,9 @@ valid commands in \f$\mbox{\LaTeX}\f$'s math-mode. For the third command
the section should contain valid command for the specific environment.
\warning Currently, doxygen is not very fault tolerant in recovering
from typos in formulas. It may have to be necessary to remove the
from typos in formulas. It may be necessary to remove the
file <code>formula.repository</code> that is written to the html directory to
a rid of an incorrect formula
get rid of an incorrect formula.
\htmlonly
Go to the <a href="diagrams.html">next</a> section or return to the
......
......@@ -124,7 +124,7 @@ documentation under the terms of the GNU General Public License is hereby
granted. No representations are made about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
See the
<a href="http://www.gnu.org/copyleft/gpl.html">
<a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">
GNU General Public License</a>
for more details.
<p>
......
......@@ -19,6 +19,7 @@
* - Ian Jackson <ian@chiark.greenend.org.uk>.
* Still in the public domain.
*/
#include <string.h> /* for memcpy() */
#include <sys/types.h> /* for stupid systems */
......
......@@ -48,6 +48,6 @@ distclean: clean
-$(RM) scanner.cpp code.cpp config.cpp pre.cpp ce_lex.cpp \
ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp commentscan.cpp \
declinfo.cpp defargs.cpp commentcnv.cpp doctokenizer.cpp \
pycode.cpp pyscanner.cpp
pycode.cpp pyscanner.cpp fortrancode.cpp fortranscanner.cpp
FORCE:
......@@ -2709,6 +2709,7 @@ void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,co
void ClassDef::addInnerCompound(Definition *d)
{
//printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data());
if (d->definitionType()==Definition::TypeClass) // only classes can be
// nested in classes.
{
......
......@@ -2607,8 +2607,8 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
g_code->codify(yytext);
}
<MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
addParmType();
g_parmName=yytext;
//addParmType();
//g_parmName=yytext;
startFontClass("keyword");
g_code->codify(yytext);
endFontClass();
......
......@@ -354,6 +354,7 @@ static OutputContext inContext; // are we inside the brief, details
static bool briefEndsAtDot; // does the brief description stop at a dot?
static QCString formulaText; // Running text of a formula
static QCString formulaEnv; // environment name
static int formulaNewLines; // amount of new lines in the formula
static QCString *pOutputString; // pointer to string to which the output is appended.
static QCString outputXRef; // temp argument of todo/test/../xrefitem commands
static QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...)
......@@ -566,6 +567,8 @@ static QCString addFormula()
{
formLabel.sprintf("\\form#%d",f->getId());
}
int i;
for (i=0;i<formulaNewLines;i++) formLabel+='\n';
return formLabel;
}
......@@ -955,14 +958,17 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
formulaText="\\begin";
formulaEnv=&yytext[2];
formulaText+=formulaEnv;
formulaNewLines=0;
BEGIN(ReadFormulaLong);
}
<Comment>{CMD}"f$" { // start of a inline formula
formulaText="$";
formulaNewLines=0;
BEGIN(ReadFormulaShort);
}
<Comment>{CMD}"f[" { // start of a block formula
formulaText="\\[";
formulaNewLines=0;
BEGIN(ReadFormulaLong);
}
<Comment>{CMD}"{" { // begin of a group
......@@ -1056,6 +1062,7 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]
formulaText+=yytext;
}
<ReadFormulaLong,ReadFormulaShort>\n { // new line
formulaNewLines++;
formulaText+=*yytext;
yyLineNr++;
}
......
......@@ -155,7 +155,7 @@ ID ([a-z_A-Z][a-z_A-Z0-9]*)|(@[0-9]+)
<Start>{B}+ {
addType();
}
<Start>{B}*"("({ID}"::")*{B}*"*"({B}*("const"|"volatile"){B}+)? {
<Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? {
addType();
QCString text=yytext;
type+=text.stripWhiteSpace();
......
......@@ -23,6 +23,7 @@
class ArgumentList;
extern void stringToArgumentList(const char *argsString,ArgumentList* &argList);
extern void stringToArgumentList(const char *argsString,ArgumentList* &argList,
QCString *extraTypeChars=0);
#endif
......@@ -71,6 +71,7 @@ static QCString g_curArgName;
static QCString g_curArgDocs;
static QCString g_curArgAttrib;
static QCString g_curArgArray;
static QCString g_extraTypeChars;
static int g_argRoundCount;
static int g_argSharpCount;
static int g_argCurlyCount;
......@@ -359,6 +360,10 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
<FuncQual>"="{B}*"0" {
g_argList->pureSpecifier=TRUE;
}
<FuncQual>")"{B}*"["[^]]*"]" { // for functions returning a pointer to an array,
// i.e. ")[]" in "int (*f(int))[4]" with argsString="(int))[4]"
g_extraTypeChars=yytext;
}
<ReadDocBlock>[^\*\n]+ {
g_curArgDocs+=yytext;
}
......@@ -402,7 +407,7 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
* \param al a reference to resulting argument list pointer.
*/
void stringToArgumentList(const char *argsString,ArgumentList* &al)
void stringToArgumentList(const char *argsString,ArgumentList* &al,QCString *extraTypeChars)
{
if (al==0) return;
if (argsString==0) return;
......@@ -411,6 +416,7 @@ void stringToArgumentList(const char *argsString,ArgumentList* &al)
g_curArgDocs.resize(0);
g_curArgAttrib.resize(0);
g_curArgArray.resize(0);
g_extraTypeChars.resize(0);
g_argRoundCount = 0;
g_argSharpCount = 0;
g_argCurlyCount = 0;
......@@ -425,6 +431,7 @@ void stringToArgumentList(const char *argsString,ArgumentList* &al)
defargsYYrestart( defargsYYin );
BEGIN( Start );
defargsYYlex();
if (extraTypeChars) *extraTypeChars=g_extraTypeChars;
//printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(al).data());
}
......
......@@ -321,11 +321,12 @@ FUNCARG "("{FUNCCHAR}*")"({BLANK}*("volatile"|"const"))?
OPNEW {BLANK}+"new"({BLANK}*"[]")?
OPDEL {BLANK}+"delete"({BLANK}*"[]")?
OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()"
OPCAST {BLANK}+[^(\r\n.,]+
OPMASK ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG})
OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]*
OPMASK ({BLANK}*{OPNORM}{FUNCARG})
OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG})
LNKWORD1 ("::"|"#")?{SCOPEMASK}
CVSPEC {BLANK}*("const"|"volatile")
LNKWORD2 {SCOPEPRE}*"operator"{OPMASK}
LNKWORD2 ({SCOPEPRE}*"operator"{OPMASK})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOPT})
LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+
CHARWORD [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,.]
CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."]
......
......@@ -68,6 +68,7 @@
#include "parserintf.h"
#include "htags.h"
#include "pyscanner.h"
#include "fortranscanner.h"
#include "code.h"
#include "objcache.h"
#include "store.h"
......@@ -1149,8 +1150,6 @@ static void addClassToContext(EntryNav *rootNav)
else // new class
{
ClassDef::CompoundType sec = convertToCompoundType(root->section,root->spec);
Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d\n",
fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
QCString className;
QCString namespaceName;
......@@ -1168,6 +1167,8 @@ static void addClassToContext(EntryNav *rootNav)
}
cd=new ClassDef(root->fileName,root->startLine,fullName,sec,
tagName,refFileName);
Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d cd=%p\n",
fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1,cd);
cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
cd->setIsObjectiveC(root->objc);
......@@ -1279,6 +1280,7 @@ static void resolveClassNestingRelations()
{
QCString c,n;
extractNamespaceName(cd->name(),c,n,TRUE);
n = stripAnonymousNamespaceScope(n);
if (cd->name().contains("::")==nestingLevel && !n.isEmpty())
{
cd->visited=TRUE;
......@@ -1316,14 +1318,15 @@ static void resolveClassNestingRelations()
if (cd->name().contains("::")==nestingLevel && !cd->visited)
{
cd->visited=TRUE;
QCString name = stripAnonymousNamespaceScope(cd->name());
//printf("Level=%d processing=%s\n",nestingLevel,cd->name().data());
// also add class to the correct structural context
Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,
cd->name(),cd->getFileDef());
name,cd->getFileDef());
if (d==0) // we didn't find anything, create the scope artificially
// anyway, so we can at least relate scopes properly.
{
Definition *d = buildScopeFromQualifiedName(cd->name(),cd->name().contains("::"));
Definition *d = buildScopeFromQualifiedName(name,name.contains("::"));
if (d!=cd) // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; }
// for this case doxygen assumes the exitance of a namespace N::N in which C is to be found!
{
......@@ -1331,7 +1334,7 @@ static void resolveClassNestingRelations()
cd->setOuterScope(d);
warn(cd->getDefFileName(),cd->getDefLine(),
"Warning: Internal inconsistency: scope for class %s not "
"found!",cd->name().data()
"found while looking in the global scope!",name.data()
);
}
}
......@@ -2127,8 +2130,10 @@ static MemberDef *addVariableToFile(
{
if (md->getFileDef() &&
! // not a php array
(getLanguageFromFileName(md->getFileDef()->name())==SrcLangExt_PHP) &&
(md->argsString()!=root->args && root->args.find('[')!=-1)
(
(getLanguageFromFileName(md->getFileDef()->name())==SrcLangExt_PHP) &&
(md->argsString()!=root->args && root->args.find('[')!=-1)
)
)
// not a php array variable
{
......@@ -2600,7 +2605,7 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
FileDef *fd=rootNav->fileDef();
int l,i;
static QRegExp re("([a-z_A-Z0-9: ]*[ *]*[ ]*");
static QRegExp re("([a-z_A-Z0-9: ]*[ &*]*[ ]*");
if (!root->type.isEmpty() && (i=re.match(root->type,0,&l))!=-1) // function variable
{
......@@ -2784,10 +2789,6 @@ static void buildFunctionList(EntryNav *rootNav)
ClassDef *cd=0;
// check if this function's parent is a class
static QRegExp re("([a-z_A-Z0-9: ]*[ *]*[ ]*");
//printf("root->parent=`%s' %x cd=%p root->type.find(re,0)=%d\n",
// root->parent->name.data(),root->parent->section,getClass(root->parent->name),
// root->type.find(re,0));
QCString scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
scope=stripTemplateSpecifiersFromScope(scope,FALSE);
......@@ -2826,12 +2827,14 @@ static void buildFunctionList(EntryNav *rootNav)
}
static QRegExp re("([a-z_A-Z0-9: ]*[ &*]*[ ]*");
if (!rootNav->parent()->name().isEmpty() &&
(rootNav->parent()->section() & Entry::COMPOUND_MASK) &&
cd &&
// do some fuzzy things to exclude function pointers
(root->type.isEmpty() || root->type.find(re,0)==-1 ||
root->type.find(")(")!=-1 || root->type.find("operator")!=-1
(root->type.isEmpty() ||
(root->type.find(re,0)==-1 || root->args.find(")[")!=-1) || // type contains ..(..* and args not )[.. -> function pointer
root->type.find(")(")!=-1 || root->type.find("operator")!=-1 // type contains ..)(.. and not "operator"
)
)
{
......@@ -3122,6 +3125,10 @@ static void buildFunctionList(EntryNav *rootNav)
//printf("unrelated function %d `%s' `%s' `%s'\n",
// root->parent->section,root->type.data(),rname.data(),root->args.data());
}
else
{
Debug::print(Debug::Functions,0," --> %s not processed!\n",rname.data());
}
}
else if (rname.isEmpty())
{
......@@ -4030,7 +4037,7 @@ static bool findClassRelation(
// int *tempArgIndex;
// for (;(tempArgIndex=qdi.current());++qdi)
// {
// printf("(%s->%d) ",qdi.currentKey().data(),*tempArgIndex);
// printf("(%s->%d) ",qdi.currentKey(),*tempArgIndex);
// }
//}
//printf("\n");
......@@ -4077,8 +4084,8 @@ static bool findClassRelation(
);
//printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n",
// baseClassName.data(),baseClass,cd,explicitGlobalScope);
//printf(" root->name=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
// root->name.data(),
//printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
// cd ? cd->name().data():"<none>",
// baseClassName.data(),
// baseClass?baseClass->name().data():"<none>",
// templSpec.data()
......@@ -4091,11 +4098,12 @@ static bool findClassRelation(
if (!isRecursiveBaseClass(rootNav->name(),baseClassName) || explicitGlobalScope)
{
Debug::print(
Debug::Classes,0," class relation %s inherited/used by %s found (%s and %s)\n",
Debug::Classes,0," class relation %s inherited/used by %s found (%s and %s) templSpec='%s'\n",
baseClassName.data(),
rootNav->name().data(),
(bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
(bi->virt==Normal)?"normal":"virtual"
(bi->virt==Normal)?"normal":"virtual",
templSpec.data()
);
int i=baseClassName.find('<');
......@@ -4142,17 +4150,19 @@ static bool findClassRelation(
bool found=baseClass!=0 && (baseClass!=cd || mode==TemplateInstances);
if (!found && si!=-1)
{
QCString tmpTemplSpec;
// replace any namespace aliases
replaceNamespaceAliases(baseClassName,si);
baseClass=getResolvedClass(cd,
cd->getFileDef(),
baseClassName,
&baseClassTypeDef,
&templSpec,
&tmpTemplSpec,
mode==Undocumented,
TRUE
);
found=baseClass!=0 && baseClass!=cd;
if (found) templSpec = tmpTemplSpec;
}
//printf("root->name=%s biName=%s baseClassName=%s\n",
......@@ -4227,6 +4237,8 @@ static bool findClassRelation(
else
{
baseClass=Doxygen::classSDict->find(baseClassName);
//printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n",
// baseClassName.data(),baseClass,biName.data(),templSpec.data());
if (baseClass==0)
{
baseClass=new ClassDef(root->fileName,root->startLine,
......@@ -5384,8 +5396,8 @@ static void findMember(EntryNav *rootNav,
// don't be fooled by anonymous scopes
tcd=cd;
}
//printf("Looking for %s inside nd=%s result=%p\n",
// scopeName.data(),nd?nd->name().data():"<none>",tcd);
//printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n",
// scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd);
if (cd && tcd==cd) // member's classes match
{
......@@ -8825,6 +8837,9 @@ void initDoxygen()
ParserInterface *defaultParser = new CLanguageScanner;
Doxygen::parserManager = new ParserManager(defaultParser);
Doxygen::parserManager->registerParser(".py",new PythonLanguageScanner);
Doxygen::parserManager->registerParser(".f90", new FortranLanguageScanner);
Doxygen::parserManager->registerParser(".F90", new FortranLanguageScanner);
// register any additional parsers here...
......
/******************************************************************************
*
*
*
* Copyright (C) 1997-2006 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef CODE_H
#define CODE_H
#include "qtbc.h"
#include <stdio.h>
class CodeOutputInterface;
class FileDef;
class MemberDef;
void parseFortranCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd=0,
int startLine=-1,int endLine=-1,bool inlineFragment=FALSE,
MemberDef *memberDef=0);
void resetFortranCodeParserState();
void codeFreeScanner();
#endif
/******************************************************************************
*
* Parser for syntax hightlighting and references for Fortran90 F subset
*
* Copyright (C) by Anke Visser
* based on the work of Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
/**
@TODO - continutation lines not always recognized
- merging of use-statements with same module name and different only-names
- rename part of use-statement
- links to interface functions
- references to variables
**/
%{
/*
* includes
*/
#include "qtbc.h"
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <qregexp.h>
#include <qdir.h>
#include <qstringlist.h>
#include "entry.h"
#include "doxygen.h"
#include "message.h"
#include "outputlist.h"
#include "util.h"
#include "membername.h"
#include "searchindex.h"
#include "defargs.h"
#define YY_NEVER_INTERACTIVE 1
#define YY_NO_TOP_STATE 1
//--------------------------------------------------------------------------------
/**
data of an use-statement
*/
class UseEntry
{
public:
QCString module; // just for debug
QStringList onlyNames; /* entries of the ONLY-part */
};
/**
module name -> list of ONLY/remote entries
(module name = name of the module, which can be accessed via use-directive)
*/
class UseSDict : public SDict<UseEntry>
{
public:
UseSDict() : SDict<UseEntry>(17) {}
};
/*===================================================================*/
/*
* statics
*/
static QCString docBlock; //!< contents of all lines of a documentation block
static QCString currentModule=0; //!< name of the current enclosing module
static UseSDict *useMembers= new UseSDict; //!< info about used modules
static UseEntry *useEntry = 0; //!< current use statement info
static QStack<QStringList> useStack; //!< contains names of used modules for current program tree
static QStringList *currentUseNames= new QStringList; //! contains names of used modules of current program unit
static QCString str=""; //!> contents of fortran string
static CodeOutputInterface * g_code;
// TODO: is this still needed? if so, make it work
static QCString g_parmType;
static QCString g_parmName;
static const char * g_inputString; //!< the code fragment as text
static int g_inputPosition; //!< read offset during parsing
static int g_inputLines; //!< number of line in the code fragment
static int g_yyLineNr; //!< current line number
static bool g_needsTermination;
static bool g_insideBody; //!< inside subprog/program body? => create links
static const char * g_currentFontClass;
static bool g_exampleBlock;
static QCString g_exampleName;
static QCString g_exampleFile;
static FileDef * g_sourceFileDef;
static Definition * g_currentDefinition;
static MemberDef * g_currentMemberDef;
static bool g_includeCodeFragment;
static void endFontClass()
{
if (g_currentFontClass)
{
g_code->endFontClass();
g_currentFontClass=0;
}
}
static void startFontClass(const char *s)
{
endFontClass();
g_code->startFontClass(s);
g_currentFontClass=s;
}
static void setCurrentDoc(const QCString &name,const QCString &base,const QCString &anchor="")
{
static bool searchEngineEnabled=Config_getBool("SEARCHENGINE");
if (searchEngineEnabled)
{
Doxygen::searchIndex->setCurrentDoc(name,base,anchor);
}
}
static void addToSearchIndex(const char *text)
{
static bool searchEngineEnabled=Config_getBool("SEARCHENGINE");
if (searchEngineEnabled)
{
Doxygen::searchIndex->addWord(text,FALSE);
}
}
/*! start a new line of code, inserting a line number if g_sourceFileDef
* is TRUE. If a definition starts at the current line, then the line
* number is linked to the documentation of that definition.
*/
static void startCodeLine()
{
if (g_sourceFileDef)
{
//QCString lineNumber,lineAnchor;
//lineNumber.sprintf("%05d",g_yyLineNr);
//lineAnchor.sprintf("l%05d",g_yyLineNr);
Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
//printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>");
if (!g_includeCodeFragment && d)
{
g_currentDefinition = d;
g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
g_insideBody = FALSE;
g_parmType.resize(0);
g_parmName.resize(0);
QCString lineAnchor;
lineAnchor.sprintf("l%05d",g_yyLineNr);
if (g_currentMemberDef)
{
g_code->writeLineNumber(g_currentMemberDef->getReference(),
g_currentMemberDef->getOutputFileBase(),
g_currentMemberDef->anchor(),g_yyLineNr);
setCurrentDoc(
g_currentMemberDef->qualifiedName(),
g_sourceFileDef->getSourceFileBase(),
lineAnchor);
}
else if (d->isLinkableInProject())
{
g_code->writeLineNumber(d->getReference(),
d->getOutputFileBase(),
0,g_yyLineNr);
setCurrentDoc(
d->qualifiedName(),
g_sourceFileDef->getSourceFileBase(),
lineAnchor);
}
}
else
{
g_code->writeLineNumber(0,0,0,g_yyLineNr);
}
}
g_code->startCodeLine();
if (g_currentFontClass)
{
g_code->startFontClass(g_currentFontClass);
}
}
static void endFontClass();
static void endCodeLine()
{
if (g_currentFontClass) { g_code->endFontClass(); }
g_code->endCodeLine();
}
/*! write a code fragment `text' that may span multiple lines, inserting
* line numbers for each line.
*/
static void codifyLines(char *text)
{
//printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
char *p=text,*sp=p;
char c;
bool done=FALSE;
while (!done)
{
sp=p;
while ((c=*p++) && c!='\n');
if (c=='\n')
{
g_yyLineNr++;
*(p-1)='\0';
g_code->codify(sp);
endCodeLine();
if (g_yyLineNr<g_inputLines)
{
startCodeLine();
}
}
else
{
g_code->codify(sp);
done=TRUE;
}
}
}
static void codifyLines(QCString str)
{
char *tmp= (char *) malloc(str.length()+1);
strcpy(tmp, str);
codifyLines(tmp);
free(tmp);
}
/*! writes a link to a fragment \a text that may span multiple lines, inserting
* line numbers for each line. If \a text contains newlines, the link will be
* split into multiple links with the same destination, one for each line.
*/
static void writeMultiLineCodeLink(CodeOutputInterface &ol,
const char *ref,const char *file,
const char *anchor,const char *text)
{
bool done=FALSE;
char *p=(char *)text;
while (!done)
{
char *sp=p;
char c;
while ((c=*p++) && c!='\n');
if (c=='\n')
{
g_yyLineNr++;
*(p-1)='\0';
//printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
ol.writeCodeLink(ref,file,anchor,sp,0);
endCodeLine();
if (g_yyLineNr<g_inputLines)
{
startCodeLine();
}
}
else
{
//printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
ol.writeCodeLink(ref,file,anchor,sp,0);
done=TRUE;
}
}
}
/**
generates dictionay entries that are used if REFERENCED_BY_RELATION ... options are set
(e.g. the "referenced by ..." list after the function documentation)
*/
static void addDocCrossReference(MemberDef *src, MemberDef *dst)
{
if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
//printf("======= addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data());
if ((Config_getBool("REFERENCED_BY_RELATION") || Config_getBool("CALLER_GRAPH")) &&
(src->isFunction()))
{
dst->addSourceReferencedBy(src);
}
if ((Config_getBool("REFERENCES_RELATION") || Config_getBool("CALL_GRAPH")) && (src->isFunction()))
{
src->addSourceReferences(dst);
}
}
//-------------------------------------------------------------------------------
/**
searches for definition of a type
@param memberName the name of the type
@param moduleName name of enclosing module or null, if global entry
@param cd the entry, if found or null
@param useList array of data of USE-statement
@returns true, if type is found
*/
static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName,
ClassDef *&cd, UseSDict *usedict=0)
{
if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */
//cout << "=== search for type: " << tname << endl;
// search for type
if ((cd=Doxygen::classSDict->find(tname)))
{
//cout << "=== type found in global module" << endl;
return TRUE;
}
else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname)))
{
//cout << "=== type found in local module" << endl;
return TRUE;
}
else
{
UseEntry *use;
for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di)
if ((cd= Doxygen::classSDict->find(use->module+"::"+tname)))
{
//cout << "=== type found in used module" << endl;
return TRUE;
}
}
return FALSE;
}
/**
searches for definition of function memberName
@param memberName the name of the function/variable
@param moduleName name of enclosing module or null, if global entry
@param memberDef the entry, if found or null
@param useList array of data of USE-statement
@returns true, if found
*/
static bool getFortranDefs(const QCString &memberName, const QCString &moduleName,
MemberDef *&md, UseSDict *usedict=0)
{
if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */
// search for function
MemberName *mn = Doxygen::functionNameSDict->find(memberName);
if (mn) // name is known
{
MemberListIterator mli(*mn);
for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name
{
FileDef *fd=md->getFileDef();
GroupDef *gd=md->getGroupDef();
//cout << "found link with same name: " << fd->fileName() << " " << memberName;
//if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl;
if ((gd && gd->isLinkable()) || (fd && fd->isLinkable()))
{
NamespaceDef *nspace= md->getNamespaceDef();
if (nspace == 0)
{ // found function in global scope
return TRUE;
}
else if (moduleName == nspace->name())
{ // found in local scope
return TRUE;
}
else
{ // else search in used modules
QCString moduleName= nspace->name();
UseEntry *ue= usedict->find(moduleName);
if (ue)
{
// check if only-list exists and if current entry exists is this list
QStringList &only= ue->onlyNames;
if (only.isEmpty())
{
//cout << " found in module " << moduleName << " entry " << memberName << endl;
return TRUE; // whole module used
}
else
{
for ( QStringList::Iterator it = only.begin(); it != only.end(); ++it)
{
//cout << " search in only: " << moduleName << ":: " << memberName << "==" << (*it)<< endl;
if (memberName == (QCString)(*it))
return TRUE; // found in ONLY-part of use list
}
}
}
}
} // if linkable
} // for
}
return FALSE;
}
/**
gets the link to a generic procedure which depends not on the name, but on the parameter list
@TODO implementation
*/
static bool getGenericProcedureLink(const ClassDef *cd,
const char *memberText,
CodeOutputInterface &ol)
{
(void)cd;
(void)memberText;
(void)ol;
return FALSE;
}
static bool getLink(UseSDict *usedict, // dictonary with used modules
const char *memberText, // exact member text
CodeOutputInterface &ol,
const char *text)
{
MemberDef *md;
QCString memberName= removeRedundantWhiteSpace(memberText);
//printf("Trying `%s'::`%s'\n",c.data(),m.data());
if (getFortranDefs(memberName, currentModule, md, usedict) && md->isLinkable())
{
//if (md->isVariable()) return FALSE; // variables aren't handled yet
Definition *d = md->getOuterScope()==Doxygen::globalScope ?
md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable())
{
if (g_currentDefinition && g_currentMemberDef && md!=g_currentMemberDef && g_insideBody)
{
addDocCrossReference(g_currentMemberDef,md);
}
ol.linkableSymbol(g_yyLineNr,md->name(),md,
g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
writeMultiLineCodeLink(ol,md->getReference(),
md->getOutputFileBase(),
md->anchor(),
text ? text : memberText);
addToSearchIndex(text ? text : memberText);
return TRUE;
}
}
return FALSE;
}
static void generateLink(CodeOutputInterface &ol, char *lname)
{
ClassDef *cd=0;
// check if lname is a linkable type or interface
if ( (getFortranTypeDefs(lname, currentModule, cd, useMembers)) && cd->isLinkable() )
{
if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) &&
(getGenericProcedureLink(cd, lname, ol)) )
{
//cout << "=== generic procedure resolved" << endl;
}
else
{ // write type or interface link
ol.linkableSymbol(g_yyLineNr, lname, cd, g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
writeMultiLineCodeLink(ol,cd->getReference(),cd->getOutputFileBase(),0,lname);
addToSearchIndex(lname);
}
}
// check for function/variable
else if (getLink(useMembers, lname, ol, lname))
{
//cout << "=== found link for " << lname << endl;
}
else
{
// nothing found, just write out the word
ol.linkableSymbol(g_yyLineNr, lname, 0, g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
//startFontClass("charliteral"); //test
codifyLines(lname);
//endFontClass(); //test
addToSearchIndex(lname);
}
}
/*! counts the number of lines in the input */
static int countLines()
{
const char *p=g_inputString;
char c;
int count=1;
while ((c=*p))
{
p++ ;
if (c=='\n') count++;
}
if (p>g_inputString && *(p-1)!='\n')
{ // last line does not end with a \n, so we add an extra
// line and explicitly terminate the line after parsing.
count++,
g_needsTermination=TRUE;
}
return count;
}
//----------------------------------------------------------------------------
/** start use list */
void startUseScope()
{
//fprintf("===> startUse %s",yytext);
useStack.push(currentUseNames);
currentUseNames= new QStringList;
}
/** end use list */
void endUseScope()
{
//fprintf(stderr,"===> endUse %s",yytext);
//UseSDict::Iterator di(*useMembers); UseEntry *ue;
//for (di.toFirst(); ue=di.current(); ++di){cout << ue->module ;} cout << endl;
for ( QStringList::Iterator it = currentUseNames->begin(); it != currentUseNames->end(); ++it)
{
useMembers->remove(*it);
}
delete currentUseNames;
currentUseNames= useStack.pop();
if (currentUseNames == 0)
{
fprintf(stderr,"fortrancode.l: stack empty!");
//exit(-1);
}
}
void addUse(QString moduleName)
{
currentUseNames->append(moduleName);
}
//----------------------------------------------------------------------------
/* -----------------------------------------------------------------*/
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
static int yyread(char *buf,int max_size)
{
int c=0;
while( c < max_size && g_inputString[g_inputPosition] )
{
*buf = g_inputString[g_inputPosition++] ;
c++; buf++;
}
return c;
}
%}
IDSYM [a-z_A-Z0-9]
ID [a-z_A-Z]+{IDSYM}*
SUBPROG (subroutine|function)
B [ \t]
BS [ \t]*
BS_ [ \t]+
COMMA {BS},{BS}
ARGS {BS}("("[^)]*")"){BS}
NUM_TYPE (complex|integer|logical|real)
KIND {ARGS}
CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"([0-9]+|{ARGS}))
TYPE_SPEC (({NUM_TYPE}("*"[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}PRECISION|{CHAR})
INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
ATTR_SPEC (ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PRIVATE|PUBLIC|SAVE|TARGET)
ACCESS_SPEC (PRIVATE|PUBLIC)
/* Assume that attribute statements are almost the same as attributes. */
ATTR_STMT {ATTR_SPEC}|DIMENSION
COMMANDS (BLOCK{BS}DATA|DO|SELECT|CASE|WHERE|IF|THEN|ELSE|MODULE{BS_}PROCEDURE)
IGNORE (IMPLICIT{BS}NONE|CONTAINS|WRITE|READ|ALLOCATE|DEALLOCATE|SIZE)
/* | */
%option noyywrap
%option stack
%option caseless
/*%option debug*/
%x Start
%x SubCall
%x FuncDef
%x ClassName
%x ClassVar
%x Subprog
%x DocBlock
%x Use
%x UseOnly
%x TypeDecl
%x Declaration
%x DeclContLine
%x Parameterlist
%x String
%%
/*==================================================================*/
/*-------- ignore ------------------------------------------------------------*/
<Start>{IGNORE}/{BS}"("? { // do not search keywords, intrinsics... @TODO: complete list
codifyLines(yytext);
}
/*-------- inner construct ---------------------------------------------------*/
<Start>{COMMANDS}/[,( \t\n].* { // hightlight rest of fortran statements
/* font class is defined e.g. in doxygen.css */
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
}
<Start>"end"{BS}{COMMANDS}/[ \t\n].* {
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
}
/*-------- use statement -------------------------------------------*/
<Start>"use"{BS_} {
codifyLines(yytext);
yy_push_state(YY_START);
BEGIN(Use);
}
<Use>{ID} {
startFontClass("keywordflow");
codifyLines(yytext);
endFontClass();
/* append module name to use dict */
useEntry = new UseEntry();
useEntry->module = yytext;
useMembers->append(yytext, useEntry);
addUse(yytext);
}
<Use>,{BS}"ONLY" { // TODO: rename
codifyLines(yytext);
yy_push_state(YY_START);
BEGIN(UseOnly);
}
<UseOnly>{BS},{BS} { codifyLines(yytext); }
<UseOnly>{ID} {
codifyLines(yytext);
useEntry->onlyNames.append(yytext);
}
<Use,UseOnly>"\n" {
unput(*yytext);
yy_pop_state();
}
/*-------- fortran module -----------------------------------------*/
<Start>("program"|"module"|"type"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { //
startUseScope();
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
yy_push_state(YY_START);
BEGIN(ClassName);
if (!strcmp(yytext,"module")) currentModule="module";
}
<ClassName>{ID} {
if (currentModule == "module") currentModule=yytext;
generateLink(*g_code,yytext);
yy_pop_state();
}
<ClassName>\n { // interface may be without name
yy_pop_state();
REJECT;
}
<Start>"end"{BS}"module".* { // just reset currentModule, rest is done in following rule
currentModule=0;
REJECT;
}
<Start>"end"{BS}("program"|"module"|"type"|"interface") { //
endUseScope();
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
}
/*-------- subprog definition -------------------------------------*/
<Start>{TYPE_SPEC}{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
}
<Start>{SUBPROG}{BS_} { // Fortran subroutine or function found
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
yy_push_state(YY_START);
BEGIN(Subprog);
}
<Subprog>{ID} { // subroutine/function name
//cout << "===> start procedure " << yytext << endl;
startUseScope();
generateLink(*g_code,yytext);
}
<Subprog>"(".* { // ignore rest of line
codifyLines(yytext);
}
<Subprog>"\n" { codifyLines(yytext);
yy_pop_state();
}
<Start>"end"{BS}{SUBPROG}.* { // Fortran subroutine or function ends
//cout << "===> end function " << yytext << endl;
endUseScope();
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
}
/*-------- variable declaration ----------------------------------*/
<Start>"TYPE"{BS}"(" {
yy_push_state(YY_START);
BEGIN(TypeDecl);
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<TypeDecl>{ID} { // link type
g_insideBody=TRUE;
generateLink(*g_code,yytext);
g_insideBody=FALSE;
}
<TypeDecl>")" {
BEGIN(Declaration);
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<Start>{TYPE_SPEC}/[,:( ] {
yy_push_state(YY_START);
BEGIN(Declaration);
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<Start>{ATTR_SPEC} {
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable deklaration
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<Declaration>"&" { // continuation line
yy_push_state(YY_START);
BEGIN(DeclContLine);
}
<DeclContLine>"\n" { // declaration not yet finished
codifyLines(yytext);
yy_pop_state();
}
<Declaration>"\n" { // end declaration line
codifyLines(yytext);
yy_pop_state();
}
/*-------- subprog calls -----------------------------------------*/
<Start>"call"{BS_} {
codifyLines(yytext);
yy_push_state(YY_START);
BEGIN(SubCall);
}
<SubCall>{ID} { // subroutine call
g_insideBody=TRUE;
generateLink(*g_code, yytext);
g_insideBody=FALSE;
yy_pop_state();
}
<Start>{ID}{BS}/"(" { // function call
g_insideBody=TRUE;
generateLink(*g_code, yytext);
g_insideBody=FALSE;
}
/*-------- comments ---------------------------------------------------*/
<Start>\n?{BS}"!>" { // start comment line or comment block
yy_push_state(YY_START);
BEGIN(DocBlock);
docBlock=yytext;
}
<DocBlock>.* { // contents of current comment line
docBlock+=yytext;
}
<DocBlock>"\n"{BS}("!>"|"!"+) { //| comment block (next line is also comment line)
docBlock+=yytext;
}
<DocBlock>"\n" { // comment block ends at the end of this line
docBlock+=yytext;
// remove special comment (default config)
if (Config_getBool("STRIP_CODE_COMMENTS"))
{
g_yyLineNr+=((QCString)docBlock).contains('\n');
endCodeLine();
if (g_yyLineNr<g_inputLines)
{
startCodeLine();
}
}
else // do not remove comment
{
startFontClass("comment");
codifyLines(docBlock);
endFontClass();
}
yy_pop_state();
}
<*>"!"[^>\n].*|"!"$ { // normal comment
startFontClass("comment");
codifyLines(yytext);
endFontClass();
}
/*------ preprocessor --------------------------------------------*/
<Start>"#".*\n { startFontClass("preprocessor");
codifyLines(yytext);
endFontClass();
}
/*------ variable references? -------------------------------------*/
<Start>{ID} {
g_insideBody=TRUE;
generateLink(*g_code, yytext);
g_insideBody=FALSE;
}
/*------ strings --------------------------------------------------*/
<*>"\\\\" { str+=yytext; /* ignore \\ */}
<*>"\\\"" { str+=yytext; /* ignore \" */}
<String>\" { // string ends with next quote without previous backspace
str+=yytext;
startFontClass("stringliteral");
codifyLines(str);
endFontClass();
yy_pop_state();
}
<*>\" { /* string starts */
yy_push_state(YY_START);
BEGIN(String);
str=yytext;
}
<String>. {str+=yytext;}
/*-----------------------------------------------------------------------------*/
<*>\n {
codifyLines(yytext);
}
<*>. {
g_code->codify(yytext);
}
%%
/*@ ----------------------------------------------------------------------------
*/
/*===================================================================*/
void resetFortranCodeParserState() {}
void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s,
bool exBlock, const char *exName,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
MemberDef *memberDef)
{
//printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
// used parameters
(void)memberDef;
(void)className;
if (s.isEmpty()) return;
g_code = &od;
g_inputString = s;
g_inputPosition = 0;
g_currentFontClass = 0;
g_needsTermination = FALSE;
if (endLine!=-1)
g_inputLines = endLine+1;
else
g_inputLines = countLines();
if (startLine!=-1)
g_yyLineNr = startLine;
else
g_yyLineNr = 1;
g_exampleBlock = exBlock;
g_exampleName = exName;
g_sourceFileDef = fd;
if (exBlock && fd==0)
{
// create a dummy filedef for the example
g_sourceFileDef = new FileDef("",exName);
}
if (g_sourceFileDef)
{
setCurrentDoc(g_sourceFileDef->name(),g_sourceFileDef->getSourceFileBase());
}
g_currentDefinition = 0;
g_currentMemberDef = 0;
if (!g_exampleName.isEmpty())
{
g_exampleFile = convertNameToFile(g_exampleName+"-example");
}
g_includeCodeFragment = inlineFragment;
startCodeLine();
g_parmName.resize(0);
g_parmType.resize(0);
fcodeYYrestart( fcodeYYin );
BEGIN( Start );
fcodeYYlex();
if (g_needsTermination)
{
endFontClass();
g_code->endCodeLine();
}
if (exBlock && g_sourceFileDef)
{
// delete the temporary file definition used for this example
delete g_sourceFileDef;
g_sourceFileDef=0;
}
return;
}
#if !defined(YY_FLEX_SUBMINOR_VERSION)
extern "C" { // some bogus code to keep the compiler happy
void fcodeYYdummy() { yy_flex_realloc(0,0); }
}
#elif YY_FLEX_SUBMINOR_VERSION<33
#error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!"
#endif
/******************************************************************************
*
*
*
* Copyright (C) 1997-2006 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef SCANNER_FORTRAN_H
#define SCANNER_FORTRAN_H
#include "parserintf.h"
/** \brief Fortran language parser using state-based lexical scanning.
*
* This is the Fortran language parser for doxygen.
*/
class FortranLanguageScanner : public ParserInterface
{
public:
virtual ~FortranLanguageScanner() {}
void parseInput(const char *fileName,
const char *fileBuf,
Entry *root);
bool needsPreprocessing(const QCString &extension);
void parseCode(CodeOutputInterface &codeOutIntf,
const char *scopeName,
const QCString &input,
bool isExampleBlock,
const char *exampleName=0,
FileDef *fileDef=0,
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
MemberDef *memberDef=0
);
void resetCodeParserState();
void parsePrototype(const char *text);
};
#endif
/* -*- mode: fundamental; indent-tabs-mode: 1; -*- */
/*****************************************************************************
* Parser for Fortran90 F subset
*
* Copyright (C) by Anke Visser
* based on the work of Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
/* Developer notes.
*
* - Consider using startScope(), endScope() functions with module, program,
* subroutine or any other scope in fortran program.
*
* - Symbol modifiers (attributes) are collected using SymbolModifiers |= operator during
* substructure parsing. When substructure ends all modifiers are applied to actual
* entries in applyModifiers() functions.
*
* - How case insensitiveness should be handled in code?
* On one side we have arg->name and entry->name, on another side modifierMap[name].
* In entries and arguments case is the same as in code, in modifier map case is lowered and
* then it is compared to lowered entry/argument names.
*
* - Do not like constructs like aa{BS} or {BS}bb. Should try to handle blank space
* with separate rule?: It seems it is often necessary, because we may parse something like
* "functionA" or "MyInterface". So constructs like `(^|[ \t])interface({BS_}{ID})?/[ \t\n]'
* are desired.
*/
%{
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include "qtbc.h"
#include <qarray.h>
#include <qstack.h>
#include <qregexp.h>
#include <unistd.h>
#include <qfile.h>
#include <qmap.h>
#include "fortranscanner.h"
#include "entry.h"
#include "message.h"
#include "config.h"
#include "doxygen.h"
#include "util.h"
#include "defargs.h"
#include "language.h"
#include "commentscan.h"
#include "fortrancode.h"
#include "pre.h"
#define YY_NEVER_INTERACTIVE 1
enum ScanVar { V_IGNORE, V_VARIABLE, V_PARAMETER};
// {{{ ----- Helper structs -----
//! Holds modifiers (ie attributes) for one symbol (variable, function, etc)
struct SymbolModifiers {
enum Protection {NONE_P, PUBLIC, PRIVATE};
enum Direction {NONE_D, IN, OUT, INOUT};
//!< This is only used with function return value.
QString type, returnName;
Protection protection;
Direction direction;
bool optional;
QString dimension;
bool allocatable;
bool external;
bool intrinsic;
bool parameter;
bool pointer;
bool target;
bool save;
SymbolModifiers() : type(), returnName(), protection(NONE_P), direction(NONE_D),
optional(FALSE), dimension(), allocatable(FALSE),
external(FALSE), intrinsic(FALSE), parameter(FALSE),
pointer(FALSE), target(FALSE), save(FALSE) {}
SymbolModifiers& operator|=(const SymbolModifiers &mdfs);
SymbolModifiers& operator|=(QString mdfrString);
};
//ostream& operator<<(ostream& out, const SymbolModifiers& mdfs);
static const char *directionStrs[] =
{
"", "intent(in)", "intent(out)", "intent(inout)"
};
// }}}
/* -----------------------------------------------------------------
*
* statics
*/
static ParserInterface *g_thisParser;
static const char * inputString;
static int inputPosition;
static QFile inputFile;
static QCString yyFileName;
static int yyLineNr = 1 ;
static Entry* current_root = 0 ;
static Entry* global_root = 0 ;
static Entry* file_root = 0 ;
static Entry* current = 0 ;
static Entry* last_entry = 0 ;
static ScanVar v_type = V_IGNORE; // type of parsed variable
static QList<Entry> moduleProcedures; // list of all interfaces which contain unresolved
// module procedures
static QCString docBlock;
static QCString docBlockName;
static bool docBlockInBody;
static bool docBlockJavaStyle;
static MethodTypes mtype;
static bool gstat;
static Specifier virt;
static QString debugStr;
static QCString result; // function result
static Argument *parameter; // element of parameter list
static QCString argType; // fortran type of an argument of a parameter list
static QCString argName; // last identifier name in variable list
static QCString initializer; // initial value of a variable
static QCString useModuleName; // name of module in the use statement
static Protection defaultProtection;
static char stringStartSymbol; // single or double quote
//! Accumulated modifiers of current statement, eg variable declaration.
static SymbolModifiers currentModifiers;
//! Holds program scope->symbol name->symbol modifiers.
static QMap<Entry*,QMap<QString,SymbolModifiers> > modifiers;
//-----------------------------------------------------------------------------
static int yyread(char *buf,int max_size);
static void startCommentBlock(bool);
static void handleCommentBlock(const QCString &doc,bool brief);
static void addCurrentEntry();
static void addInterface(QString name);
static Argument *addFortranParameter(const QCString &type,const QCString &name, const QString docs);
static void scanner_abort();
static void startScope(Entry *scope);
static bool endScope(Entry *scope);
static QString getFullName(Entry *e);
static bool isTypeName(QString name);
static void resolveModuleProcedures(QList<Entry> &moduleProcedures, Entry *current_root);
//-----------------------------------------------------------------------------
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
//-----------------------------------------------------------------------------
%}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
IDSYM [a-z_A-Z0-9]
NOTIDSYM [^a-z_A-Z0-9]
SEPARATE [:, \t]
ID [a-z_A-Z]+{IDSYM}*
PP_ID {ID}
LABELID [a-z_A-Z]+[a-z_A-Z0-9\-]*
SUBPROG (subroutine|function)
B [ \t]
BS [ \t]*
BS_ [ \t]+
COMMA {BS},{BS}
ARGS {BS}("("[^)]*")"){BS}
NOARGS {BS}"\n"
NUM_TYPE (complex|integer|logical|real)
KIND {ARGS}
CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"([0-9]+|{ARGS}))
TYPE_SPEC (({NUM_TYPE}("*"[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}PRECISION|{CHAR}|TYPE{ARGS})
INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
ATTR_SPEC (ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PRIVATE|PUBLIC|SAVE|TARGET)
ACCESS_SPEC (PRIVATE|PUBLIC)
/* Assume that attribute statements are almost the same as attributes. */
ATTR_STMT {ATTR_SPEC}|DIMENSION
%option noyywrap
%option stack
%option caseless
/*%option debug */
//---------------------------------------------------------------------------------
/** fortran parsing states */
%x Subprog
%x Parameterlist
%x SubprogBody
%x Start
%x Comment
%x Module
%x ModuleBody
%x AttributeList
%x Variable
%x Initialization
%x ArrayInitializer
%x Typedef
%x TypedefBody
%x InterfaceBody
%x StrIgnore
%x String
%x Use
%x UseOnly
%x ModuleProcedure
/** comment parsing states */
%x DocBlock
%x DocBackLine
%x EndDoc
%%
/*-----------------------------------------------------------------------------------*/
<*>"&".*"\n" { if (YY_START == String) REJECT; // "&" is ignored in strings
yyLineNr++;} /* line not finished -> read next line (text after "&" may be
comment and has to be ignored */
/*------ ignore strings */
<*>"\\\\" { /* ignore \\ */}
<*>"\\\""|\\\' { /* ignore \" and \' */}
<String>\"|\' { // string ends with next quote without previous backspace
if(yytext[0]!=stringStartSymbol) REJECT; // single vs double quote
// cout << "string end: " << debugStr << endl;
yy_pop_state();
}
<String>. {debugStr+=yytext;} // ignore String contents (especially '!')
<*>\"|\' { /* string starts */
if(YY_START == StrIgnore) REJECT; // ignore in simple comments
// cout << "string start: " << yytext[0] << yyLineNr << endl;
yy_push_state(YY_START);
stringStartSymbol=yytext[0]; // single or double quote
BEGIN(String); debugStr="!^!";
}
/*------ ignore simple comment (not documentation comments) */
<*>"!"/[^<>\n] { if (YY_START == String) REJECT; // "!" is ignored in strings
// skip comment line (without docu comments "!>" "!<" )
/* ignore further "!" and ignore comments in Strings */
if ((YY_START != StrIgnore) && (YY_START != String)) {
yy_push_state(YY_START);
BEGIN(StrIgnore);
debugStr="*!";
//cout << "start comment "<< yyLineNr << endl;
}
}
<StrIgnore>.?/\n { yy_pop_state(); // comment ends with endline character
//cout << "end comment " << yyLineNr <<" "<< debugStr << endl;
} // comment line ends
<StrIgnore>. { debugStr+=yytext; }
/*------ use handling ------------------------------------------------------------*/
<Start,ModuleBody,TypedefBody,SubprogBody>"use"{BS_} {
yy_push_state(YY_START);
BEGIN(Use);
}
<Use>{ID} {
//cout << "using dir "<< yytext << endl;
current->name=yytext;
current->fileName = yyFileName;
current->section=Entry::USINGDIR_SEC;
current_root->addSubEntry(current);
current = new Entry;
yy_pop_state();
}
<Use>{ID}/, {
useModuleName=yytext;
}
<Use>,{BS}"ONLY" { BEGIN(UseOnly);
}
<UseOnly>{BS},{BS} {}
<UseOnly>{ID} {
current->name= useModuleName+"::"+yytext;
current->fileName = yyFileName;
current->section=Entry::USINGDECL_SEC;
current_root->addSubEntry(current);
current = new Entry ;
}
<Use,UseOnly>"\n" {
unput(*yytext);
yy_pop_state();
}
/*------ ignore special fortran statements */
<Start,ModuleBody,SubprogBody>(^|[ \t])interface({BS_}{ID})?/[ \t\n] { // handle interface block
QString name = yytext;
int index = name.find("interface", 0, FALSE);
index = name.find(QRegExp("[^ \\t]"), index+9);
//cout<<name<<", "<<index<<endl;
if(index!=-1)
name = name.right(name.length()-index);
else // interface without name, must be inside subprog
name = "interface";
addInterface(name);
yy_push_state(InterfaceBody);
startScope(last_entry);
}
<InterfaceBody>"end"{BS}"interface".* {
if(!endScope(current_root))
yyterminate();
yy_pop_state();
//cout << "end interface " << yyLineNr
// <<", "<<Interface<<endl;
}
<InterfaceBody>module{BS}procedure { yy_push_state(YY_START);
BEGIN(ModuleProcedure);
}
<ModuleProcedure>{ID} {
current->section = Entry::FUNCTION_SEC ;
current->name = yytext;
moduleProcedures.append(current);
addCurrentEntry();
}
<ModuleProcedure>"\n" { unput(*yytext);
yy_pop_state();
}
<InterfaceBody>. {}
/*------ module handling ------------------------------------------------------------*/
<Start>module|program{BS_} { //
BEGIN(Module);
defaultProtection = Public;
}
<Start,ModuleBody>"end"{BS}(module|program).* { // end module
resolveModuleProcedures(moduleProcedures, current_root);
if(!endScope(current_root))
yyterminate();
defaultProtection = Public;
BEGIN(Start);
}
<Module>{ID} {
//cout << "0=========> got module " << yytext << endl;
current->section = Entry::NAMESPACE_SEC;
current->name = yytext;
current->type = "module";
current->fileName = yyFileName;
current->bodyLine = yyLineNr; // used for source reference
current->protection = Public ;
addCurrentEntry();
startScope(last_entry);
BEGIN(ModuleBody);
}
/*------- access specification --------------------------------------------------------------------------*/
<ModuleBody>private/{BS}(\n|"!") { defaultProtection = Private; }
<ModuleBody>public/{BS}(\n|"!") { defaultProtection = Public; }
/*------- type definition -------------------------------------------------------------------------------*/
<Start,ModuleBody>"type"({BS_}|({COMMA}{ACCESS_SPEC})) { /* type definition found : TYPE , access-spec::type-name |*/
yy_push_state(YY_START);
BEGIN(Typedef);
current->protection = defaultProtection;
}
<Typedef>{ACCESS_SPEC} {
QString type= yytext;
}
<Typedef>{ID} { /* type name found */
//cout << "=========> got typedef " << yytext << ": " << yyLineNr << endl;
current->section = Entry::CLASS_SEC; // was Entry::STRUCT_SEC;
current->spec = Entry::Struct;
current->name = yytext;
/* if type is part of a module, mod name is necessary for output */
if ((current_root) &&
(current_root->section == Entry::CLASS_SEC ||
current_root->section == Entry::NAMESPACE_SEC))
//current_root->section == Entry::INTERFACE_SEC))
{
current->name= current_root->name+"::"+current->name;
}
current->fileName = yyFileName;
current->bodyLine = yyLineNr;
addCurrentEntry();
startScope(last_entry);
BEGIN(TypedefBody);
}
<TypedefBody>"end"{BS}"type".* { /* end type definition */
//cout << "=========> got typedef end "<< endl;
if(!endScope(current_root))
yyterminate();
yy_pop_state();
}
/*------- module/global/typedef variable ---------------------------------------------------*/
<Start,ModuleBody,TypedefBody,SubprogBody>{
{TYPE_SPEC}/{SEPARATE} {
/* variable declaration starts */
//cout << "4=========> got variable type: " << yytext << endl;
QString help=yytext;
help= help.simplifyWhiteSpace();
argType= help.latin1();
yy_push_state(AttributeList);
}
^{BS}{PP_ID}{KIND}? { /* check for preprocessor symbol expand to type */
QString str = yytext;
str = str.stripWhiteSpace();
DefineDict* defines = getFileDefineDict();
QString name;
int index = str.find("(");
if(index != -1)
name = str.left(index).stripWhiteSpace();
else
name = str;
Define *define = (*defines)[name];
if(define != NULL && isTypeName(define->definition)) {
argType = str;
yy_push_state(AttributeList);
} else {
REJECT;
}
}
{ATTR_STMT}{BS}/{ID} {
/* attribute statement starts */
//cout << "5=========> Attribute statement: "<< yytext << endl;
QString tmp = yytext;
currentModifiers |= tmp.stripWhiteSpace();
argType="";
yy_push_state(YY_START);
/* goto attribute parsing, however there must not be one,
just catch "::" if it is there. */
BEGIN( AttributeList ) ;
}
}
<AttributeList>{
{COMMA} {}
{BS} {}
{ATTR_SPEC} { /* update current modifiers */
QString tmp = yytext;
currentModifiers |= (tmp);
}
"::" { /* end attribute list */
BEGIN( Variable );
}
. { /* unknown attribute, consider variable name */
//cout<<"start variables, unput "<<*yytext<<endl;
unput(*yytext);
BEGIN( Variable );
}
}
<Variable>{BS} {}
<Variable>{ID} { /* parse variable declaration */
//cout << "5=========> got variable: " << argType << "::" << yytext << endl;
/* work around for bug in QCString.replace (QString works) */
QString name=yytext;
/* remember attributes for the symbol */
modifiers[current_root][name.lower()] |= currentModifiers;
argName= name.latin1();
int last= yy_top_state();
v_type= V_IGNORE;
if (!argType.isEmpty() && last != SubprogBody) { // new variable entry
v_type = V_VARIABLE;
current->section = Entry::VARIABLE_SEC;
current->name = argName;
current->type = argType;
current->fileName = yyFileName;
current->bodyLine = yyLineNr; // used for source reference
addCurrentEntry();
} else if(!argType.isEmpty()){ // deklaration of parameter list: add type for corr. parameter
parameter= addFortranParameter(argType,argName,docBlock);
if (parameter) v_type= V_PARAMETER;
// save, it may be function return type
modifiers[current_root][name.lower()].type = argType;
// any accumulated doc for argument should be emptied,
// because it is handled other way and this doc can be
// unexpectedly passed to the next member.
current->doc.resize(0);
current->brief.resize(0);
}
}
<Variable>{ARGS} { /* dimension of the previous entry. */
QString name(argName);
QString attr("dimension");
attr += yytext;
modifiers[current_root][name] |= attr;
}
<Variable>{COMMA} {}
<Variable>{BS}"=" { yy_push_state(YY_START);
initializer="";
BEGIN(Initialization);
}
<Variable>"\n" { currentModifiers = SymbolModifiers();
yy_pop_state(); // end variable deklaration list
yyLineNr++;
docBlock.resize(0);
}
<Initialization>"(/" { initializer+=yytext;
BEGIN(ArrayInitializer); // initializer may contain comma
}
<ArrayInitializer>. { initializer+=yytext; }
<ArrayInitializer>"/)" { initializer+=yytext;
yy_pop_state(); // end initialization
if (v_type == V_VARIABLE) last_entry->initializer= initializer;
}
<Initialization>{COMMA} { yy_pop_state(); // end initialization
if (v_type == V_VARIABLE) last_entry->initializer= initializer;
}
<Initialization>"\n"|"!" { //|
yy_pop_state(); // end initialization
if (v_type == V_VARIABLE) last_entry->initializer= initializer;
unput(*yytext);
}
<Initialization>. { initializer+=yytext; }
/*------ fortran subroutine/function handling ------------------------------------------------------------*/
/* Start is initial condition */
<Start,ModuleBody,InterfaceBody>{TYPE_SPEC}{BS}/{SUBPROG}{BS_} {
// TYPE_SPEC is for old function style function result
result= yytext;
result= result.stripWhiteSpace();
current->type = result;
}
<Start,ModuleBody,SubprogBody,InterfaceBody>{BS}{SUBPROG}{BS_} { // Fortran subroutine or function found
//cout << "1=========> got subprog, type:" << yytext <<endl;
current->section = Entry::FUNCTION_SEC ;
QCString subtype = yytext; subtype=subtype.lower().stripWhiteSpace();
if (!current->type) current->type = subtype;
current->fileName = yyFileName;
current->bodyLine = yyLineNr; // used for source reference
current->startLine = -1; // ??? what is startLine for?
current->args.resize(0);
current->argList->clear();
yy_push_state(Subprog);
docBlock.resize(0);
}
<Subprog>{BS} { /* ignore white space */ }
<Subprog>{ID} { current->name = yytext;
//cout << "1a==========> got " << current->type << " " << yytext << " " << yyLineNr << endl;
modifiers[current_root][current->name.lower()].returnName = current->name;
BEGIN(Parameterlist);
}
<Parameterlist>{ARGS} {
//current->type not yet available
QString arglist= yytext;
//cout << "3=========> got parameterlist " << yytext << endl;
yyLineNr+= arglist.contains('\n');
arglist = arglist.replace(QRegExp("&[^\n]*\n"),"");
//cout << "3=========> got parameterlist " << arglist << endl;
current->args = arglist;
current->args = removeRedundantWhiteSpace(current->args);
stringToArgumentList(current->args, current->argList);
addCurrentEntry();
startScope(last_entry);
BEGIN(SubprogBody);
}
<Parameterlist>{NOARGS} {
yyLineNr++;
//cout << "3=========> without parameterlist " <<endl;
stringToArgumentList("", current->argList);
addCurrentEntry();
startScope(last_entry);
BEGIN(SubprogBody);
}
<SubprogBody>result{BS}\({BS}{ID} {
result= yytext;
result= result.right(result.length()-result.find("(")-1);
result= result.stripWhiteSpace();
modifiers[current_root->parent()][current_root->name.lower()].returnName = result;
//cout << "=====> got result " << result << endl;
}
<SubprogBody>"end"{BS}{SUBPROG}.* {
//cout << "1e=========> got end subprog: " << yytext << endl;
/* args is used for parameters in list of functions, argList for
parameters in detailed function descripttion */
//current->args = argListToString(current->argList);
//current->endBodyLine = yyLineNr; // ??? what ist endBodyLine for
if(!endScope(current_root))
yyterminate();
yy_pop_state() ;
}
/*---- documentation comments --------------------------------------------------------------------*/
<Variable>"!<" { /* backward docu comment (only one line) */
if (v_type != V_IGNORE) {
yy_push_state(YY_START);
current->docLine = yyLineNr;
docBlockJavaStyle = FALSE;
docBlock.resize(0);
docBlockJavaStyle = Config_getBool("JAVADOC_AUTOBRIEF");
startCommentBlock(TRUE);
BEGIN(DocBackLine);
}
}
<DocBackLine>.* { // contents of current comment line
docBlock=yytext;
if (v_type == V_VARIABLE) {
Entry *tmp_entry = current;
current = last_entry; // temporarily switch to the previous entry
handleCommentBlock(docBlock,TRUE);
current=tmp_entry;
}
else if (v_type == V_PARAMETER) {
parameter->docs=docBlock;
}
yy_pop_state();
}
<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody>"!>" {
yy_push_state(YY_START);
current->docLine = yyLineNr;
docBlockJavaStyle = FALSE;
docBlock.resize(0);
docBlockJavaStyle = Config_getBool("JAVADOC_AUTOBRIEF");
startCommentBlock(TRUE);
BEGIN(DocBlock);
//cout << "start DocBlock " << endl;
}
<DocBlock>.* { // contents of current comment line
docBlock+=yytext;
}
<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line)
docBlock+="\n"; // \n is necessary for lists
yyLineNr++;
}
<DocBlock>"\n" { // comment block ends at the end of this line
//cout <<"3=========> comment block : "<< docBlock << endl;
unput(*yytext);
handleCommentBlock(docBlock,TRUE);
yy_pop_state();
}
/*------------------------------------------------------------------------------------------------*/
<*>"\n" {yyLineNr++;
//if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <<YY_START << endl;
debugStr="";
}
/*---- error: EOF in wrong state --------------------------------------------------------------------*/
<SubprogBody,ModuleBody,String,StrIgnore,InterfaceBody><<EOF>> {
fprintf(stderr,"==== Error: EOF reached in wrong state (end missing)");
scanner_abort();
yyterminate();
}
<*>. {debugStr+=yytext;} // ignore remaining text
/**********************************************************************************/
/**********************************************************************************/
/**********************************************************************************/
%%
//----------------------------------------------------------------------------
/** used to copy entry to an interface module procedure */
static void copyEntry(Entry *dest, Entry *src)
{
dest->type = src->type;
dest->fileName = src->fileName;
dest->bodyLine = src->bodyLine;
dest->args = src->args;
dest->argList = new ArgumentList(*src->argList);
}
/** fill empty interface module procedures with info from
corresponding module subprogs
@TODO: handle procedures in used modules
*/
void resolveModuleProcedures(QList<Entry> &moduleProcedures, Entry *current_root)
{
if (moduleProcedures.isEmpty()) return;
EntryListIterator eli1(moduleProcedures);
// for all module procedures
for (Entry *ce1; (ce1=eli1.current()); ++eli1)
{
// check all entries in this module
EntryListIterator eli2(*current_root->children());
for (Entry *ce2; (ce2=eli2.current()); ++eli2)
{
if (ce1->name == ce2->name)
{
copyEntry(ce1, ce2);
}
} // for procedures in current module
} // for all interface module procedures
moduleProcedures.clear();
}
static bool isTypeName(QString name)
{
name = name.lower();
return name=="integer" || name == "real" ||
name=="complex" || name == "logical";
}
/*! Extracts string which resides within parentheses of provided string. */
static QString extractFromParens(const QString name)
{
QString extracted = name;
int start = extracted.find("(");
if(start != -1)
{
extracted.remove(0, start+1);
}
int end = extracted.findRev(")");
if(end != -1)
{
int length = extracted.length();
extracted.remove(end, length);
}
extracted = extracted.stripWhiteSpace();
return extracted;
}
/*! Adds passed modifiers to these modifiers.*/
SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs)
{
if(mdfs.protection!=NONE_P) protection = mdfs.protection;
if(mdfs.direction!=NONE_D) direction = mdfs.direction;
optional |= mdfs.optional;
if(!mdfs.dimension.isNull()) dimension = mdfs.dimension;
allocatable |= mdfs.allocatable;
external |= mdfs.external;
intrinsic |= mdfs.intrinsic;
parameter |= mdfs.parameter;
pointer |= mdfs.pointer;
target |= mdfs.target;
save |= mdfs.save;
return *this;
}
/*! Extracts and adds passed modifier to these modifiers.*/
SymbolModifiers& SymbolModifiers::operator|=(QString mdfString)
{
mdfString = mdfString.lower();
SymbolModifiers newMdf;
if (mdfString.startsWith("dimension"))
{
newMdf.dimension=mdfString;
}
else if (mdfString.contains("intent"))
{
QString tmp = extractFromParens(mdfString);
bool isin = tmp.contains("in");
bool isout = tmp.contains("out");
if(isin && isout) newMdf.direction = SymbolModifiers::INOUT;
else if(isin) newMdf.direction = SymbolModifiers::IN;
else if(isout) newMdf.direction = SymbolModifiers::OUT;
}
else if (mdfString=="public")
{
newMdf.protection = SymbolModifiers::PUBLIC;
}
else if (mdfString=="private")
{
newMdf.protection = SymbolModifiers::PRIVATE;
}
else if (mdfString=="optional")
{
newMdf.optional = TRUE;
}
else if (mdfString=="allocatable")
{
newMdf.allocatable = TRUE;
}
else if (mdfString=="external")
{
newMdf.external = TRUE;
}
else if(mdfString=="intrinsic")
{
newMdf.intrinsic = TRUE;
}
else if(mdfString=="parameter")
{
newMdf.parameter = TRUE;
}
else if(mdfString=="pointer")
{
newMdf.pointer = TRUE;
}
else if(mdfString=="target")
{
newMdf.target = TRUE;
}
else if(mdfString=="save")
{
newMdf.save = TRUE;
}
(*this) |= newMdf;
return *this;
}
/*! For debugging purposes. */
//ostream& operator<<(ostream& out, const SymbolModifiers& mdfs)
//{
// out<<mdfs.protection<<", "<<mdfs.direction<<", "<<mdfs.optional<<
// ", "<<(mdfs.dimension.isNull() ? "" : mdfs.dimension.latin1())<<
// ", "<<mdfs.allocatable<<", "<<mdfs.external<<", "<<mdfs.intrinsic;
//
// return out;
//}
/*! Find argument with given name in \a subprog entry. */
static Argument *findArgument(Entry* subprog, QString name, bool byTypeName = FALSE)
{
QCString cname(name.lower());
for (unsigned int i=0; i<subprog->argList->count(); i++)
{
Argument *arg = subprog->argList->at(i);
if(!byTypeName && arg->name.lower() == cname ||
byTypeName && arg->type.lower() == cname)
return arg;
}
return NULL;
}
/*! Find function with given name in \a entry. */
#if 0
static Entry *findFunction(Entry* entry, QString name)
{
QCString cname(name.lower());
EntryListIterator eli(*entry->children());
Entry *ce;
for (;(ce=eli.current());++eli)
{
if(ce->section != Entry::FUNCTION_SEC)
continue;
if(ce->name.lower() == cname)
return ce;
}
return NULL;
}
#endif
/*! Apply modifiers stored in \a mdfs to the \a typeName string. */
static QString applyModifiers(QString typeName, SymbolModifiers& mdfs)
{
if(!mdfs.dimension.isNull())
{
typeName += ",";
typeName += mdfs.dimension;
}
if(mdfs.direction!=SymbolModifiers::NONE_D)
{
typeName += ",";
typeName += directionStrs[mdfs.direction];
}
if(mdfs.optional)
{
typeName += ",";
typeName += "optional";
}
if(mdfs.allocatable)
{
typeName += ",";
typeName += "allocatable";
}
if(mdfs.external)
{
typeName += ",";
typeName += "external";
}
if(mdfs.intrinsic)
{
typeName += ",";
typeName += "intrinsic";
}
if(mdfs.parameter)
{
typeName += ",";
typeName += "parameter";
}
if(mdfs.pointer)
{
typeName += ",";
typeName += "pointer";
}
if(mdfs.target)
{
typeName += ",";
typeName += "target";
}
if(mdfs.save)
{
typeName += ",";
typeName += "save";
}
return typeName;
}
/*! Apply modifiers stored in \a mdfs to the \a arg argument. */
static void applyModifiers(Argument *arg, SymbolModifiers& mdfs)
{
QString tmp = arg->type;
arg->type = applyModifiers(tmp, mdfs);
}
/*! Apply modifiers stored in \a mdfs to the \a ent entry. */
static void applyModifiers(Entry *ent, SymbolModifiers& mdfs)
{
QString tmp = ent->type;
ent->type = applyModifiers(tmp, mdfs);
if(mdfs.protection == SymbolModifiers::PUBLIC)
ent->protection = Public;
else if(mdfs.protection == SymbolModifiers::PRIVATE)
ent->protection = Private;
}
/*! Starts the new scope in fortran program. Consider using this function when
* starting module, interface, function or other program block.
* \see endScope()
*/
static void startScope(Entry *scope)
{
//cout<<"start scope: "<<scope->name<<endl;
current_root= scope; /* start substructure */
QMap<QString,SymbolModifiers> mdfMap;
modifiers.insert(scope, mdfMap);
}
/*! Ends scope in fortran program: may update subprogram arguments or module variable attributes.
* \see startScope()
*/
static bool endScope(Entry *scope)
{
//cout<<"end scope: "<<scope->name<<endl;
if (current_root->parent())
{
current_root= current_root->parent(); /* end substructure */
}
else
{
fprintf(stderr,"parse error in end <scopename>");
scanner_abort();
return FALSE;
}
// update variables or subprogram arguments with modifiers
QMap<QString,SymbolModifiers>& mdfsMap = modifiers[scope];
if(scope->section == Entry::FUNCTION_SEC)
{
// iterate all symbol modifiers of the scope
for(QMap<QString,SymbolModifiers>::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++) {
//cout<<it.key()<<": "<<it.data()<<endl;
Argument *arg = findArgument(scope, it.key());
if(arg)
applyModifiers(arg, it.data());
}
// find return type for function
//cout<<"RETURN NAME "<<modifiers[current_root][scope->name.lower()].returnName<<endl;
QString returnName = modifiers[current_root][scope->name.lower()].returnName.lower();
if(modifiers[scope].contains(returnName))
{
scope->type = modifiers[scope][returnName].type; // returning type works
applyModifiers(scope, modifiers[scope][returnName]); // returning array works
}
}
else if(scope->section == Entry::CLASS_SEC)
{ // was INTERFACE_SEC
if(scope->parent()->section == Entry::FUNCTION_SEC)
{ // interface within function
// iterate functions of interface and
// try to find types for dummy(ie. argument) procedures.
//cout<<"Search in "<<scope->name<<endl;
EntryListIterator eli(*scope->children());
Entry *ce;
for (;(ce=eli.current());++eli)
{
if(ce->section != Entry::FUNCTION_SEC)
continue;
Argument *arg = findArgument(scope->parent(), ce->name, TRUE);
if(arg != NULL)
{
// set type of dummy procedure argument to interface
arg->name = arg->type;
arg->type = scope->name;
}
}
}
}
else
{ // not function section or interface
// iterate variables: get and apply modifiers
EntryListIterator eli(*scope->children());
Entry *ce;
for (;(ce=eli.current());++eli)
{
if(ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC)
continue;
//cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl;
if(mdfsMap.contains(ce->name.lower()))
applyModifiers(ce, mdfsMap[ce->name.lower()]);
}
}
// clear all modifiers of the scope
modifiers.remove(scope);
return TRUE;
}
//! Return full name of the entry. Sometimes we must combine several names recursively.
static QString getFullName(Entry *e)
{
QString name = e->name;
if(e->section == Entry::CLASS_SEC // || e->section == Entry::INTERFACE_SEC
|| !e->parent() || e->parent()->name.isEmpty())
return name;
return getFullName(e->parent())+"::"+name;
}
static int yyread(char *buf,int max_size)
{
int c=0;
while( c < max_size && inputString[inputPosition] )
{
*buf = inputString[inputPosition++] ;
c++; buf++;
}
return c;
}
static void initParser()
{
last_entry = 0;
}
static void initEntry()
{
current->protection = defaultProtection ;
current->mtype = mtype;
current->virt = virt;
current->stat = gstat;
initGroupInfo(current);
}
/**
adds current entry to current_root and creates new current
*/
static void addCurrentEntry()
{
//cout << "Adding entry " <<current->name.data() << endl;
current_root->addSubEntry(current);
last_entry = current;
current = new Entry ;
initEntry();
}
/*! Adds interface to the root entry.
* \note Code was brought to this procedure from the parser,
* because there was/is idea to use it in several parts of the parser.
*/
static void addInterface(QString name)
{
current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC;
current->spec = Entry::Interface;
current->name = name;
/* if type is part of a module, mod name is necessary for output */
if ((current_root) &&
(current_root->section == Entry::CLASS_SEC ||
current_root->section == Entry::NAMESPACE_SEC))
{
current->name= current_root->name+"::"+current->name;
}
if ((current_root) &&
(current_root->section == Entry::FUNCTION_SEC))
{
current->name = getFullName(current_root) + "__" + QString(current->name);
}
current->fileName = yyFileName;
current->bodyLine = yyLineNr;
addCurrentEntry();
}
//-----------------------------------------------------------------------------
/*! Update the argument \a name with additional \a type info.
*/
static Argument *addFortranParameter(const QCString &type,const QCString &name, const QString docs)
{
//cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isNull()?QString("null"):docs)<<endl;
Argument *ret = 0;
if (current_root->argList==0) return FALSE;
ArgumentListIterator ali(*current_root->argList);
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
if (a->type.lower()==name.lower())
{
ret=a;
//cout << "addParameter found: " << type << " , " << name << endl;
a->type=type.stripWhiteSpace();
a->name=name.stripWhiteSpace();
if(!docs.isNull())
a->docs = docs;
break;
}
} // for
return ret;
}
//----------------------------------------------------------------------------
static void startCommentBlock(bool brief)
{
if (brief)
{
current->briefFile = yyFileName;
current->briefLine = yyLineNr;
}
else
{
current->docFile = yyFileName;
current->docLine = yyLineNr;
}
}
//----------------------------------------------------------------------------
static void handleCommentBlock(const QCString &doc,bool brief)
{
docBlockInBody = FALSE;
bool needsEntry = FALSE;
static bool hideInBodyDocs = Config_getBool("HIDE_IN_BODY_DOCS");
int position=0;
if (docBlockInBody && hideInBodyDocs) return;
//fprintf(stderr,"call parseCommentBlock [%s]\n",doc.data());
while (parseCommentBlock(
g_thisParser,
docBlockInBody ? last_entry : current,
doc, // text
yyFileName, // file
brief ? current->briefLine : current->docLine, // line of block start
docBlockInBody ? FALSE : brief,
docBlockInBody ? FALSE : docBlockJavaStyle,
docBlockInBody,
defaultProtection,
position,
needsEntry
))
{
//fprintf(stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry);
if (needsEntry) addCurrentEntry();
}
//fprintf(stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry);
if (needsEntry) addCurrentEntry();
}
//----------------------------------------------------------------------------
static int level=0;
static void debugCompounds(Entry *rt) // print Entry structure (for debugging)
{
level++;
printf("%d) debugCompounds(%s) line %d\n",level, rt->name.data(), rt->bodyLine);
EntryListIterator eli(*rt->children());
Entry *ce;
for (;(ce=eli.current());++eli)
{
debugCompounds(ce);
}
level--;
}
static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
{
initParser();
defaultProtection = Public;
inputString = fileBuf;
inputPosition = 0;
//anonCount = 0; // don't reset per file
mtype = Method;
gstat = FALSE;
virt = Normal;
current_root = rt;
global_root = rt;
inputFile.setName(fileName);
if (inputFile.open(IO_ReadOnly))
{
yyLineNr= 1 ;
yyFileName = fileName;
msg("Parsing file %s...\n",yyFileName.data());
current_root = rt ;
initParser();
groupEnterFile(yyFileName,yyLineNr);
current = new Entry;
current->name = yyFileName;
current->section = Entry::SOURCE_SEC;
current_root->addSubEntry(current);
file_root = current;
current = new Entry;
fscanYYrestart( fscanYYin );
{
BEGIN( Start );
}
fscanYYlex();
groupLeaveFile(yyFileName,yyLineNr);
//debugCompounds(rt); //debug
rt->program.resize(0);
delete current; current=0;
moduleProcedures.clear();
inputFile.close();
}
}
//----------------------------------------------------------------------------
void FortranLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root)
{
g_thisParser = this;
::parseMain(fileName,fileBuf,root);
}
void FortranLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
const char * scopeName,
const QCString & input,
bool isExampleBlock,
const char * exampleName,
FileDef * fileDef,
int startLine,
int endLine,
bool inlineFragment,
MemberDef *memberDef
)
{
::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
fileDef,startLine,endLine,inlineFragment,memberDef);
}
bool FortranLanguageScanner::needsPreprocessing(const QCString &extension)
{
(void)extension;
return TRUE;
}
void FortranLanguageScanner::resetCodeParserState()
{
::resetFortranCodeParserState();
}
void FortranLanguageScanner::parsePrototype(const char *text)
{
(void)text;
}
static void scanner_abort()
{
fprintf(stderr,"********************************************************************\n");
fprintf(stderr,"Error in file %s line: %d, state: %d\n",yyFileName.data(),yyLineNr,YY_START);
fprintf(stderr,"********************************************************************\n");
EntryListIterator eli(*global_root->children());
Entry *ce;
bool start=FALSE;
for (;(ce=eli.current());++eli)
{
if (ce == file_root) start=TRUE;
if (start) ce->reset();
}
return;
//exit(-1);
}
//----------------------------------------------------------------------------
#if !defined(YY_FLEX_SUBMINOR_VERSION)
//----------------------------------------------------------------------------
extern "C" { // some bogus code to keep the compiler happy
void fscannerYYdummy() { yy_flex_realloc(0,0); }
}
#endif
......@@ -930,6 +930,7 @@ void HtmlGenerator::writeCodeLink(const char *ref,const char *f,
const char *tooltip)
{
QCString *dest;
//printf("writeCodeLink(ref=%s,f=%s,anchor=%s,name=%s,tooltip=%s)\n",ref,f,anchor,name,tooltip);
if (ref)
{
t << "<a class=\"codeRef\" ";
......
......@@ -450,6 +450,11 @@ void HtmlHelp::createProjectFile()
t << "tab_b.gif" << endl;
t << "tab_l.gif" << endl;
t << "tab_r.gif" << endl;
if (Config_getBool("HTML_DYNAMIC_SECTIONS"))
{
t << "open.gif" << endl;
t << "closed.gif" << endl;
}
f.close();
}
else
......
......@@ -2589,7 +2589,7 @@ void writeGroupIndexItem(GroupDef *gd,MemberList *ml,const QCString &title,
first=FALSE;
if (htmlHelp)
{
htmlHelp->addContentsItem(TRUE, convertToHtml(title), gd->getOutputFileBase(),0);
htmlHelp->addContentsItem(TRUE, convertToHtml(title,TRUE), gd->getOutputFileBase(),0);
htmlHelp->incContentsDepth();
}
if (ftvHelp)
......@@ -2715,7 +2715,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
SectionInfo *si=0;
if (!pd->name().isEmpty()) si=Doxygen::sectionDict[pd->name()];
if (htmlHelp) htmlHelp->addContentsItem(FALSE,
convertToHtml(pd->title()),
convertToHtml(pd->title(),TRUE),
gd->getOutputFileBase(),
si ? si->label.data() : 0
);
......@@ -2723,7 +2723,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
gd->getReference(),
gd->getOutputFileBase(),
si ? si->label.data() : 0,
convertToHtml(pd->title())
convertToHtml(pd->title(),TRUE)
);
}
......@@ -2762,7 +2762,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
{
if (htmlHelp)
{
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trNamespaces()), gd->getOutputFileBase(), 0);
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trNamespaces(),TRUE), gd->getOutputFileBase(), 0);
htmlHelp->incContentsDepth();
}
......@@ -2779,11 +2779,11 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
{
if (htmlHelp)
{
htmlHelp->addContentsItem(FALSE, convertToHtml(nsd->name()), nsd->getOutputFileBase());
htmlHelp->addContentsItem(FALSE, convertToHtml(nsd->name(),TRUE), nsd->getOutputFileBase());
}
if (ftvHelp)
{
ftvHelp->addContentsItem(FALSE, nsd->getReference(), nsd->getOutputFileBase(), 0, convertToHtml(nsd->name()));
ftvHelp->addContentsItem(FALSE, nsd->getReference(), nsd->getOutputFileBase(), 0, convertToHtml(nsd->name(),TRUE));
}
}
if (htmlHelp) htmlHelp->decContentsDepth();
......@@ -2795,7 +2795,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
{
if (htmlHelp)
{
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trClasses()), gd->getOutputFileBase(), 0);
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trClasses(),TRUE), gd->getOutputFileBase(), 0);
htmlHelp->incContentsDepth();
}
......@@ -2832,7 +2832,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
if (htmlHelp)
{
htmlHelp->addContentsItem(TRUE,
convertToHtml(theTranslator->trFile(TRUE,FALSE)),
convertToHtml(theTranslator->trFile(TRUE,FALSE),TRUE),
gd->getOutputFileBase(), 0);
htmlHelp->incContentsDepth();
}
......@@ -2850,9 +2850,9 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
while (fd)
{
if (htmlHelp)
htmlHelp->addContentsItem(FALSE,convertToHtml(fd->name()),fd->getOutputFileBase());
htmlHelp->addContentsItem(FALSE,convertToHtml(fd->name(),TRUE),fd->getOutputFileBase());
if (ftvHelp)
ftvHelp->addContentsItem(FALSE, fd->getReference(), fd->getOutputFileBase(), 0, convertToHtml(fd->name()));
ftvHelp->addContentsItem(FALSE, fd->getReference(), fd->getOutputFileBase(), 0, convertToHtml(fd->name(),TRUE));
fd=fileList->next();
}
if (htmlHelp)
......@@ -2866,7 +2866,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
{
if (htmlHelp)
{
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trExamples()), gd->getOutputFileBase(), 0);
htmlHelp->addContentsItem(TRUE, convertToHtml(theTranslator->trExamples(),TRUE), gd->getOutputFileBase(), 0);
htmlHelp->incContentsDepth();
}
......@@ -2991,9 +2991,9 @@ void writeDirTreeNode(OutputList &ol, DirDef *dd,int level)
while (fd)
{
if (htmlHelp)
htmlHelp->addContentsItem(FALSE,convertToHtml(fd->name()),fd->getOutputFileBase());
htmlHelp->addContentsItem(FALSE,convertToHtml(fd->name(),TRUE),fd->getOutputFileBase());
if (ftvHelp)
ftvHelp->addContentsItem(FALSE, fd->getReference(), fd->getOutputFileBase(), 0, convertToHtml(fd->name()));
ftvHelp->addContentsItem(FALSE, fd->getReference(), fd->getOutputFileBase(), 0, convertToHtml(fd->name(),TRUE));
fd=fileList->next();
}
}
......
......@@ -53,10 +53,12 @@
//}
static QCString escapeLabelName(const char *s)
static QCString escapeLabelName(LatexGenerator *g,const char *s)
{
QCString result;
const char *p=s;
char str[2];
str[1]=0;
char c;
while ((c=*p++))
{
......@@ -65,7 +67,7 @@ static QCString escapeLabelName(const char *s)
case '%': result+="\\%"; break;
case '|': result+="\\tt{\"|}"; break;
case '!': result+="\"!"; break;
default: result+=c;
default: str[0]=c; g->docify(str); break;
}
}
return result;
......@@ -1069,7 +1071,7 @@ void LatexGenerator::endTitleHead(const char *fileName,const char *name)
if (name)
{
t << "\\label{" << fileName << "}\\index{"
<< name << "@{";
<< escapeLabelName(this,name) << "@{";
escapeMakeIndexChars(this,t,name);
t << "}}" << endl;
}
......@@ -1139,15 +1141,15 @@ void LatexGenerator::startMemberDoc(const char *clname,
t << "\\index{";
if (clname)
{
t << clname << "@{";
docify(clname);
t << escapeLabelName(this,clname) << "@{";
escapeMakeIndexChars(this,t,clname);
t << "}!";
}
t << escapeLabelName(memname) << "@{";
t << escapeLabelName(this,memname) << "@{";
escapeMakeIndexChars(this,t,memname);
t << "}}" << endl;
t << "\\index{" << escapeLabelName(memname) << "@{";
t << "\\index{" << escapeLabelName(this,memname) << "@{";
escapeMakeIndexChars(this,t,memname);
t << "}";
if (clname)
......@@ -1221,12 +1223,12 @@ void LatexGenerator::addIndexItem(const char *s1,const char *s2)
{
if (s1)
{
t << "\\index{" << escapeLabelName(s1) << "@{";
t << "\\index{" << escapeLabelName(this,s1) << "@{";
escapeMakeIndexChars(this,t,s1);
t << "}";
if (s2)
{
t << "!" << escapeLabelName(s2) << "@{";
t << "!" << escapeLabelName(this,s2) << "@{";
escapeMakeIndexChars(this,t,s2);
t << "}";
}
......@@ -1356,9 +1358,9 @@ void LatexGenerator::startAnonTypeScope(int indent)
{
t << "\\begin{tabbing}" << endl;
t << "xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=\\kill" << endl;
//printf("LatexGenerator::startMemberItem() insideTabbing=TRUE\n");
insideTabbing=TRUE;
}
m_indent=indent;
}
void LatexGenerator::endAnonTypeScope(int indent)
......@@ -1368,6 +1370,7 @@ void LatexGenerator::endAnonTypeScope(int indent)
t << endl << "\\end{tabbing}";
insideTabbing=FALSE;
}
m_indent=indent;
}
void LatexGenerator::startMemberTemplateParams()
......@@ -1401,7 +1404,7 @@ void LatexGenerator::endMemberItem()
if (insideTabbing)
{
t << "\\\\";
}
}
templateMemberItem = FALSE;
t << endl;
}
......@@ -1414,7 +1417,7 @@ void LatexGenerator::startMemberDescription()
}
else
{
for (int i=0;i<m_indent+1;i++) t << "\\>";
for (int i=0;i<m_indent+2;i++) t << "\\>";
t << "{\\em ";
}
}
......@@ -1427,18 +1430,17 @@ void LatexGenerator::endMemberDescription()
}
else
{
t << "}\\\\";
m_indent=0;
t << "}\\\\\n";
}
}
void LatexGenerator::writeNonBreakableSpace(int)
{
//printf("writeNonBreakbleSpace()\n");
if (insideTabbing)
{
t << "\\>";
m_indent++;
}
else
t << "~";
......
......@@ -82,6 +82,8 @@ HEADERS = bufstr.h \
printdocvisitor.h \
pycode.h \
pyscanner.h \
fortrancode.h \
fortranscanner.h \
qtbc.h \
reflist.h \
rtfdocvisitor.h \
......@@ -190,6 +192,8 @@ SOURCES = ce_lex.cpp \
pre.cpp \
pycode.cpp \
pyscanner.cpp \
fortrancode.cpp \
fortranscanner.cpp \
reflist.cpp \
rtfdocvisitor.cpp \
rtfgen.cpp \
......
......@@ -57,6 +57,12 @@ sub GenerateDep {
#$ GenerateDep("pycode.cpp","pycode.l");
$(LEX) -PpycodeYY -t pycode.l | $(INCBUFSIZE) >pycode.cpp
#$ GenerateDep("fortranscanner.cpp","fortranscanner.l");
$(LEX) -i -PfscanYY -t fortranscanner.l | $(INCBUFSIZE) >fortranscanner.cpp
#$ GenerateDep("fortrancode.cpp","fortrancode.l");
$(LEX) -i -PfcodeYY -t fortrancode.l | $(INCBUFSIZE) >fortrancode.cpp
#$ GenerateDep("pre.cpp","pre.l");
$(LEX) -PpreYY -t pre.l | $(INCBUFSIZE) >pre.cpp
......
......@@ -259,6 +259,10 @@ static bool writeDefArgumentList(OutputList &ol,ClassDef *cd,
ol.endParameterName(TRUE,TRUE,!md->isObjCMethod());
}
ol.popGeneratorState();
if (md->extraTypeChars())
{
ol.docify(md->extraTypeChars());
}
if (defArgList->constSpecifier)
{
ol.docify(" const");
......@@ -334,6 +338,7 @@ class MemberDefImpl
QCString write; // property write accessor
QCString exception; // exceptions that can be thrown
QCString initializer; // initializer
QCString extraTypeChars; // extra type info found after the argument list
int initLines; // number of lines in the initializer
int memSpec; // The specifiers present for this member
......@@ -525,7 +530,7 @@ void MemberDefImpl::init(Definition *def,
if (!args.isEmpty())
{
declArgList = new ArgumentList;
stringToArgumentList(args,declArgList);
stringToArgumentList(args,declArgList,&extraTypeChars);
//printf("setDeclArgList %s to %p const=%d\n",args.data(),
// declArgList,declArgList->constSpecifier);
}
......@@ -725,6 +730,11 @@ QCString MemberDef::getOutputFileBase() const
QCString MemberDef::getReference() const
{
makeResident();
QCString ref = Definition::getReference();
if (!ref.isEmpty())
{
return ref;
}
if (m_impl->templateMaster)
{
return m_impl->templateMaster->getReference();
......@@ -1406,7 +1416,10 @@ void MemberDef::writeDeclaration(OutputList &ol,
//printf("endMember %s annoClassDef=%p annEnumType=%p\n",
// name().data(),annoClassDef,annEnumType);
ol.endMemberItem();
if (endAnonScopeNeeded) ol.endAnonTypeScope(--s_indentLevel);
if (endAnonScopeNeeded)
{
ol.endAnonTypeScope(--s_indentLevel);
}
// write brief description
if (!briefDescription().isEmpty() &&
......@@ -2872,6 +2885,7 @@ void MemberDef::setTagInfo(TagInfo *ti)
if (ti)
{
makeResident();
//printf("%s: Setting tag name=%s anchor=%s\n",name().data(),ti->tagName.data(),ti->anchor.data());
m_impl->anc=ti->anchor;
setReference(ti->tagName);
m_impl->explicitOutputFileBase = stripExtension(ti->fileName);
......@@ -2905,7 +2919,13 @@ const char *MemberDef::declaration() const
const char *MemberDef::definition() const
{
makeResident();
return m_impl->def;
return m_impl->def;
}
const char *MemberDef::extraTypeChars() const
{
makeResident();
return m_impl->extraTypeChars;
}
const char *MemberDef::typeString() const
......@@ -3661,6 +3681,7 @@ void MemberDef::flushToDisk() const
marshalQCString (Doxygen::symbolStorage,m_impl->write);
marshalQCString (Doxygen::symbolStorage,m_impl->exception);
marshalQCString (Doxygen::symbolStorage,m_impl->initializer);
marshalQCString (Doxygen::symbolStorage,m_impl->extraTypeChars);
marshalInt (Doxygen::symbolStorage,m_impl->initLines);
marshalInt (Doxygen::symbolStorage,m_impl->memSpec);
marshalInt (Doxygen::symbolStorage,(int)m_impl->mtype);
......@@ -3760,6 +3781,7 @@ void MemberDef::loadFromDisk() const
m_impl->write = unmarshalQCString (Doxygen::symbolStorage);
m_impl->exception = unmarshalQCString (Doxygen::symbolStorage);
m_impl->initializer = unmarshalQCString (Doxygen::symbolStorage);
m_impl->extraTypeChars = unmarshalQCString (Doxygen::symbolStorage);
m_impl->initLines = unmarshalInt (Doxygen::symbolStorage);
m_impl->memSpec = unmarshalInt (Doxygen::symbolStorage);
m_impl->mtype = (MemberDef::MemberType)unmarshalInt (Doxygen::symbolStorage);
......
......@@ -89,6 +89,7 @@ class MemberDef : public Definition
const char *argsString() const;
const char *excpString() const;
const char *bitfieldString() const;
const char *extraTypeChars() const;
const QCString &initializer() const;
int initializerLines() const;
int getMemberSpecifiers() const;
......
......@@ -148,7 +148,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir,
QDir::setCurrent(outDir);
//printf("Going to dir %s\n",QDir::currentDirPath().data());
QCString mscExe = "mscgen";
QCString mscExe = Config_getString("MSCGEN_PATH")+"mscgen"+portable_commandExtension();
QCString mscArgs = "-T ismap -i \"";
mscArgs+=inFile + ".msc\" -o \"";
mscArgs+=outFile + "\"";
......
......@@ -79,7 +79,7 @@ void PageDef::writeDocumentation(OutputList &ol)
(si=Doxygen::sectionDict.find(pageName))!=0)
{
ol.startSection(si->label,si->title,si->type);
ol.docify(si->title);
ol.parseDoc(docFile(),docLine(),this,0,si->title,TRUE,FALSE);
stringToSearchIndex(getOutputFileBase(),
theTranslator->trPage(TRUE,TRUE)+" "+si->title,
si->title);
......
......@@ -21,9 +21,11 @@
#include "qtbc.h"
#include <stdio.h>
//#include <qfile.h>
#include "define.h"
class BufStr;
DefineDict* getFileDefineDict();
void initPreprocessor();
void cleanUpPreprocessor();
void addSearchDir(const char *dir);
......
......@@ -104,6 +104,9 @@ static QStack<bool> g_condStack;
static bool g_lexInit = FALSE;
DefineDict* getFileDefineDict() {
return g_fileDefineDict;
}
static void setFileName(const char *name)
{
......
......@@ -666,6 +666,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
%x MemberSpecSkip
%x EndTemplate
%x FuncPtr
%x FuncPtrOperator
%x EndFuncPtr
%x ReadFuncArgType
%x ReadTempArgs
......@@ -686,6 +687,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
%x FuncFunc
%x FuncFuncEnd
%x FuncFuncType
%x FuncFuncArray
%x CopyArgString
%x CopyArgPHPString
%x CopyArgRound
......@@ -1866,6 +1868,8 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
}
}
}
<FindMembers>[0-9]{ID} { // some number where we did not expect one
}
<FindMembers>"." {
if (insideJava || insideCS || insideD)
{
......@@ -2691,14 +2695,18 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
}
<IDLProp>. {
}
<Array>"]" { current->args += *yytext ;
<Array>"]" { current->args += *yytext ;
if (--squareCount<=0)
BEGIN( FindMembers ) ;
}
<Array>"[" { current->args += *yytext ;
<FuncFuncArray>"]" { current->args += *yytext ;
if (--squareCount<=0)
BEGIN( Function ) ;
}
<Array,FuncFuncArray>"[" { current->args += *yytext ;
squareCount++;
}
<Array>. { current->args += *yytext ; }
<Array,FuncFuncArray>. { current->args += *yytext ; }
<SkipSquare>"[" { squareCount++; }
<SkipSquare>"]" {
if (--squareCount<=0)
......@@ -3155,7 +3163,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
<ReadBody,ReadNSBody,ReadBodyIntf>. { current->program += yytext ; }
<FindMembers>"("/{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */
<FindMembers>("("({BN}*{TSCOPE}{BN}*"::")*({BN}*"*"{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) */
<FindMembers>("("({BN}*{TSCOPE}{BN}*"::")*({BN}*[*&]{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) or int (*func(int))[] */
current->bodyLine = yyLineNr;
lineCount();
addType(current);
......@@ -3166,18 +3174,41 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
}
<FuncPtr>{SCOPENAME} {
current->name = yytext;
if (current->name=="const" || current->name=="volatile")
if (nameIsOperator(current->name))
{
funcPtrType += current->name;
BEGIN( FuncPtrOperator );
}
else
{
BEGIN( EndFuncPtr );
if (current->name=="const" || current->name=="volatile")
{
funcPtrType += current->name;
}
else
{
BEGIN( EndFuncPtr );
}
}
}
<FuncPtr>. {
//printf("Error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName);
}
<FuncPtrOperator>"("{BN}*")"{BN}*/"(" {
current->name += yytext;
current->name = current->name.simplifyWhiteSpace();
lineCount();
}
<FuncPtrOperator>\n {
yyLineNr++;
current->name += *yytext;
}
<FuncPtrOperator>"(" {
unput(*yytext);
BEGIN( EndFuncPtr );
}
<FuncPtrOperator>. {
current->name += *yytext;
}
<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces
lineCount();
current->type+=funcPtrType.data()+1;
......@@ -3194,10 +3225,16 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->args += ")";
BEGIN(FindMembers);
}
<EndFuncPtr>"(" { // a function returning a function
<EndFuncPtr>"(" { // a function returning a function or
// a function returning a pointer to an array
current->args += *yytext ;
roundCount=0;
BEGIN( FuncFunc );
//roundCount=0;
//BEGIN( FuncFunc );
current->bodyLine = yyLineNr;
currentArgumentContext = FuncFuncEnd;
fullArgString=current->args.copy();
copyArgString=&current->args;
BEGIN( ReadFuncArgType ) ;
}
<EndFuncPtr>"["[^\n\]]*"]" {
funcPtrType+=yytext;
......@@ -3228,6 +3265,12 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->type+=funcPtrType.data()+1;
BEGIN(Function);
}
<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array
lineCount();
current->type+=funcPtrType;
current->args+=")";
BEGIN(FuncFuncArray);
}
<FuncFuncEnd>. {
current->args += *yytext;
}
......@@ -3827,31 +3870,27 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
// was: current->args.simplifyWhiteSpace();
current->fileName = yyFileName;
current->startLine = yyLineNr;
static QRegExp re("([^)]*\\[*&][^)]*)"); // (...*...)
if (*yytext!=';' || (current_root->section&Entry::COMPOUND_MASK) )
{
int tempArg=current->name.find('<');
QCString tempName;
static QRegExp re("operator[^a-z_A-Z0-9]");
if (tempArg==-1) tempName=current->name; else tempName=current->name.left(tempArg);
if (/*(current->type.isEmpty() && tempName.find(re)==-1) || */
current->type.left(8)=="typedef "
)
if (current->type.isEmpty() &&
(current->type.find(re,0)!=-1 || current->type.left(8)=="typedef "))
{
//printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n",
// current->type.data(),current->name.data(),current->args.data());
//printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
current->section = Entry::VARIABLE_SEC ;
}
else
{
//printf("Scanner.l: found in class function: `%s' `%s' `%s'\n",
// current->type.data(),current->name.data(),current->args.data());
//printf("Scanner.l: found in class function: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
current->section = Entry::FUNCTION_SEC ;
current->proto = *yytext==';';
}
}
else // a global function prototype or function variable
{
static QRegExp re("([^)]*\\*[^)]*)"); // (...*...)
//printf("Scanner.l: prototype? type=`%s' name=`%s' args=`%s'\n",current->type.data(),current->name.data(),current->args.data());
if (!current->type.isEmpty() &&
(current->type.find(re,0)!=-1 || current->type.left(8)=="typedef "))
......@@ -4975,14 +5014,14 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
<Prototype>"operator"{B}*"("{B}*")" {
current->name+=yytext;
}
<Prototype>"(" {
<Prototype>"(" {
current->args+=*yytext;
currentArgumentContext = PrototypeQual;
fullArgString = current->args.copy();
copyArgString = &current->args;
BEGIN( ReadFuncArgType ) ;
}
<Prototype>"("({ID}"::")*({B}*"*")+ {
<Prototype>"("({ID}"::")*({B}*[&*])+ {
current->type+=current->name+yytext;
current->name.resize(0);
BEGIN( PrototypePtr );
......@@ -4990,10 +5029,20 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
<PrototypePtr>{SCOPENAME} {
current->name+=yytext;
}
<PrototypePtr>"(" {
current->args+=*yytext;
currentArgumentContext = PrototypeQual;
fullArgString = current->args.copy();
copyArgString = &current->args;
BEGIN( ReadFuncArgType ) ;
}
<PrototypePtr>")" {
current->type+=')';
BEGIN( Prototype );
}
<PrototypePtr>. {
current->name+=yytext;
}
<PrototypeQual>"{" {
BEGIN( PrototypeSkipLine);
}
......@@ -5010,7 +5059,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->virt = Pure;
current->argList->pureSpecifier=TRUE;
}
<PrototypeQual>"throw"{B}*"(" {
<PrototypeQual>"throw"{B}*"(" {
current->exception = "throw(";
BEGIN(PrototypeExc);
}
......@@ -5018,10 +5067,13 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->exception += ')';
BEGIN(PrototypeQual);
}
<PrototypeExc>. {
<PrototypeExc>. {
current->exception += *yytext;
}
<Prototype,PrototypeQual>. {
<PrototypeQual>. {
current->args += *yytext;
}
<Prototype>. {
current->name += *yytext;
}
<PrototypeSkipLine>. {
......
......@@ -690,17 +690,20 @@ static Definition *followPath(Definition *start,FileDef *fileScope,const QCStrin
int l;
Definition *current=start;
ps=0;
//printf("followPath: start='%s' path='%s'\n",start?start->name().data():"<none>",path.data());
// for each part of the explicit scope
while ((is=getScopeFragment(path,ps,&l))!=-1)
{
// try to resolve the part if it is a typedef
MemberDef *typeDef=0;
QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef);
//printf(" qualScopePart=%s\n",qualScopePart.data());
if (typeDef)
{
ClassDef *type = newResolveTypedef(fileScope,typeDef);
if (type)
{
//printf("Found type %s\n",type->name().data());
return type;
}
}
......@@ -714,14 +717,15 @@ static Definition *followPath(Definition *start,FileDef *fileScope,const QCStrin
//printf("==> next==0!\n");
if (current->definitionType()==Definition::TypeNamespace)
{
current = endOfPathIsUsedClass(
next = endOfPathIsUsedClass(
((NamespaceDef *)current)->getUsedClasses(),qualScopePart);
}
else if (current->definitionType()==Definition::TypeFile)
{
current = endOfPathIsUsedClass(
next = endOfPathIsUsedClass(
((FileDef *)current)->getUsedClasses(),qualScopePart);
}
current = next;
if (current==0) break;
}
else // continue to follow scope
......@@ -875,7 +879,7 @@ int isAccessibleFrom(Definition *scope,FileDef *fileScope,Definition *item)
// repeat for the parent scope
i=isAccessibleFrom(scope->getOuterScope(),fileScope,item);
//printf("> result=%d\n",i);
result= (i==-1) ? -1 : i+1;
result= (i==-1) ? -1 : i+2;
}
done:
visitedDict.remove(key);
......@@ -914,7 +918,7 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,
if (visitedDict.find(key)) return -1; // already looked at this
visitedDict.insert(key,(void *)0x8);
//printf("<isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>",
//printf(" <isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>",
// item?item->name().data():"<none>",
// explicitScopePart.data());
int result=0; // assume we found it
......@@ -922,12 +926,12 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,
if (newScope) // explicitScope is inside scope => newScope is the result
{
Definition *itemScope = item->getOuterScope();
//printf("scope traversal successful %s<->%s!\n",item->getOuterScope()->name().data(),newScope->name().data());
if (newScope && newScope->definitionType()==Definition::TypeClass)
{
//ClassDef *cd = (ClassDef *)newScope;
//printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses());
}
//printf(" scope traversal successful %s<->%s!\n",item->getOuterScope()->name().data(),newScope->name().data());
//if (newScope && newScope->definitionType()==Definition::TypeClass)
//{
// ClassDef *cd = (ClassDef *)newScope;
// printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses());
//}
if (itemScope==newScope) // exact match of scopes => distance==0
{
//printf("> found it\n");
......@@ -941,9 +945,14 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,
// inheritance is also ok. Example: looking for B::I, where
// class A { public: class I {} };
// class B : public A {}
// but looking for B::I, where
// class A { public: class I {} };
// class B { public: class I {} };
// will find A::I, so we still prefer a direct match and give this one a distance of 1
result=1;
//printf("outerScope(%s) is base class of newScope(%s)\n",
// outerScope->name().data(),newScope->name().data());
//printf("scope(%s) is base class of newScope(%s)\n",
// scope->name().data(),newScope->name().data());
}
else
{
......@@ -998,7 +1007,7 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,
item,explicitScopePart);
}
//printf("> result=%d\n",i);
result = (i==-1) ? -1 : i+1;
result = (i==-1) ? -1 : i+2;
}
}
else // failed to resolve explicitScope
......@@ -1033,11 +1042,11 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,
int i=isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope,
item,explicitScopePart);
//printf("> result=%d\n",i);
result= (i==-1) ? -1 : i+1;
result= (i==-1) ? -1 : i+2;
}
}
done:
//printf("> result=%d\n",result);
//printf(" > result=%d\n",result);
visitedDict.remove(key);
//Doxygen::lookupCache.insert(key,new int(result));
return result;
......@@ -1060,7 +1069,7 @@ static void getResolvedSymbol(Definition *scope,
QCString &bestResolvedType
)
{
//printf(" found type %x name=%s d=%p\n",
//printf(" => found type %x name=%s d=%p\n",
// d->definitionType(),d->name().data(),d);
// only look at classes and members that are enums or typedefs
......@@ -1160,6 +1169,13 @@ static void getResolvedSymbol(Definition *scope,
bestTemplSpec = "";
bestResolvedType = enumType->qualifiedName();
}
else if (md->isReference()) // external reference
{
bestMatch = 0;
bestTypedef = md;
bestTemplSpec = spec;
bestResolvedType = type;
}
else
{
//printf(" no match\n");
......@@ -1285,6 +1301,9 @@ ClassDef *getResolvedClassRec(Definition *scope,
//printf("Searching for %s result=%p\n",key.data(),pval);
if (pval)
{
//printf("LookupInfo %p %p '%s' %p\n",
// pval->classDef, pval->typeDef, pval->templSpec.data(),
// pval->resolvedType.data());
if (pTemplSpec) *pTemplSpec=pval->templSpec;
if (pTypeDef) *pTypeDef=pval->typeDef;
if (pResolvedType) *pResolvedType=pval->resolvedType;
......@@ -1662,10 +1681,12 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope,
MemberDef *md=0;
NamespaceDef *nd=0;
GroupDef *gd=0;
//printf("** Match word '%s'\n",matchWord.data());
MemberDef *typeDef=0;
if ((cd=getResolvedClass(scope,fileScope,matchWord,&typeDef)))
{
//printf("Found class %s\n",cd->name().data());
// add link to the result
if (external ? cd->isLinkable() : cd->isLinkableInProject())
{
......@@ -1675,6 +1696,7 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope,
}
else if (typeDef)
{
//printf("Found typedef %s\n",typeDef->name().data());
if (external ? typeDef->isLinkable() : typeDef->isLinkableInProject())
{
out.writeLink(typeDef->getReference(),
......@@ -1693,6 +1715,10 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope,
found=TRUE;
}
}
else
{
//printf(" -> nothing\n");
}
QCString scopeName;
if (scope &&
......@@ -1714,14 +1740,11 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope,
)
{
//printf("Found ref scope=%s\n",d?d->name().data():"<global>");
if ((external ? md->isLinkable() : md->isLinkableInProject()))
{
//ol.writeObjectLink(d->getReference(),d->getOutputFileBase(),
// md->anchor(),word);
out.writeLink(md->getReference(),md->getOutputFileBase(),
md->anchor(),word);
found=TRUE;
}
//ol.writeObjectLink(d->getReference(),d->getOutputFileBase(),
// md->anchor(),word);
out.writeLink(md->getReference(),md->getOutputFileBase(),
md->anchor(),word);
found=TRUE;
}
}
......@@ -4854,7 +4877,7 @@ QCString convertToXML(const char *s)
}
/*! Converts a string to a HTML-encoded string */
QCString convertToHtml(const char *s)
QCString convertToHtml(const char *s,bool keepEntities)
{
QCString result;
if (s==0) return result;
......@@ -4866,7 +4889,30 @@ QCString convertToHtml(const char *s)
{
case '<': result+="&lt;"; break;
case '>': result+="&gt;"; break;
case '&': result+="&amp;"; break;
case '&': if (keepEntities)
{
const char *e=p;
char ce;
while ((ce=*e++))
{
if (ce==';' || (!(isId(ce) || ce=='#'))) break;
}
if (ce==';') // found end of an entity
{
// copy entry verbatim
result+=c;
while (p<e) result+=*p++;
}
else
{
result+="&amp;";
}
}
else
{
result+="&amp;";
}
break;
case '\'': result+="&#39;"; break;
case '"': result+="&quot;"; break;
default: result+=c; break;
......@@ -6193,27 +6239,28 @@ QCString expandAliasRec(const QCString s)
static QCString replaceAliasArgument(const QCString &aliasValue,int paramNum,
const QCString &paramValue)
{
QCString result = aliasValue;
QCString result;
QCString paramMarker;
paramMarker.sprintf("\\%d",paramNum);
int markerLen = paramMarker.length();
int p=0,i;
while ((i=aliasValue.find(paramMarker,p))!=-1) // search for marker
{
result+=aliasValue.mid(p,i-p);
//printf("Found marker '%s' at %d len=%d for param '%s' in '%s'\n",
// paramMarker.data(),i,markerLen,paramValue.data(),aliasValue.data());
if (i==0 || aliasValue.at(i-1)!='\\') // found unescaped marker
{
QCString before = result.left(i);
QCString after = result.mid(i+markerLen);
result = before + paramValue + after;
p=i+paramValue.length();
result += paramValue;
p=i+markerLen;
}
else // ignore escaped markers
{
result += aliasValue.mid(i,markerLen);
p=i+1;
}
}
result+=aliasValue.right(aliasValue.length()-p);
result = expandAliasRec(substitute(result,"\\,",","));
//printf("replaceAliasArgument('%s',%d,'%s')->%s\n",
// aliasValue.data(),paramNum,paramValue.data(),result.data());
......
......@@ -234,7 +234,7 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te
QCString stripScope(const char *name);
QCString convertToHtml(const char *s);
QCString convertToHtml(const char *s,bool keepEntities=TRUE);
QCString convertToXML(const char *s);
......
......@@ -1170,6 +1170,8 @@ static void generateXMLForClass(ClassDef *cd,QTextStream &ti)
if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
if (cd->templateMaster()!=0) return; // skip generated template instances.
msg("Generating XML output for class %s\n",cd->name().data());
ti << " <compound refid=\"" << cd->getOutputFileBase()
<< "\" kind=\"" << cd->compoundTypeString()
<< "\"><name>" << convertToXML(cd->name()) << "</name>" << endl;
......@@ -1886,7 +1888,6 @@ void generateXML()
ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
msg("Generating XML output for class %s\n",cd->name().data());
generateXMLForClass(cd,t);
}
}
......
......@@ -1504,6 +1504,30 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\fortrancode.cpp"
>
</File>
<File
RelativePath="..\src\fortrancode.l"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="Lex"
CommandLine="flex -PfcodeYY [AllOptions] [AdditionalOptions] [inputs]"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="Lex"
CommandLine="flex -PfcodeYY [AllOptions] [AdditionalOptions] [inputs]"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\pyscanner.cpp"
>
......@@ -1528,6 +1552,30 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\fortranscanner.cpp"
>
</File>
<File
RelativePath="..\src\fortranscanner.l"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="Lex"
CommandLine="flex -PfscanYY [AllOptions] [AdditionalOptions] [inputs]"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="Lex"
CommandLine="flex -PfscanYY [AllOptions] [AdditionalOptions] [inputs]"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\reflist.cpp"
>
......@@ -2095,10 +2143,18 @@
RelativePath="..\src\pycode.h"
>
</File>
<File
RelativePath="..\src\fortrancode.h"
>
</File>
<File
RelativePath="..\src\pyscanner.h"
>
</File>
<File
RelativePath="..\src\fortranscanner.h"
>
</File>
<File
RelativePath="..\src\qtbc.h"
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment