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