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