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