Doxygen
Loading...
Searching...
No Matches
vhdldocgen.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
4 *
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.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15/******************************************************************************
16 * Parser for VHDL subset
17 * written by M. Kreis
18 * supports VHDL-87/93/2008
19 * does not support VHDL-AMS
20 ******************************************************************************/
21
22// global includes
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <map>
28#include <algorithm>
29#include <unordered_set>
30#include <mutex>
31
32/* --------------------------------------------------------------- */
33
34// local includes
35#include "qcstring.h"
36#include "vhdldocgen.h"
37#include "message.h"
38#include "config.h"
39#include "doxygen.h"
40#include "util.h"
41#include "language.h"
42#include "commentscan.h"
43#include "definition.h"
44#include "searchindex.h"
45#include "outputlist.h"
46#include "parserintf.h"
47#include "layout.h"
48#include "arguments.h"
49#include "portable.h"
50#include "memberlist.h"
51#include "memberdef.h"
52#include "groupdef.h"
53#include "classlist.h"
54#include "namespacedef.h"
55#include "filename.h"
56#include "membergroup.h"
57#include "membername.h"
58#include "plantuml.h"
59#include "vhdljjparser.h"
60#include "VhdlParser.h"
61#include "regex.h"
62#include "textstream.h"
63#include "moduledef.h"
64
65//#define DEBUGFLOW
66#define theTranslator_vhdlType theTranslator->trVhdlType
67
68static void initUCF(Entry* root,const QCString &type,QCString &qcs,int line,const QCString & fileName,QCString & brief);
69static void writeUCFLink(const MemberDef* mdef,OutputList &ol);
70static void addInstance(ClassDefMutable* entity, ClassDefMutable* arch, ClassDefMutable *inst,
71 const std::shared_ptr<Entry> &cur);
72
73static const MemberDef *flowMember=nullptr;
74
76{
77 flowMember=mem;
78}
79
81{
82 return flowMember;
83}
84
85//--------------------------------------------------------------------------------------------------
86
87static void writeLink(const MemberDef* mdef,OutputList &ol)
88{
90 mdef->getOutputFileBase(),
91 mdef->anchor(),
92 mdef->name());
93}
94
95static void startFonts(const QCString& q, const char *keyword,OutputList& ol)
96{
97 auto &codeOL = ol.codeGenerators();
98 codeOL.startFontClass(keyword);
99 codeOL.codify(q);
100 codeOL.endFontClass();
101}
102
103static QCString splitString(QCString& str,char c)
104{
105 QCString n=str;
106 int i=str.find(c);
107 if (i>0)
108 {
109 n=str.left(i);
110 str=str.remove(0,i+1);
111 }
112 return n;
113}
114
115static int compareString(const QCString& s1,const QCString& s2)
116{
117 return qstricmp(s1.stripWhiteSpace(),s2.stripWhiteSpace());
118}
119
120//--------------------------------------------------------------------------------------------------
121
122 // vhdl keywords included VHDL 2008
123static const std::unordered_set< std::string > g_vhdlKeyWordSet0 =
124{
125 "abs","access","after","alias","all","and","architecture","array","assert","assume","assume_guarantee","attribute",
126 "begin","block","body","buffer","bus",
127 "case","component","configuration","constant","context","cover",
128 "default","disconnect","downto",
129 "else","elsif","end","entity","exit",
130 "fairness","file","for","force","function",
131 "generate","generic","group","guarded",
132 "if","impure","in","inertial","inout","is",
133 "label","library","linkage","literal","loop",
134 "map","mod",
135 "nand","new","next","nor","not","null",
136 "of","on","open","or","others","out",
137 "package","parameter","port","postponed","procedure","process","property","protected","pure",
138 "range","record","register","reject","release","restrict","restrict_guarantee","rem","report","rol","ror","return",
139 "select","sequence","severity","signal","shared","sla","sll","sra","srl","strong","subtype",
140 "then","to","transport","type",
141 "unaffected","units","until","use",
142 "variable","vmode","vprop","vunit",
143 "wait","when","while","with",
144 "xor","xnor"
145};
146
147
148// type
149static const std::unordered_set< std::string> g_vhdlKeyWordSet1 =
150{
151 "natural","unsigned","signed","string","boolean", "bit","bit_vector","character",
152 "std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer",
153 "real","float","ufixed","sfixed","time","positive"
154};
155
156// logic
157static const std::unordered_set< std::string > g_vhdlKeyWordSet2 =
158{
159 "abs","and","or","not","mod","xor","rem","xnor","ror","rol","sla","sll"
160};
161
162// predefined attributes
163static const std::unordered_set< std::string > g_vhdlKeyWordSet3 =
164{
165 "base","left","right","high","low","ascending",
166 "image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low",
167 "range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event",
168 "active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name"
169};
170
172{
173}
174
175/*!
176 * returns the color of a keyword
177 */
178const char* VhdlDocGen::findKeyWord(const QCString& kw)
179{
180 std::string word=kw.lower().str();
181
182 if (word.empty()) return nullptr;
183
184 if (g_vhdlKeyWordSet0.find(word)!=g_vhdlKeyWordSet0.end())
185 return "keywordflow";
186
187 if (g_vhdlKeyWordSet1.find(word)!=g_vhdlKeyWordSet1.end())
188 return "keywordtype";
189
190 if (g_vhdlKeyWordSet2.find(word)!=g_vhdlKeyWordSet2.end())
191 return "vhdllogic";
192
193 if (g_vhdlKeyWordSet3.find(word)!=g_vhdlKeyWordSet3.end())
194 return "vhdlkeyword";
195
196 return nullptr;
197}
198
200{
201 if (name.isEmpty()) return nullptr;
203}
204
206{
207 return getClass(name);
208}
209
210static std::recursive_mutex g_vhdlMutex;
211static std::map<std::string,const MemberDef*> g_varMap;
212static std::vector<ClassDef*> g_classList;
213static std::map<ClassDef*,std::vector<ClassDef*> > g_packages;
214
215const MemberDef* VhdlDocGen::findMember(const QCString& className, const QCString& memName)
216{
217 std::lock_guard lock(g_vhdlMutex);
218 ClassDef *ecd=nullptr;
219 const MemberDef *mdef=nullptr;
220
221 ClassDef *cd=getClass(className);
222 //printf("VhdlDocGen::findMember(%s,%s)=%p\n",qPrint(className),qPrint(memName),cd);
223 if (cd==nullptr) return nullptr;
224
225 mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType::VariableMembers());
226 if (mdef) return mdef;
227 mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType::PubMethods());
228 if (mdef) return mdef;
229
230 // nothing found so far
231 // if we are an architecture or package body search in entity
232
235 {
236 Definition *d = cd->getOuterScope();
237 // searching upper/lower case names
238
239 QCString tt=d->name();
240 ecd =getClass(tt);
241 if (!ecd)
242 {
243 tt=tt.upper();
244 ecd =getClass(tt);
245 }
246 if (!ecd)
247 {
248 tt=tt.lower();
249 ecd =getClass(tt);
250 }
251
252 if (ecd) //d && d->definitionType()==Definition::TypeClass)
253 {
254 //ClassDef *ecd = (ClassDef*)d;
255 mdef=VhdlDocGen::findMemberDef(ecd,memName,MemberListType::VariableMembers());
256 if (mdef) return mdef;
257 mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType::PubMethods());
258 if (mdef) return mdef;
259 }
260 }
261
262
265 {
266 Definition *d = cd->getOuterScope();
267
268 QCString tt=d->name();
269 ClassDef *acd =getClass(tt);
270 if (!acd)
271 {
272 tt=tt.upper();
273 acd =getClass(tt);
274 }
275 if (!acd)
276 {
277 tt=tt.lower();
278 acd =getClass(tt);
279 }
280 if (acd) //d && d->definitionType()==Definition::TypeClass)
281 {
282 if(g_packages.find(acd)==g_packages.end())
283 {
285 }
286 }
287 }
288 else
289 {
290 ecd=cd;
291 if (g_packages.find(ecd)==g_packages.end()) VhdlDocGen::findAllPackages(ecd);
292 }
293
294 if (ecd)
295 {
296 auto cList_it = g_packages.find(ecd);
297 if (cList_it!=g_packages.end())
298 {
299 for (const auto &cdp : cList_it->second)
300 {
301 mdef=VhdlDocGen::findMemberDef(cdp,memName,MemberListType::VariableMembers());
302 if (mdef) return mdef;
303 mdef=VhdlDocGen::findMemberDef(cdp,memName,MemberListType::PubMethods());
304 if (mdef) return mdef;
305 }
306 }
307 }
308 return nullptr;
309
310}//findMember
311
312/**
313 * This function returns the entity|package
314 * in which the key (type) is found
315 */
317{
318 std::lock_guard lock(g_vhdlMutex);
319 QCString keyType=cd->symbolName()+"@"+key;
320 //printf("\n %s | %s | %s",qPrint(cd->symbolName()),key.data(,),qPrint(keyType));
321
322 auto it = g_varMap.find(keyType.str());
323 if (it!=g_varMap.end())
324 {
325 return it->second;
326 }
327 if (std::find(g_classList.begin(),g_classList.end(),cd)!=g_classList.end())
328 {
329 return nullptr;
330 }
331 const MemberList *ml=cd->getMemberList(type);
332 g_classList.push_back(cd);
333 if (!ml)
334 {
335 return nullptr;
336 }
337 //int l=ml->count();
338 // fprintf(stderr,"\n loading entity %s %s: %d",qPrint(cd->symbolName()),qPrint(keyType),l);
339
340 for (const auto &md : *ml)
341 {
342 QCString tkey=cd->symbolName()+"@"+md->name();
343 if (g_varMap.find(tkey.str())==g_varMap.end())
344 {
345 g_varMap.emplace(tkey.str(),md);
346 }
347 }
348 it=g_varMap.find(keyType.str());
349 if (it!=g_varMap.end())
350 {
351 return it->second;
352 }
353 return nullptr;
354}//findMemberDef
355
356/*!
357 * finds all included packages of an Entity or Package
358 */
359
361{
362 std::lock_guard lock(g_vhdlMutex);
363 if (g_packages.find(cdef)!=g_packages.end()) return;
364 std::vector<ClassDef*> cList;
365 MemberList *mem=cdef->getMemberList(MemberListType::VariableMembers());
366 if (mem)
367 {
368 for (const auto &md : *mem)
369 {
370 if (VhdlDocGen::isPackage(md))
371 {
372 ClassDef* cd=VhdlDocGen::getPackageName(md->name());
373 if (cd)
374 {
375 cList.push_back(cd);
377 g_packages.emplace(cdef,cList);
378 }
379 }
380 }//for
381 }
382
383}// findAllPackages
384
385/*!
386 * returns the function with the matching argument list
387 * is called in vhdlcode.l
388 */
389
390const MemberDef* VhdlDocGen::findFunction(const QCString& funcname, const QCString& package)
391{
392 ClassDef *cdef=getClass(package);
393 if (cdef==nullptr) return nullptr;
394
395 MemberList *mem=cdef->getMemberList(MemberListType::PubMethods());
396 if (mem)
397 {
398 for (const auto &mdef : *mem)
399 {
400 QCString mname=mdef->name();
401 if ((VhdlDocGen::isProcedure(mdef) || VhdlDocGen::isVhdlFunction(mdef)) && (compareString(funcname,mname)==0))
402 {
403 return mdef;
404 }//if
405 }//for
406 }//if
407 return nullptr;
408} //findFunction
409
410
411
427
428/*!
429 * returns the class title+ref
430 */
431
433{
434 QCString pageTitle;
435 if (cd==nullptr) return "";
436 pageTitle=VhdlDocGen::getClassName(cd);
437 pageTitle+=" ";
439 return pageTitle;
440} // getClassTitle
441
442/* returns the class name without their prefixes */
443
445{
446 QCString temp;
447 if (cd==nullptr) return "";
448
450 {
451 temp=cd->name();
452 temp.stripPrefix("_");
453 return temp;
454 }
455
456 return substitute(cd->className(),"::",".");
457}
458
459/*!
460 * writes an inline link form entity|package to architecture|package body and vice verca
461 */
462
464{
465 std::vector<QCString> ql;
466 QCString nn=cd->className();
468
470
471 //type=type.lower();
472 type+=" >> ";
475
477 {
478 nn.stripPrefix("_");
479 cd=getClass(nn);
480 }
481 else if (ii==VhdlDocGen::PACKAGECLASS)
482 {
483 nn.prepend("_");
484 cd=getClass(nn);
485 }
487 {
488 StringVector qlist=split(nn.str(),"-");
489 if (qlist.size()>1)
490 {
491 nn=qlist[1];
493 }
494 }
495
496 QCString opp;
498 {
500 for (const auto &s : ql)
501 {
502 StringVector qlist=split(s.str(),"-");
503 if (qlist.size()>2)
504 {
505 QCString s1(qlist[0]);
506 QCString s2(qlist[1]);
507 s1.stripPrefix("_");
508 if (ql.size()==1) s1.clear();
509 ClassDef *cc = getClass(s);
510 if (cc)
511 {
512 VhdlDocGen::writeVhdlLink(cc,ol,type,s2,s1);
513 }
514 }
515 }
516 }
517 else
518 {
519 VhdlDocGen::writeVhdlLink(cd,ol,type,nn,opp);
520 }
521
524
525}// write
526
527/*
528 * finds all architectures which belongs to an entity
529 */
530void VhdlDocGen::findAllArchitectures(std::vector<QCString>& qll,const ClassDef *cd)
531{
532 for (const auto &citer : *Doxygen::classLinkedMap)
533 {
534 QCString className=citer->className();
535 int pos = -1;
536 if (cd != citer.get() && (pos=className.find('-'))!=-1)
537 {
538 QCString postfix=className.mid(pos+1);
539 if (qstricmp(cd->className(),postfix)==0)
540 {
541 qll.push_back(className);
542 }
543 }
544 }// for
545}//findAllArchitectures
546
548{
549 for (const auto &citer : *Doxygen::classLinkedMap)
550 {
551 QCString jj=citer->name();
552 StringVector ql=split(jj.str(),":");
553 if (ql.size()>1)
554 {
555 if (ql[0]==cd->name())
556 {
557 return citer.get();
558 }
559 }
560 }
561 return nullptr;
562}
563/*
564 * writes the link entity >> .... or architecture >> ...
565 */
566
568{
569 if (ccd==nullptr) return;
570 ol.startBold();
571 ol.docify(type);
572 ol.endBold();
573 nn.stripPrefix("_");
575
576 if (!behav.isEmpty())
577 {
578 behav.prepend(" ");
579 ol.startBold();
580 ol.docify(behav);
581 ol.endBold();
582 }
583
584 ol.lineBreak();
585}
586
587
588/*!
589 * strips the "--!" prefixes of vhdl comments
590 */
592{
593 qcs=qcs.stripWhiteSpace();
594 if (qcs.isEmpty()) return;
595
596 const char* sc="--!";
597 if (qcs.startsWith(sc)) qcs = qcs.mid(qstrlen(sc));
598 static const reg::Ex re(R"(\n[ \t]*--!)");
599 std::string s = qcs.str();
600 reg::Iterator iter(s,re);
602 std::string result;
603 size_t p=0;
604 size_t sl=s.length();
605 for ( ; iter!=end ; ++iter)
606 {
607 const auto &match = *iter;
608 size_t i = match.position();
609 result+="\n";
610 result+=s.substr(p,i-p);
611 p = match.position()+match.length();
612 }
613 if (p<sl)
614 {
615 result+="\n";
616 result+=s.substr(p);
617 }
618
619 qcs = result;
620 qcs=qcs.stripWhiteSpace();
621}
622
623
624/*!
625 * parses a function proto
626 * @param text function string
627 * @param name points to the function name
628 * @param ret Stores the return type
629 * @param doc ???
630 */
631void VhdlDocGen::parseFuncProto(const QCString &text,QCString& name,QCString& ret,bool doc)
632{
633 QCString s1(text);
634 QCString temp;
635
636 int index=s1.find("(");
637 if (index<0) index=0;
638 int end=s1.findRev(")");
639
640 if ((end-index)>0)
641 {
642 temp=s1.mid(index+1,(end-index-1));
643 //getFuncParams(qlist,temp);
644 }
645 if (doc)
646 {
647 name=s1.left(index);
648 name=name.stripWhiteSpace();
649 if ((end-index)>0)
650 {
651 ret="function";
652 }
653 return;
654 }
655 else
656 {
657 s1=s1.stripWhiteSpace();
658 int i=s1.find('(');
659 int s=s1.find(' ');
660 if (s==-1) s=s1.find('\t');
661 if (i==-1 || i<s)
663 else // s<i, s=start of name, i=end of name
664 s1=s1.mid(s,(i-s));
665
666 name=s1.stripWhiteSpace();
667 }
668 index=s1.findRev("return",-1,FALSE);
669 if (index !=-1)
670 {
671 ret=s1.mid(index+6,s1.length());
672 ret=ret.stripWhiteSpace();
674 }
675}
676
677/*
678 * returns the n'th word of a string
679 */
680
682{
683 static const reg::Ex reg(R"([\s:|])");
684 auto ql=split(c.str(),reg);
685
686 if (index < static_cast<int>(ql.size()))
687 {
688 return ql[index];
689 }
690
691 return "";
692}
693
694
696{
697 if (prot==VhdlDocGen::ENTITYCLASS)
698 return "entity";
699 else if (prot==VhdlDocGen::ARCHITECTURECLASS)
700 return "architecture";
701 else if (prot==VhdlDocGen::PACKAGECLASS)
702 return "package";
703 else if (prot==VhdlDocGen::PACKBODYCLASS)
704 return "package body";
705
706 return "";
707}
708
709/*!
710 * deletes a char backwards in a string
711 */
712
714{
715 int index=s.findRev(c,-1,FALSE);
716 if (index > -1)
717 {
718 s = s.remove(index,1);
719 return TRUE;
720 }
721 return FALSE;
722}
723
725{
726 int index=s.findRev(c,-1,FALSE);
727 while (index > -1)
728 {
729 s = s.remove(index,1);
730 index=s.findRev(c,-1,FALSE);
731 }
732}
733
734
735static int recordCounter=0;
736
737/*!
738 * returns the next number of a record|unit member
739 */
740
742{
743 char buf[12];
744 qsnprintf(buf,12,"%d",recordCounter++);
745 QCString qcs(&buf[0]);
746 return qcs;
747}
748
749/*!
750 * returns the next number of an anonymous process
751 */
752
754{
755 static int stringCounter;
756 QCString qcs("PROCESS_");
757 char buf[8];
758 qsnprintf(buf,8,"%d",stringCounter++);
759 qcs.append(&buf[0]);
760 return qcs;
761}
762
763/*!
764 * writes a colored and formatted string
765 */
766
768{
769 static const reg::Ex reg(R"([\‍[\‍]./<>:\s,;'+*|&=()\"-])");
770 QCString qcs = s;
771 qcs+=QCString(" ");// parsing the last sign
772 QCString find=qcs;
773 QCString temp=qcs;
774 char buf[2];
775 buf[1]='\0';
776
777 int j = findIndex(temp.str(),reg);
778
779 ol.startBold();
780 if (j>=0)
781 {
782 while (j>=0)
783 {
784 find=find.left(j);
785 buf[0]=temp[j];
786 const char *ss=VhdlDocGen::findKeyWord(find);
787 bool k=isNumber(find.str()); // is this a number
788 if (k)
789 {
790 ol.docify(" ");
791 startFonts(find,"vhdldigit",ol);
792 ol.docify(" ");
793 }
794 else if (j != 0 && ss)
795 {
796 startFonts(find,ss,ol);
797 }
798 else
799 {
800 if (j>0)
801 {
802 VhdlDocGen::writeStringLink(mdef,find,ol);
803 }
804 }
805 startFonts(&buf[0],"vhdlchar",ol);
806
807 QCString st=temp.remove(0,j+1);
808 find=st;
809 if (!find.isEmpty() && find.at(0)=='"')
810 {
811 int ii=find.find('"',2);
812 if (ii>1)
813 {
814 QCString com=find.left(ii+1);
815 startFonts(com,"keyword",ol);
816 temp=find.remove(0,ii+1);
817 }
818 }
819 else
820 {
821 temp=st;
822 }
823 j = findIndex(temp.str(),reg);
824 }//while
825 }//if
826 else
827 {
828 startFonts(find,"vhdlchar",ol);
829 }
830 ol.endBold();
831}// writeFormatString
832
833/*!
834 * returns TRUE if this string is a number
835 */
836bool VhdlDocGen::isNumber(const std::string& s)
837{
838 static const reg::Ex regg(R"([0-9][0-9eEfFbBcCdDaA_.#+?xXzZ-]*)");
839 return reg::match(s,regg);
840}// isNumber
841
842
843/*!
844 * inserts white spaces for better readings
845 * and writes a colored string to the output
846 */
847
849{
850 QCString qcs = s;
851 QCString temp;
852 qcs.stripPrefix(":");
853 qcs.stripPrefix("is");
854 qcs.stripPrefix("IS");
855 qcs.stripPrefix("of");
856 qcs.stripPrefix("OF");
857
858 size_t len = qcs.length();
859 size_t index=1;
860
861 for (size_t j=0;j<len;j++)
862 {
863 char c=qcs[j];
864 char b=c;
865 if (j>0) b=qcs[j-1];
866 if (c=='"' || c==',' || c=='\''|| c=='(' || c==')' || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>'))
867 {
868 if (temp.length()>=index && temp.at(index-1) != ' ')
869 {
870 temp+=" ";
871 }
872 temp+=c;
873 temp+=" ";
874 }
875 else if (c=='=')
876 {
877 if (b==':') // := operator
878 {
879 temp.replace(index-1,1,"=");
880 temp+=" ";
881 }
882 else // = operator
883 {
884 temp+=" ";
885 temp+=c;
886 temp+=" ";
887 }
888 }
889 else
890 {
891 temp+=c;
892 }
893
894 index=temp.length();
895 }// for
896 temp=temp.stripWhiteSpace();
897 // printf("\n [%s]",qPrint(qcs));
898 VhdlDocGen::writeFormatString(temp,ol,mdef);
899}
900
901/*!
902 * writes a procedure prototype to the output
903 */
904
906{
907 bool sem=FALSE;
908 size_t len=al.size();
909 ol.docify("( ");
910 if (len > 2)
911 {
912 ol.lineBreak();
913 }
914 for (const Argument &arg : al)
915 {
916 ol.startBold();
917 if (sem && len <3)
918 ol.writeChar(',');
919
920 QCString nn=arg.name;
921 nn+=": ";
922
923 QCString defval = arg.defval;
924 const char *str=VhdlDocGen::findKeyWord(defval);
925 defval+=" ";
926 if (str)
927 {
928 startFonts(defval,str,ol);
929 }
930 else
931 {
932 startFonts(defval,"vhdlchar",ol); // write type (variable,constant etc.)
933 }
934
935 startFonts(nn,"vhdlchar",ol); // write name
936 if (qstricmp(arg.attrib,arg.type) != 0)
937 {
938 startFonts(arg.attrib.lower(),"stringliteral",ol); // write in|out
939 }
940 ol.docify(" ");
941 VhdlDocGen::formatString(arg.type,ol,mdef);
942 sem=TRUE;
943 ol.endBold();
944 if (len > 2)
945 {
946 ol.lineBreak();
947 ol.docify(" ");
948 }
949 }//for
950
951 ol.docify(" )");
952
953
954}
955
956/*!
957 * writes a function prototype to the output
958 */
959
961{
962 if (!al.hasParameters()) return;
963 bool sem=FALSE;
964 size_t len=al.size();
965 ol.startBold();
966 ol.docify(" ( ");
967 ol.endBold();
968 if (len>2)
969 {
970 ol.lineBreak();
971 }
972 for (const Argument &arg : al)
973 {
974 ol.startBold();
975 QCString att=arg.defval;
976 bool bGen=att.stripPrefix("generic");
977
978 if (sem && len < 3)
979 {
980 ol.docify(" , ");
981 }
982
983 if (bGen)
984 {
985 VhdlDocGen::formatString(QCString("generic "),ol,mdef);
986 }
987 if (!att.isEmpty())
988 {
989 const char *str=VhdlDocGen::findKeyWord(att);
990 att+=" ";
991 if (str)
992 VhdlDocGen::formatString(att,ol,mdef);
993 else
994 startFonts(att,"vhdlchar",ol);
995 }
996
997 QCString nn=arg.name;
998 nn+=": ";
999 QCString ss=arg.type.stripWhiteSpace(); //.lower();
1000 QCString w=ss.stripWhiteSpace();//.upper();
1001 startFonts(nn,"vhdlchar",ol);
1002 startFonts("in ","stringliteral",ol);
1003 const char *str=VhdlDocGen::findKeyWord(ss);
1004 if (str)
1005 VhdlDocGen::formatString(w,ol,mdef);
1006 else
1007 startFonts(w,"vhdlchar",ol);
1008
1009 if (!arg.attrib.isEmpty())
1010 startFonts(arg.attrib,"vhdlchar",ol);
1011
1012 sem=TRUE;
1013 ol.endBold();
1014 if (len > 2)
1015 {
1016 ol.lineBreak();
1017 }
1018 }
1019 ol.startBold();
1020 ol.docify(" )");
1021 QCString exp=mdef->excpString();
1022 if (!exp.isEmpty())
1023 {
1024 ol.insertMemberAlign();
1025 ol.startBold();
1026 ol.docify("[ ");
1027 ol.docify(exp);
1028 ol.docify(" ]");
1029 ol.endBold();
1030 }
1031 ol.endBold();
1032}
1033
1034/*!
1035 * writes a process prototype to the output
1036 */
1037
1039{
1040 if (!al.hasParameters()) return;
1041 bool sem=FALSE;
1042 ol.startBold();
1043 ol.docify(" ( ");
1044 for (const Argument &arg : al)
1045 {
1046 if (sem)
1047 {
1048 ol.docify(" , ");
1049 }
1050 QCString nn=arg.name;
1051 // startFonts(nn,"vhdlchar",ol);
1053 sem=TRUE;
1054 }
1055 ol.docify(" )");
1056 ol.endBold();
1057}
1058
1059
1060/*!
1061 * writes a function|procedure documentation to the output
1062 */
1063
1065 const MemberDef *md,
1066 OutputList& ol,
1067 const ArgumentList &al,
1068 bool /*type*/)
1069{
1070 //bool sem=FALSE;
1071 ol.enableAll();
1072
1073 size_t index=al.size();
1074 if (index==0)
1075 {
1076 ol.docify(" ( ) ");
1077 return FALSE;
1078 }
1079 ol.endMemberDocName();
1081 //ol.startParameterName(FALSE);
1082 bool first=TRUE;
1083 for (const Argument &arg : al)
1084 {
1085 ol.startParameterType(first,"");
1086 // if (first) ol.writeChar('(');
1087 QCString attl=arg.defval;
1088
1089 //bool bGen=attl.stripPrefix("generic");
1090 //if (bGen)
1091 // VhdlDocGen::writeFormatString(QCString("generic "),ol,md);
1092
1093
1095 {
1096 startFonts(arg.defval,"keywordtype",ol);
1097 ol.docify(" ");
1098 }
1099 ol.endParameterType();
1100
1102 VhdlDocGen::writeFormatString(arg.name,ol,md);
1103
1105 {
1106 startFonts(arg.attrib,"stringliteral",ol);
1107 }
1108 else if (VhdlDocGen::isVhdlFunction(md))
1109 {
1110 startFonts(QCString("in"),"stringliteral",ol);
1111 }
1112
1113 ol.docify(" ");
1115 ol.startEmphasis();
1117 if (!VhdlDocGen::isProcess(md))
1118 {
1119 // startFonts(arg.type,"vhdlkeyword",ol);
1120 VhdlDocGen::writeFormatString(arg.type,ol,md);
1121 }
1123 ol.endEmphasis();
1125
1126 if (--index)
1127 {
1128 ol.docify(" , ");
1129 }
1130 else
1131 {
1132 // ol.docify(" ) ");
1133 ol.endParameterName();
1135 ol.endParameterExtra(true,false,true);
1136 break;
1137 }
1138 ol.endParameterName();
1140 ol.endParameterExtra(false,false,false);
1141
1142 //sem=TRUE;
1143 first=FALSE;
1144 }
1145 //ol.endParameterList();
1146 return TRUE;
1147
1148} // writeDocFunProc
1149
1150
1151
1152
1154{
1155 QCString argString;
1156 bool sem=FALSE;
1157
1158 for (const Argument &arg : al)
1159 {
1160 if (sem) argString.append(", ");
1161 if (func)
1162 {
1163 argString+=arg.name;
1164 argString+=":";
1165 argString+=arg.type;
1166 }
1167 else
1168 {
1169 argString+=arg.defval+" ";
1170 argString+=arg.name+" :";
1171 argString+=arg.attrib+" ";
1172 argString+=arg.type;
1173 }
1174 sem=TRUE;
1175 }
1176 return argString;
1177}
1178
1179
1181 OutputList& ol,const GroupDef* gd,const ClassDef* cd,const FileDef *fd,const NamespaceDef* nd,const ModuleDef *mod)
1182{
1204
1205 // configurations must be added to global file definitions.
1208
1209}
1210
1212{
1213 if (md->argsString()=="package")
1214 {
1216 }
1217 else if (md->argsString()=="configuration")
1218 {
1220 }
1221 else if (md->typeString()=="library")
1222 {
1224 }
1225 else if (md->typeString()=="use")
1226 {
1228 }
1229 else if (md->typeString().lower()=="misc")
1230 {
1232 }
1233 else if (md->typeString().lower()=="ucf_const")
1234 {
1236 }
1237
1239 {
1240 int mm=md->name().findRev('_');
1241 if (mm>0)
1242 {
1243 md->setName(md->name().left(mm));
1244 }
1245 }
1246 else if (md->getVhdlSpecifiers()==VhdlSpecifier::TYPE)
1247 {
1248 QCString largs=md->argsString();
1249 bool bRec=largs.stripPrefix("record") ;
1250 bool bUnit=largs.stripPrefix("units") ;
1251 if (bRec || bUnit)
1252 {
1253 md->setType("");
1254 }
1255 }
1256}
1257
1258/* writes a vhdl type documentation */
1260{
1261 const ClassDef *cd=toClassDef(d);
1262 bool hasParams = FALSE;
1263
1264 if (cd==nullptr) return hasParams;
1265
1266 QCString ttype=mdef->typeString();
1267 QCString largs=mdef->argsString();
1268
1270 {
1271 QCString nn=mdef->typeString();
1272 nn=nn.stripWhiteSpace();
1273 QCString na=cd->name();
1274 const MemberDef* memdef=VhdlDocGen::findMember(na,nn);
1275 if (memdef && memdef->isLinkable())
1276 {
1277 ol.docify(" ");
1278
1279 ol.startBold();
1280 writeLink(memdef,ol);
1281 ol.endBold();
1282 ol.docify(" ");
1283 }
1284 else
1285 {
1286 ol.docify(" ");
1287 VhdlDocGen::formatString(ttype,ol,mdef);
1288 ol.docify(" ");
1289 }
1290 ol.docify(mdef->name());
1291 hasParams = VhdlDocGen::writeFuncProcDocu(mdef,ol, mdef->argumentList());
1292 }
1293
1294
1295 if (mdef->isVariable())
1296 {
1297 if (VhdlDocGen::isConstraint(mdef))
1298 {
1299 writeLink(mdef,ol);
1300 ol.docify(" ");
1301
1302 largs=substitute(largs,"#"," ");
1303 VhdlDocGen::formatString(largs,ol,mdef);
1304 return hasParams;
1305 }
1306 else
1307 {
1308 writeLink(mdef,ol);
1310 {
1311 return hasParams;
1312 }
1313 ol.docify(" ");
1314 }
1315
1316 // QCString largs=mdef->argsString();
1317
1318 bool c=largs=="context";
1319 bool brec=largs.stripPrefix("record") ;
1320
1321 if (!brec && !c)
1322 VhdlDocGen::formatString(ttype,ol,mdef);
1323
1324 if (c || brec || largs.stripPrefix("units"))
1325 {
1326 if (c)
1327 largs=ttype;
1328 VhdlDocGen::writeRecUnitDocu(mdef,ol,largs);
1329 return hasParams;
1330 }
1331
1332 ol.docify(" ");
1333 if (VhdlDocGen::isPort(mdef) || VhdlDocGen::isGeneric(mdef))
1334 {
1335 // QCString largs=mdef->argsString();
1336 VhdlDocGen::formatString(largs,ol,mdef);
1337 ol.docify(" ");
1338 }
1339 }
1340 return hasParams;
1341}
1342
1344{
1345 tagFile << " <member kind=\"";
1346 if (VhdlDocGen::isGeneric(mdef)) tagFile << "generic";
1347 if (VhdlDocGen::isPort(mdef)) tagFile << "port";
1348 if (VhdlDocGen::isEntity(mdef)) tagFile << "entity";
1349 if (VhdlDocGen::isComponent(mdef)) tagFile << "component";
1350 if (VhdlDocGen::isVType(mdef)) tagFile << "type";
1351 if (VhdlDocGen::isConstant(mdef)) tagFile << "constant";
1352 if (VhdlDocGen::isSubType(mdef)) tagFile << "subtype";
1353 if (VhdlDocGen::isVhdlFunction(mdef)) tagFile << "function";
1354 if (VhdlDocGen::isProcedure(mdef)) tagFile << "procedure";
1355 if (VhdlDocGen::isProcess(mdef)) tagFile << "process";
1356 if (VhdlDocGen::isSignals(mdef)) tagFile << "signal";
1357 if (VhdlDocGen::isAttribute(mdef)) tagFile << "attribute";
1358 if (VhdlDocGen::isRecord(mdef)) tagFile << "record";
1359 if (VhdlDocGen::isLibrary(mdef)) tagFile << "library";
1360 if (VhdlDocGen::isPackage(mdef)) tagFile << "package";
1361 if (VhdlDocGen::isVariable(mdef)) tagFile << "shared variable";
1362 if (VhdlDocGen::isFile(mdef)) tagFile << "file";
1363 if (VhdlDocGen::isGroup(mdef)) tagFile << "group";
1364 if (VhdlDocGen::isCompInst(mdef)) tagFile << "instantiation";
1365 if (VhdlDocGen::isAlias(mdef)) tagFile << "alias";
1366 if (VhdlDocGen::isCompInst(mdef)) tagFile << "configuration";
1367
1368 QCString fn = mdef->getOutputFileBase();
1370 tagFile << "\">\n";
1371 tagFile << " <type>" << convertToXML(mdef->typeString()) << "</type>\n";
1372 tagFile << " <name>" << convertToXML(mdef->name()) << "</name>\n";
1373 tagFile << " <anchorfile>" << convertToXML(fn) << "</anchorfile>\n";
1374 tagFile << " <anchor>" << convertToXML(mdef->anchor()) << "</anchor>\n";
1375
1377 tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),TRUE)) << "</arglist>\n";
1378 else if (VhdlDocGen::isProcedure(mdef))
1379 tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),FALSE)) << "</arglist>\n";
1380 else
1381 tagFile << " <arglist>" << convertToXML(mdef->argsString()) << "</arglist>\n";
1382
1383 mdef->writeDocAnchorsToTagFile(tagFile);
1384 tagFile << " </member>\n";
1385}
1386
1387/* writes a vhdl type declaration */
1388
1390 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1391 bool /*inGroup*/)
1392{
1393 const Definition *d=nullptr;
1394
1395 ASSERT(cd!=nullptr || nd!=nullptr || fd!=nullptr || gd!=nullptr || mod!=nullptr ||
1398 ); // member should belong to something
1399 if (cd) d=cd;
1400 else if (nd) d=nd;
1401 else if (fd) d=fd;
1402 else if (mod) d=mod;
1403 else if (gd) d=gd;
1404 else d=mdef;
1405
1406 // write search index info
1407 if (Doxygen::searchIndex.enabled())
1408 {
1409 Doxygen::searchIndex.setCurrentDoc(mdef,mdef->anchor(),FALSE);
1410 Doxygen::searchIndex.addWord(mdef->localName(),TRUE);
1411 Doxygen::searchIndex.addWord(mdef->qualifiedName(),FALSE);
1412 }
1413
1414 QCString cname = d->name();
1415 QCString cfname = d->getOutputFileBase();
1416
1417 //HtmlHelp *htmlHelp=nullptr;
1418 // bool hasHtmlHelp = Config_getBool(GENERATE_HTML) && Config_getBool(GENERATE_HTMLHELP);
1419 // if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
1420
1421 // search for the last anonymous scope in the member type
1422 ClassDef *annoClassDef=mdef->getClassDefOfAnonymousType();
1423
1424 // start a new member declaration
1427 ///printf("startMemberItem for %s\n",qPrint(name()));
1431
1432 ol.startMemberItem( mdef->anchor(), memType );
1433
1434 // If there is no detailed description we need to write the anchor here.
1435 bool detailsVisible = mdef->hasDetailedDescription();
1436 if (!detailsVisible)
1437 {
1438 QCString doxyName=mdef->name();
1439 if (!cname.isEmpty()) doxyName.prepend(cname+"::");
1440 QCString doxyArgs=mdef->argsString();
1441 ol.startDoxyAnchor(cfname,cname,mdef->anchor(),doxyName,doxyArgs);
1442 ol.addLabel(cfname,mdef->anchor());
1443
1444 ol.pushGeneratorState();
1447 ol.docify("\n");
1448 ol.popGeneratorState();
1449
1450 }
1451 // *** write type
1452 /*VHDL CHANGE */
1453
1454 QCString ltype(mdef->typeString());
1455 QCString largs(mdef->argsString());
1456
1457 ClassDef *kl=nullptr;
1458 const ArgumentList &al = mdef->argumentList();
1459 QCString nn;
1460 //VhdlDocGen::adjustRecordMember(mdef);
1461 if (gd) gd=nullptr;
1462 switch (mm)
1463 {
1465 VhdlDocGen::writeSource(mdef,ol,nn);
1466 break;
1469 ol.startBold();
1470 VhdlDocGen::formatString(ltype,ol,mdef);
1471 ol.endBold();
1472 ol.insertMemberAlign();
1473 ol.docify(" ");
1474
1475 writeLink(mdef,ol);
1476 if (al.hasParameters() && mm==VhdlSpecifier::FUNCTION)
1478
1481
1482 break;
1483 case VhdlSpecifier::USE:
1484 kl=VhdlDocGen::getClass(mdef->name());
1485 if (kl && (VhdlDocGen::convert(kl->protection())==VhdlDocGen::ENTITYCLASS)) break;
1486 writeLink(mdef,ol);
1487 ol.insertMemberAlign();
1488 ol.docify(" ");
1489
1490 if (kl)
1491 {
1492 nn=kl->getOutputFileBase();
1493 ol.pushGeneratorState();
1495 ol.docify(" ");
1497 ol.startBold();
1498 ol.docify(name);
1499 name.clear();
1500 ol.endBold();
1501 name+=" <"+mdef->name()+">";
1502 ol.startEmphasis();
1504 ol.popGeneratorState();
1505 }
1506 break;
1508 writeLink(mdef,ol);
1509 ol.insertMemberAlign();
1510 if (largs=="context")
1511 {
1512 VhdlDocGen::writeRecordUnit(ltype,largs,ol,mdef);
1513 }
1514
1515 break;
1516
1520
1521 writeLink(mdef,ol);
1522 ol.docify(" ");
1523 if (mm==VhdlSpecifier::GENERIC)
1524 {
1525 ol.insertMemberAlign();
1526 ol.startBold();
1527 VhdlDocGen::formatString(largs,ol,mdef);
1528 ol.endBold();
1529 }
1530 else
1531 {
1532 ol.insertMemberAlignLeft(memType, false);
1533 ol.docify(" ");
1534 ol.startBold();
1535 VhdlDocGen::formatString(ltype,ol,mdef);
1536 ol.endBold();
1537 ol.insertMemberAlign();
1538 ol.docify(" ");
1539 VhdlDocGen::formatString(largs,ol,mdef);
1540 }
1541 break;
1543 writeLink(mdef,ol);
1544 ol.insertMemberAlign();
1546 break;
1552 if (VhdlDocGen::isCompInst(mdef) )
1553 {
1554 nn=largs;
1555 if(nn.stripPrefix("function") || nn.stripPrefix("package"))
1556 {
1557 VhdlDocGen::formatString(largs,ol,mdef);
1558 ol.insertMemberAlign();
1559 writeLink(mdef,ol);
1560 ol.docify(" ");
1561 VhdlDocGen::formatString(ltype,ol,mdef);
1562 break;
1563 }
1564
1565 largs.prepend("::");
1566 largs.prepend(mdef->name());
1567 ol.writeObjectLink(mdef->getReference(),
1568 cfname,
1569 mdef->anchor(),
1570 mdef->name());
1571 }
1572 else
1573 writeLink(mdef,ol);
1574
1575 ol.insertMemberAlign();
1576 ol.docify(" ");
1577 ol.startBold();
1578 ol.docify(ltype);
1579 ol.endBold();
1580 ol.docify(" ");
1581 if (VhdlDocGen::isComponent(mdef) ||
1582 VhdlDocGen::isConfig(mdef) ||
1584 {
1586 {
1587 nn=ltype;
1588 }
1589 else
1590 {
1591 nn=mdef->name();
1592 }
1593 kl=getClass(nn);
1594 if (kl)
1595 {
1596 nn=kl->getOutputFileBase();
1597 ol.pushGeneratorState();
1599 ol.startEmphasis();
1600 QCString name("<Entity ");
1602 {
1603 name+=ltype+">";
1604 }
1605 else
1606 {
1607 name+=mdef->name()+"> ";
1608 }
1610 ol.endEmphasis();
1611 ol.popGeneratorState();
1612 }
1613 }
1614 break;
1616 writeUCFLink(mdef,ol);
1617 break;
1626 writeLink(mdef,ol);
1627 ol.docify(" ");
1628 ol.insertMemberAlign();
1629 VhdlDocGen::formatString(ltype,ol,mdef);
1630 break;
1633 writeRecordUnit(largs,ltype,ol,mdef);
1634 break;
1635
1636 default: break;
1637 }
1638
1639 bool htmlOn = ol.isEnabled(OutputType::Html);
1640 if (htmlOn && /*Config_getBool(HTML_ALIGN_MEMBERS) &&*/ !ltype.isEmpty())
1641 {
1643 }
1644 if (!ltype.isEmpty()) ol.docify(" ");
1645
1646 if (htmlOn)
1647 {
1649 }
1650
1651 if (!detailsVisible)
1652 {
1653 ol.endDoxyAnchor(cfname,mdef->anchor());
1654 }
1655
1656 ol.endMemberItem(memType);
1657 if (!mdef->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC) /* && !annMemb */)
1658 {
1659 QCString s=mdef->briefDescription();
1661 ol.generateDoc(mdef->briefFile(),
1662 mdef->briefLine(),
1663 mdef->getOuterScope()?mdef->getOuterScope():d,
1664 mdef,
1665 s,
1666 DocOptions()
1667 .setIndexWords(true)
1668 .setSingleLine(true));
1669 if (detailsVisible)
1670 {
1671 ol.pushGeneratorState();
1673 ol.docify(" ");
1674 if (mdef->getGroupDef()!=nullptr && gd==nullptr) // forward link to the group
1675 {
1676 ol.startTextLink(mdef->getOutputFileBase(),mdef->anchor());
1677 }
1678 else // local link
1679 {
1680 ol.startTextLink(QCString(),mdef->anchor());
1681 }
1682 ol.endTextLink();
1683 ol.popGeneratorState();
1684 }
1686 }
1687 mdef->warnIfUndocumented();
1688
1689}// end writeVhdlDeclaration
1690
1691
1693 const MemberList* mlist,OutputList &ol,
1694 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1695 VhdlSpecifier specifier)
1696{
1697
1698 StringSet pack;
1699
1700 bool first=TRUE;
1701 for (const auto &imd : *mlist)
1702 {
1704 if (md)
1705 {
1707 if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlSpecifier::LIBRARY) )
1708 {
1709 if (first) { ol.startMemberList();first=FALSE; }
1710 VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,mod,FALSE);
1711 } //if
1712 else if (md->isBriefSectionVisible() && (mems==specifier))
1713 {
1714 if (pack.find(md->name().str())==pack.end())
1715 {
1716 if (first) ol.startMemberList(),first=FALSE;
1717 VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,mod,FALSE);
1718 pack.insert(md->name().str());
1719 }
1720 } //if
1721 } //if
1722 } //for
1723 if (!first) ol.endMemberList();
1724}//plainDeclaration
1725
1727{
1728 if (ml==nullptr) return FALSE;
1729 for (const auto &mdd : *ml)
1730 {
1731 if (mdd->getVhdlSpecifiers()==type) //is type in class
1732 {
1733 return TRUE;
1734 }
1735 }
1736 for (const auto &mg : ml->getMemberGroupList())
1737 {
1738 if (!mg->members().empty())
1739 {
1740 if (membersHaveSpecificType(&mg->members(),type)) return TRUE;
1741 }
1742 }
1743 return FALSE;
1744}
1745
1747 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1748 const QCString &title,const QCString &subtitle,bool /*showEnumValues*/,VhdlSpecifier type)
1749{
1750 if (!membersHaveSpecificType(ml,type)) return;
1751
1752 if (!title.isEmpty())
1753 {
1754 ol.startMemberHeader(convertToId(title),type == VhdlSpecifier::PORT ? 3 : 2);
1755 ol.parseText(title);
1756 ol.endMemberHeader();
1757 ol.docify(" ");
1758 }
1759 if (!subtitle.isEmpty())
1760 {
1762 ol.generateDoc("[generated]",
1763 -1,
1764 nullptr,
1765 nullptr,
1766 subtitle,
1767 DocOptions()
1768 .setSingleLine(true));
1769 ol.endMemberSubtitle();
1770 } //printf("memberGroupList=%p\n",memberGroupList);
1771
1772 VhdlDocGen::writePlainVHDLDeclarations(ml,ol,cd,nd,fd,gd,mod,type);
1773
1774 int groupId=0;
1775 for (const auto &mg : ml->getMemberGroupList())
1776 {
1777 if (membersHaveSpecificType(&mg->members(),type))
1778 {
1779 //printf("mg->header=%s\n",qPrint(mg->header()));
1780 bool hasHeader=!mg->header().isEmpty();
1781 QCString groupAnchor = QCString(ml->listType().toLabel())+"-"+QCString().setNum(groupId++);
1782 ol.startMemberGroupHeader(groupAnchor,hasHeader);
1783 if (hasHeader)
1784 {
1785 ol.parseText(mg->header());
1786 }
1787 ol.endMemberGroupHeader(hasHeader);
1788 if (!mg->documentation().isEmpty())
1789 {
1790 //printf("Member group has docs!\n");
1792 ol.generateDoc("[generated]",
1793 -1,
1794 nullptr,
1795 nullptr,
1796 mg->documentation()+"\n",
1797 DocOptions());
1798 ol.endMemberGroupDocs();
1799 }
1800 ol.startMemberGroup();
1801 //printf("--- mg->writePlainDeclarations ---\n");
1802 VhdlDocGen::writePlainVHDLDeclarations(&mg->members(),ol,cd,nd,fd,gd,mod,type);
1803 ol.endMemberGroup(hasHeader);
1804 }
1805 }
1806}// writeVHDLDeclarations
1807
1808
1810 OutputList &ol ,QCString & cname)
1811{
1813 cname=VhdlDocGen::getClassName(cd);
1814 ol.startBold();
1815 ol.writeString(qcs);
1816 ol.writeString(" ");
1817 ol.endBold();
1818 //ol.insertMemberAlign();
1819 return FALSE;
1820}// writeClassLink
1821
1822
1823/*! writes a link if the string is linkable else a formatted string */
1824
1826{
1827 if (mdef)
1828 {
1829 const ClassDef *cd=mdef->getClassDef();
1830 if (cd)
1831 {
1832 QCString n=cd->name();
1833 const MemberDef* memdef=VhdlDocGen::findMember(n,mem);
1834 if (memdef && memdef->isLinkable())
1835 {
1836 ol.startBold();
1837 writeLink(memdef,ol);
1838 ol.endBold();
1839 ol.docify(" ");
1840 return;
1841 }
1842 }
1843 }
1844 startFonts(mem,"vhdlchar",ol);
1845}// found component
1846
1847
1848
1849void VhdlDocGen::writeSource(const MemberDef* mdef,OutputList& ol,const QCString &cname)
1850{
1851 auto intf = Doxygen::parserManager->getCodeParser(".vhd");
1852 // pIntf->resetCodeParserState();
1853
1854 QCString codeFragment=mdef->documentation();
1855
1856 if (cname.isEmpty())
1857 {
1858 writeLink(mdef,ol);
1859 int fi=0;
1860 int j=0;
1861 do
1862 {
1863 fi=codeFragment.find("\n",++fi);
1864 } while(fi>=0 && j++ <3);
1865
1866 // show only the first four lines
1867 if (j==4)
1868 {
1869 codeFragment=codeFragment.left(fi);
1870 codeFragment.append("\n .... ");
1871 }
1872 }
1873
1874 codeFragment.prepend("\n");
1875 ol.pushGeneratorState();
1876 auto &codeOL = ol.codeGenerators();
1877 codeOL.startCodeFragment("DoxyCode");
1878 intf->parseCode(codeOL, // codeOutIntf
1879 QCString(), // scope
1880 codeFragment, // input
1881 SrcLangExt::VHDL, // lang
1882 Config_getBool(STRIP_CODE_COMMENTS),
1884 .setFileDef(mdef->getFileDef())
1886 .setEndLine(mdef->getEndBodyLine())
1887 .setInlineFragment(true)
1888 .setMemberDef(mdef)
1889 );
1890
1891 codeOL.endCodeFragment("DoxyCode");
1892 ol.popGeneratorState();
1893
1894 if (cname.isEmpty()) return;
1895
1896 MemberDefMutable *mdm = toMemberDefMutable(const_cast<MemberDef*>(mdef));
1897 if (mdm)
1898 {
1899 mdm->writeSourceDef(ol);
1900 if (mdef->hasReferencesRelation()) mdm->writeSourceRefs(ol,cname);
1901 if (mdef->hasReferencedByRelation()) mdm->writeSourceReffedBy(ol,cname);
1902 }
1903}
1904
1905
1906
1908{
1909
1910 QCString n=name;
1911 n=n.remove(0,6);
1912
1913 int i=0;
1914
1915 while((i=n.find("__"))>0)
1916 {
1917 n=n.remove(i,1);
1918 }
1919
1920 while((i=n.find("_1"))>0)
1921 {
1922 n=n.replace(i,2,":");
1923 }
1924
1925 return n;
1926}
1927
1928void VhdlDocGen::parseUCF(const QCString &input,Entry* entity,const QCString &fileName,bool altera)
1929{
1930 QCString ucFile(input);
1931 int lineNo=0;
1932 QCString comment("#!");
1933 QCString brief;
1934
1935 while (!ucFile.isEmpty())
1936 {
1937 int i=ucFile.find("\n");
1938 if (i<0) break;
1939 lineNo++;
1940 QCString temp=ucFile.left(i);
1941 temp=temp.stripWhiteSpace();
1942 bool bb=temp.stripPrefix("//");
1943
1944 if (!temp.isEmpty())
1945 {
1946 if (temp.stripPrefix(comment) )
1947 {
1948 brief+=temp;
1949 brief.append("\\n");
1950 }
1951 else if (!temp.stripPrefix("#") && !bb)
1952 {
1953 if (altera)
1954 {
1955 int in=temp.find("-name");
1956 if (in>0)
1957 {
1958 temp=temp.remove(0,in+5);
1959 }
1960
1961 temp.stripPrefix("set_location_assignment");
1962
1963 initUCF(entity,QCString(),temp,lineNo,fileName,brief);
1964 }
1965 else
1966 {
1967 static const reg::Ex ee(R"([\s=])");
1968 int in=findIndex(temp.str(),ee);
1969 if (in<0) in=0;
1970 QCString ff=temp.left(in);
1971 temp.stripPrefix(ff);
1972 ff.append("#");
1973 if (!temp.isEmpty())
1974 {
1975 initUCF(entity,ff,temp,lineNo,fileName,brief);
1976 }
1977 }
1978 }
1979 }//temp
1980
1981 ucFile=ucFile.remove(0,i+1);
1982 }// while
1983}
1984
1985static void initUCF(Entry* root,const QCString &type,QCString &qcs,
1986 int line,const QCString &fileName,QCString & brief)
1987{
1988 if (qcs.isEmpty())return;
1989 QCString n;
1990
1992 qcs=qcs.stripWhiteSpace();
1993
1994 static const reg::Ex reg(R"([\s=])");
1995 int i = findIndex(qcs.str(),reg);
1996 if (i<0) return;
1997 if (i==0)
1998 {
1999 n=type;
2001 }
2002 else
2003 {
2004 n=qcs.left(i);
2005 }
2006 qcs=qcs.remove(0,i+1);
2007 // qcs.prepend("|");
2008
2009 qcs.stripPrefix("=");
2010
2011 std::shared_ptr<Entry> current = std::make_shared<Entry>();
2012 current->vhdlSpec=VhdlSpecifier::UCF_CONST;
2013 current->section=EntryType::makeVariable();
2014 current->bodyLine=line;
2015 current->fileName=fileName;
2016 current->type="ucf_const";
2017 current->args+=qcs;
2018 current->lang= SrcLangExt::VHDL ;
2019
2020 // adding dummy name for constraints like VOLTAGE=5,TEMPERATURE=20 C
2021 if (n.isEmpty())
2022 {
2023 n="dummy";
2025 }
2026
2027 current->name= n+"_";
2028 current->name.append(VhdlDocGen::getRecordNumber());
2029
2030 if (!brief.isEmpty())
2031 {
2032 current->brief=brief;
2033 current->briefLine=line;
2034 current->briefFile=fileName;
2035 brief.clear();
2036 }
2037
2038 root->moveToSubEntryAndKeep(current);
2039}
2040
2041
2042static void writeUCFLink(const MemberDef* mdef,OutputList &ol)
2043{
2044
2045 QCString largs(mdef->argsString());
2046 QCString n= splitString(largs, '#');
2047 // VhdlDocGen::adjustRecordMember(mdef);
2048 bool equ=(n.length()==largs.length());
2049
2050 if (!equ)
2051 {
2052 ol.writeString(n);
2053 ol.docify(" ");
2054 ol.insertMemberAlign();
2055 }
2056
2057 if (mdef->name().contains("dummy")==0)
2058 {
2059 writeLink(mdef,ol);
2060 }
2061 if (equ)
2062 {
2063 ol.insertMemberAlign();
2064 }
2065 ol.docify(" ");
2066 VhdlDocGen::formatString(largs,ol,mdef);
2067}
2068
2069// for cell_inst : [entity] work.proto [ (label|expr) ]
2071{
2072 if (!entity.contains(":")) return "";
2073
2074 static const reg::Ex exp(R"([:()\s])");
2075 auto ql=split(entity.str(),exp);
2076 if (ql.size()<2)
2077 {
2078 return "";
2079 }
2080 QCString label(ql[0]);
2081 entity = ql[1];
2082 int index = entity.findRev(".");
2083 if (index!=-1)
2084 {
2085 entity.remove(0,index+1);
2086 }
2087
2088 if (ql.size()==3)
2089 {
2090 arch = ql[2];
2091 ql=split(arch.str(),exp);
2092 if (ql.size()>1) // expression
2093 {
2094 arch="";
2095 }
2096 }
2097 return label; // label
2098}
2099
2100// use (configuration|entity|open) work.test [(cellfor)];
2101
2103{
2104 static const reg::Ex exp(R"([()\s])");
2105
2106 auto ql = split(entity.str(),exp);
2107
2108 if (findIndex(ql,"open")!=-1)
2109 {
2110 return "open";
2111 }
2112
2113 if (ql.size()<2)
2114 {
2115 return "";
2116 }
2117
2118 std::string label=ql[0];
2119 entity = ql[1];
2120 int index=entity.findRev(".");
2121 if (index!=-1)
2122 {
2123 entity.remove(0,index+1);
2124 }
2125
2126 if (ql.size()==3)
2127 {
2128 arch=ql[2];
2129 }
2130 return label;
2131}
2132
2133
2134
2135// find class with upper/lower letters
2137{
2138 for (const auto &cd : *Doxygen::classLinkedMap)
2139 {
2140 if (qstricmp(className.data(),qPrint(cd->name()))==0)
2141 {
2142 return cd.get();
2143 }
2144 }
2145 return nullptr;
2146}
2147
2148
2149/*
2150
2151// file foo.vhd
2152// entity foo
2153// .....
2154// end entity
2155
2156// file foo_arch.vhd
2157// architecture xxx of foo is
2158// ........
2159// end architecture
2160
2161*/
2163{
2164
2165 QCString entity,arch,inst;
2166
2167 for (const auto &cur : getVhdlInstList())
2168 {
2169 if (cur->isStatic ) // was bind
2170 {
2171 continue;
2172 }
2173
2174 if (cur->includeName=="entity" || cur->includeName=="component" )
2175 {
2176 entity=cur->includeName+" "+cur->type;
2177 QCString rr=VhdlDocGen::parseForBinding(entity,arch);
2178 }
2179 else if (cur->includeName.isEmpty())
2180 {
2181 entity=cur->type;
2182 }
2183
2185 inst=VhdlDocGen::getIndexWord(cur->args,0);
2188
2189 if (cd==nullptr)
2190 {
2191 continue;
2192 }
2193
2194 addInstance(classEntity,ar,cd,cur);
2195 }
2196
2197}
2198
2199static void addInstance(ClassDefMutable* classEntity, ClassDefMutable* ar,
2200 ClassDefMutable *cd , const std::shared_ptr<Entry> &cur)
2201{
2202
2203 QCString bName,n1;
2204 if (ar==nullptr) return;
2205
2206 if (classEntity==nullptr)
2207 {
2208 //add component inst
2209 n1=cur->type;
2210 goto ferr;
2211 }
2212
2213 if (classEntity==cd) return;
2214
2215 bName=classEntity->name();
2216 // fprintf(stderr,"\naddInstance %s to %s %s %s\n",qPrint( classEntity->name()),qPrint(cd->name()),qPrint(ar->name()),cur->name);
2217 n1=classEntity->name();
2218
2219 if (!cd->isBaseClass(classEntity, true))
2220 {
2221 cd->insertBaseClass(classEntity,n1,Protection::Public,Specifier::Normal,QCString());
2222 }
2223 else
2224 {
2225 VhdlDocGen::addBaseClass(cd,classEntity);
2226 }
2227
2228 if (!VhdlDocGen::isSubClass(classEntity,cd,true,0))
2229 {
2230 classEntity->insertSubClass(cd,Protection::Public,Specifier::Normal,QCString());
2231 classEntity->setLanguage(SrcLangExt::VHDL);
2232 }
2233
2234ferr:
2235 QCString uu=cur->name;
2236 auto md = createMemberDef(
2237 ar->getDefFileName(), cur->startLine,cur->startColumn,
2238 n1,uu,uu, QCString(),
2239 Protection::Public,
2240 Specifier::Normal,
2241 cur->isStatic,
2242 Relationship::Member,
2244 ArgumentList(),
2245 ArgumentList(),
2246 "");
2247 auto mmd = toMemberDefMutable(md.get());
2248
2249 if (!ar->getOutputFileBase().isEmpty())
2250 {
2251 TagInfo tg;
2252 tg.anchor = nullptr;
2253 tg.fileName = ar->getOutputFileBase();
2254 tg.tagName = nullptr;
2255 mmd->setTagInfo(&tg);
2256 }
2257
2258 //fprintf(stderr,"\n%s%s%s\n",qPrint(md->name()),qPrint(cur->brief),qPrint(cur->doc));
2259
2260 mmd->setLanguage(SrcLangExt::VHDL);
2261 mmd->setVhdlSpecifiers(VhdlSpecifier::INSTANTIATION);
2262 mmd->setBriefDescription(cur->brief,cur->briefFile,cur->briefLine);
2263 mmd->setBodySegment(cur->startLine,cur->startLine,-1) ;
2264 mmd->setDocumentation(cur->doc,cur->docFile,cur->docLine);
2265 FileDef *fd=ar->getFileDef();
2266 mmd->setBodyDef(fd);
2267 ar->insertMember(md.get());
2269 mn->push_back(std::move(md));
2270
2271}
2272
2273
2275{
2276 int i=mdef->name().find('~');
2277 if (i>0)
2278 {
2279 //sets the real record member name
2280 mdef->setName(mdef->name().left(i));
2281 }
2282
2283 writeLink(mdef,ol);
2284 ol.startBold();
2285 ol.insertMemberAlign();
2286 if (!ltype.isEmpty())
2287 {
2288 VhdlDocGen::formatString(ltype,ol,mdef);
2289 }
2290 ol.endBold();
2291}
2292
2293
2295 const MemberDef *md,
2296 OutputList& ol,
2297 QCString largs)
2298{
2299
2300 StringVector ql=split(largs.str(),"#");
2301 size_t len=ql.size();
2303 bool first=TRUE;
2304
2305 for(size_t i=0;i<len;i++)
2306 {
2307 QCString n = ql[i];
2308 ol.startParameterType(first,"");
2309 ol.endParameterType();
2311 VhdlDocGen::formatString(n,ol,md);
2312 ol.endParameterName();
2314 if ((len-i)>1)
2315 {
2316 ol.endParameterExtra(false,false,false);
2317 }
2318 else
2319 {
2320 ol.endParameterExtra(true,false,true);
2321 }
2322
2323 first=FALSE;
2324 }
2325
2326}//#
2327
2328
2329
2330bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int level)
2331{
2332 bool found=FALSE;
2333 //printf("isBaseClass(cd=%s) looking for %s\n",qPrint(name()),qPrint(bcd->name()));
2334 if (level>255)
2335 {
2336 err("Possible recursive class relation while inside {} and looking for {}\n",cd->name(),scd->name());
2337 abort();
2338 }
2339
2340 for (const auto &bcd :cd->subClasses())
2341 {
2342 const ClassDef *ccd=bcd.classDef;
2343 if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
2344 //printf("isSubClass() subclass %s\n",qPrint(ccd->name()));
2345 if (ccd==scd)
2346 {
2347 found=true;
2348 }
2349 else
2350 {
2351 if (level <256)
2352 {
2353 level = ccd->isBaseClass(scd,followInstances);
2354 if (level>0)
2355 {
2356 found=true;
2357 }
2358 }
2359 }
2360 }
2361 return found;
2362}
2363
2365{
2366 BaseClassList bcl = cd->baseClasses();
2367 for (auto &bcd : bcl)
2368 {
2369 ClassDef *ccd = bcd.classDef;
2370 if (ccd==ent)
2371 {
2372 QCString n = bcd.usedName;
2373 int i = n.find('(');
2374 if(i<0)
2375 {
2376 bcd.usedName.append("(2)");
2377 return;
2378 }
2379 static const reg::Ex reg(R"(\d+)");
2380 QCString s=n.left(i);
2381 QCString r=n.right(n.length()-i);
2382 std::string t=r.str();
2385 r.setNum(r.toInt()+1);
2386 reg::replace(t, reg, r.str());
2387 s.append(t);
2388 bcd.usedName=s;
2389 bcd.templSpecifiers=t;
2390 }
2391 }
2392 cd->updateBaseClasses(bcl);
2393}
2394
2395
2396static std::vector<const MemberDef*> mdList;
2397
2398static const MemberDef* findMemFlow(const MemberDef* mdef)
2399{
2400 for (const auto &md : mdList)
2401 {
2402 if (md->name()==mdef->name() && md->getStartBodyLine()==mdef->getStartBodyLine())
2403 {
2404 return md;
2405 }
2406 }
2407 return nullptr;
2408}
2409
2411{
2412 if (mdef==nullptr) return;
2413
2414 QCString codeFragment;
2415 const MemberDef* mm=nullptr;
2416 if ((mm=findMemFlow(mdef))!=nullptr)
2417 {
2418 // don't create the same flowchart twice
2420 return;
2421 }
2422 else
2423 {
2424 mdList.push_back(mdef);
2425 }
2426
2427 //fprintf(stderr,"\n create flow mem %s %p\n",qPrint(mdef->name()),mdef);
2428
2429 int actualStart= mdef->getStartBodyLine();
2430 int actualEnd=mdef->getEndBodyLine();
2431 const FileDef* fd=mdef->getFileDef();
2432 bool b=readCodeFragment( fd->absFilePath(), false, actualStart, actualEnd, codeFragment);
2433 if (!b) return;
2434
2435 auto parser { Doxygen::parserManager->getOutlineParser(".vhd") };
2437 std::shared_ptr<Entry> root = std::make_shared<Entry>();
2438 StringVector filesInSameTu;
2439 parser->parseInput("",codeFragment.data(),root,nullptr);
2440}
2441
2443{
2444 std::lock_guard lock(g_vhdlMutex);
2445 g_varMap.clear();
2446 g_classList.clear();
2447 g_packages.clear();
2448}
2449
2455{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::ALIAS; }
2461{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::PORT; }
2465{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::USE; }
2471{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::TYPE; }
2491{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::UNITS; }
2497{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::VFILE; }
2499{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::GROUP; }
2504
2505
2506
2507//############################## Flowcharts #################################################
2508
2509#define STARTL (FlowChart::WHILE_NO | FlowChart::IF_NO | \
2510 FlowChart::FOR_NO | FlowChart::CASE_NO | \
2511 FlowChart::LOOP_NO | WHEN_NO)
2512#define DECLN (FlowChart::WHEN_NO | \
2513 FlowChart::ELSIF_NO | FlowChart::IF_NO | \
2514 FlowChart::FOR_NO | FlowChart::WHILE_NO | \
2515 FlowChart::CASE_NO | FlowChart::LOOP_NO )
2516#define STARTFIN (FlowChart::START_NO | FlowChart::END_NO)
2517#define LOOP (FlowChart::FOR_NO | FlowChart::WHILE_NO | \
2518 FlowChart::LOOP_NO )
2519#define ENDCL (FlowChart::END_CASE | FlowChart::END_LOOP)
2520#define EEND (FlowChart::ENDIF_NO | FlowChart::ELSE_NO )
2521#define IFF (FlowChart::ELSIF_NO | FlowChart::IF_NO)
2522#define EXITNEXT (FlowChart::EXIT_NO | FlowChart::NEXT_NO )
2523#define EMPTY (EEND | FlowChart::ELSIF_NO)
2524#define EE (FlowChart::ELSE_NO | FlowChart::ELSIF_NO)
2525#define EMPTNODE (ENDCL | EEND | FlowChart::ELSIF_NO)
2526#define FLOWLEN (flowList.size()-1)
2527
2528static int ifcounter=0;
2529static int nodeCounter=0;
2530
2531static struct
2532{
2533 // link colors
2534 const char *textNodeLink;
2535 const char *yesNodeLink;
2536 const char *noNodeLink;
2537
2538 // node colors
2539 const char* comment;
2540 const char* decisionNode;
2541 const char* varNode;
2542 const char *startEndNode;
2543 const char* textNode;
2544} flowCol =
2545{ "green", // textNodeLink
2546 "red", // yesNodeLink
2547 "black", // noNodeLink
2548 "khaki", // comment
2549 "0.7 0.3 1.0", // decisionNode
2550 "lightyellow", // varNode
2551 "white", // startEndNode
2552 "lightcyan" // textNode
2554
2555std::vector<FlowChart> flowList;
2556
2557#ifdef DEBUGFLOW
2558static std::map<std::string,int> g_keyMap;
2559#endif
2560
2562{
2563 if (q.length()<=80) return;
2564
2565 if (q.length()>200)
2566 {
2567 q.resize(200);
2568 }
2569
2570 q.append(" ...");
2571
2572 QCString str(q);
2573 QCString temp;
2574
2575 while (str.length()>80)
2576 {
2577 int j=std::max(str.findRev(' ',80),str.findRev('|',80));
2578 if (j<=0)
2579 {
2580 temp+=str;
2581 q=temp;
2582 return;
2583 }
2584 else
2585 {
2586 QCString qcs=str.left(j);
2587 temp+=qcs+"\\";
2588 temp+="n";
2589 str.remove(0,j);
2590 }
2591 }//while
2592
2593 q=temp+str;
2594// #endif
2595}
2596
2598{
2599 QCString ui="-";
2600 std::string q;
2601 std::string t;
2602
2603 ui.fill('-',255);
2604
2605 if (flo.type & STARTL)
2606 {
2607 if (flo.stamp>0)
2608 {
2609 q=ui.left(2*flo.stamp).str();
2610 }
2611 else
2612 {
2613 q=" ";
2614 }
2615 QCString nn=flo.exp.stripWhiteSpace();
2616 printf("\nYES: %s%s[%d,%d]",qPrint(q),qPrint(nn),flo.stamp,flo.id);
2617 }
2618 else
2619 {
2620 if (flo.type & COMMENT_NO)
2621 {
2622 t=flo.label.str();
2623 }
2624 else
2625 {
2626 t=flo.text.str();
2627 }
2628 static const reg::Ex ep(R"(\s)");
2629 t = reg::replace(t,ep,std::string());
2630 if (t.empty())
2631 {
2632 t=" ";
2633 }
2634 if (flo.stamp>0)
2635 {
2636 q=ui.left(2*flo.stamp).str();
2637 }
2638 else
2639 {
2640 q=" ";
2641 }
2642 if (flo.type & EMPTNODE)
2643 {
2644 printf("\n NO: %s%s[%d,%d]",qPrint(q),FlowChart::getNodeType(flo.type),flo.stamp,flo.id);
2645 }
2646 else if (flo.type & COMMENT_NO)
2647 {
2648 printf("\n NO: %s%s[%d,%d]",qPrint(t),FlowChart::getNodeType(flo.type),flo.stamp,flo.id);
2649 }
2650 else
2651 {
2652 printf("\n NO: %s[%d,%d]",qPrint(t),flo.stamp,flo.id);
2653 }
2654 }
2655}
2656
2658{
2659 for (const auto &flowChart : flowList)
2660 {
2661 printNode(flowChart);
2662 }
2663}
2664
2666{
2667 FlowChart *flno = nullptr;
2668 bool found=FALSE;
2669 for (size_t j=0;j<flowList.size();j++)
2670 {
2671 FlowChart &flo = flowList[j];
2672 if (flo.type&TEXT_NO)
2673 {
2674 if (!found)
2675 {
2676 flno=&flo;
2677 }
2678 else
2679 {
2680 flno->text+=flo.text;
2681 flowList.erase(flowList.begin()+j);
2682 if (j>0) j=j-1;
2683 }
2684 found=TRUE;
2685 }
2686 else
2687 {
2688 found=FALSE;
2689 }
2690 }
2691
2692 // find if..endif without text
2693 // if..elseif without text
2694 if (!flowList.empty())
2695 {
2696 for (size_t j=0;j<flowList.size()-1;j++)
2697 {
2698 const FlowChart &flo = flowList[j];
2699 int kind = flo.type;
2700 if ( (kind & IFF) || (flo.type & ELSE_NO))
2701 {
2702 const FlowChart &ftemp = flowList[j+1];
2703 if (ftemp.type & EMPTY)
2704 {
2705 FlowChart fc(TEXT_NO,"empty ",QCString());
2706 fc.stamp = flo.stamp;
2707 flowList.insert(flowList.begin()+j+1,fc);
2708 }
2709 }
2710 }
2711 }
2712
2713}// colTextNode
2714
2716{
2717 QCString node;
2718 node.setNum(n);
2719 return node.prepend("node");
2720}
2721
2723{
2724 ifcounter=0;
2725 nodeCounter=0;
2726 flowList.clear();
2727}
2728
2730{
2731 size_t max=0;
2732 QCString s;
2733 StringVector ql=split(com.str(),"\n");
2734 for (size_t j=0;j<ql.size();j++)
2735 {
2736 s=ql[j];
2737 if (max<s.length()) max=s.length();
2738 }
2739
2740 s=ql.back();
2741 int diff=static_cast<int>(max-s.length());
2742
2743 QCString n;
2744 if (diff>0)
2745 {
2746 n.fill(' ',2*diff);
2747 n.append(".");
2748 s+=n;
2749 ql.pop_back();
2750 ql.push_back(s.str());
2751 }
2752
2753 for (size_t j=0;j<ql.size();j++)
2754 {
2755 s=ql[j];
2756 if (j<ql.size()-1)
2757 {
2758 s+="\n";
2759 }
2760 FlowChart::codify(t,s);
2761 }
2762}
2763
2764
2766{
2767 size_t size=flowList.size();
2768 bool begin=false;
2769
2770 if (size>0)
2771 {
2772 for (uint32_t j=0;j < size-1 ;j++)
2773 {
2774 FlowChart &fll = flowList[j];
2775 if (fll.type & COMMENT_NO)
2776 {
2777 FlowChart &to=flowList[j+1];
2778 if (to.type & COMMENT_NO)
2779 {
2780 to.label = fll.label+"\n"+to.label;
2781 flowList.erase(flowList.begin()+j);
2782 if (size>0) size--;
2783 if (j>0) j--;
2784 }
2785 }
2786 }// for
2787 }
2788
2789 for (size_t j=0;j <flowList.size() ;j++)
2790 {
2791 const FlowChart &fll=flowList[j];
2792
2793 if (fll.type & BEGIN_NO)
2794 {
2795 begin = true;
2796 continue;
2797 }
2798
2799 if (fll.type & COMMENT_NO)
2800 {
2801 const FlowChart *to = nullptr;
2802 if (!begin)
2803 {
2804 // comment between function/process .. begin is linked to start node
2805 to = &flowList[0];
2806 }
2807 else if (j>0 && flowList[j-1].line==fll.line)
2808 {
2809 to = &flowList[j-1];
2810 }
2811 else
2812 {
2813 to = &flowList[j+1];
2814 }
2815 t << getNodeName(fll.id);
2816 t << "[shape=none, label=<\n";
2817 t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
2818 t << "<TR><TD BGCOLOR=\"";
2819 t << flowCol.comment;
2820 t << "\" > ";
2821
2823 t << " </TD></TR></TABLE>>];";
2824 writeEdge(t,fll.id,to->id,2);
2825 }
2826 }// for
2827
2828 // delete comment nodes;
2829 size=flowList.size();
2830 for (size_t j=0; j<size; j++)
2831 {
2832 FlowChart &fll=flowList[j];
2833 if (fll.type & (COMMENT_NO | BEGIN_NO))
2834 {
2835 size_t diff=FLOWLEN-(j+1);
2836
2837 if ((fll.type & COMMENT_NO) && diff > 1)
2838 {
2839 flowList[j+1].label = fll.label;
2840 }
2841
2842 flowList.erase(flowList.begin()+j);
2843
2844 if (size>0) size--;
2845 if (j>0) j--;
2846 }
2847 }// for;
2848}
2849
2851{
2852 if (!str.isEmpty())
2853 {
2854 const char *p=str.data();
2855 while (*p)
2856 {
2857 char c=*p++;
2858 switch(c)
2859 {
2860 case '<': t << "&lt;"; break;
2861 case '>': t << "&gt;"; break;
2862 case '&': t << "&amp;"; break;
2863 case '\'': t << "&#39;"; break;
2864 case '"': t << "&quot;"; break;
2865 case '\n': t <<"<BR ALIGN=\"LEFT\"/>"; break;
2866 default: t << c; break;
2867 }
2868 }
2869 }
2870}//codify
2871
2872FlowChart::FlowChart(int typ,const QCString &t,const QCString &ex,const QCString &lab)
2873{
2875
2876 if (typ & STARTL)
2877 {
2878 ifcounter++;
2879 }
2880
2881 text=t;
2882 exp=ex;
2883 type=typ;
2884 label=lab;
2885
2886 if (typ & (ELSE_NO | ELSIF_NO))
2887 {
2888 stamp--;
2889 }
2890
2891 if (typ & (START_NO | END_NO | VARIABLE_NO))
2892 {
2893 stamp=0;
2894 }
2895
2896 id=nodeCounter++;
2897}
2898
2900{
2901 if (!VhdlDocGen::getFlowMember()) return;
2902
2903 QCString typeString(text);
2904 QCString expression(exp);
2905
2906
2907 if (!text.isEmpty())
2908 {
2909 typeString=substitute(typeString,";","\n");
2910 }
2911
2912 if (!exp.isEmpty())
2913 {
2914 expression=substitute(expression,"\"","\\\"");
2915 }
2916
2917 if (type & VARIABLE_NO)
2918 {
2919 // Ignore the empty section of the VHDL variable definition.
2920 // This is section between `process` and `begin` keywords, where any source text is missing, probably a bug in the VHDL source parser.
2921 if(text.isEmpty()) return;
2922
2923 flowList.insert(flowList.begin(),FlowChart(type,typeString,expression,label));
2924 flowList.front().line=1; // TODO: use getLine(); of the parser
2925 }
2926 else if (type & START_NO)
2927 {
2928 flowList.insert(flowList.begin(),FlowChart(type,typeString,expression,label));
2929 flowList.front().line=1; // TODO: use getLine(); of the parser
2930 }
2931 else
2932 {
2933 flowList.emplace_back(type,typeString,expression,label);
2934 flowList.back().line=1; // TODO: use getLine(); of the parser
2935 }
2936}
2937
2939{
2940 if (!VhdlDocGen::getFlowMember()) return;
2941 ifcounter--;
2942}
2943
2945{
2946 QCString t;
2949 switch (flo.type)
2950 {
2951 case START_NO: t=":"+text+"|"; break;
2952 case IF_NO : t="\nif ("+exp+") then (yes)"; break;
2953 case ELSIF_NO: t="\nelseif ("+exp+") then (yes)"; break;
2954 case ELSE_NO: t="\nelse"; break;
2955 case CASE_NO: t="\n:"+exp+";"; break;
2956 case WHEN_NO: t="\n";
2957 if (!ca) t+="else";
2958 t+="if ("+exp+") then (yes)";
2959 break;
2960 case EXIT_NO: break;
2961 case END_NO: if (text.contains(" function")==0) t="\n:"+text+";";
2962 break;
2963 case TEXT_NO: t="\n:"+text+"]"; break;
2964 case ENDIF_NO: t="\nendif"; break;
2965 case FOR_NO: t="\nwhile ("+exp+") is (yes)"; break;
2966 case WHILE_NO: t="\nwhile ("+exp+") is (yes)"; break;
2967 case END_LOOP: t="\nendwhile"; break;
2968 case END_CASE: t="\nendif\n:end case;"; break;
2969 case VARIABLE_NO:t="\n:"+text+";"; break;
2970 case RETURN_NO: t="\n:"+text+";";
2971 if (!endL) t+="\nstop";
2972 break;
2973 case LOOP_NO: t="\nwhile (infinite loop)"; break;
2974 case NEXT_NO: break;
2975 case EMPTY_NO: break;
2976 case COMMENT_NO: t="\n note left \n "+flo.label+"\nend note \n"; break;
2977 case BEGIN_NO: t="\n:begin;"; break;
2978 default: assert(false); break;
2979 }
2980 return t;
2981}
2982
2984{
2985 int caseCounter = 0;
2986 int whenCounter = 0;
2987
2988 QCString qcs;
2989 size_t size=flowList.size();
2990 for (size_t j=0;j<size;j++)
2991 {
2992 bool endList = j==FLOWLEN;
2993 const FlowChart &flo = flowList[j];
2994 if (flo.type==CASE_NO)
2995 {
2996 caseCounter++;
2997 whenCounter=0;
2998 }
2999
3000 if (flo.type==END_CASE)
3001 {
3002 caseCounter--;
3003 }
3004
3005 bool ca = (caseCounter>0 && whenCounter==0);
3006
3007 qcs+=printPlantUmlNode(flo,ca,endList);
3008
3009 if (flo.type==WHEN_NO)
3010 {
3011 whenCounter++;
3012 }
3013
3014 }
3015 qcs+="\n";
3016
3017 QCString htmlOutDir = Config_getString(HTML_OUTPUT);
3018
3020 auto baseNameVector=PlantumlManager::instance().writePlantUMLSource(htmlOutDir,n,qcs,PlantumlManager::PUML_SVG,"uml",n,1,true);
3021 for (const auto &baseName: baseNameVector)
3022 {
3024 }
3025}
3026
3031
3032const char* FlowChart::getNodeType(int c)
3033{
3034 switch(c)
3035 {
3036 case IF_NO: return "if ";
3037 case ELSIF_NO: return "elsif ";
3038 case ELSE_NO: return "else ";
3039 case CASE_NO: return "case ";
3040 case WHEN_NO: return "when ";
3041 case EXIT_NO: return "exit ";
3042 case END_NO: return "end ";
3043 case TEXT_NO: return "text ";
3044 case START_NO: return "start ";
3045 case ENDIF_NO: return "endif ";
3046 case FOR_NO: return "for ";
3047 case WHILE_NO: return "while ";
3048 case END_LOOP: return "end_loop ";
3049 case END_CASE: return "end_case ";
3050 case VARIABLE_NO: return "variable_decl ";
3051 case RETURN_NO: return "return ";
3052 case LOOP_NO: return "infinite loop ";
3053 case NEXT_NO: return "next ";
3054 case COMMENT_NO: return "comment ";
3055 case EMPTY_NO: return "empty ";
3056 case BEGIN_NO: return "<begin> ";
3057 default: return "--failure--";
3058 }
3059}
3060
3062{
3063 QCString qcs("/");
3064 QCString ov = Config_getString(HTML_OUTPUT);
3065
3067
3068 //const MemberDef *m=VhdlDocGen::getFlowMember();
3069 //if (m)
3070 // fprintf(stderr,"\n creating flowchart : %s %s in file %s \n",theTranslator->trVhdlType(m->getMemberSpecifiers(),TRUE),qPrint(m->name()),qPrint(m->getFileDef()->name()));
3071
3072 QCString dir=" -o \""+ov+qcs+"\"";
3073 ov+="/flow_design.dot";
3074
3075 QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
3076
3078 {
3079 err("could not create dot file\n");
3080 }
3081}
3082
3084{
3085 t << " digraph G { \n";
3086 t << "rankdir=TB \n";
3087 t << "concentrate=true\n";
3088 t << "stylesheet=\"doxygen.css\"\n";
3089}
3090
3092{
3093 t << " } \n";
3094}
3095
3097{
3098 // assert(VhdlDocGen::flowMember);
3099
3100 QCString ov = Config_getString(HTML_OUTPUT);
3101 QCString fileName = ov+"/flow_design.dot";
3102 std::ofstream f = Portable::openOutputStream(fileName);
3103 if (!f.is_open())
3104 {
3105 err("Cannot open file {} for writing\n",fileName);
3106 return;
3107 }
3108 TextStream t(&f);
3109
3110 colTextNodes();
3111 // buildCommentNodes(t);
3112
3113#ifdef DEBUGFLOW
3114 printFlowTree();
3115#endif
3116
3117 if (!Config_getString(PLANTUML_JAR_PATH).isEmpty())
3118 {
3119 printUmlTree();
3120 delFlowList();
3121 t.flush();
3122 f.close();
3123 return;
3124 }
3125
3126 startDot(t);
3128 for (const auto &fll : flowList)
3129 {
3130 writeShape(t,fll);
3131 }
3132 writeFlowLinks(t);
3133
3135 delFlowList();
3136 t.flush();
3137 f.close();
3139}// writeFlowChart
3140
3142{
3143 if (fl.type & EEND) return;
3144 QCString var;
3145 if (fl.type & LOOP)
3146 {
3147 var=" loop";
3148 }
3149 else if (fl.type & IFF)
3150 {
3151 var=" then";
3152 }
3153 else
3154 {
3155 var="";
3156 }
3157
3158 t << getNodeName(fl.id);
3159
3160#ifdef DEBUGFLOW
3161 QCString qq(getNodeName(fl.id));
3162 g_keyMap.emplace(qq.str(),fl.id);
3163#endif
3164
3165 bool dec=(fl.type & DECLN);
3166 bool exit=(fl.type & EXITNEXT);
3167 if (exit && !fl.exp.isEmpty())
3168 {
3169 dec=TRUE;
3170 }
3171 if (dec)
3172 {
3173 QCString exp=fl.exp;
3174 alignText(exp);
3175
3176 t << " [shape=diamond,style=filled,color=\"";
3177 t << flowCol.decisionNode;
3178 t << "\",label=\" ";
3179 QCString kl;
3180 if (exit) kl=fl.text+" ";
3181
3182 if (!fl.label.isEmpty())
3183 {
3184 kl+=fl.label+":"+exp+var;
3185 }
3186 else
3187 {
3188 kl+=exp+var;
3189 }
3190
3192 t << "\"]\n";
3193 }
3194 else if (fl.type & ENDCL)
3195 {
3196 QCString val=fl.text;
3197 t << " [shape=ellipse ,label=\""+val+"\"]\n";
3198 }
3199 else if (fl.type & STARTFIN)
3200 {
3201 QCString val=fl.text;
3202 t << "[shape=box , style=rounded label=<\n";
3203 t << "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" >\n ";
3204 t << "<TR><TD BGCOLOR=\"";
3205 t<< flowCol.startEndNode;
3206 t<< "\"> ";
3208 t << " </TD></TR></TABLE>>];";
3209 }
3210 else
3211 {
3212 if (fl.text.isEmpty()) return;
3213 bool isVar=(fl.type & FlowChart::VARIABLE_NO);
3214 QCString q=fl.text;
3215
3216 if (exit)
3217 {
3218 q+=" "+fl.label;
3219 }
3220
3221 int z=q.findRev("\n");
3222
3223 if (z==static_cast<int>(q.length())-1)
3224 {
3225 q=q.remove(z,2);
3226 }
3227 t << "[shape=none margin=0.1, label=<\n";
3228 t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
3229 if (isVar)
3230 {
3231 t << "<TR><TD BGCOLOR=\"" << flowCol.varNode << "\" > ";
3232 }
3233 else
3234 {
3235 t << "<TR><TD BGCOLOR=\"" << flowCol.textNode << "\" > ";
3236 }
3238 t << " </TD></TR></TABLE>>];";
3239 }
3240}
3241
3242
3243void FlowChart::writeEdge(TextStream &t,const FlowChart &fl_from,const FlowChart &fl_to,int i)
3244{
3245 bool b=fl_from.type & STARTL;
3246 bool c=fl_to.type & STARTL;
3247
3248#ifdef DEBUGFLOW
3249 QCString s1(getNodeName(fl_from.id));
3250 QCString s2(getNodeName(fl_to.id));
3251 auto it = g_keyMap.find(s1.str());
3252 auto it1 = g_keyMap.find(s2.str());
3253 // checks if the link is connected to a valid node
3254 assert(it!=g_keyMap.end());
3255 assert(it1!=g_keyMap.end());
3256#endif
3257
3258 writeEdge(t,fl_from.id,fl_to.id,i,b,c);
3259}
3260
3261void FlowChart::writeEdge(TextStream &t,int fl_from,int fl_to,int i,bool bFrom,bool bTo)
3262{
3263 QCString label,col;
3264
3265 if (i==0)
3266 {
3267 col=flowCol.yesNodeLink;
3268 label="yes";
3269 }
3270 else if (i==1)
3271 {
3272 col=flowCol.noNodeLink;
3273 label="no";
3274 }
3275 else
3276 {
3277 col=flowCol.textNodeLink;
3278 label="";
3279 }
3280
3281 t << "edge [color=\""+col+"\",label=\""+label+"\"]\n";
3282 t << getNodeName(fl_from);
3283 if (bFrom) t << ":s";
3284 t << "->";
3285 t << getNodeName(fl_to);
3286 if (bTo) t << ":n";
3287 t << "\n";
3288}
3289
3290void FlowChart::alignFuncProc( QCString & q,const ArgumentList &al,bool isFunc)
3291{
3292 size_t index=al.size();
3293 if (index==0) return;
3294
3295 size_t len=q.length()+VhdlDocGen::getFlowMember()->name().length();
3296 QCString prev,temp;
3297 prev.fill(' ',static_cast<int>(len)+1);
3298
3299 q+="\n";
3300 for (const Argument &arg : al)
3301 {
3302 QCString attl=arg.defval+" ";
3303 attl+=arg.name+" ";
3304
3305 if (!isFunc)
3306 {
3307 attl+=arg.attrib+" ";
3308 }
3309 else
3310 {
3311 attl+=" in ";
3312 }
3313 attl+=arg.type;
3314 if (--index) attl+=",\n"; else attl+="\n";
3315
3316 attl.prepend(prev);
3317 temp+=attl;
3318 }
3319
3320 q+=temp;
3321}
3322
3323size_t FlowChart::findNextLoop(size_t index,int stamp)
3324{
3325 for (size_t j=index+1; j<flowList.size(); j++)
3326 {
3327 const FlowChart &flo = flowList[j];
3328 if (flo.stamp==stamp)
3329 {
3330 continue;
3331 }
3332 if (flo.type&END_LOOP)
3333 {
3334 return j;
3335 }
3336 }
3337 return flowList.size()-1;
3338}
3339
3340size_t FlowChart::findPrevLoop(size_t index,int stamp,bool endif)
3341{
3342 for (size_t j=index;j>0;j--)
3343 {
3344 const FlowChart &flo = flowList[j];
3345 if (flo.type & LOOP)
3346 {
3347 if (flo.stamp==stamp && endif)
3348 {
3349 return j;
3350 }
3351 else
3352 {
3353 if (flo.stamp<stamp)
3354 {
3355 return j;
3356 }
3357 }
3358 }
3359 }
3360 return flowList.size()-1;
3361}
3362
3363size_t FlowChart::findLabel(size_t index,const QCString &label)
3364{
3365 for (size_t j=index;j>0;j--)
3366 {
3367 const FlowChart &flo = flowList[j];
3368 if ((flo.type & LOOP) && !flo.label.isEmpty() && qstricmp(flo.label,label)==0)
3369 {
3370 return j;
3371 }
3372 }
3373 err("could not find label: '{}'\n",label);
3374 return 0;
3375}
3376
3377size_t FlowChart::findNode(size_t index,int stamp,int type)
3378{
3379 for (size_t j=index+1; j<flowList.size(); j++)
3380 {
3381 const FlowChart &flo = flowList[j];
3382 if (flo.type==type && flo.stamp==stamp)
3383 {
3384 return j;
3385 }
3386 }
3387 return 0;
3388}// findNode
3389
3390size_t FlowChart::getNextNode(size_t index,int stamp)
3391{
3392 for (size_t j=index+1; j<flowList.size(); j++)
3393 {
3394 const FlowChart &flo = flowList[j];
3395 int kind = flo.type;
3396 int s = flo.stamp;
3397 if (s>stamp)
3398 {
3399 continue;
3400 }
3401 if (kind & ENDIF_NO)
3402 {
3403 if (s<stamp && stamp>0)
3404 {
3405 stamp--;
3406 continue;
3407 }
3408 }
3409 if (kind & (ELSE_NO | ELSIF_NO))
3410 {
3411 if (s<stamp && stamp>0)
3412 {
3413 stamp--;
3414 }
3415 j=findNode(j,stamp,ENDIF_NO);
3416 continue;
3417 }
3418 if (kind & WHEN_NO)
3419 {
3420 if (s<stamp && stamp>0)
3421 {
3422 stamp--;
3423 }
3424 return findNode(j,stamp-1,END_CASE);
3425 }
3426 return j;
3427 }
3428 return FLOWLEN;
3429}
3430
3431size_t FlowChart::getNextIfLink(const FlowChart &fl,size_t index)
3432{
3433 int stamp=fl.stamp;
3434 size_t start = index+1;
3435 size_t endifNode = findNode(start,stamp,ENDIF_NO);
3436 size_t elseifNode = findNode(start,stamp,ELSIF_NO);
3437 size_t elseNode = findNode(start,stamp,ELSE_NO);
3438
3439 if (elseifNode>0 && elseifNode<endifNode)
3440 {
3441 return elseifNode;
3442 }
3443
3444 if (elseNode>0 && elseNode<endifNode)
3445 {
3446 return elseNode+1;
3447 }
3448
3449 stamp=flowList[endifNode].stamp;
3450 return getNextNode(endifNode,stamp);
3451}
3452
3454{
3455 size_t size=flowList.size();
3456 if (size<2) return;
3457
3458 // write start link
3459 writeEdge(t,flowList[0],flowList[1],2);
3460
3461 for (size_t j=0;j<size;j++)
3462 {
3463 const FlowChart &fll = flowList[j];
3464 int kind = fll.type;
3465 int stamp = fll.stamp;
3466 if (kind & EEND)
3467 {
3468 continue;
3469 }
3470
3471 if (kind & IFF)
3472 {
3473 writeEdge(t,fll,flowList[j+1],0);
3474 size_t z=getNextIfLink(fll,j);
3475 // assert(z>-1);
3476 writeEdge(t,fll,flowList[z],1);
3477 }
3478 else if (kind & LOOP_NO)
3479 {
3480 writeEdge(t,fll,flowList[j+1],2);
3481 continue;
3482 }
3483 else if (kind & (CASE_NO | FOR_NO | WHILE_NO))
3484 {
3485 if (kind & CASE_NO)
3486 {
3487 writeEdge(t,fll,flowList[j+1],2);
3488 continue;
3489 }
3490 else
3491 {
3492 writeEdge(t,fll,flowList[j+1],0);
3493 }
3494
3495 kind=END_LOOP;
3496 size_t z=findNode(j+1,fll.stamp,kind);
3497 z=getNextNode(z,flowList[z].stamp);
3498
3499 // assert(z>-1);
3500 writeEdge(t,fll,flowList[z],1);
3501 continue;
3502 }
3503 else if (kind & (TEXT_NO | VARIABLE_NO))
3504 {
3505 size_t z=getNextNode(j,stamp);
3506 writeEdge(t,fll,flowList[z],2);
3507 }
3508 else if (kind & WHEN_NO)
3509 {
3510 // default value
3511 if (qstricmp(fll.text.simplifyWhiteSpace(),"others")==0)
3512 {
3513 writeEdge(t,fll,flowList[j+1],2);
3514 continue;
3515 }
3516
3517
3518 writeEdge(t,fll,flowList[j+1],0);
3519 size_t u=findNode(j,stamp,WHEN_NO);
3520 size_t v=findNode(j,stamp-1,END_CASE);
3521
3522 if (u>0 && u<v)
3523 {
3524 writeEdge(t,fll,flowList[u],1);
3525 }
3526 else
3527 {
3528 writeEdge(t,fll,flowList[v],1);
3529 }
3530 }
3531 else if (kind & END_CASE)
3532 {
3533 size_t z=FlowChart::getNextNode(j,fll.stamp);
3534 writeEdge(t,fll,flowList[z],2);
3535 }
3536 else if (kind & END_LOOP)
3537 {
3538 size_t z=findPrevLoop(j,fll.stamp,true);
3539 writeEdge(t,fll,flowList[z],2);
3540 }
3541 else if (kind & RETURN_NO)
3542 {
3543 writeEdge(t,fll,flowList[size-1],2);
3544 }
3545 else if (kind & (EXIT_NO | NEXT_NO))
3546 {
3547 size_t z = 0;
3548 bool b = kind==NEXT_NO;
3549 if (!fll.exp.isEmpty())
3550 {
3551 writeEdge(t,fll,flowList[j+1],1);
3552 }
3553 if (!fll.label.isEmpty())
3554 {
3555 z=findLabel(j,fll.label);
3556 if (b)
3557 {
3558 writeEdge(t,fll,flowList[z],0);
3559 }
3560 else
3561 {
3563 z=getNextNode(z,flowList[z].stamp);
3564 writeEdge(t,fll,flowList[z],0);
3565 }
3566 continue;
3567 }
3568 else
3569 {
3570 if (b)
3571 {
3572 z=findPrevLoop(j,fll.stamp);
3573 writeEdge(t,fll,flowList[z],0);
3574 continue;
3575 }
3576 else
3577 {
3578 z =findNextLoop(j,fll.stamp-1);
3579 }
3580 z=getNextNode(z,flowList[z].stamp);
3581 }
3582 writeEdge(t,fll,flowList[z],0);
3583 }
3584 } //for
3585} //writeFlowLinks
This class represents an function or template argument list.
Definition arguments.h:65
bool hasParameters() const
Definition arguments.h:76
size_t size() const
Definition arguments.h:100
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual void updateBaseClasses(const BaseClassList &bcd)=0
Update the list of base classes to the one passed.
virtual QCString className() const =0
Returns the name of the class including outer classes, but not including namespaces.
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
virtual int isBaseClass(const ClassDef *bcd, bool followInstances, const QCString &templSpec=QCString()) const =0
Returns TRUE iff bcd is a direct or indirect base class of this class.
virtual Protection protection() const =0
Return the protection level (Public,Protected,Private) in which this compound was found.
virtual MemberList * getMemberList(MemberListType lt) const =0
Returns the members in the list identified by lt.
virtual const ClassDef * templateMaster() const =0
Returns the template master of which this class is an instance.
virtual FileDef * getFileDef() const =0
Returns the namespace this compound is in, or 0 if it has a global scope.
virtual const BaseClassList & subClasses() const =0
Returns the list of sub classes that directly derive from this class.
virtual void insertBaseClass(ClassDef *, const QCString &name, Protection p, Specifier s, const QCString &t=QCString())=0
virtual void insertSubClass(ClassDef *, Protection p, Specifier s, const QCString &t=QCString())=0
virtual void insertMember(MemberDef *)=0
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual const QCString & localName() const =0
virtual int getEndBodyLine() const =0
virtual QCString getDefFileName() const =0
virtual bool isLinkable() const =0
virtual QCString anchor() const =0
virtual int briefLine() const =0
virtual QCString symbolName() const =0
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
virtual QCString getReference() const =0
virtual QCString documentation() const =0
virtual QCString qualifiedName() const =0
virtual QCString briefFile() const =0
virtual QCString getOutputFileBase() const =0
virtual Definition * getOuterScope() const =0
virtual int getStartBodyLine() const =0
virtual const QCString & name() const =0
virtual void setName(const QCString &name)=0
virtual void writeSourceRefs(OutputList &ol, const QCString &scopeName) const =0
virtual void writeSourceDef(OutputList &ol) const =0
virtual void setLanguage(SrcLangExt lang)=0
virtual void writeSourceReffedBy(OutputList &ol, const QCString &scopeName) const =0
virtual void writeDocAnchorsToTagFile(TextStream &) const =0
virtual void setBodyDef(const FileDef *fd)=0
static ParserManager * parserManager
Definition doxygen.h:128
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:95
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:111
static QCString verifiedDotPath
Definition doxygen.h:136
static SearchIndexIntf searchIndex
Definition doxygen.h:123
Represents an unstructured piece of information, about an entity found in the sources.
Definition entry.h:117
void moveToSubEntryAndKeep(Entry *e)
Definition entry.cpp:145
A model of a file symbol.
Definition filedef.h:99
virtual QCString absFilePath() const =0
static size_t findPrevLoop(size_t j, int stamp, bool endif=FALSE)
QCString label
Definition vhdldocgen.h:311
QCString text
Definition vhdldocgen.h:312
static void writeEdge(TextStream &t, int fl_from, int fl_to, int i, bool bFrom=FALSE, bool bTo=FALSE)
static void printFlowTree()
static void alignFuncProc(QCString &q, const ArgumentList &al, bool isFunc)
static void startDot(TextStream &t)
static const char * getNodeType(int c)
static void codify(TextStream &t, const QCString &str)
static size_t findLabel(size_t j, const QCString &)
static void addFlowChart(int type, const QCString &text, const QCString &exp, const QCString &label=QCString())
static void delFlowList()
static size_t getNextNode(size_t index, int stamp)
static void writeFlowChart()
static void colTextNodes()
static void createSVG()
static size_t findNextLoop(size_t j, int stamp)
static void writeShape(TextStream &t, const FlowChart &fl)
static size_t getNextIfLink(const FlowChart &, size_t)
static void printNode(const FlowChart &n)
static void moveToPrevLevel()
static QCString getNodeName(int n)
static QCString convertNameToFileName()
static void alignCommentNode(TextStream &t, QCString com)
static size_t findNode(size_t index, int stamp, int type)
static void buildCommentNodes(TextStream &t)
static void printUmlTree()
static void writeFlowLinks(TextStream &t)
FlowChart(int typ, const QCString &t, const QCString &ex, const QCString &label=QCString())
static void endDot(TextStream &t)
static QCString printPlantUmlNode(const FlowChart &flo, bool, bool)
QCString exp
Definition vhdldocgen.h:313
A model of a group of symbols.
Definition groupdef.h:52
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual QCString typeString() const =0
virtual bool hasDetailedDescription() const =0
virtual void warnIfUndocumented() const =0
virtual QCString excpString() const =0
virtual const ClassDef * getClassDef() const =0
virtual bool hasReferencesRelation() const =0
virtual GroupDef * getGroupDef()=0
virtual const FileDef * getFileDef() const =0
virtual const ArgumentList & argumentList() const =0
virtual VhdlSpecifier getVhdlSpecifiers() const =0
virtual ClassDef * getClassDefOfAnonymousType() const =0
virtual bool hasReferencedByRelation() const =0
virtual bool isBriefSectionVisible() const =0
virtual bool isVariable() const =0
virtual QCString argsString() const =0
virtual void setVhdlSpecifiers(VhdlSpecifier s)=0
virtual void setType(const QCString &t)=0
A list of MemberDef objects as shown in documentation sections.
Definition memberlist.h:125
MemberListType listType() const
Definition memberlist.h:130
const MemberGroupRefList & getMemberGroupList() const
Definition memberlist.h:166
Wrapper class for the MemberListType type.
Definition types.h:346
constexpr const char * toLabel() const noexcept
Definition types.h:402
void push_back(Ptr &&p)
Definition membername.h:54
An abstract interface of a namespace symbol.
void startFontClass(const QCString &c)
Definition outputlist.h:270
void startCodeFragment(const QCString &style)
Definition outputlist.h:279
Class representing a list of output generators that are written to in parallel.
Definition outputlist.h:315
bool isEnabled(OutputType o)
void writeString(const QCString &text)
Definition outputlist.h:411
void endParameterExtra(bool last, bool one, bool bracket)
Definition outputlist.h:694
void writeChar(char c)
Definition outputlist.h:529
void disable(OutputType o)
void endMemberDocName()
Definition outputlist.h:682
void insertMemberAlignLeft(OutputGenerator::MemberItemType typ=OutputGenerator::MemberItemType::Normal, bool templ=FALSE)
Definition outputlist.h:519
void startParameterExtra()
Definition outputlist.h:692
const OutputCodeList & codeGenerators() const
Definition outputlist.h:358
void startParameterList(bool openBracket)
Definition outputlist.h:700
void enable(OutputType o)
void endMemberDescription()
Definition outputlist.h:567
void endMemberGroupDocs()
Definition outputlist.h:511
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:439
void startMemberDescription(const QCString &anchor, const QCString &inheritId=QCString(), bool typ=false)
Definition outputlist.h:565
void endMemberGroupHeader(bool b)
Definition outputlist.h:507
void endDoxyAnchor(const QCString &fn, const QCString &anchor)
Definition outputlist.h:541
void docify(const QCString &s)
Definition outputlist.h:437
void endEmphasis()
Definition outputlist.h:527
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
void startMemberGroup()
Definition outputlist.h:513
void startMemberList()
Definition outputlist.h:481
void endTextLink()
Definition outputlist.h:444
void startBold()
Definition outputlist.h:561
void endMemberItem(OutputGenerator::MemberItemType type)
Definition outputlist.h:495
void endMemberList()
Definition outputlist.h:483
void addLabel(const QCString &fName, const QCString &anchor)
Definition outputlist.h:543
void pushGeneratorState()
void insertMemberAlign(bool templ=FALSE)
Definition outputlist.h:517
void startParameterType(bool first, const QCString &key)
Definition outputlist.h:684
void disableAllBut(OutputType o)
void endParameterName()
Definition outputlist.h:690
void popGeneratorState()
void endBold()
Definition outputlist.h:563
void startDoxyAnchor(const QCString &fName, const QCString &manName, const QCString &anchor, const QCString &name, const QCString &args)
Definition outputlist.h:537
void startEmphasis()
Definition outputlist.h:525
void endMemberGroup(bool last)
Definition outputlist.h:515
void startMemberGroupDocs()
Definition outputlist.h:509
void endParameterType()
Definition outputlist.h:686
void startParameterName(bool one)
Definition outputlist.h:688
void enableAll()
void endMemberHeader()
Definition outputlist.h:471
void endMemberSubtitle()
Definition outputlist.h:475
void startMemberItem(const QCString &anchor, OutputGenerator::MemberItemType type, const QCString &id=QCString())
Definition outputlist.h:493
void startMemberSubtitle()
Definition outputlist.h:473
void lineBreak(const QCString &style=QCString())
Definition outputlist.h:559
void parseText(const QCString &textStr)
void startMemberGroupHeader(const QCString &id, bool b)
Definition outputlist.h:505
void startTextLink(const QCString &file, const QCString &anchor)
Definition outputlist.h:442
void startMemberHeader(const QCString &anchor, int typ=2)
Definition outputlist.h:469
StringVector writePlantUMLSource(const QCString &outDirArg, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &engine, const QCString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:31
static PlantumlManager & instance()
Definition plantuml.cpp:231
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition plantuml.cpp:202
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:422
int toInt(bool *ok=nullptr, int base=10) const
Definition qcstring.cpp:254
QCString upper() const
Definition qcstring.h:254
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
QCString lower() const
Definition qcstring.h:249
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
QCString & remove(size_t index, size_t len)
Definition qcstring.h:442
void resize(size_t newlen)
Definition qcstring.h:180
QCString fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:193
const std::string & str() const
Definition qcstring.h:552
QCString & setNum(short n)
Definition qcstring.h:459
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:190
QCString & append(char c)
Definition qcstring.h:396
QCString right(size_t len) const
Definition qcstring.h:234
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96
QCString & replace(size_t index, size_t len, const char *s)
Definition qcstring.cpp:217
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
QCString left(size_t len) const
Definition qcstring.h:229
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:213
void clear()
Definition qcstring.h:182
Text streaming class that buffers data.
Definition textstream.h:36
void flush()
Flushes the buffer.
Definition textstream.h:196
static void findAllPackages(ClassDef *)
@ ARCHITECTURECLASS
Definition vhdldocgen.h:77
static bool writeVHDLTypeDocumentation(const MemberDef *mdef, const Definition *d, OutputList &ol)
static bool isArchitecture(const MemberDef *mdef)
static bool isGroup(const MemberDef *mdef)
static bool isSignal(const MemberDef *mdef)
static void correctMemberProperties(MemberDefMutable *md)
static bool writeClassType(const ClassDef *, OutputList &ol, QCString &cname)
static void writeFormatString(const QCString &, OutputList &ol, const MemberDef *)
static const MemberDef * getFlowMember()
static QCString convertArgumentListToString(const ArgumentList &al, bool f)
static void writeSource(const MemberDef *mdef, OutputList &ol, const QCString &cname)
static bool isProcess(const MemberDef *mdef)
static void writeVHDLDeclarations(const MemberList *ml, OutputList &ol, const ClassDef *cd, const NamespaceDef *nd, const FileDef *fd, const GroupDef *gd, const ModuleDef *mod, const QCString &title, const QCString &subtitle, bool showEnumValues, VhdlSpecifier type)
static bool isConstant(const MemberDef *mdef)
static QCString getClassName(const ClassDef *)
static bool isAttribute(const MemberDef *mdef)
static void createFlowChart(const MemberDef *)
static QCString getRecordNumber()
static void writeProcessProto(OutputList &ol, const ArgumentList &al, const MemberDef *)
static ClassDef * findVhdlClass(const QCString &className)
static const MemberDef * findMemberDef(ClassDef *cd, const QCString &key, MemberListType type)
This function returns the entity|package in which the key (type) is found.
static bool isLibrary(const MemberDef *mdef)
static QCString parseForBinding(QCString &entity, QCString &arch)
static QCString getProtectionName(int prot)
static QCString parseForConfig(QCString &entity, QCString &arch)
static bool isUnit(const MemberDef *mdef)
static void addBaseClass(ClassDef *cd, ClassDef *ent)
static void writeProcedureProto(OutputList &ol, const ArgumentList &al, const MemberDef *)
static bool isMisc(const MemberDef *mdef)
static bool isConfig(const MemberDef *mdef)
static void resetCodeVhdlParserState()
static bool isEntity(const MemberDef *mdef)
static QCString getProcessNumber()
static void writeInlineClassLink(const ClassDef *, OutputList &ol)
static bool isNumber(const std::string &s)
static void writeVhdlLink(const ClassDef *cdd, OutputList &ol, QCString &type, QCString &name, QCString &beh)
static bool isPort(const MemberDef *mdef)
static const MemberDef * findFunction(const QCString &name, const QCString &package)
static void writeTagFile(MemberDefMutable *mdef, TextStream &tagFile)
static void setFlowMember(const MemberDef *flowMember)
static bool isFile(const MemberDef *mdef)
static bool isSignals(const MemberDef *mdef)
static void prepareComment(QCString &)
static void writeRecUnitDocu(const MemberDef *md, OutputList &ol, QCString largs)
static bool deleteCharRev(QCString &s, char c)
static bool isVariable(const MemberDef *mdef)
static bool isVhdlFunction(const MemberDef *mdef)
static bool isVType(const MemberDef *mdef)
static void init()
static void writeVHDLDeclaration(MemberDefMutable *mdef, OutputList &ol, const ClassDef *cd, const NamespaceDef *nd, const FileDef *fd, const GroupDef *gd, const ModuleDef *mod, bool inGroup)
static void writeFunctionProto(OutputList &ol, const ArgumentList &al, const MemberDef *)
static void findAllArchitectures(std::vector< QCString > &ql, const ClassDef *cd)
static void parseFuncProto(const QCString &text, QCString &name, QCString &ret, bool doc=false)
static ClassDef * getClass(const QCString &name)
static void writeVhdlDeclarations(const MemberList *, OutputList &, const GroupDef *, const ClassDef *, const FileDef *, const NamespaceDef *, const ModuleDef *)
static void formatString(const QCString &, OutputList &ol, const MemberDef *)
static const ClassDef * findArchitecture(const ClassDef *cd)
static VhdlClasses convert(Protection prot)
Definition vhdldocgen.h:80
static bool isSubType(const MemberDef *mdef)
static const MemberDef * findMember(const QCString &className, const QCString &memName)
static bool isPackageBody(const MemberDef *mdef)
static void computeVhdlComponentRelations()
static bool isCompInst(const MemberDef *mdef)
static void writeStringLink(const MemberDef *mdef, QCString mem, OutputList &ol)
static bool isRecord(const MemberDef *mdef)
static void parseUCF(const QCString &input, Entry *entity, const QCString &f, bool vendor)
static bool isSubClass(ClassDef *cd, ClassDef *scd, bool followInstances, int level)
static bool isPackage(const MemberDef *mdef)
static void writeRecordUnit(QCString &largs, QCString &ltype, OutputList &ol, MemberDefMutable *mdef)
static QCString convertFileNameToClassName(const QCString &name)
static bool isComponent(const MemberDef *mdef)
static QCString getClassTitle(const ClassDef *)
static ClassDef * getPackageName(const QCString &name)
static bool isConstraint(const MemberDef *mdef)
static QCString getIndexWord(const QCString &, int index)
static bool isGeneric(const MemberDef *mdef)
static void deleteAllChars(QCString &s, char c)
static bool isProcedure(const MemberDef *mdef)
static bool writeFuncProcDocu(const MemberDef *mdef, OutputList &ol, const ArgumentList &al, bool type=false)
static bool isAlias(const MemberDef *mdef)
static const char * findKeyWord(const QCString &word)
static void writePlainVHDLDeclarations(const MemberList *ml, OutputList &ol, const ClassDef *cd, const NamespaceDef *nd, const FileDef *fd, const GroupDef *gd, const ModuleDef *mod, VhdlSpecifier specifier)
ClassDefMutable * toClassDefMutable(Definition *d)
ClassDef * toClassDef(Definition *d)
std::vector< BaseClassDef > BaseClassList
Definition classdef.h:81
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230
Interface for the comment block scanner.
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
std::set< std::string > StringSet
Definition containers.h:31
std::vector< std::string > StringVector
Definition containers.h:33
bool readCodeFragment(const QCString &fileName, bool isMacro, int &startLine, int &endLine, QCString &result)
Reads a fragment from file fileName starting with line startLine and ending with line endLine.
DirIterator begin(DirIterator it) noexcept
Definition dir.cpp:170
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
Translator * theTranslator
Definition language.cpp:71
MemberDefMutable * toMemberDefMutable(Definition *d)
std::unique_ptr< MemberDef > createMemberDef(const QCString &defFileName, int defLine, int defColumn, const QCString &type, const QCString &name, const QCString &args, const QCString &excp, Protection prot, Specifier virt, bool stat, Relationship related, MemberType t, const ArgumentList &tal, const ArgumentList &al, const QCString &metaData)
Factory method to create a new instance of a MemberDef.
#define err(fmt,...)
Definition message.h:127
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:648
int system(const QCString &command, const QCString &args, bool commandHasConsole=true)
Definition portable.cpp:105
Namespace for the regular expression functions.
Definition regex.cpp:31
std::string replace(std::string_view str, const Ex &re, std::string_view replacement)
Searching in a given input string for parts that match regular expression re and replaces those parts...
Definition regex.cpp:866
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855
Portable versions of functions that are platform dependent.
int qstricmp(const char *s1, const char *s2)
Definition qcstring.cpp:530
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:571
#define qsnprintf
Definition qcstring.h:49
const char * qPrint(const char *s)
Definition qcstring.h:687
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
uint32_t qstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition qcstring.h:58
#define ASSERT(x)
Definition qcstring.h:39
Web server based search engine.
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:72
This class contains the information about the argument of a function or template.
Definition arguments.h:27
Options to configure the code parser.
Definition parserintf.h:78
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:101
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:107
CodeParserOptions & setEndLine(int lineNr)
Definition parserintf.h:104
CodeParserOptions & setMemberDef(const MemberDef *md)
Definition parserintf.h:110
This struct is used to capture the tag file information for an Entry.
Definition entry.h:104
QCString anchor
Definition entry.h:107
QCString fileName
Definition entry.h:106
QCString tagName
Definition entry.h:105
@ Variable
Definition types.h:555
VhdlSpecifier
Definition types.h:730
@ INSTANTIATION
Definition types.h:751
@ MISCELLANEOUS
Definition types.h:757
@ SHAREDVARIABLE
Definition types.h:754
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:3911
int findIndex(const StringVector &sv, const std::string &s)
find the index of a string in a vector of strings, returns -1 if the string could not be found
Definition util.cpp:6672
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
Definition util.cpp:6636
QCString convertToId(const QCString &s)
Definition util.cpp:3871
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4920
A bunch of utility functions.
static std::vector< ClassDef * > g_classList
static void initUCF(Entry *root, const QCString &type, QCString &qcs, int line, const QCString &fileName, QCString &brief)
static const MemberDef * findMemFlow(const MemberDef *mdef)
const char * noNodeLink
static void writeUCFLink(const MemberDef *mdef, OutputList &ol)
#define FLOWLEN
#define IFF
#define EMPTY
static const std::unordered_set< std::string > g_vhdlKeyWordSet0
static std::vector< const MemberDef * > mdList
static int nodeCounter
static std::map< std::string, const MemberDef * > g_varMap
static void startFonts(const QCString &q, const char *keyword, OutputList &ol)
const char * decisionNode
static std::map< ClassDef *, std::vector< ClassDef * > > g_packages
#define ENDCL
static const MemberDef * flowMember
static int recordCounter
std::vector< FlowChart > flowList
#define theTranslator_vhdlType
static void writeLink(const MemberDef *mdef, OutputList &ol)
static struct @262143045100337216022015277174266365223104043217 flowCol
static QCString splitString(QCString &str, char c)
const char * yesNodeLink
#define EMPTNODE
#define LOOP
static bool membersHaveSpecificType(const MemberList *ml, VhdlSpecifier type)
const char * textNodeLink
static const std::unordered_set< std::string > g_vhdlKeyWordSet2
#define DECLN
static int ifcounter
static VhdlSpecifier getSpecifierTypeFromClass(const ClassDef *cd)
static void addInstance(ClassDefMutable *entity, ClassDefMutable *arch, ClassDefMutable *inst, const std::shared_ptr< Entry > &cur)
const char * varNode
void alignText(QCString &q)
#define STARTFIN
const char * textNode
static int compareString(const QCString &s1, const QCString &s2)
static const std::unordered_set< std::string > g_vhdlKeyWordSet3
#define EEND
const char * startEndNode
const char * comment
static std::recursive_mutex g_vhdlMutex
#define EXITNEXT
static const std::unordered_set< std::string > g_vhdlKeyWordSet1
#define STARTL
std::vector< FlowChart > flowList
const EntryList & getVhdlInstList()