Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / src / vhdldocgen.cpp
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2014 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 /******************************************************************************
16  * Parser for VHDL subset
17  * written by M. Kreis
18  * supports VHDL-87/93/2008
19  * does not support VHDL-AMS
20  ******************************************************************************/
21
22 // global includes
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <qcstring.h>
28 #include <qfileinfo.h>
29 #include <qstringlist.h>
30
31 //#ifdef DEBUGFLOW
32 #include <qmap.h>
33 //#endif
34
35 /* --------------------------------------------------------------- */
36
37 // local includes
38 #include "vhdldocgen.h"
39 #include "message.h"
40 #include "config.h"
41 #include "doxygen.h"
42 #include "util.h"
43 #include "language.h"
44 #include "commentscan.h"
45 #include "index.h"
46 #include "definition.h"
47 #include "searchindex.h"
48 #include "outputlist.h"
49 #include "parserintf.h"
50
51 #include "layout.h"
52 #include "arguments.h"
53 #include "portable.h"
54 #include "memberlist.h"
55 #include "memberdef.h"
56 #include "groupdef.h"
57 #include "classlist.h"
58 #include "namespacedef.h"
59 #include "filename.h"
60 #include "membergroup.h"
61 #include "memberdef.h"
62
63 #include "vhdljjparser.h"
64 #include "VhdlParser.h"
65
66 #include "vhdlcode.h"
67 #define theTranslator_vhdlType VhdlDocGen::trVhdlType
68
69 static QDict<QCString> g_vhdlKeyDict0(17,FALSE);
70 static QDict<QCString> g_vhdlKeyDict1(17,FALSE);
71 static QDict<QCString> g_vhdlKeyDict2(17,FALSE);
72 static QDict<QCString> g_vhdlKeyDict3(17,FALSE);
73 static QDict<QCString> g_xilinxUcfDict(17,FALSE);
74
75 static void initUCF(Entry* root,const char* type,QCString &  qcs,int line,QCString & fileName,QCString & brief);
76 static void writeUCFLink(const MemberDef* mdef,OutputList &ol);
77 static void assignBinding(VhdlConfNode* conf);
78 static void addInstance(ClassDef* entity, ClassDef* arch, ClassDef *inst,Entry *cur,ClassDef* archBind=NULL);
79
80 //---------- create svg -------------------------------------------------------------
81 static void createSVG();
82 static void startDot(FTextStream &t);
83 static void startTable(FTextStream &t,const QCString &className);
84 static QList<MemberDef>* getPorts(ClassDef *cd);
85 static void writeVhdlEntityToolTip(FTextStream& t,ClassDef *cd);
86 static void endDot(FTextStream &t);
87 static void writeTable(QList<MemberDef>* port,FTextStream & t);
88 static void endTabel(FTextStream &t);
89 static void writeClassToDot(FTextStream &t,ClassDef* cd);
90 static void writeVhdlDotLink(FTextStream &t,const QCString &a,const QCString &b,const QCString &style);
91 //static void writeVhdlPortToolTip(FTextStream& t,QList<MemberDef>* port,ClassDef *cd);
92 static const MemberDef *flowMember=0;
93
94 void VhdlDocGen::setFlowMember( const MemberDef* mem)
95 {
96   flowMember=mem;
97 }
98
99 const MemberDef* VhdlDocGen::getFlowMember()
100 {
101   return flowMember;
102 }
103
104
105
106 //--------------------------------------------------------------------------------------------------
107 static void codify(FTextStream &t,const char *str)
108 {
109   if (str)
110   {
111     const char *p=str;
112     char c;
113     while (*p)
114     {
115       c=*p++;
116       switch(c)
117       {
118         case '<':  t << "&lt;";
119                    break;
120         case '>':  t << "&gt;";
121                    break;
122         case '&':  t << "&amp;";
123                    break;
124         case '\'': t << "&#39;";
125                    break;
126         case '"':  t << "&quot;";
127                    break;
128         default:   t << c;
129                    break;
130       }
131     }
132   }
133 }
134
135 static void writeLink(const MemberDef* mdef,OutputList &ol)
136 {
137   ol.writeObjectLink(mdef->getReference(),
138       mdef->getOutputFileBase(),
139       mdef->anchor(),
140       mdef->name());
141 }
142
143 static void startFonts(const QCString& q, const char *keyword,OutputList& ol)
144 {
145   ol.startFontClass(keyword);
146   ol.docify(q.data());
147   ol.endFontClass();
148 }
149
150 static QCString splitString(QCString& str,char c)
151 {
152   QCString n=str;
153   int i=str.find(c);
154   if (i>0)
155   {
156     n=str.left(i);
157     str=str.remove(0,i+1);
158   }
159   return n;
160 }
161
162 static int compareString(const QCString& s1,const QCString& s2)
163 {
164   return qstricmp(s1.stripWhiteSpace(),s2.stripWhiteSpace());
165 }
166
167 static void createSVG()
168 {
169     QCString ov =Config_getString("HTML_OUTPUT");
170     QCString dir="-o \""+ov+"/vhdl_design_overview.html\"";
171     ov+="/vhdl_design.dot";
172
173     QRegExp ep("[\\s]");
174     QCString vlargs="-Tsvg \""+ov+"\" "+dir ;
175
176     if (portable_system("dot",vlargs)!=0)
177     {
178       err("could not create dot file");
179     }
180 }
181
182 // Creates a svg image. All in/out/inout  ports are shown with  brief description and direction.
183 // Brief descriptions for entities are shown too.
184 void VhdlDocGen::writeOverview()
185 {
186   ClassSDict::Iterator cli(*Doxygen::classSDict);
187   ClassDef *cd;
188   bool found=FALSE;
189   for ( ; (cd=cli.current()) ; ++cli )
190   {
191     if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS )
192     {
193       found=TRUE;
194       break;
195     }
196   }
197
198   if (!found) return;
199
200   QCString ov =Config_getString("HTML_OUTPUT");
201   QCString fileName=ov+"/vhdl_design.dot";
202   QFile f(fileName);
203   QStringList qli;
204   FTextStream  t(&f);
205
206   if (!f.open(IO_WriteOnly))
207   {
208     fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
209     return;
210   }
211
212   startDot(t);
213
214   for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
215   {
216     if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS )
217     {
218       continue;
219     }
220
221     QList<MemberDef>* port= getPorts(cd);
222     if (port==0)
223     {
224       continue;
225     }
226     if (port->count()==0)
227     {
228       delete port;
229       port=NULL;
230       continue;
231     }
232
233     startTable(t,cd->name());
234     writeClassToDot(t,cd);
235     writeTable(port,t);
236     endTabel(t);
237
238    // writeVhdlPortToolTip(t,port,cd);
239     writeVhdlEntityToolTip(t,cd);
240     delete port;
241
242     BaseClassList *bl=cd->baseClasses();
243     if (bl)
244     {
245       BaseClassListIterator bcli(*bl);
246       BaseClassDef *bcd;
247       for ( ; (bcd=bcli.current()) ; ++bcli )
248       {
249         ClassDef *bClass=bcd->classDef;
250         QCString dotn=cd->name()+":";
251         dotn+=cd->name();
252         QCString csc=bClass->name()+":";
253         csc+=bClass->name();
254         //  fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data());
255         writeVhdlDotLink(t,dotn,csc,0);
256       }
257     }// if bl
258   }// for
259
260   endDot(t);
261   //  writePortLinks(t);
262   f.close();
263   createSVG();
264 }
265
266 //------------------------------------------------------------------------------------------------------------------------------------------------------
267
268 static void startDot(FTextStream &t)
269 {
270   t << " digraph G { \n";
271   t << "rankdir=LR \n";
272   t << "concentrate=TRUE\n";
273   t << "stylesheet=\"doxygen.css\"\n";
274 }
275
276 static void endDot(FTextStream &t)
277 {
278   t <<" } \n";
279 }
280
281 static void startTable(FTextStream &t,const QCString &className)
282 {
283   t << className <<" [ shape=none , fontname=\"arial\",  fontcolor=\"blue\" , \n";
284   t << "label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n";
285 }
286
287 static void writeVhdlDotLink(FTextStream &t,
288     const QCString &a,const QCString &b,const QCString &style)
289 {
290   t << a << "->" << b;
291   if (!style.isEmpty())
292   {
293     t << "[style=" << style << "];\n";
294   }
295   t << "\n";
296 }
297
298
299 static QCString formatBriefNote(const QCString &brief,ClassDef * cd)
300 {
301   QRegExp ep("[\n]");
302   QCString vForm;
303   QCString repl("<BR ALIGN=\"LEFT\"/>");
304   QCString file=cd->getDefFileName();
305
306   int k=cd->briefLine();
307
308   QStringList qsl=QStringList::split(ep,brief);
309   for(uint j=0;j<qsl.count();j++)
310   {
311     QCString qcs=qsl[j].data();
312     vForm+=parseCommentAsText(cd,NULL,qcs,file,k);
313     k++;
314     vForm+='\n';
315   }
316
317   vForm.replace(ep,repl.data());
318   return vForm;
319 }
320
321 #if 0
322 static void writeVhdlPortToolTip(FTextStream& t,QList<MemberDef>* port,ClassDef *cd)
323 {
324 /*
325   uint len=port->count();
326   MemberDef *md;
327
328   for (uint j=0;j<len;j++)
329   {
330     md=(MemberDef*)port->at(j);
331     QCString brief=md->briefDescriptionAsTooltip();
332     if (brief.isEmpty()) continue;
333
334     QCString node="node";
335     node+=VhdlDocGen::getRecordNumber();
336     t << node <<"[shape=box margin=0.1, label=<\n";
337     t<<"<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
338     t<<"<TR><TD BGCOLOR=\"lightcyan\"> ";
339     t<<brief;
340     t<<" </TD></TR></TABLE>>];";
341     QCString dotn=cd->name()+":";
342     dotn+=md->name();
343     //  writeVhdlDotLink(t,dotn,node,"dotted");
344   }
345 */
346 }
347 #endif
348
349 static void writeVhdlEntityToolTip(FTextStream& t,ClassDef *cd)
350 {
351
352   QCString brief=cd->briefDescription();
353
354   if (brief.isEmpty()) return;
355
356   brief=formatBriefNote(brief,cd);
357
358   QCString node="node";
359   node+=VhdlDocGen::getRecordNumber();
360   t << node <<"[shape=none margin=0.1, label=<\n";
361   t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
362   t << "<TR><TD BGCOLOR=\"lightcyan\"> ";
363   t << brief;
364   t << " </TD></TR></TABLE>>];";
365   QCString dotn=cd->name()+":";
366   dotn+=cd->name();
367   writeVhdlDotLink(t,dotn,node,"dotted");
368 }
369
370 static void writeColumn(FTextStream &t,MemberDef *md,bool start)
371 {
372   QCString toolTip;
373
374   static QRegExp reg("[%]");
375   bool bidir=(md!=0 &&( qstricmp(md->typeString(),"inout")==0));
376
377   if (md)
378   {
379     toolTip=md->briefDescriptionAsTooltip();
380     if (!toolTip.isEmpty())
381     {
382       QCString largs = md->argsString();
383       if (!largs.isEmpty())
384         largs=largs.replace(reg," ");
385       toolTip+=" [";
386       toolTip+=largs;
387       toolTip+="]";
388     }
389   }
390   if (start)
391   {
392     t <<"<TR>\n";
393   }
394
395   t << "<TD ALIGN=\"LEFT\" ";
396   if (md)
397   {
398     t << "href=\"";
399     t << md->getOutputFileBase()<< Doxygen::htmlFileExtension;
400     t << "#" << md->anchor();
401     t<<"\" ";
402
403     t<<" TOOLTIP=\"";
404     if (!toolTip.isEmpty())
405     {
406       codify(t,toolTip.data());
407     }
408     else
409     {
410       QCString largs = md->argsString();
411       if (!largs.isEmpty())
412       {
413         largs=largs.replace(reg," ");
414         codify(t,largs.data());
415       }
416     }
417     t << "\" ";
418
419     t << " PORT=\"";
420     t << md->name();
421     t << "\" ";
422   }
423   if (!toolTip.isEmpty())
424   {
425     // if (!toolTip.isEmpty())
426
427     if (bidir)
428       t << "BGCOLOR=\"orange\">";
429     else
430       t << "BGCOLOR=\"azure\">";
431   }
432   else if (bidir)
433   {
434     t << "BGCOLOR=\"pink\">";
435   }
436   else
437   {
438     t << "BGCOLOR=\"lightgrey\">";
439   }
440   if (md)
441   {
442     t << md->name();
443   }
444   else
445   {
446     t << " \n";
447   }
448   t << "</TD>\n";
449
450   if (!start)
451   {
452     t << "</TR>\n";
453   }
454 }
455
456 static void endTabel(FTextStream &t)
457 {
458   t << "</TABLE>>\n";
459   t << "] \n";
460 }
461
462 static void writeClassToDot(FTextStream &t,ClassDef* cd)
463 {
464   t << "<TR><TD COLSPAN=\"2\" BGCOLOR=\"yellow\" ";
465   t << "PORT=\"";
466   t << cd->name();
467   t << "\" ";
468   t << "href=\"";
469   t << cd->getOutputFileBase() << Doxygen::htmlFileExtension;
470   t << "\" ";
471   t << ">";
472   t << cd->name();
473   t << " </TD></TR>\n";
474 }
475
476 static QList<MemberDef>* getPorts(ClassDef *cd)
477 {
478   MemberDef* md;
479   QList<MemberDef> *portList=new QList<MemberDef>;
480   MemberList *ml=cd->getMemberList(MemberListType_variableMembers);
481
482   if (ml==0) return NULL;
483
484   MemberListIterator fmni(*ml);
485
486   for (fmni.toFirst();(md=fmni.current());++fmni)
487   {
488     if (md->getMemberSpecifiers()==VhdlDocGen::PORT)
489     {
490       portList->append(md);
491     }
492   }
493
494   return portList;
495 }
496
497 //writeColumn(FTextStream &t,QCString name,bool start)
498
499 static void writeTable(QList<MemberDef>* port,FTextStream & t)
500 {
501   QCString space(" ");
502   MemberDef *md;
503   uint len=port->count();
504
505   QList<MemberDef> inPorts;
506   QList<MemberDef> outPorts;
507
508   uint j;
509   for (j=0;j<len;j++)
510   {
511     md=(MemberDef*)port->at(j);
512     QCString qc=md->typeString();
513     if(qc=="in")
514     {
515       inPorts.append(md);
516     }
517     else
518     {
519       outPorts.append(md);
520     }
521   }
522
523   int inp  = inPorts.count();
524   int outp = outPorts.count();
525   int maxLen;
526
527   if (inp>=outp)
528   {
529     maxLen=inp;
530   }
531   else
532   {
533     maxLen=outp;
534   }
535
536   int i;
537   for(i=0;i<maxLen;i++)
538   {
539     //write inports
540     if (i<inp)
541     {
542       md=(MemberDef*)inPorts.at(i);
543       writeColumn(t,md,TRUE);
544     }
545     else
546     {
547       writeColumn(t,NULL,TRUE);
548     }
549
550     if (i<outp)
551     {
552       md=(MemberDef*)outPorts.at(i);
553       writeColumn(t,md,FALSE);
554     }
555     else
556     {
557       writeColumn(t,NULL,FALSE);
558     }
559   }
560 }
561
562 //--------------------------------------------------------------------------------------------------
563
564
565 VhdlDocGen::VhdlDocGen()
566 {
567 }
568
569 VhdlDocGen::~VhdlDocGen()
570 {
571 }
572
573 void VhdlDocGen::init()
574 {
575
576  // vhdl keywords inlcuded VHDL 2008
577 const char* g_vhdlKeyWordMap0[] =
578 {
579   "abs","access","after","alias","all","and","architecture","array","assert","assume","assume_guarantee","attribute",
580   "begin","block","body","buffer","bus",
581   "case","component","configuration","constant","context","cover",
582   "default","disconnect","downto",
583   "else","elsif","end","entity","exit",
584   "fairness","file","for","force","function",
585   "generate","generic","group","guarded",
586   "if","impure","in","inertial","inout","is",
587   "label","library","linkage","literal","loop",
588   "map","mod",
589   "nand","new","next","nor","not","null",
590   "of","on","open","or","others","out",
591   "package","parameter","port","postponed","procedure","process","property","proctected","pure",
592   "range","record","register","reject","release","restrict","restrict_guarantee","rem","report","rol","ror","return",
593   "select","sequence","severity","signal","shared","sla","sll","sra","srl","strong","subtype",
594   "then","to","transport","type",
595   "unaffected","units","until","use",
596   "variable","vmode","vprop","vunit",
597   "wait","when","while","with",
598   "xor","xnor",
599   0
600 };
601
602
603 // type
604 const char* g_vhdlKeyWordMap1[] =
605 {
606   "natural","unsigned","signed","string","boolean", "bit","bit_vector","character",
607   "std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer",
608   "real","float","ufixed","sfixed","time",0
609 };
610
611 // logic
612 const char* g_vhdlKeyWordMap2[] =
613 {
614   "abs","and","or","not","mod", "xor","rem","xnor","ror","rol","sla",
615   "sll",0
616 };
617
618 // predefined attributes
619 const char* g_vhdlKeyWordMap3[] =
620 {
621 "base","left","right","high","low","ascending",
622 "image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low",
623 "range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event",
624 "active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name",0
625 };
626
627   int j=0;
628   g_vhdlKeyDict0.setAutoDelete(TRUE);
629   g_vhdlKeyDict1.setAutoDelete(TRUE);
630   g_vhdlKeyDict2.setAutoDelete(TRUE);
631   g_vhdlKeyDict3.setAutoDelete(TRUE);
632
633   while (g_vhdlKeyWordMap0[j])
634   {
635     g_vhdlKeyDict0.insert(g_vhdlKeyWordMap0[j],
636                        new QCString(g_vhdlKeyWordMap0[j]));
637     j++;
638   }
639
640   j=0;
641   while (g_vhdlKeyWordMap1[j])
642   {
643     g_vhdlKeyDict1.insert(g_vhdlKeyWordMap1[j],
644                        new QCString(g_vhdlKeyWordMap1[j]));
645     j++;
646   }
647
648   j=0;
649   while (g_vhdlKeyWordMap2[j])
650   {
651     g_vhdlKeyDict2.insert(g_vhdlKeyWordMap2[j],
652                        new QCString(g_vhdlKeyWordMap2[j]));
653     j++;
654   }
655
656   j=0;
657   while (g_vhdlKeyWordMap3[j])
658   {
659     g_vhdlKeyDict3.insert(g_vhdlKeyWordMap3[j],
660                        new QCString(g_vhdlKeyWordMap3[j]));
661     j++;
662   }
663
664 }// buildKeyMap
665
666 /*!
667  * returns the color of a keyword
668  */
669
670 QCString* VhdlDocGen::findKeyWord(const QCString& tmp)
671 {
672   static  QCString vhdlkeyword("vhdlkeyword");
673   static  QCString vhdltype("comment");
674   static  QCString vhdllogic("vhdllogic");
675   static  QCString preprocessor("keywordflow");
676
677   QCString word=tmp.lower();
678
679   if (word.isEmpty() || word.at(0)=='\0') return 0;
680
681   if (g_vhdlKeyDict0.find(word))
682     return &preprocessor;
683
684   if (g_vhdlKeyDict1.find(word))
685     return &vhdltype;
686
687   if (g_vhdlKeyDict2.find(word))
688     return &vhdllogic;
689
690    if (g_vhdlKeyDict3.find(word))
691     return &vhdlkeyword;
692
693   return 0;
694 }
695
696 ClassDef *VhdlDocGen::getClass(const char *name)
697 {
698   if (name==0 || name[0]=='\0') return 0;
699
700   ClassDef *cd=0;
701   QCString temp(name);
702   //temp=temp.lower();
703   temp=temp.stripWhiteSpace();
704   cd= Doxygen::classSDict->find(temp.data());
705   return cd;
706 }
707
708 ClassDef* VhdlDocGen::getPackageName(const QCString & name)
709 {
710   ClassDef* cd=0;
711   QStringList ql=QStringList::split(".",name,FALSE);
712   cd=getClass(name);
713
714   return cd;
715 }
716
717 static QMap<QCString,MemberDef*> varMap;
718 static QList<ClassDef> qli;
719 static QMap<ClassDef*,QList<ClassDef> > packages;
720
721 MemberDef* VhdlDocGen::findMember(const QCString& className, const QCString& memName)
722 {
723   ClassDef* cd,*ecd;
724   MemberDef *mdef=0;
725
726   cd=getClass(className);
727   //printf("VhdlDocGen::findMember(%s,%s)=%p\n",className.data(),memName.data(),cd);
728   if (cd==0) return 0;
729
730   mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_variableMembers);
731   if (mdef) return mdef;
732   mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_pubMethods);
733   if (mdef) return mdef;
734
735   // nothing found so far
736   // if we are an architecture or package body search in entitiy
737
738   if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS ||
739       (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
740   {
741     Definition *d = cd->getOuterScope();
742     // searching upper/lower case names
743
744     QCString tt=d->name();
745     ecd =getClass(tt);
746     if (!ecd)
747     {
748       tt=tt.upper();
749       ecd =getClass(tt);
750     }
751     if (!ecd)
752     {
753       tt=tt.lower();
754       ecd =getClass(tt);
755     }
756
757     if (ecd) //d && d->definitionType()==Definition::TypeClass)
758     {
759       //ClassDef *ecd = (ClassDef*)d;
760       mdef=VhdlDocGen::findMemberDef(ecd,memName,MemberListType_variableMembers);
761       if (mdef) return mdef;
762       mdef=VhdlDocGen::findMemberDef(cd,memName,MemberListType_pubMethods);
763       if (mdef) return mdef;
764     }
765    }
766
767
768   if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS ||
769       (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
770   {
771     Definition *d = cd->getOuterScope();
772
773     QCString tt=d->name();
774     ClassDef *ecd =getClass(tt);
775     if (!ecd)
776     {
777       tt=tt.upper();
778       ecd =getClass(tt);
779     }
780     if (!ecd)
781     {
782       tt=tt.lower();
783       ecd =getClass(tt);
784     }
785     if (ecd) //d && d->definitionType()==Definition::TypeClass)
786     {
787       if(!packages.contains(ecd))
788       {
789         VhdlDocGen::findAllPackages(ecd);
790       }
791     }
792   }
793   else
794   {
795     ecd=cd;
796     if (!packages.contains(ecd)) VhdlDocGen::findAllPackages(ecd);
797   }
798
799   uint len=packages.count();
800   for (uint j=0;j<len;j++)
801   {
802     for (QMap<ClassDef*,QList<ClassDef> >::Iterator cList=packages.begin();cList != packages.end();cList++)
803     {
804       if (cList.key()==0) continue;
805       QList<ClassDef> mlist=cList.data();
806       for (uint j=0;j<mlist.count();j++)
807       {
808         mdef=VhdlDocGen::findMemberDef(mlist.at(j),memName,MemberListType_variableMembers);
809         if (mdef) return mdef;
810         mdef=VhdlDocGen::findMemberDef(mlist.at(j),memName,MemberListType_pubMethods);
811         if (mdef) return mdef;
812       }
813     }
814   }
815   return 0;
816
817 }//findMember
818
819 /**
820  *  This function returns the entity|package
821  *  in which the key (type) is found
822  */
823 MemberDef* VhdlDocGen::findMemberDef(ClassDef* cd,const QCString& key,MemberListType type)
824 {
825   MemberDef *md=0;
826   MemberList *ml=0;
827   QCString keyType=cd->symbolName()+"@"+key;
828   //printf("\n %s | %s | %s",cd->symbolName().data(),key.data(,),keyType.data());
829
830   QMap<QCString, MemberDef*>::Iterator it =varMap.find(keyType);
831   if (it.key())
832   {
833     md=it.data();
834     if (md)
835     {
836       return md;
837     }
838   }
839   if (qli.contains(cd))
840   {
841     return 0;
842   }
843   ml=cd->getMemberList(type);
844   qli.append(cd);
845   if (!ml)
846   {
847     return 0;
848   }
849   MemberListIterator fmni(*ml);
850   //int l=ml->count();
851   //    fprintf(stderr,"\n loading enity %s %s: %d",cd->symbolName().data(),keyType.data(),l);
852
853   for (fmni.toFirst();(md=fmni.current());++fmni)
854   {
855     QCString tkey=cd->symbolName()+"@"+md->name();
856     if (varMap.contains(tkey))
857     {
858       continue;
859     }
860     varMap.insert(tkey.data(),md);
861   }
862   it=varMap.find(keyType.data());
863   if (it.key())
864   {
865     md=it.data();
866     if (md)
867     {
868       return md;
869     }
870   }
871   return 0;
872 }//findMemberDef
873
874 /*!
875  * finds all included packages of an Entity or Package
876  */
877
878 void VhdlDocGen::findAllPackages( ClassDef *cdef)
879 {
880   QList<ClassDef> cList;
881   if (packages.contains(cdef)) return;
882   MemberList *mem=cdef->getMemberList(MemberListType_variableMembers);
883   MemberDef *md;
884
885   if (!mem) return;
886
887   MemberListIterator fmni(*mem);
888   for (fmni.toFirst();(md=fmni.current());++fmni)
889   {
890     if (VhdlDocGen::isPackage(md))
891     {
892       ClassDef* cd=VhdlDocGen::getPackageName(md->name());
893       if (cd)
894       {
895         cList.append(cd);
896         VhdlDocGen::findAllPackages(cd);
897         packages.insert(cdef,cList);
898       }
899     }
900   }//for
901
902 }// findAllPackages
903
904 /*!
905  * returns the function with the matching argument list
906  * is called in vhdlcode.l
907  */
908
909 MemberDef* VhdlDocGen::findFunction(const QList<Argument> &ql,
910     const QCString& funcname,
911     const QCString& package, bool /*type*/)
912 {
913   MemberDef* mdef=0;
914   //int funcType;
915   ClassDef *cdef=getClass(package.data());
916   if (cdef==0) return 0;
917
918   MemberList *mem=cdef->getMemberList(MemberListType_pubMethods);
919
920   if (mem)
921   {
922     MemberListIterator fmni(*mem);
923     for (fmni.toFirst();(mdef=fmni.current());++fmni)
924     {
925       QCString mname=mdef->name();
926       if ((VhdlDocGen::isProcedure(mdef) || VhdlDocGen::isVhdlFunction(mdef)) && (compareString(funcname,mname)==0))
927       {
928         ArgumentList *alp = mdef->argumentList();
929
930         //  ArgumentList* arg2=mdef->getArgumentList();
931         if (alp==0) break;
932         ArgumentListIterator ali(*alp);
933         ArgumentListIterator ali1(ql);
934
935         if (ali.count() != ali1.count()) break;
936
937         Argument *arg,*arg1;
938         int equ=0;
939
940         for (;(arg=ali.current());++ali)
941         {
942           arg1=ali1.current(); ++ali1;
943           equ+=abs(compareString(arg->type,arg1->type));
944
945           QCString s1=arg->type;
946           QCString s2=arg1->type;
947           VhdlDocGen::deleteAllChars(s1,' ');
948           VhdlDocGen::deleteAllChars(s2,' ');
949           equ+=abs(compareString(s1,s2));
950           s1=arg->attrib;
951           s2=arg1->attrib;
952           VhdlDocGen::deleteAllChars(s1,' ');
953           VhdlDocGen::deleteAllChars(s2,' ');
954           equ+=abs(compareString(s1,s2));
955           // printf("\n 1. type [%s] name [%s] attrib [%s]",arg->type,arg->name,arg->attrib);
956           // printf("\n 2. type [%s] name [%s] attrib [%s]",arg1->type,arg1->name,arg1->attrib);
957         } // for
958         if (equ==0) return mdef;
959       }//if
960     }//for
961   }//if
962   return mdef;
963 } //findFunction
964
965
966
967
968 /*!
969  * returns the class title+ref
970  */
971
972 QCString VhdlDocGen::getClassTitle(const ClassDef *cd)
973 {
974   QCString pageTitle;
975   if (cd==0) return "";
976   pageTitle+=cd->displayName();
977   pageTitle=VhdlDocGen::getClassName(cd);
978   int ii=cd->protection();
979   pageTitle+=" ";
980   pageTitle+=theTranslator_vhdlType(ii+2,TRUE);
981   pageTitle+=" ";
982   return pageTitle;
983 } // getClassTitle
984
985 /* returns the class name without their prefixes */
986
987 QCString VhdlDocGen::getClassName(const ClassDef* cd)
988 {
989   QCString temp;
990   if (cd==0) return "";
991
992   if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
993   {
994     temp=cd->name();
995     temp.stripPrefix("_");
996     return temp;
997   }
998
999   return substitute(cd->className(),"::",".");
1000 }
1001
1002 /*!
1003  * writes an inline link form entity|package to architecture|package body and vice verca
1004  */
1005
1006 void VhdlDocGen::writeInlineClassLink(const ClassDef* cd ,OutputList& ol)
1007 {
1008   QList<QCString> ql;
1009   ql.setAutoDelete(TRUE);
1010   QCString nn=cd->className();
1011   int ii=(int)cd->protection()+2;
1012
1013   QCString type;
1014   if (ii==VhdlDocGen::ENTITY)
1015     type+=theTranslator_vhdlType(VhdlDocGen::ARCHITECTURE,TRUE);
1016   else if (ii==VhdlDocGen::ARCHITECTURE)
1017     type+=theTranslator_vhdlType(VhdlDocGen::ENTITY,TRUE);
1018   else if (ii==VhdlDocGen::PACKAGE_BODY)
1019     type+=theTranslator_vhdlType(VhdlDocGen::PACKAGE,TRUE);
1020   else if (ii==VhdlDocGen::PACKAGE)
1021     type+=theTranslator_vhdlType(VhdlDocGen::PACKAGE_BODY,TRUE);
1022   else
1023     type+="";
1024
1025   //type=type.lower();
1026   type+=" >> ";
1027   ol.disable(OutputGenerator::RTF);
1028   ol.disable(OutputGenerator::Man);
1029
1030   if (ii==VhdlDocGen::PACKAGE_BODY)
1031   {
1032     nn.stripPrefix("_");
1033     cd=getClass(nn.data());
1034   }
1035   else  if (ii==VhdlDocGen::PACKAGE)
1036   {
1037     nn.prepend("_");
1038     cd=getClass(nn.data());
1039   }
1040   else if (ii==VhdlDocGen::ARCHITECTURE)
1041   {
1042     QStringList qlist=QStringList::split("-",nn,FALSE);
1043     nn=qlist[1].utf8();
1044     cd=VhdlDocGen::getClass(nn.data());
1045   }
1046
1047   QCString opp;
1048   if (ii==VhdlDocGen::ENTITY)
1049   {
1050     VhdlDocGen::findAllArchitectures(ql,cd);
1051     int j=ql.count();
1052     for (int i=0;i<j;i++)
1053     {
1054       QCString *temp=ql.at(i);
1055       QStringList qlist=QStringList::split("-",*temp,FALSE);
1056       QCString s1=qlist[0].utf8();
1057       QCString s2=qlist[1].utf8();
1058       s1.stripPrefix("_");
1059       if (j==1) s1.resize(0);
1060       ClassDef*cc = getClass(temp->data());
1061       if (cc)
1062       {
1063         VhdlDocGen::writeVhdlLink(cc,ol,type,s2,s1);
1064       }
1065     }
1066   }
1067   else
1068   {
1069     VhdlDocGen::writeVhdlLink(cd,ol,type,nn,opp);
1070   }
1071
1072   ol.enable(OutputGenerator::Man);
1073   ol.enable(OutputGenerator::RTF);
1074
1075 }// write
1076
1077 /*
1078  * finds all architectures which belongs to an entiy
1079  */
1080 void VhdlDocGen::findAllArchitectures(QList<QCString>& qll,const ClassDef *cd)
1081 {
1082   ClassDef *citer;
1083   ClassSDict::Iterator cli(*Doxygen::classSDict);
1084   for ( ; (citer=cli.current()) ; ++cli )
1085   {
1086     QCString jj=citer->className();
1087     if (cd != citer && jj.contains('-')!=-1)
1088     {
1089       QStringList ql=QStringList::split("-",jj,FALSE);
1090       QCString temp=ql[1].utf8();
1091       if (qstricmp(cd->className(),temp)==0)
1092       {
1093         QCString *cl=new QCString(jj);
1094         qll.insert(0,cl);
1095       }
1096     }
1097   }// for
1098 }//findAllArchitectures
1099
1100 ClassDef* VhdlDocGen::findArchitecture(const ClassDef *cd)
1101 {
1102   ClassDef *citer;
1103   QCString nn=cd->name();
1104   ClassSDict::Iterator cli(*Doxygen::classSDict);
1105
1106   for ( ; (citer=cli.current()) ; ++cli )
1107   {
1108     QCString jj=citer->name();
1109     QStringList ql=QStringList::split(":",jj,FALSE);
1110     if (ql.count()>1)
1111     {
1112       if (ql[0].utf8()==nn )
1113       {
1114         return citer;
1115       }
1116     }
1117   }
1118   return 0;
1119 }
1120 /*
1121  * writes the link entity >> .... or architecture >> ...
1122  */
1123
1124 void VhdlDocGen::writeVhdlLink(const ClassDef* ccd ,OutputList& ol,QCString& type,QCString& nn,QCString& behav)
1125 {
1126   if (ccd==0)  return;
1127   QCString temp=ccd->getOutputFileBase();
1128   ol.startBold();
1129   ol.docify(type.data());
1130   ol.endBold();
1131   nn.stripPrefix("_");
1132   ol.writeObjectLink(ccd->getReference(),ccd->getOutputFileBase(),0,nn.data());
1133
1134   if (!behav.isEmpty())
1135   {
1136     behav.prepend("  ");
1137     ol.startBold();
1138     ol.docify(behav.data());
1139     ol.endBold();
1140   }
1141
1142   ol.lineBreak();
1143 }
1144
1145
1146 /*!
1147  * strips the "--" prefixes of vhdl comments
1148  */
1149 void VhdlDocGen::prepareComment(QCString& qcs)
1150 {
1151   const char* s="--!";
1152   int index=0;
1153
1154   while (TRUE)
1155   {
1156     index=qcs.find(s,0,TRUE);
1157     if (index<0) break;
1158     qcs=qcs.remove(index,qstrlen(s));
1159   }
1160   qcs=qcs.stripWhiteSpace();
1161 }
1162
1163
1164 /*!
1165  * parses a function proto
1166  * @param text function string
1167  * @param qlist stores the function types
1168  * @param name points to the function name
1169  * @param ret Stores the return type
1170  * @param doc ???
1171  */
1172 void VhdlDocGen::parseFuncProto(const char* text,QList<Argument>& qlist,
1173     QCString& name,QCString& ret,bool doc)
1174 {
1175   (void)qlist; //unused
1176   int index,end;
1177   QCString s1(text);
1178   QCString temp;
1179
1180   index=s1.find("(");
1181   end=s1.findRev(")");
1182
1183   if ((end-index)>0)
1184   {
1185     QCString tt=s1.mid(index,(end-index+1));
1186     temp=s1.mid(index+1,(end-index-1));
1187     //getFuncParams(qlist,temp);
1188   }
1189   if (doc)
1190   {
1191     name=s1.left(index);
1192     name=name.stripWhiteSpace();
1193     if ((end-index)>0)
1194     {
1195       ret="function";
1196     }
1197     return;
1198   }
1199   else
1200   {
1201     QCString s1(text);
1202     s1=s1.stripWhiteSpace();
1203     int i=s1.find("(",0,FALSE);
1204     int s=s1.find(QRegExp("[ \\t]"));
1205     if (i==-1 || i<s)
1206       s1=VhdlDocGen::getIndexWord(s1.data(),1);
1207     else // s<i, s=start of name, i=end of name
1208       s1=s1.mid(s,(i-s));
1209
1210     name=s1.stripWhiteSpace();
1211   }
1212   index=s1.findRev("return",-1,FALSE);
1213   if (index !=-1)
1214   {
1215     ret=s1.mid(index+6,s1.length());
1216     ret=ret.stripWhiteSpace();
1217     VhdlDocGen::deleteCharRev(ret,';');
1218   }
1219 }
1220
1221 /*
1222  *  returns the n'th word of a string
1223  */
1224
1225 QCString VhdlDocGen::getIndexWord(const char* c,int index)
1226 {
1227   QStringList ql;
1228   QCString temp(c);
1229   QRegExp reg("[\\s:|]");
1230
1231   ql=QStringList::split(reg,temp,FALSE);
1232
1233   if (ql.count() > (unsigned int)index)
1234   {
1235     return ql[index].utf8();
1236   }
1237
1238   return "";
1239 }
1240
1241
1242 QCString VhdlDocGen::getProtectionName(int prot)
1243 {
1244   if (prot==VhdlDocGen::ENTITYCLASS)
1245     return "entity";
1246   else if (prot==VhdlDocGen::ARCHITECTURECLASS)
1247     return "architecture";
1248   else if (prot==VhdlDocGen::PACKAGECLASS)
1249     return "package";
1250   else if (prot==VhdlDocGen::PACKBODYCLASS)
1251     return "package body";
1252
1253   return "";
1254 }
1255
1256 QCString VhdlDocGen::trTypeString(uint64 type)
1257 {
1258   switch(type)
1259   {
1260     case VhdlDocGen::LIBRARY:        return "Library";
1261     case VhdlDocGen::ENTITY:         return "Entity";
1262     case VhdlDocGen::PACKAGE_BODY:   return "Package Body";
1263     case VhdlDocGen::ATTRIBUTE:      return "Attribute";
1264     case VhdlDocGen::PACKAGE:        return "Package";
1265     case VhdlDocGen::SIGNAL:         return "Signal";
1266     case VhdlDocGen::COMPONENT:      return "Component";
1267     case VhdlDocGen::CONSTANT:       return "Constant";
1268     case VhdlDocGen::TYPE:           return "Type";
1269     case VhdlDocGen::SUBTYPE:        return "Subtype";
1270     case VhdlDocGen::FUNCTION:       return "Function";
1271     case VhdlDocGen::RECORD:         return "Record";
1272     case VhdlDocGen::PROCEDURE:      return "Procedure";
1273     case VhdlDocGen::ARCHITECTURE:   return "Architecture";
1274     case VhdlDocGen::USE:            return "Package";
1275     case VhdlDocGen::PROCESS:        return "Process";
1276     case VhdlDocGen::PORT:           return "Port";
1277     case VhdlDocGen::GENERIC:        return "Generic";
1278     case VhdlDocGen::UNITS:          return "Units";
1279                                      //case VhdlDocGen::PORTMAP:        return "Port Map";
1280     case VhdlDocGen::SHAREDVARIABLE: return "Shared Variable";
1281     case VhdlDocGen::GROUP:          return "Group";
1282     case VhdlDocGen::VFILE:          return "File";
1283     case VhdlDocGen::INSTANTIATION: return "Instantiation";
1284     case VhdlDocGen::ALIAS:          return "Alias";
1285     case VhdlDocGen::CONFIG:         return "Configuration";
1286     case VhdlDocGen::MISCELLANEOUS:  return "Miscellaneous";
1287     case VhdlDocGen::UCF_CONST:      return "Constraints";
1288     default:                         return "";
1289   }
1290 } // convertType
1291
1292 /*!
1293  * deletes a char backwards in a string
1294  */
1295
1296 bool VhdlDocGen::deleteCharRev(QCString &s,char c)
1297 {
1298   int index=s.findRev(c,-1,FALSE);
1299   if (index > -1)
1300   {
1301     QCString qcs=s.remove(index,1);
1302     s=qcs;
1303     return TRUE;
1304   }
1305   return FALSE;
1306 }
1307
1308 void VhdlDocGen::deleteAllChars(QCString &s,char c)
1309 {
1310   int index=s.findRev(c,-1,FALSE);
1311   while (index > -1)
1312   {
1313     QCString qcs=s.remove(index,1);
1314     s=qcs;
1315     index=s.findRev(c,-1,FALSE);
1316   }
1317 }
1318
1319
1320 static int recordCounter=0;
1321
1322 /*!
1323  * returns the next number of a record|unit member
1324  */
1325
1326 QCString VhdlDocGen::getRecordNumber()
1327 {
1328   char buf[12];
1329   sprintf(buf,"%d",recordCounter++);
1330   QCString qcs(&buf[0]);
1331   return qcs;
1332 }
1333
1334 /*!
1335  * returns the next number of an anonymous process
1336  */
1337
1338 QCString VhdlDocGen::getProcessNumber()
1339 {
1340   static int stringCounter;
1341   char buf[8];
1342   QCString qcs("PROCESS_");
1343   sprintf(buf,"%d",stringCounter++);
1344   qcs.append(&buf[0]);
1345   return qcs;
1346 }
1347
1348 /*!
1349  * writes a colored and formatted string
1350  */
1351
1352 void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberDef* mdef)
1353 {
1354   QRegExp reg("[\\[\\]\\.\\/\\:\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]");
1355   QCString qcs = s;
1356   qcs+=QCString(" ");// parsing the last sign
1357   QCString *ss;
1358   QCString find=qcs;
1359   QCString temp=qcs;
1360   char buf[2];
1361   buf[1]='\0';
1362
1363   int j;
1364   int len;
1365   j = reg.match(temp.data(),0,&len);
1366
1367   ol.startBold();
1368   if (j>=0)
1369   {
1370     while (j>=0)
1371     {
1372       find=find.left(j);
1373       buf[0]=temp[j];
1374       ss=VhdlDocGen::findKeyWord(find);
1375       bool k=isNumber(find); // is this a number
1376       if (k)
1377       {
1378         ol.docify(" ");
1379         startFonts(find,"vhdldigit",ol);
1380         ol.docify(" ");
1381       }
1382       else if (j != 0 && ss)
1383       {
1384         startFonts(find,ss->data(),ol);
1385       }
1386       else
1387       {
1388         if (j>0)
1389         {
1390           VhdlDocGen::writeStringLink(mdef,find,ol);
1391         }
1392       }
1393       startFonts(&buf[0],"vhdlchar",ol);
1394
1395       QCString st=temp.remove(0,j+1);
1396       find=st;
1397       if (!find.isEmpty() && find.at(0)=='"')
1398       {
1399         int ii=find.find('"',2);
1400         if (ii>1)
1401         {
1402           QCString com=find.left(ii+1);
1403           startFonts(com,"keyword",ol);
1404           temp=find.remove(0,ii+1);
1405         }
1406       }
1407       else
1408       {
1409         temp=st;
1410       }
1411       j = reg.match(temp.data(),0,&len);
1412     }//while
1413   }//if
1414   else
1415   {
1416     startFonts(find,"vhdlchar",ol);
1417   }
1418   ol.endBold();
1419 }// writeFormatString
1420
1421 /*!
1422  * returns TRUE if this string is a number
1423  */
1424 bool VhdlDocGen::isNumber(const QCString& s)
1425 {
1426   static QRegExp regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*");
1427
1428   if (s.isEmpty()) return FALSE;
1429   int j,len;
1430   j = regg.match(s.data(),0,&len);
1431   if ((j==0) && (len==(int)s.length())) return TRUE;
1432   return FALSE;
1433
1434 }// isNumber
1435
1436
1437 /*!
1438  * inserts white spaces for  better readings
1439  * and writes a colored string to the output
1440  */
1441
1442 void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* mdef)
1443 {
1444   QCString qcs = s;
1445   QCString temp(qcs.length());
1446   qcs.stripPrefix(":");
1447   qcs.stripPrefix("is");
1448   qcs.stripPrefix("IS");
1449   qcs.stripPrefix("of");
1450   qcs.stripPrefix("OF");
1451
1452   // VhdlDocGen::deleteCharRev(qcs,';');
1453   //char white='\t';
1454   int len = qcs.length();
1455   unsigned int index=1;//temp.length();
1456
1457   for (int j=0;j<len;j++)
1458   {
1459     char c=qcs[j];
1460     char b=c;
1461     if (j>0) b=qcs[j-1];
1462     if (c=='"' || c==',' || c=='\''|| c=='(' || c==')'  || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>'))
1463     {
1464       if (temp.at(index-1) != ' ')
1465       {
1466         temp+=" ";
1467       }
1468       temp+=c;
1469       temp+=" ";
1470     }
1471     else if (c=='=')
1472     {
1473       if (b==':') // := operator
1474       {
1475         temp.replace(index-1,1,"=");
1476         temp+=" ";
1477       }
1478       else // = operator
1479       {
1480         temp+=" ";
1481         temp+=c;
1482         temp+=" ";
1483       }
1484     }
1485     else
1486     {
1487       temp+=c;
1488     }
1489
1490     index=temp.length();
1491   }// for
1492   temp=temp.stripWhiteSpace();
1493   // printf("\n [%s]",qcs.data());
1494   VhdlDocGen::writeFormatString(temp,ol,mdef);
1495 }
1496
1497 /*!
1498  * writes a procedure prototype to the output
1499  */
1500
1501 void VhdlDocGen::writeProcedureProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
1502 {
1503   ArgumentListIterator ali(*al);
1504   Argument *arg;
1505   bool sem=FALSE;
1506   int len=al->count();
1507   ol.docify("( ");
1508   if (len > 2)
1509   {
1510     ol.lineBreak();
1511   }
1512   for (;(arg=ali.current());++ali)
1513   {
1514     ol.startBold();
1515     if (sem && len <3)
1516       ol.writeChar(',');
1517
1518     QCString nn=arg->name;
1519     nn+=": ";
1520
1521     QCString *str=VhdlDocGen::findKeyWord(arg->defval);
1522     arg->defval+=" ";
1523     if (str)
1524     {
1525       startFonts(arg->defval,str->data(),ol);
1526     }
1527     else
1528     {
1529       startFonts(arg->defval,"vhdlchar",ol); // write type (variable,constant etc.)
1530     }
1531
1532     startFonts(nn,"vhdlchar",ol); // write name
1533     if (qstricmp(arg->attrib,arg->type) != 0)
1534     {
1535       startFonts(arg->attrib.lower(),"stringliteral",ol); // write in|out
1536     }
1537     ol.docify(" ");
1538     VhdlDocGen::formatString(arg->type,ol,mdef);
1539     sem=TRUE;
1540     ol.endBold();
1541     if (len > 2)
1542     {
1543       ol.lineBreak();
1544       ol.docify("  ");
1545     }
1546   }//for
1547
1548   ol.docify(" )");
1549
1550
1551 }
1552
1553 /*!
1554  * writes a function prototype to the output
1555  */
1556
1557 void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
1558 {
1559   if (al==0) return;
1560   ArgumentListIterator ali(*al);
1561   Argument *arg;
1562   bool sem=FALSE;
1563   int len=al->count();
1564   ol.startBold();
1565   ol.docify(" ( ");
1566   ol.endBold();
1567   if (len>2)
1568   {
1569     ol.lineBreak();
1570   }
1571   for (;(arg=ali.current());++ali)
1572   {
1573     ol.startBold();
1574     QCString att=arg->defval;
1575     bool bGen=att.stripPrefix("gen!");
1576
1577     if (sem && len < 3)
1578     {
1579       ol.docify(" , ");
1580     }
1581
1582     if (bGen)
1583     {
1584       VhdlDocGen::formatString(QCString("generic "),ol,mdef);
1585     }
1586     if (!att.isEmpty())
1587     {
1588       QCString *str=VhdlDocGen::findKeyWord(att);
1589       att+=" ";
1590       if (str)
1591         VhdlDocGen::formatString(att,ol,mdef);
1592       else
1593         startFonts(att,"vhdlchar",ol);
1594     }
1595
1596     QCString nn=arg->name;
1597     nn+=": ";
1598     QCString ss=arg->type.stripWhiteSpace(); //.lower();
1599     QCString w=ss.stripWhiteSpace();//.upper();
1600     startFonts(nn,"vhdlchar",ol);
1601     startFonts("in ","stringliteral",ol);
1602     QCString *str=VhdlDocGen::findKeyWord(ss);
1603     if (str)
1604       VhdlDocGen::formatString(w,ol,mdef);
1605     else
1606       startFonts(w,"vhdlchar",ol);
1607
1608     if (arg->attrib)
1609       startFonts(arg->attrib,"vhdlchar",ol);
1610
1611
1612     sem=TRUE;
1613     ol.endBold();
1614     if (len > 2)
1615     {
1616       ol.lineBreak();
1617     }
1618   }
1619   ol.startBold();
1620   ol.docify(" )");
1621   const char *exp=mdef->excpString();
1622   if (exp)
1623   {
1624     ol.insertMemberAlign();
1625     ol.startBold();
1626     ol.docify("[ ");
1627     ol.docify(exp);
1628     ol.docify(" ]");
1629     ol.endBold();
1630   }
1631   ol.endBold();
1632 }
1633
1634 /*!
1635  * writes a process prototype to the output
1636  */
1637
1638 void VhdlDocGen::writeProcessProto(OutputList& ol,const ArgumentList* al,const MemberDef* mdef)
1639 {
1640   if (al==0) return;
1641   ArgumentListIterator ali(*al);
1642   Argument *arg;
1643   bool sem=FALSE;
1644   ol.startBold();
1645   ol.docify(" ( ");
1646   for (;(arg=ali.current());++ali)
1647   {
1648     if (sem)
1649     {
1650       ol.docify(" , ");
1651     }
1652     QCString nn=arg->name;
1653     // startFonts(nn,"vhdlchar",ol);
1654     VhdlDocGen::writeFormatString(nn,ol,mdef);
1655     sem=TRUE;
1656   }
1657   ol.docify(" )");
1658   ol.endBold();
1659 }
1660
1661
1662 /*!
1663  * writes a function|procedure documentation to the output
1664  */
1665
1666 bool VhdlDocGen::writeFuncProcDocu(
1667     const MemberDef *md,
1668     OutputList& ol,
1669     const ArgumentList* al,
1670     bool /*type*/)
1671 {
1672   if (al==0) return FALSE;
1673   //bool sem=FALSE;
1674   ol.enableAll();
1675
1676   ArgumentListIterator ali(*al);
1677   int index=ali.count();
1678   if (index==0)
1679   {
1680     ol.docify(" ( ) ");
1681     return FALSE;
1682   }
1683   ol.endMemberDocName();
1684   ol.startParameterList(TRUE);
1685   //ol.startParameterName(FALSE);
1686   Argument *arg;
1687   bool first=TRUE;
1688   for (;(arg=ali.current());++ali)
1689   {
1690     ol.startParameterType(first,"");
1691     //   if (first) ol.writeChar('(');
1692     QCString attl=arg->defval;
1693     bool bGen=attl.stripPrefix("gen!");
1694     if (bGen)
1695       VhdlDocGen::writeFormatString(QCString("generic "),ol,md);
1696
1697
1698     if (VhdlDocGen::isProcedure(md))
1699     {
1700       startFonts(arg->defval,"keywordtype",ol);
1701       ol.docify(" ");
1702     }
1703     ol.endParameterType();
1704
1705     ol.startParameterName(TRUE);
1706     VhdlDocGen::writeFormatString(arg->name,ol,md);
1707
1708     if (VhdlDocGen::isProcedure(md))
1709     {
1710       startFonts(arg->attrib,"stringliteral",ol);
1711     }
1712     else if (VhdlDocGen::isVhdlFunction(md))
1713     {
1714       startFonts(QCString("in"),"stringliteral",ol);
1715     }
1716
1717     ol.docify(" ");
1718     ol.disable(OutputGenerator::Man);
1719     ol.startEmphasis();
1720     ol.enable(OutputGenerator::Man);
1721     if (!VhdlDocGen::isProcess(md))
1722     {
1723      // startFonts(arg->type,"vhdlkeyword",ol);
1724                 VhdlDocGen::writeFormatString(arg->type,ol,md);
1725     }
1726     ol.disable(OutputGenerator::Man);
1727     ol.endEmphasis();
1728     ol.enable(OutputGenerator::Man);
1729
1730     if (--index)
1731     {
1732       ol.docify(" , ");
1733     }
1734     else
1735     {
1736       //    ol.docify(" ) ");
1737       ol.endParameterName(TRUE,FALSE,TRUE);
1738       break;
1739     }
1740     ol.endParameterName(FALSE,FALSE,FALSE);
1741
1742     //sem=TRUE;
1743     first=FALSE;
1744   }
1745   //ol.endParameterList();
1746   return TRUE;
1747
1748 } // writeDocFunProc
1749
1750
1751
1752
1753 QCString VhdlDocGen::convertArgumentListToString(const ArgumentList* al,bool func)
1754 {
1755   QCString argString;
1756   bool sem=FALSE;
1757   ArgumentListIterator ali(*al);
1758   Argument *arg;
1759
1760   for (;(arg=ali.current());++ali)
1761   {
1762     if (sem) argString.append(", ");
1763     if (func)
1764     {
1765       argString+=arg->name;
1766       argString+=":";
1767       argString+=arg->type;
1768     }
1769     else
1770     {
1771       argString+=arg->defval+" ";
1772       argString+=arg->name+" :";
1773       argString+=arg->attrib+" ";
1774       argString+=arg->type;
1775     }
1776     sem=TRUE;
1777   }
1778   return argString;
1779 }
1780
1781
1782 void VhdlDocGen::writeVhdlDeclarations(MemberList* ml,
1783     OutputList& ol,GroupDef* gd,ClassDef* cd,FileDef *fd,NamespaceDef* nd)
1784 {
1785   static ClassDef *cdef;
1786   //static GroupDef* gdef;
1787   if (cd && cdef!=cd)
1788   { // only one inline link
1789     VhdlDocGen::writeInlineClassLink(cd,ol);
1790     cdef=cd;
1791   }
1792
1793   /*
1794      if (gd && gdef==gd) return;
1795      if (gd && gdef!=gd)
1796      {
1797      gdef=gd;
1798      }
1799    */
1800   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::LIBRARY,FALSE),0,FALSE,VhdlDocGen::LIBRARY);
1801   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::USE,FALSE),0,FALSE,VhdlDocGen::USE);
1802   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::FUNCTION,FALSE),0,FALSE,VhdlDocGen::FUNCTION);
1803   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::COMPONENT,FALSE),0,FALSE,VhdlDocGen::COMPONENT);
1804   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::CONSTANT,FALSE),0,FALSE,VhdlDocGen::CONSTANT);
1805   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::TYPE,FALSE),0,FALSE,VhdlDocGen::TYPE);
1806   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SUBTYPE,FALSE),0,FALSE,VhdlDocGen::SUBTYPE);
1807   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::GENERIC,FALSE),0,FALSE,VhdlDocGen::GENERIC);
1808   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PORT,FALSE),0,FALSE,VhdlDocGen::PORT);
1809   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PROCESS,FALSE),0,FALSE,VhdlDocGen::PROCESS);
1810   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SIGNAL,FALSE),0,FALSE,VhdlDocGen::SIGNAL);
1811   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::ATTRIBUTE,FALSE),0,FALSE,VhdlDocGen::ATTRIBUTE);
1812   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::PROCEDURE,FALSE),0,FALSE,VhdlDocGen::PROCEDURE);
1813   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::RECORD,FALSE),0,FALSE,VhdlDocGen::RECORD);
1814   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::UNITS,FALSE),0,FALSE,VhdlDocGen::UNITS);
1815   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::SHAREDVARIABLE,FALSE),0,FALSE,VhdlDocGen::SHAREDVARIABLE);
1816   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::VFILE,FALSE),0,FALSE,VhdlDocGen::VFILE);
1817   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::GROUP,FALSE),0,FALSE,VhdlDocGen::GROUP);
1818   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::INSTANTIATION,FALSE),0,FALSE,VhdlDocGen::INSTANTIATION);
1819   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::ALIAS,FALSE),0,FALSE,VhdlDocGen::ALIAS);
1820   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::MISCELLANEOUS),0,FALSE,VhdlDocGen::MISCELLANEOUS);
1821
1822   // configurations must be added to global file definitions.
1823   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::CONFIG,FALSE),0,FALSE,VhdlDocGen::CONFIG);
1824   VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::UCF_CONST,FALSE),0,FALSE,VhdlDocGen::UCF_CONST);
1825
1826 }
1827
1828 static void setGlobalType(MemberList *ml)
1829 {
1830   if (ml==0) return;
1831   MemberDef *mdd=0;
1832   MemberListIterator mmli(*ml);
1833   for ( ; (mdd=mmli.current()); ++mmli )
1834   {
1835     QCString l=mdd->typeString();
1836
1837     if (qstrcmp(mdd->argsString(),"package")==0)
1838     {
1839         mdd->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
1840     }
1841     else if (qstrcmp(mdd->argsString(),"configuration")==0)
1842     {
1843       mdd->setMemberSpecifiers(VhdlDocGen::CONFIG);
1844     }
1845     else if (qstrcmp(mdd->typeString(),"library")==0)
1846     {
1847       mdd->setMemberSpecifiers(VhdlDocGen::LIBRARY);
1848     }
1849     else if (qstrcmp(mdd->typeString(),"use")==0)
1850     {
1851       mdd->setMemberSpecifiers(VhdlDocGen::USE);
1852     }
1853     else if (qstricmp(mdd->typeString(),"misc")==0)
1854     {
1855       mdd->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS);
1856     }
1857     else if (qstricmp(mdd->typeString(),"ucf_const")==0)
1858     {
1859       mdd->setMemberSpecifiers(VhdlDocGen::UCF_CONST);
1860     }
1861   }
1862 }
1863
1864 /* writes a vhdl type documentation */
1865 bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition *d, OutputList &ol)
1866 {
1867   ClassDef *cd=(ClassDef*)d;
1868   bool hasParams = FALSE;
1869
1870   if (cd==0) return hasParams;
1871
1872   QCString ttype=mdef->typeString();
1873   QCString largs=mdef->argsString();
1874
1875   if ((VhdlDocGen::isVhdlFunction(mdef) || VhdlDocGen::isProcedure(mdef) || VhdlDocGen::isProcess(mdef)))
1876   {
1877     QCString nn=mdef->typeString();
1878     nn=nn.stripWhiteSpace();
1879     QCString na=cd->name();
1880     MemberDef* memdef=VhdlDocGen::findMember(na,nn);
1881     if (memdef && memdef->isLinkable())
1882     {
1883       ol.docify(" ");
1884
1885       ol.startBold();
1886       writeLink(memdef,ol);
1887       ol.endBold();
1888       ol.docify(" ");
1889     }
1890     else
1891     {
1892       ol.docify(" ");
1893       VhdlDocGen::formatString(ttype,ol,mdef);
1894       ol.docify(" ");
1895     }
1896     ol.docify(mdef->name());
1897     hasParams = VhdlDocGen::writeFuncProcDocu(mdef,ol, mdef->argumentList());
1898   }
1899
1900
1901   if (mdef->isVariable())
1902   {
1903     if (VhdlDocGen::isConstraint(mdef))
1904     {
1905       writeLink(mdef,ol);
1906       ol.docify(" ");
1907
1908       largs=largs.replace(QRegExp("#")," ");
1909       VhdlDocGen::formatString(largs,ol,mdef);
1910       return hasParams;
1911     }
1912     else
1913     {
1914       writeLink(mdef,ol);
1915       if (VhdlDocGen::isLibrary(mdef) || VhdlDocGen::isPackage(mdef))
1916       {
1917         return hasParams;
1918       }
1919       ol.docify(" ");
1920     }
1921
1922     // QCString largs=mdef->argsString();
1923
1924     bool c=largs=="context";
1925     bool brec=largs.stripPrefix("record")  ;
1926
1927     if (!brec && !c)
1928       VhdlDocGen::formatString(ttype,ol,mdef);
1929
1930     if (c || brec || largs.stripPrefix("units"))
1931     {
1932       if (c)
1933           largs=ttype;
1934       VhdlDocGen::writeRecUnitDocu(mdef,ol,largs);
1935       return hasParams;
1936     }
1937
1938     ol.docify(" ");
1939     if (VhdlDocGen::isPort(mdef) || VhdlDocGen::isGeneric(mdef))
1940     {
1941       // QCString largs=mdef->argsString();
1942       VhdlDocGen::formatString(largs,ol,mdef);
1943       ol.docify(" ");
1944     }
1945   }
1946   return hasParams;
1947 }
1948
1949 /* writes a vhdl type declaration */
1950
1951 void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
1952     ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
1953     bool /*inGroup*/)
1954 {
1955   static QRegExp reg("[%]");
1956
1957   Definition *d=0;
1958
1959
1960   ASSERT(cd!=0 || nd!=0 || fd!=0 || gd!=0 ||
1961       mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY ||
1962       mdef->getMemberSpecifiers()==VhdlDocGen::USE
1963       ); // member should belong to something
1964   if (cd) d=cd;
1965   else if (nd) d=nd;
1966   else if (fd) d=fd;
1967   else if (gd) d=gd;
1968   else d=(Definition*)mdef;
1969
1970   // write tag file information of this member
1971   if (!Config_getString("GENERATE_TAGFILE").isEmpty())
1972   {
1973     Doxygen::tagFile << "    <member kind=\"";
1974     if (VhdlDocGen::isGeneric(mdef))      Doxygen::tagFile << "generic";
1975     if (VhdlDocGen::isPort(mdef))         Doxygen::tagFile << "port";
1976     if (VhdlDocGen::isEntity(mdef))       Doxygen::tagFile << "entity";
1977     if (VhdlDocGen::isComponent(mdef))    Doxygen::tagFile << "component";
1978     if (VhdlDocGen::isVType(mdef))        Doxygen::tagFile << "type";
1979     if (VhdlDocGen::isConstant(mdef))     Doxygen::tagFile << "constant";
1980     if (VhdlDocGen::isSubType(mdef))      Doxygen::tagFile << "subtype";
1981     if (VhdlDocGen::isVhdlFunction(mdef)) Doxygen::tagFile << "function";
1982     if (VhdlDocGen::isProcedure(mdef))    Doxygen::tagFile << "procedure";
1983     if (VhdlDocGen::isProcess(mdef))      Doxygen::tagFile << "process";
1984     if (VhdlDocGen::isSignals(mdef))      Doxygen::tagFile << "signal";
1985     if (VhdlDocGen::isAttribute(mdef))    Doxygen::tagFile << "attribute";
1986     if (VhdlDocGen::isRecord(mdef))       Doxygen::tagFile << "record";
1987     if (VhdlDocGen::isLibrary(mdef))      Doxygen::tagFile << "library";
1988     if (VhdlDocGen::isPackage(mdef))      Doxygen::tagFile << "package";
1989     if (VhdlDocGen::isVariable(mdef))     Doxygen::tagFile << "shared variable";
1990     if (VhdlDocGen::isFile(mdef))         Doxygen::tagFile << "file";
1991     if (VhdlDocGen::isGroup(mdef))        Doxygen::tagFile << "group";
1992     if (VhdlDocGen::isCompInst(mdef))     Doxygen::tagFile << " instantiation";
1993     if (VhdlDocGen::isAlias(mdef))        Doxygen::tagFile << "alias";
1994     if (VhdlDocGen::isCompInst(mdef))     Doxygen::tagFile << "configuration";
1995
1996     Doxygen::tagFile << "\">" << endl;
1997     Doxygen::tagFile << "      <type>" << convertToXML(mdef->typeString()) << "</type>" << endl;
1998     Doxygen::tagFile << "      <name>" << convertToXML(mdef->name()) << "</name>" << endl;
1999     Doxygen::tagFile << "      <anchorfile>" << convertToXML(mdef->getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
2000     Doxygen::tagFile << "      <anchor>" << convertToXML(mdef->anchor()) << "</anchor>" << endl;
2001
2002     if (VhdlDocGen::isVhdlFunction(mdef))
2003       Doxygen::tagFile << "      <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),TRUE)) << "</arglist>" << endl;
2004     else if (VhdlDocGen::isProcedure(mdef))
2005       Doxygen::tagFile << "      <arglist>" << convertToXML(VhdlDocGen::convertArgumentListToString(mdef->argumentList(),FALSE)) << "</arglist>" << endl;
2006     else
2007       Doxygen::tagFile << "      <arglist>" << convertToXML(mdef->argsString()) << "</arglist>" << endl;
2008
2009     mdef->writeDocAnchorsToTagFile();
2010     Doxygen::tagFile << "    </member>" << endl;
2011
2012   }
2013
2014   // write search index info
2015   if (Doxygen::searchIndex)
2016   {
2017     Doxygen::searchIndex->setCurrentDoc(mdef,mdef->anchor(),FALSE);
2018     Doxygen::searchIndex->addWord(mdef->localName(),TRUE);
2019     Doxygen::searchIndex->addWord(mdef->qualifiedName(),FALSE);
2020   }
2021
2022   QCString cname  = d->name();
2023   QCString cfname = d->getOutputFileBase();
2024
2025   //HtmlHelp *htmlHelp=0;
2026   //  bool hasHtmlHelp = Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP");
2027   //  if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
2028
2029   // search for the last anonymous scope in the member type
2030   ClassDef *annoClassDef=mdef->getClassDefOfAnonymousType();
2031
2032   // start a new member declaration
2033   uint isAnonymous = (bool)(annoClassDef); // || m_impl->annMemb || m_impl->annEnumType;
2034   ///printf("startMemberItem for %s\n",name().data());
2035   int mm=mdef->getMemberSpecifiers();
2036   if (mm==VhdlDocGen::MISCELLANEOUS)
2037       isAnonymous=3;
2038
2039    ol.startMemberItem( mdef->anchor(), isAnonymous ); //? 1 : m_impl->tArgList ? 3 : 0);
2040
2041   // If there is no detailed description we need to write the anchor here.
2042   bool detailsVisible = mdef->isDetailedSectionLinkable();
2043   if (!detailsVisible) // && !m_impl->annMemb)
2044   {
2045     QCString doxyName=mdef->name().copy();
2046     if (!cname.isEmpty()) doxyName.prepend(cname+"::");
2047     QCString doxyArgs=mdef->argsString();
2048     ol.startDoxyAnchor(cfname,cname,mdef->anchor(),doxyName,doxyArgs);
2049
2050     ol.pushGeneratorState();
2051     ol.disable(OutputGenerator::Man);
2052     ol.disable(OutputGenerator::Latex);
2053     ol.docify("\n");
2054     ol.popGeneratorState();
2055
2056   }
2057   // *** write type
2058   /*VHDL CHANGE */
2059   bool bRec,bUnit;
2060   QCString ltype(mdef->typeString());
2061  // ltype=ltype.replace(reg," ");
2062   QCString largs(mdef->argsString());
2063  // largs=largs.replace(reg," ");
2064   mdef->setType(ltype.data());
2065   mdef->setArgsString(largs.data());
2066   //ClassDef * plo=mdef->getClassDef();
2067   ClassDef *kl=0;
2068   ArgumentList *alp = mdef->argumentList();
2069   QCString nn;
2070   //VhdlDocGen::adjustRecordMember(mdef);
2071   if (gd) gd=0;
2072   switch (mm)
2073   {
2074     case VhdlDocGen::MISCELLANEOUS:
2075       VhdlDocGen::writeSource(mdef,ol,nn);
2076       break;
2077     case VhdlDocGen::PROCEDURE:
2078     case VhdlDocGen::FUNCTION:
2079       ol.startBold();
2080       VhdlDocGen::formatString(ltype,ol,mdef);
2081       ol.endBold();
2082       ol.insertMemberAlign();
2083       ol.docify(" ");
2084
2085       writeLink(mdef,ol);
2086       if (alp!=0 && mm==VhdlDocGen::FUNCTION)
2087         VhdlDocGen::writeFunctionProto(ol,alp,mdef);
2088
2089       if (alp!=0 && mm==VhdlDocGen::PROCEDURE)
2090         VhdlDocGen::writeProcedureProto(ol,alp,mdef);
2091
2092       break;
2093     case VhdlDocGen::USE:
2094       kl=VhdlDocGen::getClass(mdef->name());
2095       if (kl && ((VhdlDocGen::VhdlClasses)kl->protection()==VhdlDocGen::ENTITYCLASS)) break;
2096       writeLink(mdef,ol);
2097       ol.insertMemberAlign();
2098       ol.docify("  ");
2099
2100       if (kl)
2101       {
2102         nn=kl->getOutputFileBase();
2103         ol.pushGeneratorState();
2104         ol.disableAllBut(OutputGenerator::Html);
2105         ol.docify(" ");
2106         QCString name=theTranslator_vhdlType(VhdlDocGen::PACKAGE,TRUE);
2107         ol.startBold();
2108         ol.docify(name.data());
2109         name.resize(0);
2110         ol.endBold();
2111         name+=" <"+mdef->name()+">";
2112         ol.startEmphasis();
2113         ol.writeObjectLink(kl->getReference(),kl->getOutputFileBase(),0,name.data());
2114         ol.popGeneratorState();
2115       }
2116       break;
2117     case VhdlDocGen::LIBRARY:
2118       writeLink(mdef,ol);
2119       ol.insertMemberAlign();
2120       if (largs=="context")
2121       {
2122         VhdlDocGen::writeRecorUnit(ltype,ol,mdef);
2123       }
2124
2125       break;
2126
2127     case VhdlDocGen::GENERIC:
2128     case VhdlDocGen::PORT:
2129     case VhdlDocGen::ALIAS:
2130
2131       writeLink(mdef,ol);
2132       ol.docify(" ");
2133       ol.insertMemberAlign();
2134       if (mm==VhdlDocGen::GENERIC)
2135       {
2136         ol.startBold();
2137         VhdlDocGen::formatString(largs,ol,mdef);
2138         ol.endBold();
2139       }
2140       else
2141       {
2142         ol.docify(" ");
2143         ol.startBold();
2144         VhdlDocGen::formatString(ltype,ol,mdef);
2145         ol.endBold();
2146         ol.docify(" ");
2147         VhdlDocGen::formatString(largs,ol,mdef);
2148       }
2149       break;
2150     case VhdlDocGen::PROCESS:
2151       writeLink(mdef,ol);
2152       ol.insertMemberAlign();
2153       VhdlDocGen::writeProcessProto(ol,alp,mdef);
2154       break;
2155     case VhdlDocGen::PACKAGE:
2156     case VhdlDocGen::ENTITY:
2157     case VhdlDocGen::COMPONENT:
2158     case VhdlDocGen::INSTANTIATION:
2159     case VhdlDocGen::CONFIG:
2160       if (VhdlDocGen::isCompInst(mdef) )
2161       {
2162         nn=largs;
2163         if(nn.stripPrefix("function") || nn.stripPrefix("package"))
2164         {
2165           VhdlDocGen::formatString(largs,ol,mdef);
2166           ol.insertMemberAlign();
2167           writeLink(mdef,ol);
2168           ol.docify(" ");
2169           VhdlDocGen::formatString(ltype,ol,mdef);
2170           break;
2171         }
2172
2173         largs.prepend("::");
2174         largs.prepend(mdef->name().data());
2175         ol.writeObjectLink(mdef->getReference(),
2176             cfname,
2177             mdef->anchor(),
2178             mdef->name());
2179       }
2180       else
2181         writeLink(mdef,ol);
2182
2183       ol.insertMemberAlign();
2184       ol.docify("  ");
2185
2186       ol.startBold();
2187       ol.docify(ltype);
2188       ol.endBold();
2189       ol.docify("  ");
2190       if (VhdlDocGen::isComponent(mdef) ||
2191           VhdlDocGen::isConfig(mdef)    ||
2192           VhdlDocGen::isCompInst(mdef))
2193       {
2194         if (VhdlDocGen::isConfig(mdef) || VhdlDocGen::isCompInst(mdef))
2195         {
2196           nn=mdef->getOutputFileBase();
2197           nn=ltype;
2198         }
2199         else
2200         {
2201           nn=mdef->name();
2202         }
2203         kl=getClass(nn.data());
2204         if (kl)
2205         {
2206           nn=kl->getOutputFileBase();
2207           ol.pushGeneratorState();
2208           ol.disableAllBut(OutputGenerator::Html);
2209           ol.startEmphasis();
2210           QCString name("<Entity ");
2211           if (VhdlDocGen::isConfig(mdef) || VhdlDocGen::isCompInst(mdef))
2212           {
2213             name+=ltype+">";
2214           }
2215           else
2216           {
2217             name+=mdef->name()+"> ";
2218           }
2219           ol.writeObjectLink(kl->getReference(),kl->getOutputFileBase(),0,name.data());
2220           ol.endEmphasis();
2221           ol.popGeneratorState();
2222         }
2223       }
2224       break;
2225     case VhdlDocGen::UCF_CONST:
2226       mm=mdef->name().findRev('_');
2227       if (mm>0)
2228       {
2229         mdef->setName(mdef->name().left(mm));
2230       }
2231       writeUCFLink(mdef,ol);
2232       break;
2233     case VhdlDocGen::SIGNAL:
2234     case VhdlDocGen::ATTRIBUTE:
2235     case VhdlDocGen::SUBTYPE:
2236     case VhdlDocGen::CONSTANT:
2237     case VhdlDocGen::SHAREDVARIABLE:
2238     case VhdlDocGen::VFILE:
2239     case VhdlDocGen::GROUP:
2240       writeLink(mdef,ol);
2241       ol.docify(" ");
2242       ol.insertMemberAlign();
2243       VhdlDocGen::formatString(ltype,ol,mdef);
2244       break;
2245     case VhdlDocGen::TYPE:
2246       bRec=largs.stripPrefix("record") ;
2247       bUnit=largs.stripPrefix("units") ;
2248       ol.startBold();
2249       if (bRec)  ol.docify("record: ");
2250       if (bUnit) ol.docify("units: ");
2251       writeLink(mdef,ol);
2252       ol.insertMemberAlign();
2253       if (!bRec && !bUnit) VhdlDocGen::formatString(ltype,ol,mdef);
2254       if (bUnit) ol.lineBreak();
2255       if (bRec || bUnit)
2256       {
2257         writeRecorUnit(largs,ol,mdef);
2258         mdef->setType("");
2259       }
2260       ol.endBold();
2261       break;
2262
2263     default: break;
2264   }
2265
2266   bool htmlOn = ol.isEnabled(OutputGenerator::Html);
2267   if (htmlOn && /*Config_getBool("HTML_ALIGN_MEMBERS") &&*/ !ltype.isEmpty())
2268   {
2269     ol.disable(OutputGenerator::Html);
2270   }
2271   if (!ltype.isEmpty()) ol.docify(" ");
2272
2273   if (htmlOn)
2274   {
2275     ol.enable(OutputGenerator::Html);
2276   }
2277
2278   if (!detailsVisible)// && !m_impl->annMemb)
2279   {
2280     ol.endDoxyAnchor(cfname,mdef->anchor());
2281   }
2282
2283   //    name().data(),annoClassDef,annEnumType);
2284  // if(mm!=VhdlDocGen::MISCELLANEOUS)
2285   ol.endMemberItem();
2286   if (!mdef->briefDescription().isEmpty() &&   Config_getBool("BRIEF_MEMBER_DESC") /* && !annMemb */)
2287   {
2288     ol.startMemberDescription(mdef->anchor());
2289     ol.generateDoc(mdef->briefFile(),mdef->briefLine(),
2290         mdef->getOuterScope()?mdef->getOuterScope():d,
2291         mdef,mdef->briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
2292     if (detailsVisible)
2293     {
2294       ol.pushGeneratorState();
2295       ol.disableAllBut(OutputGenerator::Html);
2296       //ol.endEmphasis();
2297       ol.docify(" ");
2298       if (mdef->getGroupDef()!=0 && gd==0) // forward link to the group
2299       {
2300         ol.startTextLink(mdef->getOutputFileBase(),mdef->anchor());
2301       }
2302       else // local link
2303       {
2304         ol.startTextLink(0,mdef->anchor());
2305       }
2306       ol.endTextLink();
2307       //ol.startEmphasis();
2308       ol.popGeneratorState();
2309     }
2310     //ol.newParagraph();
2311     ol.endMemberDescription();
2312   }
2313   mdef->warnIfUndocumented();
2314
2315 }// end writeVhdlDeclaration
2316
2317
2318 void VhdlDocGen::writePlainVHDLDeclarations(
2319     MemberList* mlist,OutputList &ol,
2320     ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier)
2321 {
2322
2323   SDict<QCString> pack(1009);
2324
2325   bool first=TRUE;
2326   MemberDef *md;
2327   MemberListIterator mli(*mlist);
2328   for ( ; (md=mli.current()); ++mli )
2329   {
2330     int mems=md->getMemberSpecifiers();
2331     if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) )
2332     {
2333       if (first) { ol.startMemberList();first=FALSE; }
2334       VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE);
2335     } //if
2336     else if (md->isBriefSectionVisible() && (mems==specifier))
2337     {
2338       if (!pack.find(md->name().data()))
2339       {
2340         if (first) ol.startMemberList(),first=FALSE;
2341         VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE);
2342         pack.append(md->name().data(),new QCString(md->name().data()));
2343       }
2344     } //if
2345   } //for
2346   if (!first) ol.endMemberList();
2347   pack.clear();
2348 }//plainDeclaration
2349
2350 static bool membersHaveSpecificType(MemberList *ml,uint64 type)
2351 {
2352   if (ml==0) return FALSE;
2353   MemberDef *mdd=0;
2354   MemberListIterator mmli(*ml);
2355   for ( ; (mdd=mmli.current()); ++mmli )
2356   {
2357     if (mdd->getMemberSpecifiers()==type) //is type in class
2358     {
2359       return TRUE;
2360     }
2361   }
2362   if (ml->getMemberGroupList())
2363   {
2364     MemberGroupListIterator mgli(*ml->getMemberGroupList());
2365     MemberGroup *mg;
2366     while ((mg=mgli.current()))
2367     {
2368       if (mg->members())
2369       {
2370         if (membersHaveSpecificType(mg->members(),type)) return TRUE;
2371       }
2372       ++mgli;
2373     }
2374   }
2375   return FALSE;
2376 }
2377
2378 void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol,
2379     ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
2380     const char *title,const char *subtitle,bool /*showEnumValues*/,int type)
2381 {
2382   setGlobalType(ml);
2383   if (!membersHaveSpecificType(ml,type)) return;
2384
2385   if (title)
2386   {
2387     ol.startMemberHeader(title);
2388     ol.parseText(title);
2389     ol.endMemberHeader();
2390     ol.docify(" ");
2391   }
2392   if (subtitle && subtitle[0]!=0)
2393   {
2394     ol.startMemberSubtitle();
2395     ol.generateDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE,0,TRUE,FALSE);
2396     ol.endMemberSubtitle();
2397   } //printf("memberGroupList=%p\n",memberGroupList);
2398
2399   VhdlDocGen::writePlainVHDLDeclarations(ml,ol,cd,nd,fd,gd,type);
2400
2401   if (ml->getMemberGroupList())
2402   {
2403     MemberGroupListIterator mgli(*ml->getMemberGroupList());
2404     MemberGroup *mg;
2405     while ((mg=mgli.current()))
2406     {
2407       if (membersHaveSpecificType(mg->members(),type))
2408       {
2409         //printf("mg->header=%s\n",mg->header().data());
2410         bool hasHeader=mg->header()!="[NOHEADER]";
2411         ol.startMemberGroupHeader(hasHeader);
2412         if (hasHeader)
2413         {
2414           ol.parseText(mg->header());
2415         }
2416         ol.endMemberGroupHeader();
2417         if (!mg->documentation().isEmpty())
2418         {
2419           //printf("Member group has docs!\n");
2420           ol.startMemberGroupDocs();
2421           ol.generateDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE);
2422           ol.endMemberGroupDocs();
2423         }
2424         ol.startMemberGroup();
2425         //printf("--- mg->writePlainDeclarations ---\n");
2426         VhdlDocGen::writePlainVHDLDeclarations(mg->members(),ol,cd,nd,fd,gd,type);
2427         ol.endMemberGroup(hasHeader);
2428       }
2429       ++mgli;
2430     }
2431   }
2432 }// writeVHDLDeclarations
2433
2434
2435 bool VhdlDocGen::writeClassType( ClassDef *& cd,
2436     OutputList &ol ,QCString & cname)
2437 {
2438   int id=cd->protection();
2439   QCString qcs = VhdlDocGen::trTypeString(id+2);
2440   cname=VhdlDocGen::getClassName(cd);
2441   ol.startBold();
2442   ol.writeString(qcs.data());
2443   ol.writeString(" ");
2444   ol.endBold();
2445   //ol.insertMemberAlign();
2446   return FALSE;
2447 }// writeClassLink
2448
2449 QCString VhdlDocGen::trVhdlType(uint64 type,bool sing)
2450 {
2451   switch(type)
2452   {
2453     case VhdlDocGen::LIBRARY:
2454       if (sing) return "Library";
2455       else      return "Libraries";
2456     case VhdlDocGen::PACKAGE:
2457       if (sing) return "Package";
2458       else      return "Packages";
2459     case VhdlDocGen::SIGNAL:
2460       if (sing) return "Signal";
2461       else      return "Signals";
2462     case VhdlDocGen::COMPONENT:
2463       if (sing) return "Component";
2464       else      return "Components";
2465     case VhdlDocGen::CONSTANT:
2466       if (sing) return "Constant";
2467       else      return "Constants";
2468     case VhdlDocGen::ENTITY:
2469       if (sing) return "Entity";
2470       else      return "Entities";
2471     case VhdlDocGen::TYPE:
2472       if (sing) return "Type";
2473       else      return "Types";
2474     case VhdlDocGen::SUBTYPE:
2475       if (sing) return "Subtype";
2476       else      return "Subtypes";
2477     case VhdlDocGen::FUNCTION:
2478       if (sing) return "Function";
2479       else      return "Functions";
2480     case VhdlDocGen::RECORD:
2481       if (sing) return "Record";
2482       else      return "Records";
2483     case VhdlDocGen::PROCEDURE:
2484       if (sing) return "Procedure";
2485       else      return "Procedures";
2486     case VhdlDocGen::ARCHITECTURE:
2487       if (sing) return "Architecture";
2488       else      return "Architectures";
2489     case VhdlDocGen::ATTRIBUTE:
2490       if (sing) return "Attribute";
2491       else      return "Attributes";
2492     case VhdlDocGen::PROCESS:
2493       if (sing) return "Process";
2494       else      return "Processes";
2495     case VhdlDocGen::PORT:
2496       if (sing) return "Port";
2497       else      return "Ports";
2498     case VhdlDocGen::USE:
2499       if (sing) return "use clause";
2500       else      return "Use Clauses";
2501     case VhdlDocGen::GENERIC:
2502       if (sing) return "Generic";
2503       else      return "Generics";
2504     case VhdlDocGen::PACKAGE_BODY:
2505       return "Package Body";
2506     case VhdlDocGen::UNITS:
2507       return "Units";
2508     case VhdlDocGen::SHAREDVARIABLE:
2509       if (sing) return "Shared Variable";
2510       return "Shared Variables";
2511     case VhdlDocGen::VFILE:
2512       if (sing) return "File";
2513       return "Files";
2514     case VhdlDocGen::GROUP:
2515       if (sing) return "Group";
2516       return "Groups";
2517     case VhdlDocGen::INSTANTIATION:
2518       if (sing) return "Instantiation";
2519       else      return "Instantiations";
2520     case VhdlDocGen::ALIAS:
2521       if (sing) return "Alias";
2522       return "Aliases";
2523     case VhdlDocGen::CONFIG:
2524       if (sing) return "Configuration";
2525       return "Configurations";
2526     case VhdlDocGen::MISCELLANEOUS:
2527       return "Miscellaneous";
2528     case VhdlDocGen::UCF_CONST:
2529       return "Constraints";
2530     default:
2531       return "Class";
2532   }
2533 }
2534
2535 QCString VhdlDocGen::trDesignUnitHierarchy()
2536 {
2537   return "Design Unit Hierarchy";
2538 }
2539
2540 QCString VhdlDocGen::trDesignUnitList()
2541 {
2542   return "Design Unit List";
2543 }
2544
2545 QCString VhdlDocGen::trDesignUnitMembers()
2546 {
2547   return "Design Unit Members";
2548 }
2549
2550 QCString VhdlDocGen::trDesignUnitListDescription()
2551 {
2552   return "Here is a list of all design unit members with links to "
2553     "the Entities  they belong to:";
2554 }
2555
2556 QCString VhdlDocGen::trDesignUnitIndex()
2557 {
2558   return "Design Unit Index";
2559 }
2560
2561 QCString VhdlDocGen::trDesignUnits()
2562 {
2563   return "Design Units";
2564 }
2565
2566 QCString VhdlDocGen::trFunctionAndProc()
2567 {
2568   return "Functions/Procedures/Processes";
2569 }
2570
2571
2572 /*! writes a link if the string is linkable else a formatted string */
2573
2574 void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& ol)
2575 {
2576   if (mdef)
2577   {
2578     ClassDef *cd=mdef->getClassDef();
2579     if (cd)
2580     {
2581       QCString n=cd->name();
2582       MemberDef* memdef=VhdlDocGen::findMember(n,mem);
2583       if (memdef && memdef->isLinkable())
2584       {
2585         ol.startBold();
2586         writeLink(memdef,ol);
2587         ol.endBold();
2588         ol.docify(" ");
2589         return;
2590       }
2591     }
2592   }
2593   startFonts(mem,"vhdlchar",ol);
2594 }// found component
2595
2596
2597
2598 void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname)
2599 {
2600   ParserInterface *pIntf = Doxygen::parserManager->getParser(".vhd");
2601  // pIntf->resetCodeParserState();
2602
2603   QCString codeFragment=mdef->documentation();
2604
2605   if (cname.isEmpty())
2606   {
2607     writeLink(mdef,ol);
2608     int fi=0;
2609     int j=0;
2610     do
2611     {
2612      fi=codeFragment.find("\n",++fi);
2613     } while(fi>=0 && j++ <3);
2614
2615     // show only the first four lines
2616     if (j==4)
2617     {
2618       codeFragment=codeFragment.left(fi);
2619       codeFragment.append("\n    ....    ");
2620     }
2621   }
2622
2623   codeFragment.prepend("\n");
2624   ol.pushGeneratorState();
2625   ol.startCodeFragment();
2626   pIntf->parseCode(ol,                   // codeOutIntf
2627                        0,                // scope
2628                        codeFragment,     // input
2629                        SrcLangExt_VHDL,  // lang
2630                        FALSE,            // isExample
2631                        0,                // exampleName
2632                        mdef->getFileDef(),            // fileDef
2633                        mdef->getStartBodyLine(),      // startLine
2634                        mdef->getEndBodyLine(),        // endLine
2635                        TRUE,             // inlineFragment
2636                        mdef,             // memberDef
2637                        TRUE              // show line numbers
2638                       );
2639
2640   ol.endCodeFragment();
2641   ol.popGeneratorState();
2642
2643   if (cname.isEmpty()) return;
2644
2645   mdef->writeSourceDef(ol,cname);
2646   mdef->writeSourceRefs(ol,cname);
2647   mdef->writeSourceReffedBy(ol,cname);
2648 }
2649
2650
2651
2652 QCString VhdlDocGen::convertFileNameToClassName(QCString name)
2653 {
2654
2655   QCString n=name;
2656   n=n.remove(0,6);
2657
2658   int i=0;
2659
2660   while((i=n.find("__"))>0)
2661   {
2662     n=n.remove(i,1);
2663   }
2664
2665   while((i=n.find("_1"))>0)
2666   {
2667     n=n.replace(i,2,":");
2668   }
2669
2670   return n;
2671 }
2672
2673 void VhdlDocGen::parseUCF(const char*  input,  Entry* entity,QCString fileName,bool altera)
2674 {
2675   QCString ucFile(input);
2676   int lineNo=0;
2677   QCString newLine="\n";
2678   QCString comment("#!");
2679   QCString brief;
2680
2681   while (!ucFile.isEmpty())
2682   {
2683     int i=ucFile.find("\n");
2684     if (i<0) break;
2685     lineNo++;
2686     QCString temp=ucFile.left(i);
2687     temp=temp.stripWhiteSpace();
2688     bool bb=temp.stripPrefix("//");
2689
2690     if (!temp.isEmpty())
2691     {
2692       if (temp.stripPrefix(comment) )
2693       {
2694         brief+=temp;
2695         brief.append("\\n");
2696       }
2697       else if (!temp.stripPrefix("#") && !bb)
2698       {
2699         if (altera)
2700         {
2701           int i=temp.find("-name");
2702           if (i>0)
2703           {
2704             temp=temp.remove(0,i+5);
2705           }
2706
2707           temp.stripPrefix("set_location_assignment");
2708
2709           initUCF(entity,0,temp,lineNo,fileName,brief);
2710         }
2711         else
2712         {
2713           QRegExp ee("[\\s=]");
2714           int i=temp.find(ee);
2715           QCString ff=temp.left(i);
2716           temp.stripPrefix(ff.data());
2717           ff.append("#");
2718           if (!temp.isEmpty())
2719           {
2720             initUCF(entity,ff.data(),temp,lineNo,fileName,brief);
2721           }
2722         }
2723       }
2724     }//temp
2725
2726     ucFile=ucFile.remove(0,i+1);
2727   }// while
2728 }
2729
2730 static void initUCF(Entry* root,const char*  type,QCString &  qcs,int line,QCString & fileName,QCString & brief)
2731 {
2732   if (qcs.isEmpty())return;
2733   QRegExp sp("\\s");
2734   QRegExp reg("[\\s=]");
2735   QCString n;
2736   // bool bo=(qstricmp(type,qcs.data())==0);
2737
2738   VhdlDocGen::deleteAllChars(qcs,';');
2739   qcs=qcs.stripWhiteSpace();
2740
2741   int i= qcs.find(reg);
2742   if (i<0) return;
2743   if (i==0)
2744   {
2745     n=type;
2746     VhdlDocGen::deleteAllChars(n,'#');
2747     type="";
2748   }
2749   else
2750   {
2751     n=qcs.left(i);
2752   }
2753   qcs=qcs.remove(0,i+1);
2754   //  qcs.prepend("|");
2755
2756   qcs.stripPrefix("=");
2757
2758   Entry* current=new Entry;
2759   current->spec=VhdlDocGen::UCF_CONST;
2760   current->section=Entry::VARIABLE_SEC;
2761   current->bodyLine=line;
2762   current->fileName=fileName;
2763   current->type="ucf_const";
2764   current->args+=qcs;
2765   current->lang=  SrcLangExt_VHDL ;
2766
2767   // adding dummy name for constraints like VOLTAGE=5,TEMPERATURE=20 C
2768   if (n.isEmpty())
2769   {
2770     n="dummy";
2771     n+=VhdlDocGen::getRecordNumber();
2772   }
2773
2774   current->name= n+"_";
2775   current->name.append(VhdlDocGen::getRecordNumber().data());
2776
2777   if (!brief.isEmpty())
2778   {
2779     current->brief=brief;
2780     current->briefLine=line;
2781     current->briefFile=fileName;
2782     brief.resize(0);
2783   }
2784
2785   root->addSubEntry(current);
2786 }
2787
2788
2789 static void writeUCFLink(const MemberDef* mdef,OutputList &ol)
2790 {
2791
2792   QCString largs(mdef->argsString());
2793   QCString n= splitString(largs, '#');
2794   // VhdlDocGen::adjustRecordMember(mdef);
2795   bool equ=(n.length()==largs.length());
2796
2797   if (!equ)
2798   {
2799     ol.writeString(n.data());
2800     ol.docify(" ");
2801     ol.insertMemberAlign();
2802   }
2803
2804   if (mdef->name().contains("dummy")==0)
2805   {
2806     writeLink(mdef,ol);
2807   }
2808   if (equ)
2809   {
2810     ol.insertMemberAlign();
2811   }
2812   ol.docify(" ");
2813   VhdlDocGen::formatString(largs,ol,mdef);
2814 }
2815
2816 bool VhdlDocGen::findConstraintFile(LayoutNavEntry *lne)
2817 {
2818   FileName *fn=Doxygen::inputNameList->getFirst();
2819   //LayoutNavEntry *cc = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files);
2820   uint count=Doxygen::inputNameList->count();
2821   LayoutNavEntry *kk = lne->parent();//   find(LayoutNavEntry::Files);
2822   // LayoutNavEntry *kks = kk->parent();//   find(LayoutNavEntry::Files);
2823   QCString file;
2824   QCString co("Constraints");
2825
2826   if (Config_getBool("HAVE_DOT") && Config_getEnum("DOT_IMAGE_FORMAT")=="svg")
2827   {
2828     QCString ov = theTranslator->trDesignOverview();
2829     QCString ofile("vhdl_design_overview");
2830     LayoutNavEntry *oo=new LayoutNavEntry( lne,LayoutNavEntry::MainPage,TRUE,ofile,ov,"");
2831     kk->addChild(oo);
2832   }
2833
2834   uint i=0;
2835   while (i<count)
2836   {
2837         FileDef *fd=fn->at(i);
2838     if (fd->name().contains(".ucf") || fd->name().contains(".qsf"))
2839     {
2840       file = convertNameToFile(fd->name().data(),FALSE,FALSE);
2841       LayoutNavEntry *ucf=new LayoutNavEntry(lne,LayoutNavEntry::MainPage,TRUE,file,co,"");
2842       kk->addChild(ucf);
2843       break;
2844     }
2845    i++;
2846   }
2847   return  FALSE;
2848 }
2849
2850
2851 //        for cell_inst : [entity] work.proto [ (label|expr) ]
2852 QCString  VhdlDocGen::parseForConfig(QCString & entity,QCString & arch)
2853 {
2854   int index;
2855   QCString label;
2856   QCString ent("entity");
2857   if (!entity.contains(":")) return "";
2858
2859   QRegExp exp("[:()\\s]");
2860   QStringList ql=QStringList::split(exp,entity,FALSE);
2861   //int ii=ql.findIndex(ent);
2862   assert(ql.count()>=2);
2863   label = ql[0].utf8();
2864   entity = ql[1].utf8();
2865   if ((index=entity.findRev("."))>=0)
2866   {
2867     entity.remove(0,index+1);
2868   }
2869
2870   if (ql.count()==3)
2871   {
2872     arch= ql[2].utf8();
2873     ql=QStringList::split(exp,arch,FALSE);
2874     if (ql.count()>1) // expression
2875     {
2876       arch="";
2877     }
2878   }
2879   return label; // label
2880 }
2881
2882 //        use (configuration|entity|open) work.test [(cellfor)];
2883
2884 QCString  VhdlDocGen::parseForBinding(QCString & entity,QCString & arch)
2885 {
2886   int index;
2887   QRegExp exp("[()\\s]");
2888
2889   QCString label="";
2890   QStringList ql=QStringList::split(exp,entity,FALSE);
2891
2892   if (ql.contains("open"))
2893   {
2894     return "open";
2895   }
2896
2897   label=ql[0].utf8();
2898
2899   entity = ql[1].utf8();
2900   if ((index=entity.findRev("."))>=0)
2901   {
2902     entity.remove(0,index+1);
2903   }
2904
2905   if (ql.count()==3)
2906   {
2907     arch=ql[2].utf8();
2908   }
2909   return label;
2910 }
2911
2912
2913
2914  // find class with upper/lower letters
2915  ClassDef* VhdlDocGen::findVhdlClass(const char *className )
2916  {
2917
2918   ClassSDict::Iterator cli(*Doxygen::classSDict);
2919   ClassDef *cd;
2920   for (;(cd=cli.current());++cli)
2921   {
2922     if (qstricmp(className,cd->name().data())==0)
2923     {
2924       return cd;
2925     }
2926   }
2927   return 0;
2928  }
2929
2930
2931 //@param arch bit0:flipflop
2932 //@param binding  e.g entity work.foo(bar)
2933 //@param label  |label0|label1
2934 //                          label0:architecture name
2935 //@param confVhdl of configuration file (identifier::entity_name) or
2936 //               the architecture if isInlineConf TRUE
2937 //@param isInlineConf
2938 //@param confN List of configurations
2939
2940 void assignBinding(VhdlConfNode * conf)
2941 {
2942   QList<Entry> instList=getVhdlInstList();
2943   QListIterator<Entry> eli(instList);
2944   Entry *cur=0;
2945   ClassDef *archClass=0,*entClass=0;
2946   QCString archName,entityName;
2947   QCString arcBind,entBind;
2948
2949   bool others,all;
2950   entBind=conf->binding;
2951   QCString conf2=VhdlDocGen::parseForBinding(entBind,arcBind);
2952
2953   if (qstricmp(conf2,"configuration")==0)
2954   {
2955     QList<VhdlConfNode> confList =  getVhdlConfiguration();
2956     VhdlConfNode* vconf;
2957     //  bool found=false;
2958     for (uint iter=0;iter<confList.count(); iter++)
2959     {
2960       vconf= (VhdlConfNode *)confList.at(iter);
2961       QCString n=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),0);
2962       if (n==entBind)
2963       {
2964         // found=true;
2965         entBind=VhdlDocGen::getIndexWord(vconf->confVhdl.data(),1);
2966         QCString a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0);
2967         QCString e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1);
2968         a=e+"::"+a;
2969         archClass= VhdlDocGen::findVhdlClass(a.data());//Doxygen::classSDict->find(a.data());
2970         entClass= VhdlDocGen::findVhdlClass(e.data());//Doxygen::classSDict->find(e.data());
2971         break;
2972       }
2973     }
2974   }
2975   else  // conf2!=configuration
2976   {
2977     QCString a,c,e;
2978     if (conf->isInlineConf)
2979     {
2980       c=conf->confVhdl;
2981       e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),0);
2982     }
2983     else
2984     {
2985       a=VhdlDocGen::getIndexWord(conf->compSpec.data(),0);
2986       e=VhdlDocGen::getIndexWord(conf->confVhdl.data(),1);
2987       c=e+"::"+a;
2988     }
2989     archClass= VhdlDocGen::findVhdlClass(c.data());//Doxygen::classSDict->find(a.data());
2990     entClass= VhdlDocGen::findVhdlClass(e.data()); //Doxygen::classSDict->find(e.data());
2991   }
2992
2993   QCString label=conf->compSpec.lower();
2994   //label.prepend("|");
2995
2996   if (!archClass)
2997   {
2998  //   err("architecture %s not found ! ",conf->confVhdl.data());
2999     return;
3000   }
3001
3002   archName=archClass->name();
3003   QCString allOt=VhdlDocGen::getIndexWord(conf->arch.data(),0);
3004   all=allOt.lower()=="all" ;
3005   others= allOt.lower()=="others";
3006
3007   for (;(cur=eli.current());++eli)
3008   {
3009     if (cur->exception.lower()==label || conf->isInlineConf)
3010     {
3011       QCString sign,archy;
3012
3013       if (all || others)
3014       {
3015         archy=VhdlDocGen::getIndexWord(conf->arch.data(),1);
3016       }
3017       else
3018       {
3019         archy=conf->arch;
3020       }
3021
3022       QCString    inst1=VhdlDocGen::getIndexWord(archy.data(),0).lower();
3023       QCString    comp=VhdlDocGen::getIndexWord(archy.data(),1).lower();
3024
3025       QStringList ql=QStringList::split(",",inst1);
3026
3027       for (uint j=0;j<ql.count();j++)
3028       {
3029         QCString archy1,sign1;
3030         if (all || others)
3031         {
3032           archy1=VhdlDocGen::getIndexWord(conf->arch.data(),1);
3033           sign1=cur->type;
3034         }
3035         else
3036         {
3037           archy1=comp+":"+ql[j].utf8();
3038           sign1=cur->type+":"+cur->name;
3039         }
3040
3041         if (archy1==sign1.lower() && !cur->stat)
3042         {
3043           // fprintf(stderr," \n label [%s] [%s] [%s]",cur->exception.data(),cur->type.data(),cur->name.data());
3044           ClassDef *ent= VhdlDocGen::findVhdlClass(entBind.data());//Doxygen::classSDict->find(entBind.data());
3045
3046           if (entClass==0 || ent==0)
3047           {
3048             continue;
3049           }
3050
3051           addInstance(ent,archClass,entClass,cur);
3052           cur->stat=TRUE;
3053           break;
3054         }
3055       }// for
3056     }
3057   }//for each element in instList
3058
3059 }//assignBinding
3060
3061 /*
3062
3063 // file foo.vhd
3064 // enitity foo
3065 //        .....
3066 // end entity
3067
3068 // file foo_arch.vhd
3069 // architecture xxx of foo is
3070 //          ........
3071 //  end architecture
3072
3073 */
3074 void VhdlDocGen::computeVhdlComponentRelations()
3075 {
3076
3077   QCString entity,arch,inst;
3078   QList<VhdlConfNode> confList =  getVhdlConfiguration();
3079
3080   for (uint iter=0;iter<confList.count(); iter++)
3081   {
3082     VhdlConfNode* conf= (VhdlConfNode *)confList.at(iter);
3083     if (!(conf->isInlineConf || conf->isLeaf))
3084     {
3085       continue;
3086     }
3087     assignBinding(conf);
3088   }
3089
3090   QList<Entry> qsl= getVhdlInstList();
3091   QListIterator<Entry> eli(qsl);
3092   Entry *cur;
3093
3094   for (eli.toFirst();(cur=eli.current());++eli)
3095   {
3096     if (cur->stat ) //  was bind
3097     {
3098       continue;
3099     }
3100
3101     if (cur->includeName=="entity" || cur->includeName=="component" )
3102     {
3103       entity=cur->includeName+" "+cur->type;
3104       QCString rr=VhdlDocGen::parseForBinding(entity,arch);
3105     }
3106     else if (cur->includeName.isEmpty())
3107     {
3108       entity=cur->type;
3109     }
3110
3111     ClassDef *classEntity= VhdlDocGen::findVhdlClass(entity.data());//Doxygen::classSDict->find(entity);
3112     inst=VhdlDocGen::getIndexWord(cur->args.data(),0);
3113     ClassDef *cd=Doxygen::classSDict->find(inst);
3114     ClassDef *ar=Doxygen::classSDict->find(cur->args);
3115
3116     if (cd==0)
3117     {
3118       continue;
3119     }
3120
3121     // if (classEntity==0)
3122     //   err("%s:%d:Entity:%s%s",cur->fileName.data(),cur->startLine,entity.data()," could not be found");
3123
3124     addInstance(classEntity,ar,cd,cur);
3125   }
3126
3127 }
3128
3129 static void addInstance(ClassDef* classEntity, ClassDef* ar,
3130                         ClassDef *cd , Entry *cur,ClassDef* /*archBind*/)
3131 {
3132
3133   QCString bName,n1;
3134   if (ar==0) return;
3135
3136   if (classEntity==0)
3137   {
3138     //add component inst
3139     n1=cur->type;
3140     goto ferr;
3141   }
3142
3143   if (classEntity==cd) return;
3144
3145   bName=classEntity->name();
3146   // fprintf(stderr,"\naddInstance %s to %s %s %s\n", classEntity->name().data(),cd->name().data(),ar->name().data(),cur->name);
3147   n1=classEntity->name().data();
3148
3149   if (!cd->isBaseClass(classEntity, true, 0))
3150   {
3151     cd->insertBaseClass(classEntity,n1,Public,Normal,0);
3152   }
3153   else
3154   {
3155     VhdlDocGen::addBaseClass(cd,classEntity);
3156   }
3157
3158   if (!VhdlDocGen::isSubClass(classEntity,cd,true,0))
3159   {
3160     classEntity->insertSubClass(cd,Public,Normal,0);
3161     classEntity->setLanguage(SrcLangExt_VHDL);
3162   }
3163
3164 ferr:
3165   QCString uu=cur->name;
3166   MemberDef *md=new MemberDef(
3167       ar->getDefFileName(), cur->startLine,cur->startColumn,
3168       n1,uu,uu, 0,
3169       Public, Normal, cur->stat,Member,
3170       MemberType_Variable,
3171       0,
3172       0);
3173
3174   if (ar->getOutputFileBase())
3175   {
3176     TagInfo tg;
3177     tg.anchor = 0;
3178     tg.fileName = ar->getOutputFileBase();
3179     tg.tagName = 0;
3180     md->setTagInfo(&tg);
3181   }
3182
3183   //fprintf(stderr,"\n%s%s%s\n",md->name().data(),cur->brief.data(),cur->doc.data());
3184
3185   md->setLanguage(SrcLangExt_VHDL);
3186   md->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
3187   md->setBriefDescription(cur->brief,cur->briefFile,cur->briefLine);
3188   md->setBodySegment(cur->startLine,-1) ;
3189   md->setDocumentation(cur->doc.data(),cur->docFile.data(),cur->docLine);
3190   FileDef *fd=ar->getFileDef();
3191   md->setBodyDef(fd);
3192
3193
3194   QCString info="Info: Elaborating entity "+n1;
3195   fd=ar->getFileDef();
3196   info+=" for hierarchy ";
3197   QRegExp epr("[|]");
3198   QCString label=cur->type+":"+cur->write+":"+cur->name;
3199   label.replace(epr,":");
3200   info+=label;
3201   fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data());
3202
3203
3204   ar->insertMember(md);
3205
3206 }
3207
3208
3209 void  VhdlDocGen::writeRecorUnit(QCString & largs,OutputList& ol ,const MemberDef *mdef)
3210 {
3211   QStringList ql=QStringList::split("#",largs,FALSE);
3212   uint len=ql.count();
3213   for(uint i=0;i<len;i++)
3214   {
3215     QCString n=ql[i].utf8();
3216     VhdlDocGen::formatString(n,ol,mdef);
3217     if ((len-i)>1) ol.lineBreak();
3218   }
3219 }
3220
3221
3222 void VhdlDocGen::writeRecUnitDocu(
3223     const MemberDef *md,
3224     OutputList& ol,
3225     QCString largs)
3226 {
3227
3228   QStringList ql=QStringList::split("#",largs,FALSE);
3229   uint len=ql.count();
3230   ol.startParameterList(TRUE);
3231   bool first=TRUE;
3232
3233   for(uint i=0;i<len;i++)
3234   {
3235     QCString n=ql[i].utf8();
3236     ol.startParameterType(first,"");
3237     ol.endParameterType();
3238     ol.startParameterName(TRUE);
3239     VhdlDocGen::formatString(n,ol,md);
3240     if ((len-i)>1)
3241     {
3242       ol.endParameterName(FALSE,FALSE,FALSE);
3243     }
3244     else
3245     {
3246       ol.endParameterName(TRUE,FALSE,TRUE);
3247     }
3248
3249     first=FALSE;
3250   }
3251
3252 }//#
3253
3254
3255
3256 bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int level)
3257 {
3258   bool found=FALSE;
3259   //printf("isBaseClass(cd=%s) looking for %s\n",name().data(),bcd->name().data());
3260   if (level>255)
3261   {
3262     err("Possible recursive class relation while inside %s and looking for %s\n",qPrint(cd->name()),qPrint(scd->name()));
3263     abort();
3264     return FALSE;
3265   }
3266
3267   if (cd->subClasses())
3268   {
3269     BaseClassListIterator bcli(*cd->subClasses());
3270     for ( ; bcli.current() && !found ; ++bcli)
3271     {
3272       ClassDef *ccd=bcli.current()->classDef;
3273       if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
3274       //printf("isSubClass() subclass %s\n",ccd->name().data());
3275       if (ccd==scd)
3276       {
3277         found=TRUE;
3278       }
3279       else
3280       {
3281         if (level <256)
3282         {
3283           found=ccd->isBaseClass(scd,followInstances,level+1);
3284         }
3285       }
3286     }
3287   }
3288   return found;
3289 }
3290
3291 void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent)
3292 {
3293   if (cd->baseClasses())
3294   {
3295     BaseClassListIterator bcli(*cd->baseClasses());
3296     for ( ; bcli.current()  ; ++bcli)
3297     {
3298       ClassDef *ccd=bcli.current()->classDef;
3299       if (ccd==ent)
3300       {
3301         QCString n = bcli.current()->usedName;
3302         int i = n.find('(');
3303         if(i<0)
3304         {
3305           bcli.current()->usedName.append("(2)");
3306           return;
3307         }
3308         static QRegExp reg("[0-9]+");
3309         QCString s=n.left(i);
3310         QCString r=n.right(n.length()-i);
3311         QCString t=r;
3312         VhdlDocGen::deleteAllChars(r,')');
3313         VhdlDocGen::deleteAllChars(r,'(');
3314         r.setNum(r.toInt()+1);
3315         t.replace(reg,r.data());
3316         s.append(t.data());
3317         bcli.current()->usedName=s;
3318         bcli.current()->templSpecifiers=t;
3319       }
3320     }
3321   }
3322 }
3323
3324
3325 static QList<MemberDef> mdList;
3326
3327 static MemberDef* findMemFlow(const MemberDef* mdef)
3328 {
3329   for(uint j=0;j<mdList.count();j++)
3330   {
3331     MemberDef* md=(MemberDef*)mdList.at(j);
3332     if (md->name()==mdef->name() &&  md->getStartBodyLine()==mdef->getStartBodyLine())
3333       return md;
3334   }
3335   return 0;
3336 }
3337
3338 void VhdlDocGen::createFlowChart(const MemberDef *mdef)
3339 {
3340   if (mdef==0) return;
3341
3342   QCString codeFragment;
3343   MemberDef* mm=0;
3344   if((mm=findMemFlow(mdef))!=0)
3345   {
3346     // don't create the same flowchart twice
3347     VhdlDocGen::setFlowMember(mm);
3348     return;
3349   }
3350   else
3351   {
3352     mdList.append(mdef);
3353   }
3354
3355   //fprintf(stderr,"\n create flow mem %s %p\n",mdef->name().data(),mdef);
3356
3357   int actualStart= mdef->getStartBodyLine();
3358   int actualEnd=mdef->getEndBodyLine();
3359   FileDef* fd=mdef->getFileDef();
3360   bool b=readCodeFragment( fd->absFilePath().data(), actualStart,actualEnd,codeFragment);
3361   if (!b) return;
3362
3363   VHDLLanguageScanner *pIntf =(VHDLLanguageScanner*) Doxygen::parserManager->getParser(".vhd");
3364   VhdlDocGen::setFlowMember(mdef);
3365   Entry root;
3366   QStrList filesInSameTu;
3367   pIntf->startTranslationUnit("");
3368   pIntf->parseInput("",codeFragment.data(),&root,FALSE,filesInSameTu);
3369   pIntf->finishTranslationUnit();
3370 }
3371
3372 void VhdlDocGen::resetCodeVhdlParserState()
3373 {
3374   varMap.clear();
3375   qli.clear();
3376   packages.clear();
3377 }
3378
3379 bool VhdlDocGen::isConstraint(const MemberDef *mdef)
3380 { return mdef->getMemberSpecifiers()==VhdlDocGen::UCF_CONST; }
3381 bool VhdlDocGen::isConfig(const MemberDef *mdef)
3382 { return mdef->getMemberSpecifiers()==VhdlDocGen::CONFIG; }
3383 bool VhdlDocGen::isAlias(const MemberDef *mdef)
3384 { return mdef->getMemberSpecifiers()==VhdlDocGen::ALIAS; }
3385 bool VhdlDocGen::isLibrary(const MemberDef *mdef)
3386 { return mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY; }
3387 bool VhdlDocGen::isGeneric(const MemberDef *mdef)
3388 { return mdef->getMemberSpecifiers()==VhdlDocGen::GENERIC; }
3389 bool VhdlDocGen::isPort(const MemberDef *mdef)
3390 { return mdef->getMemberSpecifiers()==VhdlDocGen::PORT; }
3391 bool VhdlDocGen::isComponent(const MemberDef *mdef)
3392 { return mdef->getMemberSpecifiers()==VhdlDocGen::COMPONENT; }
3393 bool VhdlDocGen::isPackage(const MemberDef *mdef)
3394 { return mdef->getMemberSpecifiers()==VhdlDocGen::USE; }
3395 bool VhdlDocGen::isEntity(const MemberDef *mdef)
3396 { return mdef->getMemberSpecifiers()==VhdlDocGen::ENTITY; }
3397 bool VhdlDocGen::isConstant(const MemberDef *mdef)
3398 { return mdef->getMemberSpecifiers()==VhdlDocGen::CONSTANT; }
3399 bool VhdlDocGen::isVType(const MemberDef *mdef)
3400 { return mdef->getMemberSpecifiers()==VhdlDocGen::TYPE; }
3401 bool VhdlDocGen::isSubType(const MemberDef *mdef)
3402 { return mdef->getMemberSpecifiers()==VhdlDocGen::SUBTYPE; }
3403 bool VhdlDocGen::isVhdlFunction(const MemberDef *mdef)
3404 { return mdef->getMemberSpecifiers()==VhdlDocGen::FUNCTION; }
3405 bool VhdlDocGen::isProcess(const MemberDef *mdef)
3406 { return mdef->getMemberSpecifiers()==VhdlDocGen::PROCESS; }
3407 bool VhdlDocGen::isSignal(const MemberDef *mdef)
3408 { return mdef->getMemberSpecifiers()==VhdlDocGen::SIGNAL; }
3409 bool VhdlDocGen::isAttribute(const MemberDef *mdef)
3410 { return mdef->getMemberSpecifiers()==VhdlDocGen::ATTRIBUTE; }
3411 bool VhdlDocGen::isSignals(const MemberDef *mdef)
3412 { return mdef->getMemberSpecifiers()==VhdlDocGen::SIGNAL; }
3413 bool VhdlDocGen::isProcedure(const MemberDef *mdef)
3414 { return mdef->getMemberSpecifiers()==VhdlDocGen::PROCEDURE; }
3415 bool VhdlDocGen::isRecord(const MemberDef *mdef)
3416 { return mdef->getMemberSpecifiers()==VhdlDocGen::RECORD; }
3417 bool VhdlDocGen::isArchitecture(const MemberDef *mdef)
3418 { return mdef->getMemberSpecifiers()==VhdlDocGen::ARCHITECTURE; }
3419 bool VhdlDocGen::isUnit(const MemberDef *mdef)
3420 { return mdef->getMemberSpecifiers()==VhdlDocGen::UNITS; }
3421 bool VhdlDocGen::isPackageBody(const MemberDef *mdef)
3422 { return mdef->getMemberSpecifiers()==VhdlDocGen::PACKAGE_BODY; }
3423 bool VhdlDocGen::isVariable(const MemberDef *mdef)
3424 { return mdef->getMemberSpecifiers()==VhdlDocGen::SHAREDVARIABLE; }
3425 bool VhdlDocGen::isFile(const MemberDef *mdef)
3426 { return mdef->getMemberSpecifiers()==VhdlDocGen::VFILE; }
3427 bool VhdlDocGen::isGroup(const MemberDef *mdef)
3428 { return mdef->getMemberSpecifiers()==VhdlDocGen::GROUP; }
3429 bool VhdlDocGen::isCompInst(const MemberDef *mdef)
3430 { return mdef->getMemberSpecifiers()==VhdlDocGen::INSTANTIATION; }
3431 bool VhdlDocGen::isMisc(const MemberDef *mdef)
3432 { return mdef->getMemberSpecifiers()==VhdlDocGen::MISCELLANEOUS; }
3433
3434
3435
3436 //############################## Flowcharts #################################################
3437
3438 #define STARTL   (FlowChart::WHILE_NO     | FlowChart::IF_NO    | \
3439                   FlowChart::FOR_NO       | FlowChart::CASE_NO  | \
3440                   FlowChart::LOOP_NO      | WHEN_NO)
3441 #define DECLN    (FlowChart::WHEN_NO      | \
3442                   FlowChart::ELSIF_NO     | FlowChart::IF_NO    | \
3443                   FlowChart::FOR_NO       | FlowChart::WHILE_NO | \
3444                   FlowChart::CASE_NO      | FlowChart::LOOP_NO )
3445 #define STARTFIN (FlowChart::START_NO     | FlowChart::END_NO)
3446 #define LOOP     (FlowChart::FOR_NO       | FlowChart::WHILE_NO | \
3447                   FlowChart::LOOP_NO )
3448 #define ENDCL    (FlowChart::END_CASE     | FlowChart::END_LOOP)
3449 #define EEND     (FlowChart::ENDIF_NO     | FlowChart::ELSE_NO )
3450 #define IFF      (FlowChart::ELSIF_NO     | FlowChart::IF_NO)
3451 #define EXITNEXT (FlowChart::EXIT_NO      | FlowChart::NEXT_NO )
3452 #define EMPTY    (EEND                    | FlowChart::ELSIF_NO)
3453 #define EE       (FlowChart::ELSE_NO      | FlowChart::ELSIF_NO)
3454 #define EMPTNODE (ENDCL | EEND            | FlowChart::ELSIF_NO)
3455 #define FLOWLEN (flowList.count()-1)
3456
3457 static int ifcounter=0;
3458 static int nodeCounter=0;
3459
3460 static struct
3461 {
3462    // link colors
3463    const char *textNodeLink;
3464    const char *yesNodeLink;
3465    const char *noNodeLink;
3466
3467    // node colors
3468    const char* comment;
3469    const char* decisionNode;
3470    const char* varNode;
3471    const char *startEndNode;
3472    const char* textNode;
3473 } flowCol =
3474 { "green",       // textNodeLink
3475   "red",         // yesNodeLink
3476   "black",       // noNodeLink
3477   "khaki",       // comment
3478   "0.7 0.3 1.0", // decisionNode
3479   "lightyellow", // varNode
3480   "white",       // startEndNode
3481   "lightcyan"    // textNode
3482 };
3483
3484 QList<FlowChart>  FlowChart::flowList;
3485
3486 #ifdef DEBUGFLOW
3487 static QMap<QCString,int> keyMap;
3488 #endif
3489
3490 void alignText(QCString & q)
3491 {
3492   if (q.length()<=80) return;
3493
3494   if (q.length()>200)
3495   {
3496     q.resize(200);
3497   }
3498
3499   q.append(" ...");
3500
3501   QRegExp reg("[\\s|]");
3502   QCString str(q.data());
3503   QCString temp;
3504
3505   while (str.length()>80)
3506   {
3507     int j=str.findRev(reg,80);
3508     if (j<=0)
3509     {
3510       temp+=str;
3511       q=temp;
3512       return;
3513     }
3514     else
3515     {
3516       QCString qcs=str.left(j);
3517       temp+=qcs+"\\";
3518       temp+="n";
3519       str.remove(0,j);
3520     }
3521   }//while
3522
3523  q=temp+str;
3524 // #endif
3525 }
3526
3527 void FlowChart::printNode(const FlowChart* flo)
3528 {
3529   if (flo==0) return;
3530   QCString ui="-";
3531   QCString q,t;
3532   QRegExp ep("[\t\n\r]");
3533
3534   ui.fill('-',255);
3535
3536   if (flo->type & STARTL)
3537   {
3538     if (flo->stamp>0)
3539     {
3540       q=ui.left(2*flo->stamp);
3541     }
3542     else
3543     {
3544       q=" ";
3545     }
3546     QCString nn=flo->exp.stripWhiteSpace();
3547     printf("\nYES: %s%s[%d,%d]",q.data(),nn.data(),flo->stamp,flo->id);
3548   }
3549   else
3550   {
3551     if (flo->type & COMMENT_NO)
3552     {
3553       t=flo->label;
3554     }
3555     else
3556     {
3557       t=flo->text;
3558     }
3559     t=t.replace(ep,"");
3560     if (t.isEmpty())
3561     {
3562       t=" ";
3563     }
3564     if (flo->stamp>0)
3565     {
3566       q=ui.left(2*flo->stamp);
3567     }
3568     else
3569     {
3570       q=" ";
3571     }
3572     if (flo->type & EMPTNODE)
3573     {
3574       printf("\n NO: %s%s[%d,%d]",q.data(),FlowChart::getNodeType(flo->type),flo->stamp,flo->id);
3575     }
3576     else if (flo->type & COMMENT_NO)
3577     {
3578       printf("\n NO: %s%s[%d,%d]",t.data(),FlowChart::getNodeType(flo->type),flo->stamp,flo->id);
3579     }
3580     else
3581     {
3582       printf("\n NO: %s%s[%d,%d]",q.data(),t.data(),flo->stamp,flo->id);
3583     }
3584   }
3585 }
3586
3587 void  FlowChart::printFlowTree()
3588 {
3589   uint size=flowList.count();
3590   for (uint j=0;j<size;j++)
3591   {
3592     printNode(flowList.at(j));
3593   }
3594 }
3595
3596 void  FlowChart::colTextNodes()
3597 {
3598   QCString text;
3599   FlowChart *flno;
3600   bool found=FALSE;
3601   for (uint j=0;j<flowList.count();j++)
3602   {
3603     FlowChart *flo=flowList.at(j);
3604     if (flo->type&TEXT_NO)
3605     {
3606       text+=flo->text+'\n';
3607       if (!found)
3608       {
3609         flno=flo;
3610       }
3611       if (found)
3612       {
3613         flno->text+=flo->text;
3614         flowList.remove(flo);
3615         if (j>0) j=j-1;
3616       }
3617       found=TRUE;
3618     }
3619     else
3620       found=FALSE;
3621   }
3622
3623   // find if..endif without text
3624   //       if..elseif without text
3625   for (uint j=0;j<flowList.count()-1;j++)
3626   {
3627     FlowChart *flo=flowList.at(j);
3628     int kind=flo->type;
3629     if ( (kind & IFF) || (flo->type & ELSE_NO))
3630     {
3631       FlowChart *ftemp=flowList.at(j+1);
3632       if (ftemp->type & EMPTY)
3633       {
3634         FlowChart *fNew = new FlowChart(TEXT_NO,"empty ",0);
3635         fNew->stamp=flo->stamp;
3636         flowList.insert(j+1,fNew);
3637       }
3638     }
3639   }
3640
3641 }// colTextNode
3642
3643 QCString FlowChart::getNodeName(int n)
3644 {
3645   QCString node;
3646   node.setNum(n);
3647   return node.prepend("node");
3648 }
3649
3650 void FlowChart::delFlowList()
3651 {
3652   ifcounter=0;
3653   nodeCounter=0;
3654   uint size=flowList.count();
3655
3656   for (uint j=0;j <size ;j++)
3657   {
3658     FlowChart *fll=flowList.at(j);
3659     delete fll;
3660   }
3661   flowList.clear();
3662 }
3663
3664 void FlowChart::alignCommentNode(FTextStream &t,QCString com)
3665 {
3666   uint max=0;
3667   QCString s;
3668   QStringList ql=QStringList::split("\n",com);
3669   for (uint j=0;j<ql.count();j++)
3670   {
3671     s=(QCString)ql[j].utf8();
3672     if (max<s.length()) max=s.length();
3673   }
3674
3675   s=ql.last().utf8();
3676   int diff=max-s.length();
3677
3678   QCString n(1);
3679   if (diff>0)
3680   {
3681     n.fill(' ',2*diff);
3682     n.append(".");
3683     s+=n;
3684     ql.remove(ql.last());
3685     ql.append(s);
3686   }
3687
3688   for (uint j=0;j<ql.count();j++)
3689   {
3690     s=(QCString)ql[j].utf8();
3691     if (j<ql.count()-1)
3692     {
3693       s+="\n";
3694     }
3695     FlowChart::codify(t,s.data());
3696   }
3697 }
3698
3699
3700 void FlowChart::buildCommentNodes(FTextStream & t)
3701 {
3702   uint size=flowList.count();
3703   bool begin=false;
3704
3705   for (uint j=0;j < size-1 ;j++)
3706   {
3707     FlowChart *fll=flowList.at(j);
3708     if (fll->type & COMMENT_NO)
3709     {
3710       FlowChart* to=flowList.at(j+1);
3711       if (to->type & COMMENT_NO)
3712       {
3713         fll->label+="\n";
3714         QCString temp=fll->label+to->label;
3715         to->label=temp;
3716         flowList.remove(j);
3717         size--;
3718         if (j>0) j--;
3719       }
3720     }
3721   }// for
3722
3723   for (uint j=0;j <flowList.count() ;j++)
3724   {
3725     FlowChart *fll=flowList.at(j);
3726
3727     if (fll->type & BEGIN_NO)
3728     {
3729       begin = true;
3730       continue;
3731     }
3732
3733     if (fll->type & COMMENT_NO)
3734     {
3735       FlowChart* to;
3736       if (!begin)
3737       {
3738         //  comment between function/process .. begin is linked to start node
3739         to=flowList.at(0);
3740       }
3741       else
3742       {
3743         if (j>0 && flowList.at(j-1)->line==fll->line)
3744           to=flowList.at(j-1);
3745         else
3746           to=flowList.at(j+1);
3747        }
3748       t << getNodeName(fll->id);
3749       t << "[shape=none, label=<\n";
3750       t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
3751       t << "<TR><TD BGCOLOR=\"";
3752       t << flowCol.comment;
3753       t << "\" > ";
3754
3755       FlowChart::alignCommentNode(t,fll->label);
3756       t << " </TD></TR></TABLE>>];";
3757       writeEdge(t,fll->id,to->id,2);
3758     }
3759   }// for
3760
3761   // delete comment nodes;
3762   size=flowList.count();
3763   for (uint j=0;j < size;j++)
3764   {
3765     FlowChart *fll=flowList.at(j);
3766     if (fll->type & (COMMENT_NO | BEGIN_NO))
3767     {
3768       flowList.remove(j);
3769       delete fll;
3770       fll=0;
3771       size--;
3772       if (j>0) j--;
3773     }
3774   }// for;
3775 }
3776
3777 void FlowChart::codify(FTextStream &t,const char *str)
3778 {
3779   if (str)
3780   {
3781     const char *p=str;
3782     char c;
3783     while (*p)
3784     {
3785       c=*p++;
3786       switch(c)
3787       {
3788         case '<':  t << "&lt;"; break;
3789         case '>':  t << "&gt;"; break;
3790         case '&':  t << "&amp;"; break;
3791         case '\'': t << "&#39;"; break;
3792         case '"':  t << "&quot;"; break;
3793         case '\n': t <<"<BR ALIGN=\"LEFT\"/>"; break;
3794         default:   t << c; break;
3795       }
3796     }
3797   }
3798 }//codify
3799
3800 FlowChart::~FlowChart()
3801 {
3802 }
3803
3804 FlowChart::FlowChart(int typ,const char * t,const char* ex,const char* lab)
3805 {
3806   stamp=ifcounter;
3807
3808   if (typ & STARTL)
3809   {
3810     ifcounter++;
3811   }
3812
3813   text=t;
3814   exp=ex;
3815   type=typ;
3816   label=lab;
3817
3818   if (typ & (ELSE_NO | ELSIF_NO))
3819   {
3820     stamp--;
3821   }
3822
3823   if (typ & (START_NO | END_NO | VARIABLE_NO))
3824   {
3825     stamp=0;
3826   }
3827
3828   id=nodeCounter++;
3829 }
3830
3831 void FlowChart::addFlowChart(int type,const char* text,const char* exp, const char *label)
3832 {
3833   static QRegExp reg("[;]");
3834   static QRegExp reg1("[\"]");
3835
3836   if (!VhdlDocGen::getFlowMember()) return;
3837
3838   QCString typeString(text);
3839   QCString expression(exp);
3840
3841
3842   if (text)
3843   {
3844     typeString=typeString.replace(reg,"\n");
3845   }
3846
3847   if (exp)
3848   {
3849     expression=expression.replace(reg1,"\\\"");
3850   }
3851
3852   FlowChart *fl=new FlowChart(type,typeString.data(),expression.data(),label);
3853
3854   fl->line=vhdl::parser::VhdlParser::getLine();
3855
3856   if (type & (START_NO | VARIABLE_NO))
3857   {
3858     flowList.prepend(fl);
3859   }
3860   else
3861   {
3862     flowList.append(fl);
3863   }
3864
3865 }
3866
3867 void FlowChart::moveToPrevLevel()
3868 {
3869   if (!VhdlDocGen::getFlowMember()) return;
3870   ifcounter--;
3871 }
3872
3873
3874 QCString FlowChart::convertNameToFileName()
3875 {
3876   static QRegExp exp ("[^][a-z_A-Z0-9]");
3877   QCString temp,qcs;
3878   const  MemberDef* md=VhdlDocGen::getFlowMember();
3879
3880   temp.sprintf("%p",md);
3881   qcs=md->name();
3882
3883   if (qcs.find(exp,0)>=0)
3884   {
3885     qcs.prepend("Z");
3886     qcs=qcs.replace(exp,"_");
3887   }
3888
3889   return qcs+temp;
3890 }
3891
3892 const char* FlowChart::getNodeType(int c)
3893 {
3894   switch(c)
3895   {
3896     case IF_NO:        return "if ";
3897     case ELSIF_NO:     return "elsif ";
3898     case ELSE_NO:      return "else ";
3899     case CASE_NO:      return "case ";
3900     case WHEN_NO:      return "when ";
3901     case EXIT_NO:      return "exit ";
3902     case END_NO:       return "end ";
3903     case TEXT_NO:      return "text ";
3904     case START_NO:     return "start  ";
3905     case ENDIF_NO:     return "endif  ";
3906     case FOR_NO:       return "for ";
3907     case WHILE_NO:     return "while  ";
3908     case END_LOOP:     return "end_loop  ";
3909     case END_CASE:     return "end_case  ";
3910     case VARIABLE_NO:  return "variable_decl  ";
3911     case RETURN_NO:    return "return  ";
3912     case LOOP_NO:      return "infinte loop  ";
3913     case NEXT_NO:      return "next  ";
3914     case COMMENT_NO:   return "comment  ";
3915     case EMPTY_NO:     return "empty  ";
3916     case BEGIN_NO:     return "<begin>  ";
3917     default: return "--failure--";
3918   }
3919 }
3920
3921 void FlowChart::createSVG()
3922 {
3923   QCString qcs("/");
3924   QCString ov = Config_getString("HTML_OUTPUT");
3925
3926   qcs+=FlowChart::convertNameToFileName()+".svg";
3927
3928   //const  MemberDef *m=VhdlDocGen::getFlowMember();
3929   //if (m)
3930   //  fprintf(stderr,"\n creating  flowchart  : %s  %s in file %s \n",VhdlDocGen::trTypeString(m->getMemberSpecifiers()),m->name().data(),m->getFileDef()->name().data());
3931
3932   QCString dir=" -o "+ov+qcs;
3933   ov+="/flow_design.dot";
3934
3935   QCString vlargs="-Tsvg "+ov+dir ;
3936
3937   if (portable_system("dot",vlargs)!=0)
3938   {
3939     err("could not create dot file");
3940   }
3941 }
3942
3943 void FlowChart::startDot(FTextStream &t)
3944 {
3945   t << " digraph G { \n";
3946   t << "rankdir=TB \n";
3947   t << "concentrate=true\n";
3948   t << "stylesheet=\"doxygen.css\"\n";
3949 }
3950
3951 void FlowChart::endDot(FTextStream &t)
3952 {
3953   t << " } \n";
3954 }
3955
3956 void FlowChart::writeFlowChart()
3957 {
3958   //  assert(VhdlDocGen::flowMember);
3959
3960   QCString ov = Config_getString("HTML_OUTPUT");
3961   QCString fileName = ov+"/flow_design.dot";
3962   QFile f(fileName);
3963   FTextStream t(&f);
3964
3965   if (!f.open(IO_WriteOnly))
3966   {
3967     err("Cannot open file %s for writing\n",fileName.data());
3968     return;
3969   }
3970
3971   colTextNodes();
3972
3973 #ifdef DEBUGFLOW
3974   printFlowTree();
3975 #endif
3976
3977   startDot(t);
3978   buildCommentNodes(t);
3979
3980   uint size=flowList.count();
3981
3982   for (uint j=0;j <size ;j++)
3983   {
3984     FlowChart *fll=flowList.at(j);
3985     writeShape(t,fll);
3986   }
3987   writeFlowLinks(t);
3988
3989   FlowChart::endDot(t);
3990   delFlowList();
3991   f.close();
3992   FlowChart::createSVG();
3993 }// writeFlowChart
3994
3995 void FlowChart::writeShape(FTextStream &t,const FlowChart* fl)
3996 {
3997   if (fl->type & EEND) return;
3998   QCString var;
3999   if (fl->type & LOOP)
4000   {
4001     var=" loop";
4002   }
4003   else if (fl->type & IFF)
4004   {
4005     var=" then";
4006   }
4007   else
4008   {
4009     var="";
4010   }
4011
4012   t<<getNodeName(fl->id).data();
4013   QCString q=getNodeType(fl->type);
4014
4015 #ifdef DEBUGFLOW
4016   QCString qq(getNodeName(fl->id).data());
4017   keyMap.insert(qq,fl->id);
4018 #endif
4019
4020   bool dec=(fl->type & DECLN);
4021   bool exit=(fl->type & EXITNEXT);
4022   if (exit && !fl->exp.isEmpty())
4023   {
4024     dec=TRUE;
4025   }
4026   if (dec)
4027   {
4028     QCString exp=fl->exp;
4029     alignText(exp);
4030
4031     t << " [shape=diamond,style=filled,color=\"";
4032     t << flowCol.decisionNode;
4033     t << "\",label=\" ";
4034     QCString kl;
4035     if (exit) kl=fl->text+"  ";
4036
4037     if (fl->label)
4038     {
4039       kl+=fl->label+":"+exp+var;
4040     }
4041     else
4042     {
4043       kl+=exp+var;
4044     }
4045
4046     FlowChart::alignCommentNode(t,kl);
4047     t << "\"]\n";
4048   }
4049   else if (fl->type & ENDCL)
4050   {
4051     QCString val=fl->text;
4052     t << " [shape=ellipse ,label=\""+val+"\"]\n";
4053   }
4054   else if (fl->type & STARTFIN)
4055   {
4056     QCString val=fl->text;
4057     t << "[shape=box , style=rounded label=<\n";
4058     t << "<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" >\n ";
4059     t << "<TR><TD BGCOLOR=\"";
4060     t<< flowCol.startEndNode;
4061     t<< "\"> ";
4062     FlowChart::alignCommentNode(t,val);
4063     t << " </TD></TR></TABLE>>];";
4064   }
4065   else
4066   {
4067     if (fl->text.isEmpty()) return;
4068     bool var=(fl->type & FlowChart::VARIABLE_NO);
4069     QCString repl("<BR ALIGN=\"LEFT\"/>");
4070     QCString q=fl->text;
4071
4072     if (exit)
4073     {
4074       q+=" "+fl->label;
4075     }
4076
4077     int z=q.findRev("\n");
4078
4079     if (z==(int)q.length()-1)
4080     {
4081       q=q.remove(z,2);
4082     }
4083     t << "[shape=none margin=0.1, label=<\n";
4084     t << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"2\" >\n ";
4085     if (var)
4086     {
4087       t << "<TR><TD BGCOLOR=\"" << flowCol.varNode << "\" > ";
4088     }
4089     else
4090     {
4091       t << "<TR><TD BGCOLOR=\"" << flowCol.textNode << "\" > ";
4092     }
4093     FlowChart::alignCommentNode(t,q);
4094     t << " </TD></TR></TABLE>>];";
4095   }
4096 }
4097
4098
4099 void FlowChart::writeEdge(FTextStream &t,const FlowChart* fl_from,const FlowChart* fl_to,int i)
4100 {
4101   bool b=fl_from->type & STARTL;
4102   bool c=fl_to->type & STARTL;
4103
4104 #ifdef DEBUGFLOW
4105   QCString s1(getNodeName(fl_from->id).data());
4106   QCString s2(getNodeName(fl_to->id).data());
4107   QMap<QCString, int>::Iterator it = keyMap.find(s1);
4108   QMap<QCString, int>::Iterator it1 = keyMap.find(s2);
4109   // checks if the link is connected to a valid node
4110   assert(it.key());
4111   assert(it1.key());
4112 #endif
4113
4114   writeEdge(t,fl_from->id,fl_to->id,i,b,c);
4115 }
4116
4117 void FlowChart::writeEdge(FTextStream &t,int fl_from,int fl_to,int i,bool bFrom,bool bTo)
4118 {
4119   QCString label,col;
4120
4121   if (i==0)
4122   {
4123     col=flowCol.yesNodeLink;
4124     label="yes";
4125   }
4126   else if (i==1)
4127   {
4128     col=flowCol.noNodeLink;
4129     label="no";
4130   }
4131   else
4132   {
4133     col=flowCol.textNodeLink;
4134     label="";
4135   }
4136
4137   t << "edge [color=\""+col+"\",label=\""+label+"\"]\n";
4138   t << getNodeName(fl_from).data();
4139   if (bFrom) t << ":s";
4140   t << "->";
4141   t << getNodeName(fl_to).data();
4142   if (bTo) t << ":n";
4143   t << "\n";
4144 }
4145
4146 void FlowChart::alignFuncProc( QCString & q,const ArgumentList* al,bool isFunc)
4147 {
4148   if (al==0) return;
4149
4150   ArgumentListIterator ali(*al);
4151   int index=ali.count();
4152   if (index==0) return;
4153
4154   int len=q.length()+VhdlDocGen::getFlowMember()->name().length();
4155   QCString prev,temp;
4156   prev.fill(' ',len+1);
4157
4158   Argument *arg;
4159   q+="\n";
4160   for (;(arg=ali.current());++ali)
4161   {
4162     QCString attl=arg->defval+" ";
4163     attl+=arg->name+" ";
4164
4165     if (!isFunc)
4166     {
4167       attl+=arg->attrib+" ";
4168     }
4169     else
4170     {
4171       attl+=" in ";
4172     }
4173     attl+=arg->type;
4174     if (--index) attl+=",\n"; else attl+="\n";
4175
4176     attl.prepend(prev.data());
4177     temp+=attl;
4178   }
4179
4180   q+=temp;
4181 }
4182
4183 int FlowChart::findNextLoop(int index,int stamp)
4184 {
4185   for (uint j=index+1;j<flowList.count();j++)
4186   {
4187     FlowChart *flo=flowList.at(j);
4188     if (flo->stamp==stamp)
4189     {
4190       continue;
4191     }
4192     if (flo->type&END_LOOP)
4193     {
4194       return j;
4195     }
4196   }
4197   return flowList.count()-1;
4198 }
4199
4200 int FlowChart::findPrevLoop(int index,int stamp,bool endif)
4201 {
4202   for (uint j=index;j>0;j--)
4203   {
4204     FlowChart *flo=flowList.at(j);
4205     if (flo->type & LOOP)
4206     {
4207       if (flo->stamp==stamp && endif)
4208       {
4209         return j;
4210       }
4211       else
4212       {
4213         if (flo->stamp<stamp)
4214         {
4215           return j;
4216         }
4217       }
4218     }
4219   }
4220   return flowList.count()-1;
4221 }
4222
4223 int FlowChart::findLabel(int index,QCString &label)
4224 {
4225   for (uint j=index;j>0;j--)
4226   {
4227     FlowChart *flo=flowList.at(j);
4228     if ((flo->type & LOOP) && !flo->label.isEmpty() && qstricmp(flo->label,label)==0)
4229     {
4230       return j;
4231     }
4232   }
4233   err("could not find label: ",label.data());
4234   return 0;
4235 }
4236
4237 int FlowChart::findNode(int index,int stamp,int type)
4238 {
4239   for (uint j=index+1;j<flowList.count();j++)
4240   {
4241     FlowChart *flo=flowList.at(j);
4242     if (flo->type==type && flo->stamp==stamp)
4243     {
4244       return j;
4245     }
4246   }
4247   return 0;
4248 }// findNode
4249
4250 int FlowChart::getNextNode(int index,int stamp)
4251 {
4252   for (uint j=index+1;j<flowList.count();j++)
4253   {
4254     FlowChart *flo=flowList.at(j);
4255     int kind=flo->type;
4256     int s=flo->stamp;
4257     if (s>stamp)
4258     {
4259       continue;
4260     }
4261     if (kind & ENDIF_NO)
4262     {
4263       if (s<stamp && stamp>0)
4264       {
4265         stamp--;
4266         continue;
4267       }
4268     }
4269     if (kind & (ELSE_NO | ELSIF_NO))
4270     {
4271       if (s<stamp && stamp>0)
4272       {
4273         stamp--;
4274       }
4275       j=findNode(j,stamp,ENDIF_NO);
4276       continue;
4277     }
4278     if (kind & WHEN_NO)
4279     {
4280       if (s<stamp && stamp>0)
4281       {
4282         stamp--;
4283       }
4284       return findNode(j,stamp-1,END_CASE);
4285     }
4286     return j;
4287   }
4288   return FLOWLEN;
4289 }
4290
4291 int FlowChart::getNextIfLink(const FlowChart* fl,uint index)
4292 {
4293   int stamp=fl->stamp;
4294   uint start = index+1;
4295   int endifNode  = findNode(start,stamp,ENDIF_NO);
4296   int elseifNode = findNode(start,stamp,ELSIF_NO);
4297   int elseNode   = findNode(start,stamp,ELSE_NO);
4298
4299   assert(endifNode>-1);
4300
4301   if (elseifNode>0 && elseifNode<endifNode)
4302   {
4303     return elseifNode;
4304   }
4305
4306   if (elseNode>0 && elseNode<endifNode)
4307   {
4308     return elseNode+1;
4309   }
4310
4311   stamp=flowList.at(endifNode)->stamp;
4312   return getNextNode(endifNode,stamp);
4313 }
4314
4315 void FlowChart::writeFlowLinks(FTextStream &t)
4316 {
4317   uint size=flowList.count();
4318   if (size<2) return;
4319
4320   // write start link
4321   writeEdge(t,flowList.at(0),flowList.at(1),2);
4322
4323   for (uint j=0;j<size;j++)
4324   {
4325     FlowChart *fll=flowList.at(j);
4326     int kind=fll->type;
4327     int stamp=fll->stamp;
4328     if (kind & EEND)
4329     {
4330       continue;
4331     }
4332
4333     if (kind & IFF)
4334     {
4335       writeEdge(t,fll,flowList.at(j+1),0);
4336       int z=getNextIfLink(fll,j);
4337       // assert(z>-1);
4338       writeEdge(t,fll,flowList.at(z),1);
4339     }
4340     else if (kind & LOOP_NO)
4341     {
4342       writeEdge(t,fll,flowList.at(j+1),2);
4343       continue;
4344     }
4345     else if (kind & (CASE_NO | FOR_NO | WHILE_NO))
4346     {
4347       if (kind & CASE_NO)
4348       {
4349         writeEdge(t,fll,flowList.at(j+1),2);
4350         continue;
4351       }
4352       else
4353       {
4354         writeEdge(t,fll,flowList.at(j+1),0);
4355       }
4356
4357       kind=END_LOOP;
4358       int z=findNode(j+1,fll->stamp,kind);
4359       z=getNextNode(z,flowList.at(z)->stamp);
4360
4361       // assert(z>-1);
4362       writeEdge(t,fll,flowList.at(z),1);
4363       continue;
4364     }
4365     else if (kind & (TEXT_NO | VARIABLE_NO))
4366     {
4367       int z=getNextNode(j,stamp);
4368       writeEdge(t,fll,flowList.at(z),2);
4369     }
4370     else if (kind & WHEN_NO)
4371     {
4372       // default value
4373       if (qstricmp(fll->text.simplifyWhiteSpace().data(),"others")==0)
4374       {
4375         writeEdge(t,fll,flowList.at(j+1),2);
4376         continue;
4377       }
4378
4379
4380       writeEdge(t,fll,flowList.at(j+1),0);
4381       int u=findNode(j,stamp,WHEN_NO);
4382       int v=findNode(j,stamp-1,END_CASE);
4383
4384       if (u>0 && u<v)
4385       {
4386         writeEdge(t,fll,flowList.at(u),1);
4387       }
4388       else
4389       {
4390         writeEdge(t,fll,flowList.at(v),1);
4391       }
4392     }
4393     else if (kind & END_CASE)
4394     {
4395       int z=FlowChart::getNextNode(j,fll->stamp);
4396       writeEdge(t,fll,flowList.at(z),2);
4397     }
4398     else if (kind & END_LOOP)
4399     {
4400       int z=findPrevLoop(j,fll->stamp,true);
4401       writeEdge(t,fll,flowList.at(z),2);
4402     }
4403     else if (kind & RETURN_NO)
4404     {
4405       writeEdge(t,fll,FlowChart::flowList.at(size-1),2);
4406     }
4407     else if (kind & (EXIT_NO | NEXT_NO))
4408     {
4409       int z;
4410       bool b = kind==NEXT_NO;
4411       if (fll->exp)
4412       {
4413         writeEdge(t,fll,flowList.at(j+1),1);
4414       }
4415       if (!fll->label.isEmpty())
4416       {
4417         z=findLabel(j,fll->label);
4418         if (b)
4419         {
4420           writeEdge(t,fll,flowList.at(z),0);
4421         }
4422         else
4423         {
4424           z=findNode(z,flowList.at(z)->stamp,END_LOOP);
4425           z=getNextNode(z,flowList.at(z)->stamp);
4426           writeEdge(t,fll,flowList.at(z),0);
4427         }
4428         continue;
4429       }
4430       else
4431       {
4432         if (b)
4433         {
4434           z=findPrevLoop(j,fll->stamp);
4435           writeEdge(t,fll,flowList.at(z),0);
4436           continue;
4437         }
4438         else
4439         {
4440           z =findNextLoop(j,fll->stamp-1);
4441         }
4442         z=getNextNode(z,flowList.at(z)->stamp);
4443       }
4444       writeEdge(t,fll,flowList.at(z),0);
4445     }
4446   } //for
4447 } //writeFlowLinks
4448
4449
4450 void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
4451     const char *scopeName,
4452     const QCString &input,
4453     SrcLangExt, // lang
4454     bool isExampleBlock,
4455     const char *exampleName,
4456     FileDef *fileDef,
4457     int startLine,
4458     int endLine,
4459     bool inlineFragment,
4460     MemberDef *memberDef,
4461     bool showLineNumbers,
4462     Definition *searchCtx,
4463     bool collectXRefs
4464     )
4465 {
4466
4467 parseVhdlCode(codeOutIntf,
4468                  scopeName,
4469                   input,
4470                   isExampleBlock,
4471                   exampleName,
4472                   fileDef,
4473                   startLine,
4474                   endLine,
4475                   inlineFragment,
4476                   memberDef,
4477                   showLineNumbers,
4478                   searchCtx,
4479                   collectXRefs
4480
4481 );
4482
4483 }