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
187 return "keywordflow";
188
190 return "keywordtype";
191
193 return "vhdllogic";
194
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 QCString nn=cd->name();
552 for (const auto &citer : *Doxygen::classLinkedMap)
553 {
554 QCString jj=citer->name();
555 StringVector ql=split(jj.str(),":");
556 if (ql.size()>1)
557 {
558 if (QCString(ql[0])==nn)
559 {
560 return citer.get();
561 }
562 }
563 }
564 return nullptr;
565}
566/*
567 * writes the link entity >> .... or architecture >> ...
568 */
569
571{
572 if (ccd==nullptr) return;
573 ol.startBold();
574 ol.docify(type);
575 ol.endBold();
576 nn.stripPrefix("_");
578
579 if (!behav.isEmpty())
580 {
581 behav.prepend(" ");
582 ol.startBold();
583 ol.docify(behav);
584 ol.endBold();
585 }
586
587 ol.lineBreak();
588}
589
590
591/*!
592 * strips the "--!" prefixes of vhdl comments
593 */
595{
596 qcs=qcs.stripWhiteSpace();
597 if (qcs.isEmpty()) return;
598
599 const char* sc="--!";
600 if (qcs.startsWith(sc)) qcs = qcs.mid(qstrlen(sc));
601 static const reg::Ex re(R"(\n[ \t]*--!)");
602 std::string s = qcs.str();
603 reg::Iterator iter(s,re);
605 std::string result;
606 size_t p=0;
607 size_t sl=s.length();
608 for ( ; iter!=end ; ++iter)
609 {
610 const auto &match = *iter;
611 size_t i = match.position();
612 result+="\n";
613 result+=s.substr(p,i-p);
614 p = match.position()+match.length();
615 }
616 if (p<sl)
617 {
618 result+="\n";
619 result+=s.substr(p);
620 }
621
622 qcs = result;
623 qcs=qcs.stripWhiteSpace();
624}
625
626
627/*!
628 * parses a function proto
629 * @param text function string
630 * @param name points to the function name
631 * @param ret Stores the return type
632 * @param doc ???
633 */
634void VhdlDocGen::parseFuncProto(const QCString &text,QCString& name,QCString& ret,bool doc)
635{
636 QCString s1(text);
637 QCString temp;
638
639 int index=s1.find("(");
640 if (index<0) index=0;
641 int end=s1.findRev(")");
642
643 if ((end-index)>0)
644 {
645 temp=s1.mid(index+1,(end-index-1));
646 //getFuncParams(qlist,temp);
647 }
648 if (doc)
649 {
650 name=s1.left(index);
651 name=name.stripWhiteSpace();
652 if ((end-index)>0)
653 {
654 ret="function";
655 }
656 return;
657 }
658 else
659 {
660 s1=s1.stripWhiteSpace();
661 int i=s1.find('(');
662 int s=s1.find(' ');
663 if (s==-1) s=s1.find('\t');
664 if (i==-1 || i<s)
666 else // s<i, s=start of name, i=end of name
667 s1=s1.mid(s,(i-s));
668
669 name=s1.stripWhiteSpace();
670 }
671 index=s1.findRev("return",-1,FALSE);
672 if (index !=-1)
673 {
674 ret=s1.mid(index+6,s1.length());
675 ret=ret.stripWhiteSpace();
677 }
678}
679
680/*
681 * returns the n'th word of a string
682 */
683
685{
686 static const reg::Ex reg(R"([\s:|])");
687 auto ql=split(c.str(),reg);
688
689 if (index < static_cast<int>(ql.size()))
690 {
691 return QCString(ql[index]);
692 }
693
694 return "";
695}
696
697
699{
700 if (prot==VhdlDocGen::ENTITYCLASS)
701 return "entity";
702 else if (prot==VhdlDocGen::ARCHITECTURECLASS)
703 return "architecture";
704 else if (prot==VhdlDocGen::PACKAGECLASS)
705 return "package";
706 else if (prot==VhdlDocGen::PACKBODYCLASS)
707 return "package body";
708
709 return "";
710}
711
712/*!
713 * deletes a char backwards in a string
714 */
715
717{
718 int index=s.findRev(c,-1,FALSE);
719 if (index > -1)
720 {
721 s = s.remove(index,1);
722 return TRUE;
723 }
724 return FALSE;
725}
726
728{
729 int index=s.findRev(c,-1,FALSE);
730 while (index > -1)
731 {
732 s = s.remove(index,1);
733 index=s.findRev(c,-1,FALSE);
734 }
735}
736
737
738static int recordCounter=0;
739
740/*!
741 * returns the next number of a record|unit member
742 */
743
745{
746 char buf[12];
747 qsnprintf(buf,12,"%d",recordCounter++);
748 QCString qcs(&buf[0]);
749 return qcs;
750}
751
752/*!
753 * returns the next number of an anonymous process
754 */
755
757{
758 static int stringCounter;
759 QCString qcs("PROCESS_");
760 char buf[8];
761 qsnprintf(buf,8,"%d",stringCounter++);
762 qcs.append(&buf[0]);
763 return qcs;
764}
765
766/*!
767 * writes a colored and formatted string
768 */
769
771{
772 static const reg::Ex reg(R"([\[\]./<>:\s,;'+*|&=()\"-])");
773 QCString qcs = s;
774 qcs+=QCString(" ");// parsing the last sign
775 QCString find=qcs;
776 QCString temp=qcs;
777 char buf[2];
778 buf[1]='\0';
779
780 int j = findIndex(temp.str(),reg);
781
782 ol.startBold();
783 if (j>=0)
784 {
785 while (j>=0)
786 {
787 find=find.left(j);
788 buf[0]=temp[j];
789 const char *ss=VhdlDocGen::findKeyWord(find);
790 bool k=isNumber(find.str()); // is this a number
791 if (k)
792 {
793 ol.docify(" ");
794 startFonts(find,"vhdldigit",ol);
795 ol.docify(" ");
796 }
797 else if (j != 0 && ss)
798 {
799 startFonts(find,ss,ol);
800 }
801 else
802 {
803 if (j>0)
804 {
805 VhdlDocGen::writeStringLink(mdef,find,ol);
806 }
807 }
808 startFonts(&buf[0],"vhdlchar",ol);
809
810 QCString st=temp.remove(0,j+1);
811 find=st;
812 if (!find.isEmpty() && find.at(0)=='"')
813 {
814 int ii=find.find('"',2);
815 if (ii>1)
816 {
817 QCString com=find.left(ii+1);
818 startFonts(com,"keyword",ol);
819 temp=find.remove(0,ii+1);
820 }
821 }
822 else
823 {
824 temp=st;
825 }
826 j = findIndex(temp.str(),reg);
827 }//while
828 }//if
829 else
830 {
831 startFonts(find,"vhdlchar",ol);
832 }
833 ol.endBold();
834}// writeFormatString
835
836/*!
837 * returns TRUE if this string is a number
838 */
839bool VhdlDocGen::isNumber(const std::string& s)
840{
841 static const reg::Ex regg(R"([0-9][0-9eEfFbBcCdDaA_.#+?xXzZ-]*)");
842 return reg::match(s,regg);
843}// isNumber
844
845
846/*!
847 * inserts white spaces for better readings
848 * and writes a colored string to the output
849 */
850
852{
853 QCString qcs = s;
854 QCString temp;
855 qcs.stripPrefix(":");
856 qcs.stripPrefix("is");
857 qcs.stripPrefix("IS");
858 qcs.stripPrefix("of");
859 qcs.stripPrefix("OF");
860
861 size_t len = qcs.length();
862 size_t index=1;
863
864 for (size_t j=0;j<len;j++)
865 {
866 char c=qcs[j];
867 char b=c;
868 if (j>0) b=qcs[j-1];
869 if (c=='"' || c==',' || c=='\''|| c=='(' || c==')' || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>'))
870 {
871 if (temp.length()>=index && temp.at(index-1) != ' ')
872 {
873 temp+=" ";
874 }
875 temp+=c;
876 temp+=" ";
877 }
878 else if (c=='=')
879 {
880 if (b==':') // := operator
881 {
882 temp.replace(index-1,1,"=");
883 temp+=" ";
884 }
885 else // = operator
886 {
887 temp+=" ";
888 temp+=c;
889 temp+=" ";
890 }
891 }
892 else
893 {
894 temp+=c;
895 }
896
897 index=temp.length();
898 }// for
899 temp=temp.stripWhiteSpace();
900 // printf("\n [%s]",qPrint(qcs));
901 VhdlDocGen::writeFormatString(temp,ol,mdef);
902}
903
904/*!
905 * writes a procedure prototype to the output
906 */
907
909{
910 bool sem=FALSE;
911 size_t len=al.size();
912 ol.docify("( ");
913 if (len > 2)
914 {
915 ol.lineBreak();
916 }
917 for (const Argument &arg : al)
918 {
919 ol.startBold();
920 if (sem && len <3)
921 ol.writeChar(',');
922
923 QCString nn=arg.name;
924 nn+=": ";
925
926 QCString defval = arg.defval;
927 const char *str=VhdlDocGen::findKeyWord(defval);
928 defval+=" ";
929 if (str)
930 {
931 startFonts(defval,str,ol);
932 }
933 else
934 {
935 startFonts(defval,"vhdlchar",ol); // write type (variable,constant etc.)
936 }
937
938 startFonts(nn,"vhdlchar",ol); // write name
939 if (qstricmp(arg.attrib,arg.type) != 0)
940 {
941 startFonts(arg.attrib.lower(),"stringliteral",ol); // write in|out
942 }
943 ol.docify(" ");
944 VhdlDocGen::formatString(arg.type,ol,mdef);
945 sem=TRUE;
946 ol.endBold();
947 if (len > 2)
948 {
949 ol.lineBreak();
950 ol.docify(" ");
951 }
952 }//for
953
954 ol.docify(" )");
955
956
957}
958
959/*!
960 * writes a function prototype to the output
961 */
962
964{
965 if (!al.hasParameters()) return;
966 bool sem=FALSE;
967 size_t len=al.size();
968 ol.startBold();
969 ol.docify(" ( ");
970 ol.endBold();
971 if (len>2)
972 {
973 ol.lineBreak();
974 }
975 for (const Argument &arg : al)
976 {
977 ol.startBold();
978 QCString att=arg.defval;
979 bool bGen=att.stripPrefix("generic");
980
981 if (sem && len < 3)
982 {
983 ol.docify(" , ");
984 }
985
986 if (bGen)
987 {
988 VhdlDocGen::formatString(QCString("generic "),ol,mdef);
989 }
990 if (!att.isEmpty())
991 {
992 const char *str=VhdlDocGen::findKeyWord(att);
993 att+=" ";
994 if (str)
995 VhdlDocGen::formatString(att,ol,mdef);
996 else
997 startFonts(att,"vhdlchar",ol);
998 }
999
1000 QCString nn=arg.name;
1001 nn+=": ";
1002 QCString ss=arg.type.stripWhiteSpace(); //.lower();
1003 QCString w=ss.stripWhiteSpace();//.upper();
1004 startFonts(nn,"vhdlchar",ol);
1005 startFonts("in ","stringliteral",ol);
1006 const char *str=VhdlDocGen::findKeyWord(ss);
1007 if (str)
1008 VhdlDocGen::formatString(w,ol,mdef);
1009 else
1010 startFonts(w,"vhdlchar",ol);
1011
1012 if (!arg.attrib.isEmpty())
1013 startFonts(arg.attrib,"vhdlchar",ol);
1014
1015 sem=TRUE;
1016 ol.endBold();
1017 if (len > 2)
1018 {
1019 ol.lineBreak();
1020 }
1021 }
1022 ol.startBold();
1023 ol.docify(" )");
1024 QCString exp=mdef->excpString();
1025 if (!exp.isEmpty())
1026 {
1027 ol.insertMemberAlign();
1028 ol.startBold();
1029 ol.docify("[ ");
1030 ol.docify(exp);
1031 ol.docify(" ]");
1032 ol.endBold();
1033 }
1034 ol.endBold();
1035}
1036
1037/*!
1038 * writes a process prototype to the output
1039 */
1040
1042{
1043 if (!al.hasParameters()) return;
1044 bool sem=FALSE;
1045 ol.startBold();
1046 ol.docify(" ( ");
1047 for (const Argument &arg : al)
1048 {
1049 if (sem)
1050 {
1051 ol.docify(" , ");
1052 }
1053 QCString nn=arg.name;
1054 // startFonts(nn,"vhdlchar",ol);
1056 sem=TRUE;
1057 }
1058 ol.docify(" )");
1059 ol.endBold();
1060}
1061
1062
1063/*!
1064 * writes a function|procedure documentation to the output
1065 */
1066
1068 const MemberDef *md,
1069 OutputList& ol,
1070 const ArgumentList &al,
1071 bool /*type*/)
1072{
1073 //bool sem=FALSE;
1074 ol.enableAll();
1075
1076 size_t index=al.size();
1077 if (index==0)
1078 {
1079 ol.docify(" ( ) ");
1080 return FALSE;
1081 }
1082 ol.endMemberDocName();
1084 //ol.startParameterName(FALSE);
1085 bool first=TRUE;
1086 for (const Argument &arg : al)
1087 {
1088 ol.startParameterType(first,"");
1089 // if (first) ol.writeChar('(');
1090 QCString attl=arg.defval;
1091
1092 //bool bGen=attl.stripPrefix("generic");
1093 //if (bGen)
1094 // VhdlDocGen::writeFormatString(QCString("generic "),ol,md);
1095
1096
1098 {
1099 startFonts(arg.defval,"keywordtype",ol);
1100 ol.docify(" ");
1101 }
1102 ol.endParameterType();
1103
1105 VhdlDocGen::writeFormatString(arg.name,ol,md);
1106
1108 {
1109 startFonts(arg.attrib,"stringliteral",ol);
1110 }
1111 else if (VhdlDocGen::isVhdlFunction(md))
1112 {
1113 startFonts(QCString("in"),"stringliteral",ol);
1114 }
1115
1116 ol.docify(" ");
1118 ol.startEmphasis();
1120 if (!VhdlDocGen::isProcess(md))
1121 {
1122 // startFonts(arg.type,"vhdlkeyword",ol);
1123 VhdlDocGen::writeFormatString(arg.type,ol,md);
1124 }
1126 ol.endEmphasis();
1128
1129 if (--index)
1130 {
1131 ol.docify(" , ");
1132 }
1133 else
1134 {
1135 // ol.docify(" ) ");
1136 ol.endParameterName();
1138 ol.endParameterExtra(true,false,true);
1139 break;
1140 }
1141 ol.endParameterName();
1143 ol.endParameterExtra(false,false,false);
1144
1145 //sem=TRUE;
1146 first=FALSE;
1147 }
1148 //ol.endParameterList();
1149 return TRUE;
1150
1151} // writeDocFunProc
1152
1153
1154
1155
1157{
1158 QCString argString;
1159 bool sem=FALSE;
1160
1161 for (const Argument &arg : al)
1162 {
1163 if (sem) argString.append(", ");
1164 if (func)
1165 {
1166 argString+=arg.name;
1167 argString+=":";
1168 argString+=arg.type;
1169 }
1170 else
1171 {
1172 argString+=arg.defval+" ";
1173 argString+=arg.name+" :";
1174 argString+=arg.attrib+" ";
1175 argString+=arg.type;
1176 }
1177 sem=TRUE;
1178 }
1179 return argString;
1180}
1181
1182
1184 OutputList& ol,const GroupDef* gd,const ClassDef* cd,const FileDef *fd,const NamespaceDef* nd,const ModuleDef *mod)
1185{
1207
1208 // configurations must be added to global file definitions.
1211
1212}
1213
1215{
1216 if (md->argsString()=="package")
1217 {
1219 }
1220 else if (md->argsString()=="configuration")
1221 {
1223 }
1224 else if (md->typeString()=="library")
1225 {
1227 }
1228 else if (md->typeString()=="use")
1229 {
1231 }
1232 else if (md->typeString().lower()=="misc")
1233 {
1235 }
1236 else if (md->typeString().lower()=="ucf_const")
1237 {
1239 }
1240
1242 {
1243 int mm=md->name().findRev('_');
1244 if (mm>0)
1245 {
1246 md->setName(md->name().left(mm));
1247 }
1248 }
1249 else if (md->getVhdlSpecifiers()==VhdlSpecifier::TYPE)
1250 {
1251 QCString largs=md->argsString();
1252 bool bRec=largs.stripPrefix("record") ;
1253 bool bUnit=largs.stripPrefix("units") ;
1254 if (bRec || bUnit)
1255 {
1256 md->setType("");
1257 }
1258 }
1259}
1260
1261/* writes a vhdl type documentation */
1263{
1264 const ClassDef *cd=toClassDef(d);
1265 bool hasParams = FALSE;
1266
1267 if (cd==nullptr) return hasParams;
1268
1269 QCString ttype=mdef->typeString();
1270 QCString largs=mdef->argsString();
1271
1273 {
1274 QCString nn=mdef->typeString();
1275 nn=nn.stripWhiteSpace();
1276 QCString na=cd->name();
1277 const MemberDef* memdef=VhdlDocGen::findMember(na,nn);
1278 if (memdef && memdef->isLinkable())
1279 {
1280 ol.docify(" ");
1281
1282 ol.startBold();
1283 writeLink(memdef,ol);
1284 ol.endBold();
1285 ol.docify(" ");
1286 }
1287 else
1288 {
1289 ol.docify(" ");
1290 VhdlDocGen::formatString(ttype,ol,mdef);
1291 ol.docify(" ");
1292 }
1293 ol.docify(mdef->name());
1294 hasParams = VhdlDocGen::writeFuncProcDocu(mdef,ol, mdef->argumentList());
1295 }
1296
1297
1298 if (mdef->isVariable())
1299 {
1300 if (VhdlDocGen::isConstraint(mdef))
1301 {
1302 writeLink(mdef,ol);
1303 ol.docify(" ");
1304
1305 largs=substitute(largs,"#"," ");
1306 VhdlDocGen::formatString(largs,ol,mdef);
1307 return hasParams;
1308 }
1309 else
1310 {
1311 writeLink(mdef,ol);
1313 {
1314 return hasParams;
1315 }
1316 ol.docify(" ");
1317 }
1318
1319 // QCString largs=mdef->argsString();
1320
1321 bool c=largs=="context";
1322 bool brec=largs.stripPrefix("record") ;
1323
1324 if (!brec && !c)
1325 VhdlDocGen::formatString(ttype,ol,mdef);
1326
1327 if (c || brec || largs.stripPrefix("units"))
1328 {
1329 if (c)
1330 largs=ttype;
1331 VhdlDocGen::writeRecUnitDocu(mdef,ol,largs);
1332 return hasParams;
1333 }
1334
1335 ol.docify(" ");
1336 if (VhdlDocGen::isPort(mdef) || VhdlDocGen::isGeneric(mdef))
1337 {
1338 // QCString largs=mdef->argsString();
1339 VhdlDocGen::formatString(largs,ol,mdef);
1340 ol.docify(" ");
1341 }
1342 }
1343 return hasParams;
1344}
1345
1347{
1348 tagFile << " <member kind=\"";
1349 if (VhdlDocGen::isGeneric(mdef)) tagFile << "generic";
1350 if (VhdlDocGen::isPort(mdef)) tagFile << "port";
1351 if (VhdlDocGen::isEntity(mdef)) tagFile << "entity";
1352 if (VhdlDocGen::isComponent(mdef)) tagFile << "component";
1353 if (VhdlDocGen::isVType(mdef)) tagFile << "type";
1354 if (VhdlDocGen::isConstant(mdef)) tagFile << "constant";
1355 if (VhdlDocGen::isSubType(mdef)) tagFile << "subtype";
1356 if (VhdlDocGen::isVhdlFunction(mdef)) tagFile << "function";
1357 if (VhdlDocGen::isProcedure(mdef)) tagFile << "procedure";
1358 if (VhdlDocGen::isProcess(mdef)) tagFile << "process";
1359 if (VhdlDocGen::isSignals(mdef)) tagFile << "signal";
1360 if (VhdlDocGen::isAttribute(mdef)) tagFile << "attribute";
1361 if (VhdlDocGen::isRecord(mdef)) tagFile << "record";
1362 if (VhdlDocGen::isLibrary(mdef)) tagFile << "library";
1363 if (VhdlDocGen::isPackage(mdef)) tagFile << "package";
1364 if (VhdlDocGen::isVariable(mdef)) tagFile << "shared variable";
1365 if (VhdlDocGen::isFile(mdef)) tagFile << "file";
1366 if (VhdlDocGen::isGroup(mdef)) tagFile << "group";
1367 if (VhdlDocGen::isCompInst(mdef)) tagFile << "instantiation";
1368 if (VhdlDocGen::isAlias(mdef)) tagFile << "alias";
1369 if (VhdlDocGen::isCompInst(mdef)) tagFile << "configuration";
1370
1371 QCString fn = mdef->getOutputFileBase();
1373 tagFile << "\">\n";
1374 tagFile << " <type>" << convertToXML(mdef->typeString()) << "</type>\n";
1375 tagFile << " <name>" << convertToXML(mdef->name()) << "</name>\n";
1376 tagFile << " <anchorfile>" << convertToXML(fn) << "</anchorfile>\n";
1377 tagFile << " <anchor>" << convertToXML(mdef->anchor()) << "</anchor>\n";
1378
1380 tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),TRUE)) << "</arglist>\n";
1381 else if (VhdlDocGen::isProcedure(mdef))
1382 tagFile << " <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),FALSE)) << "</arglist>\n";
1383 else
1384 tagFile << " <arglist>" << convertToXML(mdef->argsString()) << "</arglist>\n";
1385
1386 mdef->writeDocAnchorsToTagFile(tagFile);
1387 tagFile << " </member>\n";
1388}
1389
1390/* writes a vhdl type declaration */
1391
1393 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1394 bool /*inGroup*/)
1395{
1396 const Definition *d=nullptr;
1397
1398 ASSERT(cd!=nullptr || nd!=nullptr || fd!=nullptr || gd!=nullptr || mod!=nullptr ||
1401 ); // member should belong to something
1402 if (cd) d=cd;
1403 else if (nd) d=nd;
1404 else if (fd) d=fd;
1405 else if (mod) d=mod;
1406 else if (gd) d=gd;
1407 else d=mdef;
1408
1409 // write search index info
1410 if (Doxygen::searchIndex.enabled())
1411 {
1412 Doxygen::searchIndex.setCurrentDoc(mdef,mdef->anchor(),FALSE);
1413 Doxygen::searchIndex.addWord(mdef->localName(),TRUE);
1414 Doxygen::searchIndex.addWord(mdef->qualifiedName(),FALSE);
1415 }
1416
1417 QCString cname = d->name();
1418 QCString cfname = d->getOutputFileBase();
1419
1420 //HtmlHelp *htmlHelp=nullptr;
1421 // bool hasHtmlHelp = Config_getBool(GENERATE_HTML) && Config_getBool(GENERATE_HTMLHELP);
1422 // if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
1423
1424 // search for the last anonymous scope in the member type
1425 ClassDef *annoClassDef=mdef->getClassDefOfAnonymousType();
1426
1427 // start a new member declaration
1430 ///printf("startMemberItem for %s\n",qPrint(name()));
1434
1435 ol.startMemberItem( mdef->anchor(), memType );
1436
1437 // If there is no detailed description we need to write the anchor here.
1438 bool detailsVisible = mdef->hasDetailedDescription();
1439 if (!detailsVisible)
1440 {
1441 QCString doxyName=mdef->name();
1442 if (!cname.isEmpty()) doxyName.prepend(cname+"::");
1443 QCString doxyArgs=mdef->argsString();
1444 ol.startDoxyAnchor(cfname,cname,mdef->anchor(),doxyName,doxyArgs);
1445 ol.addLabel(cfname,mdef->anchor());
1446
1447 ol.pushGeneratorState();
1450 ol.docify("\n");
1451 ol.popGeneratorState();
1452
1453 }
1454 // *** write type
1455 /*VHDL CHANGE */
1456
1457 QCString ltype(mdef->typeString());
1458 QCString largs(mdef->argsString());
1459
1460 ClassDef *kl=nullptr;
1461 const ArgumentList &al = mdef->argumentList();
1462 QCString nn;
1463 //VhdlDocGen::adjustRecordMember(mdef);
1464 if (gd) gd=nullptr;
1465 switch (mm)
1466 {
1468 VhdlDocGen::writeSource(mdef,ol,nn);
1469 break;
1472 ol.startBold();
1473 VhdlDocGen::formatString(ltype,ol,mdef);
1474 ol.endBold();
1475 ol.insertMemberAlign();
1476 ol.docify(" ");
1477
1478 writeLink(mdef,ol);
1479 if (al.hasParameters() && mm==VhdlSpecifier::FUNCTION)
1481
1484
1485 break;
1486 case VhdlSpecifier::USE:
1487 kl=VhdlDocGen::getClass(mdef->name());
1488 if (kl && (VhdlDocGen::convert(kl->protection())==VhdlDocGen::ENTITYCLASS)) break;
1489 writeLink(mdef,ol);
1490 ol.insertMemberAlign();
1491 ol.docify(" ");
1492
1493 if (kl)
1494 {
1495 nn=kl->getOutputFileBase();
1496 ol.pushGeneratorState();
1498 ol.docify(" ");
1500 ol.startBold();
1501 ol.docify(name);
1502 name.clear();
1503 ol.endBold();
1504 name+=" <"+mdef->name()+">";
1505 ol.startEmphasis();
1507 ol.popGeneratorState();
1508 }
1509 break;
1511 writeLink(mdef,ol);
1512 ol.insertMemberAlign();
1513 if (largs=="context")
1514 {
1515 VhdlDocGen::writeRecordUnit(ltype,largs,ol,mdef);
1516 }
1517
1518 break;
1519
1523
1524 writeLink(mdef,ol);
1525 ol.docify(" ");
1526 if (mm==VhdlSpecifier::GENERIC)
1527 {
1528 ol.insertMemberAlign();
1529 ol.startBold();
1530 VhdlDocGen::formatString(largs,ol,mdef);
1531 ol.endBold();
1532 }
1533 else
1534 {
1535 ol.insertMemberAlignLeft(memType, false);
1536 ol.docify(" ");
1537 ol.startBold();
1538 VhdlDocGen::formatString(ltype,ol,mdef);
1539 ol.endBold();
1540 ol.insertMemberAlign();
1541 ol.docify(" ");
1542 VhdlDocGen::formatString(largs,ol,mdef);
1543 }
1544 break;
1546 writeLink(mdef,ol);
1547 ol.insertMemberAlign();
1549 break;
1555 if (VhdlDocGen::isCompInst(mdef) )
1556 {
1557 nn=largs;
1558 if(nn.stripPrefix("function") || nn.stripPrefix("package"))
1559 {
1560 VhdlDocGen::formatString(largs,ol,mdef);
1561 ol.insertMemberAlign();
1562 writeLink(mdef,ol);
1563 ol.docify(" ");
1564 VhdlDocGen::formatString(ltype,ol,mdef);
1565 break;
1566 }
1567
1568 largs.prepend("::");
1569 largs.prepend(mdef->name());
1570 ol.writeObjectLink(mdef->getReference(),
1571 cfname,
1572 mdef->anchor(),
1573 mdef->name());
1574 }
1575 else
1576 writeLink(mdef,ol);
1577
1578 ol.insertMemberAlign();
1579 ol.docify(" ");
1580 ol.startBold();
1581 ol.docify(ltype);
1582 ol.endBold();
1583 ol.docify(" ");
1584 if (VhdlDocGen::isComponent(mdef) ||
1585 VhdlDocGen::isConfig(mdef) ||
1587 {
1589 {
1590 nn=ltype;
1591 }
1592 else
1593 {
1594 nn=mdef->name();
1595 }
1596 kl=getClass(nn);
1597 if (kl)
1598 {
1599 nn=kl->getOutputFileBase();
1600 ol.pushGeneratorState();
1602 ol.startEmphasis();
1603 QCString name("<Entity ");
1605 {
1606 name+=ltype+">";
1607 }
1608 else
1609 {
1610 name+=mdef->name()+"> ";
1611 }
1613 ol.endEmphasis();
1614 ol.popGeneratorState();
1615 }
1616 }
1617 break;
1619 writeUCFLink(mdef,ol);
1620 break;
1629 writeLink(mdef,ol);
1630 ol.docify(" ");
1631 ol.insertMemberAlign();
1632 VhdlDocGen::formatString(ltype,ol,mdef);
1633 break;
1636 writeRecordUnit(largs,ltype,ol,mdef);
1637 break;
1638
1639 default: break;
1640 }
1641
1642 bool htmlOn = ol.isEnabled(OutputType::Html);
1643 if (htmlOn && /*Config_getBool(HTML_ALIGN_MEMBERS) &&*/ !ltype.isEmpty())
1644 {
1646 }
1647 if (!ltype.isEmpty()) ol.docify(" ");
1648
1649 if (htmlOn)
1650 {
1652 }
1653
1654 if (!detailsVisible)
1655 {
1656 ol.endDoxyAnchor(cfname,mdef->anchor());
1657 }
1658
1659 ol.endMemberItem(memType);
1660 if (!mdef->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC) /* && !annMemb */)
1661 {
1662 QCString s=mdef->briefDescription();
1664 ol.generateDoc(mdef->briefFile(),mdef->briefLine(),
1665 mdef->getOuterScope()?mdef->getOuterScope():d,
1666 mdef,s,TRUE,FALSE,
1667 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1668 if (detailsVisible)
1669 {
1670 ol.pushGeneratorState();
1672 ol.docify(" ");
1673 if (mdef->getGroupDef()!=nullptr && gd==nullptr) // forward link to the group
1674 {
1675 ol.startTextLink(mdef->getOutputFileBase(),mdef->anchor());
1676 }
1677 else // local link
1678 {
1679 ol.startTextLink(QCString(),mdef->anchor());
1680 }
1681 ol.endTextLink();
1682 ol.popGeneratorState();
1683 }
1685 }
1686 mdef->warnIfUndocumented();
1687
1688}// end writeVhdlDeclaration
1689
1690
1692 const MemberList* mlist,OutputList &ol,
1693 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1694 VhdlSpecifier specifier)
1695{
1696
1697 StringSet pack;
1698
1699 bool first=TRUE;
1700 for (const auto &imd : *mlist)
1701 {
1703 if (md)
1704 {
1706 if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlSpecifier::LIBRARY) )
1707 {
1708 if (first) { ol.startMemberList();first=FALSE; }
1709 VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,mod,FALSE);
1710 } //if
1711 else if (md->isBriefSectionVisible() && (mems==specifier))
1712 {
1713 if (pack.find(md->name().str())==pack.end())
1714 {
1715 if (first) ol.startMemberList(),first=FALSE;
1716 VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,mod,FALSE);
1717 pack.insert(md->name().str());
1718 }
1719 } //if
1720 } //if
1721 } //for
1722 if (!first) ol.endMemberList();
1723}//plainDeclaration
1724
1726{
1727 if (ml==nullptr) return FALSE;
1728 for (const auto &mdd : *ml)
1729 {
1730 if (mdd->getVhdlSpecifiers()==type) //is type in class
1731 {
1732 return TRUE;
1733 }
1734 }
1735 for (const auto &mg : ml->getMemberGroupList())
1736 {
1737 if (!mg->members().empty())
1738 {
1739 if (membersHaveSpecificType(&mg->members(),type)) return TRUE;
1740 }
1741 }
1742 return FALSE;
1743}
1744
1746 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,const ModuleDef *mod,
1747 const QCString &title,const QCString &subtitle,bool /*showEnumValues*/,VhdlSpecifier type)
1748{
1749 if (!membersHaveSpecificType(ml,type)) return;
1750
1751 if (!title.isEmpty())
1752 {
1753 ol.startMemberHeader(convertToId(title),type == VhdlSpecifier::PORT ? 3 : 2);
1754 ol.parseText(title);
1755 ol.endMemberHeader();
1756 ol.docify(" ");
1757 }
1758 if (!subtitle.isEmpty())
1759 {
1761 ol.generateDoc("[generated]",-1,nullptr,nullptr,subtitle,FALSE,FALSE,
1762 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1763 ol.endMemberSubtitle();
1764 } //printf("memberGroupList=%p\n",memberGroupList);
1765
1766 VhdlDocGen::writePlainVHDLDeclarations(ml,ol,cd,nd,fd,gd,mod,type);
1767
1768 int groupId=0;
1769 for (const auto &mg : ml->getMemberGroupList())
1770 {
1771 if (membersHaveSpecificType(&mg->members(),type))
1772 {
1773 //printf("mg->header=%s\n",qPrint(mg->header()));
1774 bool hasHeader=!mg->header().isEmpty();
1775 QCString groupAnchor = QCString(ml->listType().toLabel())+"-"+QCString().setNum(groupId++);
1776 ol.startMemberGroupHeader(groupAnchor,hasHeader);
1777 if (hasHeader)
1778 {
1779 ol.parseText(mg->header());
1780 }
1782 if (!mg->documentation().isEmpty())
1783 {
1784 //printf("Member group has docs!\n");
1786 ol.generateDoc("[generated]",-1,nullptr,nullptr,mg->documentation()+"\n",FALSE,FALSE,
1787 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1788 ol.endMemberGroupDocs();
1789 }
1790 ol.startMemberGroup();
1791 //printf("--- mg->writePlainDeclarations ---\n");
1792 VhdlDocGen::writePlainVHDLDeclarations(&mg->members(),ol,cd,nd,fd,gd,mod,type);
1793 ol.endMemberGroup(hasHeader);
1794 }
1795 }
1796}// writeVHDLDeclarations
1797
1798
1800 OutputList &ol ,QCString & cname)
1801{
1803 cname=VhdlDocGen::getClassName(cd);
1804 ol.startBold();
1805 ol.writeString(qcs);
1806 ol.writeString(" ");
1807 ol.endBold();
1808 //ol.insertMemberAlign();
1809 return FALSE;
1810}// writeClassLink
1811
1812
1813/*! writes a link if the string is linkable else a formatted string */
1814
1816{
1817 if (mdef)
1818 {
1819 const ClassDef *cd=mdef->getClassDef();
1820 if (cd)
1821 {
1822 QCString n=cd->name();
1823 const MemberDef* memdef=VhdlDocGen::findMember(n,mem);
1824 if (memdef && memdef->isLinkable())
1825 {
1826 ol.startBold();
1827 writeLink(memdef,ol);
1828 ol.endBold();
1829 ol.docify(" ");
1830 return;
1831 }
1832 }
1833 }
1834 startFonts(mem,"vhdlchar",ol);
1835}// found component
1836
1837
1838
1839void VhdlDocGen::writeSource(const MemberDef* mdef,OutputList& ol,const QCString &cname)
1840{
1841 auto intf = Doxygen::parserManager->getCodeParser(".vhd");
1842 // pIntf->resetCodeParserState();
1843
1844 QCString codeFragment=mdef->documentation();
1845
1846 if (cname.isEmpty())
1847 {
1848 writeLink(mdef,ol);
1849 int fi=0;
1850 int j=0;
1851 do
1852 {
1853 fi=codeFragment.find("\n",++fi);
1854 } while(fi>=0 && j++ <3);
1855
1856 // show only the first four lines
1857 if (j==4)
1858 {
1859 codeFragment=codeFragment.left(fi);
1860 codeFragment.append("\n .... ");
1861 }
1862 }
1863
1864 codeFragment.prepend("\n");
1865 ol.pushGeneratorState();
1866 auto &codeOL = ol.codeGenerators();
1867 codeOL.startCodeFragment("DoxyCode");
1868 intf->parseCode( codeOL, // codeOutIntf
1869 QCString(), // scope
1870 codeFragment, // input
1871 SrcLangExt::VHDL, // lang
1872 Config_getBool(STRIP_CODE_COMMENTS),
1873 FALSE, // isExample
1874 QCString(), // exampleName
1875 mdef->getFileDef(), // fileDef
1876 mdef->getStartBodyLine(), // startLine
1877 mdef->getEndBodyLine(), // endLine
1878 TRUE, // inlineFragment
1879 mdef, // memberDef
1880 TRUE // show line numbers
1881 );
1882
1883 codeOL.endCodeFragment("DoxyCode");
1884 ol.popGeneratorState();
1885
1886 if (cname.isEmpty()) return;
1887
1888 MemberDefMutable *mdm = toMemberDefMutable(const_cast<MemberDef*>(mdef));
1889 if (mdm)
1890 {
1891 mdm->writeSourceDef(ol);
1892 if (mdef->hasReferencesRelation()) mdm->writeSourceRefs(ol,cname);
1893 if (mdef->hasReferencedByRelation()) mdm->writeSourceReffedBy(ol,cname);
1894 }
1895}
1896
1897
1898
1900{
1901
1902 QCString n=name;
1903 n=n.remove(0,6);
1904
1905 int i=0;
1906
1907 while((i=n.find("__"))>0)
1908 {
1909 n=n.remove(i,1);
1910 }
1911
1912 while((i=n.find("_1"))>0)
1913 {
1914 n=n.replace(i,2,":");
1915 }
1916
1917 return n;
1918}
1919
1920void VhdlDocGen::parseUCF(const QCString &input,Entry* entity,const QCString &fileName,bool altera)
1921{
1922 QCString ucFile(input);
1923 int lineNo=0;
1924 QCString comment("#!");
1925 QCString brief;
1926
1927 while (!ucFile.isEmpty())
1928 {
1929 int i=ucFile.find("\n");
1930 if (i<0) break;
1931 lineNo++;
1932 QCString temp=ucFile.left(i);
1933 temp=temp.stripWhiteSpace();
1934 bool bb=temp.stripPrefix("//");
1935
1936 if (!temp.isEmpty())
1937 {
1938 if (temp.stripPrefix(comment) )
1939 {
1940 brief+=temp;
1941 brief.append("\\n");
1942 }
1943 else if (!temp.stripPrefix("#") && !bb)
1944 {
1945 if (altera)
1946 {
1947 int in=temp.find("-name");
1948 if (in>0)
1949 {
1950 temp=temp.remove(0,in+5);
1951 }
1952
1953 temp.stripPrefix("set_location_assignment");
1954
1955 initUCF(entity,QCString(),temp,lineNo,fileName,brief);
1956 }
1957 else
1958 {
1959 static const reg::Ex ee(R"([\s=])");
1960 int in=findIndex(temp.str(),ee);
1961 if (in<0) in=0;
1962 QCString ff=temp.left(in);
1963 temp.stripPrefix(ff);
1964 ff.append("#");
1965 if (!temp.isEmpty())
1966 {
1967 initUCF(entity,ff,temp,lineNo,fileName,brief);
1968 }
1969 }
1970 }
1971 }//temp
1972
1973 ucFile=ucFile.remove(0,i+1);
1974 }// while
1975}
1976
1977static void initUCF(Entry* root,const QCString &type,QCString &qcs,
1978 int line,const QCString &fileName,QCString & brief)
1979{
1980 if (qcs.isEmpty())return;
1981 QCString n;
1982
1984 qcs=qcs.stripWhiteSpace();
1985
1986 static const reg::Ex reg(R"([\s=])");
1987 int i = findIndex(qcs.str(),reg);
1988 if (i<0) return;
1989 if (i==0)
1990 {
1991 n=type;
1993 }
1994 else
1995 {
1996 n=qcs.left(i);
1997 }
1998 qcs=qcs.remove(0,i+1);
1999 // qcs.prepend("|");
2000
2001 qcs.stripPrefix("=");
2002
2003 std::shared_ptr<Entry> current = std::make_shared<Entry>();
2004 current->vhdlSpec=VhdlSpecifier::UCF_CONST;
2005 current->section=EntryType::makeVariable();
2006 current->bodyLine=line;
2007 current->fileName=fileName;
2008 current->type="ucf_const";
2009 current->args+=qcs;
2010 current->lang= SrcLangExt::VHDL ;
2011
2012 // adding dummy name for constraints like VOLTAGE=5,TEMPERATURE=20 C
2013 if (n.isEmpty())
2014 {
2015 n="dummy";
2017 }
2018
2019 current->name= n+"_";
2020 current->name.append(VhdlDocGen::getRecordNumber());
2021
2022 if (!brief.isEmpty())
2023 {
2024 current->brief=brief;
2025 current->briefLine=line;
2026 current->briefFile=fileName;
2027 brief.clear();
2028 }
2029
2030 root->moveToSubEntryAndKeep(current);
2031}
2032
2033
2034static void writeUCFLink(const MemberDef* mdef,OutputList &ol)
2035{
2036
2037 QCString largs(mdef->argsString());
2038 QCString n= splitString(largs, '#');
2039 // VhdlDocGen::adjustRecordMember(mdef);
2040 bool equ=(n.length()==largs.length());
2041
2042 if (!equ)
2043 {
2044 ol.writeString(n);
2045 ol.docify(" ");
2046 ol.insertMemberAlign();
2047 }
2048
2049 if (mdef->name().contains("dummy")==0)
2050 {
2051 writeLink(mdef,ol);
2052 }
2053 if (equ)
2054 {
2055 ol.insertMemberAlign();
2056 }
2057 ol.docify(" ");
2058 VhdlDocGen::formatString(largs,ol,mdef);
2059}
2060
2061// for cell_inst : [entity] work.proto [ (label|expr) ]
2063{
2064 if (!entity.contains(":")) return "";
2065
2066 static const reg::Ex exp(R"([:()\s])");
2067 auto ql=split(entity.str(),exp);
2068 if (ql.size()<2)
2069 {
2070 return "";
2071 }
2072 QCString label(ql[0]);
2073 entity = ql[1];
2074 int index = entity.findRev(".");
2075 if (index!=-1)
2076 {
2077 entity.remove(0,index+1);
2078 }
2079
2080 if (ql.size()==3)
2081 {
2082 arch = ql[2];
2083 ql=split(arch.str(),exp);
2084 if (ql.size()>1) // expression
2085 {
2086 arch="";
2087 }
2088 }
2089 return label; // label
2090}
2091
2092// use (configuration|entity|open) work.test [(cellfor)];
2093
2095{
2096 static const reg::Ex exp(R"([()\s])");
2097
2098 auto ql = split(entity.str(),exp);
2099
2100 if (findIndex(ql,"open")!=-1)
2101 {
2102 return "open";
2103 }
2104
2105 if (ql.size()<2)
2106 {
2107 return "";
2108 }
2109
2110 std::string label=ql[0];
2111 entity = ql[1];
2112 int index=entity.findRev(".");
2113 if (index!=-1)
2114 {
2115 entity.remove(0,index+1);
2116 }
2117
2118 if (ql.size()==3)
2119 {
2120 arch=ql[2];
2121 }
2122 return QCString(label);
2123}
2124
2125
2126
2127// find class with upper/lower letters
2129{
2130 for (const auto &cd : *Doxygen::classLinkedMap)
2131 {
2132 if (qstricmp(className.data(),qPrint(cd->name()))==0)
2133 {
2134 return cd.get();
2135 }
2136 }
2137 return nullptr;
2138}
2139
2140
2141/*
2142
2143// file foo.vhd
2144// entity foo
2145// .....
2146// end entity
2147
2148// file foo_arch.vhd
2149// architecture xxx of foo is
2150// ........
2151// end architecture
2152
2153*/
2155{
2156
2157 QCString entity,arch,inst;
2158
2159 for (const auto &cur : getVhdlInstList())
2160 {
2161 if (cur->isStatic ) // was bind
2162 {
2163 continue;
2164 }
2165
2166 if (cur->includeName=="entity" || cur->includeName=="component" )
2167 {
2168 entity=cur->includeName+" "+cur->type;
2169 QCString rr=VhdlDocGen::parseForBinding(entity,arch);
2170 }
2171 else if (cur->includeName.isEmpty())
2172 {
2173 entity=cur->type;
2174 }
2175
2177 inst=VhdlDocGen::getIndexWord(cur->args,0);
2180
2181 if (cd==nullptr)
2182 {
2183 continue;
2184 }
2185
2186 addInstance(classEntity,ar,cd,cur);
2187 }
2188
2189}
2190
2191static void addInstance(ClassDefMutable* classEntity, ClassDefMutable* ar,
2192 ClassDefMutable *cd , const std::shared_ptr<Entry> &cur)
2193{
2194
2195 QCString bName,n1;
2196 if (ar==nullptr) return;
2197
2198 if (classEntity==nullptr)
2199 {
2200 //add component inst
2201 n1=cur->type;
2202 goto ferr;
2203 }
2204
2205 if (classEntity==cd) return;
2206
2207 bName=classEntity->name();
2208 // fprintf(stderr,"\naddInstance %s to %s %s %s\n",qPrint( classEntity->name()),qPrint(cd->name()),qPrint(ar->name()),cur->name);
2209 n1=classEntity->name();
2210
2211 if (!cd->isBaseClass(classEntity, true))
2212 {
2213 cd->insertBaseClass(classEntity,n1,Protection::Public,Specifier::Normal,QCString());
2214 }
2215 else
2216 {
2217 VhdlDocGen::addBaseClass(cd,classEntity);
2218 }
2219
2220 if (!VhdlDocGen::isSubClass(classEntity,cd,true,0))
2221 {
2222 classEntity->insertSubClass(cd,Protection::Public,Specifier::Normal,QCString());
2223 classEntity->setLanguage(SrcLangExt::VHDL);
2224 }
2225
2226ferr:
2227 QCString uu=cur->name;
2228 auto md = createMemberDef(
2229 ar->getDefFileName(), cur->startLine,cur->startColumn,
2230 n1,uu,uu, QCString(),
2231 Protection::Public,
2232 Specifier::Normal,
2233 cur->isStatic,
2234 Relationship::Member,
2236 ArgumentList(),
2237 ArgumentList(),
2238 "");
2239 auto mmd = toMemberDefMutable(md.get());
2240
2241 if (!ar->getOutputFileBase().isEmpty())
2242 {
2243 TagInfo tg;
2244 tg.anchor = nullptr;
2245 tg.fileName = ar->getOutputFileBase();
2246 tg.tagName = nullptr;
2247 mmd->setTagInfo(&tg);
2248 }
2249
2250 //fprintf(stderr,"\n%s%s%s\n",qPrint(md->name()),qPrint(cur->brief),qPrint(cur->doc));
2251
2252 mmd->setLanguage(SrcLangExt::VHDL);
2253 mmd->setVhdlSpecifiers(VhdlSpecifier::INSTANTIATION);
2254 mmd->setBriefDescription(cur->brief,cur->briefFile,cur->briefLine);
2255 mmd->setBodySegment(cur->startLine,cur->startLine,-1) ;
2256 mmd->setDocumentation(cur->doc,cur->docFile,cur->docLine);
2257 FileDef *fd=ar->getFileDef();
2258 mmd->setBodyDef(fd);
2259 ar->insertMember(md.get());
2261 mn->push_back(std::move(md));
2262
2263}
2264
2265
2267{
2268 int i=mdef->name().find('~');
2269 if (i>0)
2270 {
2271 //sets the real record member name
2272 mdef->setName(mdef->name().left(i));
2273 }
2274
2275 writeLink(mdef,ol);
2276 ol.startBold();
2277 ol.insertMemberAlign();
2278 if (!ltype.isEmpty())
2279 {
2280 VhdlDocGen::formatString(ltype,ol,mdef);
2281 }
2282 ol.endBold();
2283}
2284
2285
2287 const MemberDef *md,
2288 OutputList& ol,
2289 QCString largs)
2290{
2291
2292 StringVector ql=split(largs.str(),"#");
2293 size_t len=ql.size();
2295 bool first=TRUE;
2296
2297 for(size_t i=0;i<len;i++)
2298 {
2299 QCString n=QCString(ql[i]);
2300 ol.startParameterType(first,"");
2301 ol.endParameterType();
2303 VhdlDocGen::formatString(n,ol,md);
2304 ol.endParameterName();
2306 if ((len-i)>1)
2307 {
2308 ol.endParameterExtra(false,false,false);
2309 }
2310 else
2311 {
2312 ol.endParameterExtra(true,false,true);
2313 }
2314
2315 first=FALSE;
2316 }
2317
2318}//#
2319
2320
2321
2322bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int level)
2323{
2324 bool found=FALSE;
2325 //printf("isBaseClass(cd=%s) looking for %s\n",qPrint(name()),qPrint(bcd->name()));
2326 if (level>255)
2327 {
2328 err("Possible recursive class relation while inside {} and looking for {}\n",cd->name(),scd->name());
2329 abort();
2330 }
2331
2332 for (const auto &bcd :cd->subClasses())
2333 {
2334 const ClassDef *ccd=bcd.classDef;
2335 if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
2336 //printf("isSubClass() subclass %s\n",qPrint(ccd->name()));
2337 if (ccd==scd)
2338 {
2339 found=true;
2340 }
2341 else
2342 {
2343 if (level <256)
2344 {
2345 level = ccd->isBaseClass(scd,followInstances);
2346 if (level>0)
2347 {
2348 found=true;
2349 }
2350 }
2351 }
2352 }
2353 return found;
2354}
2355
2357{
2358 BaseClassList bcl = cd->baseClasses();
2359 for (auto &bcd : bcl)
2360 {
2361 ClassDef *ccd = bcd.classDef;
2362 if (ccd==ent)
2363 {
2364 QCString n = bcd.usedName;
2365 int i = n.find('(');
2366 if(i<0)
2367 {
2368 bcd.usedName.append("(2)");
2369 return;
2370 }
2371 static const reg::Ex reg(R"(\d+)");
2372 QCString s=n.left(i);
2373 QCString r=n.right(n.length()-i);
2374 std::string t=r.str();
2377 r.setNum(r.toInt()+1);
2378 reg::replace(t, reg, r.str());
2379 s.append(t.c_str());
2380 bcd.usedName=s;
2381 bcd.templSpecifiers=t;
2382 }
2383 }
2384 cd->updateBaseClasses(bcl);
2385}
2386
2387
2388static std::vector<const MemberDef*> mdList;
2389
2390static const MemberDef* findMemFlow(const MemberDef* mdef)
2391{
2392 for (const auto &md : mdList)
2393 {
2394 if (md->name()==mdef->name() && md->getStartBodyLine()==mdef->getStartBodyLine())
2395 {
2396 return md;
2397 }
2398 }
2399 return nullptr;
2400}
2401
2403{
2404 if (mdef==nullptr) return;
2405
2406 QCString codeFragment;
2407 const MemberDef* mm=nullptr;
2408 if ((mm=findMemFlow(mdef))!=nullptr)
2409 {
2410 // don't create the same flowchart twice
2412 return;
2413 }
2414 else
2415 {
2416 mdList.push_back(mdef);
2417 }
2418
2419 //fprintf(stderr,"\n create flow mem %s %p\n",qPrint(mdef->name()),mdef);
2420
2421 int actualStart= mdef->getStartBodyLine();
2422 int actualEnd=mdef->getEndBodyLine();
2423 const FileDef* fd=mdef->getFileDef();
2424 bool b=readCodeFragment( fd->absFilePath(), false, actualStart, actualEnd, codeFragment);
2425 if (!b) return;
2426
2427 auto parser { Doxygen::parserManager->getOutlineParser(".vhd") };
2429 std::shared_ptr<Entry> root = std::make_shared<Entry>();
2430 StringVector filesInSameTu;
2431 parser->parseInput("",codeFragment.data(),root,nullptr);
2432}
2433
2435{
2436 std::lock_guard lock(g_vhdlMutex);
2437 g_varMap.clear();
2438 g_classList.clear();
2439 g_packages.clear();
2440}
2441
2447{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::ALIAS; }
2453{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::PORT; }
2457{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::USE; }
2463{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::TYPE; }
2483{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::UNITS; }
2489{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::VFILE; }
2491{ return mdef->getVhdlSpecifiers()==VhdlSpecifier::GROUP; }
2496
2497
2498
2499//############################## Flowcharts #################################################
2500
2501#define STARTL (FlowChart::WHILE_NO | FlowChart::IF_NO | \
2502 FlowChart::FOR_NO | FlowChart::CASE_NO | \
2503 FlowChart::LOOP_NO | WHEN_NO)
2504#define DECLN (FlowChart::WHEN_NO | \
2505 FlowChart::ELSIF_NO | FlowChart::IF_NO | \
2506 FlowChart::FOR_NO | FlowChart::WHILE_NO | \
2507 FlowChart::CASE_NO | FlowChart::LOOP_NO )
2508#define STARTFIN (FlowChart::START_NO | FlowChart::END_NO)
2509#define LOOP (FlowChart::FOR_NO | FlowChart::WHILE_NO | \
2510 FlowChart::LOOP_NO )
2511#define ENDCL (FlowChart::END_CASE | FlowChart::END_LOOP)
2512#define EEND (FlowChart::ENDIF_NO | FlowChart::ELSE_NO )
2513#define IFF (FlowChart::ELSIF_NO | FlowChart::IF_NO)
2514#define EXITNEXT (FlowChart::EXIT_NO | FlowChart::NEXT_NO )
2515#define EMPTY (EEND | FlowChart::ELSIF_NO)
2516#define EE (FlowChart::ELSE_NO | FlowChart::ELSIF_NO)
2517#define EMPTNODE (ENDCL | EEND | FlowChart::ELSIF_NO)
2518#define FLOWLEN (flowList.size()-1)
2519
2520static int ifcounter=0;
2521static int nodeCounter=0;
2522
2523static struct
2524{
2525 // link colors
2526 const char *textNodeLink;
2527 const char *yesNodeLink;
2528 const char *noNodeLink;
2529
2530 // node colors
2531 const char* comment;
2532 const char* decisionNode;
2533 const char* varNode;
2534 const char *startEndNode;
2535 const char* textNode;
2536} flowCol =
2537{ "green", // textNodeLink
2538 "red", // yesNodeLink
2539 "black", // noNodeLink
2540 "khaki", // comment
2541 "0.7 0.3 1.0", // decisionNode
2542 "lightyellow", // varNode
2543 "white", // startEndNode
2544 "lightcyan" // textNode
2546
2547std::vector<FlowChart> flowList;
2548
2549#ifdef DEBUGFLOW
2550static std::map<std::string,int> g_keyMap;
2551#endif
2552
2554{
2555 if (q.length()<=80) return;
2556
2557 if (q.length()>200)
2558 {
2559 q.resize(200);
2560 }
2561
2562 q.append(" ...");
2563
2564 QCString str(q);
2565 QCString temp;
2566
2567 while (str.length()>80)
2568 {
2569 int j=std::max(str.findRev(' ',80),str.findRev('|',80));
2570 if (j<=0)
2571 {
2572 temp+=str;
2573 q=temp;
2574 return;
2575 }
2576 else
2577 {
2578 QCString qcs=str.left(j);
2579 temp+=qcs+"\\";
2580 temp+="n";
2581 str.remove(0,j);
2582 }
2583 }//while
2584
2585 q=temp+str;
2586// #endif
2587}
2588
2590{
2591 QCString ui="-";
2592 std::string q;
2593 std::string t;
2594
2595 ui.fill('-',255);
2596
2597 if (flo.type & STARTL)
2598 {
2599 if (flo.stamp>0)
2600 {
2601 q=ui.left(2*flo.stamp).str();
2602 }
2603 else
2604 {
2605 q=" ";
2606 }
2607 QCString nn=flo.exp.stripWhiteSpace();
2608 printf("\nYES: %s%s[%d,%d]",qPrint(q),qPrint(nn),flo.stamp,flo.id);
2609 }
2610 else
2611 {
2612 if (flo.type & COMMENT_NO)
2613 {
2614 t=flo.label.str();
2615 }
2616 else
2617 {
2618 t=flo.text.str();
2619 }
2620 static const reg::Ex ep(R"(\s)");
2621 t = reg::replace(t,ep,std::string());
2622 if (t.empty())
2623 {
2624 t=" ";
2625 }
2626 if (flo.stamp>0)
2627 {
2628 q=ui.left(2*flo.stamp).str();
2629 }
2630 else
2631 {
2632 q=" ";
2633 }
2634 if (flo.type & EMPTNODE)
2635 {
2636 printf("\n NO: %s%s[%d,%d]",q.c_str(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id);
2637 }
2638 else if (flo.type & COMMENT_NO)
2639 {
2640 printf("\n NO: %s%s[%d,%d]",t.c_str(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id);
2641 }
2642 else
2643 {
2644 printf("\n NO: %s[%d,%d]",t.c_str(),flo.stamp,flo.id);
2645 }
2646 }
2647}
2648
2650{
2651 for (const auto &flowChart : flowList)
2652 {
2653 printNode(flowChart);
2654 }
2655}
2656
2658{
2659 FlowChart *flno = nullptr;
2660 bool found=FALSE;
2661 for (size_t j=0;j<flowList.size();j++)
2662 {
2663 FlowChart &flo = flowList[j];
2664 if (flo.type&TEXT_NO)
2665 {
2666 if (!found)
2667 {
2668 flno=&flo;
2669 }
2670 else
2671 {
2672 flno->text+=flo.text;
2673 flowList.erase(flowList.begin()+j);
2674 if (j>0) j=j-1;
2675 }
2676 found=TRUE;
2677 }
2678 else
2679 {
2680 found=FALSE;
2681 }
2682 }
2683
2684 // find if..endif without text
2685 // if..elseif without text
2686 if (!flowList.empty())
2687 {
2688 for (size_t j=0;j<flowList.size()-1;j++)
2689 {
2690 const FlowChart &flo = flowList[j];
2691 int kind = flo.type;
2692 if ( (kind & IFF) || (flo.type & ELSE_NO))
2693 {
2694 const FlowChart &ftemp = flowList[j+1];
2695 if (ftemp.type & EMPTY)
2696 {
2697 FlowChart fc(TEXT_NO,"empty ",QCString());
2698 fc.stamp = flo.stamp;
2699 flowList.insert(flowList.begin()+j+1,fc);
2700 }
2701 }
2702 }
2703 }
2704
2705}// colTextNode
2706
2708{
2709 QCString node;
2710 node.setNum(n);
2711 return node.prepend("node");
2712}
2713
2715{
2716 ifcounter=0;
2717 nodeCounter=0;
2718 flowList.clear();
2719}
2720
2722{
2723 size_t max=0;
2724 QCString s;
2725 StringVector ql=split(com.str(),"\n");
2726 for (size_t j=0;j<ql.size();j++)
2727 {
2728 s=ql[j];
2729 if (max<s.length()) max=s.length();
2730 }
2731
2732 s=ql.back();
2733 int diff=static_cast<int>(max-s.length());
2734
2735 QCString n;
2736 if (diff>0)
2737 {
2738 n.fill(' ',2*diff);
2739 n.append(".");
2740 s+=n;
2741 ql.pop_back();
2742 ql.push_back(s.str());
2743 }
2744
2745 for (size_t j=0;j<ql.size();j++)
2746 {
2747 s=ql[j];
2748 if (j<ql.size()-1)
2749 {
2750 s+="\n";
2751 }
2752 FlowChart::codify(t,s);
2753 }
2754}
2755
2756
2758{
2759 size_t size=flowList.size();
2760 bool begin=false;
2761
2762 if (size>0)
2763 {
2764 for (uint32_t j=0;j < size-1 ;j++)
2765 {
2766 FlowChart &fll = flowList[j];
2767 if (fll.type & COMMENT_NO)
2768 {
2769 FlowChart &to=flowList[j+1];
2770 if (to.type & COMMENT_NO)
2771 {
2772 to.label = fll.label+"\n"+to.label;
2773 flowList.erase(flowList.begin()+j);
2774 if (size>0) size--;
2775 if (j>0) j--;
2776 }
2777 }
2778 }// for
2779 }
2780
2781 for (size_t j=0;j <flowList.size() ;j++)
2782 {
2783 const FlowChart &fll=flowList[j];
2784
2785 if (fll.type & BEGIN_NO)
2786 {
2787 begin = true;
2788 continue;
2789 }
2790
2791 if (fll.type & COMMENT_NO)
2792 {
2793 const FlowChart *to = nullptr;
2794 if (!begin)
2795 {
2796 // comment between function/process .. begin is linked to start node
2797 to = &flowList[0];
2798 }
2799 else if (j>0 && flowList[j-1].line==fll.line)
2800 {
2801 to = &flowList[j-1];
2802 }
2803 else
2804 {
2805 to = &flowList[j+1];
2806 }
2807 t << getNodeName(fll.id);
2808 t << "[shape=none, label=<\n";
2809 t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
2810 t << "<TR><TD BGCOLOR=\"";
2811 t << flowCol.comment;
2812 t << "\" > ";
2813
2815 t << " </TD></TR></TABLE>>];";
2816 writeEdge(t,fll.id,to->id,2);
2817 }
2818 }// for
2819
2820 // delete comment nodes;
2821 size=flowList.size();
2822 for (size_t j=0; j<size; j++)
2823 {
2824 FlowChart &fll=flowList[j];
2825 if (fll.type & (COMMENT_NO | BEGIN_NO))
2826 {
2827 size_t diff=FLOWLEN-(j+1);
2828
2829 if ((fll.type & COMMENT_NO) && diff > 1)
2830 {
2831 flowList[j+1].label = fll.label;
2832 }
2833
2834 flowList.erase(flowList.begin()+j);
2835
2836 if (size>0) size--;
2837 if (j>0) j--;
2838 }
2839 }// for;
2840}
2841
2843{
2844 if (!str.isEmpty())
2845 {
2846 const char *p=str.data();
2847 while (*p)
2848 {
2849 char c=*p++;
2850 switch(c)
2851 {
2852 case '<': t << "&lt;"; break;
2853 case '>': t << "&gt;"; break;
2854 case '&': t << "&amp;"; break;
2855 case '\'': t << "&#39;"; break;
2856 case '"': t << "&quot;"; break;
2857 case '\n': t <<"<BR ALIGN=\"LEFT\"/>"; break;
2858 default: t << c; break;
2859 }
2860 }
2861 }
2862}//codify
2863
2864FlowChart::FlowChart(int typ,const QCString &t,const QCString &ex,const QCString &lab)
2865{
2867
2868 if (typ & STARTL)
2869 {
2870 ifcounter++;
2871 }
2872
2873 text=t;
2874 exp=ex;
2875 type=typ;
2876 label=lab;
2877
2878 if (typ & (ELSE_NO | ELSIF_NO))
2879 {
2880 stamp--;
2881 }
2882
2883 if (typ & (START_NO | END_NO | VARIABLE_NO))
2884 {
2885 stamp=0;
2886 }
2887
2888 id=nodeCounter++;
2889}
2890
2892{
2893 if (!VhdlDocGen::getFlowMember()) return;
2894
2895 QCString typeString(text);
2896 QCString expression(exp);
2897
2898
2899 if (!text.isEmpty())
2900 {
2901 typeString=substitute(typeString,";","\n");
2902 }
2903
2904 if (!exp.isEmpty())
2905 {
2906 expression=substitute(expression,"\"","\\\"");
2907 }
2908
2909 if (type & VARIABLE_NO)
2910 {
2911 // Ignore the empty section of the VHDL variable definition.
2912 // This is section between `process` and `begin` keywords, where any source text is missing, probably a bug in the VHDL source parser.
2913 if(text.isEmpty()) return;
2914
2915 flowList.insert(flowList.begin(),FlowChart(type,typeString,expression,label));
2916 flowList.front().line=1; // TODO: use getLine(); of the parser
2917 }
2918 else if (type & START_NO)
2919 {
2920 flowList.insert(flowList.begin(),FlowChart(type,typeString,expression,label));
2921 flowList.front().line=1; // TODO: use getLine(); of the parser
2922 }
2923 else
2924 {
2925 flowList.emplace_back(type,typeString,expression,label);
2926 flowList.back().line=1; // TODO: use getLine(); of the parser
2927 }
2928}
2929
2931{
2932 if (!VhdlDocGen::getFlowMember()) return;
2933 ifcounter--;
2934}
2935
2937{
2938 QCString t;
2941 switch (flo.type)
2942 {
2943 case START_NO: t=":"+text+"|"; break;
2944 case IF_NO : t="\nif ("+exp+") then (yes)"; break;
2945 case ELSIF_NO: t="\nelseif ("+exp+") then (yes)"; break;
2946 case ELSE_NO: t="\nelse"; break;
2947 case CASE_NO: t="\n:"+exp+";"; break;
2948 case WHEN_NO: t="\n";
2949 if (!ca) t+="else";
2950 t+="if ("+exp+") then (yes)";
2951 break;
2952 case EXIT_NO: break;
2953 case END_NO: if (text.contains(" function")==0) t="\n:"+text+";";
2954 break;
2955 case TEXT_NO: t="\n:"+text+"]"; break;
2956 case ENDIF_NO: t="\nendif"; break;
2957 case FOR_NO: t="\nwhile ("+exp+") is (yes)"; break;
2958 case WHILE_NO: t="\nwhile ("+exp+") is (yes)"; break;
2959 case END_LOOP: t="\nendwhile"; break;
2960 case END_CASE: t="\nendif\n:end case;"; break;
2961 case VARIABLE_NO:t="\n:"+text+";"; break;
2962 case RETURN_NO: t="\n:"+text+";";
2963 if (!endL) t+="\nstop";
2964 break;
2965 case LOOP_NO: t="\nwhile (infinite loop)"; break;
2966 case NEXT_NO: break;
2967 case EMPTY_NO: break;
2968 case COMMENT_NO: t="\n note left \n "+flo.label+"\nend note \n"; break;
2969 case BEGIN_NO: t="\n:begin;"; break;
2970 default: assert(false); break;
2971 }
2972 return t;
2973}
2974
2976{
2977 int caseCounter = 0;
2978 int whenCounter = 0;
2979
2980 QCString qcs;
2981 size_t size=flowList.size();
2982 for (size_t j=0;j<size;j++)
2983 {
2984 bool endList = j==FLOWLEN;
2985 const FlowChart &flo = flowList[j];
2986 if (flo.type==CASE_NO)
2987 {
2988 caseCounter++;
2989 whenCounter=0;
2990 }
2991
2992 if (flo.type==END_CASE)
2993 {
2994 caseCounter--;
2995 }
2996
2997 bool ca = (caseCounter>0 && whenCounter==0);
2998
2999 qcs+=printPlantUmlNode(flo,ca,endList);
3000
3001 if (flo.type==WHEN_NO)
3002 {
3003 whenCounter++;
3004 }
3005
3006 }
3007 qcs+="\n";
3008
3009 QCString htmlOutDir = Config_getString(HTML_OUTPUT);
3010
3012 n=PlantumlManager::instance().writePlantUMLSource(htmlOutDir,n,qcs,PlantumlManager::PUML_SVG,"uml",n,1,true);
3014}
3015
3020
3021const char* FlowChart::getNodeType(int c)
3022{
3023 switch(c)
3024 {
3025 case IF_NO: return "if ";
3026 case ELSIF_NO: return "elsif ";
3027 case ELSE_NO: return "else ";
3028 case CASE_NO: return "case ";
3029 case WHEN_NO: return "when ";
3030 case EXIT_NO: return "exit ";
3031 case END_NO: return "end ";
3032 case TEXT_NO: return "text ";
3033 case START_NO: return "start ";
3034 case ENDIF_NO: return "endif ";
3035 case FOR_NO: return "for ";
3036 case WHILE_NO: return "while ";
3037 case END_LOOP: return "end_loop ";
3038 case END_CASE: return "end_case ";
3039 case VARIABLE_NO: return "variable_decl ";
3040 case RETURN_NO: return "return ";
3041 case LOOP_NO: return "infinite loop ";
3042 case NEXT_NO: return "next ";
3043 case COMMENT_NO: return "comment ";
3044 case EMPTY_NO: return "empty ";
3045 case BEGIN_NO: return "<begin> ";
3046 default: return "--failure--";
3047 }
3048}
3049
3051{
3052 QCString qcs("/");
3053 QCString ov = Config_getString(HTML_OUTPUT);
3054
3056
3057 //const MemberDef *m=VhdlDocGen::getFlowMember();
3058 //if (m)
3059 // fprintf(stderr,"\n creating flowchart : %s %s in file %s \n",theTranslator->trVhdlType(m->getMemberSpecifiers(),TRUE),qPrint(m->name()),qPrint(m->getFileDef()->name()));
3060
3061 QCString dir=" -o \""+ov+qcs+"\"";
3062 ov+="/flow_design.dot";
3063
3064 QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
3065
3067 {
3068 err("could not create dot file\n");
3069 }
3070}
3071
3073{
3074 t << " digraph G { \n";
3075 t << "rankdir=TB \n";
3076 t << "concentrate=true\n";
3077 t << "stylesheet=\"doxygen.css\"\n";
3078}
3079
3081{
3082 t << " } \n";
3083}
3084
3086{
3087 // assert(VhdlDocGen::flowMember);
3088
3089 QCString ov = Config_getString(HTML_OUTPUT);
3090 QCString fileName = ov+"/flow_design.dot";
3091 std::ofstream f = Portable::openOutputStream(fileName);
3092 if (!f.is_open())
3093 {
3094 err("Cannot open file {} for writing\n",fileName);
3095 return;
3096 }
3097 TextStream t(&f);
3098
3099 colTextNodes();
3100 // buildCommentNodes(t);
3101
3102#ifdef DEBUGFLOW
3103 printFlowTree();
3104#endif
3105
3106 if (!Config_getString(PLANTUML_JAR_PATH).isEmpty())
3107 {
3108 printUmlTree();
3109 delFlowList();
3110 t.flush();
3111 f.close();
3112 return;
3113 }
3114
3115 startDot(t);
3117 for (const auto &fll : flowList)
3118 {
3119 writeShape(t,fll);
3120 }
3121 writeFlowLinks(t);
3122
3124 delFlowList();
3125 t.flush();
3126 f.close();
3128}// writeFlowChart
3129
3131{
3132 if (fl.type & EEND) return;
3133 QCString var;
3134 if (fl.type & LOOP)
3135 {
3136 var=" loop";
3137 }
3138 else if (fl.type & IFF)
3139 {
3140 var=" then";
3141 }
3142 else
3143 {
3144 var="";
3145 }
3146
3147 t << getNodeName(fl.id);
3148
3149#ifdef DEBUGFLOW
3150 QCString qq(getNodeName(fl.id));
3151 g_keyMap.emplace(qq.str(),fl.id);
3152#endif
3153
3154 bool dec=(fl.type & DECLN);
3155 bool exit=(fl.type & EXITNEXT);
3156 if (exit && !fl.exp.isEmpty())
3157 {
3158 dec=TRUE;
3159 }
3160 if (dec)
3161 {
3162 QCString exp=fl.exp;
3163 alignText(exp);
3164
3165 t << " [shape=diamond,style=filled,color=\"";
3166 t << flowCol.decisionNode;
3167 t << "\",label=\" ";
3168 QCString kl;
3169 if (exit) kl=fl.text+" ";
3170
3171 if (!fl.label.isEmpty())
3172 {
3173 kl+=fl.label+":"+exp+var;
3174 }
3175 else
3176 {
3177 kl+=exp+var;
3178 }
3179
3181 t << "\"]\n";
3182 }
3183 else if (fl.type & ENDCL)
3184 {
3185 QCString val=fl.text;
3186 t << " [shape=ellipse ,label=\""+val+"\"]\n";
3187 }
3188 else if (fl.type & STARTFIN)
3189 {
3190 QCString val=fl.text;
3191 t << "[shape=box , style=rounded label=<\n";
3192 t << "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" >\n ";
3193 t << "<TR><TD BGCOLOR=\"";
3194 t<< flowCol.startEndNode;
3195 t<< "\"> ";
3197 t << " </TD></TR></TABLE>>];";
3198 }
3199 else
3200 {
3201 if (fl.text.isEmpty()) return;
3202 bool isVar=(fl.type & FlowChart::VARIABLE_NO);
3203 QCString q=fl.text;
3204
3205 if (exit)
3206 {
3207 q+=" "+fl.label;
3208 }
3209
3210 int z=q.findRev("\n");
3211
3212 if (z==static_cast<int>(q.length())-1)
3213 {
3214 q=q.remove(z,2);
3215 }
3216 t << "[shape=none margin=0.1, label=<\n";
3217 t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
3218 if (isVar)
3219 {
3220 t << "<TR><TD BGCOLOR=\"" << flowCol.varNode << "\" > ";
3221 }
3222 else
3223 {
3224 t << "<TR><TD BGCOLOR=\"" << flowCol.textNode << "\" > ";
3225 }
3227 t << " </TD></TR></TABLE>>];";
3228 }
3229}
3230
3231
3232void FlowChart::writeEdge(TextStream &t,const FlowChart &fl_from,const FlowChart &fl_to,int i)
3233{
3234 bool b=fl_from.type & STARTL;
3235 bool c=fl_to.type & STARTL;
3236
3237#ifdef DEBUGFLOW
3238 QCString s1(getNodeName(fl_from.id));
3239 QCString s2(getNodeName(fl_to.id));
3240 auto it = g_keyMap.find(s1.str());
3241 auto it1 = g_keyMap.find(s2.str());
3242 // checks if the link is connected to a valid node
3243 assert(it!=g_keyMap.end());
3244 assert(it1!=g_keyMap.end());
3245#endif
3246
3247 writeEdge(t,fl_from.id,fl_to.id,i,b,c);
3248}
3249
3250void FlowChart::writeEdge(TextStream &t,int fl_from,int fl_to,int i,bool bFrom,bool bTo)
3251{
3252 QCString label,col;
3253
3254 if (i==0)
3255 {
3256 col=flowCol.yesNodeLink;
3257 label="yes";
3258 }
3259 else if (i==1)
3260 {
3261 col=flowCol.noNodeLink;
3262 label="no";
3263 }
3264 else
3265 {
3266 col=flowCol.textNodeLink;
3267 label="";
3268 }
3269
3270 t << "edge [color=\""+col+"\",label=\""+label+"\"]\n";
3271 t << getNodeName(fl_from);
3272 if (bFrom) t << ":s";
3273 t << "->";
3274 t << getNodeName(fl_to);
3275 if (bTo) t << ":n";
3276 t << "\n";
3277}
3278
3279void FlowChart::alignFuncProc( QCString & q,const ArgumentList &al,bool isFunc)
3280{
3281 size_t index=al.size();
3282 if (index==0) return;
3283
3284 size_t len=q.length()+VhdlDocGen::getFlowMember()->name().length();
3285 QCString prev,temp;
3286 prev.fill(' ',static_cast<int>(len)+1);
3287
3288 q+="\n";
3289 for (const Argument &arg : al)
3290 {
3291 QCString attl=arg.defval+" ";
3292 attl+=arg.name+" ";
3293
3294 if (!isFunc)
3295 {
3296 attl+=arg.attrib+" ";
3297 }
3298 else
3299 {
3300 attl+=" in ";
3301 }
3302 attl+=arg.type;
3303 if (--index) attl+=",\n"; else attl+="\n";
3304
3305 attl.prepend(prev);
3306 temp+=attl;
3307 }
3308
3309 q+=temp;
3310}
3311
3312size_t FlowChart::findNextLoop(size_t index,int stamp)
3313{
3314 for (size_t j=index+1; j<flowList.size(); j++)
3315 {
3316 const FlowChart &flo = flowList[j];
3317 if (flo.stamp==stamp)
3318 {
3319 continue;
3320 }
3321 if (flo.type&END_LOOP)
3322 {
3323 return j;
3324 }
3325 }
3326 return flowList.size()-1;
3327}
3328
3329size_t FlowChart::findPrevLoop(size_t index,int stamp,bool endif)
3330{
3331 for (size_t j=index;j>0;j--)
3332 {
3333 const FlowChart &flo = flowList[j];
3334 if (flo.type & LOOP)
3335 {
3336 if (flo.stamp==stamp && endif)
3337 {
3338 return j;
3339 }
3340 else
3341 {
3342 if (flo.stamp<stamp)
3343 {
3344 return j;
3345 }
3346 }
3347 }
3348 }
3349 return flowList.size()-1;
3350}
3351
3352size_t FlowChart::findLabel(size_t index,const QCString &label)
3353{
3354 for (size_t j=index;j>0;j--)
3355 {
3356 const FlowChart &flo = flowList[j];
3357 if ((flo.type & LOOP) && !flo.label.isEmpty() && qstricmp(flo.label,label)==0)
3358 {
3359 return j;
3360 }
3361 }
3362 err("could not find label: '{}'\n",label);
3363 return 0;
3364}
3365
3366size_t FlowChart::findNode(size_t index,int stamp,int type)
3367{
3368 for (size_t j=index+1; j<flowList.size(); j++)
3369 {
3370 const FlowChart &flo = flowList[j];
3371 if (flo.type==type && flo.stamp==stamp)
3372 {
3373 return j;
3374 }
3375 }
3376 return 0;
3377}// findNode
3378
3379size_t FlowChart::getNextNode(size_t index,int stamp)
3380{
3381 for (size_t j=index+1; j<flowList.size(); j++)
3382 {
3383 const FlowChart &flo = flowList[j];
3384 int kind = flo.type;
3385 int s = flo.stamp;
3386 if (s>stamp)
3387 {
3388 continue;
3389 }
3390 if (kind & ENDIF_NO)
3391 {
3392 if (s<stamp && stamp>0)
3393 {
3394 stamp--;
3395 continue;
3396 }
3397 }
3398 if (kind & (ELSE_NO | ELSIF_NO))
3399 {
3400 if (s<stamp && stamp>0)
3401 {
3402 stamp--;
3403 }
3404 j=findNode(j,stamp,ENDIF_NO);
3405 continue;
3406 }
3407 if (kind & WHEN_NO)
3408 {
3409 if (s<stamp && stamp>0)
3410 {
3411 stamp--;
3412 }
3413 return findNode(j,stamp-1,END_CASE);
3414 }
3415 return j;
3416 }
3417 return FLOWLEN;
3418}
3419
3420size_t FlowChart::getNextIfLink(const FlowChart &fl,size_t index)
3421{
3422 int stamp=fl.stamp;
3423 size_t start = index+1;
3424 size_t endifNode = findNode(start,stamp,ENDIF_NO);
3425 size_t elseifNode = findNode(start,stamp,ELSIF_NO);
3426 size_t elseNode = findNode(start,stamp,ELSE_NO);
3427
3428 if (elseifNode>0 && elseifNode<endifNode)
3429 {
3430 return elseifNode;
3431 }
3432
3433 if (elseNode>0 && elseNode<endifNode)
3434 {
3435 return elseNode+1;
3436 }
3437
3438 stamp=flowList[endifNode].stamp;
3439 return getNextNode(endifNode,stamp);
3440}
3441
3443{
3444 size_t size=flowList.size();
3445 if (size<2) return;
3446
3447 // write start link
3448 writeEdge(t,flowList[0],flowList[1],2);
3449
3450 for (size_t j=0;j<size;j++)
3451 {
3452 const FlowChart &fll = flowList[j];
3453 int kind = fll.type;
3454 int stamp = fll.stamp;
3455 if (kind & EEND)
3456 {
3457 continue;
3458 }
3459
3460 if (kind & IFF)
3461 {
3462 writeEdge(t,fll,flowList[j+1],0);
3463 size_t z=getNextIfLink(fll,j);
3464 // assert(z>-1);
3465 writeEdge(t,fll,flowList[z],1);
3466 }
3467 else if (kind & LOOP_NO)
3468 {
3469 writeEdge(t,fll,flowList[j+1],2);
3470 continue;
3471 }
3472 else if (kind & (CASE_NO | FOR_NO | WHILE_NO))
3473 {
3474 if (kind & CASE_NO)
3475 {
3476 writeEdge(t,fll,flowList[j+1],2);
3477 continue;
3478 }
3479 else
3480 {
3481 writeEdge(t,fll,flowList[j+1],0);
3482 }
3483
3484 kind=END_LOOP;
3485 size_t z=findNode(j+1,fll.stamp,kind);
3486 z=getNextNode(z,flowList[z].stamp);
3487
3488 // assert(z>-1);
3489 writeEdge(t,fll,flowList[z],1);
3490 continue;
3491 }
3492 else if (kind & (TEXT_NO | VARIABLE_NO))
3493 {
3494 size_t z=getNextNode(j,stamp);
3495 writeEdge(t,fll,flowList[z],2);
3496 }
3497 else if (kind & WHEN_NO)
3498 {
3499 // default value
3500 if (qstricmp(fll.text.simplifyWhiteSpace(),"others")==0)
3501 {
3502 writeEdge(t,fll,flowList[j+1],2);
3503 continue;
3504 }
3505
3506
3507 writeEdge(t,fll,flowList[j+1],0);
3508 size_t u=findNode(j,stamp,WHEN_NO);
3509 size_t v=findNode(j,stamp-1,END_CASE);
3510
3511 if (u>0 && u<v)
3512 {
3513 writeEdge(t,fll,flowList[u],1);
3514 }
3515 else
3516 {
3517 writeEdge(t,fll,flowList[v],1);
3518 }
3519 }
3520 else if (kind & END_CASE)
3521 {
3522 size_t z=FlowChart::getNextNode(j,fll.stamp);
3523 writeEdge(t,fll,flowList[z],2);
3524 }
3525 else if (kind & END_LOOP)
3526 {
3527 size_t z=findPrevLoop(j,fll.stamp,true);
3528 writeEdge(t,fll,flowList[z],2);
3529 }
3530 else if (kind & RETURN_NO)
3531 {
3532 writeEdge(t,fll,flowList[size-1],2);
3533 }
3534 else if (kind & (EXIT_NO | NEXT_NO))
3535 {
3536 size_t z = 0;
3537 bool b = kind==NEXT_NO;
3538 if (!fll.exp.isEmpty())
3539 {
3540 writeEdge(t,fll,flowList[j+1],1);
3541 }
3542 if (!fll.label.isEmpty())
3543 {
3544 z=findLabel(j,fll.label);
3545 if (b)
3546 {
3547 writeEdge(t,fll,flowList[z],0);
3548 }
3549 else
3550 {
3552 z=getNextNode(z,flowList[z].stamp);
3553 writeEdge(t,fll,flowList[z],0);
3554 }
3555 continue;
3556 }
3557 else
3558 {
3559 if (b)
3560 {
3561 z=findPrevLoop(j,fll.stamp);
3562 writeEdge(t,fll,flowList[z],0);
3563 continue;
3564 }
3565 else
3566 {
3567 z =findNextLoop(j,fll.stamp-1);
3568 }
3569 z=getNextNode(z,flowList[z].stamp);
3570 }
3571 writeEdge(t,fll,flowList[z],0);
3572 }
3573 } //for
3574} //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:109
MemberListType listType() const
Definition memberlist.h:114
const MemberGroupRefList & getMemberGroupList() const
Definition memberlist.h:149
Wrapper class for the MemberListType type.
Definition types.h:346
constexpr const char * toLabel() const
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:269
void startCodeFragment(const QCString &style)
Definition outputlist.h:278
Class representing a list of output generators that are written to in parallel.
Definition outputlist.h:314
bool isEnabled(OutputType o)
void writeString(const QCString &text)
Definition outputlist.h:412
void endParameterExtra(bool last, bool one, bool bracket)
Definition outputlist.h:695
void writeChar(char c)
Definition outputlist.h:530
void disable(OutputType o)
void endMemberDocName()
Definition outputlist.h:683
void insertMemberAlignLeft(OutputGenerator::MemberItemType typ=OutputGenerator::MemberItemType::Normal, bool templ=FALSE)
Definition outputlist.h:520
void startParameterExtra()
Definition outputlist.h:693
const OutputCodeList & codeGenerators() const
Definition outputlist.h:357
void startParameterList(bool openBracket)
Definition outputlist.h:701
void enable(OutputType o)
void endMemberDescription()
Definition outputlist.h:568
void endMemberGroupDocs()
Definition outputlist.h:512
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:440
void startMemberDescription(const QCString &anchor, const QCString &inheritId=QCString(), bool typ=false)
Definition outputlist.h:566
void endDoxyAnchor(const QCString &fn, const QCString &anchor)
Definition outputlist.h:542
void docify(const QCString &s)
Definition outputlist.h:438
void endEmphasis()
Definition outputlist.h:528
void startMemberGroup()
Definition outputlist.h:514
void startMemberList()
Definition outputlist.h:482
void endTextLink()
Definition outputlist.h:445
void startBold()
Definition outputlist.h:562
void endMemberItem(OutputGenerator::MemberItemType type)
Definition outputlist.h:496
void endMemberList()
Definition outputlist.h:484
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
void addLabel(const QCString &fName, const QCString &anchor)
Definition outputlist.h:544
void pushGeneratorState()
void insertMemberAlign(bool templ=FALSE)
Definition outputlist.h:518
void startParameterType(bool first, const QCString &key)
Definition outputlist.h:685
void disableAllBut(OutputType o)
void endParameterName()
Definition outputlist.h:691
void popGeneratorState()
void endBold()
Definition outputlist.h:564
void startDoxyAnchor(const QCString &fName, const QCString &manName, const QCString &anchor, const QCString &name, const QCString &args)
Definition outputlist.h:538
void startEmphasis()
Definition outputlist.h:526
void endMemberGroupHeader()
Definition outputlist.h:508
void endMemberGroup(bool last)
Definition outputlist.h:516
void startMemberGroupDocs()
Definition outputlist.h:510
void endParameterType()
Definition outputlist.h:687
void startParameterName(bool one)
Definition outputlist.h:689
void enableAll()
void endMemberHeader()
Definition outputlist.h:472
void endMemberSubtitle()
Definition outputlist.h:476
void startMemberItem(const QCString &anchor, OutputGenerator::MemberItemType type, const QCString &id=QCString())
Definition outputlist.h:494
void startMemberSubtitle()
Definition outputlist.h:474
void lineBreak(const QCString &style=QCString())
Definition outputlist.h:560
void parseText(const QCString &textStr)
void startMemberGroupHeader(const QCString &id, bool b)
Definition outputlist.h:506
void startTextLink(const QCString &file, const QCString &anchor)
Definition outputlist.h:443
void startMemberHeader(const QCString &anchor, int typ=2)
Definition outputlist.h:470
QCString 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:28
static PlantumlManager & instance()
Definition plantuml.cpp:157
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition plantuml.cpp:128
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
void fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:180
QCString & prepend(const char *s)
Definition qcstring.h:407
int toInt(bool *ok=nullptr, int base=10) const
Definition qcstring.cpp:249
QCString upper() const
Definition qcstring.h:239
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool startsWith(const char *s) const
Definition qcstring.h:492
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
QCString lower() const
Definition qcstring.h:234
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
QCString & remove(size_t index, size_t len)
Definition qcstring.h:427
void resize(size_t newlen)
Definition qcstring.h:167
const std::string & str() const
Definition qcstring.h:537
QCString & setNum(short n)
Definition qcstring.h:444
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:185
QCString & append(char c)
Definition qcstring.h:381
QCString right(size_t len) const
Definition qcstring.h:219
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
QCString & replace(size_t index, size_t len, const char *s)
Definition qcstring.cpp:212
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:159
QCString left(size_t len) const
Definition qcstring.h:214
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:143
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:198
void clear()
Definition qcstring.h:169
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:232
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:665
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:770
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:759
Portable versions of functions that are platform dependent.
int qstricmp(const char *s1, const char *s2)
Definition qcstring.cpp:442
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
#define qsnprintf
Definition qcstring.h:49
const char * qPrint(const char *s)
Definition qcstring.h:672
#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:710
@ INSTANTIATION
Definition types.h:731
@ MISCELLANEOUS
Definition types.h:737
@ SHAREDVARIABLE
Definition types.h:734
std::string_view word
Definition util.cpp:980
bool found
Definition util.cpp:984
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:4428
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:7131
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
Definition util.cpp:7095
QCString convertToId(const QCString &s)
Definition util.cpp:4388
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5415
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()