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