perlmodgen.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *
00004  *
00005  *
00006  * Copyright (C) 1997-2008 by Dimitri van Heesch.
00007  * Authors: Dimitri van Heesch, Miguel Lobo.
00008  *
00009  * Permission to use, copy, modify, and distribute this software and its
00010  * documentation under the terms of the GNU General Public License is hereby
00011  * granted. No representations are made about the suitability of this software
00012  * for any purpose. It is provided "as is" without express or implied warranty.
00013  * See the GNU General Public License for more details.
00014  *
00015  * Documents produced by Doxygen are derivative works derived from the
00016  * input used in their production; they are not affected by this license.
00017  *
00018  */
00019 
00020 #include <stdlib.h>
00021 
00022 #include "perlmodgen.h"
00023 #include "docparser.h"
00024 #include "message.h"
00025 #include "doxygen.h"
00026 #include "pagedef.h"
00027 
00028 #include <qdir.h>
00029 #include <qstack.h>
00030 #include <qdict.h>
00031 #include <qfile.h>
00032 #include <qtextstream.h>
00033 
00034 #define PERLOUTPUT_MAX_INDENTATION 40
00035 
00036 class PerlModOutputStream
00037 {
00038 public:
00039 
00040   QString m_s;
00041   QTextStream *m_t;
00042 
00043   PerlModOutputStream(QTextStream *t = 0) : m_t(t) { }
00044 
00045   void add(char c);
00046   void add(const char *s);
00047   void add(QCString &s);
00048   void add(QString &s);
00049   void add(int n);
00050   void add(unsigned int n);
00051 };
00052 
00053 void PerlModOutputStream::add(char c)
00054 {
00055   if (m_t != 0)
00056     (*m_t) << c;
00057   else
00058     m_s += c;
00059 }
00060 
00061 void PerlModOutputStream::add(const char *s)
00062 {
00063   if (m_t != 0)
00064     (*m_t) << s;
00065   else
00066     m_s += s;
00067 }
00068 
00069 void PerlModOutputStream::add(QCString &s)
00070 {
00071   if (m_t != 0)
00072     (*m_t) << s;
00073   else
00074     m_s += s;
00075 }
00076 
00077 void PerlModOutputStream::add(QString &s)
00078 {
00079   if (m_t != 0)
00080     (*m_t) << s;
00081   else
00082     m_s += s;
00083 }
00084 
00085 void PerlModOutputStream::add(int n)
00086 {
00087   if (m_t != 0)
00088     (*m_t) << n;
00089   else
00090     m_s += n;
00091 }
00092 
00093 void PerlModOutputStream::add(unsigned int n)
00094 {
00095   if (m_t != 0)
00096     (*m_t) << n;
00097   else
00098     m_s += n;
00099 }
00100 
00101 class PerlModOutput
00102 {
00103 public:
00104 
00105   bool m_pretty;
00106 
00107   inline PerlModOutput(bool pretty)
00108     : m_pretty(pretty), m_stream(0), m_indentation(false), m_blockstart(true)
00109   {
00110     m_spaces[0] = 0;
00111   }
00112 
00113   virtual ~PerlModOutput() { }
00114 
00115   inline void setPerlModOutputStream(PerlModOutputStream *os) { m_stream = os; }
00116 
00117   inline PerlModOutput &openSave() { iopenSave(); return *this; }
00118   inline PerlModOutput &closeSave(QString &s) { icloseSave(s); return *this; }
00119 
00120   inline PerlModOutput &continueBlock()
00121   {
00122     if (m_blockstart)
00123       m_blockstart = false;
00124     else
00125       m_stream->add(',');
00126     indent();
00127     return *this;
00128   }
00129 
00130   inline PerlModOutput &add(char c) { m_stream->add(c); return *this; }
00131   inline PerlModOutput &add(const char *s) { m_stream->add(s); return *this; }
00132   inline PerlModOutput &add(QCString &s) { m_stream->add(s); return *this; }
00133   inline PerlModOutput &add(QString &s) { m_stream->add(s); return *this; }
00134   inline PerlModOutput &add(int n) { m_stream->add(n); return *this; }
00135   inline PerlModOutput &add(unsigned int n) { m_stream->add(n); return *this; }
00136 
00137   PerlModOutput &addQuoted(const char *s) { iaddQuoted(s); return *this; }
00138 
00139   inline PerlModOutput &indent()
00140   {
00141     if (m_pretty) {
00142       m_stream->add('\n');
00143       m_stream->add(m_spaces);
00144     }
00145     return *this;
00146   }
00147 
00148   inline PerlModOutput &open(char c, const char *s = 0) { iopen(c, s); return *this; }
00149   inline PerlModOutput &close(char c = 0) { iclose(c); return *this; }
00150 
00151   inline PerlModOutput &addField(const char *s) { iaddField(s); return *this; }
00152   inline PerlModOutput &addFieldQuotedChar(const char *field, char content)
00153   {
00154     iaddFieldQuotedChar(field, content); return *this;
00155   }
00156   inline PerlModOutput &addFieldQuotedString(const char *field, const char *content)
00157   {
00158     iaddFieldQuotedString(field, content); return *this;
00159   }
00160   inline PerlModOutput &addFieldBoolean(const char *field, bool content)
00161   {
00162     return addFieldQuotedString(field, content ? "yes" : "no");
00163   }
00164   inline PerlModOutput &openList(const char *s = 0) { open('[', s); return *this; }
00165   inline PerlModOutput &closeList() { close(']'); return *this; }
00166   inline PerlModOutput &openHash(const char *s = 0 ) { open('{', s); return *this; }
00167   inline PerlModOutput &closeHash() { close('}'); return *this; }
00168 
00169 protected:
00170   
00171   void iopenSave();
00172   void icloseSave(QString &);
00173   
00174   void incIndent();
00175   void decIndent();
00176 
00177   void iaddQuoted(const char *);
00178   void iaddFieldQuotedChar(const char *, char);
00179   void iaddFieldQuotedString(const char *, const char *);
00180   void iaddField(const char *);
00181 
00182   void iopen(char, const char *);
00183   void iclose(char);
00184 
00185 private:
00186   
00187   PerlModOutputStream *m_stream;
00188   int m_indentation;
00189   bool m_blockstart;
00190 
00191   QStack<PerlModOutputStream> m_saved;
00192   char m_spaces[PERLOUTPUT_MAX_INDENTATION * 2 + 2];
00193 };
00194 
00195 void PerlModOutput::iopenSave()
00196 {
00197   m_saved.push(m_stream);
00198   m_stream = new PerlModOutputStream();
00199 }
00200 
00201 void PerlModOutput::icloseSave(QString &s)
00202 {
00203   s = m_stream->m_s;
00204   delete m_stream;
00205   m_stream = m_saved.pop();
00206 }
00207 
00208 void PerlModOutput::incIndent()
00209 {
00210   if (m_indentation < PERLOUTPUT_MAX_INDENTATION)
00211   {
00212     char *s = &m_spaces[m_indentation * 2];
00213     *s++ = ' '; *s++ = ' '; *s = 0;
00214   }
00215   m_indentation++;
00216 }
00217 
00218 void PerlModOutput::decIndent()
00219 {
00220   m_indentation--;
00221   if (m_indentation < PERLOUTPUT_MAX_INDENTATION)
00222     m_spaces[m_indentation * 2] = 0;
00223 }
00224 
00225 void PerlModOutput::iaddQuoted(const char *s) 
00226 {
00227   char c;
00228   while ((c = *s++) != 0) {
00229     if ((c == '\'') || (c == '\\'))
00230       m_stream->add('\\');
00231     m_stream->add(c);
00232   }
00233 }
00234   
00235 void PerlModOutput::iaddField(const char *s)
00236 {
00237   continueBlock();
00238   m_stream->add(s);
00239   m_stream->add(m_pretty ? " => " : "=>");
00240 }
00241 
00242 void PerlModOutput::iaddFieldQuotedChar(const char *field, char content)
00243 {
00244   iaddField(field);
00245   m_stream->add('\'');
00246   if ((content == '\'') || (content == '\\'))
00247     m_stream->add('\\');
00248   m_stream->add(content);
00249   m_stream->add('\'');
00250 }
00251 
00252 void PerlModOutput::iaddFieldQuotedString(const char *field, const char *content)
00253 {
00254   if (content == 0)
00255     return;
00256   iaddField(field);
00257   m_stream->add('\'');
00258   iaddQuoted(content);
00259   m_stream->add('\'');
00260 }
00261 
00262 void PerlModOutput::iopen(char c, const char *s)
00263 {
00264   if (s != 0)
00265     iaddField(s);
00266   else
00267     continueBlock();
00268   m_stream->add(c);
00269   incIndent();
00270   m_blockstart = true;
00271 }
00272 
00273 void PerlModOutput::iclose(char c)
00274 {
00275   decIndent(); 
00276   indent();
00277   if (c != 0)
00278     m_stream->add(c); 
00279   m_blockstart = false;
00280 }
00281 
00283 class PerlModDocVisitor : public DocVisitor
00284 {
00285 public:
00286   PerlModDocVisitor(PerlModOutput &);
00287   virtual ~PerlModDocVisitor() { }
00288 
00289   void finish();
00290   
00291   //--------------------------------------
00292   // visitor functions for leaf nodes
00293   //--------------------------------------
00294    
00295   void visit(DocWord *);
00296   void visit(DocLinkedWord *);
00297   void visit(DocWhiteSpace *);
00298   void visit(DocSymbol *);
00299   void visit(DocURL *);
00300   void visit(DocLineBreak *);
00301   void visit(DocHorRuler *);
00302   void visit(DocStyleChange *);
00303   void visit(DocVerbatim *);
00304   void visit(DocAnchor *);
00305   void visit(DocInclude *);
00306   void visit(DocIncOperator *);
00307   void visit(DocFormula *);
00308   void visit(DocIndexEntry *);
00309 
00310   //--------------------------------------
00311   // visitor functions for compound nodes
00312   //--------------------------------------
00313    
00314   void visitPre(DocAutoList *);
00315   void visitPost(DocAutoList *);
00316   void visitPre(DocAutoListItem *);
00317   void visitPost(DocAutoListItem *);
00318   void visitPre(DocPara *) ;
00319   void visitPost(DocPara *);
00320   void visitPre(DocRoot *);
00321   void visitPost(DocRoot *);
00322   void visitPre(DocSimpleSect *);
00323   void visitPost(DocSimpleSect *);
00324   void visitPre(DocTitle *);
00325   void visitPost(DocTitle *);
00326   void visitPre(DocSimpleList *);
00327   void visitPost(DocSimpleList *);
00328   void visitPre(DocSimpleListItem *);
00329   void visitPost(DocSimpleListItem *);
00330   void visitPre(DocSection *);
00331   void visitPost(DocSection *);
00332   void visitPre(DocHtmlList *);
00333   void visitPost(DocHtmlList *) ;
00334   void visitPre(DocHtmlListItem *);
00335   void visitPost(DocHtmlListItem *);
00336   //void visitPre(DocHtmlPre *);
00337   //void visitPost(DocHtmlPre *);
00338   void visitPre(DocHtmlDescList *);
00339   void visitPost(DocHtmlDescList *);
00340   void visitPre(DocHtmlDescTitle *);
00341   void visitPost(DocHtmlDescTitle *);
00342   void visitPre(DocHtmlDescData *);
00343   void visitPost(DocHtmlDescData *);
00344   void visitPre(DocHtmlTable *);
00345   void visitPost(DocHtmlTable *);
00346   void visitPre(DocHtmlRow *);
00347   void visitPost(DocHtmlRow *) ;
00348   void visitPre(DocHtmlCell *);
00349   void visitPost(DocHtmlCell *);
00350   void visitPre(DocHtmlCaption *);
00351   void visitPost(DocHtmlCaption *);
00352   void visitPre(DocInternal *);
00353   void visitPost(DocInternal *);
00354   void visitPre(DocHRef *);
00355   void visitPost(DocHRef *);
00356   void visitPre(DocHtmlHeader *);
00357   void visitPost(DocHtmlHeader *);
00358   void visitPre(DocImage *);
00359   void visitPost(DocImage *);
00360   void visitPre(DocDotFile *);
00361   void visitPost(DocDotFile *);
00362   void visitPre(DocLink *);
00363   void visitPost(DocLink *);
00364   void visitPre(DocRef *);
00365   void visitPost(DocRef *);
00366   void visitPre(DocSecRefItem *);
00367   void visitPost(DocSecRefItem *);
00368   void visitPre(DocSecRefList *);
00369   void visitPost(DocSecRefList *);
00370   //void visitPre(DocLanguage *);
00371   //void visitPost(DocLanguage *);
00372   void visitPre(DocParamSect *);
00373   void visitPost(DocParamSect *);
00374   void visitPre(DocParamList *);
00375   void visitPost(DocParamList *);
00376   void visitPre(DocXRefItem *);
00377   void visitPost(DocXRefItem *);
00378   void visitPre(DocInternalRef *);
00379   void visitPost(DocInternalRef *);
00380   void visitPre(DocCopy *);
00381   void visitPost(DocCopy *);
00382   void visitPre(DocText *);
00383   void visitPost(DocText *);
00384 
00385 private:
00386 
00387   //--------------------------------------
00388   // helper functions
00389   //--------------------------------------
00390 
00391   void addLink(const QString &ref, const QString &file,
00392                const QString &anchor);
00393    
00394   void enterText();
00395   void leaveText();
00396 
00397   void openItem(const char *);
00398   void closeItem();
00399   void singleItem(const char *);
00400   void openSubBlock(const char * = 0);
00401   void closeSubBlock();
00402   void openOther();
00403   void closeOther();
00404 
00405   //--------------------------------------
00406   // state variables
00407   //--------------------------------------
00408 
00409   PerlModOutput &m_output;
00410   bool m_textmode;
00411   bool m_textblockstart;
00412   QString m_other;
00413 };
00414 
00415 PerlModDocVisitor::PerlModDocVisitor(PerlModOutput &output)
00416   : DocVisitor(DocVisitor_Other), m_output(output), m_textmode(false)
00417 {
00418   m_output.openList("doc");
00419 }
00420 
00421 void PerlModDocVisitor::finish()
00422 {
00423   leaveText();
00424   m_output.closeList()
00425     .add(m_other);
00426 }
00427 
00428 void PerlModDocVisitor::addLink(const QString &,const QString &file,const QString &anchor)
00429 {
00430   QString link = file;
00431   if (!anchor.isEmpty())
00432     (link += "_1") += anchor;
00433   m_output.addFieldQuotedString("link", link);
00434 }
00435 
00436 void PerlModDocVisitor::openItem(const char *name)
00437 {
00438   leaveText();
00439   m_output.openHash().addFieldQuotedString("type", name);
00440 }
00441 
00442 void PerlModDocVisitor::closeItem()
00443 {
00444   leaveText();
00445   m_output.closeHash();
00446 }
00447 
00448 void PerlModDocVisitor::enterText()
00449 {
00450   if (m_textmode)
00451     return;
00452   openItem("text");
00453   m_output.addField("content").add('\'');
00454   m_textmode = true;
00455 }
00456 
00457 void PerlModDocVisitor::leaveText()
00458 {
00459   if (!m_textmode)
00460     return;
00461   m_textmode = false;
00462   m_output
00463     .add('\'')
00464     .closeHash();
00465 }
00466 
00467 void PerlModDocVisitor::singleItem(const char *name)
00468 {
00469   openItem(name);
00470   closeItem();
00471 }
00472 
00473 void PerlModDocVisitor::openSubBlock(const char *s)
00474 {
00475   m_output.openList(s);
00476   m_textblockstart = true;
00477 }
00478 
00479 void PerlModDocVisitor::closeSubBlock()
00480 {
00481   leaveText();
00482   m_output.closeList();
00483 }
00484 
00485 void PerlModDocVisitor::openOther()
00486 {
00487   // Using a secondary text stream will corrupt the perl file. Instead of
00488   // printing doc => [ data => [] ], it will print doc => [] data => [].
00489   /*
00490   leaveText();
00491   m_output.openSave();
00492   */
00493 }
00494 
00495 void PerlModDocVisitor::closeOther()
00496 {
00497   // Using a secondary text stream will corrupt the perl file. Instead of
00498   // printing doc => [ data => [] ], it will print doc => [] data => [].
00499   /*
00500   QString other;
00501   leaveText();
00502   m_output.closeSave(other);
00503   m_other += other;
00504   */
00505 }
00506 
00507 void PerlModDocVisitor::visit(DocWord *w)
00508 {
00509   enterText();
00510   m_output.addQuoted(w->word());
00511 }
00512 
00513 void PerlModDocVisitor::visit(DocLinkedWord *w)
00514 {
00515   openItem("url");
00516   addLink(w->ref(), w->file(), w->anchor());
00517   m_output.addFieldQuotedString("content", w->word());
00518   closeItem();
00519 }
00520 
00521 void PerlModDocVisitor::visit(DocWhiteSpace *)
00522 {
00523   enterText();
00524   m_output.add(' ');
00525 }
00526 
00527 void PerlModDocVisitor::visit(DocSymbol *sy)
00528 {
00529   char c = 0;
00530   const char *s = 0;
00531   const char *accent = 0;
00532   const char *symbol = 0;
00533   switch(sy->symbol())
00534   {
00535   case DocSymbol::At:      c = '@'; break;
00536   case DocSymbol::Less:    c = '<'; break;
00537   case DocSymbol::Greater: c = '>'; break;
00538   case DocSymbol::Amp:     c = '&'; break;
00539   case DocSymbol::Dollar:  c = '$'; break;
00540   case DocSymbol::Hash:    c = '#'; break;
00541   case DocSymbol::Percent: c = '%'; break;
00542   case DocSymbol::Quot:    c = '"'; break;
00543   case DocSymbol::Lsquo:   s = "\\\'"; break;
00544   case DocSymbol::Rsquo:   s = "\\\'"; break;
00545   case DocSymbol::Ldquo:   c = '"'; break;
00546   case DocSymbol::Rdquo:   c = '"'; break;
00547   case DocSymbol::Ndash:   c = '-'; break;
00548   case DocSymbol::Mdash:   s = "--"; break;
00549   case DocSymbol::Nbsp:    c = ''; break;
00550   case DocSymbol::Uml:     accent = "umlaut"; break;
00551   case DocSymbol::Acute:   accent = "acute"; break;
00552   case DocSymbol::Grave:   accent = "grave"; break;
00553   case DocSymbol::Circ:    accent = "circ"; break;
00554   case DocSymbol::Slash:   accent = "slash"; break;
00555   case DocSymbol::Tilde:   accent = "tilde"; break;
00556   case DocSymbol::Cedil:   accent = "cedilla"; break;
00557   case DocSymbol::Ring:    accent = "ring"; break;
00558   case DocSymbol::BSlash:  s = "\\\\"; break;
00559   case DocSymbol::Copy:    symbol = "copyright"; break;
00560   case DocSymbol::Tm:      symbol = "trademark"; break;
00561   case DocSymbol::Reg:     symbol = "registered"; break;
00562   case DocSymbol::Szlig:   symbol = "szlig"; break;
00563   case DocSymbol::Apos:    s = "\\\'"; break;
00564   case DocSymbol::Unknown:
00565     err("Error: unknown symbol found\n");
00566     break;
00567   }
00568   if (c != 0) {
00569     enterText();
00570     m_output.add(c);
00571   } else if (s != 0) {
00572     enterText();
00573     m_output.add(s);
00574   } else if (symbol != 0) {
00575     leaveText();
00576     openItem("symbol");
00577     m_output.addFieldQuotedString("symbol", symbol);
00578     closeItem();
00579   } else if (accent != 0) {
00580     leaveText();
00581     openItem("accent");
00582     m_output
00583       .addFieldQuotedString("accent", accent)
00584       .addFieldQuotedChar("letter", sy->letter());
00585     closeItem();
00586   }
00587 }
00588 
00589 void PerlModDocVisitor::visit(DocURL *u)
00590 {
00591   openItem("url");
00592   m_output.addFieldQuotedString("content", u->url());
00593   closeItem();
00594 }
00595 
00596 void PerlModDocVisitor::visit(DocLineBreak *) { singleItem("linebreak"); }
00597 void PerlModDocVisitor::visit(DocHorRuler *) { singleItem("hruler"); }
00598 
00599 void PerlModDocVisitor::visit(DocStyleChange *s)
00600 {
00601   const char *style = 0;
00602   switch (s->style())
00603   {
00604     case DocStyleChange::Bold:          style = "bold"; break;
00605     case DocStyleChange::Italic:        style = "italic"; break;
00606     case DocStyleChange::Code:          style = "code"; break;
00607     case DocStyleChange::Subscript:     style = "subscript"; break;
00608     case DocStyleChange::Superscript:   style = "superscript"; break;
00609     case DocStyleChange::Center:        style = "center"; break;
00610     case DocStyleChange::Small:         style = "small"; break;
00611     case DocStyleChange::Preformatted:  style = "preformatted"; break;
00612     case DocStyleChange::Div:           style = "div"; break;
00613     case DocStyleChange::Span:          style = "span"; break;
00614                                         
00615   }
00616   openItem("style");
00617   m_output.addFieldQuotedString("style", style)
00618     .addFieldBoolean("enable", s->enable());
00619   closeItem();
00620 }
00621 
00622 void PerlModDocVisitor::visit(DocVerbatim *s)
00623 {
00624   const char *type = 0;
00625   switch(s->type())
00626   {
00627   case DocVerbatim::Code:
00628 #if 0
00629     m_output.add("<programlisting>");
00630     parseCode(m_ci,s->context(),s->text(),FALSE,0);
00631     m_output.add("</programlisting>");
00632 #endif
00633     return;
00634   case DocVerbatim::Verbatim:   type = "preformatted"; break;
00635   case DocVerbatim::HtmlOnly:   type = "htmlonly"; break;
00636   case DocVerbatim::ManOnly:    type = "manonly"; break;
00637   case DocVerbatim::LatexOnly:  type = "latexonly"; break;
00638   case DocVerbatim::XmlOnly:    type = "xmlonly"; break;
00639   case DocVerbatim::Dot:        type = "dot"; break;
00640   case DocVerbatim::Msc:        type = "msc"; break;
00641   }
00642   openItem(type);
00643   m_output.addFieldQuotedString("content", s->text());
00644   closeItem();
00645 }
00646 
00647 void PerlModDocVisitor::visit(DocAnchor *anc)
00648 {
00649   QString anchor = anc->file() + "_1" + anc->anchor();
00650   openItem("anchor");
00651   m_output.addFieldQuotedString("id", anchor);
00652   closeItem();
00653 }
00654 
00655 void PerlModDocVisitor::visit(DocInclude *inc)
00656 {
00657   const char *type = 0;
00658   switch(inc->type())
00659   {
00660   case DocInclude::IncWithLines:
00661   #if 0
00662       { 
00663          m_t << "<div class=\"fragment\"><pre>";
00664          QFileInfo cfi( inc->file() );
00665          FileDef fd( cfi.dirPath(), cfi.fileName() );
00666          parseCode(m_ci,inc->context(),inc->text().latin1(),inc->isExample(),inc->exampleFile(), &fd);
00667          m_t << "</pre></div>"; 
00668       }
00669       break;
00670   #endif
00671     return;
00672   case DocInclude::Include:
00673 #if 0
00674     m_output.add("<programlisting>");
00675     parseCode(m_ci,inc->context(),inc->text(),FALSE,0);
00676     m_output.add("</programlisting>");
00677 #endif
00678     return;
00679   case DocInclude::DontInclude: return;
00680   case DocInclude::HtmlInclude: type = "htmlonly"; break;
00681   case DocInclude::VerbInclude: type = "preformatted"; break;
00682   }
00683   openItem(type);
00684   m_output.addFieldQuotedString("content", inc->text());
00685   closeItem();
00686 }
00687 
00688 void PerlModDocVisitor::visit(DocIncOperator *)
00689 {
00690 #if 0
00691   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
00692   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
00693   if (op->isFirst())
00694   {
00695     m_output.add("<programlisting>");
00696   }
00697   if (op->type()!=DocIncOperator::Skip)
00698   {
00699     parseCode(m_ci,op->context(),op->text(),FALSE,0);
00700   }
00701   if (op->isLast()) 
00702   {
00703     m_output.add("</programlisting>");
00704   }
00705   else
00706   {
00707     m_output.add('\n');
00708   }
00709 #endif
00710 }
00711 
00712 void PerlModDocVisitor::visit(DocFormula *f)
00713 {
00714   openItem("formula");
00715   QString id;
00716   id += f->id();
00717   m_output.addFieldQuotedString("id", id).addFieldQuotedString("content", f->text());
00718   closeItem();
00719 }
00720 
00721 void PerlModDocVisitor::visit(DocIndexEntry *)
00722 {
00723 #if 0
00724   m_output.add("<indexentry>"
00725                "<primaryie>");
00726   m_output.addQuoted(ie->entry());
00727   m_output.add("</primaryie>"
00728                "<secondaryie></secondaryie>"
00729                "</indexentry>");
00730 #endif
00731 }
00732 
00733 //--------------------------------------
00734 // visitor functions for compound nodes
00735 //--------------------------------------
00736 
00737 void PerlModDocVisitor::visitPre(DocAutoList *l)
00738 {
00739   openItem("list");
00740   m_output.addFieldQuotedString("style", l->isEnumList() ? "ordered" : "itemized");
00741   openSubBlock("content");
00742 }
00743 
00744 void PerlModDocVisitor::visitPost(DocAutoList *)
00745 {
00746   closeSubBlock();
00747   closeItem();
00748 }
00749 
00750 void PerlModDocVisitor::visitPre(DocAutoListItem *)
00751 {
00752   openSubBlock();
00753 }
00754 
00755 void PerlModDocVisitor::visitPost(DocAutoListItem *)
00756 {
00757   closeSubBlock();
00758 }
00759 
00760 void PerlModDocVisitor::visitPre(DocPara *)
00761 {
00762   if (m_textblockstart)
00763     m_textblockstart = false;
00764   else
00765     singleItem("parbreak");
00766   /*
00767   openItem("para");
00768   openSubBlock("content");
00769   */
00770 }
00771 
00772 void PerlModDocVisitor::visitPost(DocPara *)
00773 {
00774   /*
00775   closeSubBlock();
00776   closeItem();
00777   */
00778 }
00779 
00780 void PerlModDocVisitor::visitPre(DocRoot *)
00781 {
00782 }
00783 
00784 void PerlModDocVisitor::visitPost(DocRoot *)
00785 {
00786 }
00787 
00788 void PerlModDocVisitor::visitPre(DocSimpleSect *s)
00789 {
00790   const char *type = 0;
00791   switch (s->type())
00792   {
00793   case DocSimpleSect::See:              type = "see"; break;
00794   case DocSimpleSect::Return:           type = "return"; break;
00795   case DocSimpleSect::Author:           type = "author"; break;
00796   case DocSimpleSect::Authors:          type = "authors"; break;
00797   case DocSimpleSect::Version:          type = "version"; break;
00798   case DocSimpleSect::Since:            type = "since"; break;
00799   case DocSimpleSect::Date:             type = "date"; break;
00800   case DocSimpleSect::Note:             type = "bug"; break;
00801   case DocSimpleSect::Warning:          type = "warning"; break;
00802   case DocSimpleSect::Pre:              type = "pre"; break;
00803   case DocSimpleSect::Post:             type = "post"; break;
00804   case DocSimpleSect::Invar:            type = "invariant"; break;
00805   case DocSimpleSect::Remark:           type = "remark"; break;
00806   case DocSimpleSect::Attention:        type = "attention"; break;
00807   case DocSimpleSect::User:             type = "par"; break;
00808   case DocSimpleSect::Rcs:              type = "rcs"; break;
00809   case DocSimpleSect::Unknown:
00810     err("Error: unknown simple section found\n");
00811     break;
00812   }
00813   openOther();
00814   openSubBlock(type);
00815 }
00816 
00817 void PerlModDocVisitor::visitPost(DocSimpleSect *)
00818 {
00819   closeSubBlock();
00820   closeOther();
00821 }
00822 
00823 void PerlModDocVisitor::visitPre(DocTitle *)
00824 {
00825   openItem("title");
00826   openSubBlock("content");
00827 }
00828 
00829 void PerlModDocVisitor::visitPost(DocTitle *)
00830 {
00831   closeSubBlock();
00832   closeItem();
00833 }
00834 
00835 void PerlModDocVisitor::visitPre(DocSimpleList *) 
00836 {
00837   openItem("list");
00838   m_output.addFieldQuotedString("style", "itemized");
00839   openSubBlock("content");
00840 }
00841 
00842 void PerlModDocVisitor::visitPost(DocSimpleList *)
00843 {
00844   closeSubBlock();
00845   closeItem();
00846 }
00847 
00848 void PerlModDocVisitor::visitPre(DocSimpleListItem *) { openSubBlock(); }
00849 void PerlModDocVisitor::visitPost(DocSimpleListItem *) { closeSubBlock(); }
00850 
00851 void PerlModDocVisitor::visitPre(DocSection *s)
00852 {
00853   QString sect = QString("sect%1").arg(s->level());
00854   openItem(sect);
00855   openSubBlock("content");
00856 }
00857 
00858 void PerlModDocVisitor::visitPost(DocSection *)
00859 {
00860   closeSubBlock();
00861   closeItem();
00862 }
00863 
00864 void PerlModDocVisitor::visitPre(DocHtmlList *l)
00865 {
00866   openItem("list");
00867   m_output.addFieldQuotedString("style", (l->type() == DocHtmlList::Ordered) ? "ordered" : "itemized");
00868   openSubBlock("content");
00869 }
00870 
00871 void PerlModDocVisitor::visitPost(DocHtmlList *)
00872 {
00873   closeSubBlock();
00874   closeItem();
00875 }
00876 
00877 void PerlModDocVisitor::visitPre(DocHtmlListItem *) { openSubBlock(); }
00878 void PerlModDocVisitor::visitPost(DocHtmlListItem *) { closeSubBlock(); }
00879 
00880 //void PerlModDocVisitor::visitPre(DocHtmlPre *)
00881 //{
00882 //  openItem("preformatted");
00883 //  openSubBlock("content");
00884 //  //m_insidePre=TRUE;
00885 //}
00886 
00887 //void PerlModDocVisitor::visitPost(DocHtmlPre *)
00888 //{
00889 //  //m_insidePre=FALSE;
00890 //  closeSubBlock();
00891 //  closeItem();
00892 //}
00893 
00894 void PerlModDocVisitor::visitPre(DocHtmlDescList *)
00895 {
00896 #if 0
00897   m_output.add("<variablelist>\n");
00898 #endif
00899 }
00900 
00901 void PerlModDocVisitor::visitPost(DocHtmlDescList *)
00902 {
00903 #if 0
00904   m_output.add("</variablelist>\n");
00905 #endif
00906 }
00907 
00908 void PerlModDocVisitor::visitPre(DocHtmlDescTitle *)
00909 {
00910 #if 0
00911   m_output.add("<varlistentry><term>");
00912 #endif
00913 }
00914 
00915 void PerlModDocVisitor::visitPost(DocHtmlDescTitle *)
00916 {
00917 #if 0
00918   m_output.add("</term></varlistentry>\n");
00919 #endif
00920 }
00921 
00922 void PerlModDocVisitor::visitPre(DocHtmlDescData *)
00923 {
00924 #if 0
00925   m_output.add("<listitem>");
00926 #endif
00927 }
00928 
00929 void PerlModDocVisitor::visitPost(DocHtmlDescData *)
00930 {
00931 #if 0
00932   m_output.add("</listitem>\n");
00933 #endif
00934 }
00935 
00936 void PerlModDocVisitor::visitPre(DocHtmlTable *)
00937 {
00938 #if 0
00939   m_output.add("<table rows=\""); m_output.add(t->numRows());
00940   m_output.add("\" cols=\""); m_output.add(t->numCols()); m_output.add("\">");
00941 #endif
00942 }
00943 
00944 void PerlModDocVisitor::visitPost(DocHtmlTable *)
00945 {
00946 #if 0
00947   m_output.add("</table>\n");
00948 #endif
00949 }
00950 
00951 void PerlModDocVisitor::visitPre(DocHtmlRow *)
00952 {
00953 #if 0
00954   m_output.add("<row>\n");
00955 #endif
00956 }
00957 
00958 void PerlModDocVisitor::visitPost(DocHtmlRow *)
00959 {
00960 #if 0
00961   m_output.add("</row>\n");
00962 #endif
00963 }
00964 
00965 void PerlModDocVisitor::visitPre(DocHtmlCell *)
00966 {
00967 #if 0
00968   if (c->isHeading()) m_output.add("<entry thead=\"yes\">"); else m_output.add("<entry thead=\"no\">");
00969 #endif
00970 }
00971 
00972 void PerlModDocVisitor::visitPost(DocHtmlCell *)
00973 {
00974 #if 0
00975   m_output.add("</entry>");
00976 #endif
00977 }
00978 
00979 void PerlModDocVisitor::visitPre(DocHtmlCaption *)
00980 {
00981 #if 0
00982   m_output.add("<caption>");
00983 #endif
00984 }
00985 
00986 void PerlModDocVisitor::visitPost(DocHtmlCaption *)
00987 {
00988 #if 0
00989   m_output.add("</caption>\n");
00990 #endif
00991 }
00992 
00993 void PerlModDocVisitor::visitPre(DocInternal *)
00994 {
00995 #if 0
00996   m_output.add("<internal>");
00997 #endif
00998 }
00999 
01000 void PerlModDocVisitor::visitPost(DocInternal *)
01001 {
01002 #if 0
01003   m_output.add("</internal>");
01004 #endif
01005 }
01006 
01007 void PerlModDocVisitor::visitPre(DocHRef *)
01008 {
01009 #if 0
01010   m_output.add("<ulink url=\""); m_output.add(href->url()); m_output.add("\">");
01011 #endif
01012 }
01013 
01014 void PerlModDocVisitor::visitPost(DocHRef *)
01015 {
01016 #if 0
01017   m_output.add("</ulink>");
01018 #endif
01019 }
01020 
01021 void PerlModDocVisitor::visitPre(DocHtmlHeader *)
01022 {
01023 #if 0
01024   m_output.add("<sect"); m_output.add(header->level()); m_output.add(">");
01025 #endif
01026 }
01027 
01028 void PerlModDocVisitor::visitPost(DocHtmlHeader *)
01029 {
01030 #if 0
01031   m_output.add("</sect"); m_output.add(header->level()); m_output.add(">\n");
01032 #endif
01033 }
01034 
01035 void PerlModDocVisitor::visitPre(DocImage *)
01036 {
01037 #if 0
01038   m_output.add("<image type=\"");
01039   switch(img->type())
01040   {
01041   case DocImage::Html:  m_output.add("html"); break;
01042   case DocImage::Latex: m_output.add("latex"); break;
01043   case DocImage::Rtf:   m_output.add("rtf"); break;
01044   }
01045   m_output.add("\"");
01046   
01047   QCString baseName=img->name();
01048   int i;
01049   if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
01050   {
01051     baseName=baseName.right(baseName.length()-i-1);
01052   }
01053   m_output.add(" name=\""); m_output.add(baseName); m_output.add("\"");
01054   if (!img->width().isEmpty())
01055   {
01056     m_output.add(" width=\"");
01057     m_output.addQuoted(img->width());
01058     m_output.add("\"");
01059   }
01060   else if (!img->height().isEmpty())
01061   {
01062     m_output.add(" height=\"");
01063     m_output.addQuoted(img->height());
01064     m_output.add("\"");
01065   }
01066   m_output.add(">");
01067 #endif
01068 }
01069 
01070 void PerlModDocVisitor::visitPost(DocImage *)
01071 {
01072 #if 0
01073   m_output.add("</image>");
01074 #endif
01075 }
01076 
01077 void PerlModDocVisitor::visitPre(DocDotFile *)
01078 {
01079 #if 0
01080   m_output.add("<dotfile name=\""); m_output.add(df->file()); m_output.add("\">");
01081 #endif
01082 }
01083 
01084 void PerlModDocVisitor::visitPost(DocDotFile *)
01085 {
01086 #if 0
01087   m_output.add("</dotfile>");
01088 #endif
01089 }
01090 
01091 void PerlModDocVisitor::visitPre(DocLink *lnk)
01092 {
01093   openItem("link");
01094   addLink(lnk->ref(), lnk->file(), lnk->anchor());
01095 }
01096 
01097 void PerlModDocVisitor::visitPost(DocLink *)
01098 {
01099   closeItem();
01100 }
01101 
01102 void PerlModDocVisitor::visitPre(DocRef *ref)
01103 {
01104   openItem("ref");
01105   if (!ref->hasLinkText())
01106     m_output.addFieldQuotedString("text", ref->targetTitle());
01107   openSubBlock("content");
01108 }
01109 
01110 void PerlModDocVisitor::visitPost(DocRef *)
01111 {
01112   closeSubBlock();
01113   closeItem();
01114 }
01115 
01116 void PerlModDocVisitor::visitPre(DocSecRefItem *)
01117 {
01118 #if 0
01119   m_output.add("<tocitem id=\""); m_output.add(ref->file()); m_output.add("_1"); m_output.add(ref->anchor()); m_output.add("\">");
01120 #endif
01121 }
01122 
01123 void PerlModDocVisitor::visitPost(DocSecRefItem *)
01124 {
01125 #if 0
01126   m_output.add("</tocitem>");
01127 #endif
01128 }
01129 
01130 void PerlModDocVisitor::visitPre(DocSecRefList *)
01131 {
01132 #if 0
01133   m_output.add("<toclist>");
01134 #endif
01135 }
01136 
01137 void PerlModDocVisitor::visitPost(DocSecRefList *)
01138 {
01139 #if 0
01140   m_output.add("</toclist>");
01141 #endif
01142 }
01143 
01144 //void PerlModDocVisitor::visitPre(DocLanguage *l)
01145 //{
01146 //  openItem("language");
01147 //  m_output.addFieldQuotedString("id", l->id());
01148 //}
01149 //
01150 //void PerlModDocVisitor::visitPost(DocLanguage *)
01151 //{
01152 //  closeItem();
01153 //}
01154 
01155 void PerlModDocVisitor::visitPre(DocParamSect *s)
01156 {
01157   leaveText();
01158   const char *type = 0;
01159   switch(s->type())
01160   {
01161   case DocParamSect::Param:     type = "params"; break;
01162   case DocParamSect::RetVal:    type = "retvals"; break;
01163   case DocParamSect::Exception: type = "exceptions"; break;
01164   case DocParamSect::TemplateParam: type = "templateparam"; break;
01165   case DocParamSect::Unknown:
01166     err("Error: unknown parameter section found\n");
01167     break;
01168   }
01169   openOther();
01170   openSubBlock(type);
01171 }
01172 
01173 void PerlModDocVisitor::visitPost(DocParamSect *)
01174 {
01175   closeSubBlock();
01176   closeOther();
01177 }
01178 
01179 void PerlModDocVisitor::visitPre(DocParamList *pl)
01180 {
01181   leaveText();
01182   m_output.openHash()
01183     .openList("parameters");
01184   //QStrListIterator li(pl->parameters());
01185   //const char *s;
01186   QListIterator<DocNode> li(pl->parameters());
01187   DocNode *param;
01188   for (li.toFirst();(param=li.current());++li)
01189   {
01190     QCString s;
01191     if (param->kind()==DocNode::Kind_Word)
01192     {
01193       s = ((DocWord*)param)->word(); 
01194     }
01195     else if (param->kind()==DocNode::Kind_LinkedWord)
01196     {
01197       s = ((DocLinkedWord*)param)->word(); 
01198     }
01199     m_output.openHash()
01200       .addFieldQuotedString("name", s)
01201       .closeHash();
01202   }
01203   m_output.closeList()
01204     .openList("doc");
01205 }
01206 
01207 void PerlModDocVisitor::visitPost(DocParamList *)
01208 {
01209   leaveText();
01210   m_output.closeList()
01211     .closeHash();
01212 }
01213 
01214 void PerlModDocVisitor::visitPre(DocXRefItem *)
01215 {
01216 #if 0
01217   m_output.add("<xrefsect id=\"");
01218   m_output.add(x->file()); m_output.add("_1"); m_output.add(x->anchor());
01219   m_output.add("\">");
01220   m_output.add("<xreftitle>");
01221   m_output.addQuoted(x->title());
01222   m_output.add("</xreftitle>");
01223   m_output.add("<xrefdescription>");
01224 #endif
01225   openItem("xrefitem");
01226   openSubBlock("content");
01227 }
01228 
01229 void PerlModDocVisitor::visitPost(DocXRefItem *)
01230 {
01231   closeSubBlock();
01232   closeItem();
01233 #if 0
01234   m_output.add("</xrefdescription>");
01235   m_output.add("</xrefsect>");
01236 #endif
01237 }
01238 
01239 void PerlModDocVisitor::visitPre(DocInternalRef *ref)
01240 {
01241   openItem("ref");
01242   addLink(0,ref->file(),ref->anchor());
01243   openSubBlock("content");
01244 }
01245 
01246 void PerlModDocVisitor::visitPost(DocInternalRef *)
01247 {
01248   closeSubBlock();
01249   closeItem();
01250 }
01251 
01252 void PerlModDocVisitor::visitPre(DocCopy *)
01253 {
01254 }
01255 
01256 void PerlModDocVisitor::visitPost(DocCopy *)
01257 {
01258 }
01259 
01260 void PerlModDocVisitor::visitPre(DocText *)
01261 {
01262 }
01263 
01264 void PerlModDocVisitor::visitPost(DocText *)
01265 {
01266 }
01267 
01268 static void addTemplateArgumentList(ArgumentList *al,PerlModOutput &output,const char *)
01269 {
01270   QCString indentStr;
01271   if (!al)
01272     return;
01273   output.openList("template_parameters");
01274   ArgumentListIterator ali(*al);
01275   Argument *a;
01276   for (ali.toFirst();(a=ali.current());++ali)
01277   {
01278     output.openHash();
01279     if (!a->type.isEmpty())
01280       output.addFieldQuotedString("type", a->type);
01281     if (!a->name.isEmpty())
01282       output.addFieldQuotedString("declaration_name", a->name)
01283         .addFieldQuotedString("definition_name", a->name);
01284     if (!a->defval.isEmpty())
01285       output.addFieldQuotedString("default", a->defval);
01286     output.closeHash();
01287   }
01288   output.closeList();
01289 }
01290 
01291 #if 0
01292 static void addMemberTemplateLists(MemberDef *md,PerlModOutput &output)
01293 {
01294   ClassDef *cd = md->getClassDef();
01295   const char *cname = cd ? cd->name().data() : 0;
01296   if (md->templateArguments()) // function template prefix
01297     addTemplateArgumentList(md->templateArguments(),output,cname);
01298 }
01299 #endif
01300 
01301 static void addTemplateList(ClassDef *cd,PerlModOutput &output)
01302 {
01303   addTemplateArgumentList(cd->templateArguments(),output,cd->name());
01304 }
01305 
01306 static void addPerlModDocBlock(PerlModOutput &output,
01307                             const char *name,
01308                             const QCString &fileName,
01309                             int lineNr,
01310                             Definition *scope,
01311                             MemberDef *md,
01312                             const QCString &text)
01313 {
01314   QCString stext = text.stripWhiteSpace();
01315   if (stext.isEmpty())
01316     output.addField(name).add("{}");
01317   else {
01318     DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE,0);
01319     output.openHash(name);
01320     PerlModDocVisitor *visitor = new PerlModDocVisitor(output);
01321     root->accept(visitor);
01322     visitor->finish();
01323     output.closeHash();
01324     delete visitor;
01325     delete root;
01326   }
01327 }
01328 
01329 static const char *getProtectionName(Protection prot) 
01330 {
01331   switch (prot)
01332   {
01333   case Public:    return "public";
01334   case Protected: return "protected";
01335   case Private:   return "private";
01336   case Package:   return "package";
01337   }
01338   return 0;
01339 }
01340 
01341 static const char *getVirtualnessName(Specifier virt)
01342 {
01343   switch(virt)
01344   {
01345   case Normal:  return "non_virtual";
01346   case Virtual: return "virtual";
01347   case Pure:    return "pure_virtual";
01348   }
01349   return 0;
01350 }
01351 
01352 static QString pathDoxyfile;
01353 static QString pathDoxyExec;
01354 
01355 void setPerlModDoxyfile(const QString &qs)
01356 {
01357   pathDoxyfile = qs;
01358   pathDoxyExec = QDir::currentDirPath();
01359 }
01360 
01361 class PerlModGenerator
01362 {
01363 public:
01364 
01365   PerlModOutput m_output;
01366 
01367   QString pathDoxyStructurePM;
01368   QString pathDoxyDocsTex;
01369   QString pathDoxyFormatTex;
01370   QString pathDoxyLatexTex;
01371   QString pathDoxyLatexDVI;
01372   QString pathDoxyLatexPDF;
01373   QString pathDoxyStructureTex;
01374   QString pathDoxyDocsPM;
01375   QString pathDoxyLatexPL;
01376   QString pathDoxyLatexStructurePL;
01377   QString pathDoxyRules;
01378   QString pathMakefile;
01379 
01380   inline PerlModGenerator(bool pretty) : m_output(pretty) { }
01381 
01382   void generatePerlModForMember(MemberDef *md, Definition *);
01383   void generatePerlModSection(Definition *d, MemberList *ml,
01384                               const char *name, const char *header=0);
01385   void addListOfAllMembers(ClassDef *cd);
01386   void generatePerlModForClass(ClassDef *cd);
01387   void generatePerlModForNamespace(NamespaceDef *nd);
01388   void generatePerlModForFile(FileDef *fd);
01389   void generatePerlModForGroup(GroupDef *gd);
01390   void generatePerlModForPage(PageDef *pi);
01391   
01392   bool createOutputFile(QFile &f, const char *s);
01393   bool createOutputDir(QDir &perlModDir);
01394   bool generateDoxyLatexTex();
01395   bool generateDoxyFormatTex();
01396   bool generateDoxyStructurePM();
01397   bool generateDoxyLatexPL();
01398   bool generateDoxyLatexStructurePL();
01399   bool generateDoxyRules();
01400   bool generateMakefile();
01401   bool generatePerlModOutput();
01402 
01403   void generate();
01404 };
01405 
01406 void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
01407 {
01408   // + declaration/definition arg lists
01409   // + reimplements
01410   // + reimplementedBy
01411   // + exceptions
01412   // + const/volatile specifiers
01413   // - examples
01414   // - source definition
01415   // - source references
01416   // - source referenced by
01417   // - body code
01418   // - template arguments
01419   //     (templateArguments(), definitionTemplateParameterLists())
01420  
01421   QCString memType;
01422   bool isFunc=FALSE;
01423   switch (md->memberType())
01424   {
01425   case MemberDef::Define:      memType="define";    break;
01426   case MemberDef::EnumValue:   memType="enumvalue"; break;
01427   case MemberDef::Property:    memType="property";  break;
01428   case MemberDef::Variable:    memType="variable";  break;
01429   case MemberDef::Typedef:     memType="typedef";   break;
01430   case MemberDef::Enumeration: memType="enum";      break;
01431   case MemberDef::Function:    memType="function";  isFunc=TRUE; break;
01432   case MemberDef::Signal:      memType="signal";    isFunc=TRUE; break;
01433   case MemberDef::Prototype:   memType="prototype"; isFunc=TRUE; break;
01434   case MemberDef::Friend:      memType="friend";    isFunc=TRUE; break;
01435   case MemberDef::DCOP:        memType="dcop";      isFunc=TRUE; break;
01436   case MemberDef::Slot:        memType="slot";      isFunc=TRUE; break;
01437   case MemberDef::Event:       memType="event";     break;
01438   }
01439 
01440   m_output.openHash()
01441     .addFieldQuotedString("kind", memType)
01442     .addFieldQuotedString("name", md->name())
01443     .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness()))
01444     .addFieldQuotedString("protection", getProtectionName(md->protection()))
01445     .addFieldBoolean("static", md->isStatic());
01446   
01447   addPerlModDocBlock(m_output,"brief",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->briefDescription());
01448   addPerlModDocBlock(m_output,"detailed",md->getDefFileName(),md->getDefLine(),md->getOuterScope(),md,md->documentation());
01449   if (md->memberType()!=MemberDef::Define &&
01450       md->memberType()!=MemberDef::Enumeration)
01451     m_output.addFieldQuotedString("type", md->typeString());
01452   
01453   LockingPtr<ArgumentList> al = md->argumentList();
01454   if (isFunc) //function
01455   {
01456     m_output.addFieldBoolean("const", al!=0 && al->constSpecifier)
01457       .addFieldBoolean("volatile", al!=0 && al->volatileSpecifier);
01458 
01459     m_output.openList("parameters");
01460     LockingPtr<ArgumentList> declAl = md->declArgumentList();
01461     LockingPtr<ArgumentList> defAl  = md->argumentList();
01462     if (declAl!=0 && declAl->count()>0)
01463     {
01464       ArgumentListIterator declAli(*declAl);
01465       ArgumentListIterator defAli(*defAl);
01466       Argument *a;
01467       for (declAli.toFirst();(a=declAli.current());++declAli)
01468       {
01469         Argument *defArg = defAli.current();
01470         m_output.openHash();
01471 
01472         if (!a->name.isEmpty())
01473           m_output.addFieldQuotedString("declaration_name", a->name);
01474 
01475         if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
01476           m_output.addFieldQuotedString("definition_name", defArg->name);
01477 
01478         if (!a->type.isEmpty())
01479           m_output.addFieldQuotedString("type", a->type);
01480 
01481         if (!a->array.isEmpty())
01482           m_output.addFieldQuotedString("array", a->array);
01483 
01484         if (!a->defval.isEmpty())
01485           m_output.addFieldQuotedString("default_value", a->defval);
01486 
01487         if (!a->attrib.isEmpty())
01488           m_output.addFieldQuotedString("attributes", a->attrib);
01489         
01490         m_output.closeHash();
01491         if (defArg) ++defAli;
01492       }
01493     }
01494     m_output.closeList();
01495   }
01496   else if (md->memberType()==MemberDef::Define &&
01497            md->argsString()!=0) // define
01498   {
01499     m_output.openList("parameters");
01500     ArgumentListIterator ali(*al);
01501     Argument *a;
01502     for (ali.toFirst();(a=ali.current());++ali)
01503     {
01504       m_output.openHash()
01505         .addFieldQuotedString("name", a->type)
01506         .closeHash();
01507     }
01508     m_output.closeList();
01509   }
01510   if (!md->initializer().isEmpty())
01511     m_output.addFieldQuotedString("initializer", md->initializer());
01512   
01513   if (md->excpString())
01514     m_output.addFieldQuotedString("exceptions", md->excpString());
01515   
01516   if (md->memberType()==MemberDef::Enumeration) // enum
01517   {
01518     LockingPtr<MemberList> enumFields = md->enumFieldList();
01519     if (enumFields!=0)
01520     {
01521       m_output.openList("values");
01522       MemberListIterator emli(*enumFields);
01523       MemberDef *emd;
01524       for (emli.toFirst();(emd=emli.current());++emli)
01525       {
01526         m_output.openHash()
01527           .addFieldQuotedString("name", emd->name());
01528          
01529         if (!emd->initializer().isEmpty())
01530           m_output.addFieldQuotedString("initializer", emd->initializer());
01531 
01532         addPerlModDocBlock(m_output,"brief",emd->getDefFileName(),emd->getDefLine(),emd->getOuterScope(),emd,emd->briefDescription());
01533 
01534         addPerlModDocBlock(m_output,"detailed",emd->getDefFileName(),emd->getDefLine(),emd->getOuterScope(),emd,emd->documentation());
01535 
01536         m_output.closeHash();
01537       }
01538       m_output.closeList();
01539     }
01540   }
01541 
01542   MemberDef *rmd = md->reimplements();
01543   if (rmd)
01544     m_output.openHash("reimplements")
01545       .addFieldQuotedString("name", rmd->name())
01546       .closeHash();
01547 
01548   LockingPtr<MemberList> rbml = md->reimplementedBy();
01549   if (rbml!=0)
01550   {
01551     MemberListIterator mli(*rbml);
01552     m_output.openList("reimplemented_by");
01553     for (mli.toFirst();(rmd=mli.current());++mli)
01554       m_output.openHash()
01555         .addFieldQuotedString("name", rmd->name())
01556         .closeHash();
01557     m_output.closeList();
01558   }
01559   
01560   m_output.closeHash();
01561 }
01562 
01563 void PerlModGenerator::generatePerlModSection(Definition *d,
01564                                               MemberList *ml,const char *name,const char *header)
01565 {
01566   if (ml==0) return; // empty list
01567 
01568   m_output.openHash(name);
01569 
01570   if (header)
01571     m_output.addFieldQuotedString("header", header);
01572   
01573   m_output.openList("members");
01574   MemberListIterator mli(*ml);
01575   MemberDef *md;
01576   for (mli.toFirst();(md=mli.current());++mli)
01577   {
01578     generatePerlModForMember(md,d);
01579   }
01580   m_output.closeList()
01581     .closeHash();
01582 }
01583 
01584 void PerlModGenerator::addListOfAllMembers(ClassDef *cd)
01585 {
01586   m_output.openList("all_members");
01587   if (cd->memberNameInfoSDict())
01588   {
01589     MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict());
01590     MemberNameInfo *mni;
01591     for (mnii.toFirst();(mni=mnii.current());++mnii)
01592     {
01593       MemberNameInfoIterator mii(*mni);
01594       MemberInfo *mi;
01595       for (mii.toFirst();(mi=mii.current());++mii)
01596       {
01597         MemberDef *md=mi->memberDef;
01598         ClassDef  *cd=md->getClassDef();
01599         Definition *d=md->getGroupDef();
01600         if (d==0) d = cd;
01601 
01602         m_output.openHash()
01603           .addFieldQuotedString("name", md->name())
01604           .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness()))
01605           .addFieldQuotedString("protection", getProtectionName(mi->prot));
01606 
01607         if (!mi->ambiguityResolutionScope.isEmpty())
01608           m_output.addFieldQuotedString("ambiguity_scope", mi->ambiguityResolutionScope);
01609 
01610         m_output.addFieldQuotedString("scope", cd->name())
01611           .closeHash();
01612       }
01613     }
01614   }
01615   m_output.closeList();
01616 }
01617 
01618 void PerlModGenerator::generatePerlModForClass(ClassDef *cd)
01619 {
01620   // + brief description
01621   // + detailed description
01622   // + template argument list(s)
01623   // - include file
01624   // + member groups
01625   // + inheritance diagram
01626   // + list of direct super classes
01627   // + list of direct sub classes
01628   // + list of inner classes
01629   // + collaboration diagram
01630   // + list of all members
01631   // + user defined member sections
01632   // + standard member sections
01633   // + detailed member documentation
01634   // - examples using the class
01635   
01636   if (cd->isReference())        return; // skip external references.
01637   if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
01638   if (cd->templateMaster()!=0)  return; // skip generated template instances.
01639 
01640   m_output.openHash()
01641     .addFieldQuotedString("name", cd->name());
01642   
01643   if (cd->baseClasses())
01644   {
01645     m_output.openList("base");
01646     BaseClassListIterator bcli(*cd->baseClasses());
01647     BaseClassDef *bcd;
01648     for (bcli.toFirst();(bcd=bcli.current());++bcli)
01649       m_output.openHash()
01650         .addFieldQuotedString("name", bcd->classDef->displayName())
01651         .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt))
01652         .addFieldQuotedString("protection", getProtectionName(bcd->prot))
01653         .closeHash();
01654     m_output.closeList();
01655   }
01656 
01657   if (cd->subClasses())
01658   {
01659     m_output.openList("derived");
01660     BaseClassListIterator bcli(*cd->subClasses());
01661     BaseClassDef *bcd;
01662     for (bcli.toFirst();(bcd=bcli.current());++bcli)
01663       m_output.openHash()
01664         .addFieldQuotedString("name", bcd->classDef->displayName())
01665         .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt))
01666         .addFieldQuotedString("protection", getProtectionName(bcd->prot))
01667         .closeHash();
01668     m_output.closeList();
01669   }
01670 
01671   ClassSDict *cl = cd->getInnerClasses();
01672   if (cl)
01673   {
01674     m_output.openList("inner");
01675     ClassSDict::Iterator cli(*cl);
01676     ClassDef *cd;
01677     for (cli.toFirst();(cd=cli.current());++cli)
01678       m_output.openHash()
01679         .addFieldQuotedString("name", cd->name())
01680         .closeHash();
01681     m_output.closeList();
01682   }
01683 
01684   IncludeInfo *ii=cd->includeInfo();
01685   if (ii)
01686   {
01687     QCString nm = ii->includeName;
01688     if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
01689     if (!nm.isEmpty())
01690     {
01691       m_output.openHash("includes");
01692 #if 0
01693       if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
01694         t << " id=\"" << ii->fileDef->getOutputFileBase() << "\"";
01695 #endif
01696       m_output.addFieldBoolean("local", ii->local)
01697         .addFieldQuotedString("name", nm)
01698         .closeHash();
01699     }
01700   }
01701 
01702   addTemplateList(cd,m_output);
01703   addListOfAllMembers(cd);
01704   if (cd->getMemberGroupSDict())
01705   {
01706     MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
01707     MemberGroup *mg;
01708     for (;(mg=mgli.current());++mgli)
01709       generatePerlModSection(cd,mg->members(),"user_defined",mg->header());
01710   }
01711 
01712   generatePerlModSection(cd,cd->getMemberList(MemberList::pubTypes),"public_typedefs");
01713   generatePerlModSection(cd,cd->getMemberList(MemberList::pubMethods),"public_methods");
01714   generatePerlModSection(cd,cd->getMemberList(MemberList::pubAttribs),"public_members");
01715   generatePerlModSection(cd,cd->getMemberList(MemberList::pubSlots),"public_slots");
01716   generatePerlModSection(cd,cd->getMemberList(MemberList::signals),"signals");
01717   generatePerlModSection(cd,cd->getMemberList(MemberList::dcopMethods),"dcop_methods");
01718   generatePerlModSection(cd,cd->getMemberList(MemberList::properties),"properties");
01719   generatePerlModSection(cd,cd->getMemberList(MemberList::pubStaticMethods),"public_static_methods");
01720   generatePerlModSection(cd,cd->getMemberList(MemberList::pubStaticAttribs),"public_static_members");
01721   generatePerlModSection(cd,cd->getMemberList(MemberList::proTypes),"protected_typedefs");
01722   generatePerlModSection(cd,cd->getMemberList(MemberList::proMethods),"protected_methods");
01723   generatePerlModSection(cd,cd->getMemberList(MemberList::proAttribs),"protected_members");
01724   generatePerlModSection(cd,cd->getMemberList(MemberList::proSlots),"protected_slots");
01725   generatePerlModSection(cd,cd->getMemberList(MemberList::proStaticMethods),"protected_static_methods");
01726   generatePerlModSection(cd,cd->getMemberList(MemberList::proStaticAttribs),"protected_static_members");
01727   generatePerlModSection(cd,cd->getMemberList(MemberList::priTypes),"private_typedefs");
01728   generatePerlModSection(cd,cd->getMemberList(MemberList::priMethods),"private_methods");
01729   generatePerlModSection(cd,cd->getMemberList(MemberList::priAttribs),"private_members");
01730   generatePerlModSection(cd,cd->getMemberList(MemberList::priSlots),"private_slots");
01731   generatePerlModSection(cd,cd->getMemberList(MemberList::priStaticMethods),"private_static_methods");
01732   generatePerlModSection(cd,cd->getMemberList(MemberList::priStaticAttribs),"private_static_members");
01733   generatePerlModSection(cd,cd->getMemberList(MemberList::friends),"friend_methods");
01734   generatePerlModSection(cd,cd->getMemberList(MemberList::related),"related_methods");
01735 
01736   addPerlModDocBlock(m_output,"brief",cd->getDefFileName(),cd->getDefLine(),cd,0,cd->briefDescription());
01737   addPerlModDocBlock(m_output,"detailed",cd->getDefFileName(),cd->getDefLine(),cd,0,cd->documentation());
01738 
01739 #if 0
01740   DotClassGraph inheritanceGraph(cd,DotClassGraph::Inheritance);
01741   if (!inheritanceGraph.isTrivial())
01742   {
01743     t << "    <inheritancegraph>" << endl;
01744     inheritanceGraph.writePerlMod(t);
01745     t << "    </inheritancegraph>" << endl;
01746   }
01747   DotClassGraph collaborationGraph(cd,DotClassGraph::Implementation);
01748   if (!collaborationGraph.isTrivial())
01749   {
01750     t << "    <collaborationgraph>" << endl;
01751     collaborationGraph.writePerlMod(t);
01752     t << "    </collaborationgraph>" << endl;
01753   }
01754   t << "    <location file=\"" 
01755     << cd->getDefFileName() << "\" line=\"" 
01756     << cd->getDefLine() << "\"";
01757     if (cd->getStartBodyLine()!=-1)
01758     {
01759       t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" 
01760         << cd->getEndBodyLine() << "\"";
01761     }
01762   t << "/>" << endl;
01763 #endif
01764 
01765   m_output.closeHash();
01766 }
01767 
01768 void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
01769 {
01770   // + contained class definitions
01771   // + contained namespace definitions
01772   // + member groups
01773   // + normal members
01774   // + brief desc
01775   // + detailed desc
01776   // + location
01777   // - files containing (parts of) the namespace definition
01778 
01779   if (nd->isReference()) return; // skip external references
01780 
01781   m_output.openHash()
01782     .addFieldQuotedString("name", nd->name());
01783   
01784   ClassSDict *cl = nd->getClassSDict();
01785   if (cl)
01786   {
01787     m_output.openList("classes");
01788     ClassSDict::Iterator cli(*cl);
01789     ClassDef *cd;
01790     for (cli.toFirst();(cd=cli.current());++cli)
01791       m_output.openHash()
01792         .addFieldQuotedString("name", cd->name())
01793         .closeHash();
01794     m_output.closeList();
01795   }
01796 
01797   NamespaceSDict *nl = nd->getNamespaceSDict();
01798   if (nl)
01799   {
01800     m_output.openList("namespaces");
01801     NamespaceSDict::Iterator nli(*nl);
01802     NamespaceDef *nd;
01803     for (nli.toFirst();(nd=nli.current());++nli)
01804       m_output.openHash()
01805         .addFieldQuotedString("name", nd->name())
01806         .closeHash();
01807     m_output.closeList();
01808   }
01809 
01810   if (nd->getMemberGroupSDict())
01811   {
01812     MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
01813     MemberGroup *mg;
01814     for (;(mg=mgli.current());++mgli)
01815       generatePerlModSection(nd,mg->members(),"user-defined",mg->header());
01816   }
01817 
01818   generatePerlModSection(nd,nd->getMemberList(MemberList::decDefineMembers),"defines");
01819   generatePerlModSection(nd,nd->getMemberList(MemberList::decProtoMembers),"prototypes");
01820   generatePerlModSection(nd,nd->getMemberList(MemberList::decTypedefMembers),"typedefs");
01821   generatePerlModSection(nd,nd->getMemberList(MemberList::decEnumMembers),"enums");
01822   generatePerlModSection(nd,nd->getMemberList(MemberList::decFuncMembers),"functions");
01823   generatePerlModSection(nd,nd->getMemberList(MemberList::decVarMembers),"variables");
01824 
01825   addPerlModDocBlock(m_output,"brief",nd->getDefFileName(),nd->getDefLine(),0,0,nd->briefDescription());
01826   addPerlModDocBlock(m_output,"detailed",nd->getDefFileName(),nd->getDefLine(),0,0,nd->documentation());
01827 
01828   m_output.closeHash();
01829 }
01830 
01831 void PerlModGenerator::generatePerlModForFile(FileDef *fd)
01832 {
01833   // + includes files
01834   // + includedby files
01835   // - include graph
01836   // - included by graph
01837   // - contained class definitions
01838   // - contained namespace definitions
01839   // - member groups
01840   // + normal members
01841   // + brief desc
01842   // + detailed desc
01843   // - source code
01844   // - location
01845   // - number of lines
01846  
01847   if (fd->isReference()) return;
01848 
01849   m_output.openHash()
01850     .addFieldQuotedString("name", fd->name());
01851   
01852   IncludeInfo *inc;
01853   m_output.openList("includes");
01854   if (fd->includeFileList())
01855   {
01856     QListIterator<IncludeInfo> ili1(*fd->includeFileList());
01857     for (ili1.toFirst();(inc=ili1.current());++ili1)
01858     {
01859       m_output.openHash()
01860         .addFieldQuotedString("name", inc->includeName);
01861       if (inc->fileDef && !inc->fileDef->isReference())
01862       {
01863         m_output.addFieldQuotedString("ref", inc->fileDef->getOutputFileBase());
01864       }
01865       m_output.closeHash();
01866     }
01867   }
01868   m_output.closeList();
01869   
01870   m_output.openList("included_by");
01871   if (fd->includedByFileList())
01872   {
01873     QListIterator<IncludeInfo> ili2(*fd->includedByFileList());
01874     for (ili2.toFirst();(inc=ili2.current());++ili2)
01875     {
01876       m_output.openHash()
01877         .addFieldQuotedString("name", inc->includeName);
01878       if (inc->fileDef && !inc->fileDef->isReference())
01879       {
01880         m_output.addFieldQuotedString("ref", inc->fileDef->getOutputFileBase());
01881       }
01882       m_output.closeHash();
01883     }
01884   }
01885   m_output.closeList();
01886   
01887   generatePerlModSection(fd,fd->getMemberList(MemberList::decDefineMembers),"defines");
01888   generatePerlModSection(fd,fd->getMemberList(MemberList::decProtoMembers),"prototypes");
01889   generatePerlModSection(fd,fd->getMemberList(MemberList::decTypedefMembers),"typedefs");
01890   generatePerlModSection(fd,fd->getMemberList(MemberList::decEnumMembers),"enums");
01891   generatePerlModSection(fd,fd->getMemberList(MemberList::decFuncMembers),"functions");
01892   generatePerlModSection(fd,fd->getMemberList(MemberList::decVarMembers),"variables");
01893 
01894   addPerlModDocBlock(m_output,"brief",fd->getDefFileName(),fd->getDefLine(),0,0,fd->briefDescription());
01895   addPerlModDocBlock(m_output,"detailed",fd->getDefFileName(),fd->getDefLine(),0,0,fd->documentation());
01896 
01897   m_output.closeHash();
01898 }
01899 
01900 void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
01901 {
01902   // + members
01903   // + member groups
01904   // + files
01905   // + classes
01906   // + namespaces
01907   // - packages
01908   // + pages
01909   // + child groups
01910   // - examples
01911   // + brief description
01912   // + detailed description
01913 
01914   if (gd->isReference()) return; // skip external references
01915 
01916   m_output.openHash()
01917     .addFieldQuotedString("name", gd->name())
01918     .addFieldQuotedString("title", gd->groupTitle());
01919 
01920   FileList *fl = gd->getFiles();
01921   if (fl)
01922   {
01923     m_output.openList("files");
01924     QListIterator<FileDef> fli(*fl);
01925     FileDef *fd = fl->first();
01926     for (fli.toFirst();(fd=fli.current());++fli)
01927       m_output.openHash()
01928         .addFieldQuotedString("name", fd->name())
01929         .closeHash();
01930     m_output.closeList();
01931   }
01932 
01933   ClassSDict *cl = gd->getClasses();
01934   if (cl)
01935   {
01936     m_output.openList("classes");
01937     ClassSDict::Iterator cli(*cl);
01938     ClassDef *cd;
01939     for (cli.toFirst();(cd=cli.current());++cli)
01940       m_output.openHash()
01941         .addFieldQuotedString("name", cd->name())
01942         .closeHash();
01943     m_output.closeList();
01944   }
01945 
01946   NamespaceSDict *nl = gd->getNamespaces();
01947   if (nl)
01948   {
01949     m_output.openList("namespaces");
01950     NamespaceSDict::Iterator nli(*nl);
01951     NamespaceDef *nd;
01952     for (nli.toFirst();(nd=nli.current());++nli)
01953       m_output.openHash()
01954         .addFieldQuotedString("name", nd->name())
01955         .closeHash();
01956     m_output.closeList();
01957   }
01958 
01959   PageSDict *pl = gd->getPages();
01960   if (pl)
01961   {
01962     m_output.openList("pages");
01963     PageSDict::Iterator pli(*pl);
01964     PageDef *pd;
01965     for (pli.toFirst();(pd=pli.current());++pli)
01966       m_output.openHash()
01967         .addFieldQuotedString("title", pd->title())
01968         .closeHash();
01969     m_output.closeList();
01970   }
01971 
01972   GroupList *gl = gd->getSubGroups();
01973   if (gl)
01974   {
01975     m_output.openList("groups");
01976     GroupListIterator gli(*gl);
01977     GroupDef *sgd;
01978     for (gli.toFirst();(sgd=gli.current());++gli)
01979       m_output.openHash()
01980         .addFieldQuotedString("title", sgd->groupTitle())
01981         .closeHash();
01982     m_output.closeList();
01983   }
01984 
01985   if (gd->getMemberGroupSDict())
01986   {
01987     MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
01988     MemberGroup *mg;
01989     for (;(mg=mgli.current());++mgli)
01990       generatePerlModSection(gd,mg->members(),"user-defined",mg->header());
01991   }
01992 
01993   generatePerlModSection(gd,gd->getMemberList(MemberList::decDefineMembers),"defines");
01994   generatePerlModSection(gd,gd->getMemberList(MemberList::decProtoMembers),"prototypes");
01995   generatePerlModSection(gd,gd->getMemberList(MemberList::decTypedefMembers),"typedefs");
01996   generatePerlModSection(gd,gd->getMemberList(MemberList::decEnumMembers),"enums");
01997   generatePerlModSection(gd,gd->getMemberList(MemberList::decFuncMembers),"functions");
01998   generatePerlModSection(gd,gd->getMemberList(MemberList::decVarMembers),"variables");
01999 
02000   addPerlModDocBlock(m_output,"brief",gd->getDefFileName(),gd->getDefLine(),0,0,gd->briefDescription());
02001   addPerlModDocBlock(m_output,"detailed",gd->getDefFileName(),gd->getDefLine(),0,0,gd->documentation());
02002 
02003   m_output.closeHash();
02004 }
02005 
02006 void PerlModGenerator::generatePerlModForPage(PageDef *pd)
02007 {
02008   // + name
02009   // + title
02010   // + documentation
02011 
02012   if (pd->isReference()) return;
02013 
02014   m_output.openHash()
02015     .addFieldQuotedString("name", pd->name());
02016     
02017   SectionInfo *si = Doxygen::sectionDict.find(pd->name());
02018   if (si)
02019     m_output.addFieldQuotedString("title", si->title);
02020 
02021   addPerlModDocBlock(m_output,"detailed",pd->docFile(),pd->docLine(),0,0,pd->documentation());
02022   m_output.closeHash();
02023 }
02024 
02025 bool PerlModGenerator::generatePerlModOutput()
02026 {
02027   QFile outputFile;
02028   if (!createOutputFile(outputFile, pathDoxyDocsPM))
02029     return false;
02030   
02031   QTextStream outputTextStream(&outputFile);
02032   PerlModOutputStream outputStream(&outputTextStream);
02033   m_output.setPerlModOutputStream(&outputStream);
02034   m_output.add("$doxydocs=").openHash();
02035   
02036   m_output.openList("classes");
02037   ClassSDict::Iterator cli(*Doxygen::classSDict);
02038   ClassDef *cd;
02039   for (cli.toFirst();(cd=cli.current());++cli)
02040     generatePerlModForClass(cd);
02041   m_output.closeList();
02042 
02043   m_output.openList("namespaces");
02044   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
02045   NamespaceDef *nd;
02046   for (nli.toFirst();(nd=nli.current());++nli)
02047     generatePerlModForNamespace(nd);
02048   m_output.closeList();
02049 
02050   m_output.openList("files");
02051   FileNameListIterator fnli(*Doxygen::inputNameList);
02052   FileName *fn;
02053   for (;(fn=fnli.current());++fnli)
02054   {
02055     FileNameIterator fni(*fn);
02056     FileDef *fd;
02057     for (;(fd=fni.current());++fni)
02058       generatePerlModForFile(fd);
02059   }
02060   m_output.closeList();
02061 
02062   m_output.openList("groups");
02063   GroupSDict::Iterator gli(*Doxygen::groupSDict);
02064   GroupDef *gd;
02065   for (;(gd=gli.current());++gli)
02066   {
02067     generatePerlModForGroup(gd);
02068   }
02069   m_output.closeList();
02070 
02071   m_output.openList("pages");
02072   PageSDict::Iterator pdi(*Doxygen::pageSDict);
02073   PageDef *pd=0;
02074   for (pdi.toFirst();(pd=pdi.current());++pdi)
02075   {
02076     generatePerlModForPage(pd);
02077   }
02078   if (Doxygen::mainPage)
02079   {
02080     generatePerlModForPage(Doxygen::mainPage);
02081   }
02082   m_output.closeList();
02083 
02084   m_output.closeHash().add(";\n1;\n");
02085   return true;
02086 }
02087 
02088 bool PerlModGenerator::createOutputFile(QFile &f, const char *s)
02089 {
02090   f.setName(s);
02091   if (!f.open(IO_WriteOnly))
02092   {
02093     err("Cannot open file %s for writing!\n", s);
02094     return false;
02095   }
02096   return true;
02097 }
02098 
02099 bool PerlModGenerator::createOutputDir(QDir &perlModDir)
02100 {
02101   QCString outputDirectory = Config_getString("OUTPUT_DIRECTORY");
02102   if (outputDirectory.isEmpty())
02103   {
02104     outputDirectory=QDir::currentDirPath();
02105   }
02106   else
02107   {
02108     QDir dir(outputDirectory);
02109     if (!dir.exists())
02110     {
02111       dir.setPath(QDir::currentDirPath());
02112       if (!dir.mkdir(outputDirectory))
02113       {
02114         err("Error: tag OUTPUT_DIRECTORY: Output directory `%s' does not "
02115             "exist and cannot be created\n",outputDirectory.data());
02116         exit(1);
02117       }
02118       else if (!Config_getBool("QUIET"))
02119       {
02120         err("Notice: Output directory `%s' does not exist. "
02121             "I have created it for you.\n", outputDirectory.data());
02122       }
02123       dir.cd(outputDirectory);
02124     }
02125     outputDirectory=dir.absPath();
02126   }
02127 
02128   QDir dir(outputDirectory);
02129   if (!dir.exists())
02130   {
02131     dir.setPath(QDir::currentDirPath());
02132     if (!dir.mkdir(outputDirectory))
02133     {
02134       err("Cannot create directory %s\n",outputDirectory.data());
02135       return false;
02136     }
02137   }
02138  
02139   perlModDir.setPath(outputDirectory+"/perlmod");
02140   if (!perlModDir.exists() && !perlModDir.mkdir(outputDirectory+"/perlmod"))
02141   {
02142     err("Could not create perlmod directory in %s\n",outputDirectory.data());
02143     return false;
02144   }
02145   return true;
02146 }
02147 
02148 bool PerlModGenerator::generateDoxyStructurePM()
02149 {
02150   QFile doxyModelPM;
02151   if (!createOutputFile(doxyModelPM, pathDoxyStructurePM))
02152     return false;
02153 
02154   QTextStream doxyModelPMStream(&doxyModelPM);
02155   doxyModelPMStream << 
02156     "sub memberlist($) {\n"
02157     "    my $prefix = $_[0];\n"
02158     "    return\n"
02159     "\t[ \"hash\", $prefix . \"s\",\n"
02160     "\t  {\n"
02161     "\t    members =>\n"
02162     "\t      [ \"list\", $prefix . \"List\",\n"
02163     "\t\t[ \"hash\", $prefix,\n"
02164     "\t\t  {\n"
02165     "\t\t    kind => [ \"string\", $prefix . \"Kind\" ],\n"
02166     "\t\t    name => [ \"string\", $prefix . \"Name\" ],\n"
02167     "\t\t    static => [ \"string\", $prefix . \"Static\" ],\n"
02168     "\t\t    virtualness => [ \"string\", $prefix . \"Virtualness\" ],\n"
02169     "\t\t    protection => [ \"string\", $prefix . \"Protection\" ],\n"
02170     "\t\t    type => [ \"string\", $prefix . \"Type\" ],\n"
02171     "\t\t    parameters =>\n"
02172     "\t\t      [ \"list\", $prefix . \"Params\",\n"
02173     "\t\t\t[ \"hash\", $prefix . \"Param\",\n"
02174     "\t\t\t  {\n"
02175     "\t\t\t    declaration_name => [ \"string\", $prefix . \"ParamName\" ],\n"
02176     "\t\t\t    type => [ \"string\", $prefix . \"ParamType\" ],\n"
02177     "\t\t\t  },\n"
02178     "\t\t\t],\n"
02179     "\t\t      ],\n"
02180     "\t\t    detailed =>\n"
02181     "\t\t      [ \"hash\", $prefix . \"Detailed\",\n"
02182     "\t\t\t{\n"
02183     "\t\t\t  doc => [ \"doc\", $prefix . \"DetailedDoc\" ],\n"
02184     "\t\t\t  return => [ \"doc\", $prefix . \"Return\" ],\n"
02185     "\t\t\t  see => [ \"doc\", $prefix . \"See\" ],\n"
02186     "\t\t\t  params =>\n"
02187     "\t\t\t    [ \"list\", $prefix . \"PDBlocks\",\n"
02188     "\t\t\t      [ \"hash\", $prefix . \"PDBlock\",\n"
02189     "\t\t\t\t{\n"
02190     "\t\t\t\t  parameters =>\n"
02191     "\t\t\t\t    [ \"list\", $prefix . \"PDParams\",\n"
02192     "\t\t\t\t      [ \"hash\", $prefix . \"PDParam\",\n"
02193     "\t\t\t\t\t{\n"
02194     "\t\t\t\t\t  name => [ \"string\", $prefix . \"PDParamName\" ],\n"
02195     "\t\t\t\t\t},\n"
02196     "\t\t\t\t      ],\n"
02197     "\t\t\t\t    ],\n"
02198     "\t\t\t\t  doc => [ \"doc\", $prefix . \"PDDoc\" ],\n"
02199     "\t\t\t\t},\n"
02200     "\t\t\t      ],\n"
02201     "\t\t\t    ],\n"
02202     "\t\t\t},\n"
02203     "\t\t      ],\n"
02204     "\t\t  },\n"
02205     "\t\t],\n"
02206     "\t      ],\n"
02207     "\t  },\n"
02208     "\t];\n"
02209     "}\n"
02210     "\n"
02211     "$doxystructure =\n"
02212     "    [ \"hash\", \"Root\",\n"
02213     "      {\n"
02214     "\tfiles =>\n"
02215     "\t  [ \"list\", \"Files\",\n"
02216     "\t    [ \"hash\", \"File\",\n"
02217     "\t      {\n"
02218     "\t\tname => [ \"string\", \"FileName\" ],\n"
02219     "\t\ttypedefs => memberlist(\"FileTypedef\"),\n"
02220     "\t\tvariables => memberlist(\"FileVariable\"),\n"
02221     "\t\tfunctions => memberlist(\"FileFunction\"),\n"
02222     "\t\tdetailed =>\n"
02223     "\t\t  [ \"hash\", \"FileDetailed\",\n"
02224     "\t\t    {\n"
02225     "\t\t      doc => [ \"doc\", \"FileDetailedDoc\" ],\n"
02226     "\t\t    },\n"
02227     "\t\t  ],\n"
02228     "\t      },\n"
02229     "\t    ],\n"
02230     "\t  ],\n"
02231     "\tpages =>\n"
02232     "\t  [ \"list\", \"Pages\",\n"
02233     "\t    [ \"hash\", \"Page\",\n"
02234     "\t      {\n"
02235     "\t\tname => [ \"string\", \"PageName\" ],\n"
02236     "\t\tdetailed =>\n"
02237     "\t\t  [ \"hash\", \"PageDetailed\",\n"
02238     "\t\t    {\n"
02239     "\t\t      doc => [ \"doc\", \"PageDetailedDoc\" ],\n"
02240     "\t\t    },\n"
02241     "\t\t  ],\n"
02242     "\t      },\n"
02243     "\t    ],\n"
02244     "\t  ],\n"
02245     "\tclasses =>\n"
02246     "\t  [ \"list\", \"Classes\",\n"
02247     "\t    [ \"hash\", \"Class\",\n"
02248     "\t      {\n"
02249     "\t\tname => [ \"string\", \"ClassName\" ],\n"
02250     "\t\tpublic_typedefs => memberlist(\"ClassPublicTypedef\"),\n"
02251     "\t\tpublic_methods => memberlist(\"ClassPublicMethod\"),\n"
02252     "\t\tpublic_members => memberlist(\"ClassPublicMember\"),\n"
02253     "\t\tprotected_typedefs => memberlist(\"ClassProtectedTypedef\"),\n"
02254     "\t\tprotected_methods => memberlist(\"ClassProtectedMethod\"),\n"
02255     "\t\tprotected_members => memberlist(\"ClassProtectedMember\"),\n"
02256     "\t\tprivate_typedefs => memberlist(\"ClassPrivateTypedef\"),\n"
02257     "\t\tprivate_methods => memberlist(\"ClassPrivateMethod\"),\n"
02258     "\t\tprivate_members => memberlist(\"ClassPrivateMember\"),\n"
02259     "\t\tdetailed =>\n"
02260     "\t\t  [ \"hash\", \"ClassDetailed\",\n"
02261     "\t\t    {\n"
02262     "\t\t      doc => [ \"doc\", \"ClassDetailedDoc\" ],\n"
02263     "\t\t    },\n"
02264     "\t\t  ],\n"
02265     "\t      },\n"
02266     "\t    ],\n"
02267     "\t  ],\n"
02268     "\tgroups =>\n"
02269     "\t  [ \"list\", \"Groups\",\n"
02270     "\t    [ \"hash\", \"Group\",\n"
02271     "\t      {\n"
02272     "\t\tname => [ \"string\", \"GroupName\" ],\n"
02273     "\t\ttitle => [ \"string\", \"GroupTitle\" ],\n"
02274     "\t\tfiles =>\n"
02275     "\t\t  [ \"list\", \"Files\",\n"
02276     "\t\t    [ \"hash\", \"File\",\n"
02277     "\t\t      {\n"
02278     "\t\t        name => [ \"string\", \"Filename\" ]\n"
02279     "\t\t      }\n"
02280     "\t\t    ],\n"
02281     "\t\t  ],\n"
02282     "\t\tclasses  =>\n"
02283     "\t\t  [ \"list\", \"Classes\",\n"
02284     "\t\t    [ \"hash\", \"Class\",\n"
02285     "\t\t      {\n" 
02286     "\t\t        name => [ \"string\", \"Classname\" ]\n"
02287     "\t\t      }\n"
02288     "\t\t    ],\n"
02289     "\t\t  ],\n"
02290     "\t\tnamespaces =>\n"
02291     "\t\t  [ \"list\", \"Namespaces\",\n"
02292     "\t\t    [ \"hash\", \"Namespace\",\n"
02293     "\t\t      {\n" 
02294     "\t\t        name => [ \"string\", \"NamespaceName\" ]\n"
02295     "\t\t      }\n"
02296     "\t\t    ],\n"
02297     "\t\t  ],\n"
02298     "\t\tpages =>\n"
02299     "\t\t  [ \"list\", \"Pages\",\n"
02300     "\t\t    [ \"hash\", \"Page\","
02301     "\t\t      {\n"
02302     "\t\t        title => [ \"string\", \"PageName\" ]\n"
02303     "\t\t      }\n"
02304     "\t\t    ],\n"
02305     "\t\t  ],\n"
02306     "\t\tgroups =>\n"
02307     "\t\t  [ \"list\", \"Groups\",\n"
02308     "\t\t    [ \"hash\", \"Group\",\n"
02309     "\t\t      {\n"
02310     "\t\t        title => [ \"string\", \"GroupName\" ]\n"
02311     "\t\t      }\n"
02312     "\t\t    ],\n"
02313     "\t\t  ],\n"
02314     "\t\tfunctions => memberlist(\"GroupFunction\"),\n"
02315     "\t\tdetailed =>\n"
02316     "\t\t  [ \"hash\", \"GroupDetailed\",\n"
02317     "\t\t    {\n"
02318     "\t\t      doc => [ \"doc\", \"GroupDetailedDoc\" ],\n"
02319     "\t\t    },\n"
02320     "\t\t  ],\n"
02321     "\t      }\n"
02322     "\t    ],\n"
02323     "\t  ],\n"
02324     "      },\n"
02325     "    ];\n"
02326     "\n"
02327     "1;\n";
02328 
02329   return true;
02330 }
02331 
02332 bool PerlModGenerator::generateDoxyRules()
02333 {
02334   QFile doxyRules;
02335   if (!createOutputFile(doxyRules, pathDoxyRules))
02336     return false;
02337 
02338   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
02339   QString prefix = Config_getString("PERLMOD_MAKEVAR_PREFIX");
02340 
02341   QTextStream doxyRulesStream(&doxyRules);
02342   doxyRulesStream <<
02343     prefix << "DOXY_EXEC_PATH = " << pathDoxyExec << "\n" <<
02344     prefix << "DOXYFILE = " << pathDoxyfile << "\n" <<
02345     prefix << "DOXYDOCS_PM = " << pathDoxyDocsPM << "\n" <<
02346     prefix << "DOXYSTRUCTURE_PM = " << pathDoxyStructurePM << "\n" <<
02347     prefix << "DOXYRULES = " << pathDoxyRules << "\n";
02348   if (perlmodLatex)
02349     doxyRulesStream <<
02350       prefix << "DOXYLATEX_PL = " << pathDoxyLatexPL << "\n" <<
02351       prefix << "DOXYLATEXSTRUCTURE_PL = " << pathDoxyLatexStructurePL << "\n" <<
02352       prefix << "DOXYSTRUCTURE_TEX = " << pathDoxyStructureTex << "\n" <<
02353       prefix << "DOXYDOCS_TEX = " << pathDoxyDocsTex << "\n" <<
02354       prefix << "DOXYFORMAT_TEX = " << pathDoxyFormatTex << "\n" <<
02355       prefix << "DOXYLATEX_TEX = " << pathDoxyLatexTex << "\n" <<
02356       prefix << "DOXYLATEX_DVI = " << pathDoxyLatexDVI << "\n" <<
02357       prefix << "DOXYLATEX_PDF = " << pathDoxyLatexPDF << "\n";
02358 
02359   doxyRulesStream <<
02360     "\n"
02361     ".PHONY: clean-perlmod\n"
02362     "clean-perlmod::\n"
02363     "\trm -f $(" << prefix << "DOXYSTRUCTURE_PM) \\\n"
02364     "\t$(" << prefix << "DOXYDOCS_PM)";
02365   if (perlmodLatex)
02366     doxyRulesStream <<
02367       " \\\n"
02368       "\t$(" << prefix << "DOXYLATEX_PL) \\\n"
02369       "\t$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
02370       "\t$(" << prefix << "DOXYDOCS_TEX) \\\n"
02371       "\t$(" << prefix << "DOXYSTRUCTURE_TEX) \\\n"
02372       "\t$(" << prefix << "DOXYFORMAT_TEX) \\\n"
02373       "\t$(" << prefix << "DOXYLATEX_TEX) \\\n"
02374       "\t$(" << prefix << "DOXYLATEX_PDF) \\\n"
02375       "\t$(" << prefix << "DOXYLATEX_DVI) \\\n"
02376       "\t$(addprefix $(" << prefix << "DOXYLATEX_TEX:tex=),out aux log)";
02377   doxyRulesStream << "\n\n";
02378 
02379   doxyRulesStream <<
02380     "$(" << prefix << "DOXYRULES) \\\n"
02381     "$(" << prefix << "DOXYMAKEFILE) \\\n"
02382     "$(" << prefix << "DOXYSTRUCTURE_PM) \\\n"
02383     "$(" << prefix << "DOXYDOCS_PM)";
02384   if (perlmodLatex) {
02385     doxyRulesStream <<
02386       " \\\n"
02387       "$(" << prefix << "DOXYLATEX_PL) \\\n"
02388       "$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
02389       "$(" << prefix << "DOXYFORMAT_TEX) \\\n"
02390       "$(" << prefix << "DOXYLATEX_TEX)";
02391   }
02392   doxyRulesStream <<
02393     ": \\\n"
02394     "\t$(" << prefix << "DOXYFILE)\n"
02395     "\tcd $(" << prefix << "DOXY_EXEC_PATH) ; doxygen \"$<\"\n";
02396 
02397   if (perlmodLatex) {
02398     doxyRulesStream <<
02399       "\n"
02400       "$(" << prefix << "DOXYDOCS_TEX): \\\n"
02401       "$(" << prefix << "DOXYLATEX_PL) \\\n"
02402       "$(" << prefix << "DOXYDOCS_PM)\n"
02403       "\tperl -I\"$(<D)\" \"$<\" >\"$@\"\n"
02404       "\n"
02405       "$(" << prefix << "DOXYSTRUCTURE_TEX): \\\n"
02406       "$(" << prefix << "DOXYLATEXSTRUCTURE_PL) \\\n"
02407       "$(" << prefix << "DOXYSTRUCTURE_PM)\n"
02408       "\tperl -I\"$(<D)\" \"$<\" >\"$@\"\n"
02409       "\n"
02410       "$(" << prefix << "DOXYLATEX_PDF) \\\n"
02411       "$(" << prefix << "DOXYLATEX_DVI): \\\n"
02412       "$(" << prefix << "DOXYLATEX_TEX) \\\n"
02413       "$(" << prefix << "DOXYFORMAT_TEX) \\\n"
02414       "$(" << prefix << "DOXYSTRUCTURE_TEX) \\\n"
02415       "$(" << prefix << "DOXYDOCS_TEX)\n"
02416       "\n"
02417       "$(" << prefix << "DOXYLATEX_PDF): \\\n"
02418       "$(" << prefix << "DOXYLATEX_TEX)\n"
02419       "\tpdflatex -interaction=nonstopmode \"$<\"\n"
02420       "\n"
02421       "$(" << prefix << "DOXYLATEX_DVI): \\\n"
02422       "$(" << prefix << "DOXYLATEX_TEX)\n"
02423       "\tlatex -interaction=nonstopmode \"$<\"\n";
02424   }
02425 
02426   return true;
02427 }
02428 
02429 bool PerlModGenerator::generateMakefile()
02430 {
02431   QFile makefile;
02432   if (!createOutputFile(makefile, pathMakefile))
02433     return false;
02434 
02435   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
02436   QString prefix = Config_getString("PERLMOD_MAKEVAR_PREFIX");
02437 
02438   QTextStream makefileStream(&makefile);
02439   makefileStream <<
02440     ".PHONY: default clean" << (perlmodLatex ? " pdf" : "") << "\n"
02441     "default: " << (perlmodLatex ? "pdf" : "clean") << "\n"
02442     "\n"
02443     "include " << pathDoxyRules << "\n"
02444     "\n"
02445     "clean: clean-perlmod\n";
02446 
02447   if (perlmodLatex) {
02448     makefileStream <<
02449       "pdf: $(" << prefix << "DOXYLATEX_PDF)\n"
02450       "dvi: $(" << prefix << "DOXYLATEX_DVI)\n";
02451   }
02452 
02453   return true;
02454 }
02455 
02456 bool PerlModGenerator::generateDoxyLatexStructurePL()
02457 {
02458   QFile doxyLatexStructurePL;
02459   if (!createOutputFile(doxyLatexStructurePL, pathDoxyLatexStructurePL))
02460     return false;
02461 
02462   QTextStream doxyLatexStructurePLStream(&doxyLatexStructurePL);
02463   doxyLatexStructurePLStream << 
02464     "use DoxyStructure;\n"
02465     "\n"
02466     "sub process($) {\n"
02467     "\tmy $node = $_[0];\n"
02468     "\tmy ($type, $name) = @$node[0, 1];\n"
02469     "\tmy $command;\n"
02470     "\tif ($type eq \"string\") { $command = \"String\" }\n"
02471     "\telsif ($type eq \"doc\") { $command = \"Doc\" }\n"
02472     "\telsif ($type eq \"hash\") {\n"
02473     "\t\t$command = \"Hash\";\n"
02474     "\t\tfor my $subnode (values %{$$node[2]}) {\n"
02475     "\t\t\tprocess($subnode);\n"
02476     "\t\t}\n"
02477     "\t}\n"
02478     "\telsif ($type eq \"list\") {\n"
02479     "\t\t$command = \"List\";\n"
02480     "\t\tprocess($$node[2]);\n"
02481     "\t}\n"
02482     "\tprint \"\\\\\" . $command . \"Node{\" . $name . \"}%\\n\";\n"
02483     "}\n"
02484     "\n"
02485     "process($doxystructure);\n";
02486 
02487   return true;
02488 }
02489 
02490 bool PerlModGenerator::generateDoxyLatexPL()
02491 {
02492   QFile doxyLatexPL;
02493   if (!createOutputFile(doxyLatexPL, pathDoxyLatexPL))
02494     return false;
02495 
02496   QTextStream doxyLatexPLStream(&doxyLatexPL);
02497   doxyLatexPLStream << 
02498     "use DoxyStructure;\n"
02499     "use DoxyDocs;\n"
02500     "\n"
02501     "sub latex_quote($) {\n"
02502     "\tmy $text = $_[0];\n"
02503     "\t$text =~ s/\\\\/\\\\textbackslash /g;\n"
02504     "\t$text =~ s/\\|/\\\\textbar /g;\n"
02505     "\t$text =~ s/</\\\\textless /g;\n"
02506     "\t$text =~ s/>/\\\\textgreater /g;\n"
02507     "\t$text =~ s/~/\\\\textasciitilde /g;\n"
02508     "\t$text =~ s/\\^/\\\\textasciicircum /g;\n"
02509     "\t$text =~ s/[\\$&%#_{}]/\\\\$&/g;\n"
02510     "\tprint $text;\n"
02511     "}\n"
02512     "\n"
02513     "sub generate_doc($) {\n"
02514     "\tmy $doc = $_[0];\n"
02515     "\tfor my $item (@$doc) {\n"
02516     "\t\tmy $type = $$item{type};\n"
02517     "\t\tif ($type eq \"text\") {\n"
02518     "\t\t\tlatex_quote($$item{content});\n"
02519     "\t\t} elsif ($type eq \"parbreak\") {\n"
02520     "\t\t\tprint \"\\n\\n\";\n"
02521     "\t\t} elsif ($type eq \"style\") {\n"
02522     "\t\t\tmy $style = $$item{style};\n"
02523     "\t\t\tif ($$item{enable} eq \"yes\") {\n"
02524     "\t\t\t\tif ($style eq \"bold\") { print '\\bfseries'; }\n"
02525     "\t\t\t\tif ($style eq \"italic\") { print '\\itshape'; }\n"
02526     "\t\t\t\tif ($style eq \"code\") { print '\\ttfamily'; }\n"
02527     "\t\t\t} else {\n"
02528     "\t\t\t\tif ($style eq \"bold\") { print '\\mdseries'; }\n"
02529     "\t\t\t\tif ($style eq \"italic\") { print '\\upshape'; }\n"
02530     "\t\t\t\tif ($style eq \"code\") { print '\\rmfamily'; }\n"
02531     "\t\t\t}\n"
02532     "\t\t\tprint '{}';\n"
02533     "\t\t} elsif ($type eq \"symbol\") {\n"
02534     "\t\t\tmy $symbol = $$item{symbol};\n"
02535     "\t\t\tif ($symbol eq \"copyright\") { print '\\copyright'; }\n"
02536     "\t\t\telsif ($symbol eq \"szlig\") { print '\\ss'; }\n"
02537     "\t\t\tprint '{}';\n"
02538     "\t\t} elsif ($type eq \"accent\") {\n"
02539     "\t\t\tmy ($accent) = $$item{accent};\n"
02540     "\t\t\tif ($accent eq \"umlaut\") { print '\\\"'; }\n"
02541     "\t\t\telsif ($accent eq \"acute\") { print '\\\\\\''; }\n"
02542     "\t\t\telsif ($accent eq \"grave\") { print '\\`'; }\n"
02543     "\t\t\telsif ($accent eq \"circ\") { print '\\^'; }\n"
02544     "\t\t\telsif ($accent eq \"tilde\") { print '\\~'; }\n"
02545     "\t\t\telsif ($accent eq \"cedilla\") { print '\\c'; }\n"
02546     "\t\t\telsif ($accent eq \"ring\") { print '\\r'; }\n"
02547     "\t\t\tprint \"{\" . $$item{letter} . \"}\"; \n"
02548     "\t\t} elsif ($type eq \"list\") {\n"
02549     "\t\t\tmy $env = ($$item{style} eq \"ordered\") ? \"enumerate\" : \"itemize\";\n"
02550     "\t\t\tprint \"\\n\\\\begin{\" . $env .\"}\";\n"
02551     "\t\t  \tfor my $subitem (@{$$item{content}}) {\n"
02552     "\t\t\t\tprint \"\\n\\\\item \";\n"
02553     "\t\t\t\tgenerate_doc($subitem);\n"
02554     "\t\t  \t}\n"
02555     "\t\t\tprint \"\\n\\\\end{\" . $env .\"}\";\n"
02556     "\t\t} elsif ($type eq \"url\") {\n"
02557     "\t\t\tlatex_quote($$item{content});\n"
02558     "\t\t}\n"
02559     "\t}\n"
02560     "}\n"
02561     "\n"
02562     "sub generate($$) {\n"
02563     "\tmy ($item, $node) = @_;\n"
02564     "\tmy ($type, $name) = @$node[0, 1];\n"
02565     "\tif ($type eq \"string\") {\n"
02566     "\t\tprint \"\\\\\" . $name . \"{\";\n"
02567     "\t\tlatex_quote($item);\n"
02568     "\t\tprint \"}\";\n"
02569     "\t} elsif ($type eq \"doc\") {\n"
02570     "\t\tif (@$item) {\n"
02571     "\t\t\tprint \"\\\\\" . $name . \"{\";\n"
02572     "\t\t\tgenerate_doc($item);\n"
02573     "\t\t\tprint \"}%\\n\";\n"
02574     "\t\t} else {\n"
02575     "#\t\t\tprint \"\\\\\" . $name . \"Empty%\\n\";\n"
02576     "\t\t}\n"
02577     "\t} elsif ($type eq \"hash\") {\n"
02578     "\t\tmy ($key, $value);\n"
02579     "\t\twhile (($key, $subnode) = each %{$$node[2]}) {\n"
02580     "\t\t\tmy $subname = $$subnode[1];\n"
02581     "\t\t\tprint \"\\\\Defcs{field\" . $subname . \"}{\";\n"
02582     "\t\t\tif ($$item{$key}) {\n"
02583     "\t\t\t\tgenerate($$item{$key}, $subnode);\n"
02584     "\t\t\t} else {\n"
02585     "#\t\t\t\t\tprint \"\\\\\" . $subname . \"Empty%\\n\";\n"
02586     "\t\t\t}\n"
02587     "\t\t\tprint \"}%\\n\";\n"
02588     "\t\t}\n"
02589     "\t\tprint \"\\\\\" . $name . \"%\\n\";\n"
02590     "\t} elsif ($type eq \"list\") {\n"
02591     "\t\tmy $index = 0;\n"
02592     "\t\tif (@$item) {\n"
02593     "\t\t\tprint \"\\\\\" . $name . \"{%\\n\";\n"
02594     "\t\t\tfor my $subitem (@$item) {\n"
02595     "\t\t\t\tif ($index) {\n"
02596     "\t\t\t\t\tprint \"\\\\\" . $name . \"Sep%\\n\";\n"
02597     "\t\t\t\t}\n"
02598     "\t\t\t\tgenerate($subitem, $$node[2]);\n"
02599     "\t\t\t\t$index++;\n"
02600     "\t\t\t}\n"
02601     "\t\t\tprint \"}%\\n\";\n"
02602     "\t\t} else {\n"
02603     "#\t\t\tprint \"\\\\\" . $name . \"Empty%\\n\";\n"
02604     "\t\t}\n"
02605     "\t}\n"
02606     "}\n"
02607     "\n"
02608     "generate($doxydocs, $doxystructure);\n";
02609 
02610   return true;
02611 }
02612 
02613 bool PerlModGenerator::generateDoxyFormatTex()
02614 {
02615   QFile doxyFormatTex;
02616   if (!createOutputFile(doxyFormatTex, pathDoxyFormatTex))
02617     return false;
02618 
02619   QTextStream doxyFormatTexStream(&doxyFormatTex);
02620   doxyFormatTexStream << 
02621     "\\def\\Defcs#1{\\long\\expandafter\\def\\csname#1\\endcsname}\n"
02622     "\\Defcs{Empty}{}\n"
02623     "\\def\\IfEmpty#1{\\expandafter\\ifx\\csname#1\\endcsname\\Empty}\n"
02624     "\n"
02625     "\\def\\StringNode#1{\\Defcs{#1}##1{##1}}\n"
02626     "\\def\\DocNode#1{\\Defcs{#1}##1{##1}}\n"
02627     "\\def\\ListNode#1{\\Defcs{#1}##1{##1}\\Defcs{#1Sep}{}}\n"
02628     "\\def\\HashNode#1{\\Defcs{#1}{}}\n"
02629     "\n"
02630     "\\input{" << pathDoxyStructureTex << "}\n"
02631     "\n"
02632     "\\newbox\\BoxA\n"
02633     "\\dimendef\\DimenA=151\\relax\n"
02634     "\\dimendef\\DimenB=152\\relax\n"
02635     "\\countdef\\ZoneDepth=151\\relax\n"
02636     "\n"
02637     "\\def\\Cs#1{\\csname#1\\endcsname}\n"
02638     "\\def\\Letcs#1{\\expandafter\\let\\csname#1\\endcsname}\n"
02639     "\\def\\Heading#1{\\vskip 4mm\\relax\\textbf{#1}}\n"
02640     "\\def\\See#1{\\begin{flushleft}\\Heading{See also: }#1\\end{flushleft}}\n"
02641     "\n"
02642     "\\def\\Frame#1{\\vskip 3mm\\relax\\fbox{ \\vbox{\\hsize0.95\\hsize\\vskip 1mm\\relax\n"
02643     "\\raggedright#1\\vskip 0.5mm\\relax} }}\n"
02644     "\n"
02645     "\\def\\Zone#1#2#3{%\n"
02646     "\\Defcs{Test#1}{#2}%\n"
02647     "\\Defcs{Emit#1}{#3}%\n"
02648     "\\Defcs{#1}{%\n"
02649     "\\advance\\ZoneDepth1\\relax\n"
02650     "\\Letcs{Mode\\number\\ZoneDepth}0\\relax\n"
02651     "\\Letcs{Present\\number\\ZoneDepth}0\\relax\n"
02652     "\\Cs{Test#1}\n"
02653     "\\expandafter\\if\\Cs{Present\\number\\ZoneDepth}1%\n"
02654     "\\advance\\ZoneDepth-1\\relax\n"
02655     "\\Letcs{Present\\number\\ZoneDepth}1\\relax\n"
02656     "\\expandafter\\if\\Cs{Mode\\number\\ZoneDepth}1%\n"
02657     "\\advance\\ZoneDepth1\\relax\n"
02658     "\\Letcs{Mode\\number\\ZoneDepth}1\\relax\n"
02659     "\\Cs{Emit#1}\n"
02660     "\\advance\\ZoneDepth-1\\relax\\fi\n"
02661     "\\advance\\ZoneDepth1\\relax\\fi\n"
02662     "\\advance\\ZoneDepth-1\\relax}}\n"
02663     "\n"
02664     "\\def\\Member#1#2{%\n"
02665     "\\Defcs{Test#1}{\\Cs{field#1Detailed}\n"
02666     "\\IfEmpty{field#1DetailedDoc}\\else\\Letcs{Present#1}1\\fi}\n"
02667     "\\Defcs{#1}{\\Letcs{Present#1}0\\relax\n"
02668     "\\Cs{Test#1}\\if1\\Cs{Present#1}\\Letcs{Present\\number\\ZoneDepth}1\\relax\n"
02669     "\\if1\\Cs{Mode\\number\\ZoneDepth}#2\\fi\\fi}}\n"
02670     "\n"
02671     "\\def\\TypedefMemberList#1#2{%\n"
02672     "\\Defcs{#1DetailedDoc}##1{\\vskip 5.5mm\\relax##1}%\n"
02673     "\\Defcs{#1Name}##1{\\textbf{##1}}%\n"
02674     "\\Defcs{#1See}##1{\\See{##1}}%\n"
02675     "%\n"
02676     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
02677     "\\Member{#1}{\\Frame{typedef \\Cs{field#1Type} \\Cs{field#1Name}}%\n"
02678     "\\Cs{field#1DetailedDoc}\\Cs{field#1See}\\vskip 5mm\\relax}}%\n"
02679     "\n"
02680     "\\def\\VariableMemberList#1#2{%\n"
02681     "\\Defcs{#1DetailedDoc}##1{\\vskip 5.5mm\\relax##1}%\n"
02682     "\\Defcs{#1Name}##1{\\textbf{##1}}%\n"
02683     "\\Defcs{#1See}##1{\\See{##1}}%\n"
02684     "%\n"
02685     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
02686     "\\Member{#1}{\\Frame{\\Cs{field#1Type}{} \\Cs{field#1Name}}%\n"
02687     "\\Cs{field#1DetailedDoc}\\Cs{field#1See}\\vskip 5mm\\relax}}%\n"
02688     "\n"
02689     "\\def\\FunctionMemberList#1#2{%\n"
02690     "\\Defcs{#1PDParamName}##1{\\textit{##1}}%\n"
02691     "\\Defcs{#1PDParam}{\\Cs{field#1PDParamName}}%\n"
02692     "\\Defcs{#1PDParamsSep}{, }%\n"
02693     "\\Defcs{#1PDBlocksSep}{\\vskip 2mm\\relax}%\n"
02694     "%\n"
02695     "\\Defcs{#1PDBlocks}##1{%\n"
02696     "\\Heading{Parameters:}\\vskip 1.5mm\\relax\n"
02697     "\\DimenA0pt\\relax\n"
02698     "\\Defcs{#1PDBlock}{\\setbox\\BoxA\\hbox{\\Cs{field#1PDParams}}%\n"
02699     "\\ifdim\\DimenA<\\wd\\BoxA\\DimenA\\wd\\BoxA\\fi}%\n"
02700     "##1%\n"
02701     "\\advance\\DimenA3mm\\relax\n"
02702     "\\DimenB\\hsize\\advance\\DimenB-\\DimenA\\relax\n"
02703     "\\Defcs{#1PDBlock}{\\hbox to\\hsize{\\vtop{\\hsize\\DimenA\\relax\n"
02704     "\\Cs{field#1PDParams}}\\hfill\n"
02705     "\\vtop{\\hsize\\DimenB\\relax\\Cs{field#1PDDoc}}}}%\n"
02706     "##1}\n"
02707     "\n"
02708     "\\Defcs{#1ParamName}##1{\\textit{##1}}\n"
02709     "\\Defcs{#1Param}{\\Cs{field#1ParamType}{} \\Cs{field#1ParamName}}\n"
02710     "\\Defcs{#1ParamsSep}{, }\n"
02711     "\n"
02712     "\\Defcs{#1Name}##1{\\textbf{##1}}\n"
02713     "\\Defcs{#1See}##1{\\See{##1}}\n"
02714     "\\Defcs{#1Return}##1{\\Heading{Returns: }##1}\n"
02715     "\\Defcs{field#1Title}{\\Frame{\\Cs{field#1Type}{} \\Cs{field#1Name}(\\Cs{field#1Params})}}%\n"
02716     "%\n"
02717     "\\Zone{#1s}{\\Cs{field#1List}}{\\subsubsection{#2}\\Cs{field#1List}}%\n"
02718     "\\Member{#1}{%\n"
02719     "\\Cs{field#1Title}\\vskip 6mm\\relax\\Cs{field#1DetailedDoc}\n"
02720     "\\Cs{field#1Return}\\Cs{field#1PDBlocks}\\Cs{field#1See}\\vskip 5mm\\relax}}\n"
02721     "\n"
02722     "\\def\\FileDetailed{\\fieldFileDetailedDoc\\par}\n"
02723     "\\def\\ClassDetailed{\\fieldClassDetailedDoc\\par}\n"
02724     "\n"
02725     "\\def\\FileSubzones{\\fieldFileTypedefs\\fieldFileVariables\\fieldFileFunctions}\n"
02726     "\n"
02727     "\\def\\ClassSubzones{%\n"
02728     "\\fieldClassPublicTypedefs\\fieldClassPublicMembers\\fieldClassPublicMethods\n"
02729     "\\fieldClassProtectedTypedefs\\fieldClassProtectedMembers\\fieldClassProtectedMethods\n"
02730     "\\fieldClassPrivateTypedefs\\fieldClassPrivateMembers\\fieldClassPrivateMethods}\n"
02731     "\n"
02732     "\\Member{Page}{\\subsection{\\fieldPageName}\\fieldPageDetailedDoc}\n"
02733     "\n"
02734     "\\TypedefMemberList{FileTypedef}{Typedefs}\n"
02735     "\\VariableMemberList{FileVariable}{Variables}\n"
02736     "\\FunctionMemberList{FileFunction}{Functions}\n"
02737     "\\Zone{File}{\\FileSubzones}{\\subsection{\\fieldFileName}\\fieldFileDetailed\\FileSubzones}\n"
02738     "\n"
02739     "\\TypedefMemberList{ClassPublicTypedef}{Public Typedefs}\n"
02740     "\\TypedefMemberList{ClassProtectedTypedef}{Protected Typedefs}\n"
02741     "\\TypedefMemberList{ClassPrivateTypedef}{Private Typedefs}\n"
02742     "\\VariableMemberList{ClassPublicMember}{Public Members}\n"
02743     "\\VariableMemberList{ClassProtectedMember}{Protected Members}\n"
02744     "\\VariableMemberList{ClassPrivateMember}{Private Members}\n"
02745     "\\FunctionMemberList{ClassPublicMethod}{Public Methods}\n"
02746     "\\FunctionMemberList{ClassProtectedMethod}{Protected Methods}\n"
02747     "\\FunctionMemberList{ClassPrivateMethod}{Private Methods}\n"
02748     "\\Zone{Class}{\\ClassSubzones}{\\subsection{\\fieldClassName}\\fieldClassDetailed\\ClassSubzones}\n"
02749     "\n"
02750     "\\Zone{AllPages}{\\fieldPages}{\\section{Pages}\\fieldPages}\n"
02751     "\\Zone{AllFiles}{\\fieldFiles}{\\section{Files}\\fieldFiles}\n"
02752     "\\Zone{AllClasses}{\\fieldClasses}{\\section{Classes}\\fieldClasses}\n"
02753     "\n"
02754     "\\newlength{\\oldparskip}\n"
02755     "\\newlength{\\oldparindent}\n"
02756     "\\newlength{\\oldfboxrule}\n"
02757     "\n"
02758     "\\ZoneDepth0\\relax\n"
02759     "\\Letcs{Mode0}1\\relax\n"
02760     "\n"
02761     "\\def\\EmitDoxyDocs{%\n"
02762     "\\setlength{\\oldparskip}{\\parskip}\n"
02763     "\\setlength{\\oldparindent}{\\parindent}\n"
02764     "\\setlength{\\oldfboxrule}{\\fboxrule}\n"
02765     "\\setlength{\\parskip}{0cm}\n"
02766     "\\setlength{\\parindent}{0cm}\n"
02767     "\\setlength{\\fboxrule}{1pt}\n"
02768     "\\AllPages\\AllFiles\\AllClasses\n"
02769     "\\setlength{\\parskip}{\\oldparskip}\n"
02770     "\\setlength{\\parindent}{\\oldparindent}\n"
02771     "\\setlength{\\fboxrule}{\\oldfboxrule}}\n";
02772 
02773   return true;
02774 }
02775 
02776 bool PerlModGenerator::generateDoxyLatexTex()
02777 {
02778   QFile doxyLatexTex;
02779   if (!createOutputFile(doxyLatexTex, pathDoxyLatexTex))
02780     return false;
02781 
02782   QTextStream doxyLatexTexStream(&doxyLatexTex);
02783   doxyLatexTexStream <<
02784     "\\documentclass[a4paper,12pt]{article}\n"
02785     "\\usepackage[latin1]{inputenc}\n"
02786     "\\usepackage[none]{hyphenat}\n"
02787     "\\usepackage[T1]{fontenc}\n"
02788     "\\usepackage{hyperref}\n"
02789     "\\usepackage{times}\n"
02790     "\n"
02791     "\\input{doxyformat}\n"
02792     "\n"
02793     "\\begin{document}\n"
02794     "\\input{" << pathDoxyDocsTex << "}\n"
02795     "\\sloppy\n"
02796     "\\EmitDoxyDocs\n"
02797     "\\end{document}\n";
02798 
02799   return true;
02800 }
02801 
02802 void PerlModGenerator::generate()
02803 {
02804   // + classes
02805   // + namespaces
02806   // + files
02807   // - packages
02808   // + groups
02809   // + related pages
02810   // - examples
02811 
02812   QDir perlModDir;
02813   if (!createOutputDir(perlModDir))
02814     return;
02815 
02816   bool perlmodLatex = Config_getBool("PERLMOD_LATEX");
02817 
02818   pathDoxyDocsPM = perlModDir.absPath() + "/DoxyDocs.pm";
02819   pathDoxyStructurePM = perlModDir.absPath() + "/DoxyStructure.pm";
02820   pathMakefile = perlModDir.absPath() + "/Makefile";
02821   pathDoxyRules = perlModDir.absPath() + "/doxyrules.make";
02822 
02823   if (perlmodLatex) {
02824     pathDoxyStructureTex = perlModDir.absPath() + "/doxystructure.tex";
02825     pathDoxyFormatTex = perlModDir.absPath() + "/doxyformat.tex";
02826     pathDoxyLatexTex = perlModDir.absPath() + "/doxylatex.tex";
02827     pathDoxyLatexDVI = perlModDir.absPath() + "/doxylatex.dvi";
02828     pathDoxyLatexPDF = perlModDir.absPath() + "/doxylatex.pdf";
02829     pathDoxyDocsTex = perlModDir.absPath() + "/doxydocs.tex";
02830     pathDoxyLatexPL = perlModDir.absPath() + "/doxylatex.pl";
02831     pathDoxyLatexStructurePL = perlModDir.absPath() + "/doxylatex-structure.pl";
02832   }
02833 
02834   if (!(generatePerlModOutput()
02835         && generateDoxyStructurePM()
02836         && generateMakefile()
02837         && generateDoxyRules()))
02838     return;
02839 
02840   if (perlmodLatex) {
02841     if (!(generateDoxyLatexStructurePL()
02842           && generateDoxyLatexPL()
02843           && generateDoxyLatexTex()
02844           && generateDoxyFormatTex()))
02845       return;
02846   }
02847 }
02848 
02849 void generatePerlMod()
02850 {
02851   PerlModGenerator pmg(Config_getBool("PERLMOD_PRETTY"));
02852   pmg.generate();
02853 }
02854 
02855 // Local Variables:
02856 // c-basic-offset: 2
02857 // End:
02858 
02859 /* This elisp function for XEmacs makes Control-Z transform
02860    the text in the region into a valid C string.
02861 
02862   (global-set-key '(control z) (lambda () (interactive)
02863    (save-excursion
02864     (if (< (mark) (point)) (exchange-point-and-mark))
02865     (let ((start (point)) (replacers 
02866      '(("\\\\" "\\\\\\\\")
02867        ("\"" "\\\\\"")
02868        ("\t" "\\\\t")
02869        ("^.*$" "\"\\&\\\\n\""))))
02870      (while replacers   
02871       (while (re-search-forward (caar replacers) (mark) t)
02872        (replace-match (cadar replacers) t))
02873       (goto-char start)
02874       (setq replacers (cdr replacers)))))))
02875 */



Generated on Mon Mar 31 10:58:41 2008 by  doxygen 1.5.1