/******************************************************************************
*
* Copyright (C) 1997-2008 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
* 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>
/* --------------------------------------------------------------- */
// local includes
#include "vhdlscanner.h"
#include "vhdlcode.h"
#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"
/* --------------------------------------------------------------- */
//#define theTranslator_vhdlType theTranslator->trVhdlType
#define theTranslator_vhdlType VhdlDocGen::getVhdlType
static QStringList qrl;
static int openGroups;
static ParserInterface *g_thisParser;
static const char * inputString;
static int inputPosition;
static int startComment = 0;
static QFile inputFile;
static QCString inbuf;
static Entry* global_root = 0;
static Entry* current_root = 0;
static Entry* current = 0;
static Entry* previous = 0;
static Entry* functionEntry = 0;
static Entry* lastEntity = 0;
static Entry* lastCompound = 0;
static int genPort = 0;
static QCString yyFileName;
static int iFuncLine = 1;
static bool g_inputFromFile ;
static bool g_lexInit = FALSE;
static int isBody=0;
static int isFunc=0;
static int yyLineNr = 1;
static char * g_buf = 0;
static uint g_bufSize = 0;
static int iTextCounter = 0;
static int iCounter = 0;
static int bropen = 0;
static int scantype = 0;
static int g_lastCommentContext = 0;
static bool docBlockAutoBrief;
static char docBlockTerm;
static int iDocLine = -1;
//#define YY_A_INTERACTIVE 1
#define YY_NEVER_INTERACTIVE 1
//-----------------------------------------------------------------------------
static void parserInit();
static void deleteSpecChars(char* str,char *buf);
static void handleCommentBlock(const QCString &doc,bool brief);
static void newEntry();
static void initEntry(Entry *e);
static void addSubEntry(Entry* root, Entry* e)
{
if (e==0 || root==0) return;
//if (isPrevDoc)
//{
// e->brief=prevDocEntry.brief;
// e->briefLine=prevDocEntry.briefLine;
// prevDocEntry.reset();
// isPrevDoc=FALSE;
//}
root->addSubEntry(e);
}
static void bufferClear()
{
int j;
for (j=0;j<iCounter+1;j++)
{
g_buf[j]=0;
}
iCounter=0;
}
static void addText (char *word, int llen)
{
if ((uint)(iCounter + llen) > g_bufSize)
{
char *pTmp = (char*)realloc(g_buf,iCounter+llen+2048);
if (pTmp)
{
g_buf = pTmp;
}
else
{
fprintf(stderr,"\n not enough memory for realloc\n");
return;
}
}
while (llen>0)
{
g_buf[iCounter]=*word++;
iCounter++;
llen--;
}
g_buf[iCounter]='\0';
}
static void getBufText(QCString& qc,int start)
{
while (start < iCounter)
{
qc+=(g_buf[start]);
start++;
}
}
static void lineCount()
{
for ( const char* c = yytext ; *c ; ++c )
{
yyLineNr += (*c == '\n') ;
}
}
static void deleteSpecChars(char* str,char *buf)
{
while (*str)
{
if ((*str == '\t') || (*str == '\n') || (*str == '\r') || (*str == ' '))
{
*str++;
}
else
{
*buf++ = *str++;
}
}
*buf='\0';
}
void getType(Entry* p,char* text)
{
QCString name(text);
name=name.stripWhiteSpace();
if (stricmp(name.data(),"signal" )==0)
{
p->spec=VhdlDocGen::SIGNAL;
}
else if (stricmp(name.data(),"type" )==0)
{
p->spec=VhdlDocGen::TYPE;
}
else if (stricmp(name.data(),"subtype" )==0)
{
p->spec=VhdlDocGen::SUBTYPE;
}
else if (stricmp(name.data(),"constant" )==0)
{
p->spec=VhdlDocGen::CONSTANT;
}
else if (stricmp(name.data(),"attribute" )==0)
{
p->spec=VhdlDocGen::ATTRIBUTE;
}
else if (stricmp(name.data(),"function" )==0)
{
p->spec=VhdlDocGen::FUNCTION;
}
else if (stricmp(name.data(),"procedure" )==0)
{
p->spec=VhdlDocGen::PROCEDURE;
}
else if (stricmp(name.data(),"units" )==0)
{
p->spec=VhdlDocGen::UNITS;
}
else if (name.contains("shared",false) && name.contains("variable",false))
{
p->spec=VhdlDocGen::SHAREDVARIABLE;
}
else if (stricmp(name.data(),"file" )==0)
{
p->spec=VhdlDocGen::VFILE;
}
else if (stricmp(name.data(),"group" )==0)
{
p->spec=VhdlDocGen::GROUP;
}
else if (stricmp(name.data(),"alias" )==0)
{
p->spec=VhdlDocGen::ALIAS;
}
else
{
err("wrong type");
}
p->section=Entry::VARIABLE_SEC;
}
//-------------------------------------------------------------------------
/*
* adds signals found in entities|records|units
*/
void addSignals(const char* str,int line, Entry *e,const char *comment=0)
{
//printf("===> addSignals (%s) comment='%s'\n",str,comment);
QList<QCString> ql;
QCString bufio;
ql.setAutoDelete(TRUE);
VhdlDocGen::getSigName(ql,str,bufio);
int count = ql.count();
QCString brief = current->brief;
QCString doc = current->doc;
Entry *tmpEntry = current;
current = new Entry;
initEntry(current);
handleCommentBlock(comment,TRUE);
if (!current->brief.isEmpty())
{
if (doc.isEmpty())
{
doc = brief;
}
else if (!brief.isEmpty())
{
doc = brief + "<p>" + doc;
}
brief = current->brief;
}
delete current;
current = tmpEntry;
current->brief.resize(0);
current->doc.resize(0);
if (genPort!=3) // not a unit
{
for (int k=1;k<count;k++)
{
//printf("adding '%s' '%s'\n",ql.at(0)->data(),ql.at(k)->data());
Entry *pTemp=new Entry;
initEntry(pTemp);
pTemp->startLine = line;
pTemp->bodyLine = line;
pTemp->name = ql.at(k)->data();
pTemp->section = Entry::VARIABLE_SEC;
pTemp->brief = brief;
pTemp->doc = doc;
pTemp->mGrpId = current->mGrpId; // copy member group id
QCString stSpec = ql.at(0)->data();
if (genPort==1) // found port
{
pTemp->spec = VhdlDocGen::PORT;
stSpec.stripPrefix(bufio.data());
stSpec=stSpec.stripWhiteSpace();
pTemp->args = stSpec;
pTemp->type = bufio;
addSubEntry(e,pTemp);
}
else if (genPort==2) // found record
{
pTemp->spec = VhdlDocGen::RECORD;
pTemp->type = stSpec;
pTemp->name.prepend(VhdlDocGen::getRecordNumber());
delete current;
current = new Entry(*pTemp); // make a deep copy of pTemp
newEntry(); // add it to lastCompound and make a new current
delete pTemp;
}
else
{
pTemp->spec = VhdlDocGen::GENERIC;
pTemp->type = stSpec;
addSubEntry(e,pTemp);
}
}// for
}
else // found a unit
{
Entry *pTemp=new Entry;
initEntry(pTemp);
QCString tt(str);
QStringList ql=QStringList::split("=",tt,FALSE);
pTemp->spec = VhdlDocGen::UNITS;
pTemp->section = Entry::VARIABLE_SEC;
pTemp->startLine = line;
pTemp->bodyLine = line;
pTemp->brief = brief; // adds brief description to the unit member
pTemp->doc = doc; // adds doc to the unit member
pTemp->type = ql[1];
pTemp->name = ql[0].stripWhiteSpace();
pTemp->name.prepend(VhdlDocGen::getRecordNumber());
delete current;
current = new Entry(*pTemp); // make a deep copy
newEntry(); // add it to lastCompound
delete pTemp;
}
}
/*
* this function parses a process prototype
* and adds the signal to the process
*/
static void parseProcessProto()
{
QStringList ql;
QCString qcs;
bool sem=FALSE;
//Entry* ppEntry=new Entry;
//ppEntry->fileName=yyFileName;
//processEntry=ppEntry;
QCString name;
scantype=0;
getBufText(qcs,0);
if (qcs.contains('(') != qcs.contains(')')) return;
VhdlDocGen::deleteAllChars(qcs,'\n');
VhdlDocGen::parseProcessProto(qcs,name,ql);
current->section=Entry::FUNCTION_SEC;
//current->stat=TRUE;
current->spec=VhdlDocGen::PROCESS;
current->startLine=iFuncLine;
current->bodyLine=iFuncLine;
current->fileName=yyFileName;
if (!name.isEmpty())
{
current->name=name.stripWhiteSpace();
}
else // found an anonymous process, so we add a generated name
{
current->name=VhdlDocGen::getProcessNumber();
}
current->args+=" ( ";
if (!ql.isEmpty())
{
QValueList<QString>::Iterator iter = ql.begin();
for ( ; iter != ql.end(); ++iter)
{
if (sem)
{
current->args+=',';
}
Argument *arg=new Argument;
arg->name=((QCString)*iter).stripWhiteSpace();
current->argList->append(arg);
current->args+=(QCString)*iter;
sem = TRUE;
}
}
current->args+=" ) ";
bufferClear();
}//parseProcessProto
/*
* parses a function|procedure protoype
*/
static void parseFunctionProto()
{
QCString name,ret,qcs,temp;
bool sem=FALSE;
QList<Argument> ql;
ql.setAutoDelete(TRUE);
getBufText(qcs,0);
if (qcs.contains('(') != qcs.contains(')'))
return; // function without a prototype
if (qcs.contains("function",FALSE)==0 && qcs.contains("procedure",FALSE)==0)
return;
qcs=qcs.stripWhiteSpace();
temp=qcs.lower();
if (temp.stripPrefix("impure"))
{
current->exception="impure";
qcs=qcs.remove(0,6);
}
else if (temp.stripPrefix("pure"))
{
current->exception="pure";
qcs=qcs.remove(0,4);
}
VhdlDocGen::parseFuncProto(qcs.data(),ql,name,ret);
//printf("parseFuncProto(%s)=%s,%s\n",qcs.data(),name.data(),ret.data());
VhdlDocGen::deleteAllChars(name,';');
current->name=name;
current->startLine=iFuncLine;
current->bodyLine=iFuncLine;
int count = ql.count();
current->args+" ( ";
for (int k=0;k<count;k++)
{
if (sem)
{
current->args+=",";
}
Argument *arg=new Argument;
Argument *hh=(Argument*)ql.at(k);
arg->name=hh->name;
arg->type=hh->type;
arg->defval=hh->defval;
arg->attrib=hh->attrib;
current->argList->append(arg);
current->args+=hh->name;
sem=TRUE;
}
current->args+" )";
if (!ret.isEmpty())
current->spec=VhdlDocGen::FUNCTION;
else
current->spec=VhdlDocGen::PROCEDURE;
current->section=Entry::FUNCTION_SEC;
current->type=ret;
//addSubEntry(ee,ppEntry);
if (lastCompound)
{
lastCompound->addSubEntry(current);
current = new Entry;
initEntry(current);
}
else
{
newEntry();
}
bufferClear();
}//parseFunctionProto
static Entry* getEntryAtLine(const Entry* ce,int line)
{
EntryListIterator eli(*ce->children());
Entry *found=0;
Entry *rt;
for (;(rt=eli.current());++eli)
{
if (rt->bodyLine==line)
{
found=rt;
} // if
if (!found)
{
found=getEntryAtLine(rt,line);
}
}
return found;
}// getEntryAtLine
//-------------------------------------------------------------------------
void parserInit()
{
iCounter=0;
iTextCounter=0;
yyLineNr=1;
current=0;
previous=0;
isFunc=0;
isBody=0;
scantype=0;
//pEntry=0;
//pp=0;
lastCompound=0;
lastEntity=0;
bropen=0;
openGroups=0;
iDocLine=-1;
//isPrevDoc=FALSE;
//prevDocEntry.reset();
qrl.clear();
if (!g_lexInit)
{
VhdlDocGen::init();
}
g_bufSize=inputFile.size()+1024;
if (g_buf==0) free(g_buf);
g_buf=(char*)(calloc(g_bufSize,sizeof(char)));
if (g_buf==0)
{
fprintf(stderr,"\n not enough memory");
return;
}
g_buf[g_bufSize-1]='\0';
}
bool VHDLLanguageScanner::needsPreprocessing(const QCString &)
{
return FALSE;
}
void VHDLLanguageScanner::resetCodeParserState()
{
}
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
static int yyread(char *buf,int max_size)
{
int c=0;
if (g_inputFromFile)
{
c = inputFile.readBlock(buf,max_size);
if (c==-1) yy_fatal_error("input in flex scanner failed");
}
else
{
while ( c < max_size && inputString[inputPosition] )
{
*buf = inputString[inputPosition++] ;
c++; buf++;
}
}
return c;
}
#if 0
/*
* adds a text line description [--#] to the the previous type
*/
static void addOneTextLine(QCString& ss )
{
Entry* pTemp=0;
if (current && current->bodyLine==yyLineNr)
pTemp=current;
//else if (pEntry && pEntry->bodyLine==yyLineNr)
// pTemp=pEntry;
else
pTemp=getEntryAtLine(current_root,yyLineNr) ;
if (pTemp)
{
ss=ss.stripWhiteSpace();
ss.stripPrefix("--!");
pTemp->brief=ss;
pTemp->briefLine=yyLineNr;
}
}
#endif
%}
/* start command character */
/* -------------- VHDL SECTION -----------------------------------*/
B [ \t]
CR [\r\n]
BR [ \t\n\r]
DIGIT [0-9]
LOWER_CASE_LETTER [a-z]
UPPER_CASE_LETTER [A-Z]
LETTER [a-zA-Z_0-9]
SPACE_CHARACTER [ \t]
SPECIAL_CHARACTER [#&'()*+,\-\./:;<=>_|]
OTHER_SPECIAL_CHARACTER [~!$ยง%?@\[\\\]^{}]
BASIC_GRAPHIC_CHARACTER {UPPER_CASE_LETTER}|{DIGIT}|{SPECIAL_CHARACTER}|{SPACE_CHARACTER}
GRAPHIC_CHARACTER {BASIC_GRAPHIC_CHARACTER}|{LOWER_CASE_LETTER}|{OTHER_SPECIAL_CHARACTER}
EXTENDED_CHARACTER [\\]{GRAPHIC_CHARACTER}*[\\]
NAME ({LETTER}[a-zA-Z0-9_.]*)|{EXTENDED_CHARACTER}
STRING_LITERAL \"{GRAPHIC_CHARACTER}*\"
FUNCNAME ([a-zA-Z"][*+\-_a-zA-Z0-9"\/=<>]*)|{EXTENDED_CHARACTER}
DIGITS [0-9]+|[0-9]+"."[0-9]+|[0-9]+"#"[0-9_a-fA-F\+\.]+"#"
COMMENT "--"[^\n]*
LABELID [a-z_A-Z][^\;]*";"({B}*{COMMENT})*
PROTO [ (]*
TEXTT "--"[^\/\@\*\#][^\n]*
PROC ("function"|"procedure")
ENDE ({BR}*("end"){BR}*{PROC}*{BR}*[;]{1})
ENDEFF ("if"|"case"|"loop"|"generate"){BR}*[;]
ENDE3 ({BR}*("end"){BR}*{PROC}*{BR}*{FUNCNAME}{BR}*[;])|{ENDE}
ENDFUNC {B}*"end"{BR}*{PROC}*{BR}*{FUNCNAME}{BR}*[;]
FUNCIMPURE "impure"|"pure"
FUNCPROC ^{B}*{FUNCIMPURE}*{BR}*("function"|"procedure"){B}*
ARCHITECTURE ("architecture"){BR}+{NAME}{BR}*("of")
/* Removed due to bug 538239
POST "postponed"
PROCESS ({BR}*{FUNCNAME}{B}*[:]{BR}*({POST}{BR}+)?("process"){BR}*{PROTO})|("process"){BR}*("("){BR}*{PROTO}|[^a-zA-Z]("process"){CR}|[^a-zA-Z]("process"){BR}+("is")
*/
PROCESS ({B}*{FUNCNAME}{B}*:{BR}*)?({B}*("postponed"){BR}+)?{B}*("process"){BR}*{PROTO}
ENDPROCESS ("end"){BR}*("postponed")*("process"){BR}*{FUNCNAME}*{BR}*[;]
LIBUSE ^{B}*("use"|"library"){BR}+
ENTITY ^{B}*("component"|"entity"|"package"){BR}+
PBODY ("package"){B}+("body"){BR}+{NAME}
SHARED ("shared"){BR}+("variable")
SIGTYPES ^{B}*({SHARED}|"alias"|"file"|"group"|"subtype"|"type"|"constant"|"attribute"|"signal"|"units"){BR}+
CONFIG ("configuration"){BR}+{NAME}{BR}*("of"){BR}+{NAME}{BR}+"is"
ALLTYPESMAP {B}*[_a-zA-ZA_Z0-9.() ]*{B}*
MAPCOMPONENT ({ALLTYPESMAP}{BR}*[:]{BR}*("component"|"configuration")*{ALLTYPESMAP}{BR}*{TEXTT}*{BR}*("port"|"generic"){BR}*("map"){BR}*("("){1})
MAPCOMPONENT1 ({ALLTYPESMAP}{BR}*[:]{BR}*("entity"){BR}*{ALLTYPESMAP}{BR}*("port"|"generic"){BR}*("map"){BR}*("("){1})
BRACEOPEN [(]{1}
BRACECLOSE [)]{1}
ALLID [^;()\t ]
/* VHDL 2001 */
ENDPROTECTED ("end"{BR}+"protected"{BR}+{NAME}{BR}*";")|("end"{BR}+"protected"{BR}*";")
ENDPROTECEDBODY "end"{BR}+"protected"{BR}+"body"{BR}+{NAME}
%option noyywrap
/* language parsing states */
%x Start
%x Comment
%x FindTypeName
%x ParseType
%x ParseRecord
%x ParseUnits
%x ParseProcess
%x ParseFunc
%x FindName
%x FindEntityName
%x FindGenPort
%x FindTypes
%x FindSigName
%x FindFuncName
%x FindBegin
%%
<Start>{ENDPROTECTED}|{ENDPROTECEDBODY} {
lineCount();
}
<Start>{CONFIG} { // found configuration
QCString qcs(vhdlscanYYtext);
current->name=VhdlDocGen::getIndexWord(qcs,1);
current->type=VhdlDocGen::getIndexWord(qcs,3);
current->startLine=yyLineNr;
current->bodyLine=yyLineNr;
current->section=Entry::VARIABLE_SEC;
current->spec=VhdlDocGen::CONFIG;
current->args="configuration";
newEntry();
BEGIN(Start);
}
<Start>{SIGTYPES} { // found type constant|type|attribute and so on..
bropen=0;
lineCount();
bufferClear();
//pEntry=current;
getType(current,yytext);
current->bodyLine=yyLineNr;
if (current->spec==VhdlDocGen::UNITS)
{
//addSubEntry(current,pEntry);
current->startLine=yyLineNr;
current->bodyLine=yyLineNr;
newEntry(); // adds the unit to the lastCompound
genPort=3;
BEGIN(ParseRecord);
}
else
{
BEGIN(FindTypeName);
}
}
<Start>{ARCHITECTURE} { //found architecure
lineCount();
bropen=0;
bufferClear();
isBody=0;
lastCompound = current;
QCString curName=VhdlDocGen::getIndexWord(yytext,1);
current->section=Entry::CLASS_SEC; //Entry::CLASS_SEC;
current->spec=VhdlDocGen::ARCHITECTURE;
current->protection=Private;
current->name=curName;
current->fileName=yyFileName;
current->startLine=yyLineNr;
current->bodyLine=yyLineNr;
//printf("-> Architecture at line %d\n",yyLineNr);
BEGIN(FindName);
}
<Start>{PROCESS} { //found process
lineCount();
iFuncLine=yyLineNr;
bropen=0;
//printf("--> Process: line=%d\n",yyLineNr);
bufferClear();
addText(yytext,yyleng);
QCString qcs(yytext);
if (qcs.contains('('))
{
bropen=1;
scantype=2;
BEGIN(ParseType);
}
else
{
// iFuncLine--;
parseProcessProto();
BEGIN(ParseProcess);
}
}
<Start>{LIBUSE}{BR}* { // found library or package
bropen=0;
bufferClear();
isBody=0;
QCString qcs=QCString(yytext);
// lowerString(qcs);
qcs=qcs.stripWhiteSpace();
if (stricmp(qcs.data(),"use")==0)
{
current->spec=VhdlDocGen::USE;
current->type="package";
}
else
{
current->spec=VhdlDocGen::LIBRARY;
current->type="library";
}
current->section=Entry::VARIABLE_SEC;
current->bodyLine=yyLineNr;
lineCount();
BEGIN(FindName);
}
<Start>{FUNCPROC} { // found a new function|procedure
lineCount();
iFuncLine=yyLineNr;
bropen=0;
bufferClear();
isFunc=1;
addText(yytext,yyleng);
BEGIN(FindFuncName);
}
<Start>{ENTITY} { // found entity|component|package
lineCount();
//printf("--> Entity at line %d\n",yyLineNr);
bropen=0;
bufferClear();
QCString word(yytext);
word=word.lower();
word=word.stripWhiteSpace();
if (strcmp(word.data(),"entity")==0)
{
isBody=0;
scantype=0;
lastCompound=0;
current->section=Entry::CLASS_SEC;
current->spec=VhdlDocGen::ENTITY;
current->protection=Public;
current->bodyLine=yyLineNr;
current->fileName=yyFileName;
lastEntity = current;
}
else if (strcmp(word.data(),"component")==0)
{
current->section=Entry::VARIABLE_SEC;
// current->stat=TRUE;
current->spec=VhdlDocGen::COMPONENT;
current->bodyLine=yyLineNr;
scantype=1;
}
else if (strcmp(word,"package")==0)
{
isBody=0;
scantype=0;
lastCompound = current;
current->section=Entry::CLASS_SEC;
current->spec=VhdlDocGen::PACKAGE;
current->protection=Package; //VhdlDocGen::PACKAGE;
current->bodyLine=yyLineNr;
current->fileName=yyFileName;
}
else
err("\n found wrong component at line [%d]",yyLineNr);
BEGIN(FindEntityName);
}
<Start>{MAPCOMPONENT}|{MAPCOMPONENT1} { // found component instantiation
// lineCount();
QCString type;
QCString tt(yytext);
QRegExp regg("[\\s:.()-]");
QStringList qsl=QStringList::split(regg,tt,false);
// consider upper/lower-case letters
QStringList qsltemp=QStringList::split(regg,tt.lower(),false);
int index=qsltemp.findIndex(QCString("entity"))+1;
index+=qsltemp.findIndex(QCString("component"))+1;
index+=qsltemp.findIndex(QCString("configuration"))+1;
int len=qsltemp.count();
current->spec=VhdlDocGen::COMPONENT_INST;
current->section=Entry::VARIABLE_SEC;
current->startLine=yyLineNr;
current->bodyLine=yyLineNr;
if (index!=0 && tt.contains(')')==0) // found component instantiation xxx: configuration/component/entity yyy
{
current->type=(QCString)qsl[len-3];
}
else if (index!=0 && tt.contains(')')) // found component instantiation xxx: entity www.yyy(zzz)
{
current->type=(QCString)qsl[len-4];
}
else
{
current->type=(QCString)qsl[1]; // found component instantiation xxx:yyy
}
current->name=QCString(qsl[0]);
if (lastCompound)
{
lastCompound->addSubEntry(current);
current = new Entry;
initEntry(current);
}
else
{
newEntry();
}
lineCount();
}
<Start>{CR}* {
lineCount();
addText(yytext,yyleng);
BEGIN(Start);
}
<ParseProcess>[^;()] {
// eat process body
lineCount();
BEGIN(ParseProcess);
}
<ParseProcess,ParseType>{ENDPROCESS} { // find end of process
lineCount();
current->endBodyLine=yyLineNr;
//printf("Process: start=%d end=%d\n",current->bodyLine,current->endBodyLine);
if (lastCompound)
{
lastCompound->addSubEntry(current);
current = new Entry;
initEntry(current);
}
else
{
newEntry();
}
BEGIN(Start);
}
<ParseUnits>{BR}* {
lineCount();
}
<ParseUnits>{B}*[a-z_][^\n;]* { // parse record|unit body
lineCount();
QCString zz(yytext);
addSignals(zz.data(),yyLineNr,current);
BEGIN(ParseUnits);
}
<FindName>{NAME} { // found entity|architecture|component name
lineCount();
QCString qcs(yytext);
qcs=qcs.stripWhiteSpace();
if (current->spec==VhdlDocGen::USE || current->spec==VhdlDocGen::LIBRARY)
{
int j=qcs.length();
int i=qcs.find(".");
if (i>0)
qcs=qcs.right(j-i-1);
i=qcs.find(".");
if (i>0)
qcs=qcs.left(i);
/*
-- Consider the case we have more than one entity in one file.Each entity has its own package/library
-- declaration. In this case package yyy will be added [with newEntry()] to architecture aaa !! instead to entity
-- bbb. We must place these constructs to current_root and the function mapLibPackage() will finish the rest.
-- package xxx;
-- entity aaa
-- ....
-- end entity aaa;
-- architecture aaa
-- ...
-- end architecture aaa;
-- package yyy;
-- entity bbb;
*/
current->name=qcs;
Entry *copy=new Entry(*current);
current->reset();
addSubEntry(current_root,copy); // insert into entry list with mapLibPackage()
}
else if (current->spec==VhdlDocGen::ARCHITECTURE)
{
//current->name+=qcs.lower();
current->name.prepend(qcs+"::");
if (lastEntity)
{
// inherit private inheritance relation between entity and architecture
if (!VhdlDocGen::foundInsertedComponent(current->name,lastEntity))
{
BaseInfo *bb=new BaseInfo(current->name,Private,Normal);
lastEntity->extends->append(bb);
}
}
}
else if (current->spec==VhdlDocGen::PACKAGE_BODY)
{
current->name+=qcs;
}
else
{
current->name+=qcs;
}
if (!(current->spec==VhdlDocGen::USE || current->spec==VhdlDocGen::LIBRARY))
newEntry();
BEGIN(Start);
}
<FindFuncName>{FUNCNAME} { // found name of a process|function|procedure
lineCount();
addText(yytext,yyleng);
BEGIN(ParseType);
}
<FindTypeName>{NAME}{BR}* {
lineCount();
current->name=QCString(yytext);
BEGIN(ParseType);
}
<ParseType>("is"){BR}+("protected"){BR}+("body") {lineCount(); BEGIN(Start); }
<ParseType>("is"){BR}+("protected"){BR}+ {
lineCount();
current->section=Entry::VARIABLE_SEC;
current->spec=VhdlDocGen::TYPE;
current->type="protected";
newEntry();
BEGIN(Start);
}
<ParseType>("is"){BR}*("record") { // find record
lineCount();
if (isFunc)
{
BEGIN(Start);
}
genPort=2;
current->section=Entry::VARIABLE_SEC;
current->spec=VhdlDocGen::RECORD;
addText(yytext,yyleng);
newEntry(); // adds the record to the last compound
BEGIN(ParseRecord);
}
<ParseRecord>{BR}* {
lineCount();
}
<ParseRecord>("end"){BR}*("record"){BR}*{LETTER}*{BR}*[;]|("end"){BR}*("units"){BR}*[;] {
lineCount();
genPort=0;
bufferClear();
BEGIN(Start);
}
<ParseRecord>[a-z_A-Z0-9][^\n;]*";"({B}*{COMMENT})* { // parse record body
lineCount();
QCString comment;
QCString zz(yytext);
VhdlDocGen::deleteAllChars(zz,';'); //delete ; in unit construct
if (zz.contains("--!"))
{
QStringList ql=QStringList::split("--!",zz,FALSE);
comment = ql[1];
zz = ql[0];
}
else if (zz.contains("--"))
{
QStringList ql=QStringList::split("--",zz,FALSE);
zz = ql[0];
}
initEntry(current);
addSignals(zz,yyLineNr,current,comment);
addText(yytext,yyleng);
BEGIN(ParseRecord);
}
<ParseType>{BR}+("is"){BR}+|{BR}+("is"){B}*"--" { // found a new function in an architecture ?
addText(yytext,yyleng);
lineCount();
QCString ttt;
bool bb=TRUE;
getBufText(ttt,0);
if (ttt.contains("--"))
{
unput('-');unput('-');
VhdlDocGen::deleteCharRev(ttt,'-');
VhdlDocGen::deleteCharRev(ttt,'-');
}
if (ttt.contains('(') != ttt.contains(')'))
{
bb=FALSE;
}
bool ss = VhdlDocGen::isFunctionProto(ttt);
//printf("VhdlDocGen::isFunctionProto(%s)=%d\n",ttt.data(),ss);
if (ss && bb)
{
bufferClear();
addText(ttt.data(),ttt.length());
functionEntry=0;
//eFuncBody=new Entry;
::parseFunctionProto();
#if 0
EntryListIterator eli(*eFuncBody->children());
Entry *rrt=eli.current();
if (current && (current->spec==VhdlDocGen::ARCHITECTURE && rrt))
{
Entry *ep=new Entry(*rrt);
addSubEntry(current,ep);
isBody=1;
}
if (rrt)
{
Entry *ef=VhdlDocGen::findFunction(current_root,rrt);
if (ef)
{
ef->bodyLine=iFuncLine;
functionEntry=ef;
}
else if ((current->spec==VhdlDocGen::PACKAGE_BODY))//VhdlDocGen::Package_Body))
{
Entry *ep=new Entry(*rrt);
addSubEntry(current,ep);
ep->bodyLine=iFuncLine;
functionEntry = ep;
}
}
delete eFuncBody;
eFuncBody=0;
#endif
}
bufferClear();
BEGIN(ParseType);
}
<ParseType>[^;()\t ] {
lineCount();
addText(yytext,yyleng);
BEGIN(ParseType);
}
<ParseType>{BRACEOPEN} {
lineCount();
bropen++;
addText(yytext,yyleng);
BEGIN(ParseType);
}
<ParseType>{BRACECLOSE} {
lineCount();
bropen--;
addText(yytext,yyleng);
if (bropen==0 && scantype==2) // process
{
::parseProcessProto();
BEGIN(ParseProcess);
} // if
else
{
BEGIN(ParseType);
}
}
<ParseType>{ENDE}|{ENDFUNC} { // found end of function|process
QRegExp regg("[\\s;]");
lineCount();
QCString tt(yytext);
tt=tt.lower();
QStringList ql=QStringList::split(regg,tt,FALSE);
int index=ql.findIndex(QCString("if"))+1;
index+=ql.findIndex(QCString("case"))+1;
index+=ql.findIndex(QCString("loop"))+1;
index+=ql.findIndex(QCString("generate"))+1;
bufferClear();
if (index==0)
{
if (isFunc)
{
Entry* pFunc=getEntryAtLine(current_root,iFuncLine);
if (pFunc && pFunc->section==Entry::FUNCTION_SEC)
{
pFunc->endBodyLine=yyLineNr;
}
isFunc=0;
BEGIN(Start);
}
}
}
<ParseFunc>[^;()] {
// eat process body
lineCount();
BEGIN(ParseFunc);
}
<ParseFunc>{ENDE3} {
QRegExp regg("[\\s;]");
lineCount();
QCString tt(yytext);
tt=tt.lower();
QStringList ql=QStringList::split(regg,tt,FALSE);
int index=ql.findIndex(QCString("if"))+1;
index+=ql.findIndex(QCString("case"))+1;
index+=ql.findIndex(QCString("loop"))+1;
index+=ql.findIndex(QCString("generate"))+1;
bufferClear();
if (index==0 && isFunc)
{
Entry* pFunc=getEntryAtLine(current_root,iFuncLine);
if (pFunc && pFunc->section==Entry::FUNCTION_SEC)
{
pFunc->endBodyLine=yyLineNr;
}
isFunc=0;
BEGIN(Start);
}
}
<ParseType>";" {
lineCount();
addText(yytext,yyleng);
if (bropen==0 && !(isFunc==1 && isBody==1) )
{
if (isFunc)
{
parseFunctionProto();
bufferClear();
if (lastCompound && lastCompound->spec==VhdlDocGen::PACKAGE)
{
isFunc=0;
BEGIN(Start);
}
else
{
BEGIN(ParseFunc);
}
}//if
else
{
QCString qcs;
getBufText(qcs,0);
qcs=qcs.stripWhiteSpace();
current->section=Entry::VARIABLE_SEC;
current->type+=qcs.data();
if ((current->spec==VhdlDocGen::SIGNAL ||
current->spec==VhdlDocGen::CONSTANT ||
current->spec==VhdlDocGen::TYPE ||
current->spec==VhdlDocGen::SUBTYPE ||
current->spec==VhdlDocGen::SHAREDVARIABLE
) &&
qcs.stripPrefix(","))
{
QList<QCString> ql;
ql.setAutoDelete(TRUE);
QCString buffer;
if (current->spec==VhdlDocGen::SUBTYPE ||
current->spec==VhdlDocGen::TYPE
)
{
VhdlDocGen::getSigTypeName(ql,qcs.data(),buffer);
}
else
{
VhdlDocGen::getSigName(ql,qcs.data(),buffer);
}
QCString doc = current->doc;
QCString brief = current->brief;
if (ql.count()>0)
{
for (uint j=1;j<ql.count();j++)
{
Entry *ppt = new Entry;
initEntry(ppt);
ppt->type += ql.at(0)->data();
ppt->section = Entry::VARIABLE_SEC;
ppt->spec = current->spec;
ppt->name += ql.at(j)->data();
ppt->bodyLine = yyLineNr;
ppt->startLine = yyLineNr;
ppt->brief = brief;
ppt->doc = doc;
if (lastCompound)
{
lastCompound->addSubEntry(ppt);
}
else
{
current->addSubEntry(ppt);
}
}
current->type=ql.at(0)->data();
ql.clear();
}
}
if (lastCompound)
{
lastCompound->addSubEntry(current);
current = new Entry;
initEntry(current);
}
else
{
newEntry();
}
isFunc=0;
bufferClear();
BEGIN(Start);
}
}
else
{
BEGIN(ParseType);
}
}
<ParseType>{TEXTT} {
lineCount();
BEGIN(ParseType);
}
<ParseType>{BR}* {
lineCount();
addText(yytext,yyleng);
BEGIN(ParseType);
}
<FindEntityName>{NAME} { // found name of an entity/architecture/package
lineCount();
QCString qcs(yytext);
qcs=qcs.stripWhiteSpace();
qcs=qcs.lower();
if (strcmp(qcs.data(),"body")==0) // found package body
{
current->spec=VhdlDocGen::PACKAGE_BODY;
current->section=Entry::CLASS_SEC;
current->protection=Protected;
current->name+=QCString("_");
isBody=1;
BEGIN(FindName);
}
else if (scantype==1) // found a component
{
QCString qq(yytext);
qq=qq.stripWhiteSpace();
//qq=qq.lower();
current->name=qq;
if (lastCompound)
{
if (lastCompound->spec==VhdlDocGen::PACKAGE)
{
if (!VhdlDocGen::foundInsertedComponent(qq,lastCompound))
{
BaseInfo *bb=new BaseInfo(qq,Private,Normal);
lastCompound->extends->append(bb);
}
}
lastCompound->addSubEntry(current);
current = new Entry;
initEntry(current);
}
else
{
newEntry();
}
BEGIN(Start);
}
else
{
QCString qq(yytext);
qq=qq.stripWhiteSpace();
current->name=qq;
newEntry();
//QCString qreal=QCString(yytext);
BEGIN(Start);
}
}
<Start>{B}*("generic"|"port"){BR}*[(]+ { // found generic|port in entity
QCString genp(yyleng+1);
deleteSpecChars(yytext,genp.data());
VhdlDocGen::deleteCharRev(genp,'(');
if (stricmp(genp.data(),"port" )==0)
{
genPort=1;
}
else
{
genPort=0;
}
bropen=1;
bufferClear();
lineCount();
BEGIN(FindSigName);
}
<FindSigName>{BRACECLOSE} {
lineCount();
bropen--;
addText(yytext,yyleng);
if (bropen==0)
{
bufferClear();
BEGIN(Start);
}
else
{
BEGIN(FindSigName);
}
}
<FindSigName>{LABELID} { // found signals in entity
QCString line(yytext);
// note that line can be something like:
// "var1, var2, var3 : in std_logic_vector(8 downto 0); --! Some comment"
// but also
// "var4 --! Some comment
// );"
// which marks the end of a port
// and also
// "-- Some comment
// var1 : in std_logic;"
//printf("--> labelid='%s'\n",line.data());
QStringList ql;
QCString comment;
int openCount=line.contains('(');
int closeCount=line.contains(')');
int semi = line.find(';');
int pos = line.find("--");
int pos1 = line.find("--!");
if (pos!=-1 && pos<pos1) // strip normal comment before special one
{
line = line.remove(pos,pos1-pos);
}
//printf("=> signal: line='%s'\n",line.data());
if (semi!=-1 && pos!=-1)
{
int eol = line.findRev('\n');
//printf("pos=%d eol=%d\n",pos,eol);
if (eol>=pos+2)
{
QRegExp re("\\n[\\s]*--!"); // comment continuation
comment=line.mid(pos+2,eol-pos-2);
//printf("Comment: '%s'\n",comment.data());
int p,l;
while ((p=re.match(comment,0,&l))!=-1)
{
comment.remove(p,l);
}
line=line.left(pos)+line.right(line.length()-eol);
}
else
{
comment=line.mid(pos+2);
line=line.left(pos);
}
comment.stripWhiteSpace();
// must subtract "(" and ")" in comments because they are used for determining the
// end of a port/generic construct
openCount-=comment.contains('(');
closeCount-=comment.contains(')');
if (!comment.stripPrefix("!")) // not a special comment
{
comment.resize(0);
}
}
else
{
//printf("no ; or --: pos=%d semi=%d\n",pos,semi);
}
int diff=openCount-closeCount;
if (diff<0)
{
VhdlDocGen::deleteCharRev(line,')');
}
if (scantype!=1) // not a component
{
addText(yytext,yyleng);
addSignals(line,yyLineNr,lastEntity,comment);
}
lineCount();
if ((bropen+openCount-closeCount)==0)
{
bufferClear();
BEGIN(Start);
}
}
<FindSigName>{BRACEOPEN} {
lineCount();
bropen++;
addText(yytext,yyleng);
}
<FindSigName>{CR} {
lineCount();
addText(yytext,yyleng);
//BEGIN(FindSigName);
}
<*>^{B}*("for ")[^;]* {
//printf("\n found for[%s] [%d]",yytext,yyLineNr);
lineCount();
}
<*>{DIGITS} { // found digit
addText(yytext,yyleng);
lineCount();
}
<*>{STRING_LITERAL} {
// Make sure string literals get transfered to the output
// We have to match these because the comment characters (--)
// can exist inside a string literal.
// We shouldn't have to call lineCount because newlines
// are not allowed inside string literals
addText(yytext,yyleng);
}
/*
<*>{BR}*"--!"{B}*"@}" { // end group
if (current)
{
Entry *pg=new Entry;
addSubEntry(current,pg);
pg->startLine=yyLineNr;
pg->name="endgroup";
}
lineCount();
}
<*>{BR}*"--!"{B}*"@{" { // start group
if (current)
{
Entry *pg=new Entry;
addSubEntry(current,pg);
pg->startLine=yyLineNr;
pg->name="startgroup";
}
lineCount();
}
*/
<*>{BR}*"--!"[^{}\n][^\n]*\n/{B}*"--!" { // multi line comment
if (iDocLine==-1) iDocLine=yyLineNr;
// signal clk :in std_logic; --!@brief global clock
// --!@brief global reset
// signal reset:in std_logic;
// these two comments are detected as a multi line comment
QCString qc(yytext);
int len=qc.contains('\n')+yyLineNr-1;
if (YY_START!=Comment) // Start of the comment block
{
bufferClear();
iTextCounter=0;
startComment=yyLineNr;
g_lastCommentContext=YY_START;
}
Entry* pTemp=getEntryAtLine(current_root,len);
if (pTemp)
{ // found one line comment, add it to the entry on this line
pTemp->briefLine=yyLineNr;
pTemp->brief+=yytext;
VhdlDocGen::prepareComment(pTemp->brief);
}
else
{
addText(yytext,yyleng);
}
lineCount();
BEGIN(Comment);
}
<Comment>^{B}*"--!"[^\n]* {
if (iDocLine==-1) iDocLine=yyLineNr;
addText(yytext,yyleng);
lineCount();
}
<Comment>.|\n {
// found end of comment block
QCString qcs;
getBufText(qcs,iTextCounter);
VhdlDocGen::prepareComment(qcs);
handleCommentBlock(qcs,FALSE);
bufferClear();
unput(*yytext);
BEGIN(g_lastCommentContext);
}
<*>"--!"[^\n]* { // one line comment
if (iDocLine==-1) iDocLine=yyLineNr;
QCString qcs(yytext);
int j=qcs.find("--!");
qcs=qcs.right(qcs.length()-3-j);
//printf("--> handleCommentBlock line %d\n",yyLineNr);
Entry* pTemp=getEntryAtLine(current_root,yyLineNr);
if (pTemp)
{
pTemp->briefLine=yyLineNr;
pTemp->brief+=qcs;
iDocLine=-1;
}
else
{
handleCommentBlock(qcs,TRUE);
}
//printf("--> end: handleCommentBlock line %d\n",yyLineNr);
bufferClear();
}
<*>{COMMENT} {
}
<*>\n {
lineCount();
addText(yytext,yyleng);
// printf("\n new-line [%d]",yyLineNr);
BEGIN(Start);
}
<*>{NAME} {
addText(yytext,yyleng);
lineCount();
}
<*>{B}* {
addText(yytext,yyleng);
lineCount();
}
<*>. {
addText(yytext,yyleng);
lineCount();
}
%%
static void initEntry(Entry *e)
{
e->fileName = yyFileName;
initGroupInfo(e);
}
static void newEntry()
{
// Add only enties/architectures/packages to root
// and signals to classes where they were found
// ENTITY dlatch_93 IS -- VHDL'93-Syntax !!!
// PORT (d, clk : IN bit;
// q, qbar : OUT bit);
// GROUP path IS (SIGNAL, SIGNAL);
// GROUP d_to_q : path (d, q);
// ATTRIBUTE propagation : time;
// END dlatch_93;
if (current->spec==VhdlDocGen::ENTITY ||
current->spec==VhdlDocGen::PACKAGE ||
current->spec==VhdlDocGen::ARCHITECTURE ||
current->spec==VhdlDocGen::PACKAGE_BODY)
{
current_root->addSubEntry(current);
}
else
{
if (lastCompound)
{
lastCompound->addSubEntry(current);
}
else
{
if (lastEntity)
{
lastEntity->addSubEntry(current);
}
else
{
current_root->addSubEntry(current); // should not happen!
}
}
}
previous = current;
current = new Entry ;
initEntry(current);
}
static void handleCommentBlock(const QCString &doc,bool brief)
{
int position=0;
bool needsEntry=FALSE;
Protection protection=Public;
int lineNr = iDocLine;
if (brief)
current->briefLine = iDocLine;
else
current->docLine = iDocLine;
//printf("parseCommentBlock %p [%s]\n",current,doc.data());
while (parseCommentBlock(
g_thisParser,
current,
doc, // text
yyFileName, // file
lineNr, // line of block start
brief,
docBlockAutoBrief,
FALSE,
protection,
position,
needsEntry
)
)
{
//printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
if (needsEntry) newEntry();
}
if (needsEntry)
{
newEntry();
}
if (docBlockTerm)
{
unput(docBlockTerm);
docBlockTerm=0;
}
iDocLine=-1;
}
#if 0
/*!
* adds grouping to the entries
*/
static void mergeGrouping(const Entry* ce,int)
{
EntryListIterator eli(*ce->children());
Entry *rt;
for (;(rt=eli.current());++eli)
{
if (rt->section==Entry::GROUPDOC_SEC)
{
if (openGroups)
{
QCString tt=(QCString)qrl.last();
if (!tt.isEmpty())
{
rt->groups->append(new Grouping(tt.data(),Grouping::GROUPING_LOWEST));
}
}
qrl.append(rt->name);
}
if ((strcmp(rt->name.data(),"endgroup")==0) && !qrl.isEmpty())
{
qrl.remove((QCString)qrl.last());
openGroups--;
}
if ((strcmp(rt->name.data(),"startgroup")==0))
{
openGroups++;
}
if (rt->section!=Entry::GROUPDOC_SEC && openGroups && !qrl.isEmpty())
{
rt->groups->append(new Grouping(qrl.last().data(),Grouping::GROUPING_LOWEST));
}
mergeGrouping(rt,openGroups);
}
}
#endif
/*
* adds the library|use statements to the next class (entity|package|architecture|package body
* library ieee
* entity xxx
* .....
* library
* package
* enity zzz
* .....
* and so on..
*/
void mapLibPackage(const Entry* ce)
{
Entry *lastComp=0;
while (TRUE)
{
bool found = FALSE;
Entry *rt=0;
//const QList<Entry> *epp=ce->children();
EntryListIterator eli(*ce->children());
EntryListIterator eli1=eli;
for (;(rt=eli.current()),eli1=eli;++eli)
{
if (rt->spec==VhdlDocGen::LIBRARY || rt->spec==VhdlDocGen::USE)
// top level library or use statement
{
Entry *temp=0;
for (;(temp=eli1.current());++eli1) // find next entity
{
if (temp->spec==VhdlDocGen::ENTITY || temp->spec==VhdlDocGen::PACKAGE || temp->spec==VhdlDocGen::ARCHITECTURE || temp->spec==VhdlDocGen::PACKAGE_BODY)
{
Entry *ee=new Entry(*rt); //append a copy to entries sublist
temp->addSubEntry(ee);
found=TRUE;
rt->spec=-1; //nullify entry
rt->section=0;
lastComp=temp;
break;
}
}//for
if (lastComp && rt->spec!=-1)
{
Entry *ee=new Entry(*rt); //append a copy to entries sublist
lastComp->addSubEntry(ee);
found=TRUE;
rt->spec=-1; //nullify entry
rt->section=0;
}
}//if
}//for
if (!found) // nothing left to do
{
return;
}
}//while
}//MapLib
#if 0
/*!
* merges a brief descriptions to the next entry
*/
void mergeBrief(const Entry* ce)
{
EntryListIterator eli(*ce->children());
Entry *rt;
for (;(rt=eli.current());++eli)
{
if (found && (!eMerge.brief.isEmpty() || !eMerge.doc.isEmpty()))
{
rt->doc+=eMerge.doc.data();
rt->docLine=eMerge.docLine;
rt->brief+=eMerge.brief.data();
rt->briefLine=eMerge.briefLine;
found=FALSE;
}
if ((strcmp(rt->name.data(),"string")==0))
{
eMerge.reset();
eMerge.doc+=rt->doc.data();
eMerge.docLine=rt->docLine;
eMerge.brief+=rt->brief.data();
eMerge.briefLine=rt->briefLine;
found=TRUE;
}
MergeBrief(rt);
}
}
#endif
void vhdlscanFreeScanner()
{
#if defined(YY_FLEX_SUBMINOR_VERSION)
if (g_lexInit)
{
vhdlscanYYlex_destroy();
}
if (g_buf)
{
free(g_buf);
}
g_buf=0;
#endif
}
void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root)
{
inputFile.setName(fileName);
//uint jfile=inputFile.size();
::parserInit();
yyFileName=QCString(fileName);
groupEnterFile(fileName,yyLineNr);
g_thisParser = this;
g_inputFromFile = FALSE;
inputPosition = 0;
assert(root!=0);
inputString=fileBuf;
current_root = root;
global_root = root;
current=new Entry;
initEntry(current);
//current_root->name=QCString("XXX"); // dummy name for root
if (!inputFile.open(IO_ReadOnly))
{
err("\n\n could not open file: %s !!\n\n",yyFileName.data());
return ;
}
if (g_lexInit)
{
vhdlscanYYrestart(vhdlscanYYin);
unput(' ');
BEGIN(Start);
}
vhdlscanYYlex();
g_lexInit=TRUE;
free(g_buf);
g_buf=0;
delete current;
current=0;
groupLeaveFile(yyFileName,yyLineNr);
inputFile.close();
//mergeBrief(current_root);
//mergeGrouping(current_root,0);
mapLibPackage(current_root);
}
void VHDLLanguageScanner::parsePrototype(const char *text)
{
// will be called when a \fn command is found in a comment block
QCString ss,ret;
bool sem=FALSE;
bool func=FALSE;
QList<Argument> qs;
qs.setAutoDelete(TRUE);
VhdlDocGen::parseFuncProto(text,qs,ss,ret,TRUE);
int count=qs.count();
if (stricmp(ret.data(),"function")==0)
{
func=TRUE;
}
if (count<1 && !func)
{
return;
}
Entry *pp = new Entry;
initEntry(pp);
pp->name=ss.stripWhiteSpace();
pp->args+='(';
for (int j=0;j<count;j++)
{
if (sem)
{
pp->args+=',';
}
Argument *ars=(Argument*)(qs.at(j));
Argument *arg=new Argument;
arg->attrib = ars->attrib;
arg->name = ars->name;
arg->type = ars->type;
pp->args+=ars->name.data();
pp->args+=" ";
pp->args+=ars->type.data();
pp->argList->append(arg);
sem=TRUE;
}
pp->args+=')';
if (!ret.isEmpty())
pp->spec=VhdlDocGen::FUNCTION;
else
pp->spec=VhdlDocGen::PROCEDURE;
if (pp->section == Entry::MEMBERDOC_SEC && pp->args.isEmpty())
pp->section = Entry::VARIABLEDOC_SEC;
pp->type=ret;
current_root->addSubEntry(pp);
}
void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
const char *scopeName,
const QCString &input,
bool isExampleBlock,
const char *exampleName,
FileDef *fileDef,
int startLine,
int endLine,
bool inlineFragment,
MemberDef *memberDef
)
{
::parseVhdlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,fileDef,startLine,endLine,inlineFragment,memberDef);
}