/******************************************************************************
*
* Copyright (C) 1997-2015 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.
*
*/
/******************************************************************************
* Parser for VHDL subset
* written by M. Kreis
* supports VHDL-87/93/2008
* does not support VHDL-AMS
******************************************************************************/
// global includes
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <qcstring.h>
#include <qfileinfo.h>
#include <qstringlist.h>
#include <qmap.h>
/* --------------------------------------------------------------- */
// local includes
#include "vhdldocgen.h"
#include "message.h"
#include "config.h"
#include "doxygen.h"
#include "util.h"
#include "language.h"
#include "commentscan.h"
#include "index.h"
#include "definition.h"
#include "searchindex.h"
#include "outputlist.h"
#include "parserintf.h"
#include "layout.h"
#include "arguments.h"
#include "portable.h"
#include "memberlist.h"
#include "memberdef.h"
#include "groupdef.h"
#include "classlist.h"
#include "namespacedef.h"
#include "filename.h"
#include "membergroup.h"
#include "memberdef.h"
#include "plantuml.h"
#include "vhdljjparser.h"
#include "VhdlParser.h"
#include "vhdlcode.h"
#include "plantuml.h"
//#define DEBUGFLOW
#define theTranslator_vhdlType VhdlDocGen::trVhdlType
static QDict<QCString> g_vhdlKeyDict0(17,FALSE);
static QDict<QCString> g_vhdlKeyDict1(17,FALSE);
static QDict<QCString> g_vhdlKeyDict2(17,FALSE);
static QDict<QCString> g_vhdlKeyDict3(17,FALSE);
static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCString & fileName,QCString & brief);
static void writeUCFLink(const MemberDef* mdef,OutputList &ol);
static void assignBinding(VhdlConfNode* conf);
static void addInstance(ClassDef* entity, ClassDef* arch, ClassDef *inst,Entry *cur,ClassDef* archBind=NULL);
//---------- create svg -------------------------------------------------------------
static void createSVG();
static void startDot(FTextStream &t);
static void startTable(FTextStream &t,const QCString &className);
static QList<MemberDef>* getPorts(ClassDef *cd);
static void writeVhdlEntityToolTip(FTextStream& t,ClassDef *cd);
static void endDot(FTextStream &t);
static void writeTable(QList<MemberDef>* port,FTextStream & t);
static void endTabel(FTextStream &t);
static void writeClassToDot(FTextStream &t,ClassDef* cd);
static void writeVhdlDotLink(FTextStream &t,const QCString &a,const QCString &b,const QCString &style);
//static void writeVhdlPortToolTip(FTextStream& t,QList<MemberDef>* port,ClassDef *cd);
static const MemberDef *flowMember=0;
void VhdlDocGen::setFlowMember( const MemberDef* mem)
{
flowMember=mem;
}
const MemberDef* VhdlDocGen::getFlowMember()
{
return flowMember;
}
//--------------------------------------------------------------------------------------------------
static void codify(FTextStream &t,const char *str)
{
if (str)
{
const char *p=str;
char c;
while (*p)
{
c=*p++;
switch(c)
{
case '<': t << "<";
break;
case '>': t << ">";
break;
case '&': t << "&";
break;
case '\'': t << "'";
break;
case '"': t << """;
break;
default: t << c;
break;
}
}
}
}
static void writeLink(const MemberDef* mdef,OutputList &ol)
{
ol.writeObjectLink(mdef->getReference(),
mdef->getOutputFileBase(),
mdef->anchor(),
mdef->name());
}
static void startFonts(const QCString& q, const char *keyword,OutputList& ol)
{
ol.startFontClass(keyword);
ol.docify(q.data());
ol.endFontClass();
}
static QCString splitString(QCString& str,char c)
{
QCString n=str;
int i=str.find(c);
if (i>0)
{
n=str.left(i);
str=str.remove(0,i+1);
}
return n;
}
static int compareString(const QCString& s1,const QCString& s2)
{
return qstricmp(s1.stripWhiteSpace(),s2.stripWhiteSpace());
}
static void createSVG()
{
QCString ov =Config_getString(HTML_OUTPUT);
QCString dir="-o \""+ov+"/vhdl_design_overview.html\"";
ov+="/vhdl_design.dot";
QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
if (portable_system("dot",vlargs)!=0)
{
err("could not create dot file");
}
}
// Creates an svg image. All in/out/inout ports are shown with brief description and direction.
// Brief descriptions for entities are shown too.
void VhdlDocGen::writeOverview()
{
ClassSDict::Iterator cli(*Doxygen::classSDict);
ClassDef *cd;
bool found=FALSE;
for ( ; (cd=cli.current()) ; ++cli )
{
if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS )
{
found=TRUE;
break;
}
}
if (!found) return;
QCString ov =Config_getString(HTML_OUTPUT);
QCString fileName=ov+"/vhdl_design.dot";
QFile f(fileName);
FTextStream t(&f);
if (!f.open(IO_WriteOnly))
{
fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
return;
}
startDot(t);
for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
{
if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS )
{
continue;
}
QList<MemberDef>* port= getPorts(cd);
if (port==0)
{
continue;
}
if (port->count()==0)
{
delete port;
port=NULL;
continue;
}
startTable(t,cd->name());
writeClassToDot(t,cd);
writeTable(port,t);
endTabel(t);
// writeVhdlPortToolTip(t,port,cd);
writeVhdlEntityToolTip(t,cd);
delete port;
BaseClassList *bl=cd->baseClasses();
if (bl)
{
BaseClassListIterator bcli(*bl);
BaseClassDef *bcd;
for ( ; (bcd=bcli.current()) ; ++bcli )
{
ClassDef *bClass=bcd->classDef;
QCString dotn=cd->name()+":";
dotn+=cd->name();
QCString csc=bClass->name()+":";
csc+=bClass->name();
// fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data());
writeVhdlDotLink(t,dotn,csc,0);
}
}// if bl
}// for
endDot(t);
// writePortLinks(t);
f.close();
createSVG();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
static void startDot(FTextStream &t)
{
t << " digraph G { \n";
t << "rankdir=LR \n";
t << "concentrate=TRUE\n";
t << "stylesheet=\"doxygen.css\"\n";
}
static void endDot(FTextStream &t)
{
t <<" } \n";
}
static void startTable(FTextStream &t,const QCString &className)
{
t << className <<" [ shape=none , fontname=\"arial\", fontcolor=\"blue\" , \n";
t << "label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n";
}
static void writeVhdlDotLink(FTextStream &t,
const QCString &a,const QCString &b,const QCString &style)
{
t << a << "->" << b;
if (!style.isEmpty())
{
t << "[style=" << style << "];\n";
}
t << "\n";
}
static QCString formatBriefNote(const QCString &brief,ClassDef * cd)
{
QRegExp ep("[\n]");
QCString vForm;
QCString repl("<BR ALIGN=\"LEFT\"/>");
QCString file=cd->getDefFileName();
int k=cd->briefLine();
QStringList qsl=QStringList::split(ep,brief);
for(uint j=0;j<qsl.count();j++)
{
QCString qcs=qsl[j].data();
vForm+=parseCommentAsText(cd,NULL,qcs,file,k);
k++;
vForm+='\n';
}
vForm.replace(ep,repl.data());
return vForm;
}
#if 0
static void writeVhdlPortToolTip(FTextStream& t,QList<MemberDef>* port,ClassDef *cd)
{
/*
uint len=port->count();
MemberDef *md;
for (uint j=0;j<len;j++)
{
md=(MemberDef*)port->at(j);
QCString brief=md->briefDescriptionAsTooltip();
if (brief.isEmpty()) continue;
QCString node="node";
node+=VhdlDocGen::getRecordNumber();
t << node <<"[shape=box margin=0.1, label=<\n";
t<<"<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
t<<"<TR><TD BGCOLOR=\"lightcyan\"> ";
t<<brief;
t<<" </TD></TR></TABLE>>];";
QCString dotn=cd->name()+":";
dotn+=md->name();
// writeVhdlDotLink(t,dotn,node,"dotted");
}
*/
}
#endif
static void writeVhdlEntityToolTip(FTextStream& t,ClassDef *cd)
{
QCString brief=cd->briefDescription();
if (brief.isEmpty()) return;
brief=formatBriefNote(brief,cd);
QCString node="node";
node+=VhdlDocGen::getRecordNumber();
t << node <<"[shape=none margin=0.1, label=<\n";
t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
t << "<TR><TD BGCOLOR=\"lightcyan\"> ";
t << brief;
t << " </TD></TR></TABLE>>];";
QCString dotn=cd->name()+":";
dotn+=cd->name();
writeVhdlDotLink(t,dotn,node,"dotted");
}
static void writeColumn(FTextStream &t,MemberDef *md,bool start)
{
QCString toolTip;
static QRegExp reg("[%]");
bool bidir=(md!=0 &&( qstricmp(md->typeString(),"inout")==0));
if (md)
{
toolTip=md->briefDescriptionAsTooltip();
if (!toolTip.isEmpty())
{
QCString largs = md->argsString();
if (!largs.isEmpty())
largs=largs.replace(reg," ");
toolTip+=" [";
toolTip+=largs;
toolTip+="]";
}
}
if (start)
{
t <<"<TR>\n";
}
t << "<TD ALIGN=\"LEFT\" ";
if (md)
{
t << "href=\"";
t << md->getOutputFileBase()<< Doxygen::htmlFileExtension;
t << "#" << md->anchor();
t<<"\" ";
t<<" TOOLTIP=\"";
if (!toolTip.isEmpty())
{
codify(t,toolTip.data());
}
else
{
QCString largs = md->argsString();
if (!largs.isEmpty())
{
largs=largs.replace(reg," ");
codify(t,largs.data());
}
}
t << "\" ";
t << " PORT=\"";
t << md->name();
t << "\" ";
}
if (!toolTip.isEmpty())
{
// if (!toolTip.isEmpty())
if (bidir)
t << "BGCOLOR=\"orange\">";
else
t << "BGCOLOR=\"azure\">";
}
else if (bidir)
{
t << "BGCOLOR=\"pink\">";
}
else
{
t << "BGCOLOR=\"lightgrey\">";
}
if (md)
{
t << md->name();
}
else
{
t << " \n";
}
t << "</TD>\n";
if (!start)
{
t << "</TR>\n";
}
}
static void endTabel(FTextStream &t)
{
t << "</TABLE>>\n";
t << "] \n";
}
static void writeClassToDot(FTextStream &t,ClassDef* cd)
{
t << "<TR><TD COLSPAN=\"2\" BGCOLOR=\"yellow\" ";
t << "PORT=\"";
t << cd->name();
t << "\" ";
t << "href=\"";
t << cd->getOutputFileBase() << Doxygen::htmlFileExtension;
t << "\" ";
t << ">";
t << cd->name();
t << " </TD></TR>\n";
}
static QList<MemberDef>* getPorts(ClassDef *cd)
{
MemberDef* md;
QList<MemberDef> *portList=new QList<MemberDef>;
MemberList *ml=cd->getMemberList(MemberListType_variableMembers);
if (ml==0)
{
delete portList;
return 0;
}
MemberListIterator fmni(*ml);
for (fmni.toFirst();(md=fmni.current());++fmni)
{
if (md->getMemberSpecifiers()==VhdlDocGen::PORT)
{
portList->append(md);
}
}
return portList;
}
//writeColumn(FTextStream &t,QCString name,bool start)
static void writeTable(QList<MemberDef>* port,FTextStream & t)
{
MemberDef *md;
uint len=port->count();
QList<MemberDef> inPorts;
QList<MemberDef> outPorts;
uint j;
for (j=0;j<len;j++)
{
md=(MemberDef*)port->at(j);
QCString qc=md->typeString();
if(qc=="in")
{
inPorts.append(md);
}
else
{
outPorts.append(md);
}
}
int inp = inPorts.count();
int outp = outPorts.count();
int maxLen;
if (inp>=outp)
{
maxLen=inp;
}
else
{
maxLen=outp;
}
int i;
for(i=0;i<maxLen;i++)
{
//write inports
if (i<inp)
{
md=(MemberDef*)inPorts.at(i);
writeColumn(t,md,TRUE);
}
else
{
writeColumn(t,NULL,TRUE);
}
if (i<outp)
{
md=(MemberDef*)outPorts.at(i);
writeColumn(t,md,FALSE);
}
else
{
writeColumn(t,NULL,FALSE);
}
}
}
//--------------------------------------------------------------------------------------------------
VhdlDocGen::VhdlDocGen()
{
}
VhdlDocGen::~VhdlDocGen()
{
}
void VhdlDocGen::init()
{
// vhdl keywords included VHDL 2008
const char* g_vhdlKeyWordMap0[] =
{
"abs","access","after","alias","all","and","architecture","array","assert","assume","assume_guarantee","attribute",
"begin","block","body","buffer","bus",
"case","component","configuration","constant","context","cover",
"default","disconnect","downto",
"else","elsif","end","entity","exit",
"fairness","file","for","force","function",
"generate","generic","group","guarded",
"if","impure","in","inertial","inout","is",
"label","library","linkage","literal","loop",
"map","mod",
"nand","new","next","nor","not","null",
"of","on","open","or","others","out",
"package","parameter","port","postponed","procedure","process","property","protected","pure",
"range","record","register","reject","release","restrict","restrict_guarantee","rem","report","rol","ror","return",
"select","sequence","severity","signal","shared","sla","sll","sra","srl","strong","subtype",
"then","to","transport","type",
"unaffected","units","until","use",
"variable","vmode","vprop","vunit",
"wait","when","while","with",
"xor","xnor",
0
};
// type
const char* g_vhdlKeyWordMap1[] =
{
"natural","unsigned","signed","string","boolean", "bit","bit_vector","character",
"std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer",
"real","float","ufixed","sfixed","time",0
};
// logic
const char* g_vhdlKeyWordMap2[] =
{
"abs","and","or","not","mod", "xor","rem","xnor","ror","rol","sla",
"sll",0
};
// predefined attributes
const char* g_vhdlKeyWordMap3[] =
{
"base","left","right","high","low","ascending",
"image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low",
"range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event",
"active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name",0
};
int j=0;
g_vhdlKeyDict0.setAutoDelete(TRUE);
g_vhdlKeyDict1.setAutoDelete(TRUE);
g_vhdlKeyDict2.setAutoDelete(TRUE);
g_vhdlKeyDict3.setAutoDelete(TRUE);
while (g_vhdlKeyWordMap0[j])
{
g_vhdlKeyDict0.insert(g_vhdlKeyWordMap0[j],
new QCString(g_vhdlKeyWordMap0[j]));
j++;
}
j=0;
while (g_vhdlKeyWordMap1[j])
{
g_vhdlKeyDict1.insert(g_vhdlKeyWordMap1[j],
new QCString(g_vhdlKeyWordMap1[j]));
j++;
}
j=0;
while (g_vhdlKeyWordMap2[j])
{
g_vhdlKeyDict2.insert(g_vhdlKeyWordMap2[j],
new QCString(g_vhdlKeyWordMap2[j]));
j++;
}
j=0;
while (g_vhdlKeyWordMap3[j])
{
g_vhdlKeyDict3.insert(g_vhdlKeyWordMap3[j],
new QCString(g_vhdlKeyWordMap3[j]));
j++;
}
}// buildKeyMap
/*!
* returns the color of a keyword
*/
QCString* VhdlDocGen::findKeyWord(const QCString& tmp)
{
static QCString vhdlkeyword("vhdlkeyword");
static QCString vhdltype("comment");
static QCString vhdllogic("vhdllogic");
static QCString preprocessor("keywordflow");
QCString word=tmp.lower();
if (word.isEmpty() || word.at(0)=='\0') return 0;
if (g_vhdlKeyDict0.find(word))
return &preprocessor;
if (g_vhdlKeyDict1.find(word))
return &vhdltype;
if (g_vhdlKeyDict2.find(word))
return &vhdllogic;
if (g_vhdlKeyDict3.find(word))
return &vhdlkeyword;
return 0;
}
ClassDef *VhdlDocGen::getClass(const char *name)
{
if (name==0 || name[0]=='\0') return 0;
ClassDef *cd=0;
QCString temp(name);
//temp=temp.lower();
temp=temp.stripWhiteSpace();
cd= Doxygen::classSDict->find(temp.data());
return cd;
}
ClassDef* VhdlDocGen::getPackageName(const QCString & name)
{
ClassDef* cd=0;
cd=getClass(name);
return cd;
}
static QMap<QCString,MemberDef*> varMap;
static QList<ClassDef> qli;
static QMap<ClassDef*,QList<ClassDef> > packages;
MemberDef* VhdlDocGen::findMember(const QCString& className, const QCString& memName)
{
ClassDef* cd,*ecd;
MemberDef *mdef=0;
cd=getClass(className);
//printf("VhdlDocGen::findMember(%s,%s)=%p\n",className.data(),memName.data(),cd);
if (cd==0) return 0;
mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_variableMembers);
if (mdef) return mdef;
mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_pubMethods);
if (mdef) return mdef;
// nothing found so far
// if we are an architecture or package body search in entity
if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS ||
(VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
{
Definition *d = cd->getOuterScope();
// searching upper/lower case names
QCString tt=d->name();
ecd =getClass(tt);
if (!ecd)
{
tt=tt.upper();
ecd =getClass(tt);
}
if (!ecd)
{
tt=tt.lower();
ecd =getClass(tt);
}
if (ecd) //d && d->definitionType()==Definition::TypeClass)
{
//ClassDef *ecd = (ClassDef*)d;
mdef=VhdlDocGen::findMemberDef(ecd,memName,MemberListType_variableMembers);
if (mdef) return mdef;
mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_pubMethods);
if (mdef) return mdef;
}
}
if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS ||
(VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
{
Definition *d = cd->getOuterScope();
QCString tt=d->name();
ClassDef *ecd =getClass(tt);
if (!ecd)
{
tt=tt.upper();
ecd =getClass(tt);
}
if (!ecd)
{
tt=tt.lower();
ecd =getClass(tt);
}
if (ecd) //d && d->definitionType()==Definition::TypeClass)
{
if(!packages.contains(ecd))
{
VhdlDocGen::findAllPackages(ecd);
}
}
}
else
{
ecd=cd;
if (!packages.contains(ecd)) VhdlDocGen::findAllPackages(ecd);
}
QMap<ClassDef*,QList<ClassDef> >::Iterator cList=packages.find(ecd);
if (cList.key()!=0)
{
QList<ClassDef> mlist=cList.data();
for (uint j=0;j<mlist.count();j++)
{
mdef=VhdlDocGen::findMemberDef(mlist.at(j),memName,MemberListType_variableMembers);
if (mdef) return mdef;
mdef=VhdlDocGen::findMemberDef(mlist.at(j),memName,MemberListType_pubMethods);
if (mdef) return mdef;
}
}
return 0;
}//findMember
/**
* This function returns the entity|package
* in which the key (type) is found
*/
MemberDef* VhdlDocGen::findMemberDef(ClassDef* cd,const QCString& key,MemberListType type)
{
MemberDef *md=0;
MemberList *ml=0;
QCString keyType=cd->symbolName()+"@"+key;
//printf("\n %s | %s | %s",cd->symbolName().data(),key.data(,),keyType.data());
QMap<QCString, MemberDef*>::Iterator it =varMap.find(keyType);
if (it.key())
{
md=it.data();
if (md)
{
return md;
}
}
if (qli.contains(cd))
{
return 0;
}
ml=cd->getMemberList(type);
qli.append(cd);
if (!ml)
{
return 0;
}
MemberListIterator fmni(*ml);
//int l=ml->count();
// fprintf(stderr,"\n loading entity %s %s: %d",cd->symbolName().data(),keyType.data(),l);
for (fmni.toFirst();(md=fmni.current());++fmni)
{
QCString tkey=cd->symbolName()+"@"+md->name();
if (varMap.contains(tkey))
{
continue;
}
varMap.insert(tkey.data(),md);
}
it=varMap.find(keyType.data());
if (it.key())
{
md=it.data();
if (md)
{
return md;
}
}
return 0;
}//findMemberDef
/*!
* finds all included packages of an Entity or Package
*/
void VhdlDocGen::findAllPackages( ClassDef *cdef)
{
QList<ClassDef> cList;
if (packages.contains(cdef)) return;
MemberList *mem=cdef->getMemberList(MemberListType_variableMembers);
MemberDef *md;
if (!mem) return;
MemberListIterator fmni(*mem);
for (fmni.toFirst();(md=fmni.current());++fmni)
{
if (VhdlDocGen::isPackage(md))
{
ClassDef* cd=VhdlDocGen::getPackageName(md->name());
if (cd)
{
cList.append(cd);
VhdlDocGen::findAllPackages(cd);
packages.insert(cdef,cList);
}
}
}//for
}// findAllPackages
/*!
* returns the function with the matching argument list
* is called in vhdlcode.l
*/
MemberDef* VhdlDocGen::findFunction(const QList<Argument> &ql,
const QCString& funcname,
const QCString& package, bool /*type*/)
{
MemberDef* mdef=0;
//int funcType;
ClassDef *cdef=getClass(package.data());
if (cdef==0) return 0;
MemberList *mem=cdef->getMemberList(MemberListType_pubMethods);
if (mem)
{
MemberListIterator fmni(*mem);
for (fmni.toFirst();(mdef=fmni.current());++fmni)
{
QCString mname=mdef->name();
if ((VhdlDocGen::isProcedure(mdef) || VhdlDocGen::isVhdlFunction(mdef)) && (compareString(funcname,mname)==0))
{
ArgumentList *alp = mdef->argumentList();
// ArgumentList* arg2=mdef->getArgumentList();
if (alp==0) break;
ArgumentListIterator ali(*alp);
ArgumentListIterator ali1(ql);
if (ali.count() != ali1.count()) break;
Argument *arg,*arg1;
int equ=0;
for (;(arg=ali.current()) && (arg1=ali1.current());++ali,++ali1)
{
equ+=abs(compareString(arg->type,arg1->type));
QCString s1=arg->type;
QCString s2=arg1->type;
VhdlDocGen::deleteAllChars(s1,' ');
VhdlDocGen::deleteAllChars(s2,' ');
equ+=abs(compareString(s1,s2));
s1=arg->attrib;
s2=arg1->attrib;
VhdlDocGen::deleteAllChars(s1,' ');
VhdlDocGen::deleteAllChars(s2,' ');
equ+=abs(compareString(s1,s2));
// printf("\n 1. type [%s] name [%s] attrib [%s]",arg->type,arg->name,arg->attrib);
// printf("\n 2. type [%s] name [%s] attrib [%s]",arg1->type,arg1->name,arg1->attrib);
} // for
if (equ==0) return mdef;
}//if
}//for
}//if
return mdef;
} //findFunction
/*!
* returns the class title+ref
*/
QCString VhdlDocGen::getClassTitle(const ClassDef *cd)
{
QCString pageTitle;
if (cd==0) return "";
pageTitle=VhdlDocGen::getClassName(cd);
int ii=cd->protection();
pageTitle+=" ";
pageTitle+=theTranslator_vhdlType(ii+2,TRUE);
pageTitle+=" ";
return pageTitle;
} // getClassTitle
/* returns the class name without their prefixes */
QCString VhdlDocGen::getClassName(const ClassDef* cd)
{
QCString temp;
if (cd==0) return "";
if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
{
temp=cd->name();
temp.stripPrefix("_");
return temp;
}
return substitute(cd->className(),"::",".");
}
/*!
* writes an inline link form entity|package to architecture|package body and vice verca
*/
void VhdlDocGen::writeInlineClassLink(const ClassDef* cd ,OutputList& ol)
{
QList<QCString> ql;
ql.setAutoDelete(TRUE);
QCString nn=cd->className();
int ii=(int)cd->protection()+2;
QCString type;
if (ii==VhdlDocGen::ENTITY)
type+=theTranslator_vhdlType(VhdlDocGen::ARCHITECTURE,TRUE);
else if (ii==VhdlDocGen::ARCHITECTURE)
type+=theTranslator_vhdlType(VhdlDocGen::ENTITY,TRUE);
else if (ii==VhdlDocGen::PACKAGE_BODY)
type+=theTranslator_vhdlType(VhdlDocGen::PACKAGE,TRUE);
else if (ii==VhdlDocGen::PACKAGE)
type+=theTranslator_vhdlType(VhdlDocGen::PACKAGE_BODY,TRUE);
else
type+="";
//type=type.lower();
type+=" >> ";
ol.disable(OutputGenerator::RTF);
ol.disable(OutputGenerator::Man);
if (ii==VhdlDocGen::PACKAGE_BODY)
{
nn.stripPrefix("_");
cd=getClass(nn.data());
}
else if (ii==VhdlDocGen::PACKAGE)
{
nn.prepend("_");
cd=getClass(nn.data());
}
else if (ii==VhdlDocGen::ARCHITECTURE)
{
QStringList qlist=QStringList::split("-",nn,FALSE);
nn=qlist[1].utf8();
cd=VhdlDocGen::getClass(nn.data());
}
QCString opp;
if (ii==VhdlDocGen::ENTITY)
{
VhdlDocGen::findAllArchitectures(ql,cd);
int j=ql.count();
for (int i=0;i<j;i++)
{
QCString *temp=ql.at(i);
QStringList qlist=QStringList::split("-",*temp,FALSE);
QCString s1=qlist[0].utf8();
QCString s2=qlist[1].utf8();
s1.stripPrefix("_");
if (j==1) s1.resize(0);
ClassDef*cc = getClass(temp->data());
if (cc)
{
VhdlDocGen::writeVhdlLink(cc,ol,type,s2,s1);
}
}
}
else
{
VhdlDocGen::writeVhdlLink(cd,ol,type,nn,opp);
}
ol.enable(OutputGenerator::Man);
ol.enable(OutputGenerator::RTF);
}// write
/*
* finds all architectures which belongs to an entity
*/
void VhdlDocGen::findAllArchitectures(QList<QCString>& qll,const ClassDef *cd)
{
ClassDef *citer;
ClassSDict::Iterator cli(*Doxygen::classSDict);
for ( ; (citer=cli.current()) ; ++cli )
{
QCString jj=citer->className();
if (cd != citer && jj.contains('-')!=-1)
{
QStringList ql=QStringList::split("-",jj,FALSE);
QCString temp=ql[1].utf8();
if (qstricmp(cd->className(),temp)==0)
{
QCString *cl=new QCString(jj);
qll.insert(0,cl);
}
}
}// for
}//findAllArchitectures
ClassDef* VhdlDocGen::findArchitecture(const ClassDef *cd)
{
ClassDef *citer;
QCString nn=cd->name();
ClassSDict::Iterator cli(*Doxygen::classSDict);
for ( ; (citer=cli.current()) ; ++cli )
{
QCString jj=citer->name();
QStringList ql=QStringList::split(":",jj,FALSE);
if (ql.count()>1)
{
if (ql[0].utf8()==nn )
{
return citer;
}
}
}
return 0;
}
/*
* writes the link entity >> .... or architecture >> ...
*/
void VhdlDocGen::writeVhdlLink(const ClassDef* ccd ,OutputList& ol,QCString& type,QCString& nn,QCString& behav)
{
if (ccd==0) return;
ol.startBold();
ol.docify(type.data());
ol.endBold();
nn.stripPrefix("_");
ol.writeObjectLink(ccd->getReference(),ccd->getOutputFileBase(),0,nn.data());
if (!behav.isEmpty())
{
behav.prepend(" ");
ol.startBold();
ol.docify(behav.data());
ol.endBold();
}
ol.lineBreak();
}
/*!
* strips the "--" prefixes of vhdl comments
*/
void VhdlDocGen::prepareComment(QCString& qcs)
{
const char* s="--!";
int index=0;
while (TRUE)
{
index=qcs.find(s,0,TRUE);
if (index<0) break;
qcs=qcs.remove(index,qstrlen(s));
}
qcs=qcs.stripWhiteSpace();
}
/*!
* parses a function proto
* @param text function string
* @param qlist stores the function types
* @param name points to the function name
* @param ret Stores the return type
* @param doc ???
*/
void VhdlDocGen::parseFuncProto(const char* text,QList<Argument>& qlist,
QCString& name,QCString& ret,bool doc)
{
(void)qlist; //unused
int index,end;
QCString s1(text);
QCString temp;
index=s1.find("(");
end=s1.findRev(")");
if ((end-index)>0)
{
temp=s1.mid(index+1,(end-index-1));
//getFuncParams(qlist,temp);
}
if (doc)
{
name=s1.left(index);
name=name.stripWhiteSpace();
if ((end-index)>0)
{
ret="function";
}
return;
}
else
{
QCString s1(text);
s1=s1.stripWhiteSpace();
int i=s1.find("(",0,FALSE);
int s=s1.find(QRegExp("[ \\t]"));
if (i==-1 || i<s)
s1=VhdlDocGen::getIndexWord(s1.data(),1);
else // s<i, s=start of name, i=end of name
s1=s1.mid(s,(i-s));
name=s1.stripWhiteSpace();
}
index=s1.findRev("return",-1,FALSE);
if (index !=-1)
{
ret=s1.mid(index+6,s1.length());
ret=ret.stripWhiteSpace();
VhdlDocGen::deleteCharRev(ret,';');
}
}
/*
* returns the n'th word of a string
*/
QCString VhdlDocGen::getIndexWord(const char* c,int index)
{
QStringList ql;
QCString temp(c);
QRegExp reg("[\\s:|]");
ql=QStringList::split(reg,temp,FALSE);
if (ql.count() > (unsigned int)index)
{
return ql[index].utf8();
}
return "";
}
QCString VhdlDocGen::getProtectionName(int prot)
{
if (prot==VhdlDocGen::ENTITYCLASS)
return "entity";
else if (prot==VhdlDocGen::ARCHITECTURECLASS)
return "architecture";
else if (prot==VhdlDocGen::PACKAGECLASS)
return "package";
else if (prot==VhdlDocGen::PACKBODYCLASS)
return "package body";
return "";
}
QCString VhdlDocGen::trTypeString(uint64 type)
{
switch(type)
{
case VhdlDocGen::LIBRARY: return "Library";
case VhdlDocGen::ENTITY: return "Entity";
case VhdlDocGen::PACKAGE_BODY: return "Package Body";
case VhdlDocGen::ATTRIBUTE: return "Attribute";
case VhdlDocGen::PACKAGE: return "Package";
case VhdlDocGen::SIGNAL: return "Signal";
case VhdlDocGen::COMPONENT: return "Component";
case VhdlDocGen::CONSTANT: return "Constant";
case VhdlDocGen::TYPE: return "Type";
case VhdlDocGen::SUBTYPE: return "Subtype";
case VhdlDocGen::FUNCTION: return "Function";
case VhdlDocGen::RECORD: return "Record";
case VhdlDocGen::PROCEDURE: return "Procedure";
case VhdlDocGen::ARCHITECTURE: return "Architecture";
case VhdlDocGen::USE: return "Package";
case VhdlDocGen::PROCESS: return "Process";
case VhdlDocGen::PORT: return "Port";
case VhdlDocGen::GENERIC: return "Generic";
case VhdlDocGen::UNITS: return "Units";
//case VhdlDocGen::PORTMAP: return "Port Map";
case VhdlDocGen::SHAREDVARIABLE: return "Shared Variable";
case VhdlDocGen::GROUP: return "Group";
case VhdlDocGen::VFILE: return "File";
case VhdlDocGen::INSTANTIATION: return "Instantiation";
case VhdlDocGen::ALIAS: return "Alias";
case VhdlDocGen::CONFIG: return "Configuration";
case VhdlDocGen::MISCELLANEOUS: return "Miscellaneous";
case VhdlDocGen::UCF_CONST: return "Constraints";
default: return "";
}
} // convertType
/*!
* deletes a char backwards in a string
*/
bool VhdlDocGen::deleteCharRev(QCString &s,char c)
{
int index=s.findRev(c,-1,FALSE);
if (index > -1)
{
QCString qcs=s.remove(index,1);
s=qcs;
return TRUE;
}
return FALSE;
}
void VhdlDocGen::deleteAllChars(QCString &s,char c)
{
int index=s.findRev(c,-1,FALSE);
while (index > -1)
{
QCString qcs=s.remove(index,1);
s=qcs;
index=s.findRev(c,-1,FALSE);
}
}
static int recordCounter=0;
/*!
* returns the next number of a record|unit member
*/
QCString VhdlDocGen::getRecordNumber()
{
char buf[12];
sprintf(buf,"%d",recordCounter++);
QCString qcs(&buf[0]);
return qcs;
}
/*!
* returns the next number of an anonymous process
*/
QCString VhdlDocGen::getProcessNumber()
{
static int stringCounter;
char buf[8];
QCString qcs("PROCESS_");
sprintf(buf,"%d",stringCounter++);
qcs.append(&buf[0]);
return qcs;
}
/*!
* writes a colored and formatted string
*/
void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberDef* mdef)
{
QRegExp reg("[\\[\\]\\.\\/\\:\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]");
QCString qcs = s;
qcs+=QCString(" ");// parsing the last sign
QCString *ss;
QCString find=qcs;
QCString temp=qcs;
char buf[2];
buf[1]='\0';
int j;
int len;
j = reg.match(temp.data(),0,&len);
ol.startBold();
if (j>=0)
{
while (j>=0)
{
find=find.left(j);
buf[0]=temp[j];
ss=VhdlDocGen::findKeyWord(find);
bool k=isNumber(find); // is this a number
if (k)
{
ol.docify(" ");
startFonts(find,"vhdldigit",ol);
ol.docify(" ");
}
else if (j != 0 && ss)
{
startFonts(find,ss->data(),ol);
}
else
{
if (j>0)
{
VhdlDocGen::writeStringLink(mdef,find,ol);
}
}
startFonts(&buf[0],"vhdlchar",ol);
QCString st=temp.remove(0,j+1);
find=st;
if (!find.isEmpty() && find.at(0)=='"')
{
int ii=find.find('"',2);
if (ii>1)
{
QCString com=find.left(ii+1);
startFonts(com,"keyword",ol);
temp=find.remove(0,ii+1);
}
}
else
{
temp=st;
}
j = reg.match(temp.data(),0,&len);
}//while
}//if
else
{
startFonts(find,"vhdlchar",ol);
}
ol.endBold();
}// writeFormatString
/*!
* returns TRUE if this string is a number
*/
bool VhdlDocGen::isNumber(const QCString& s)
{
static QRegExp regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*");
if (s.isEmpty()) return FALSE;
int j,len;
j = regg.match(s.data(),0,&len);
if ((j==0) && (len==(int)s.length())) return TRUE;
return FALSE;
}// isNumber
/*!
* inserts white spaces for better readings
* and writes a colored string to the output
*/
void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* mdef)
{
QCString qcs = s;
QCString temp;
qcs.stripPrefix(":");
qcs.stripPrefix("is");
qcs.stripPrefix("IS");
qcs.stripPrefix("of");
qcs.stripPrefix("OF");
// VhdlDocGen::deleteCharRev(qcs,';');
//char white='\t';
int len = qcs.length();
unsigned int index=1;//temp.length();
for (int j=0;j<len;j++)
{
char c=qcs[j];
char b=c;
if (j>0) b=qcs[j-1];
if (c=='"' || c==',' || c=='\''|| c=='(' || c==')' || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>'))
{
if (temp.length()>=index && temp.at(index-1) != ' ')
{
temp+=" ";
}
temp+=c;
temp+=" ";
}
else if (c=='=')
{
if (b==':') // := operator
{
temp.replace(index-1,1,"=");
temp+=" ";
}
else // = operator
{
temp+=" ";
temp+=c;
temp+=" ";
}
}
else
{
temp+=c;
}
index=temp.length();
}// for
temp=temp.stripWhiteSpace();
// printf("\n [%s]",qcs.data());
VhdlDocGen::writeFormatString(temp,ol,mdef);
}
/*!
* writes a procedure prototype to the output
*/
void VhdlDocGen::writeProcedureProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
{
ArgumentListIterator ali(*al);
Argument *arg;
bool sem=FALSE;
int len=al->count();
ol.docify("( ");
if (len > 2)
{
ol.lineBreak();
}
for (;(arg=ali.current());++ali)
{
ol.startBold();
if (sem && len <3)
ol.writeChar(',');
QCString nn=arg->name;
nn+=": ";
QCString *str=VhdlDocGen::findKeyWord(arg->defval);
arg->defval+=" ";
if (str)
{
startFonts(arg->defval,str->data(),ol);
}
else
{
startFonts(arg->defval,"vhdlchar",ol); // write type (variable,constant etc.)
}
startFonts(nn,"vhdlchar",ol); // write name
if (qstricmp(arg->attrib,arg->type) != 0)
{
startFonts(arg->attrib.lower(),"stringliteral",ol); // write in|out
}
ol.docify(" ");
VhdlDocGen::formatString(arg->type,ol,mdef);
sem=TRUE;
ol.endBold();
if (len > 2)
{
ol.lineBreak();
ol.docify(" ");
}
}//for
ol.docify(" )");
}
/*!
* writes a function prototype to the output
*/
void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
{
if (al==0) return;
ArgumentListIterator ali(*al);
Argument *arg;
bool sem=FALSE;
int len=al->count();
ol.startBold();
ol.docify(" ( ");
ol.endBold();
if (len>2)
{
ol.lineBreak();
}
for (;(arg=ali.current());++ali)
{
ol.startBold();
QCString att=arg->defval;
bool bGen=att.stripPrefix("gen!");
if (sem && len < 3)
{
ol.docify(" , ");
}
if (bGen)
{
VhdlDocGen::formatString(QCString("generic "),ol,mdef);
}
if (!att.isEmpty())
{
QCString *str=VhdlDocGen::findKeyWord(att);
att+=" ";
if (str)
VhdlDocGen::formatString(att,ol,mdef);
else
startFonts(att,"vhdlchar",ol);
}
QCString nn=arg->name;
nn+=": ";
QCString ss=arg->type.stripWhiteSpace(); //.lower();
QCString w=ss.stripWhiteSpace();//.upper();
startFonts(nn,"vhdlchar",ol);
startFonts("in ","stringliteral",ol);
QCString *str=VhdlDocGen::findKeyWord(ss);
if (str)
VhdlDocGen::formatString(w,ol,mdef);
else
startFonts(w,"vhdlchar",ol);
if (arg->attrib)
startFonts(arg->attrib,"vhdlchar",ol);
sem=TRUE;
ol.endBold();
if (len > 2)
{
ol.lineBreak();
}
}
ol.startBold();
ol.docify(" )");
const char *exp=mdef->excpString();
if (exp)
{
ol.insertMemberAlign();
ol.startBold();
ol.docify("[ ");
ol.docify(exp);
ol.docify(" ]");
ol.endBold();
}
ol.endBold();
}
/*!
* writes a process prototype to the output
*/
void VhdlDocGen::writeProcessProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
{
if (al==0) return;
ArgumentListIterator ali(*al);
Argument *arg;
bool sem=FALSE;
ol.startBold();
ol.docify(" ( ");
for (;(arg=ali.current());++ali)
{
if (sem)
{
ol.docify(" , ");
}
QCString nn=arg->name;
// startFonts(nn,"vhdlchar",ol);
VhdlDocGen::writeFormatString(nn,ol,mdef);
sem=TRUE;
}
ol.docify(" )");
ol.endBold();
}
/*!
* writes a function|procedure documentation to the output
*/
bool VhdlDocGen::writeFuncProcDocu(
const MemberDef *md,
OutputList& ol,
const ArgumentList* al,
bool /*type*/)
{
if (al==0) return FALSE;
//bool sem=FALSE;
ol.enableAll();
ArgumentListIterator ali(*al);
int index=ali.count();
if (index==0)
{
ol.docify(" ( ) ");
return FALSE;
}
ol.endMemberDocName();
ol.startParameterList(TRUE);
//ol.startParameterName(FALSE);
Argument *arg;
bool first=TRUE;
for (;(arg=ali.current());++ali)
{
ol.startParameterType(first,"");
// if (first) ol.writeChar('(');
QCString attl=arg->defval;
bool bGen=attl.stripPrefix("gen!");
if (bGen)
VhdlDocGen::writeFormatString(QCString("generic "),ol,md);
if (VhdlDocGen::isProcedure(md))
{
startFonts(arg->defval,"keywordtype",ol);
ol.docify(" ");
}
ol.endParameterType();
ol.startParameterName(TRUE);
VhdlDocGen::writeFormatString(arg->name,ol,md);
if (VhdlDocGen::isProcedure(md))
{
startFonts(arg->attrib,"stringliteral",ol);
}
else if (VhdlDocGen::isVhdlFunction(md))
{
startFonts(QCString("in"),"stringliteral",ol);
}
ol.docify(" ");
ol.disable(OutputGenerator::Man);
ol.startEmphasis();
ol.enable(OutputGenerator::Man);
if (!VhdlDocGen::isProcess(md))
{
// startFonts(arg->type,"vhdlkeyword",ol);
VhdlDocGen::writeFormatString(arg->type,ol,md);
}
ol.disable(OutputGenerator::Man);
ol.endEmphasis();
ol.enable(OutputGenerator::Man);
if (--index)
{
ol.docify(" , ");
}
else
{
// ol.docify(" ) ");
ol.endParameterName(TRUE,FALSE,TRUE);
break;
}
ol.endParameterName(FALSE,FALSE,FALSE);
//sem=TRUE;
first=FALSE;
}
//ol.endParameterList();
return TRUE;
} // writeDocFunProc
QCString VhdlDocGen::convertArgumentListToString(const ArgumentList* al,bool func)
{
QCString argString;
bool sem=FALSE;
ArgumentListIterator ali(*al);
Argument *arg;
for (;(arg=ali.current());++ali)
{
if (sem) argString.append(", ");
if (func)
{
argString+=arg->name;
argString+=":";
argString+=arg->type;
}
else
{
argString+=arg->defval+" ";
argString+=arg->name+" :";
argString+=arg->attrib+" ";
argString+=arg->type;
}
sem=TRUE;
}
return argString;
}
void VhdlDocGen::writeVhdlDeclarations(MemberList* ml,
OutputList& ol,GroupDef* gd,ClassDef* cd,FileDef *fd,NamespaceDef* nd)
{
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::LIBRARY,FALSE),0,FALSE,VhdlDocGen::LIBRARY);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::USE,FALSE),0,FALSE,VhdlDocGen::USE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::FUNCTION,FALSE),0,FALSE,VhdlDocGen::FUNCTION);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::COMPONENT,FALSE),0,FALSE,VhdlDocGen::COMPONENT);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::CONSTANT,FALSE),0,FALSE,VhdlDocGen::CONSTANT);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::TYPE,FALSE),0,FALSE,VhdlDocGen::TYPE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SUBTYPE,FALSE),0,FALSE,VhdlDocGen::SUBTYPE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::GENERIC,FALSE),0,FALSE,VhdlDocGen::GENERIC);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PORT,FALSE),0,FALSE,VhdlDocGen::PORT);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PROCESS,FALSE),0,FALSE,VhdlDocGen::PROCESS);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SIGNAL,FALSE),0,FALSE,VhdlDocGen::SIGNAL);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::ATTRIBUTE,FALSE),0,FALSE,VhdlDocGen::ATTRIBUTE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PROCEDURE,FALSE),0,FALSE,VhdlDocGen::PROCEDURE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::RECORD,FALSE),0,FALSE,VhdlDocGen::RECORD);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::UNITS,FALSE),0,FALSE,VhdlDocGen::UNITS);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SHAREDVARIABLE,FALSE),0,FALSE,VhdlDocGen::SHAREDVARIABLE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::VFILE,FALSE),0,FALSE,VhdlDocGen::VFILE);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::GROUP,FALSE),0,FALSE,VhdlDocGen::GROUP);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::INSTANTIATION,FALSE),0,FALSE,VhdlDocGen::INSTANTIATION);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::ALIAS,FALSE),0,FALSE,VhdlDocGen::ALIAS);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::MISCELLANEOUS),0,FALSE,VhdlDocGen::MISCELLANEOUS);
// configurations must be added to global file definitions.
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::CONFIG,FALSE),0,FALSE,VhdlDocGen::CONFIG);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::UCF_CONST,FALSE),0,FALSE,VhdlDocGen::UCF_CONST);
}
static void setGlobalType(MemberList *ml)
{
if (ml==0) return;
MemberDef *mdd=0;
MemberListIterator mmli(*ml);
for ( ; (mdd=mmli.current()); ++mmli )
{
if (qstrcmp(mdd->argsString(),"package")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
}
else if (qstrcmp(mdd->argsString(),"configuration")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::CONFIG);
}
else if (qstrcmp(mdd->typeString(),"library")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::LIBRARY);
}
else if (qstrcmp(mdd->typeString(),"use")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::USE);
}
else if (qstricmp(mdd->typeString(),"misc")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS);
}
else if (qstricmp(mdd->typeString(),"ucf_const")==0)
{
mdd->setMemberSpecifiers(VhdlDocGen::UCF_CONST);
}
}
}
/* writes a vhdl type documentation */
bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition *d, OutputList &ol)
{
ClassDef *cd=(ClassDef*)d;
bool hasParams = FALSE;
if (cd==0) return hasParams;
QCString ttype=mdef->typeString();
QCString largs=mdef->argsString();
if ((VhdlDocGen::isVhdlFunction(mdef) || VhdlDocGen::isProcedure(mdef) || VhdlDocGen::isProcess(mdef)))
{
QCString nn=mdef->typeString();
nn=nn.stripWhiteSpace();
QCString na=cd->name();
MemberDef* memdef=VhdlDocGen::findMember(na,nn);
if (memdef && memdef->isLinkable())
{
ol.docify(" ");
ol.startBold();
writeLink(memdef,ol);
ol.endBold();
ol.docify(" ");
}
else
{
ol.docify(" ");
VhdlDocGen::formatString(ttype,ol,mdef);
ol.docify(" ");
}
ol.docify(mdef->name());
hasParams = VhdlDocGen::writeFuncProcDocu(mdef,ol, mdef->argumentList());
}
if (mdef->isVariable())
{
if (VhdlDocGen::isConstraint(mdef))
{
writeLink(mdef,ol);
ol.docify(" ");
largs=largs.replace(QRegExp("#")," ");
VhdlDocGen::formatString(largs,ol,mdef);
return hasParams;
}
else
{
writeLink(mdef,ol);
if (VhdlDocGen::isLibrary(mdef) || VhdlDocGen::isPackage(mdef))
{
return hasParams;
}
ol.docify(" ");
}
// QCString largs=mdef->argsString();
bool c=largs=="context";
bool brec=largs.stripPrefix("record") ;
if (!brec && !c)
VhdlDocGen::formatString(ttype,ol,mdef);
if (c || brec || largs.stripPrefix("units"))
{
if (c)
largs=ttype;
VhdlDocGen::writeRecUnitDocu(mdef,ol,largs);
return hasParams;
}
ol.docify(" ");
if (VhdlDocGen::isPort(mdef) || VhdlDocGen::isGeneric(mdef))
{
// QCString largs=mdef->argsString();
VhdlDocGen::formatString(largs,ol,mdef);
ol.docify(" ");
}
}
return hasParams;
}
void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile)
{
tagFile << " <member kind=\"";
if (VhdlDocGen::isGeneric(mdef)) tagFile << "generic";
if (VhdlDocGen::isPort(mdef)) tagFile << "port";
if (VhdlDocGen::isEntity(mdef)) tagFile << "entity";
if (VhdlDocGen::isComponent(mdef)) tagFile << "component";
if (VhdlDocGen::isVType(mdef)) tagFile << "type";
if (VhdlDocGen::isConstant(mdef)) tagFile << "constant";
if (VhdlDocGen::isSubType(mdef)) tagFile << "subtype";
if (VhdlDocGen::isVhdlFunction(mdef)) tagFile << "function";
if (VhdlDocGen::isProcedure(mdef)) tagFile << "procedure";
if (VhdlDocGen::isProcess(mdef)) tagFile << "process";
if (VhdlDocGen::isSignals(mdef)) tagFile << "signal";
if (VhdlDocGen::isAttribute(mdef)) tagFile << "attribute";
if (VhdlDocGen::isRecord(mdef)) tagFile << "record";
if (VhdlDocGen::isLibrary(mdef)) tagFile << "library";
if (VhdlDocGen::isPackage(mdef)) tagFile << "package";
if (VhdlDocGen::isVariable(mdef)) tagFile << "shared variable";
if (VhdlDocGen::isFile(mdef)) tagFile << "file";
if (VhdlDocGen::isGroup(mdef)) tagFile << "group";
if (VhdlDocGen::isCompInst(mdef)) tagFile << "instantiation";
if (VhdlDocGen::isAlias(mdef)) tagFile << "alias";
if (VhdlDocGen::isCompInst(mdef)) tagFile << "configuration";
tagFile << "\">" << endl;
tagFile << " <type>" << convertToXML(mdef->typeString()) << "</type>" << endl;
tagFile << " <name>" << convertToXML(mdef->name()) << "</name>" << endl;
tagFile << " <anchorfile>" << convertToXML(mdef->getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
tagFile << " <anchor>" << convertToXML(mdef->anchor()) << "</anchor>" << endl;
if (VhdlDocGen::isVhdlFunction(mdef))
tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),TRUE)) << "</arglist>" << endl;
else if (VhdlDocGen::isProcedure(mdef))
tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),FALSE)) << "</arglist>" << endl;
else
tagFile << " <arglist>" << convertToXML(mdef->argsString()) << "</arglist>" << endl;
mdef->writeDocAnchorsToTagFile(tagFile);
tagFile << " </member>" << endl;
}
/* writes a vhdl type declaration */
void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
bool /*inGroup*/)
{
Definition *d=0;
ASSERT(cd!=0 || nd!=0 || fd!=0 || gd!=0 ||
mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY ||
mdef->getMemberSpecifiers()==VhdlDocGen::USE
); // member should belong to something
if (cd) d=cd;
else if (nd) d=nd;
else if (fd) d=fd;
else if (gd) d=gd;
else d=(Definition*)mdef;
// write search index info
if (Doxygen::searchIndex)
{
Doxygen::searchIndex->setCurrentDoc(mdef,mdef->anchor(),FALSE);
Doxygen::searchIndex->addWord(mdef->localName(),TRUE);
Doxygen::searchIndex->addWord(mdef->qualifiedName(),FALSE);
}
QCString cname = d->name();
QCString cfname = d->getOutputFileBase();
//HtmlHelp *htmlHelp=0;
// bool hasHtmlHelp = Config_getBool(GENERATE_HTML) && Config_getBool(GENERATE_HTMLHELP);
// if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
// search for the last anonymous scope in the member type
ClassDef *annoClassDef=mdef->getClassDefOfAnonymousType();
// start a new member declaration
uint isAnonymous = (bool)(annoClassDef); // || m_impl->annMemb || m_impl->annEnumType;
///printf("startMemberItem for %s\n",name().data());
int mm=mdef->getMemberSpecifiers();
if (mm==VhdlDocGen::MISCELLANEOUS)
isAnonymous=3;
ol.startMemberItem( mdef->anchor(), isAnonymous ); //? 1 : m_impl->tArgList ? 3 : 0);
// If there is no detailed description we need to write the anchor here.
bool detailsVisible = mdef->isDetailedSectionLinkable();
if (!detailsVisible) // && !m_impl->annMemb)
{
QCString doxyName=mdef->name().copy();
if (!cname.isEmpty()) doxyName.prepend(cname+"::");
QCString doxyArgs=mdef->argsString();
ol.startDoxyAnchor(cfname,cname,mdef->anchor(),doxyName,doxyArgs);
ol.pushGeneratorState();
ol.disable(OutputGenerator::Man);
ol.disable(OutputGenerator::Latex);
ol.docify("\n");
ol.popGeneratorState();
}
// *** write type
/*VHDL CHANGE */
bool bRec,bUnit;
QCString ltype(mdef->typeString());
// ltype=ltype.replace(reg," ");
QCString largs(mdef->argsString());
// largs=largs.replace(reg," ");
mdef->setType(ltype.data());
mdef->setArgsString(largs.data());
//ClassDef * plo=mdef->getClassDef();
ClassDef *kl=0;
ArgumentList *alp = mdef->argumentList();
QCString nn;
//VhdlDocGen::adjustRecordMember(mdef);
if (gd) gd=0;
switch (mm)
{
case VhdlDocGen::MISCELLANEOUS:
VhdlDocGen::writeSource(mdef,ol,nn);
break;
case VhdlDocGen::PROCEDURE:
case VhdlDocGen::FUNCTION:
ol.startBold();
VhdlDocGen::formatString(ltype,ol,mdef);
ol.endBold();
ol.insertMemberAlign();
ol.docify(" ");
writeLink(mdef,ol);
if (alp!=0 && mm==VhdlDocGen::FUNCTION)
VhdlDocGen::writeFunctionProto(ol,alp,mdef);
if (alp!=0 && mm==VhdlDocGen::PROCEDURE)
VhdlDocGen::writeProcedureProto(ol,alp,mdef);
break;
case VhdlDocGen::USE:
kl=VhdlDocGen::getClass(mdef->name());
if (kl && ((VhdlDocGen::VhdlClasses)kl->protection()==VhdlDocGen::ENTITYCLASS)) break;
writeLink(mdef,ol);
ol.insertMemberAlign();
ol.docify(" ");
if (kl)
{
nn=kl->getOutputFileBase();
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
ol.docify(" ");
QCString name=theTranslator_vhdlType(VhdlDocGen::PACKAGE,TRUE);
ol.startBold();
ol.docify(name.data());
name.resize(0);
ol.endBold();
name+=" <"+mdef->name()+">";
ol.startEmphasis();
ol.writeObjectLink(kl->getReference(),kl->getOutputFileBase(),0,name.data());
ol.popGeneratorState();
}
break;
case VhdlDocGen::LIBRARY:
writeLink(mdef,ol);
ol.insertMemberAlign();
if (largs=="context")
{
VhdlDocGen::writeRecorUnit(ltype,ol,mdef);
}
break;
case VhdlDocGen::GENERIC:
case VhdlDocGen::PORT:
case VhdlDocGen::ALIAS:
writeLink(mdef,ol);
ol.docify(" ");
ol.insertMemberAlign();
if (mm==VhdlDocGen::GENERIC)
{
ol.startBold();
VhdlDocGen::formatString(largs,ol,mdef);
ol.endBold();
}
else
{
ol.docify(" ");
ol.startBold();
VhdlDocGen::formatString(ltype,ol,mdef);
ol.endBold();
ol.docify(" ");
VhdlDocGen::formatString(largs,ol,mdef);
}
break;
case VhdlDocGen::PROCESS:
writeLink(mdef,ol);
ol.insertMemberAlign();
VhdlDocGen::writeProcessProto(ol,alp,mdef);
break;
case VhdlDocGen::PACKAGE:
case VhdlDocGen::ENTITY:
case VhdlDocGen::COMPONENT:
case VhdlDocGen::INSTANTIATION:
case VhdlDocGen::CONFIG:
if (VhdlDocGen::isCompInst(mdef) )
{
nn=largs;
if(nn.stripPrefix("function") || nn.stripPrefix("package"))
{
VhdlDocGen::formatString(largs,ol,mdef);
ol.insertMemberAlign();
writeLink(mdef,ol);
ol.docify(" ");
VhdlDocGen::formatString(ltype,ol,mdef);
break;
}
largs.prepend("::");
largs.prepend(mdef->name().data());
ol.writeObjectLink(mdef->getReference(),
cfname,
mdef->anchor(),
mdef->name());
}
else
writeLink(mdef,ol);
ol.insertMemberAlign();
ol.docify(" ");
ol.startBold();
ol.docify(ltype);
ol.endBold();
ol.docify(" ");
if (VhdlDocGen::isComponent(mdef) ||
VhdlDocGen::isConfig(mdef) ||
VhdlDocGen::isCompInst(mdef))
{
if (VhdlDocGen::isConfig(mdef) || VhdlDocGen::isCompInst(mdef))
{
nn=ltype;
}
else
{
nn=mdef->name();
}
kl=getClass(nn.data());
if (kl)
{
nn=kl->getOutputFileBase();
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
ol.startEmphasis();
QCString name("<Entity ");
if (VhdlDocGen::isConfig(mdef) || VhdlDocGen::isCompInst(mdef))
{
name+=ltype+">";
}
else
{
name+=mdef->name()+"> ";
}
ol.writeObjectLink(kl->getReference(),kl->getOutputFileBase(),0,name.data());
ol.endEmphasis();
ol.popGeneratorState();
}
}
break;
case VhdlDocGen::UCF_CONST:
mm=mdef->name().findRev('_');
if (mm>0)
{
mdef->setName(mdef->name().left(mm));
}
writeUCFLink(mdef,ol);
break;
case VhdlDocGen::SIGNAL:
case VhdlDocGen::ATTRIBUTE:
case VhdlDocGen::SUBTYPE:
case VhdlDocGen::CONSTANT:
case VhdlDocGen::SHAREDVARIABLE:
case VhdlDocGen::VFILE:
case VhdlDocGen::GROUP:
writeLink(mdef,ol);
ol.docify(" ");
ol.insertMemberAlign();
VhdlDocGen::formatString(ltype,ol,mdef);
break;
case VhdlDocGen::RECORD:
case VhdlDocGen::UNITS:
writeLink(mdef,ol);
ol.docify(" ");
ol.startBold();
if (ltype.isEmpty()) {
ol.docify(" ");
}
ol.insertMemberAlign();
if (!ltype.isEmpty())
VhdlDocGen::formatString(ltype,ol,mdef);
ol.endBold();
break;
case VhdlDocGen::TYPE:
bRec=largs.stripPrefix("record") ;
bUnit=largs.stripPrefix("units") ;
ol.startBold();
if (bRec) ol.docify("record: ");
if (bUnit) ol.docify("units: ");
writeLink(mdef,ol);
ol.insertMemberAlign();
if (!bRec && !bUnit) VhdlDocGen::formatString(ltype,ol,mdef);
if (bUnit) ol.lineBreak();
if (bRec || bUnit)
{
writeRecorUnit(largs,ol,mdef);
mdef->setType("");
}
ol.endBold();
break;
default: break;
}
bool htmlOn = ol.isEnabled(OutputGenerator::Html);
if (htmlOn && /*Config_getBool(HTML_ALIGN_MEMBERS) &&*/ !ltype.isEmpty())
{
ol.disable(OutputGenerator::Html);
}
if (!ltype.isEmpty()) ol.docify(" ");
if (htmlOn)
{
ol.enable(OutputGenerator::Html);
}
if (!detailsVisible)// && !m_impl->annMemb)
{
ol.endDoxyAnchor(cfname,mdef->anchor());
}
// name().data(),annoClassDef,annEnumType);
// if(mm!=VhdlDocGen::MISCELLANEOUS)
ol.endMemberItem();
if (!mdef->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC) /* && !annMemb */)
{
QCString s=mdef->briefDescription();
ol.startMemberDescription(mdef->anchor());
ol.generateDoc(mdef->briefFile(),mdef->briefLine(),
mdef->getOuterScope()?mdef->getOuterScope():d,
mdef,s.data(),TRUE,FALSE,0,TRUE,FALSE);
if (detailsVisible)
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
//ol.endEmphasis();
ol.docify(" ");
if (mdef->getGroupDef()!=0 && gd==0) // forward link to the group
{
ol.startTextLink(mdef->getOutputFileBase(),mdef->anchor());
}
else // local link
{
ol.startTextLink(0,mdef->anchor());
}
ol.endTextLink();
//ol.startEmphasis();
ol.popGeneratorState();
}
//ol.newParagraph();
ol.endMemberDescription();
}
mdef->warnIfUndocumented();
}// end writeVhdlDeclaration
void VhdlDocGen::writePlainVHDLDeclarations(
MemberList* mlist,OutputList &ol,
ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier)
{
SDict<QCString> pack(1009);
pack.setAutoDelete(TRUE);
bool first=TRUE;
MemberDef *md;
MemberListIterator mli(*mlist);
for ( ; (md=mli.current()); ++mli )
{
int mems=md->getMemberSpecifiers();
if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) )
{
if (first) { ol.startMemberList();first=FALSE; }
VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE);
} //if
else if (md->isBriefSectionVisible() && (mems==specifier))
{
if (!pack.find(md->name().data()))
{
if (first) ol.startMemberList(),first=FALSE;
VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE);
pack.append(md->name().data(),new QCString(md->name().data()));
}
} //if
} //for
if (!first) ol.endMemberList();
pack.clear();
}//plainDeclaration
static bool membersHaveSpecificType(MemberList *ml,uint64 type)
{
if (ml==0) return FALSE;
MemberDef *mdd=0;
MemberListIterator mmli(*ml);
for ( ; (mdd=mmli.current()); ++mmli )
{
if (mdd->getMemberSpecifiers()==type) //is type in class
{
return TRUE;
}
}
if (ml->getMemberGroupList())
{
MemberGroupListIterator mgli(*ml->getMemberGroupList());
MemberGroup *mg;
while ((mg=mgli.current()))
{
if (mg->members())
{
if (membersHaveSpecificType(mg->members(),type)) return TRUE;
}
++mgli;
}
}
return FALSE;
}
void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol,
ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
const char *title,const char *subtitle,bool /*showEnumValues*/,int type)
{
setGlobalType(ml);
if (!membersHaveSpecificType(ml,type)) return;
if (title)
{
ol.startMemberHeader(title);
ol.parseText(title);
ol.endMemberHeader();
ol.docify(" ");
}
if (subtitle && subtitle[0]!=0)
{
ol.startMemberSubtitle();
ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE,0,TRUE,FALSE);
ol.endMemberSubtitle();
} //printf("memberGroupList=%p\n",memberGroupList);
VhdlDocGen::writePlainVHDLDeclarations(ml,ol,cd,nd,fd,gd,type);
if (ml->getMemberGroupList())
{
MemberGroupListIterator mgli(*ml->getMemberGroupList());
MemberGroup *mg;
while ((mg=mgli.current()))
{
if (membersHaveSpecificType(mg->members(),type))
{
//printf("mg->header=%s\n",mg->header().data());
bool hasHeader=mg->header()!="[NOHEADER]";
ol.startMemberGroupHeader(hasHeader);
if (hasHeader)
{
ol.parseText(mg->header());
}
ol.endMemberGroupHeader();
if (!mg->documentation().isEmpty())
{
//printf("Member group has docs!\n");
ol.startMemberGroupDocs();
ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE);
ol.endMemberGroupDocs();
}
ol.startMemberGroup();
//printf("--- mg->writePlainDeclarations ---\n");
VhdlDocGen::writePlainVHDLDeclarations(mg->members(),ol,cd,nd,fd,gd,type);
ol.endMemberGroup(hasHeader);
}
++mgli;
}
}
}// writeVHDLDeclarations
bool VhdlDocGen::writeClassType( ClassDef *& cd,
OutputList &ol ,QCString & cname)
{
int id=cd->protection();
QCString qcs = VhdlDocGen::trTypeString(id+2);
cname=VhdlDocGen::getClassName(cd);
ol.startBold();
ol.writeString(qcs.data());
ol.writeString(" ");
ol.endBold();
//ol.insertMemberAlign();
return FALSE;
}// writeClassLink
QCString VhdlDocGen::trVhdlType(uint64 type,bool sing)
{
switch(type)
{
case VhdlDocGen::LIBRARY:
if (sing) return "Library";
else return "Libraries";
case VhdlDocGen::PACKAGE:
if (sing) return "Package";
else return "Packages";
case VhdlDocGen::SIGNAL:
if (sing) return "Signal";
else return "Signals";
case VhdlDocGen::COMPONENT:
if (sing) return "Component";
else return "Components";
case VhdlDocGen::CONSTANT:
if (sing) return "Constant";
else return "Constants";
case VhdlDocGen::ENTITY:
if (sing) return "Entity";
else return "Entities";
case VhdlDocGen::TYPE:
if (sing) return "Type";
else return "Types";
case VhdlDocGen::SUBTYPE:
if (sing) return "Subtype";
else return "Subtypes";
case VhdlDocGen::FUNCTION:
if (sing) return "Function";
else return "Functions";
case VhdlDocGen::RECORD:
if (sing) return "Record";
else return "Records";
case VhdlDocGen::PROCEDURE:
if (sing) return "Procedure";
else return "Procedures";
case VhdlDocGen::ARCHITECTURE:
if (sing) return "Architecture";
else return "Architectures";
case VhdlDocGen::ATTRIBUTE:
if (sing) return "Attribute";
else return "Attributes";
case VhdlDocGen::PROCESS:
if (sing) return "Process";
else return "Processes";
case VhdlDocGen::PORT:
if (sing) return "Port";
else return "Ports";
case VhdlDocGen::USE:
if (sing) return "use clause";
else return "Use Clauses";
case VhdlDocGen::GENERIC:
if (sing) return "Generic";
else return "Generics";
case VhdlDocGen::PACKAGE_BODY:
return "Package Body";
case VhdlDocGen::UNITS:
return "Units";
case VhdlDocGen::SHAREDVARIABLE:
if (sing) return "Shared Variable";
return "Shared Variables";
case VhdlDocGen::VFILE:
if (sing) return "File";
return "Files";
case VhdlDocGen::GROUP:
if (sing) return "Group";
return "Groups";
case VhdlDocGen::INSTANTIATION:
if (sing) return "Instantiation";
else return "Instantiations";
case VhdlDocGen::ALIAS:
if (sing) return "Alias";
return "Aliases";
case VhdlDocGen::CONFIG:
if (sing) return "Configuration";
return "Configurations";
case VhdlDocGen::MISCELLANEOUS:
return "Miscellaneous";
case VhdlDocGen::UCF_CONST:
return "Constraints";
default:
return "Class";
}
}
QCString VhdlDocGen::trDesignUnitHierarchy()
{
return "Design Unit Hierarchy";
}
QCString VhdlDocGen::trDesignUnitList()
{
return "Design Unit List";
}
QCString VhdlDocGen::trDesignUnitMembers()
{
return "Design Unit Members";
}
QCString VhdlDocGen::trDesignUnitListDescription()
{
return "Here is a list of all design unit members with links to "
"the Entities they belong to:";
}
QCString VhdlDocGen::trDesignUnitIndex()
{
return "Design Unit Index";
}
QCString VhdlDocGen::trDesignUnits()
{
return "Design Units";
}
QCString VhdlDocGen::trFunctionAndProc()
{
return "Functions/Procedures/Processes";
}
/*! writes a link if the string is linkable else a formatted string */
void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& ol)
{
if (mdef)
{
ClassDef *cd=mdef->getClassDef();
if (cd)
{
QCString n=cd->name();
MemberDef* memdef=VhdlDocGen::findMember(n,mem);
if (memdef && memdef->isLinkable())
{
ol.startBold();
writeLink(memdef,ol);
ol.endBold();
ol.docify(" ");
return;
}
}
}
startFonts(mem,"vhdlchar",ol);
}// found component
void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname)
{
ParserInterface *pIntf = Doxygen::parserManager->getParser(".vhd");
// pIntf->resetCodeParserState();
QCString codeFragment=mdef->documentation();
if (cname.isEmpty())
{
writeLink(mdef,ol);
int fi=0;
int j=0;
do
{
fi=codeFragment.find("\n",++fi);
} while(fi>=0 && j++ <3);
// show only the first four lines
if (j==4)
{
codeFragment=codeFragment.left(fi);
codeFragment.append("\n .... ");
}
}
codeFragment.prepend("\n");
ol.pushGeneratorState();
ol.startCodeFragment();
pIntf->parseCode(ol, // codeOutIntf
0, // scope
codeFragment, // input
SrcLangExt_VHDL, // lang
FALSE, // isExample
0, // exampleName
mdef->getFileDef(), // fileDef
mdef->getStartBodyLine(), // startLine
mdef->getEndBodyLine(), // endLine
TRUE, // inlineFragment
mdef, // memberDef
TRUE // show line numbers
);
ol.endCodeFragment();
ol.popGeneratorState();
if (cname.isEmpty()) return;
mdef->writeSourceDef(ol,cname);
mdef->writeSourceRefs(ol,cname);
mdef->writeSourceReffedBy(ol,cname);
}
QCString VhdlDocGen::convertFileNameToClassName(QCString name)
{
QCString n=name;
n=n.remove(0,6);
int i=0;
while((i=n.find("__"))>0)
{
n=n.remove(i,1);
}
while((i=n.find("_1"))>0)
{
n=n.replace(i,2,":");
}
return n;
}
void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,bool altera)
{
QCString ucFile(input);
int lineNo=0;
QCString comment("#!");
QCString brief;
while (!ucFile.isEmpty())
{
int i=ucFile.find("\n");
if (i<0) break;
lineNo++;
QCString temp=ucFile.left(i);
temp=temp.stripWhiteSpace();
bool bb=temp.stripPrefix("//");
if (!temp.isEmpty())
{
if (temp.stripPrefix(comment) )
{
brief+=temp;
brief.append("\\n");
}
else if (!temp.stripPrefix("#") && !bb)
{
if (altera)
{
int i=temp.find("-name");
if (i>0)
{
temp=temp.remove(0,i+5);
}
temp.stripPrefix("set_location_assignment");
initUCF(entity,0,temp,lineNo,fileName,brief);
}
else
{
QRegExp ee("[\\s=]");
int i=temp.find(ee);
QCString ff=temp.left(i);
temp.stripPrefix(ff.data());
ff.append("#");
if (!temp.isEmpty())
{
initUCF(entity,ff.data(),temp,lineNo,fileName,brief);
}
}
}
}//temp
ucFile=ucFile.remove(0,i+1);
}// while
}
static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCString & fileName,QCString & brief)
{
if (qcs.isEmpty())return;
QRegExp reg("[\\s=]");
QCString n;
// bool bo=(qstricmp(type,qcs.data())==0);
VhdlDocGen::deleteAllChars(qcs,';');
qcs=qcs.stripWhiteSpace();
int i= qcs.find(reg);
if (i<0) return;
if (i==0)
{
n=type;
VhdlDocGen::deleteAllChars(n,'#');
type="";
}
else
{
n=qcs.left(i);
}
qcs=qcs.remove(0,i+1);
// qcs.prepend("|");
qcs.stripPrefix("=");
Entry* current=new Entry;
current->spec=VhdlDocGen::UCF_CONST;
current->section=Entry::VARIABLE_SEC;
current->bodyLine=line;
current->fileName=fileName;
current->type="ucf_const";
current->args+=qcs;
current->lang= SrcLangExt_VHDL ;
// adding dummy name for constraints like VOLTAGE=5,TEMPERATURE=20 C
if (n.isEmpty())
{
n="dummy";
n+=VhdlDocGen::getRecordNumber();
}
current->name= n+"_";
current->name.append(VhdlDocGen::getRecordNumber().data());
if (!brief.isEmpty())
{
current->brief=brief;
current->briefLine=line;
current->briefFile=fileName;
brief.resize(0);
}
root->addSubEntry(current);
}
static void writeUCFLink(const MemberDef* mdef,OutputList &ol)
{
QCString largs(mdef->argsString());
QCString n= splitString(largs, '#');
// VhdlDocGen::adjustRecordMember(mdef);
bool equ=(n.length()==largs.length());
if (!equ)
{
ol.writeString(n.data());
ol.docify(" ");
ol.insertMemberAlign();
}
if (mdef->name().contains("dummy")==0)
{
writeLink(mdef,ol);
}
if (equ)
{
ol.insertMemberAlign();
}
ol.docify(" ");
VhdlDocGen::formatString(largs,ol,mdef);
}
bool VhdlDocGen::findConstraintFile(LayoutNavEntry *lne)
{
FileName *fn=Doxygen::inputNameList->getFirst();
//LayoutNavEntry *cc = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files);
uint count=Doxygen::inputNameList->count();
LayoutNavEntry *kk = lne->parent();// find(LayoutNavEntry::Files);
// LayoutNavEntry *kks = kk->parent();// find(LayoutNavEntry::Files);
QCString file;
QCString co("Constraints");
QCString imgExt = getDotImageExtension();
if (Config_getBool(HAVE_DOT) && imgExt=="svg")
{
QCString ov = theTranslator->trDesignOverview();
QCString ofile("vhdl_design_overview");
LayoutNavEntry *oo=new LayoutNavEntry( lne,LayoutNavEntry::MainPage,TRUE,ofile,ov,"");
kk->addChild(oo);
}
uint i=0;
while (i<count)
{
FileDef *fd=fn->at(i);
if (fd->name().contains(".ucf") || fd->name().contains(".qsf"))
{
file = convertNameToFile(fd->name().data(),FALSE,FALSE);
LayoutNavEntry *ucf=new LayoutNavEntry(lne,LayoutNavEntry::MainPage,TRUE,file,co,"");
kk->addChild(ucf);
break;
}
i++;
}
return FALSE;
}
// for cell_inst : [entity] work.proto [ (label|expr) ]
QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch)
{
int index;
QCString label;
if (!entity.contains(":")) return "";
QRegExp exp("[:()\\s]");
QStringList ql=QStringList::split(exp,entity,FALSE);
//int ii=ql.findIndex(ent);
assert(ql.count()>=2);
label = ql[0].utf8();
entity = ql[1].utf8();
if ((index=entity.findRev("."))>=0)
{
entity.remove(0,index+1);
}
if (ql.count()==3)
{
arch= ql[2].utf8();
ql=QStringList::split(exp,arch,FALSE);
if (ql.count()>1) // expression
{
arch="";
}
}
return label; // label
}
// use (configuration|entity|open) work.test [(cellfor)];
QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch)
{
int index;
QRegExp exp("[()\\s]");
QCString label="";
QStringList ql=QStringList::split(exp,entity,FALSE);
if (ql.contains("open"))
{
return "open";
}
label=ql[0].utf8();
entity = ql[1].utf8();
if ((index=entity.findRev("."))>=0)
{
entity.remove(0,index+1);
}
if (ql.count()==3)
{
arch=ql[2].utf8();
}
return label;
}
// find class with upper/lower letters
ClassDef* VhdlDocGen::findVhdlClass(const char *className )
{
ClassSDict::Iterator cli(*Doxygen::classSDict);
ClassDef *cd;
for (;(cd=cli.current());++cli)
{
if (qstricmp(className,cd->name().data())==0)
{
return cd;
}
}
return 0;
}
//@param arch bit0:flipflop
//@param binding e.g entity work.foo(bar)
//@param label |label0|label1
// label0:architecture name
//@param confVhdl of configuration file (identifier::entity_name) or
// the architecture if isInlineConf TRUE
//@param isInlineConf
//@param confN List of configurations
void assignBinding(VhdlConfNode * conf)
{
QList<Entry> instList=getVhdlInstList();
QListIterator<Entry> eli(instList);
Entry *cur=0;
ClassDef *archClass=0,*entClass=0;
QCString archName;
QCString arcBind,entBind;
bool others,all;
entBind=conf->binding;
QCString conf2=VhdlDocGen::parseForBinding(entBind,arcBind);
if (qstricmp(conf2,"configuration")==0)
{
QList<VhdlConfNode> confList = getVhdlConfiguration();
VhdlConfNode* vconf;
// bool found=false;
for (uint iter=0;iter<confList.count(); iter++)
{
vconf= (VhdlConfNode *)confList.at(iter);
QCString n=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),0);
if (n==entBind)
{
// found=true;
entBind=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),1);
QCString a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0);
QCString e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1);
a=e+"::"+a;
archClass= VhdlDocGen::findVhdlClass(a.data());//Doxygen::classSDict->find(a.data());
entClass= VhdlDocGen::findVhdlClass(e.data());//Doxygen::classSDict->find(e.data());
break;
}
}
}
else // conf2!=configuration
{
QCString a,c,e;
if (conf->isInlineConf)
{
c=conf->confVhdl;
e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),0);
}
else
{
a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0);
e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1);
c=e+"::"+a;
}
archClass= VhdlDocGen::findVhdlClass(c.data());//Doxygen::classSDict->find(a.data());
entClass= VhdlDocGen::findVhdlClass(e.data()); //Doxygen::classSDict->find(e.data());
}
QCString label=conf->compSpec.lower();
//label.prepend("|");
if (!archClass)
{
// err("architecture %s not found ! ",conf->confVhdl.data());
return;
}
archName=archClass->name();
QCString allOt=VhdlDocGen::getIndexWord(conf->arch.data(),0);
all=allOt.lower()=="all" ;
others= allOt.lower()=="others";
for (;(cur=eli.current());++eli)
{
if (cur->exception.lower()==label || conf->isInlineConf)
{
QCString archy;
if (all || others)
{
archy=VhdlDocGen::getIndexWord(conf->arch.data(),1);
}
else
{
archy=conf->arch;
}
QCString inst1=VhdlDocGen::getIndexWord(archy.data(),0).lower();
QCString comp=VhdlDocGen::getIndexWord(archy.data(),1).lower();
QStringList ql=QStringList::split(",",inst1);
for (uint j=0;j<ql.count();j++)
{
QCString archy1,sign1;
if (all || others)
{
archy1=VhdlDocGen::getIndexWord(conf->arch.data(),1);
sign1=cur->type;
}
else
{
archy1=comp+":"+ql[j].utf8();
sign1=cur->type+":"+cur->name;
}
if (archy1==sign1.lower() && !cur->stat)
{
// fprintf(stderr," \n label [%s] [%s] [%s]",cur->exception.data(),cur->type.data(),cur->name.data());
ClassDef *ent= VhdlDocGen::findVhdlClass(entBind.data());//Doxygen::classSDict->find(entBind.data());
if (entClass==0 || ent==0)
{
continue;
}
addInstance(ent,archClass,entClass,cur);
cur->stat=TRUE;
break;
}
}// for
}
}//for each element in instList
}//assignBinding
/*
// file foo.vhd
// entity foo
// .....
// end entity
// file foo_arch.vhd
// architecture xxx of foo is
// ........
// end architecture
*/
void VhdlDocGen::computeVhdlComponentRelations()
{
QCString entity,arch,inst;
QList<VhdlConfNode> confList = getVhdlConfiguration();
for (uint iter=0;iter<confList.count(); iter++)
{
VhdlConfNode* conf= (VhdlConfNode *)confList.at(iter);
if (!(conf->isInlineConf || conf->isLeaf))
{
continue;
}
assignBinding(conf);
}
QList<Entry> qsl= getVhdlInstList();
QListIterator<Entry> eli(qsl);
Entry *cur;
for (eli.toFirst();(cur=eli.current());++eli)
{
if (cur->stat ) // was bind
{
continue;
}
if (cur->includeName=="entity" || cur->includeName=="component" )
{
entity=cur->includeName+" "+cur->type;
QCString rr=VhdlDocGen::parseForBinding(entity,arch);
}
else if (cur->includeName.isEmpty())
{
entity=cur->type;
}
ClassDef *classEntity= VhdlDocGen::findVhdlClass(entity.data());//Doxygen::classSDict->find(entity);
inst=VhdlDocGen::getIndexWord(cur->args.data(),0);
ClassDef *cd=Doxygen::classSDict->find(inst);
ClassDef *ar=Doxygen::classSDict->find(cur->args);
if (cd==0)
{
continue;
}
// if (classEntity==0)
// err("%s:%d:Entity:%s%s",cur->fileName.data(),cur->startLine,entity.data()," could not be found");
addInstance(classEntity,ar,cd,cur);
}
}
static void addInstance(ClassDef* classEntity, ClassDef* ar,
ClassDef *cd , Entry *cur,ClassDef* /*archBind*/)
{
QCString bName,n1;
if (ar==0) return;
if (classEntity==0)
{
//add component inst
n1=cur->type;
goto ferr;
}
if (classEntity==cd) return;
bName=classEntity->name();
// fprintf(stderr,"\naddInstance %s to %s %s %s\n", classEntity->name().data(),cd->name().data(),ar->name().data(),cur->name);
n1=classEntity->name().data();
if (!cd->isBaseClass(classEntity, true, 0))
{
cd->insertBaseClass(classEntity,n1,Public,Normal,0);
}
else
{
VhdlDocGen::addBaseClass(cd,classEntity);
}
if (!VhdlDocGen::isSubClass(classEntity,cd,true,0))
{
classEntity->insertSubClass(cd,Public,Normal,0);
classEntity->setLanguage(SrcLangExt_VHDL);
}
ferr:
QCString uu=cur->name;
MemberDef *md=new MemberDef(
ar->getDefFileName(), cur->startLine,cur->startColumn,
n1,uu,uu, 0,
Public, Normal, cur->stat,Member,
MemberType_Variable,
0,
0);
if (ar->getOutputFileBase())
{
TagInfo tg;
tg.anchor = 0;
tg.fileName = ar->getOutputFileBase();
tg.tagName = 0;
md->setTagInfo(&tg);
}
//fprintf(stderr,"\n%s%s%s\n",md->name().data(),cur->brief.data(),cur->doc.data());
md->setLanguage(SrcLangExt_VHDL);
md->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
md->setBriefDescription(cur->brief,cur->briefFile,cur->briefLine);
md->setBodySegment(cur->startLine,-1) ;
md->setDocumentation(cur->doc.data(),cur->docFile.data(),cur->docLine);
FileDef *fd=ar->getFileDef();
md->setBodyDef(fd);
QCString info="Info: Elaborating entity "+n1;
fd=ar->getFileDef();
info+=" for hierarchy ";
QRegExp epr("[|]");
QCString label=cur->type+":"+cur->write+":"+cur->name;
label.replace(epr,":");
info+=label;
fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data());
ar->insertMember(md);
}
void VhdlDocGen::writeRecorUnit(QCString & largs,OutputList& ol ,const MemberDef *mdef)
{
QStringList ql=QStringList::split("#",largs,FALSE);
uint len=ql.count();
for(uint i=0;i<len;i++)
{
QCString n=ql[i].utf8();
VhdlDocGen::formatString(n,ol,mdef);
if ((len-i)>1) ol.lineBreak();
}
}
void VhdlDocGen::writeRecUnitDocu(
const MemberDef *md,
OutputList& ol,
QCString largs)
{
QStringList ql=QStringList::split("#",largs,FALSE);
uint len=ql.count();
ol.startParameterList(TRUE);
bool first=TRUE;
for(uint i=0;i<len;i++)
{
QCString n=ql[i].utf8();
ol.startParameterType(first,"");
ol.endParameterType();
ol.startParameterName(TRUE);
VhdlDocGen::formatString(n,ol,md);
if ((len-i)>1)
{
ol.endParameterName(FALSE,FALSE,FALSE);
}
else
{
ol.endParameterName(TRUE,FALSE,TRUE);
}
first=FALSE;
}
}//#
bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int level)
{
bool found=FALSE;
//printf("isBaseClass(cd=%s) looking for %s\n",name().data(),bcd->name().data());
if (level>255)
{
err("Possible recursive class relation while inside %s and looking for %s\n",qPrint(cd->name()),qPrint(scd->name()));
abort();
return FALSE;
}
if (cd->subClasses())
{
BaseClassListIterator bcli(*cd->subClasses());
for ( ; bcli.current() && !found ; ++bcli)
{
ClassDef *ccd=bcli.current()->classDef;
if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
//printf("isSubClass() subclass %s\n",ccd->name().data());
if (ccd==scd)
{
found=TRUE;
}
else
{
if (level <256)
{
found=ccd->isBaseClass(scd,followInstances,level+1);
}
}
}
}
return found;
}
void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent)
{
if (cd->baseClasses())
{
BaseClassListIterator bcli(*cd->baseClasses());
for ( ; bcli.current() ; ++bcli)
{
ClassDef *ccd=bcli.current()->classDef;
if (ccd==ent)
{
QCString n = bcli.current()->usedName;
int i = n.find('(');
if(i<0)
{
bcli.current()->usedName.append("(2)");
return;
}
static QRegExp reg("[0-9]+");
QCString s=n.left(i);
QCString r=n.right(n.length()-i);
QCString t=r;
VhdlDocGen::deleteAllChars(r,')');
VhdlDocGen::deleteAllChars(r,'(');
r.setNum(r.toInt()+1);
t.replace(reg,r.data());
s.append(t.data());
bcli.current()->usedName=s;
bcli.current()->templSpecifiers=t;
}
}
}
}
static QList<MemberDef> mdList;
static MemberDef* findMemFlow(const MemberDef* mdef)
{
for(uint j=0;j<mdList.count();j++)
{
MemberDef* md=(MemberDef*)mdList.at(j);
if (md->name()==mdef->name() && md->getStartBodyLine()==mdef->getStartBodyLine())
return md;
}
return 0;
}
void VhdlDocGen::createFlowChart(const MemberDef *mdef)
{
if (mdef==0) return;
QCString codeFragment;
MemberDef* mm=0;
if((mm=findMemFlow(mdef))!=0)
{
// don't create the same flowchart twice
VhdlDocGen::setFlowMember(mm);
return;
}
else
{
mdList.append(mdef);
}
//fprintf(stderr,"\n create flow mem %s %p\n",mdef->name().data(),mdef);
int actualStart= mdef->getStartBodyLine();
int actualEnd=mdef->getEndBodyLine();
FileDef* fd=mdef->getFileDef();
bool b=readCodeFragment( fd->absFilePath().data(), actualStart,actualEnd,codeFragment);
if (!b) return;
VHDLLanguageScanner *pIntf =(VHDLLanguageScanner*) Doxygen::parserManager->getParser(".vhd");
VhdlDocGen::setFlowMember(mdef);
Entry root;
QStrList filesInSameTu;
pIntf->startTranslationUnit("");
pIntf->parseInput("",codeFragment.data(),&root,FALSE,filesInSameTu);
pIntf->finishTranslationUnit();
}
void VhdlDocGen::resetCodeVhdlParserState()
{
varMap.clear();
qli.clear();
packages.clear();
}
bool VhdlDocGen::isConstraint(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::UCF_CONST; }
bool VhdlDocGen::isConfig(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::CONFIG; }
bool VhdlDocGen::isAlias(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::ALIAS; }
bool VhdlDocGen::isLibrary(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY; }
bool VhdlDocGen::isGeneric(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::GENERIC; }
bool VhdlDocGen::isPort(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::PORT; }
bool VhdlDocGen::isComponent(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::COMPONENT; }
bool VhdlDocGen::isPackage(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::USE; }
bool VhdlDocGen::isEntity(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::ENTITY; }
bool VhdlDocGen::isConstant(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::CONSTANT; }
bool VhdlDocGen::isVType(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::TYPE; }
bool VhdlDocGen::isSubType(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::SUBTYPE; }
bool VhdlDocGen::isVhdlFunction(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::FUNCTION; }
bool VhdlDocGen::isProcess(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::PROCESS; }
bool VhdlDocGen::isSignal(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::SIGNAL; }
bool VhdlDocGen::isAttribute(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::ATTRIBUTE; }
bool VhdlDocGen::isSignals(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::SIGNAL; }
bool VhdlDocGen::isProcedure(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::PROCEDURE; }
bool VhdlDocGen::isRecord(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::RECORD; }
bool VhdlDocGen::isArchitecture(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::ARCHITECTURE; }
bool VhdlDocGen::isUnit(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::UNITS; }
bool VhdlDocGen::isPackageBody(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::PACKAGE_BODY; }
bool VhdlDocGen::isVariable(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::SHAREDVARIABLE; }
bool VhdlDocGen::isFile(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::VFILE; }
bool VhdlDocGen::isGroup(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::GROUP; }
bool VhdlDocGen::isCompInst(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::INSTANTIATION; }
bool VhdlDocGen::isMisc(const MemberDef *mdef)
{ return mdef->getMemberSpecifiers()==VhdlDocGen::MISCELLANEOUS; }
//############################## Flowcharts #################################################
#define STARTL (FlowChart::WHILE_NO | FlowChart::IF_NO | \
FlowChart::FOR_NO | FlowChart::CASE_NO | \
FlowChart::LOOP_NO | WHEN_NO)
#define DECLN (FlowChart::WHEN_NO | \
FlowChart::ELSIF_NO | FlowChart::IF_NO | \
FlowChart::FOR_NO | FlowChart::WHILE_NO | \
FlowChart::CASE_NO | FlowChart::LOOP_NO )
#define STARTFIN (FlowChart::START_NO | FlowChart::END_NO)
#define LOOP (FlowChart::FOR_NO | FlowChart::WHILE_NO | \
FlowChart::LOOP_NO )
#define ENDCL (FlowChart::END_CASE | FlowChart::END_LOOP)
#define EEND (FlowChart::ENDIF_NO | FlowChart::ELSE_NO )
#define IFF (FlowChart::ELSIF_NO | FlowChart::IF_NO)
#define EXITNEXT (FlowChart::EXIT_NO | FlowChart::NEXT_NO )
#define EMPTY (EEND | FlowChart::ELSIF_NO)
#define EE (FlowChart::ELSE_NO | FlowChart::ELSIF_NO)
#define EMPTNODE (ENDCL | EEND | FlowChart::ELSIF_NO)
#define FLOWLEN (flowList.count()-1)
static int ifcounter=0;
static int nodeCounter=0;
static struct
{
// link colors
const char *textNodeLink;
const char *yesNodeLink;
const char *noNodeLink;
// node colors
const char* comment;
const char* decisionNode;
const char* varNode;
const char *startEndNode;
const char* textNode;
} flowCol =
{ "green", // textNodeLink
"red", // yesNodeLink
"black", // noNodeLink
"khaki", // comment
"0.7 0.3 1.0", // decisionNode
"lightyellow", // varNode
"white", // startEndNode
"lightcyan" // textNode
};
QList<FlowChart> FlowChart::flowList;
#ifdef DEBUGFLOW
static QMap<QCString,int> keyMap;
#endif
void alignText(QCString & q)
{
if (q.length()<=80) return;
if (q.length()>200)
{
q.resize(200);
}
q.append(" ...");
QRegExp reg("[\\s|]");
QCString str(q.data());
QCString temp;
while (str.length()>80)
{
int j=str.findRev(reg,80);
if (j<=0)
{
temp+=str;
q=temp;
return;
}
else
{
QCString qcs=str.left(j);
temp+=qcs+"\\";
temp+="n";
str.remove(0,j);
}
}//while
q=temp+str;
// #endif
}
void FlowChart::printNode(const FlowChart* flo)
{
if (flo==0) return;
QCString ui="-";
QCString q,t;
QRegExp ep("[\t\n\r]");
ui.fill('-',255);
if (flo->type & STARTL)
{
if (flo->stamp>0)
{
q=ui.left(2*flo->stamp);
}
else
{
q=" ";
}
QCString nn=flo->exp.stripWhiteSpace();
printf("\nYES: %s%s[%d,%d]",q.data(),nn.data(),flo->stamp,flo->id);
}
else
{
if (flo->type & COMMENT_NO)
{
t=flo->label;
}
else
{
t=flo->text;
}
t=t.replace(ep,"");
if (t.isEmpty())
{
t=" ";
}
if (flo->stamp>0)
{
q=ui.left(2*flo->stamp);
}
else
{
q=" ";
}
if (flo->type & EMPTNODE)
{
printf("\n NO: %s%s[%d,%d]",q.data(),FlowChart::getNodeType(flo->type),flo->stamp,flo->id);
}
else if (flo->type & COMMENT_NO)
{
printf("\n NO: %s%s[%d,%d]",t.data(),FlowChart::getNodeType(flo->type),flo->stamp,flo->id);
}
else
{
printf("\n NO: %s[%d,%d]",t.data(),flo->stamp,flo->id);
}
}
}
void FlowChart::printFlowTree()
{
uint size=flowList.count();
for (uint j=0;j<size;j++)
{
printNode(flowList.at(j));
}
}
void FlowChart::colTextNodes()
{
QCString text;
FlowChart *flno;
bool found=FALSE;
for (uint j=0;j<flowList.count();j++)
{
FlowChart *flo=flowList.at(j);
if (flo->type&TEXT_NO)
{
text+=flo->text+'\n';
if (!found)
{
flno=flo;
}
if (found)
{
flno->text+=flo->text;
flowList.remove(flo);
if (j>0) j=j-1;
}
found=TRUE;
}
else
found=FALSE;
}
// find if..endif without text
// if..elseif without text
for (uint j=0;j<flowList.count()-1;j++)
{
FlowChart *flo=flowList.at(j);
int kind=flo->type;
if ( (kind & IFF) || (flo->type & ELSE_NO))
{
FlowChart *ftemp=flowList.at(j+1);
if (ftemp->type & EMPTY)
{
FlowChart *fNew = new FlowChart(TEXT_NO,"empty ",0);
fNew->stamp=flo->stamp;
flowList.insert(j+1,fNew);
}
}
}
}// colTextNode
QCString FlowChart::getNodeName(int n)
{
QCString node;
node.setNum(n);
return node.prepend("node");
}
void FlowChart::delFlowList()
{
ifcounter=0;
nodeCounter=0;
uint size=flowList.count();
for (uint j=0;j <size ;j++)
{
FlowChart *fll=flowList.at(j);
delete fll;
}
flowList.clear();
}
void FlowChart::alignCommentNode(FTextStream &t,QCString com)
{
uint max=0;
QCString s;
QStringList ql=QStringList::split("\n",com);
for (uint j=0;j<ql.count();j++)
{
s=(QCString)ql[j].utf8();
if (max<s.length()) max=s.length();
}
s=ql.last().utf8();
int diff=max-s.length();
QCString n(1);
if (diff>0)
{
n.fill(' ',2*diff);
n.append(".");
s+=n;
ql.remove(ql.last());
ql.append(s);
}
for (uint j=0;j<ql.count();j++)
{
s=(QCString)ql[j].utf8();
if (j<ql.count()-1)
{
s+="\n";
}
FlowChart::codify(t,s.data());
}
}
void FlowChart::buildCommentNodes(FTextStream & t)
{
uint size=flowList.count();
bool begin=false;
for (uint j=0;j < size-1 ;j++)
{
FlowChart *fll=flowList.at(j);
if (fll->type & COMMENT_NO)
{
FlowChart* to=flowList.at(j+1);
if (to->type & COMMENT_NO)
{
fll->label+="\n";
QCString temp=fll->label+to->label;
to->label=temp;
flowList.remove(j);
size--;
if (j>0) j--;
}
}
}// for
for (uint j=0;j <flowList.count() ;j++)
{
FlowChart *fll=flowList.at(j);
if (fll->type & BEGIN_NO)
{
begin = true;
continue;
}
if (fll->type & COMMENT_NO)
{
FlowChart* to;
if (!begin)
{
// comment between function/process .. begin is linked to start node
to=flowList.at(0);
}
else
{
if (j>0 && flowList.at(j-1)->line==fll->line)
to=flowList.at(j-1);
else
to=flowList.at(j+1);
}
t << getNodeName(fll->id);
t << "[shape=none, label=<\n";
t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
t << "<TR><TD BGCOLOR=\"";
t << flowCol.comment;
t << "\" > ";
FlowChart::alignCommentNode(t,fll->label);
t << " </TD></TR></TABLE>>];";
writeEdge(t,fll->id,to->id,2);
}
}// for
// delete comment nodes;
size=flowList.count();
for (uint j=0;j < size;j++)
{
FlowChart *fll=flowList.at(j);
if (fll->type & (COMMENT_NO | BEGIN_NO))
{
int diff=FLOWLEN-(j+1);
flowList.remove(j);
if ((fll->type & COMMENT_NO) && diff > 1)
flowList.at(j+1)->label=fll->label;
delete fll;
fll=0;
size--;
if (j>0) j--;
}
}// for;
}
void FlowChart::codify(FTextStream &t,const char *str)
{
if (str)
{
const char *p=str;
char c;
while (*p)
{
c=*p++;
switch(c)
{
case '<': t << "<"; break;
case '>': t << ">"; break;
case '&': t << "&"; break;
case '\'': t << "'"; break;
case '"': t << """; break;
case '\n': t <<"<BR ALIGN=\"LEFT\"/>"; break;
default: t << c; break;
}
}
}
}//codify
FlowChart::~FlowChart()
{
}
FlowChart::FlowChart(int typ,const char * t,const char* ex,const char* lab)
{
stamp=ifcounter;
if (typ & STARTL)
{
ifcounter++;
}
text=t;
exp=ex;
type=typ;
label=lab;
if (typ & (ELSE_NO | ELSIF_NO))
{
stamp--;
}
if (typ & (START_NO | END_NO | VARIABLE_NO))
{
stamp=0;
}
id=nodeCounter++;
}
void FlowChart::addFlowChart(int type,const char* text,const char* exp, const char *label)
{
static QRegExp reg("[;]");
static QRegExp reg1("[\"]");
if (!VhdlDocGen::getFlowMember()) return;
QCString typeString(text);
QCString expression(exp);
if (text)
{
typeString=typeString.replace(reg,"\n");
}
if (exp)
{
expression=expression.replace(reg1,"\\\"");
}
FlowChart *fl=new FlowChart(type,typeString.data(),expression.data(),label);
fl->line=vhdl::parser::VhdlParser::getLine();
if (type & (START_NO | VARIABLE_NO))
{
flowList.prepend(fl);
}
else
{
flowList.append(fl);
}
}
void FlowChart::moveToPrevLevel()
{
if (!VhdlDocGen::getFlowMember()) return;
ifcounter--;
}
QCString FlowChart::printPlantUmlNode(const FlowChart *flo,bool ca,bool endL)
{
QCString t;
QCString exp=flo->exp.stripWhiteSpace();
QCString text=flo->text.stripWhiteSpace();
switch (flo->type)
{
case START_NO: t=":"+text+"|"; break;
case IF_NO : t="\nif ("+exp+") then (yes)"; break;
case ELSIF_NO: t="\nelseif ("+exp+") then (yes)"; break;
case ELSE_NO: t="\nelse"; break;
case CASE_NO: t="\n:"+exp+";"; break;
case WHEN_NO: t="\n";
if (!ca) t+="else";
t+="if ("+exp+") then (yes)";
break;
case EXIT_NO: break;
case END_NO: if (text.contains(" function")==0) t="\n:"+text+";";
break;
case TEXT_NO: t="\n:"+text+"]"; break;
case ENDIF_NO: t="\nendif"; break;
case FOR_NO: t="\nwhile ("+exp+") is (yes)"; break;
case WHILE_NO: t="\nwhile ("+exp+") is (yes)"; break;
case END_LOOP: t="\nendwhile"; break;
case END_CASE: t="\nendif\n:end case;"; break;
case VARIABLE_NO:t="\n:"+text+";"; break;
case RETURN_NO: t="\n:"+text+";";
if (!endL) t+="\nstop";
break;
case LOOP_NO: t="\nwhile (infinite loop)"; break;
case NEXT_NO: break;
case EMPTY_NO: break;
case COMMENT_NO: t="\n note left \n "+flo->label+"\nend note \n"; break;
case BEGIN_NO: t="\n:begin;"; break;
default: assert(false); break;
}
return t;
}
void FlowChart::printUmlTree()
{
int caseCounter = 0;
int whenCounter = 0;
QCString qcs;
uint size=flowList.count();
bool endList;
for (uint j=0;j<size;j++)
{
endList=j==FLOWLEN;
FlowChart *flo=flowList.at(j);
if (flo->type==CASE_NO)
{
caseCounter++;
whenCounter=0;
}
if (flo->type==END_CASE)
{
caseCounter--;
}
bool ca = (caseCounter>0 && whenCounter==0);
qcs+=printPlantUmlNode(flo,ca,endList);
if (flo->type==WHEN_NO)
{
whenCounter++;
}
}
qcs+="\n";
QCString & htmlOutDir = Config_getString(HTML_OUTPUT);
QCString n=convertNameToFileName();
QCString tmp=htmlOutDir;
n=writePlantUMLSource(tmp,n,qcs);
generatePlantUMLOutput(n.data(),tmp.data(),PUML_SVG);
}
QCString FlowChart::convertNameToFileName()
{
static QRegExp exp ("[^][a-z_A-Z0-9]");
QCString temp,qcs;
const MemberDef* md=VhdlDocGen::getFlowMember();
// temp.sprintf("%p",md);
qcs=md->name();
#if 0
if (qcs.find(exp,0)>=0)
{
qcs.prepend("Z");
qcs=qcs.replace(exp,"_");
}
#endif
//QCString tt= qcs;VhdlDocGen::getRecordNumber();
return qcs;
}
const char* FlowChart::getNodeType(int c)
{
switch(c)
{
case IF_NO: return "if ";
case ELSIF_NO: return "elsif ";
case ELSE_NO: return "else ";
case CASE_NO: return "case ";
case WHEN_NO: return "when ";
case EXIT_NO: return "exit ";
case END_NO: return "end ";
case TEXT_NO: return "text ";
case START_NO: return "start ";
case ENDIF_NO: return "endif ";
case FOR_NO: return "for ";
case WHILE_NO: return "while ";
case END_LOOP: return "end_loop ";
case END_CASE: return "end_case ";
case VARIABLE_NO: return "variable_decl ";
case RETURN_NO: return "return ";
case LOOP_NO: return "infinite loop ";
case NEXT_NO: return "next ";
case COMMENT_NO: return "comment ";
case EMPTY_NO: return "empty ";
case BEGIN_NO: return "<begin> ";
default: return "--failure--";
}
}
void FlowChart::createSVG()
{
QCString qcs("/");
QCString ov = Config_getString(HTML_OUTPUT);
qcs+=FlowChart::convertNameToFileName()+".svg";
//const MemberDef *m=VhdlDocGen::getFlowMember();
//if (m)
// fprintf(stderr,"\n creating flowchart : %s %s in file %s \n",VhdlDocGen::trTypeString(m->getMemberSpecifiers()),m->name().data(),m->getFileDef()->name().data());
QCString dir=" -o \""+ov+qcs+"\"";
ov+="/flow_design.dot";
QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
if (portable_system("dot",vlargs)!=0)
{
err("could not create dot file");
}
}
void FlowChart::startDot(FTextStream &t)
{
t << " digraph G { \n";
t << "rankdir=TB \n";
t << "concentrate=true\n";
t << "stylesheet=\"doxygen.css\"\n";
}
void FlowChart::endDot(FTextStream &t)
{
t << " } \n";
}
void FlowChart::writeFlowChart()
{
// assert(VhdlDocGen::flowMember);
QCString ov = Config_getString(HTML_OUTPUT);
QCString fileName = ov+"/flow_design.dot";
QFile f(fileName);
FTextStream t(&f);
if (!f.open(IO_WriteOnly))
{
err("Cannot open file %s for writing\n",fileName.data());
return;
}
colTextNodes();
// buildCommentNodes(t);
#ifdef DEBUGFLOW
printFlowTree();
#endif
const MemberDef *p=VhdlDocGen::getFlowMember();
if (p->isStatic())
{
printUmlTree();
delFlowList();
f.close();
return;
}
startDot(t);
buildCommentNodes(t);
uint size=flowList.count();
for (uint j=0;j <size ;j++)
{
FlowChart *fll=flowList.at(j);
writeShape(t,fll);
}
writeFlowLinks(t);
FlowChart::endDot(t);
delFlowList();
f.close();
FlowChart::createSVG();
}// writeFlowChart
void FlowChart::writeShape(FTextStream &t,const FlowChart* fl)
{
if (fl->type & EEND) return;
QCString var;
if (fl->type & LOOP)
{
var=" loop";
}
else if (fl->type & IFF)
{
var=" then";
}
else
{
var="";
}
t<<getNodeName(fl->id).data();
#ifdef DEBUGFLOW
QCString qq(getNodeName(fl->id).data());
keyMap.insert(qq,fl->id);
#endif
bool dec=(fl->type & DECLN);
bool exit=(fl->type & EXITNEXT);
if (exit && !fl->exp.isEmpty())
{
dec=TRUE;
}
if (dec)
{
QCString exp=fl->exp;
alignText(exp);
t << " [shape=diamond,style=filled,color=\"";
t << flowCol.decisionNode;
t << "\",label=\" ";
QCString kl;
if (exit) kl=fl->text+" ";
if (fl->label)
{
kl+=fl->label+":"+exp+var;
}
else
{
kl+=exp+var;
}
FlowChart::alignCommentNode(t,kl);
t << "\"]\n";
}
else if (fl->type & ENDCL)
{
QCString val=fl->text;
t << " [shape=ellipse ,label=\""+val+"\"]\n";
}
else if (fl->type & STARTFIN)
{
QCString val=fl->text;
t << "[shape=box , style=rounded label=<\n";
t << "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" >\n ";
t << "<TR><TD BGCOLOR=\"";
t<< flowCol.startEndNode;
t<< "\"> ";
FlowChart::alignCommentNode(t,val);
t << " </TD></TR></TABLE>>];";
}
else
{
if (fl->text.isEmpty()) return;
bool var=(fl->type & FlowChart::VARIABLE_NO);
QCString q=fl->text;
if (exit)
{
q+=" "+fl->label;
}
int z=q.findRev("\n");
if (z==(int)q.length()-1)
{
q=q.remove(z,2);
}
t << "[shape=none margin=0.1, label=<\n";
t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
if (var)
{
t << "<TR><TD BGCOLOR=\"" << flowCol.varNode << "\" > ";
}
else
{
t << "<TR><TD BGCOLOR=\"" << flowCol.textNode << "\" > ";
}
FlowChart::alignCommentNode(t,q);
t << " </TD></TR></TABLE>>];";
}
}
void FlowChart::writeEdge(FTextStream &t,const FlowChart* fl_from,const FlowChart* fl_to,int i)
{
bool b=fl_from->type & STARTL;
bool c=fl_to->type & STARTL;
#ifdef DEBUGFLOW
QCString s1(getNodeName(fl_from->id).data());
QCString s2(getNodeName(fl_to->id).data());
QMap<QCString, int>::Iterator it = keyMap.find(s1);
QMap<QCString, int>::Iterator it1 = keyMap.find(s2);
// checks if the link is connected to a valid node
assert(it.key());
assert(it1.key());
#endif
writeEdge(t,fl_from->id,fl_to->id,i,b,c);
}
void FlowChart::writeEdge(FTextStream &t,int fl_from,int fl_to,int i,bool bFrom,bool bTo)
{
QCString label,col;
if (i==0)
{
col=flowCol.yesNodeLink;
label="yes";
}
else if (i==1)
{
col=flowCol.noNodeLink;
label="no";
}
else
{
col=flowCol.textNodeLink;
label="";
}
t << "edge [color=\""+col+"\",label=\""+label+"\"]\n";
t << getNodeName(fl_from).data();
if (bFrom) t << ":s";
t << "->";
t << getNodeName(fl_to).data();
if (bTo) t << ":n";
t << "\n";
}
void FlowChart::alignFuncProc( QCString & q,const ArgumentList* al,bool isFunc)
{
if (al==0) return;
ArgumentListIterator ali(*al);
int index=ali.count();
if (index==0) return;
int len=q.length()+VhdlDocGen::getFlowMember()->name().length();
QCString prev,temp;
prev.fill(' ',len+1);
Argument *arg;
q+="\n";
for (;(arg=ali.current());++ali)
{
QCString attl=arg->defval+" ";
attl+=arg->name+" ";
if (!isFunc)
{
attl+=arg->attrib+" ";
}
else
{
attl+=" in ";
}
attl+=arg->type;
if (--index) attl+=",\n"; else attl+="\n";
attl.prepend(prev.data());
temp+=attl;
}
q+=temp;
}
int FlowChart::findNextLoop(int index,int stamp)
{
for (uint j=index+1;j<flowList.count();j++)
{
FlowChart *flo=flowList.at(j);
if (flo->stamp==stamp)
{
continue;
}
if (flo->type&END_LOOP)
{
return j;
}
}
return flowList.count()-1;
}
int FlowChart::findPrevLoop(int index,int stamp,bool endif)
{
for (uint j=index;j>0;j--)
{
FlowChart *flo=flowList.at(j);
if (flo->type & LOOP)
{
if (flo->stamp==stamp && endif)
{
return j;
}
else
{
if (flo->stamp<stamp)
{
return j;
}
}
}
}
return flowList.count()-1;
}
int FlowChart::findLabel(int index,QCString &label)
{
for (uint j=index;j>0;j--)
{
FlowChart *flo=flowList.at(j);
if ((flo->type & LOOP) && !flo->label.isEmpty() && qstricmp(flo->label,label)==0)
{
return j;
}
}
err("could not find label: ",label.data());
return 0;
}
int FlowChart::findNode(int index,int stamp,int type)
{
for (uint j=index+1;j<flowList.count();j++)
{
FlowChart *flo=flowList.at(j);
if (flo->type==type && flo->stamp==stamp)
{
return j;
}
}
return 0;
}// findNode
int FlowChart::getNextNode(int index,int stamp)
{
for (uint j=index+1;j<flowList.count();j++)
{
FlowChart *flo=flowList.at(j);
int kind=flo->type;
int s=flo->stamp;
if (s>stamp)
{
continue;
}
if (kind & ENDIF_NO)
{
if (s<stamp && stamp>0)
{
stamp--;
continue;
}
}
if (kind & (ELSE_NO | ELSIF_NO))
{
if (s<stamp && stamp>0)
{
stamp--;
}
j=findNode(j,stamp,ENDIF_NO);
continue;
}
if (kind & WHEN_NO)
{
if (s<stamp && stamp>0)
{
stamp--;
}
return findNode(j,stamp-1,END_CASE);
}
return j;
}
return FLOWLEN;
}
int FlowChart::getNextIfLink(const FlowChart* fl,uint index)
{
int stamp=fl->stamp;
uint start = index+1;
int endifNode = findNode(start,stamp,ENDIF_NO);
int elseifNode = findNode(start,stamp,ELSIF_NO);
int elseNode = findNode(start,stamp,ELSE_NO);
assert(endifNode>-1);
if (elseifNode>0 && elseifNode<endifNode)
{
return elseifNode;
}
if (elseNode>0 && elseNode<endifNode)
{
return elseNode+1;
}
stamp=flowList.at(endifNode)->stamp;
return getNextNode(endifNode,stamp);
}
void FlowChart::writeFlowLinks(FTextStream &t)
{
uint size=flowList.count();
if (size<2) return;
// write start link
writeEdge(t,flowList.at(0),flowList.at(1),2);
for (uint j=0;j<size;j++)
{
FlowChart *fll=flowList.at(j);
int kind=fll->type;
int stamp=fll->stamp;
if (kind & EEND)
{
continue;
}
if (kind & IFF)
{
writeEdge(t,fll,flowList.at(j+1),0);
int z=getNextIfLink(fll,j);
// assert(z>-1);
writeEdge(t,fll,flowList.at(z),1);
}
else if (kind & LOOP_NO)
{
writeEdge(t,fll,flowList.at(j+1),2);
continue;
}
else if (kind & (CASE_NO | FOR_NO | WHILE_NO))
{
if (kind & CASE_NO)
{
writeEdge(t,fll,flowList.at(j+1),2);
continue;
}
else
{
writeEdge(t,fll,flowList.at(j+1),0);
}
kind=END_LOOP;
int z=findNode(j+1,fll->stamp,kind);
z=getNextNode(z,flowList.at(z)->stamp);
// assert(z>-1);
writeEdge(t,fll,flowList.at(z),1);
continue;
}
else if (kind & (TEXT_NO | VARIABLE_NO))
{
int z=getNextNode(j,stamp);
writeEdge(t,fll,flowList.at(z),2);
}
else if (kind & WHEN_NO)
{
// default value
if (qstricmp(fll->text.simplifyWhiteSpace().data(),"others")==0)
{
writeEdge(t,fll,flowList.at(j+1),2);
continue;
}
writeEdge(t,fll,flowList.at(j+1),0);
int u=findNode(j,stamp,WHEN_NO);
int v=findNode(j,stamp-1,END_CASE);
if (u>0 && u<v)
{
writeEdge(t,fll,flowList.at(u),1);
}
else
{
writeEdge(t,fll,flowList.at(v),1);
}
}
else if (kind & END_CASE)
{
int z=FlowChart::getNextNode(j,fll->stamp);
writeEdge(t,fll,flowList.at(z),2);
}
else if (kind & END_LOOP)
{
int z=findPrevLoop(j,fll->stamp,true);
writeEdge(t,fll,flowList.at(z),2);
}
else if (kind & RETURN_NO)
{
writeEdge(t,fll,FlowChart::flowList.at(size-1),2);
}
else if (kind & (EXIT_NO | NEXT_NO))
{
int z;
bool b = kind==NEXT_NO;
if (fll->exp)
{
writeEdge(t,fll,flowList.at(j+1),1);
}
if (!fll->label.isEmpty())
{
z=findLabel(j,fll->label);
if (b)
{
writeEdge(t,fll,flowList.at(z),0);
}
else
{
z=findNode(z,flowList.at(z)->stamp,END_LOOP);
z=getNextNode(z,flowList.at(z)->stamp);
writeEdge(t,fll,flowList.at(z),0);
}
continue;
}
else
{
if (b)
{
z=findPrevLoop(j,fll->stamp);
writeEdge(t,fll,flowList.at(z),0);
continue;
}
else
{
z =findNextLoop(j,fll->stamp-1);
}
z=getNextNode(z,flowList.at(z)->stamp);
}
writeEdge(t,fll,flowList.at(z),0);
}
} //for
} //writeFlowLinks
void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
const char *scopeName,
const QCString &input,
SrcLangExt, // lang
bool isExampleBlock,
const char *exampleName,
FileDef *fileDef,
int startLine,
int endLine,
bool inlineFragment,
MemberDef *memberDef,
bool showLineNumbers,
Definition *searchCtx,
bool collectXRefs
)
{
parseVhdlCode(codeOutIntf,
scopeName,
input,
isExampleBlock,
exampleName,
fileDef,
startLine,
endLine,
inlineFragment,
memberDef,
showLineNumbers,
searchCtx,
collectXRefs
);
}// class