Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / src / perlmodgen.cpp
1 /******************************************************************************
2  *
3  *
4  *
5  *
6  * Copyright (C) 1997-2014 by Dimitri van Heesch.
7  * Authors: Dimitri van Heesch, Miguel Lobo.
8  *
9  * Permission to use, copy, modify, and distribute this software and its
10  * documentation under the terms of the GNU General Public License is hereby
11  * granted. No representations are made about the suitability of this software
12  * for any purpose. It is provided "as is" without express or implied warranty.
13  * See the GNU General Public License for more details.
14  *
15  * Documents produced by Doxygen are derivative works derived from the
16  * input used in their production; they are not affected by this license.
17  *
18  */
19
20 #include <stdlib.h>
21
22 #include <qdir.h>
23 #include <qstack.h>
24 #include <qdict.h>
25 #include <qfile.h>
26
27 #include "perlmodgen.h"
28 #include "docparser.h"
29 #include "message.h"
30 #include "doxygen.h"
31 #include "pagedef.h"
32 #include "memberlist.h"
33 #include "ftextstream.h"
34 #include "arguments.h"
35 #include "config.h"
36 #include "groupdef.h"
37 #include "classdef.h"
38 #include "classlist.h"
39 #include "filename.h"
40 #include "membername.h"
41 #include "namespacedef.h"
42 #include "membergroup.h"
43 #include "section.h"
44 #include "util.h"
45 #include "htmlentity.h"
46
47 #define PERLOUTPUT_MAX_INDENTATION 40
48
49 class PerlModOutputStream
50 {
51 public:
52
53   QCString m_s;
54   FTextStream *m_t;
55
56   PerlModOutputStream(FTextStream *t = 0) : m_t(t) { }
57
58   void add(char c);
59   void add(const char *s);
60   void add(QCString &s);
61   void add(int n);
62   void add(unsigned int n);
63 };
64
65 void PerlModOutputStream::add(char c)
66 {
67   if (m_t != 0)
68     (*m_t) << c;
69   else
70     m_s += c;
71 }
72
73 void PerlModOutputStream::add(const char *s)
74 {
75   if (m_t != 0)
76     (*m_t) << s;
77   else
78     m_s += s;
79 }
80
81 void PerlModOutputStream::add(QCString &s)
82 {
83   if (m_t != 0)
84     (*m_t) << s;
85   else
86     m_s += s;
87 }
88
89 void PerlModOutputStream::add(int n)
90 {
91   if (m_t != 0)
92     (*m_t) << n;
93   else
94     m_s += n;
95 }
96
97 void PerlModOutputStream::add(unsigned int n)
98 {
99   if (m_t != 0)
100     (*m_t) << n;
101   else
102     m_s += n;
103 }
104
105 class PerlModOutput
106 {
107 public:
108
109   bool m_pretty;
110
111   inline PerlModOutput(bool pretty)
112     : m_pretty(pretty), m_stream(0), m_indentation(false), m_blockstart(true)
113   {
114     m_spaces[0] = 0;
115   }
116
117   virtual ~PerlModOutput() { }
118
119   inline void setPerlModOutputStream(PerlModOutputStream *os) { m_stream = os; }
120
121   inline PerlModOutput &openSave() { iopenSave(); return *this; }
122   inline PerlModOutput &closeSave(QCString &s) { icloseSave(s); return *this; }
123
124   inline PerlModOutput &continueBlock()
125   {
126     if (m_blockstart)
127       m_blockstart = false;
128     else
129       m_stream->add(',');
130     indent();
131     return *this;
132   }
133
134   inline PerlModOutput &add(char c) { m_stream->add(c); return *this; }
135   inline PerlModOutput &add(const char *s) { m_stream->add(s); return *this; }
136   inline PerlModOutput &add(QCString &s) { m_stream->add(s); return *this; }
137   inline PerlModOutput &add(int n) { m_stream->add(n); return *this; }
138   inline PerlModOutput &add(unsigned int n) { m_stream->add(n); return *this; }
139
140   PerlModOutput &addQuoted(const char *s) { iaddQuoted(s); return *this; }
141
142   inline PerlModOutput &indent()
143   {
144     if (m_pretty) {
145       m_stream->add('\n');
146       m_stream->add(m_spaces);
147     }
148     return *this;
149   }
150
151   inline PerlModOutput &open(char c, const char *s = 0) { iopen(c, s); return *this; }
152   inline PerlModOutput &close(char c = 0) { iclose(c); return *this; }
153
154   inline PerlModOutput &addField(const char *s) { iaddField(s); return *this; }
155   inline PerlModOutput &addFieldQuotedChar(const char *field, char content)
156   {
157     iaddFieldQuotedChar(field, content); return *this;
158   }
159   inline PerlModOutput &addFieldQuotedString(const char *field, const char *content)
160   {
161     iaddFieldQuotedString(field, content); return *this;
162   }
163   inline PerlModOutput &addFieldBoolean(const char *field, bool content)
164   {
165     return addFieldQuotedString(field, content ? "yes" : "no");
166   }
167   inline PerlModOutput &openList(const char *s = 0) { open('[', s); return *this; }
168   inline PerlModOutput &closeList() { close(']'); return *this; }
169   inline PerlModOutput &openHash(const char *s = 0 ) { open('{', s); return *this; }
170   inline PerlModOutput &closeHash() { close('}'); return *this; }
171
172 protected:
173   
174   void iopenSave();
175   void icloseSave(QCString &);
176   
177   void incIndent();
178   void decIndent();
179
180   void iaddQuoted(const char *);
181   void iaddFieldQuotedChar(const char *, char);
182   void iaddFieldQuotedString(const char *, const char *);
183   void iaddField(const char *);
184
185   void iopen(char, const char *);
186   void iclose(char);
187
188 private:
189   
190   PerlModOutputStream *m_stream;
191   int m_indentation;
192   bool m_blockstart;
193
194   QStack<PerlModOutputStream> m_saved;
195   char m_spaces[PERLOUTPUT_MAX_INDENTATION * 2 + 2];
196 };
197
198 void PerlModOutput::iopenSave()
199 {
200   m_saved.push(m_stream);
201   m_stream = new PerlModOutputStream();
202 }
203
204 void PerlModOutput::icloseSave(QCString &s)
205 {
206   s = m_stream->m_s;
207   delete m_stream;
208   m_stream = m_saved.pop();
209 }
210
211 void PerlModOutput::incIndent()
212 {
213   if (m_indentation < PERLOUTPUT_MAX_INDENTATION)
214   {
215     char *s = &m_spaces[m_indentation * 2];
216     *s++ = ' '; *s++ = ' '; *s = 0;
217   }
218   m_indentation++;
219 }
220
221 void PerlModOutput::decIndent()
222 {
223   m_indentation--;
224   if (m_indentation < PERLOUTPUT_MAX_INDENTATION)
225     m_spaces[m_indentation * 2] = 0;
226 }
227
228 void PerlModOutput::iaddQuoted(const char *s) 
229 {
230   char c;
231   while ((c = *s++) != 0) {
232     if ((c == '\'') || (c == '\\'))
233       m_stream->add('\\');
234     m_stream->add(c);
235   }
236 }
237   
238 void PerlModOutput::iaddField(const char *s)
239 {
240   continueBlock();
241   m_stream->add(s);
242   m_stream->add(m_pretty ? " => " : "=>");
243 }
244
245 void PerlModOutput::iaddFieldQuotedChar(const char *field, char content)
246 {
247   iaddField(field);
248   m_stream->add('\'');
249   if ((content == '\'') || (content == '\\'))
250     m_stream->add('\\');
251   m_stream->add(content);
252   m_stream->add('\'');
253 }
254
255 void PerlModOutput::iaddFieldQuotedString(const char *field, const char *content)
256 {
257   if (content == 0)
258     return;
259   iaddField(field);
260   m_stream->add('\'');
261   iaddQuoted(content);
262   m_stream->add('\'');
263 }
264
265 void PerlModOutput::iopen(char c, const char *s)
266 {
267   if (s != 0)
268     iaddField(s);
269   else
270     continueBlock();
271   m_stream->add(c);
272   incIndent();
273   m_blockstart = true;
274 }
275
276 void PerlModOutput::iclose(char c)
277 {
278   decIndent(); 
279   indent();
280   if (c != 0)
281     m_stream->add(c); 
282   m_blockstart = false;
283 }
284
285 /*! @brief Concrete visitor implementation for PerlMod output. */
286 class PerlModDocVisitor : public DocVisitor
287 {
288 public:
289   PerlModDocVisitor(PerlModOutput &);
290   virtual ~PerlModDocVisitor() { }
291
292   void finish();
293   
294   //--------------------------------------
295   // visitor functions for leaf nodes
296   //--------------------------------------
297    
298   void visit(DocWord *);
299   void visit(DocLinkedWord *);
300   void visit(DocWhiteSpace *);
301   void visit(DocSymbol *);
302   void visit(DocURL *);
303   void visit(DocLineBreak *);
304   void visit(DocHorRuler *);
305   void visit(DocStyleChange *);
306   void visit(DocVerbatim *);
307   void visit(DocAnchor *);
308   void visit(DocInclude *);
309   void visit(DocIncOperator *);
310   void visit(DocFormula *);
311   void visit(DocIndexEntry *);
312   void visit(DocSimpleSectSep *);
313   void visit(DocCite *);
314
315   //--------------------------------------
316   // visitor functions for compound nodes
317   //--------------------------------------
318    
319   void visitPre(DocAutoList *);
320   void visitPost(DocAutoList *);
321   void visitPre(DocAutoListItem *);
322   void visitPost(DocAutoListItem *);
323   void visitPre(DocPara *) ;
324   void visitPost(DocPara *);
325   void visitPre(DocRoot *);
326   void visitPost(DocRoot *);
327   void visitPre(DocSimpleSect *);
328   void visitPost(DocSimpleSect *);
329   void visitPre(DocTitle *);
330   void visitPost(DocTitle *);
331   void visitPre(DocSimpleList *);
332   void visitPost(DocSimpleList *);
333   void visitPre(DocSimpleListItem *);
334   void visitPost(DocSimpleListItem *);
335   void visitPre(DocSection *);
336   void visitPost(DocSection *);
337   void visitPre(DocHtmlList *);
338   void visitPost(DocHtmlList *) ;
339   void visitPre(DocHtmlListItem *);
340   void visitPost(DocHtmlListItem *);
341   //void visitPre(DocHtmlPre *);
342   //void visitPost(DocHtmlPre *);
343   void visitPre(DocHtmlDescList *);
344   void visitPost(DocHtmlDescList *);
345   void visitPre(DocHtmlDescTitle *);
346   void visitPost(DocHtmlDescTitle *);
347   void visitPre(DocHtmlDescData *);
348   void visitPost(DocHtmlDescData *);
349   void visitPre(DocHtmlTable *);
350   void visitPost(DocHtmlTable *);
351   void visitPre(DocHtmlRow *);
352   void visitPost(DocHtmlRow *) ;
353   void visitPre(DocHtmlCell *);
354   void visitPost(DocHtmlCell *);
355   void visitPre(DocHtmlCaption *);
356   void visitPost(DocHtmlCaption *);
357   void visitPre(DocInternal *);
358   void visitPost(DocInternal *);
359   void visitPre(DocHRef *);
360   void visitPost(DocHRef *);
361   void visitPre(DocHtmlHeader *);
362   void visitPost(DocHtmlHeader *);
363   void visitPre(DocImage *);
364   void visitPost(DocImage *);
365   void visitPre(DocDotFile *);
366   void visitPost(DocDotFile *);
367   void visitPre(DocMscFile *);
368   void visitPost(DocMscFile *);
369   void visitPre(DocDiaFile *);
370   void visitPost(DocDiaFile *);
371   void visitPre(DocLink *);
372   void visitPost(DocLink *);
373   void visitPre(DocRef *);
374   void visitPost(DocRef *);
375   void visitPre(DocSecRefItem *);
376   void visitPost(DocSecRefItem *);
377   void visitPre(DocSecRefList *);
378   void visitPost(DocSecRefList *);
379   //void visitPre(DocLanguage *);
380   //void visitPost(DocLanguage *);
381   void visitPre(DocParamSect *);
382   void visitPost(DocParamSect *);
383   void visitPre(DocParamList *);
384   void visitPost(DocParamList *);
385   void visitPre(DocXRefItem *);
386   void visitPost(DocXRefItem *);
387   void visitPre(DocInternalRef *);
388   void visitPost(DocInternalRef *);
389   void visitPre(DocCopy *);
390   void visitPost(DocCopy *);
391   void visitPre(DocText *);
392   void visitPost(DocText *);
393   void visitPre(DocHtmlBlockQuote *);
394   void visitPost(DocHtmlBlockQuote *);
395   void visitPre(DocVhdlFlow *);
396   void visitPost(DocVhdlFlow *);
397   void visitPre(DocParBlock *);
398   void visitPost(DocParBlock *);
399
400 private:
401
402   //--------------------------------------
403   // helper functions
404   //--------------------------------------
405
406   void addLink(const QCString &ref, const QCString &file,
407                const QCString &anchor);
408    
409   void enterText();
410   void leaveText();
411
412   void openItem(const char *);
413   void closeItem();
414   void singleItem(const char *);
415   void openSubBlock(const char * = 0);
416   void closeSubBlock();
417   void openOther();
418   void closeOther();
419
420   //--------------------------------------
421   // state variables
422   //--------------------------------------
423
424   PerlModOutput &m_output;
425   bool m_textmode;
426   bool m_textblockstart;
427   QCString m_other;
428 };
429
430 PerlModDocVisitor::PerlModDocVisitor(PerlModOutput &output)
431   : DocVisitor(DocVisitor_Other), m_output(output), m_textmode(false)
432 {
433   m_output.openList("doc");
434 }
435
436 void PerlModDocVisitor::finish()
437 {
438   leaveText();
439   m_output.closeList()
440     .add(m_other);
441 }
442
443 void PerlModDocVisitor::addLink(const QCString &,const QCString &file,const QCString &anchor)
444 {
445   QCString link = file;
446   if (!anchor.isEmpty())
447     (link += "_1") += anchor;
448   m_output.addFieldQuotedString("link", link);
449 }
450
451 void PerlModDocVisitor::openItem(const char *name)
452 {
453   leaveText();
454   m_output.openHash().addFieldQuotedString("type", name);
455 }
456
457 void PerlModDocVisitor::closeItem()
458 {
459   leaveText();
460   m_output.closeHash();
461 }
462
463 void PerlModDocVisitor::enterText()
464 {
465   if (m_textmode)
466     return;
467   openItem("text");
468   m_output.addField("content").add('\'');
469   m_textmode = true;
470 }
471
472 void PerlModDocVisitor::leaveText()
473 {
474   if (!m_textmode)
475     return;
476   m_textmode = false;
477   m_output
478     .add('\'')
479     .closeHash();
480 }
481
482 void PerlModDocVisitor::singleItem(const char *name)
483 {
484   openItem(name);
485   closeItem();
486 }
487
488 void PerlModDocVisitor::openSubBlock(const char *s)
489 {
490   leaveText();
491   m_output.openList(s);
492   m_textblockstart = true;
493 }
494
495 void PerlModDocVisitor::closeSubBlock()
496 {
497   leaveText();
498   m_output.closeList();
499 }
500
501 void PerlModDocVisitor::openOther()
502 {
503   // Using a secondary text stream will corrupt the perl file. Instead of
504   // printing doc => [ data => [] ], it will print doc => [] data => [].
505   /*
506   leaveText();
507   m_output.openSave();
508   */
509 }
510
511 void PerlModDocVisitor::closeOther()
512 {
513   // Using a secondary text stream will corrupt the perl file. Instead of
514   // printing doc => [ data => [] ], it will print doc => [] data => [].
515   /*
516   QCString other;
517   leaveText();
518   m_output.closeSave(other);
519   m_other += other;
520   */
521 }
522
523 void PerlModDocVisitor::visit(DocWord *w)
524 {
525   enterText();
526   m_output.addQuoted(w->word());
527 }
528
529 void PerlModDocVisitor::visit(DocLinkedWord *w)
530 {
531   openItem("url");
532   addLink(w->ref(), w->file(), w->anchor());
533   m_output.addFieldQuotedString("content", w->word());
534   closeItem();
535 }
536
537 void PerlModDocVisitor::visit(DocWhiteSpace *)
538 {
539   enterText();
540   m_output.add(' ');
541 }
542
543 void PerlModDocVisitor::visit(DocSymbol *sy)
544 {
545   const DocSymbol::PerlSymb *res = HtmlEntityMapper::instance()->perl(sy->symbol());
546   const char *accent=0;
547   if (res-> symb)
548   {
549     switch (res->type)
550     {
551       case DocSymbol::Perl_string:
552         enterText();
553         m_output.add(res->symb);
554         break;
555       case DocSymbol::Perl_char:
556         enterText();
557         m_output.add(res->symb[0]);
558         break;
559       case DocSymbol::Perl_symbol:
560         leaveText();
561         openItem("symbol");
562         m_output.addFieldQuotedString("symbol", res->symb);
563         closeItem();
564         break;
565       default:
566         switch(res->type)
567         {
568           case DocSymbol::Perl_umlaut:
569             accent = "umlaut";
570             break;
571           case DocSymbol::Perl_acute:
572             accent = "acute";
573             break;
574           case DocSymbol::Perl_grave:
575             accent = "grave";
576             break;
577           case DocSymbol::Perl_circ:
578             accent = "circ";
579             break;
580           case DocSymbol::Perl_slash:
581             accent = "slash";
582             break;
583           case DocSymbol::Perl_tilde:
584             accent = "tilde";
585             break;
586           case DocSymbol::Perl_cedilla:
587             accent = "cedilla";
588             break;
589           case DocSymbol::Perl_ring:
590             accent = "ring";
591             break;
592           default:
593             break;
594         }
595         leaveText();
596         if (accent)
597         {
598           openItem("accent");
599           m_output
600             .addFieldQuotedString("accent", accent)
601             .addFieldQuotedChar("letter", res->symb[0]);
602           closeItem();
603         }
604         break;
605     }
606   }
607   else
608   {
609     err("perl: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(sy->symbol(),TRUE));
610   }
611 }
612
613 void PerlModDocVisitor::visit(DocURL *u)
614 {
615   openItem("url");
616   m_output.addFieldQuotedString("content", u->url());
617   closeItem();
618 }
619
620 void PerlModDocVisitor::visit(DocLineBreak *) { singleItem("linebreak"); }
621 void PerlModDocVisitor::visit(DocHorRuler *) { singleItem("hruler"); }
622
623 void PerlModDocVisitor::visit(DocStyleChange *s)
624 {
625   const char *style = 0;
626   switch (s->style())
627   {
628     case DocStyleChange::Bold:          style = "bold"; break;
629     case DocStyleChange::Italic:        style = "italic"; break;
630     case DocStyleChange::Code:          style = "code"; break;
631     case DocStyleChange::Subscript:     style = "subscript"; break;
632     case DocStyleChange::Superscript:   style = "superscript"; break;
633     case DocStyleChange::Center:        style = "center"; break;
634     case DocStyleChange::Small:         style = "small"; break;
635     case DocStyleChange::Preformatted:  style = "preformatted"; break;
636     case DocStyleChange::Div:           style = "div"; break;
637     case DocStyleChange::Span:          style = "span"; break;
638                                         
639   }
640   openItem("style");
641   m_output.addFieldQuotedString("style", style)
642     .addFieldBoolean("enable", s->enable());
643   closeItem();
644 }
645
646 void PerlModDocVisitor::visit(DocVerbatim *s)
647 {
648   const char *type = 0;
649   switch (s->type())
650   {
651     case DocVerbatim::Code:
652 #if 0
653       m_output.add("<programlisting>");
654       parseCode(m_ci,s->context(),s->text(),FALSE,0);
655       m_output.add("</programlisting>");
656 #endif
657       return;
658     case DocVerbatim::Verbatim:  type = "preformatted"; break;
659     case DocVerbatim::HtmlOnly:  type = "htmlonly";     break;
660     case DocVerbatim::RtfOnly:   type = "rtfonly";      break;
661     case DocVerbatim::ManOnly:   type = "manonly";      break;
662     case DocVerbatim::LatexOnly: type = "latexonly";    break;
663     case DocVerbatim::XmlOnly:   type = "xmlonly";      break;
664     case DocVerbatim::DocbookOnly: type = "docbookonly"; break;
665     case DocVerbatim::Dot:       type = "dot";          break;
666     case DocVerbatim::Msc:       type = "msc";          break;
667     case DocVerbatim::PlantUML:  type = "plantuml";     break;
668   }
669   openItem(type);
670   m_output.addFieldQuotedString("content", s->text());
671   closeItem();
672 }
673
674 void PerlModDocVisitor::visit(DocAnchor *anc)
675 {
676   QCString anchor = anc->file() + "_1" + anc->anchor();
677   openItem("anchor");
678   m_output.addFieldQuotedString("id", anchor);
679   closeItem();
680 }
681
682 void PerlModDocVisitor::visit(DocInclude *inc)
683 {
684   const char *type = 0;
685   switch(inc->type())
686   {
687   case DocInclude::IncWithLines:
688   #if 0
689       { 
690          m_t << "<div class=\"fragment\"><pre>";
691          QFileInfo cfi( inc->file() );
692          FileDef fd( cfi.dirPath(), cfi.fileName() );
693          parseCode(m_ci,inc->context(),inc->text().latin1(),inc->isExample(),inc->exampleFile(), &fd);
694          m_t << "</pre></div>"; 
695       }
696       break;
697   #endif
698     return;
699   case DocInclude::Include:
700 #if 0
701     m_output.add("<programlisting>");
702     parseCode(m_ci,inc->context(),inc->text(),FALSE,0);
703     m_output.add("</programlisting>");
704 #endif
705     return;
706   case DocInclude::DontInclude: return;
707   case DocInclude::HtmlInclude: type = "htmlonly"; break;
708   case DocInclude::LatexInclude: type = "latexonly"; break;
709   case DocInclude::VerbInclude: type = "preformatted"; break;
710   case DocInclude::Snippet: return;
711   }
712   openItem(type);
713   m_output.addFieldQuotedString("content", inc->text());
714   closeItem();
715 }
716
717 void PerlModDocVisitor::visit(DocIncOperator *)
718 {
719 #if 0
720   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
721   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
722   if (op->isFirst())
723   {
724     m_output.add("<programlisting>");
725   }
726   if (op->type()!=DocIncOperator::Skip)
727   {
728     parseCode(m_ci,op->context(),op->text(),FALSE,0);
729   }
730   if (op->isLast()) 
731   {
732     m_output.add("</programlisting>");
733   }
734   else
735   {
736     m_output.add('\n');
737   }
738 #endif
739 }
740
741 void PerlModDocVisitor::visit(DocFormula *f)
742 {
743   openItem("formula");
744   QCString id;
745   id += f->id();
746   m_output.addFieldQuotedString("id", id).addFieldQuotedString("content", f->text());
747   closeItem();
748 }
749
750 void PerlModDocVisitor::visit(DocIndexEntry *)
751 {
752 #if 0
753   m_output.add("<indexentry>"
754                "<primaryie>");
755   m_output.addQuoted(ie->entry());
756   m_output.add("</primaryie>"
757                "<secondaryie></secondaryie>"
758                "</indexentry>");
759 #endif
760 }
761
762 void PerlModDocVisitor::visit(DocSimpleSectSep *)
763 {
764 }
765
766 void PerlModDocVisitor::visit(DocCite *cite)
767 {
768   openItem("cite");
769   m_output.addFieldQuotedString("text", cite->text());
770   closeItem();
771 }
772
773
774 //--------------------------------------
775 // visitor functions for compound nodes
776 //--------------------------------------
777
778 void PerlModDocVisitor::visitPre(DocAutoList *l)
779 {
780   openItem("list");
781   m_output.addFieldQuotedString("style", l->isEnumList() ? "ordered" : "itemized");
782   openSubBlock("content");
783 }
784
785 void PerlModDocVisitor::visitPost(DocAutoList *)
786 {
787   closeSubBlock();
788   closeItem();
789 }
790
791 void PerlModDocVisitor::visitPre(DocAutoListItem *)
792 {
793   openSubBlock();
794 }
795
796 void PerlModDocVisitor::visitPost(DocAutoListItem *)
797 {
798   closeSubBlock();
799 }
800
801 void PerlModDocVisitor::visitPre(DocPara *)
802 {
803   if (m_textblockstart)
804     m_textblockstart = false;
805   else
806     singleItem("parbreak");
807   /*
808   openItem("para");
809   openSubBlock("content");
810   */
811 }
812
813 void PerlModDocVisitor::visitPost(DocPara *)
814 {
815   /*
816   closeSubBlock();
817   closeItem();
818   */
819 }
820
821 void PerlModDocVisitor::visitPre(DocRoot *)
822 {
823 }
824
825 void PerlModDocVisitor::visitPost(DocRoot *)
826 {
827 }
828
829 void PerlModDocVisitor::visitPre(DocSimpleSect *s)
830 {
831   const char *type = 0;
832   switch (s->type())
833   {
834   case DocSimpleSect::See:              type = "see"; break;
835   case DocSimpleSect::Return:           type = "return"; break;
836   case DocSimpleSect::Author:           type = "author"; break;
837   case DocSimpleSect::Authors:          type = "authors"; break;
838   case DocSimpleSect::Version:          type = "version"; break;
839   case DocSimpleSect::Since:            type = "since"; break;
840   case DocSimpleSect::Date:             type = "date"; break;
841   case DocSimpleSect::Note:             type = "note"; break;
842   case DocSimpleSect::Warning:          type = "warning"; break;
843   case DocSimpleSect::Pre:              type = "pre"; break;
844   case DocSimpleSect::Post:             type = "post"; break;
845   case DocSimpleSect::Copyright:        type = "copyright"; break;
846   case DocSimpleSect::Invar:            type = "invariant"; break;
847   case DocSimpleSect::Remark:           type = "remark"; break;
848   case DocSimpleSect::Attention:        type = "attention"; break;
849   case DocSimpleSect::User:             type = "par"; break;
850   case DocSimpleSect::Rcs:              type = "rcs"; break;
851   case DocSimpleSect::Unknown:
852     err("unknown simple section found\n");
853     break;
854   }
855   leaveText();
856   m_output.openHash();
857   openOther();
858   openSubBlock(type);
859 }
860
861 void PerlModDocVisitor::visitPost(DocSimpleSect *)
862 {
863   closeSubBlock();
864   closeOther();
865   m_output.closeHash();
866 }
867
868 void PerlModDocVisitor::visitPre(DocTitle *)
869 {
870   openItem("title");
871   openSubBlock("content");
872 }
873
874 void PerlModDocVisitor::visitPost(DocTitle *)
875 {
876   closeSubBlock();
877   closeItem();
878 }
879
880 void PerlModDocVisitor::visitPre(DocSimpleList *) 
881 {
882   openItem("list");
883   m_output.addFieldQuotedString("style", "itemized");
884   openSubBlock("content");
885 }
886
887 void PerlModDocVisitor::visitPost(DocSimpleList *)
888 {
889   closeSubBlock();
890   closeItem();
891 }
892
893 void PerlModDocVisitor::visitPre(DocSimpleListItem *) { openSubBlock(); }
894 void PerlModDocVisitor::visitPost(DocSimpleListItem *) { closeSubBlock(); }
895
896 void PerlModDocVisitor::visitPre(DocSection *s)
897 {
898   QCString sect = QCString().sprintf("sect%d",s->level());
899   openItem(sect);
900   openSubBlock("content");
901 }
902
903 void PerlModDocVisitor::visitPost(DocSection *)
904 {
905   closeSubBlock();
906   closeItem();
907 }
908
909 void PerlModDocVisitor::visitPre(DocHtmlList *l)
910 {
911   openItem("list");
912   m_output.addFieldQuotedString("style", (l->type() == DocHtmlList::Ordered) ? "ordered" : "itemized");
913   openSubBlock("content");
914 }
915
916 void PerlModDocVisitor::visitPost(DocHtmlList *)
917 {
918   closeSubBlock();
919   closeItem();
920 }
921
922 void PerlModDocVisitor::visitPre(DocHtmlListItem *) { openSubBlock(); }
923 void PerlModDocVisitor::visitPost(DocHtmlListItem *) { closeSubBlock(); }
924
925 //void PerlModDocVisitor::visitPre(DocHtmlPre *)
926 //{
927 //  openItem("preformatted");
928 //  openSubBlock("content");
929 //  //m_insidePre=TRUE;
930 //}
931
932 //void PerlModDocVisitor::visitPost(DocHtmlPre *)
933 //{
934 //  //m_insidePre=FALSE;
935 //  closeSubBlock();
936 //  closeItem();
937 //}
938
939 void PerlModDocVisitor::visitPre(DocHtmlDescList *)
940 {
941 #if 0
942   m_output.add("<variablelist>\n");
943 #endif
944 }
945
946 void PerlModDocVisitor::visitPost(DocHtmlDescList *)
947 {
948 #if 0
949   m_output.add("</variablelist>\n");
950 #endif
951 }
952
953 void PerlModDocVisitor::visitPre(DocHtmlDescTitle *)
954 {
955 #if 0
956   m_output.add("<varlistentry><term>");
957 #endif
958 }
959
960 void PerlModDocVisitor::visitPost(DocHtmlDescTitle *)
961 {
962 #if 0
963   m_output.add("</term></varlistentry>\n");
964 #endif
965 }
966
967 void PerlModDocVisitor::visitPre(DocHtmlDescData *)
968 {
969 #if 0
970   m_output.add("<listitem>");
971 #endif
972 }
973
974 void PerlModDocVisitor::visitPost(DocHtmlDescData *)
975 {
976 #if 0
977   m_output.add("</listitem>\n");
978 #endif
979 }
980
981 void PerlModDocVisitor::visitPre(DocHtmlTable *)
982 {
983 #if 0
984   m_output.add("<table rows=\""); m_output.add(t->numRows());
985   m_output.add("\" cols=\""); m_output.add(t->numCols()); m_output.add("\">");
986 #endif
987 }
988
989 void PerlModDocVisitor::visitPost(DocHtmlTable *)
990 {
991 #if 0
992   m_output.add("</table>\n");
993 #endif
994 }
995
996 void PerlModDocVisitor::visitPre(DocHtmlRow *)
997 {
998 #if 0
999   m_output.add("<row>\n");
1000 #endif
1001 }
1002
1003 void PerlModDocVisitor::visitPost(DocHtmlRow *)
1004 {
1005 #if 0
1006   m_output.add("</row>\n");
1007 #endif
1008 }
1009
1010 void PerlModDocVisitor::visitPre(DocHtmlCell *)
1011 {
1012 #if 0
1013   if (c->isHeading()) m_output.add("<entry thead=\"yes\">"); else m_output.add("<entry thead=\"no\">");
1014 #endif
1015 }
1016
1017 void PerlModDocVisitor::visitPost(DocHtmlCell *)
1018 {
1019 #if 0
1020   m_output.add("</entry>");
1021 #endif
1022 }
1023
1024 void PerlModDocVisitor::visitPre(DocHtmlCaption *)
1025 {
1026 #if 0
1027   m_output.add("<caption>");
1028 #endif
1029 }
1030
1031 void PerlModDocVisitor::visitPost(DocHtmlCaption *)
1032 {
1033 #if 0
1034   m_output.add("</caption>\n");
1035 #endif
1036 }
1037
1038 void PerlModDocVisitor::visitPre(DocInternal *)
1039 {
1040 #if 0
1041   m_output.add("<internal>");
1042 #endif
1043 }
1044
1045 void PerlModDocVisitor::visitPost(DocInternal *)
1046 {
1047 #if 0
1048   m_output.add("</internal>");
1049 #endif
1050 }
1051
1052 void PerlModDocVisitor::visitPre(DocHRef *)
1053 {
1054 #if 0
1055   m_output.add("<ulink url=\""); m_output.add(href->url()); m_output.add("\">");
1056 #endif
1057 }
1058
1059 void PerlModDocVisitor::visitPost(DocHRef *)
1060 {
1061 #if 0
1062   m_output.add("</ulink>");
1063 #endif
1064 }
1065
1066 void PerlModDocVisitor::visitPre(DocHtmlHeader *)
1067 {
1068 #if 0
1069   m_output.add("<sect"); m_output.add(header->level()); m_output.add(">");
1070 #endif
1071 }
1072
1073 void PerlModDocVisitor::visitPost(DocHtmlHeader *)
1074 {
1075 #if 0
1076   m_output.add("</sect"); m_output.add(header->level()); m_output.add(">\n");
1077 #endif
1078 }
1079
1080 void PerlModDocVisitor::visitPre(DocImage *)
1081 {
1082 #if 0
1083   m_output.add("<image type=\"");
1084   switch(img->type())
1085   {
1086   case DocImage::Html:  m_output.add("html"); break;
1087   case DocImage::Latex: m_output.add("latex"); break;
1088   case DocImage::Rtf:   m_output.add("rtf"); break;
1089   }
1090   m_output.add("\"");
1091   
1092   QCString baseName=img->name();
1093   int i;
1094   if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
1095   {
1096     baseName=baseName.right(baseName.length()-i-1);
1097   }
1098   m_output.add(" name=\""); m_output.add(baseName); m_output.add("\"");
1099   if (!img->width().isEmpty())
1100   {
1101     m_output.add(" width=\"");
1102     m_output.addQuoted(img->width());
1103     m_output.add("\"");
1104   }
1105   else if (!img->height().isEmpty())
1106   {
1107     m_output.add(" height=\"");
1108     m_output.addQuoted(img->height());
1109     m_output.add("\"");
1110   }
1111   m_output.add(">");
1112 #endif
1113 }
1114
1115 void PerlModDocVisitor::visitPost(DocImage *)
1116 {
1117 #if 0
1118   m_output.add("</image>");
1119 #endif
1120 }
1121
1122 void PerlModDocVisitor::visitPre(DocDotFile *)
1123 {
1124 #if 0
1125   m_output.add("<dotfile name=\""); m_output.add(df->file()); m_output.add("\">");
1126 #endif
1127 }
1128
1129 void PerlModDocVisitor::visitPost(DocDotFile *)
1130 {
1131 #if 0
1132   m_output.add("</dotfile>");
1133 #endif
1134 }
1135 void PerlModDocVisitor::visitPre(DocMscFile *)
1136 {
1137 #if 0
1138   m_output.add("<mscfile name=\""); m_output.add(df->file()); m_output.add("\">");
1139 #endif
1140 }
1141
1142 void PerlModDocVisitor::visitPost(DocMscFile *)
1143 {
1144 #if 0
1145   m_output.add("<mscfile>");
1146 #endif
1147 }
1148
1149 void PerlModDocVisitor::visitPre(DocDiaFile *)
1150 {
1151 #if 0
1152   m_output.add("<diafile name=\""); m_output.add(df->file()); m_output.add("\">");
1153 #endif
1154 }
1155
1156 void PerlModDocVisitor::visitPost(DocDiaFile *)
1157 {
1158 #if 0
1159   m_output.add("</diafile>");
1160 #endif
1161 }
1162
1163
1164 void PerlModDocVisitor::visitPre(DocLink *lnk)
1165 {
1166   openItem("link");
1167   addLink(lnk->ref(), lnk->file(), lnk->anchor());
1168 }
1169
1170 void PerlModDocVisitor::visitPost(DocLink *)
1171 {
1172   closeItem();
1173 }
1174
1175 void PerlModDocVisitor::visitPre(DocRef *ref)
1176 {
1177   openItem("ref");
1178   if (!ref->hasLinkText())
1179     m_output.addFieldQuotedString("text", ref->targetTitle());
1180   openSubBlock("content");
1181 }
1182
1183 void PerlModDocVisitor::visitPost(DocRef *)
1184 {
1185   closeSubBlock();
1186   closeItem();
1187 }
1188
1189 void PerlModDocVisitor::visitPre(DocSecRefItem *)
1190 {
1191 #if 0
1192   m_output.add("<tocitem id=\""); m_output.add(ref->file()); m_output.add("_1"); m_output.add(ref->anchor()); m_output.add("\">");
1193 #endif
1194 }
1195
1196 void PerlModDocVisitor::visitPost(DocSecRefItem *)
1197 {
1198 #if 0
1199   m_output.add("</tocitem>");
1200 #endif
1201 }
1202
1203 void PerlModDocVisitor::visitPre(DocSecRefList *)
1204 {
1205 #if 0
1206   m_output.add("<toclist>");
1207 #endif
1208 }
1209
1210 void PerlModDocVisitor::visitPost(DocSecRefList *)
1211 {
1212 #if 0
1213   m_output.add("</toclist>");
1214 #endif
1215 }
1216
1217 //void PerlModDocVisitor::visitPre(DocLanguage *l)
1218 //{
1219 //  openItem("language");
1220 //  m_output.addFieldQuotedString("id", l->id());
1221 //}
1222 //
1223 //void PerlModDocVisitor::visitPost(DocLanguage *)
1224 //{
1225 //  closeItem();
1226 //}
1227
1228 void PerlModDocVisitor::visitPre(DocParamSect *s)
1229 {
1230   leaveText();
1231   const char *type = 0;
1232   switch(s->type())
1233   {
1234   case DocParamSect::Param:     type = "params"; break;
1235   case DocParamSect::RetVal:    type = "retvals"; break;
1236   case DocParamSect::Exception: type = "exceptions"; break;
1237   case DocParamSect::TemplateParam: type = "templateparam"; break;
1238   case DocParamSect::Unknown:
1239     err("unknown parameter section found\n");
1240     break;
1241   }
1242   openOther();
1243   openSubBlock(type);
1244 }
1245
1246 void PerlModDocVisitor::visitPost(DocParamSect *)
1247 {
1248   closeSubBlock();
1249   closeOther();
1250 }
1251
1252 void PerlModDocVisitor::visitPre(DocParamList *pl)
1253 {
1254   leaveText();
1255   m_output.openHash()
1256     .openList("parameters");
1257   //QStrListIterator li(pl->parameters());
1258   //const char *s;
1259   QListIterator<DocNode> li(pl->parameters());
1260   DocNode *param;
1261   for (li.toFirst();(param=li.current());++li)
1262   {
1263     QCString s;
1264     if (param->kind()==DocNode::Kind_Word)
1265     {
1266       s = ((DocWord*)param)->word(); 
1267     }
1268     else if (param->kind()==DocNode::Kind_LinkedWord)
1269     {
1270       s = ((DocLinkedWord*)param)->word(); 
1271     }
1272     m_output.openHash()
1273       .addFieldQuotedString("name", s)
1274       .closeHash();
1275   }
1276   m_output.closeList()
1277     .openList("doc");
1278 }
1279
1280 void PerlModDocVisitor::visitPost(DocParamList *)
1281 {
1282   leaveText();
1283   m_output.closeList()
1284     .closeHash();
1285 }
1286
1287 void PerlModDocVisitor::visitPre(DocXRefItem *x)
1288 {
1289 #if 0
1290   m_output.add("<xrefsect id=\"");
1291   m_output.add(x->file()); m_output.add("_1"); m_output.add(x->anchor());
1292   m_output.add("\">");
1293   m_output.add("<xreftitle>");
1294   m_output.addQuoted(x->title());
1295   m_output.add("</xreftitle>");
1296   m_output.add("<xrefdescription>");
1297 #endif
1298   if (x->title().isEmpty()) return;
1299   openItem("xrefitem");
1300   openSubBlock("content");
1301 }
1302
1303 void PerlModDocVisitor::visitPost(DocXRefItem *x)
1304 {
1305   if (x->title().isEmpty()) return;
1306   closeSubBlock();
1307   closeItem();
1308 #if 0
1309   m_output.add("</xrefdescription>");
1310   m_output.add("</xrefsect>");
1311 #endif
1312 }
1313
1314 void PerlModDocVisitor::visitPre(DocInternalRef *ref)
1315 {
1316   openItem("ref");
1317   addLink(0,ref->file(),ref->anchor());
1318   openSubBlock("content");
1319 }
1320
1321 void PerlModDocVisitor::visitPost(DocInternalRef *)
1322 {
1323   closeSubBlock();
1324   closeItem();
1325 }
1326
1327 void PerlModDocVisitor::visitPre(DocCopy *)
1328 {
1329 }
1330
1331 void PerlModDocVisitor::visitPost(DocCopy *)
1332 {
1333 }
1334
1335 void PerlModDocVisitor::visitPre(DocText *)
1336 {
1337 }
1338
1339 void PerlModDocVisitor::visitPost(DocText *)
1340 {
1341 }
1342
1343 void PerlModDocVisitor::visitPre(DocHtmlBlockQuote *)
1344 {
1345   openItem("blockquote");
1346   openSubBlock("content");
1347 }
1348
1349 void PerlModDocVisitor::visitPost(DocHtmlBlockQuote *)
1350 {
1351   closeSubBlock();
1352   closeItem();
1353 }
1354
1355 void PerlModDocVisitor::visitPre(DocVhdlFlow *)
1356 {
1357 }
1358
1359 void PerlModDocVisitor::visitPost(DocVhdlFlow *)
1360 {
1361 }
1362
1363 void PerlModDocVisitor::visitPre(DocParBlock *)
1364 {
1365 }
1366
1367 void PerlModDocVisitor::visitPost(DocParBlock *)
1368 {
1369 }
1370
1371
1372 static void addTemplateArgumentList(ArgumentList *al,PerlModOutput &output,const char *)
1373 {
1374   QCString indentStr;
1375   if (!al)
1376     return;
1377   output.openList("template_parameters");
1378   ArgumentListIterator ali(*al);
1379   Argument *a;
1380   for (ali.toFirst();(a=ali.current());++ali)
1381   {
1382     output.openHash();
1383     if (!a->type.isEmpty())
1384       output.addFieldQuotedString("type", a->type);
1385     if (!a->name.isEmpty())
1386       output.addFieldQuotedString("declaration_name", a->name)
1387         .addFieldQuotedString("definition_name", a->name);
1388     if (!a->defval.isEmpty())
1389       output.addFieldQuotedString("default", a->defval);
1390     output.closeHash();
1391   }
1392   output.closeList();
1393 }
1394
1395 #if 0
1396 static void addMemberTemplateLists(MemberDef *md,PerlModOutput &output)
1397 {
1398   ClassDef *cd = md->getClassDef();
1399   const char *cname = cd ? cd->name().data() : 0;
1400   if (md->templateArguments()) // function template prefix
1401     addTemplateArgumentList(md->templateArguments(),output,cname);
1402 }
1403 #endif
1404
1405 static void addTemplateList(ClassDef *cd,PerlModOutput &output)
1406 {
1407   addTemplateArgumentList(cd->templateArguments(),output,cd->name());
1408 }
1409
1410 static void addPerlModDocBlock(PerlModOutput &output,
1411                             const char *name,
1412                             const QCString &fileName,
1413                             int lineNr,
1414                             Definition *scope,
1415                             MemberDef *md,
1416                             const QCString &text)
1417 {
1418   QCString stext = text.stripWhiteSpace();
1419   if (stext.isEmpty())
1420     output.addField(name).add("{}");
1421   else {
1422     DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,0);
1423     output.openHash(name);
1424     PerlModDocVisitor *visitor = new PerlModDocVisitor(output);
1425     root->accept(visitor);
1426     visitor->finish();
1427     output.closeHash();
1428     delete visitor;
1429     delete root;
1430   }
1431 }
1432
1433 static const char *getProtectionName(Protection prot) 
1434 {
1435   switch (prot)
1436   {
1437   case Public:    return "public";
1438   case Protected: return "protected";
1439   case Private:   return "private";
1440   case Package:   return "package";
1441   }
1442   return 0;
1443 }
1444
1445 static const char *getVirtualnessName(Specifier virt)
1446 {
1447   switch(virt)
1448   {
1449   case Normal:  return "non_virtual";
1450   case Virtual: return "virtual";
1451   case Pure:    return "pure_virtual";
1452   }
1453   return 0;
1454 }
1455
1456 static QCString pathDoxyfile;
1457 static QCString pathDoxyExec;
1458
1459 void setPerlModDoxyfile(const QCString &qs)
1460 {
1461   pathDoxyfile = qs;
1462   pathDoxyExec = QDir::currentDirPath().utf8();
1463 }
1464
1465 class PerlModGenerator
1466 {
1467 public:
1468
1469   PerlModOutput m_output;
1470
1471   QCString pathDoxyStructurePM;
1472   QCString pathDoxyDocsTex;
1473   QCString pathDoxyFormatTex;
1474   QCString pathDoxyLatexTex;
1475   QCString pathDoxyLatexDVI;
1476   QCString pathDoxyLatexPDF;
1477   QCString pathDoxyStructureTex;
1478   QCString pathDoxyDocsPM;
1479   QCString pathDoxyLatexPL;
1480   QCString pathDoxyLatexStructurePL;
1481   QCString pathDoxyRules;
1482   QCString pathMakefile;
1483
1484   inline PerlModGenerator(bool pretty) : m_output(pretty) { }
1485
1486   void generatePerlModForMember(MemberDef *md, Definition *);
1487   void generatePerlModSection(Definition *d, MemberList *ml,
1488                               const char *name, const char *header=0);
1489   void addListOfAllMembers(ClassDef *cd);
1490   void generatePerlModForClass(ClassDef *cd);
1491   void generatePerlModForNamespace(NamespaceDef *nd);
1492   void generatePerlModForFile(FileDef *fd);
1493   void generatePerlModForGroup(GroupDef *gd);
1494   void generatePerlModForPage(PageDef *pi);
1495   
1496   bool createOutputFile(QFile &f, const char *s);
1497   bool createOutputDir(QDir &perlModDir);
1498   bool generateDoxyLatexTex();
1499   bool generateDoxyFormatTex();
1500   bool generateDoxyStructurePM();
1501   bool generateDoxyLatexPL();
1502   bool generateDoxyLatexStructurePL();
1503   bool generateDoxyRules();
1504   bool generateMakefile();
1505   bool generatePerlModOutput();
1506
1507   void generate();
1508 };
1509
1510 void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
1511 {
1512   // + declaration/definition arg lists
1513   // + reimplements
1514   // + reimplementedBy
1515   // + exceptions
1516   // + const/volatile specifiers
1517   // - examples
1518   // - source definition
1519   // - source references
1520   // - source referenced by
1521   // - body code
1522   // - template arguments
1523   //     (templateArguments(), definitionTemplateParameterLists())
1524  
1525   QCString memType;
1526   bool isFunc=FALSE;
1527   switch (md->memberType())
1528   {
1529   case MemberType_Define:      memType="define";    break;
1530   case MemberType_EnumValue:   memType="enumvalue"; break;
1531   case MemberType_Property:    memType="property";  break;
1532   case MemberType_Variable:    memType="variable";  break;
1533   case MemberType_Typedef:     memType="typedef";   break;
1534   case MemberType_Enumeration: memType="enum";      break;
1535   case MemberType_Function:    memType="function";  isFunc=TRUE; break;
1536   case MemberType_Signal:      memType="signal";    isFunc=TRUE; break;
1537   //case MemberType_Prototype:   memType="prototype"; isFunc=TRUE; break;
1538   case MemberType_Friend:      memType="friend";    isFunc=TRUE; break;
1539   case MemberType_DCOP:        memType="dcop";      isFunc=TRUE; break;
1540   case MemberType_Slot:        memType="slot";      isFunc=TRUE; break;
1541   case MemberType_Event:       memType="event";     break;
1542   case MemberType_Interface:   memType="interface"; break;
1543   case MemberType_Service:     memType="service";   break;
1544   }
1545
1546   m_output.openHash()
1547     .addFieldQuotedString("kind", memType)
1548     .addFieldQuotedString("name", md->name())
1549     .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness()))
1550     .addFieldQuotedString("protection", getProtectionName(md->protection()))
1551     .addFieldBoolean("static", md->isStatic());
1552   
1553   addPerlModDocBlock(m_output,"brief",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->briefDescription());
1554   addPerlModDocBlock(m_output,"detailed",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->documentation());
1555   if (md->memberType()!=MemberType_Define &&
1556       md->memberType()!=MemberType_Enumeration)
1557     m_output.addFieldQuotedString("type", md->typeString());
1558   
1559   ArgumentList *al = md->argumentList();
1560   if (isFunc) //function
1561   {
1562     m_output.addFieldBoolean("const", al!=0 && al->constSpecifier)
1563       .addFieldBoolean("volatile", al!=0 && al->volatileSpecifier);
1564
1565     m_output.openList("parameters");
1566     ArgumentList *declAl = md->declArgumentList();
1567     ArgumentList *defAl  = md->argumentList();
1568     if (declAl && declAl->count()>0)
1569     {
1570       ArgumentListIterator declAli(*declAl);
1571       ArgumentListIterator defAli(*defAl);
1572       Argument *a;
1573       for (declAli.toFirst();(a=declAli.current());++declAli)
1574       {
1575         Argument *defArg = defAli.current();
1576         m_output.openHash();
1577
1578         if (!a->name.isEmpty())
1579           m_output.addFieldQuotedString("declaration_name", a->name);
1580
1581         if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
1582           m_output.addFieldQuotedString("definition_name", defArg->name);
1583
1584         if (!a->type.isEmpty())
1585           m_output.addFieldQuotedString("type", a->type);
1586
1587         if (!a->array.isEmpty())
1588           m_output.addFieldQuotedString("array", a->array);
1589
1590         if (!a->defval.isEmpty())
1591           m_output.addFieldQuotedString("default_value", a->defval);
1592
1593         if (!a->attrib.isEmpty())
1594           m_output.addFieldQuotedString("attributes", a->attrib);
1595         
1596         m_output.closeHash();
1597         if (defArg) ++defAli;
1598       }
1599     }
1600     m_output.closeList();
1601   }
1602   else if (md->memberType()==MemberType_Define &&
1603            md->argsString()!=0) // define
1604   {
1605     m_output.openList("parameters");
1606     ArgumentListIterator ali(*al);
1607     Argument *a;
1608     for (ali.toFirst();(a=ali.current());++ali)
1609     {
1610       m_output.openHash()
1611         .addFieldQuotedString("name", a->type)
1612         .closeHash();
1613     }
1614     m_output.closeList();
1615   }
1616   else if (md->argsString()!=0) 
1617   {
1618     m_output.addFieldQuotedString("arguments", md->argsString());
1619   }
1620
1621   if (!md->initializer().isEmpty())
1622     m_output.addFieldQuotedString("initializer", md->initializer());
1623   
1624   if (md->excpString())
1625     m_output.addFieldQuotedString("exceptions", md->excpString());
1626   
1627   if (md->memberType()==MemberType_Enumeration) // enum
1628   {
1629     MemberList *enumFields = md->enumFieldList();
1630     if (enumFields)
1631     {
1632       m_output.openList("values");
1633       MemberListIterator emli(*enumFields);
1634       MemberDef *emd;
1635       for (emli.toFirst();(emd=emli.current());++emli)
1636       {
1637         m_output.openHash()
1638           .addFieldQuotedString("name", emd->name());
1639          
1640         if (!emd->initializer().isEmpty())
1641           m_output.addFieldQuotedString("initializer", emd->initializer());
1642
1643         addPerlModDocBlock(m_output,"brief",emd->getDefFileName(),emd->getDefLine(),emd->getOuterScope(),emd,emd->briefDescription());
1644
1645         addPerlModDocBlock(m_output,"detailed",emd->getDefFileName(),emd->getDefLine(),emd->getOuterScope(),emd,emd->documentation());
1646
1647         m_output.closeHash();
1648       }
1649       m_output.closeList();
1650     }
1651   }
1652
1653   MemberDef *rmd = md->reimplements();
1654   if (rmd)
1655     m_output.openHash("reimplements")
1656       .addFieldQuotedString("name", rmd->name())
1657       .closeHash();
1658
1659   MemberList *rbml = md->reimplementedBy();
1660   if (rbml)
1661   {
1662     MemberListIterator mli(*rbml);
1663     m_output.openList("reimplemented_by");
1664     for (mli.toFirst();(rmd=mli.current());++mli)
1665       m_output.openHash()
1666         .addFieldQuotedString("name", rmd->name())
1667         .closeHash();
1668     m_output.closeList();
1669   }
1670   
1671   m_output.closeHash();
1672 }
1673
1674 void PerlModGenerator::generatePerlModSection(Definition *d,
1675                                               MemberList *ml,const char *name,const char *header)
1676 {
1677   if (ml==0) return; // empty list
1678
1679   m_output.openHash(name);
1680
1681   if (header)
1682     m_output.addFieldQuotedString("header", header);
1683   
1684   m_output.openList("members");
1685   MemberListIterator mli(*ml);
1686   MemberDef *md;
1687   for (mli.toFirst();(md=mli.current());++mli)
1688   {
1689     generatePerlModForMember(md,d);
1690   }
1691   m_output.closeList()
1692     .closeHash();
1693 }
1694
1695 void PerlModGenerator::addListOfAllMembers(ClassDef *cd)
1696 {
1697   m_output.openList("all_members");
1698   if (cd->memberNameInfoSDict())
1699   {
1700     MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict());
1701     MemberNameInfo *mni;
1702     for (mnii.toFirst();(mni=mnii.current());++mnii)
1703     {
1704       MemberNameInfoIterator mii(*mni);
1705       MemberInfo *mi;
1706       for (mii.toFirst();(mi=mii.current());++mii)
1707       {
1708         MemberDef *md=mi->memberDef;
1709         ClassDef  *cd=md->getClassDef();
1710         Definition *d=md->getGroupDef();
1711         if (d==0) d = cd;
1712
1713         m_output.openHash()
1714           .addFieldQuotedString("name", md->name())
1715           .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness()))
1716           .addFieldQuotedString("protection", getProtectionName(mi->prot));
1717
1718         if (!mi->ambiguityResolutionScope.isEmpty())
1719           m_output.addFieldQuotedString("ambiguity_scope", mi->ambiguityResolutionScope);
1720
1721         m_output.addFieldQuotedString("scope", cd->name())
1722           .closeHash();
1723       }
1724     }
1725   }
1726   m_output.closeList();
1727 }
1728
1729 void PerlModGenerator::generatePerlModForClass(ClassDef *cd)
1730 {
1731   // + brief description
1732   // + detailed description
1733   // + template argument list(s)
1734   // - include file
1735   // + member groups
1736   // + inheritance diagram
1737   // + list of direct super classes
1738   // + list of direct sub classes
1739   // + list of inner classes
1740   // + collaboration diagram
1741   // + list of all members
1742   // + user defined member sections
1743   // + standard member sections
1744   // + detailed member documentation
1745   // - examples using the class
1746   
1747   if (cd->isReference())        return; // skip external references.
1748   if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
1749   if (cd->templateMaster()!=0)  return; // skip generated template instances.
1750
1751   m_output.openHash()
1752     .addFieldQuotedString("name", cd->name());
1753   
1754   if (cd->baseClasses())
1755   {
1756     m_output.openList("base");
1757     BaseClassListIterator bcli(*cd->baseClasses());
1758     BaseClassDef *bcd;
1759     for (bcli.toFirst();(bcd=bcli.current());++bcli)
1760       m_output.openHash()
1761         .addFieldQuotedString("name", bcd->classDef->displayName())
1762         .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt))
1763         .addFieldQuotedString("protection", getProtectionName(bcd->prot))
1764         .closeHash();
1765     m_output.closeList();
1766   }
1767
1768   if (cd->subClasses())
1769   {
1770     m_output.openList("derived");
1771     BaseClassListIterator bcli(*cd->subClasses());
1772     BaseClassDef *bcd;
1773     for (bcli.toFirst();(bcd=bcli.current());++bcli)
1774       m_output.openHash()
1775         .addFieldQuotedString("name", bcd->classDef->displayName())
1776         .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt))
1777         .addFieldQuotedString("protection", getProtectionName(bcd->prot))
1778         .closeHash();
1779     m_output.closeList();
1780   }
1781
1782   ClassSDict *cl = cd->getClassSDict();
1783   if (cl)
1784   {
1785     m_output.openList("inner");
1786     ClassSDict::Iterator cli(*cl);
1787     ClassDef *cd;
1788     for (cli.toFirst();(cd=cli.current());++cli)
1789       m_output.openHash()
1790         .addFieldQuotedString("name", cd->name())
1791         .closeHash();
1792     m_output.closeList();
1793   }
1794
1795   IncludeInfo *ii=cd->includeInfo();
1796   if (ii)
1797   {
1798     QCString nm = ii->includeName;
1799     if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1800     if (!nm.isEmpty())
1801     {
1802       m_output.openHash("includes");
1803 #if 0
1804       if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
1805         t << " id=\"" << ii->fileDef->getOutputFileBase() << "\"";
1806 #endif
1807       m_output.addFieldBoolean("local", ii->local)
1808         .addFieldQuotedString("name", nm)
1809         .closeHash();
1810     }
1811   }
1812
1813   addTemplateList(cd,m_output);
1814   addListOfAllMembers(cd);
1815   if (cd->getMemberGroupSDict())
1816   {
1817     MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
1818     MemberGroup *mg;
1819     for (;(mg=mgli.current());++mgli)
1820       generatePerlModSection(cd,mg->members(),"user_defined",mg->header());
1821   }
1822
1823   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubTypes),"public_typedefs");
1824   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubMethods),"public_methods");
1825   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubAttribs),"public_members");
1826   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubSlots),"public_slots");
1827   generatePerlModSection(cd,cd->getMemberList(MemberListType_signals),"signals");
1828   generatePerlModSection(cd,cd->getMemberList(MemberListType_dcopMethods),"dcop_methods");
1829   generatePerlModSection(cd,cd->getMemberList(MemberListType_properties),"properties");
1830   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubStaticMethods),"public_static_methods");
1831   generatePerlModSection(cd,cd->getMemberList(MemberListType_pubStaticAttribs),"public_static_members");
1832   generatePerlModSection(cd,cd->getMemberList(MemberListType_proTypes),"protected_typedefs");
1833   generatePerlModSection(cd,cd->getMemberList(MemberListType_proMethods),"protected_methods");
1834   generatePerlModSection(cd,cd->getMemberList(MemberListType_proAttribs),"protected_members");
1835   generatePerlModSection(cd,cd->getMemberList(MemberListType_proSlots),"protected_slots");
1836   generatePerlModSection(cd,cd->getMemberList(MemberListType_proStaticMethods),"protected_static_methods");
1837   generatePerlModSection(cd,cd->getMemberList(MemberListType_proStaticAttribs),"protected_static_members");
1838   generatePerlModSection(cd,cd->getMemberList(MemberListType_priTypes),"private_typedefs");
1839   generatePerlModSection(cd,cd->getMemberList(MemberListType_priMethods),"private_methods");
1840   generatePerlModSection(cd,cd->getMemberList(MemberListType_priAttribs),"private_members");
1841   generatePerlModSection(cd,cd->getMemberList(MemberListType_priSlots),"private_slots");
1842   generatePerlModSection(cd,cd->getMemberList(MemberListType_priStaticMethods),"private_static_methods");
1843   generatePerlModSection(cd,cd->getMemberList(MemberListType_priStaticAttribs),"private_static_members");
1844   generatePerlModSection(cd,cd->getMemberList(MemberListType_friends),"friend_methods");
1845   generatePerlModSection(cd,cd->getMemberList(MemberListType_related),"related_methods");
1846
1847   addPerlModDocBlock(m_output,"brief",cd->getDefFileName(),cd->getDefLine(),cd,0,cd->briefDescription());
1848   addPerlModDocBlock(m_output,"detailed",cd->getDefFileName(),cd->getDefLine(),cd,0,cd->documentation());
1849
1850 #if 0
1851   DotClassGraph inheritanceGraph(cd,DotClassGraph::Inheritance);
1852   if (!inheritanceGraph.isTrivial())
1853   {
1854     t << "    <inheritancegraph>" << endl;
1855     inheritanceGraph.writePerlMod(t);
1856     t << "    </inheritancegraph>" << endl;
1857   }
1858   DotClassGraph collaborationGraph(cd,DotClassGraph::Implementation);
1859   if (!collaborationGraph.isTrivial())
1860   {
1861     t << "    <collaborationgraph>" << endl;
1862     collaborationGraph.writePerlMod(t);
1863     t << "    </collaborationgraph>" << endl;
1864   }
1865   t << "    <location file=\"" 
1866     << cd->getDefFileName() << "\" line=\"" 
1867     << cd->getDefLine() << "\"";
1868     if (cd->getStartBodyLine()!=-1)
1869     {
1870       t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" 
1871         << cd->getEndBodyLine() << "\"";
1872     }
1873   t << "/>" << endl;
1874 #endif
1875
1876   m_output.closeHash();
1877 }
1878
1879 void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
1880 {
1881   // + contained class definitions
1882   // + contained namespace definitions
1883   // + member groups
1884   // + normal members
1885   // + brief desc
1886   // + detailed desc
1887   // + location
1888   // - files containing (parts of) the namespace definition
1889
1890   if (nd->isReference()) return; // skip external references
1891
1892   m_output.openHash()
1893     .addFieldQuotedString("name", nd->name());
1894   
1895   ClassSDict *cl = nd->getClassSDict();
1896   if (cl)
1897   {
1898     m_output.openList("classes");
1899     ClassSDict::Iterator cli(*cl);
1900     ClassDef *cd;
1901     for (cli.toFirst();(cd=cli.current());++cli)
1902       m_output.openHash()
1903         .addFieldQuotedString("name", cd->name())
1904         .closeHash();
1905     m_output.closeList();
1906   }
1907
1908   NamespaceSDict *nl = nd->getNamespaceSDict();
1909   if (nl)
1910   {
1911     m_output.openList("namespaces");
1912     NamespaceSDict::Iterator nli(*nl);
1913     NamespaceDef *nd;
1914     for (nli.toFirst();(nd=nli.current());++nli)
1915       m_output.openHash()
1916         .addFieldQuotedString("name", nd->name())
1917         .closeHash();
1918     m_output.closeList();
1919   }
1920
1921   if (nd->getMemberGroupSDict())
1922   {
1923     MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
1924     MemberGroup *mg;
1925     for (;(mg=mgli.current());++mgli)
1926       generatePerlModSection(nd,mg->members(),"user-defined",mg->header());
1927   }
1928
1929   generatePerlModSection(nd,nd->getMemberList(MemberListType_decDefineMembers),"defines");
1930   generatePerlModSection(nd,nd->getMemberList(MemberListType_decProtoMembers),"prototypes");
1931   generatePerlModSection(nd,nd->getMemberList(MemberListType_decTypedefMembers),"typedefs");
1932   generatePerlModSection(nd,nd->getMemberList(MemberListType_decEnumMembers),"enums");
1933   generatePerlModSection(nd,nd->getMemberList(MemberListType_decFuncMembers),"functions");
1934   generatePerlModSection(nd,nd->getMemberList(MemberListType_decVarMembers),"variables");
1935
1936   addPerlModDocBlock(m_output,"brief",nd->getDefFileName(),nd->getDefLine(),0,0,nd->briefDescription());
1937   addPerlModDocBlock(m_output,"detailed",nd->getDefFileName(),nd->getDefLine(),0,0,nd->documentation());
1938
1939   m_output.closeHash();
1940 }
1941
1942 void PerlModGenerator::generatePerlModForFile(FileDef *fd)
1943 {
1944   // + includes files
1945   // + includedby files
1946   // - include graph
1947   // - included by graph
1948   // - contained class definitions
1949   // - contained namespace definitions
1950   // - member groups
1951   // + normal members
1952   // + brief desc
1953   // + detailed desc
1954   // - source code
1955   // - location
1956   // - number of lines
1957  
1958   if (fd->isReference()) return;
1959
1960   m_output.openHash()
1961     .addFieldQuotedString("name", fd->name());
1962   
1963   IncludeInfo *inc;
1964   m_output.openList("includes");
1965   if (fd->includeFileList())
1966   {
1967     QListIterator<IncludeInfo> ili1(*fd->includeFileList());
1968     for (ili1.toFirst();(inc=ili1.current());++ili1)
1969     {
1970       m_output.openHash()
1971         .addFieldQuotedString("name", inc->includeName);
1972       if (inc->fileDef && !inc->fileDef->isReference())
1973       {
1974         m_output.addFieldQuotedString("ref", inc->fileDef->getOutputFileBase());
1975       }
1976       m_output.closeHash();
1977     }
1978   }
1979   m_output.closeList();
1980   
1981   m_output.openList("included_by");
1982   if (fd->includedByFileList())
1983   {
1984     QListIterator<IncludeInfo> ili2(*fd->includedByFileList());
1985     for (ili2.toFirst();(inc=ili2.current());++ili2)
1986     {
1987       m_output.openHash()
1988         .addFieldQuotedString("name", inc->includeName);
1989       if (inc->fileDef && !inc->fileDef->isReference())
1990       {
1991         m_output.addFieldQuotedString("ref", inc->fileDef->getOutputFileBase());
1992       }
1993       m_output.closeHash();
1994     }
1995   }
1996   m_output.closeList();
1997   
1998   generatePerlModSection(fd,fd->getMemberList(MemberListType_decDefineMembers),"defines");
1999   generatePerlModSection(fd,fd->getMemberList(MemberListType_decProtoMembers),"prototypes");
2000   generatePerlModSection(fd,fd->getMemberList(MemberListType_decTypedefMembers),"typedefs");
2001   generatePerlModSection(fd,fd->getMemberList(MemberListType_decEnumMembers),"enums");
2002   generatePerlModSection(fd,fd->getMemberList(MemberListType_decFuncMembers),"functions");
2003   generatePerlModSection(fd,fd->getMemberList(MemberListType_decVarMembers),"variables");
2004
2005   addPerlModDocBlock(m_output,"brief",fd->getDefFileName(),fd->getDefLine(),0,0,fd->briefDescription());
2006   addPerlModDocBlock(m_output,"detailed",fd->getDefFileName(),fd->getDefLine(),0,0,fd->documentation());
2007
2008   m_output.closeHash();
2009 }
2010
2011 void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
2012 {
2013   // + members
2014   // + member groups
2015   // + files
2016   // + classes
2017   // + namespaces
2018   // - packages
2019   // + pages
2020   // + child groups
2021   // - examples
2022   // + brief description
2023   // + detailed description
2024
2025   if (gd->isReference()) return; // skip external references
2026
2027   m_output.openHash()
2028     .addFieldQuotedString("name", gd->name())
2029     .addFieldQuotedString("title", gd->groupTitle());
2030
2031   FileList *fl = gd->getFiles();
2032   if (fl)
2033   {
2034     m_output.openList("files");
2035     QListIterator<FileDef> fli(*fl);
2036     FileDef *fd;
2037     for (fli.toFirst();(fd=fli.current());++fli)
2038       m_output.openHash()
2039         .addFieldQuotedString("name", fd->name())
2040         .closeHash();
2041     m_output.closeList();
2042   }
2043
2044   ClassSDict *cl = gd->getClasses();
2045   if (cl)
2046   {
2047     m_output.openList("classes");
2048     ClassSDict::Iterator cli(*cl);
2049     ClassDef *cd;
2050     for (cli.toFirst();(cd=cli.current());++cli)
2051       m_output.openHash()
2052         .addFieldQuotedString("name", cd->name())
2053         .closeHash();
2054     m_output.closeList();
2055   }
2056
2057   NamespaceSDict *nl = gd->getNamespaces();
2058   if (nl)
2059   {
2060     m_output.openList("namespaces");
2061     NamespaceSDict::Iterator nli(*nl);
2062     NamespaceDef *nd;
2063     for (nli.toFirst();(nd=nli.current());++nli)
2064       m_output.openHash()
2065         .addFieldQuotedString("name", nd->name())
2066         .closeHash();
2067     m_output.closeList();
2068   }
2069
2070   PageSDict *pl = gd->getPages();
2071   if (pl)
2072   {
2073     m_output.openList("pages");
2074     PageSDict::Iterator pli(*pl);
2075     PageDef *pd;
2076     for (pli.toFirst();(pd=pli.current());++pli)
2077       m_output.openHash()
2078         .addFieldQuotedString("title", pd->title())
2079         .closeHash();
2080     m_output.closeList();
2081   }
2082
2083   GroupList *gl = gd->getSubGroups();
2084   if (gl)
2085   {
2086     m_output.openList("groups");
2087     GroupListIterator gli(*gl);
2088     GroupDef *sgd;
2089     for (gli.toFirst();(sgd=gli.current());++gli)
2090       m_output.openHash()
2091         .addFieldQuotedString("title", sgd->groupTitle())
2092         .closeHash();
2093     m_output.closeList();
2094   }
2095
2096   if (gd->getMemberGroupSDict())
2097   {
2098     MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
2099     MemberGroup *mg;
2100     for (;(mg=mgli.current());++mgli)
2101       generatePerlModSection(gd,mg->members(),"user-defined",mg->header());
2102   }
2103
2104   generatePerlModSection(gd,gd->getMemberList(MemberListType_decDefineMembers),"defines");
2105   generatePerlModSection(gd,gd->getMemberList(MemberListType_decProtoMembers),"prototypes");
2106   generatePerlModSection(gd,gd->getMemberList(MemberListType_decTypedefMembers),"typedefs");
2107   generatePerlModSection(gd,gd->getMemberList(MemberListType_decEnumMembers),"enums");
2108   generatePerlModSection(gd,gd->getMemberList(MemberListType_decFuncMembers),"functions");
2109   generatePerlModSection(gd,gd->getMemberList(MemberListType_decVarMembers),"variables");
2110
2111   addPerlModDocBlock(m_output,"brief",gd->getDefFileName(),gd->getDefLine(),0,0,gd->briefDescription());
2112   addPerlModDocBlock(m_output,"detailed",gd->getDefFileName(),gd->getDefLine(),0,0,gd->documentation());
2113
2114   m_output.closeHash();
2115 }
2116
2117 void PerlModGenerator::generatePerlModForPage(PageDef *pd)
2118 {
2119   // + name
2120   // + title
2121   // + documentation
2122
2123   if (pd->isReference()) return;
2124
2125   m_output.openHash()
2126     .addFieldQuotedString("name", pd->name());
2127     
2128   SectionInfo *si = Doxygen::sectionDict->find(pd->name());
2129   if (si)
2130     m_output.addFieldQuotedString("title4", filterTitle(si->title));
2131
2132   addPerlModDocBlock(m_output,"detailed",pd->docFile(),pd->docLine(),0,0,pd->documentation());
2133   m_output.closeHash();
2134 }
2135
2136 bool PerlModGenerator::generatePerlModOutput()
2137 {
2138   QFile outputFile;
2139   if (!createOutputFile(outputFile, pathDoxyDocsPM))
2140     return false;
2141   
2142   FTextStream outputTextStream(&outputFile);
2143   PerlModOutputStream outputStream(&outputTextStream);
2144   m_output.setPerlModOutputStream(&outputStream);
2145   m_output.add("$doxydocs=").openHash();
2146   
2147   m_output.openList("classes");
2148   ClassSDict::Iterator cli(*Doxygen::classSDict);
2149   ClassDef *cd;
2150   for (cli.toFirst();(cd=cli.current());++cli)
2151     generatePerlModForClass(cd);
2152   m_output.closeList();
2153
2154   m_output.openList("namespaces");
2155   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
2156   NamespaceDef *nd;
2157   for (nli.toFirst();(nd=nli.current());++nli)
2158     generatePerlModForNamespace(nd);
2159   m_output.closeList();
2160
2161   m_output.openList("files");
2162   FileNameListIterator fnli(*Doxygen::inputNameList);
2163   FileName *fn;
2164   for (;(fn=fnli.current());++fnli)
2165   {
2166     FileNameIterator fni(*fn);
2167     FileDef *fd;
2168     for (;(fd=fni.current());++fni)
2169       generatePerlModForFile(fd);
2170   }
2171   m_output.closeList();
2172
2173   m_output.openList("groups");
2174   GroupSDict::Iterator gli(*Doxygen::groupSDict);
2175   GroupDef *gd;
2176   for (;(gd=gli.current());++gli)
2177   {
2178     generatePerlModForGroup(gd);
2179   }
2180   m_output.closeList();
2181
2182   m_output.openList("pages");
2183   PageSDict::Iterator pdi(*Doxygen::pageSDict);
2184   PageDef *pd=0;
2185   for (pdi.toFirst();(pd=pdi.current());++pdi)
2186   {
2187     generatePerlModForPage(pd);
2188   }
2189   if (Doxygen::mainPage)
2190   {
2191     generatePerlModForPage(Doxygen::mainPage);
2192   }
2193   m_output.closeList();
2194
2195   m_output.closeHash().add(";\n1;\n");
2196   return true;
2197 }
2198
2199 bool PerlModGenerator::createOutputFile(QFile &f, const char *s)
2200 {
2201   f.setName(s);
2202   if (!f.open(IO_WriteOnly))
2203   {
2204     err("Cannot open file %s for writing!\n", s);
2205     return false;
2206   }
2207   return true;
2208 }
2209
2210 bool PerlModGenerator::createOutputDir(QDir &perlModDir)
2211 {
2212   QCString outputDirectory = Config_getString("OUTPUT_DIRECTORY");
2213   if (outputDirectory.isEmpty())
2214   {
2215     outputDirectory=QDir::currentDirPath().utf8();
2216   }
2217   else
2218   {
2219     QDir dir(outputDirectory);
2220     if (!dir.exists())
2221     {
2222       dir.setPath(QDir::currentDirPath());
2223       if (!dir.mkdir(outputDirectory))
2224       {
2225         err("tag OUTPUT_DIRECTORY: Output directory `%s' does not "
2226             "exist and cannot be created\n",outputDirectory.data());
2227         exit(1);
2228       }
2229       else
2230       {
2231         msg("Notice: Output directory `%s' does not exist. "
2232             "I have created it for you.\n", outputDirectory.data());
2233       }
2234       dir.cd(outputDirectory);
2235     }
2236     outputDirectory=dir.absPath().utf8();
2237   }
2238
2239   QDir dir(outputDirectory);
2240   if (!dir.exists())
2241   {
2242     dir.setPath(QDir::currentDirPath());
2243     if (!dir.mkdir(outputDirectory))
2244     {
2245       err("Cannot create directory %s\n",outputDirectory.data());
2246       return false;
2247     }
2248   }
2249  
2250   perlModDir.setPath(outputDirectory+"/perlmod");
2251   if (!perlModDir.exists() && !perlModDir.mkdir(outputDirectory+"/perlmod"))
2252   {
2253     err("Could not create perlmod directory in %s\n",outputDirectory.data());
2254     return false;
2255   }
2256   return true;
2257 }
2258
2259 bool PerlModGenerator::generateDoxyStructurePM()
2260 {
2261   QFile doxyModelPM;
2262   if (!createOutputFile(doxyModelPM, pathDoxyStructurePM))
2263     return false;
2264
2265   FTextStream doxyModelPMStream(&doxyModelPM);
2266   doxyModelPMStream << 
2267     "sub memberlist($) {\n"
2268     "    my $prefix = $_[0];\n"
2269     "    return\n"
2270     "\t[ \"hash\", $prefix . \"s\",\n"
2271     "\t  {\n"
2272     "\t    members =>\n"
2273     "\t      [ \"list\", $prefix . \"List\",\n"
2274     "\t\t[ \"hash\", $prefix,\n"
2275     "\t\t  {\n"
2276     "\t\t    kind => [ \"string\", $prefix . \"Kind\" ],\n"
2277     "\t\t    name => [ \"string\", $prefix . \"Name\" ],\n"
2278     "\t\t    static => [ \"string\", $prefix . \"Static\" ],\n"
2279     "\t\t    virtualness => [ \"string\", $prefix . \"Virtualness\" ],\n"
2280     "\t\t    protection => [ \"string\", $prefix . \"Protection\" ],\n"
2281     "\t\t    type => [ \"string\", $prefix . \"Type\" ],\n"
2282     "\t\t    parameters =>\n"
2283     "\t\t      [ \"list\", $prefix . \"Params\",\n"
2284     "\t\t\t[ \"hash\", $prefix . \"Param\",\n"
2285     "\t\t\t  {\n"
2286     "\t\t\t    declaration_name => [ \"string\", $prefix . \"ParamName\" ],\n"
2287     "\t\t\t    type => [ \"string\", $prefix . \"ParamType\" ],\n"
2288     "\t\t\t  },\n"
2289     "\t\t\t],\n"
2290     "\t\t      ],\n"
2291     "\t\t    detailed =>\n"
2292     "\t\t      [ \"hash\", $prefix . \"Detailed\",\n"
2293     "\t\t\t{\n"
2294     "\t\t\t  doc => [ \"doc\", $prefix . \"DetailedDoc\" ],\n"
2295     "\t\t\t  return => [ \"doc\", $prefix . \"Return\" ],\n"
2296     "\t\t\t  see => [ \"doc\", $prefix . \"See\" ],\n"
2297     "\t\t\t  params =>\n"
2298     "\t\t\t    [ \"list\", $prefix . \"PDBlocks\",\n"
2299     "\t\t\t      [ \"hash\", $prefix . \"PDBlock\",\n"
2300     "\t\t\t\t{\n"
2301     "\t\t\t\t  parameters =>\n"
2302     "\t\t\t\t    [ \"list\", $prefix . \"PDParams\",\n"
2303     "\t\t\t\t      [ \"hash\", $prefix . \"PDParam\",\n"
2304     "\t\t\t\t\t{\n"
2305     "\t\t\t\t\t  name => [ \"string\", $prefix . \"PDParamName\" ],\n"
2306     "\t\t\t\t\t},\n"
2307     "\t\t\t\t      ],\n"
2308     "\t\t\t\t    ],\n"
2309     "\t\t\t\t  doc => [ \"doc\", $prefix . \"PDDoc\" ],\n"
2310     "\t\t\t\t},\n"
2311     "\t\t\t      ],\n"
2312     "\t\t\t    ],\n"
2313     "\t\t\t},\n"
2314     "\t\t      ],\n"
2315     "\t\t  },\n"
2316     "\t\t],\n"
2317     "\t      ],\n"
2318     "\t  },\n"
2319     "\t];\n"
2320     "}\n"
2321     "\n"
2322     "$doxystructure =\n"
2323     "    [ \"hash\", \"Root\",\n"
2324     "      {\n"
2325     "\tfiles =>\n"
2326     "\t  [ \"list\", \"Files\",\n"
2327     "\t    [ \"hash\", \"File\",\n"
2328     "\t      {\n"
2329     "\t\tname => [ \"string\", \"FileName\" ],\n"
2330     "\t\ttypedefs => memberlist(\"FileTypedef\"),\n"
2331     "\t\tvariables => memberlist(\"FileVariable\"),\n"
2332     "\t\tfunctions => memberlist(\"FileFunction\"),\n"
2333     "\t\tdetailed =>\n"
2334     "\t\t  [ \"hash\", \"FileDetailed\",\n"
2335     "\t\t    {\n"
2336     "\t\t      doc => [ \"doc\", \"FileDetailedDoc\" ],\n"
2337     "\t\t    },\n"
2338     "\t\t  ],\n"
2339     "\t      },\n"
2340     "\t    ],\n"
2341     "\t  ],\n"
2342     "\tpages =>\n"
2343     "\t  [ \"list\", \"Pages\",\n"
2344     "\t    [ \"hash\", \"Page\",\n"
2345     "\t      {\n"
2346     "\t\tname => [ \"string\", \"PageName\" ],\n"
2347     "\t\tdetailed =>\n"
2348     "\t\t  [ \"hash\", \"PageDetailed\",\n"
2349     "\t\t    {\n"
2350     "\t\t      doc => [ \"doc\", \"PageDetailedDoc\" ],\n"
2351     "\t\t    },\n"
2352     "\t\t  ],\n"
2353     "\t      },\n"
2354     "\t    ],\n"
2355     "\t  ],\n"
2356     "\tclasses =>\n"
2357     "\t  [ \"list\", \"Classes\",\n"
2358     "\t    [ \"hash\", \"Class\",\n"
2359     "\t      {\n"
2360     "\t\tname => [ \"string\", \"ClassName\" ],\n"
2361     "\t\tpublic_typedefs => memberlist(\"ClassPublicTypedef\"),\n"
2362     "\t\tpublic_methods => memberlist(\"ClassPublicMethod\"),\n"
2363     "\t\tpublic_members => memberlist(\"ClassPublicMember\"),\n"
2364     "\t\tprotected_typedefs => memberlist(\"ClassProtectedTypedef\"),\n"
2365     "\t\tprotected_methods => memberlist(\"ClassProtectedMethod\"),\n"
2366     "\t\tprotected_members => memberlist(\"ClassProtectedMember\"),\n"
2367     "\t\tprivate_typedefs => memberlist(\"ClassPrivateTypedef\"),\n"
2368     "\t\tprivate_methods => memberlist(\"ClassPrivateMethod\"),\n"
2369     "\t\tprivate_members => memberlist(\"ClassPrivateMember\"),\n"
2370     "\t\tdetailed =>\n"
2371     "\t\t  [ \"hash\", \"ClassDetailed\",\n"
2372     "\t\t    {\n"
2373     "\t\t      doc => [ \"doc\", \"ClassDetailedDoc\" ],\n"
2374     "\t\t    },\n"
2375     "\t\t  ],\n"
2376     "\t      },\n"
2377     "\t    ],\n"
2378     "\t  ],\n"
2379     "\tgroups =>\n"
2380     "\t  [ \"list\", \"Groups\",\n"
2381     "\t    [ \"hash\", \"Group\",\n"
2382     "\t      {\n"
2383     "\t\tname => [ \"string\", \"GroupName\" ],\n"
2384     "\t\ttitle => [ \"string\", \"GroupTitle\" ],\n"
2385     "\t\tfiles =>\n"
2386     "\t\t  [ \"list\", \"Files\",\n"
2387     "\t\t    [ \"hash\", \"File\",\n"
2388     "\t\t      {\n"
2389     "\t\t        name => [ \"string\", \"Filename\" ]\n"
2390     "\t\t      }\n"
2391     "\t\t    ],\n"
2392     "\t\t  ],\n"
2393     "\t\tclasses  =>\n"
2394     "\t\t  [ \"list\", \"Classes\",\n"
2395     "\t\t    [ \"hash\", \"Class\",\n"
2396     "\t\t      {\n" 
2397     "\t\t        name => [ \"string\", \"Classname\" ]\n"
2398     "\t\t      }\n"
2399     "\t\t    ],\n"
2400     "\t\t  ],\n"
2401     "\t\tnamespaces =>\n"
2402     "\t\t  [ \"list\", \"Namespaces\",\n"
2403     "\t\t    [ \"hash\", \"Namespace\",\n"
2404     "\t\t      {\n" 
2405     "\t\t        name => [ \"string\", \"NamespaceName\" ]\n"
2406     "\t\t      }\n"
2407     "\t\t    ],\n"
2408     "\t\t  ],\n"
2409     "\t\tpages =>\n"
2410     "\t\t  [ \"list\", \"Pages\",\n"
2411     "\t\t    [ \"hash\", \"Page\","
2412     "\t\t      {\n"
2413     "\t\t        title => [ \"string\", \"PageName\" ]\n"
2414     "\t\t      }\n"
2415     "\t\t    ],\n"
2416     "\t\t  ],\n"
2417     "\t\tgroups =>\n"
2418     "\t\t  [ \"list\", \"Groups\",\n"
2419     "\t\t    [ \"hash\", \"Group\",\n"
2420     "\t\t      {\n"
2421     "\t\t        title => [ \"string\", \"GroupName\" ]\n"
2422     "\t\t      }\n"
2423     "\t\t    ],\n"
2424     "\t\t  ],\n"
2425     "\t\tfunctions => memberlist(\"GroupFunction\"),\n"
2426     "\t\tdetailed =>\n"
2427     "\t\t  [ \"hash\", \"GroupDetailed\",\n"
2428     "\t\t    {\n"
2429     "\t\t      doc => [ \"doc\", \"GroupDetailedDoc\" ],\n"
2430     "\t\t    },\n"
2431     "\t\t  ],\n"
2432     "\t      }\n"
2433     "\t    ],\n"
2434     "\t  ],\n"
2435     "      },\n"
2436     "    ];\n"
2437     "\n"
2438     "1;\n";
2439
2440   return true;
2441 }
2442
2443 bool PerlModGenerator::generateDoxyRules()
2444 {
2445   QFile doxyRules;
2446   if (!createOutputFile(doxyRules, pathDoxyRules))
2447     return false;
2448
2449   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
2450   QCString prefix = Config_getString("PERLMOD_MAKEVAR_PREFIX");
2451
2452   FTextStream doxyRulesStream(&doxyRules);
2453   doxyRulesStream <<
2454     prefix << "DOXY_EXEC_PATH = " << pathDoxyExec << "\n" <<
2455     prefix << "DOXYFILE = " << pathDoxyfile << "\n" <<
2456     prefix << "DOXYDOCS_PM = " << pathDoxyDocsPM << "\n" <<
2457     prefix << "DOXYSTRUCTURE_PM = " << pathDoxyStructurePM << "\n" <<
2458     prefix << "DOXYRULES = " << pathDoxyRules << "\n";
2459   if (perlmodLatex)
2460     doxyRulesStream <<
2461       prefix << "DOXYLATEX_PL = " << pathDoxyLatexPL << "\n" <<
2462       prefix << "DOXYLATEXSTRUCTURE_PL = " << pathDoxyLatexStructurePL << "\n" <<
2463       prefix << "DOXYSTRUCTURE_TEX = " << pathDoxyStructureTex << "\n" <<
2464       prefix << "DOXYDOCS_TEX = " << pathDoxyDocsTex << "\n" <<
2465       prefix << "DOXYFORMAT_TEX = " << pathDoxyFormatTex << "\n" <<
2466       prefix << "DOXYLATEX_TEX = " << pathDoxyLatexTex << "\n" <<
2467       prefix << "DOXYLATEX_DVI = " << pathDoxyLatexDVI << "\n" <<
2468       prefix << "DOXYLATEX_PDF = " << pathDoxyLatexPDF << "\n";
2469
2470   doxyRulesStream <<
2471     "\n"
2472     ".PHONY: clean-perlmod\n"
2473     "clean-perlmod::\n"
2474     "\trm -f $(" << prefix << "DOXYSTRUCTURE_PM) \\\n"
2475     "\t$(" << prefix << "DOXYDOCS_PM)";
2476   if (perlmodLatex)
2477     doxyRulesStream <<
2478       " \\\n"
2479       "\t$(" << prefix << "DOXYLATEX_PL) \\\n"
2480       "\t$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
2481       "\t$(" << prefix << "DOXYDOCS_TEX) \\\n"
2482       "\t$(" << prefix << "DOXYSTRUCTURE_TEX) \\\n"
2483       "\t$(" << prefix << "DOXYFORMAT_TEX) \\\n"
2484       "\t$(" << prefix << "DOXYLATEX_TEX) \\\n"
2485       "\t$(" << prefix << "DOXYLATEX_PDF) \\\n"
2486       "\t$(" << prefix << "DOXYLATEX_DVI) \\\n"
2487       "\t$(addprefix $(" << prefix << "DOXYLATEX_TEX:tex=),out aux log)";
2488   doxyRulesStream << "\n\n";
2489
2490   doxyRulesStream <<
2491     "$(" << prefix << "DOXYRULES) \\\n"
2492     "$(" << prefix << "DOXYMAKEFILE) \\\n"
2493     "$(" << prefix << "DOXYSTRUCTURE_PM) \\\n"
2494     "$(" << prefix << "DOXYDOCS_PM)";
2495   if (perlmodLatex) {
2496     doxyRulesStream <<
2497       " \\\n"
2498       "$(" << prefix << "DOXYLATEX_PL) \\\n"
2499       "$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
2500       "$(" << prefix << "DOXYFORMAT_TEX) \\\n"
2501       "$(" << prefix << "DOXYLATEX_TEX)";
2502   }
2503   doxyRulesStream <<
2504     ": \\\n"
2505     "\t$(" << prefix << "DOXYFILE)\n"
2506     "\tcd $(" << prefix << "DOXY_EXEC_PATH) ; doxygen \"$<\"\n";
2507
2508   if (perlmodLatex) {
2509     doxyRulesStream <<
2510       "\n"
2511       "$(" << prefix << "DOXYDOCS_TEX): \\\n"
2512       "$(" << prefix << "DOXYLATEX_PL) \\\n"
2513       "$(" << prefix << "DOXYDOCS_PM)\n"
2514       "\tperl -I\"$(<D)\" \"$<\" >\"$@\"\n"
2515       "\n"
2516       "$(" << prefix << "DOXYSTRUCTURE_TEX): \\\n"
2517       "$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
2518       "$(" << prefix << "DOXYSTRUCTURE_PM)\n"
2519       "\tperl -I\"$(<D)\" \"$<\" >\"$@\"\n"
2520       "\n"
2521       "$(" << prefix << "DOXYLATEX_PDF) \\\n"
2522       "$(" << prefix << "DOXYLATEX_DVI): \\\n"
2523       "$(" << prefix << "DOXYLATEX_TEX) \\\n"
2524       "$(" << prefix << "DOXYFORMAT_TEX) \\\n"
2525       "$(" << prefix << "DOXYSTRUCTURE_TEX) \\\n"
2526       "$(" << prefix << "DOXYDOCS_TEX)\n"
2527       "\n"
2528       "$(" << prefix << "DOXYLATEX_PDF): \\\n"
2529       "$(" << prefix << "DOXYLATEX_TEX)\n"
2530       "\tpdflatex -interaction=nonstopmode \"$<\"\n"
2531       "\n"
2532       "$(" << prefix << "DOXYLATEX_DVI): \\\n"
2533       "$(" << prefix << "DOXYLATEX_TEX)\n"
2534       "\tlatex -interaction=nonstopmode \"$<\"\n";
2535   }
2536
2537   return true;
2538 }
2539
2540 bool PerlModGenerator::generateMakefile()
2541 {
2542   QFile makefile;
2543   if (!createOutputFile(makefile, pathMakefile))
2544     return false;
2545
2546   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
2547   QCString prefix = Config_getString("PERLMOD_MAKEVAR_PREFIX");
2548
2549   FTextStream makefileStream(&makefile);
2550   makefileStream <<
2551     ".PHONY: default clean" << (perlmodLatex ? " pdf" : "") << "\n"
2552     "default: " << (perlmodLatex ? "pdf" : "clean") << "\n"
2553     "\n"
2554     "include " << pathDoxyRules << "\n"
2555     "\n"
2556     "clean: clean-perlmod\n";
2557
2558   if (perlmodLatex) {
2559     makefileStream <<
2560       "pdf: $(" << prefix << "DOXYLATEX_PDF)\n"
2561       "dvi: $(" << prefix << "DOXYLATEX_DVI)\n";
2562   }
2563
2564   return true;
2565 }
2566
2567 bool PerlModGenerator::generateDoxyLatexStructurePL()
2568 {
2569   QFile doxyLatexStructurePL;
2570   if (!createOutputFile(doxyLatexStructurePL, pathDoxyLatexStructurePL))
2571     return false;
2572
2573   FTextStream doxyLatexStructurePLStream(&doxyLatexStructurePL);
2574   doxyLatexStructurePLStream << 
2575     "use DoxyStructure;\n"
2576     "\n"
2577     "sub process($) {\n"
2578     "\tmy $node = $_[0];\n"
2579     "\tmy ($type, $name) = @$node[0, 1];\n"
2580     "\tmy $command;\n"
2581     "\tif ($type eq \"string\") { $command = \"String\" }\n"
2582     "\telsif ($type eq \"doc\") { $command = \"Doc\" }\n"
2583     "\telsif ($type eq \"hash\") {\n"
2584     "\t\t$command = \"Hash\";\n"
2585     "\t\tfor my $subnode (values %{$$node[2]}) {\n"
2586     "\t\t\tprocess($subnode);\n"
2587     "\t\t}\n"
2588     "\t}\n"
2589     "\telsif ($type eq \"list\") {\n"
2590     "\t\t$command = \"List\";\n"
2591     "\t\tprocess($$node[2]);\n"
2592     "\t}\n"
2593     "\tprint \"\\\\\" . $command . \"Node{\" . $name . \"}%\\n\";\n"
2594     "}\n"
2595     "\n"
2596     "process($doxystructure);\n";
2597
2598   return true;
2599 }
2600
2601 bool PerlModGenerator::generateDoxyLatexPL()
2602 {
2603   QFile doxyLatexPL;
2604   if (!createOutputFile(doxyLatexPL, pathDoxyLatexPL))
2605     return false;
2606
2607   FTextStream doxyLatexPLStream(&doxyLatexPL);
2608   doxyLatexPLStream << 
2609     "use DoxyStructure;\n"
2610     "use DoxyDocs;\n"
2611     "\n"
2612     "sub latex_quote($) {\n"
2613     "\tmy $text = $_[0];\n"
2614     "\t$text =~ s/\\\\/\\\\textbackslash /g;\n"
2615     "\t$text =~ s/\\|/\\\\textbar /g;\n"
2616     "\t$text =~ s/</\\\\textless /g;\n"
2617     "\t$text =~ s/>/\\\\textgreater /g;\n"
2618     "\t$text =~ s/~/\\\\textasciitilde /g;\n"
2619     "\t$text =~ s/\\^/\\\\textasciicircum /g;\n"
2620     "\t$text =~ s/[\\$&%#_{}]/\\\\$&/g;\n"
2621     "\tprint $text;\n"
2622     "}\n"
2623     "\n"
2624     "sub generate_doc($) {\n"
2625     "\tmy $doc = $_[0];\n"
2626     "\tfor my $item (@$doc) {\n"
2627     "\t\tmy $type = $$item{type};\n"
2628     "\t\tif ($type eq \"text\") {\n"
2629     "\t\t\tlatex_quote($$item{content});\n"
2630     "\t\t} elsif ($type eq \"parbreak\") {\n"
2631     "\t\t\tprint \"\\n\\n\";\n"
2632     "\t\t} elsif ($type eq \"style\") {\n"
2633     "\t\t\tmy $style = $$item{style};\n"
2634     "\t\t\tif ($$item{enable} eq \"yes\") {\n"
2635     "\t\t\t\tif ($style eq \"bold\") { print '\\bfseries'; }\n"
2636     "\t\t\t\tif ($style eq \"italic\") { print '\\itshape'; }\n"
2637     "\t\t\t\tif ($style eq \"code\") { print '\\ttfamily'; }\n"
2638     "\t\t\t} else {\n"
2639     "\t\t\t\tif ($style eq \"bold\") { print '\\mdseries'; }\n"
2640     "\t\t\t\tif ($style eq \"italic\") { print '\\upshape'; }\n"
2641     "\t\t\t\tif ($style eq \"code\") { print '\\rmfamily'; }\n"
2642     "\t\t\t}\n"
2643     "\t\t\tprint '{}';\n"
2644     "\t\t} elsif ($type eq \"symbol\") {\n"
2645     "\t\t\tmy $symbol = $$item{symbol};\n"
2646     "\t\t\tif ($symbol eq \"copyright\") { print '\\copyright'; }\n"
2647     "\t\t\telsif ($symbol eq \"szlig\") { print '\\ss'; }\n"
2648     "\t\t\tprint '{}';\n"
2649     "\t\t} elsif ($type eq \"accent\") {\n"
2650     "\t\t\tmy ($accent) = $$item{accent};\n"
2651     "\t\t\tif ($accent eq \"umlaut\") { print '\\\"'; }\n"
2652     "\t\t\telsif ($accent eq \"acute\") { print '\\\\\\''; }\n"
2653     "\t\t\telsif ($accent eq \"grave\") { print '\\`'; }\n"
2654     "\t\t\telsif ($accent eq \"circ\") { print '\\^'; }\n"
2655     "\t\t\telsif ($accent eq \"tilde\") { print '\\~'; }\n"
2656     "\t\t\telsif ($accent eq \"cedilla\") { print '\\c'; }\n"
2657     "\t\t\telsif ($accent eq \"ring\") { print '\\r'; }\n"
2658     "\t\t\tprint \"{\" . $$item{letter} . \"}\"; \n"
2659     "\t\t} elsif ($type eq \"list\") {\n"
2660     "\t\t\tmy $env = ($$item{style} eq \"ordered\") ? \"enumerate\" : \"itemize\";\n"
2661     "\t\t\tprint \"\\n\\\\begin{\" . $env .\"}\";\n"
2662     "\t\t  \tfor my $subitem (@{$$item{content}}) {\n"
2663     "\t\t\t\tprint \"\\n\\\\item \";\n"
2664     "\t\t\t\tgenerate_doc($subitem);\n"
2665     "\t\t  \t}\n"
2666     "\t\t\tprint \"\\n\\\\end{\" . $env .\"}\";\n"
2667     "\t\t} elsif ($type eq \"url\") {\n"
2668     "\t\t\tlatex_quote($$item{content});\n"
2669     "\t\t}\n"
2670     "\t}\n"
2671     "}\n"
2672     "\n"
2673     "sub generate($$) {\n"
2674     "\tmy ($item, $node) = @_;\n"
2675     "\tmy ($type, $name) = @$node[0, 1];\n"
2676     "\tif ($type eq \"string\") {\n"
2677     "\t\tprint \"\\\\\" . $name . \"{\";\n"
2678     "\t\tlatex_quote($item);\n"
2679     "\t\tprint \"}\";\n"
2680     "\t} elsif ($type eq \"doc\") {\n"
2681     "\t\tif (@$item) {\n"
2682     "\t\t\tprint \"\\\\\" . $name . \"{\";\n"
2683     "\t\t\tgenerate_doc($item);\n"
2684     "\t\t\tprint \"}%\\n\";\n"
2685     "\t\t} else {\n"
2686     "#\t\t\tprint \"\\\\\" . $name . \"Empty%\\n\";\n"
2687     "\t\t}\n"
2688     "\t} elsif ($type eq \"hash\") {\n"
2689     "\t\tmy ($key, $value);\n"
2690     "\t\twhile (($key, $subnode) = each %{$$node[2]}) {\n"
2691     "\t\t\tmy $subname = $$subnode[1];\n"
2692     "\t\t\tprint \"\\\\Defcs{field\" . $subname . \"}{\";\n"
2693     "\t\t\tif ($$item{$key}) {\n"
2694     "\t\t\t\tgenerate($$item{$key}, $subnode);\n"
2695     "\t\t\t} else {\n"
2696     "#\t\t\t\t\tprint \"\\\\\" . $subname . \"Empty%\\n\";\n"
2697     "\t\t\t}\n"
2698     "\t\t\tprint \"}%\\n\";\n"
2699     "\t\t}\n"
2700     "\t\tprint \"\\\\\" . $name . \"%\\n\";\n"
2701     "\t} elsif ($type eq \"list\") {\n"
2702     "\t\tmy $index = 0;\n"
2703     "\t\tif (@$item) {\n"
2704     "\t\t\tprint \"\\\\\" . $name . \"{%\\n\";\n"
2705     "\t\t\tfor my $subitem (@$item) {\n"
2706     "\t\t\t\tif ($index) {\n"
2707     "\t\t\t\t\tprint \"\\\\\" . $name . \"Sep%\\n\";\n"
2708     "\t\t\t\t}\n"
2709     "\t\t\t\tgenerate($subitem, $$node[2]);\n"
2710     "\t\t\t\t$index++;\n"
2711     "\t\t\t}\n"
2712     "\t\t\tprint \"}%\\n\";\n"
2713     "\t\t} else {\n"
2714     "#\t\t\tprint \"\\\\\" . $name . \"Empty%\\n\";\n"
2715     "\t\t}\n"
2716     "\t}\n"
2717     "}\n"
2718     "\n"
2719     "generate($doxydocs, $doxystructure);\n";
2720
2721   return true;
2722 }
2723
2724 bool PerlModGenerator::generateDoxyFormatTex()
2725 {
2726   QFile doxyFormatTex;
2727   if (!createOutputFile(doxyFormatTex, pathDoxyFormatTex))
2728     return false;
2729
2730   FTextStream doxyFormatTexStream(&doxyFormatTex);
2731   doxyFormatTexStream << 
2732     "\\def\\Defcs#1{\\long\\expandafter\\def\\csname#1\\endcsname}\n"
2733     "\\Defcs{Empty}{}\n"
2734     "\\def\\IfEmpty#1{\\expandafter\\ifx\\csname#1\\endcsname\\Empty}\n"
2735     "\n"
2736     "\\def\\StringNode#1{\\Defcs{#1}##1{##1}}\n"
2737     "\\def\\DocNode#1{\\Defcs{#1}##1{##1}}\n"
2738     "\\def\\ListNode#1{\\Defcs{#1}##1{##1}\\Defcs{#1Sep}{}}\n"
2739     "\\def\\HashNode#1{\\Defcs{#1}{}}\n"
2740     "\n"
2741     "\\input{" << pathDoxyStructureTex << "}\n"
2742     "\n"
2743     "\\newbox\\BoxA\n"
2744     "\\dimendef\\DimenA=151\\relax\n"
2745     "\\dimendef\\DimenB=152\\relax\n"
2746     "\\countdef\\ZoneDepth=151\\relax\n"
2747     "\n"
2748     "\\def\\Cs#1{\\csname#1\\endcsname}\n"
2749     "\\def\\Letcs#1{\\expandafter\\let\\csname#1\\endcsname}\n"
2750     "\\def\\Heading#1{\\vskip 4mm\\relax\\textbf{#1}}\n"
2751     "\\def\\See#1{\\begin{flushleft}\\Heading{See also: }#1\\end{flushleft}}\n"
2752     "\n"
2753     "\\def\\Frame#1{\\vskip 3mm\\relax\\fbox{ \\vbox{\\hsize0.95\\hsize\\vskip 1mm\\relax\n"
2754     "\\raggedright#1\\vskip 0.5mm\\relax} }}\n"
2755     "\n"
2756     "\\def\\Zone#1#2#3{%\n"
2757     "\\Defcs{Test#1}{#2}%\n"
2758     "\\Defcs{Emit#1}{#3}%\n"
2759     "\\Defcs{#1}{%\n"
2760     "\\advance\\ZoneDepth1\\relax\n"
2761     "\\Letcs{Mode\\number\\ZoneDepth}0\\relax\n"
2762     "\\Letcs{Present\\number\\ZoneDepth}0\\relax\n"
2763     "\\Cs{Test#1}\n"
2764     "\\expandafter\\if\\Cs{Present\\number\\ZoneDepth}1%\n"
2765     "\\advance\\ZoneDepth-1\\relax\n"
2766     "\\Letcs{Present\\number\\ZoneDepth}1\\relax\n"
2767     "\\expandafter\\if\\Cs{Mode\\number\\ZoneDepth}1%\n"
2768     "\\advance\\ZoneDepth1\\relax\n"
2769     "\\Letcs{Mode\\number\\ZoneDepth}1\\relax\n"
2770     "\\Cs{Emit#1}\n"
2771     "\\advance\\ZoneDepth-1\\relax\\fi\n"
2772     "\\advance\\ZoneDepth1\\relax\\fi\n"
2773     "\\advance\\ZoneDepth-1\\relax}}\n"
2774     "\n"
2775     "\\def\\Member#1#2{%\n"
2776     "\\Defcs{Test#1}{\\Cs{field#1Detailed}\n"
2777     "\\IfEmpty{field#1DetailedDoc}\\else\\Letcs{Present#1}1\\fi}\n"
2778     "\\Defcs{#1}{\\Letcs{Present#1}0\\relax\n"
2779     "\\Cs{Test#1}\\if1\\Cs{Present#1}\\Letcs{Present\\number\\ZoneDepth}1\\relax\n"
2780     "\\if1\\Cs{Mode\\number\\ZoneDepth}#2\\fi\\fi}}\n"
2781     "\n"
2782     "\\def\\TypedefMemberList#1#2{%\n"
2783     "\\Defcs{#1DetailedDoc}##1{\\vskip 5.5mm\\relax##1}%\n"
2784     "\\Defcs{#1Name}##1{\\textbf{##1}}%\n"
2785     "\\Defcs{#1See}##1{\\See{##1}}%\n"
2786     "%\n"
2787     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
2788     "\\Member{#1}{\\Frame{typedef \\Cs{field#1Type} \\Cs{field#1Name}}%\n"
2789     "\\Cs{field#1DetailedDoc}\\Cs{field#1See}\\vskip 5mm\\relax}}%\n"
2790     "\n"
2791     "\\def\\VariableMemberList#1#2{%\n"
2792     "\\Defcs{#1DetailedDoc}##1{\\vskip 5.5mm\\relax##1}%\n"
2793     "\\Defcs{#1Name}##1{\\textbf{##1}}%\n"
2794     "\\Defcs{#1See}##1{\\See{##1}}%\n"
2795     "%\n"
2796     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
2797     "\\Member{#1}{\\Frame{\\Cs{field#1Type}{} \\Cs{field#1Name}}%\n"
2798     "\\Cs{field#1DetailedDoc}\\Cs{field#1See}\\vskip 5mm\\relax}}%\n"
2799     "\n"
2800     "\\def\\FunctionMemberList#1#2{%\n"
2801     "\\Defcs{#1PDParamName}##1{\\textit{##1}}%\n"
2802     "\\Defcs{#1PDParam}{\\Cs{field#1PDParamName}}%\n"
2803     "\\Defcs{#1PDParamsSep}{, }%\n"
2804     "\\Defcs{#1PDBlocksSep}{\\vskip 2mm\\relax}%\n"
2805     "%\n"
2806     "\\Defcs{#1PDBlocks}##1{%\n"
2807     "\\Heading{Parameters:}\\vskip 1.5mm\\relax\n"
2808     "\\DimenA0pt\\relax\n"
2809     "\\Defcs{#1PDBlock}{\\setbox\\BoxA\\hbox{\\Cs{field#1PDParams}}%\n"
2810     "\\ifdim\\DimenA<\\wd\\BoxA\\DimenA\\wd\\BoxA\\fi}%\n"
2811     "##1%\n"
2812     "\\advance\\DimenA3mm\\relax\n"
2813     "\\DimenB\\hsize\\advance\\DimenB-\\DimenA\\relax\n"
2814     "\\Defcs{#1PDBlock}{\\hbox to\\hsize{\\vtop{\\hsize\\DimenA\\relax\n"
2815     "\\Cs{field#1PDParams}}\\hfill\n"
2816     "\\vtop{\\hsize\\DimenB\\relax\\Cs{field#1PDDoc}}}}%\n"
2817     "##1}\n"
2818     "\n"
2819     "\\Defcs{#1ParamName}##1{\\textit{##1}}\n"
2820     "\\Defcs{#1Param}{\\Cs{field#1ParamType}{} \\Cs{field#1ParamName}}\n"
2821     "\\Defcs{#1ParamsSep}{, }\n"
2822     "\n"
2823     "\\Defcs{#1Name}##1{\\textbf{##1}}\n"
2824     "\\Defcs{#1See}##1{\\See{##1}}\n"
2825     "\\Defcs{#1Return}##1{\\Heading{Returns: }##1}\n"
2826     "\\Defcs{field#1Title}{\\Frame{\\Cs{field#1Type}{} \\Cs{field#1Name}(\\Cs{field#1Params})}}%\n"
2827     "%\n"
2828     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
2829     "\\Member{#1}{%\n"
2830     "\\Cs{field#1Title}\\vskip 6mm\\relax\\Cs{field#1DetailedDoc}\n"
2831     "\\Cs{field#1Return}\\Cs{field#1PDBlocks}\\Cs{field#1See}\\vskip 5mm\\relax}}\n"
2832     "\n"
2833     "\\def\\FileDetailed{\\fieldFileDetailedDoc\\par}\n"
2834     "\\def\\ClassDetailed{\\fieldClassDetailedDoc\\par}\n"
2835     "\n"
2836     "\\def\\FileSubzones{\\fieldFileTypedefs\\fieldFileVariables\\fieldFileFunctions}\n"
2837     "\n"
2838     "\\def\\ClassSubzones{%\n"
2839     "\\fieldClassPublicTypedefs\\fieldClassPublicMembers\\fieldClassPublicMethods\n"
2840     "\\fieldClassProtectedTypedefs\\fieldClassProtectedMembers\\fieldClassProtectedMethods\n"
2841     "\\fieldClassPrivateTypedefs\\fieldClassPrivateMembers\\fieldClassPrivateMethods}\n"
2842     "\n"
2843     "\\Member{Page}{\\subsection{\\fieldPageName}\\fieldPageDetailedDoc}\n"
2844     "\n"
2845     "\\TypedefMemberList{FileTypedef}{Typedefs}\n"
2846     "\\VariableMemberList{FileVariable}{Variables}\n"
2847     "\\FunctionMemberList{FileFunction}{Functions}\n"
2848     "\\Zone{File}{\\FileSubzones}{\\subsection{\\fieldFileName}\\fieldFileDetailed\\FileSubzones}\n"
2849     "\n"
2850     "\\TypedefMemberList{ClassPublicTypedef}{Public Typedefs}\n"
2851     "\\TypedefMemberList{ClassProtectedTypedef}{Protected Typedefs}\n"
2852     "\\TypedefMemberList{ClassPrivateTypedef}{Private Typedefs}\n"
2853     "\\VariableMemberList{ClassPublicMember}{Public Members}\n"
2854     "\\VariableMemberList{ClassProtectedMember}{Protected Members}\n"
2855     "\\VariableMemberList{ClassPrivateMember}{Private Members}\n"
2856     "\\FunctionMemberList{ClassPublicMethod}{Public Methods}\n"
2857     "\\FunctionMemberList{ClassProtectedMethod}{Protected Methods}\n"
2858     "\\FunctionMemberList{ClassPrivateMethod}{Private Methods}\n"
2859     "\\Zone{Class}{\\ClassSubzones}{\\subsection{\\fieldClassName}\\fieldClassDetailed\\ClassSubzones}\n"
2860     "\n"
2861     "\\Zone{AllPages}{\\fieldPages}{\\section{Pages}\\fieldPages}\n"
2862     "\\Zone{AllFiles}{\\fieldFiles}{\\section{Files}\\fieldFiles}\n"
2863     "\\Zone{AllClasses}{\\fieldClasses}{\\section{Classes}\\fieldClasses}\n"
2864     "\n"
2865     "\\newlength{\\oldparskip}\n"
2866     "\\newlength{\\oldparindent}\n"
2867     "\\newlength{\\oldfboxrule}\n"
2868     "\n"
2869     "\\ZoneDepth0\\relax\n"
2870     "\\Letcs{Mode0}1\\relax\n"
2871     "\n"
2872     "\\def\\EmitDoxyDocs{%\n"
2873     "\\setlength{\\oldparskip}{\\parskip}\n"
2874     "\\setlength{\\oldparindent}{\\parindent}\n"
2875     "\\setlength{\\oldfboxrule}{\\fboxrule}\n"
2876     "\\setlength{\\parskip}{0cm}\n"
2877     "\\setlength{\\parindent}{0cm}\n"
2878     "\\setlength{\\fboxrule}{1pt}\n"
2879     "\\AllPages\\AllFiles\\AllClasses\n"
2880     "\\setlength{\\parskip}{\\oldparskip}\n"
2881     "\\setlength{\\parindent}{\\oldparindent}\n"
2882     "\\setlength{\\fboxrule}{\\oldfboxrule}}\n";
2883
2884   return true;
2885 }
2886
2887 bool PerlModGenerator::generateDoxyLatexTex()
2888 {
2889   QFile doxyLatexTex;
2890   if (!createOutputFile(doxyLatexTex, pathDoxyLatexTex))
2891     return false;
2892
2893   FTextStream doxyLatexTexStream(&doxyLatexTex);
2894   doxyLatexTexStream <<
2895     "\\documentclass[a4paper,12pt]{article}\n"
2896     "\\usepackage[latin1]{inputenc}\n"
2897     "\\usepackage[none]{hyphenat}\n"
2898     "\\usepackage[T1]{fontenc}\n"
2899     "\\usepackage{hyperref}\n"
2900     "\\usepackage{times}\n"
2901     "\n"
2902     "\\input{doxyformat}\n"
2903     "\n"
2904     "\\begin{document}\n"
2905     "\\input{" << pathDoxyDocsTex << "}\n"
2906     "\\sloppy\n"
2907     "\\EmitDoxyDocs\n"
2908     "\\end{document}\n";
2909
2910   return true;
2911 }
2912
2913 void PerlModGenerator::generate()
2914 {
2915   // + classes
2916   // + namespaces
2917   // + files
2918   // - packages
2919   // + groups
2920   // + related pages
2921   // - examples
2922
2923   QDir perlModDir;
2924   if (!createOutputDir(perlModDir))
2925     return;
2926
2927   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
2928
2929   QCString perlModAbsPath = perlModDir.absPath().utf8();
2930   pathDoxyDocsPM = perlModAbsPath + "/DoxyDocs.pm";
2931   pathDoxyStructurePM = perlModAbsPath + "/DoxyStructure.pm";
2932   pathMakefile = perlModAbsPath + "/Makefile";
2933   pathDoxyRules = perlModAbsPath + "/doxyrules.make";
2934
2935   if (perlmodLatex) {
2936     pathDoxyStructureTex = perlModAbsPath + "/doxystructure.tex";
2937     pathDoxyFormatTex = perlModAbsPath + "/doxyformat.tex";
2938     pathDoxyLatexTex = perlModAbsPath + "/doxylatex.tex";
2939     pathDoxyLatexDVI = perlModAbsPath + "/doxylatex.dvi";
2940     pathDoxyLatexPDF = perlModAbsPath + "/doxylatex.pdf";
2941     pathDoxyDocsTex = perlModAbsPath + "/doxydocs.tex";
2942     pathDoxyLatexPL = perlModAbsPath + "/doxylatex.pl";
2943     pathDoxyLatexStructurePL = perlModAbsPath + "/doxylatex-structure.pl";
2944   }
2945
2946   if (!(generatePerlModOutput()
2947         && generateDoxyStructurePM()
2948         && generateMakefile()
2949         && generateDoxyRules()))
2950     return;
2951
2952   if (perlmodLatex) {
2953     if (!(generateDoxyLatexStructurePL()
2954           && generateDoxyLatexPL()
2955           && generateDoxyLatexTex()
2956           && generateDoxyFormatTex()))
2957       return;
2958   }
2959 }
2960
2961 void generatePerlMod()
2962 {
2963   PerlModGenerator pmg(Config_getBool("PERLMOD_PRETTY"));
2964   pmg.generate();
2965 }
2966
2967 // Local Variables:
2968 // c-basic-offset: 2
2969 // End:
2970
2971 /* This elisp function for XEmacs makes Control-Z transform
2972    the text in the region into a valid C string.
2973
2974   (global-set-key '(control z) (lambda () (interactive)
2975    (save-excursion
2976     (if (< (mark) (point)) (exchange-point-and-mark))
2977     (let ((start (point)) (replacers 
2978      '(("\\\\" "\\\\\\\\")
2979        ("\"" "\\\\\"")
2980        ("\t" "\\\\t")
2981        ("^.*$" "\"\\&\\\\n\""))))
2982      (while replacers   
2983       (while (re-search-forward (caar replacers) (mark) t)
2984        (replace-match (cadar replacers) t))
2985       (goto-char start)
2986       (setq replacers (cdr replacers)))))))
2987 */