1 /******************************************************************************
3 * Copyright (C) 2014 by M. Kreis
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
14 #include <qfileinfo.h>
15 #include <qstringlist.h>
16 #include "vhdljjparser.h"
18 #include "vhdldocgen.h"
24 #include "commentscan.h"
26 #include "definition.h"
27 #include "searchindex.h"
28 #include "outputlist.h"
29 #include "arguments.h"
31 #include "VhdlParserIF.h"
33 using namespace vhdl::parser;
36 static ParserInterface *g_thisParser;
38 static QCString yyFileName;
39 static int yyLineNr = 1;
40 static int* lineParse;
41 static int iDocLine = -1;
42 static QCString inputString;
44 static Entry* previous = 0;
48 ParserInterface *g_thisParser;
56 bool g_lexInit = FALSE;
58 int g_lastCommentContext = 0;
59 bool docBlockAutoBrief;
65 //-------------------------------------------------------
67 static Entry* oldEntry;
68 static bool varr=FALSE;
69 static QCString varName;
71 static QList<Entry> instFiles;
72 static QList<Entry> libUse;
73 static QList<Entry> lineEntry;
75 Entry* VhdlParser::currentCompound=0;
76 Entry* VhdlParser::tempEntry=0;
77 Entry* VhdlParser::lastEntity=0 ;
78 Entry* VhdlParser::lastCompound=0 ;
79 Entry* VhdlParser::current=0;
80 Entry* VhdlParser::current_root = 0;
81 QCString VhdlParser::compSpec;
82 QCString VhdlParser::currName;
83 QCString VhdlParser::confName;
84 QCString VhdlParser::genLabels;
85 QCString VhdlParser::lab;
86 QCString VhdlParser::forL;
88 int VhdlParser::param_sec = 0;
89 int VhdlParser::parse_sec=0;
90 int VhdlParser::currP=0;
91 int VhdlParser::levelCounter;
93 static QList<VhdlConfNode> configL;
103 static bool doxComment=FALSE; // doxygen comment ?
104 static QCString strComment;
107 bool checkMultiComment(QCString& qcs,int line);
108 QList<Entry>* getEntryAtLine(const Entry* ce,int line);
110 //-------------------------------------
112 QList<VhdlConfNode>& getVhdlConfiguration() { return configL; }
113 QList<Entry>& getVhdlInstList() { return instFiles; }
115 Entry* getVhdlCompound()
117 if (VhdlParser::lastEntity) return VhdlParser::lastEntity;
118 if (VhdlParser::lastCompound) return VhdlParser::lastCompound;
122 void startCodeBlock(int index)
124 int ll=strComment.length();
125 iCodeLen=inputString.findRev(strComment.data())+ll;
126 // fprintf(stderr,"\n startin code..%d %d %d\n",iCodeLen,num_chars,ll);
129 int len=strComment.length();
130 QCString name=strComment.right(len-index);//
131 name=VhdlDocGen::getIndexWord(name.data(),1);
133 gBlock.name="misc"+ VhdlDocGen::getRecordNumber();
137 //int li=strComment.contains('\n');
139 gBlock.startLine=yyLineNr;
140 gBlock.bodyLine=yyLineNr;
142 strComment=strComment.left(index);
143 VhdlDocGen::prepareComment(strComment);
144 gBlock.brief+=strComment;
147 void makeInlineDoc(int endCode)
149 int len=endCode-iCodeLen;
150 QCString par=inputString.mid(iCodeLen,len);
151 //fprintf(stderr,"\n inline code: \n<%s>",par.data());
153 gBlock.inbodyDocs=par;
154 gBlock.section=Entry::VARIABLE_SEC;
155 gBlock.spec=VhdlDocGen::MISCELLANEOUS;
156 gBlock.fileName = yyFileName;
157 gBlock.endBodyLine=yyLineNr-1;
158 gBlock.lang=SrcLangExt_VHDL;
159 Entry *temp=new Entry(gBlock);
160 Entry* compound=getVhdlCompound();
164 compound->addSubEntry(temp);
168 temp->type="misc"; // global code like library ieee...
169 VhdlParser::current_root->addSubEntry(temp);
171 strComment.resize(0);
176 bool isConstraintFile(const QCString &fileName,const QCString &ext)
178 return fileName.right(ext.length())==ext;
182 void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root,
188 if (strlen(fileName)==0)
193 yyFileName+=fileName;
195 bool xilinx_ucf=isConstraintFile(yyFileName,".ucf");
196 bool altera_qsf=isConstraintFile(yyFileName,".qsf");
198 // support XILINX(ucf) and ALTERA (qsf) file
202 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,FALSE);
207 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,TRUE);
210 libUse.setAutoDelete(true);
212 VhdlParser::current_root=root;
213 VhdlParser::lastCompound=0;
214 VhdlParser::lastEntity=0;
215 VhdlParser::currentCompound=0;
216 VhdlParser::lastEntity=0;
217 VhdlParser::current=new Entry();
218 VhdlParser::initEntry(VhdlParser::current);
219 groupEnterFile(fileName,yyLineNr);
220 lineParse=new int[200];
221 VhdlParserIF::parseVhdlfile(fileBuf,inLine);
223 delete VhdlParser::current;
224 VhdlParser::current=0;
227 VhdlParser::mapLibPackage(root);
230 yyFileName.resize(0);
232 VhdlDocGen::resetCodeVhdlParserState();
235 void VhdlParser::lineCount(){ yyLineNr++; }
237 void VhdlParser::lineCount(const char* text)
239 for (const char* c=text ; *c ; ++c )
241 yyLineNr += (*c == '\n') ;
245 void isVhdlDocPending()
247 if (!str_doc.pending) return;
249 str_doc.pending=FALSE;
250 oldEntry=0; // prevents endless recursion
251 iDocLine=str_doc.iDocLine;
252 VhdlParser::handleCommentBlock(str_doc.doc,str_doc.brief);
256 void VhdlParser::initEntry(Entry *e)
258 e->fileName = yyFileName;
259 e->lang = SrcLangExt_VHDL;
264 void VhdlParser::newEntry()
266 if (current->spec==VhdlDocGen::ENTITY ||
267 current->spec==VhdlDocGen::PACKAGE ||
268 current->spec==VhdlDocGen::ARCHITECTURE ||
269 current->spec==VhdlDocGen::PACKAGE_BODY)
271 current_root->addSubEntry(current);
277 lastCompound->addSubEntry(current);
283 lastEntity->addSubEntry(current);
287 current_root->addSubEntry(current);
292 current = new Entry ;
296 bool checkInlineCode(QCString & doc)
298 int index=doc.find("\\code");
303 startCodeBlock(index);
310 void VhdlParser::handleFlowComment(const char* doc)
313 if (VhdlDocGen::getFlowMember())
316 qcs=qcs.stripWhiteSpace();
317 qcs.stripPrefix("--#");
318 FlowChart::addFlowChart(FlowChart::COMMENT_NO,0,0,qcs.data());
322 void VhdlParser::handleCommentBlock(const char* doc1,bool brief)
327 if (doc.isEmpty()) return;
329 if (checkMultiComment(doc,yyLineNr))
335 isIn=checkInlineCode(doc);
336 bool isEndCode=doc.contains("\\endcode");
340 int end=inputString.find(doc.data(),iCodeLen);
342 strComment.resize(0);
352 VhdlDocGen::prepareComment(doc);
354 bool needsEntry=FALSE;
355 Protection protection=Public;
356 int lineNr = iDocLine;
358 if (oldEntry==current)
360 //printf("\n find pending message < %s > at line: %d \n ",doc.data(),iDocLine);
362 str_doc.iDocLine=iDocLine;
364 str_doc.pending=TRUE;
372 current->briefLine = yyLineNr;
376 current->docLine = yyLineNr;
378 // printf("parseCommentBlock file<%s>\n [%s]\n",yyFileName.data(),doc.data());
379 while (parseCommentBlock(
384 lineNr, // line of block start
394 //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
395 if (needsEntry) newEntry();
402 current->name=varName;
403 current->section=Entry::VARIABLEDOC_SEC;
411 void VHDLLanguageScanner::parsePrototype(const char *text)
417 void VhdlParser::addCompInst(char *n, char* instName, char* comp,int iLine)
419 current->spec=VhdlDocGen::INSTANTIATION;
420 current->section=Entry::VARIABLE_SEC;
421 current->startLine=iLine;
422 current->bodyLine=iLine;
423 current->type=instName; // foo:instname e.g proto or work. proto(ttt)
424 current->exception=genLabels.lower(); // |arch|label1:label2...
425 current->name=n; // foo
426 current->args=lastCompound->name; // architecture name
427 current->includeName=comp; // component/enity/configuration
428 int u=genLabels.find("|",1);
431 current->write=genLabels.right(genLabels.length()-u);
432 current->read=genLabels.left(u);
434 //printf (" \n genlable: [%s] inst: [%s] name: [%s] %d\n",n,instName,comp,iLine);
438 current->args=lastCompound->name;
439 if (true) // !findInstant(current->type))
442 instFiles.append(new Entry(*current));
445 Entry *temp=current; // hold current pointer (temp=oldEntry)
446 current=new Entry; // (oldEntry != current)
455 void VhdlParser::addVhdlType(const char *n,int startLine,int section,
456 uint64 spec,const char* args,const char* type,Protection prot)
458 static QRegExp reg("[\\s]");
460 if (isFuncProcProced() || VhdlDocGen::getFlowMember()) return;
462 if (parse_sec==GEN_SEC)
464 spec= VhdlDocGen::GENERIC;
467 QStringList ql=QStringList::split(",",name,FALSE);
469 for (uint u=0;u<ql.count();u++)
471 current->name=ql[u].utf8();
472 current->startLine=startLine;
473 current->bodyLine=startLine;
474 current->section=section;
476 current->fileName=yyFileName;
477 if (current->args.isEmpty())
482 current->protection=prot;
484 if (!lastCompound && (section==Entry::VARIABLE_SEC) && (spec == VhdlDocGen::USE || spec == VhdlDocGen::LIBRARY) )
486 libUse.append(new Entry(*current));
493 void VhdlParser::createFunction(const char *imp,uint64 spec,const char *fn)
495 QCString impure(imp);
498 current->section=Entry::FUNCTION_SEC;
500 if (impure=="impure" || impure=="pure")
502 current->exception=impure;
505 if (parse_sec==GEN_SEC)
507 current->spec= VhdlDocGen::GENERIC;
508 current->section=Entry::FUNCTION_SEC;
511 if (currP==VhdlDocGen::PROCEDURE)
513 current->name=impure;
514 current->exception="";
521 if (spec==VhdlDocGen::PROCESS)
524 current->name=impure;
525 VhdlDocGen::deleteAllChars(current->args,' ');
526 if (!fname.isEmpty())
528 QStringList q1=QStringList::split(",",fname);
529 for (uint ii=0;ii<q1.count();ii++)
531 Argument *arg=new Argument;
532 arg->name=q1[ii].utf8();
533 current->argList->append(arg);
541 bool VhdlParser::isFuncProcProced()
543 if (currP==VhdlDocGen::FUNCTION ||
544 currP==VhdlDocGen::PROCEDURE ||
545 currP==VhdlDocGen::PROCESS
553 void VhdlParser::pushLabel( QCString &label,QCString & val)
559 QCString VhdlParser::popLabel(QCString & q)
562 int i=q.findRev("|");
568 void VhdlParser::addConfigureNode(const char* a,const char*b, bool,bool isLeaf,bool inlineConf)
571 QCString ent,arch,lab;
572 QCString l=genLabels;
574 // lab = VhdlDocGen::parseForConfig(ent,arch);
579 // lab=VhdlDocGen::parseForBinding(ent,arch);
583 if (!configL.isEmpty())
585 VhdlConfNode* vc=configL.getLast();
591 else if (level<levelCounter)
598 else if (level>levelCounter)
610 confName=lastCompound->name;
613 //fprintf(stderr,"\n[%s %d %d]\n",forL.data(),levelCounter,level);
614 co=new VhdlConfNode(a,b,confName.lower().data(),forL.lower().data(),isLeaf);
618 co->isInlineConf=TRUE;
626 void VhdlParser::addProto(const char *s1,const char *s2,const char *s3,
627 const char *s4,const char *s5,const char *s6)
629 (void)s5; // avoid unused warning
630 static QRegExp reg("[\\s]");
632 QStringList ql=QStringList::split(",",name,FALSE);
634 for (uint u=0;u<ql.count();u++)
636 Argument *arg=new Argument;
637 arg->name=ql[u].utf8();
648 if (parse_sec==GEN_SEC && param_sec==0)
653 if (parse_sec==PARAM_SEC)
661 current->argList->append(arg);
669 * adds the library|use statements to the next class (entity|package|architecture|package body
679 void VhdlParser::mapLibPackage( Entry* root)
681 QList<Entry> epp=libUse;
682 EntryListIterator eli(epp);
684 for (;(rt=eli.current());++eli)
686 if (addLibUseClause(rt->name))
689 EntryListIterator eLib(*root->children());
691 for (eLib.toFirst();(current=eLib.current());++eLib)
693 if (VhdlDocGen::isVhdlClass(current))
695 if (current->startLine > rt->startLine)
698 current->addSubEntry(new Entry(*rt));
705 root->addSubEntry(new Entry(*rt));
711 bool VhdlParser::addLibUseClause(const QCString &type)
713 static bool showIEEESTD=Config_getBool("FORCE_LOCAL_INCLUDES");
715 if (showIEEESTD) // all standard packages and libraries will not be shown
717 if (type.lower().stripPrefix("ieee")) return FALSE;
718 if (type.lower().stripPrefix("std")) return FALSE;
723 int VhdlParser::getLine()
728 void VhdlParser::setLineParsed(int tok)
730 lineParse[tok]=yyLineNr;
733 int VhdlParser::getLine(int tok)
735 int val=lineParse[tok];
737 //assert(val>=0 && val<=yyLineNr);
742 void VhdlParser::createFlow()
744 if (!VhdlDocGen::getFlowMember())
750 if (currP==VhdlDocGen::FUNCTION)
753 FlowChart::alignFuncProc(q,tempEntry->argList,true);
756 else if (currP==VhdlDocGen::PROCEDURE)
759 FlowChart::alignFuncProc(q,tempEntry->argList,false);
764 q=":process( "+tempEntry->args;
768 q.prepend(VhdlDocGen::getFlowMember()->name().data());
770 FlowChart::addFlowChart(FlowChart::START_NO,q,0);
772 if (currP==VhdlDocGen::FUNCTION)
776 else if (currP==VhdlDocGen::PROCEDURE)
785 FlowChart::addFlowChart(FlowChart::END_NO,ret,0);
786 // FlowChart::printFlowList();
787 FlowChart::writeFlowChart();
791 bool checkMultiComment(QCString& qcs,int line)
793 QList<Entry> *pTemp=getEntryAtLine(VhdlParser::current_root,line);
795 if (pTemp->isEmpty()) return false;
797 //int ii=pTemp->count();
798 // qcs.stripPrefix("--!");
799 VhdlDocGen::prepareComment(qcs);
800 while (!pTemp->isEmpty())
802 Entry *e=(Entry*)pTemp->getFirst();
806 pTemp->removeFirst();
812 // returns the vhdl parsed types at line xxx
813 QList<Entry>* getEntryAtLine(const Entry* ce,int line)
815 EntryListIterator eli(*ce->children());
817 for (;(rt=eli.current());++eli)
819 if (rt->bodyLine==line)
821 lineEntry.insert(0,rt);
824 getEntryAtLine(rt,line);