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