Orb/Doxygen/src/mangen.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     6  *
       
     7  * Permission to use, copy, modify, and distribute this software and its
       
     8  * documentation under the terms of the GNU General Public License is hereby 
       
     9  * granted. No representations are made about the suitability of this software 
       
    10  * for any purpose. It is provided "as is" without express or implied warranty.
       
    11  * See the GNU General Public License for more details.
       
    12  *
       
    13  * Documents produced by Doxygen are derivative works derived from the
       
    14  * input used in their production; they are not affected by this license.
       
    15  *
       
    16  */
       
    17 
       
    18 /* http://www.cubic.org/source/archive/fileform/txt/man/ has some
       
    19    nice introductions to groff and man pages. */
       
    20 
       
    21 #include <stdlib.h>
       
    22 
       
    23 #include "qtbc.h"
       
    24 #include <qdir.h>
       
    25 #include "message.h"
       
    26 #include "mangen.h"
       
    27 #include "config.h"
       
    28 #include "util.h"
       
    29 #include "doxygen.h"
       
    30 #include <string.h>
       
    31 #include "docparser.h"
       
    32 #include "mandocvisitor.h"
       
    33 
       
    34 static QCString getExtension()
       
    35 {
       
    36   QCString ext = Config_getString("MAN_EXTENSION");
       
    37   if( ext.length() >= 2 &&
       
    38       ext.data()[0] == '.')
       
    39   {
       
    40     ext = ext.mid(1, ext.length()-1);
       
    41   }
       
    42   else
       
    43   {
       
    44     ext = "3"; 
       
    45   }
       
    46   return ext;
       
    47 }
       
    48 
       
    49 ManGenerator::ManGenerator() : OutputGenerator()
       
    50 {
       
    51   dir=Config_getString("MAN_OUTPUT")+"/man" + getExtension();
       
    52   firstCol=TRUE;
       
    53   paragraph=FALSE;
       
    54   col=0;
       
    55   upperCase=FALSE;
       
    56   insideTabbing=FALSE;
       
    57   inHeader=FALSE;
       
    58 }
       
    59 
       
    60 ManGenerator::~ManGenerator()
       
    61 {
       
    62 }
       
    63 
       
    64 //void ManGenerator::append(const OutputGenerator *g)
       
    65 //{
       
    66 //  QCString r=g->getContents();
       
    67 //  if (upperCase)
       
    68 //    t << r.upper();
       
    69 //  else
       
    70 //    t << r;
       
    71 //  if (!r.isEmpty())
       
    72 //    firstCol = r.at(r.length()-1)=='\n';
       
    73 //  else
       
    74 //    firstCol = ((ManGenerator *)g)->firstCol;
       
    75 //  col+=((ManGenerator *)g)->col;
       
    76 //  inHeader=((ManGenerator *)g)->inHeader;
       
    77 //  paragraph=FALSE;
       
    78 //}
       
    79 
       
    80 void ManGenerator::init()
       
    81 {
       
    82   QCString ext = getExtension();
       
    83   QCString &manOutput = Config_getString("MAN_OUTPUT");
       
    84   
       
    85   QDir d(manOutput);
       
    86   if (!d.exists() && !d.mkdir(manOutput))
       
    87   {
       
    88     err("Could not create output directory %s\n",manOutput.data());
       
    89     exit(1);
       
    90   }
       
    91   d.setPath(manOutput+"/man"+ext);
       
    92   if (!d.exists() && !d.mkdir(manOutput+"/man"+ext))
       
    93   {
       
    94     err("Could not create output directory %s/man%s\n",manOutput.data(),ext.data());
       
    95     exit(1);
       
    96   }
       
    97   createSubDirs(d);
       
    98 }
       
    99 
       
   100 static QCString buildFileName(const char *name)
       
   101 {
       
   102   QCString fileName;
       
   103 
       
   104   const char *p=name;
       
   105   char c;
       
   106   while ((c=*p++))
       
   107   {
       
   108     switch (c)
       
   109     {
       
   110       case ':':
       
   111         fileName+="_";
       
   112         if (*p==':') p++;
       
   113         break;
       
   114       case '<':
       
   115       case '>':
       
   116       case '&':
       
   117       case '*':
       
   118       case '!':
       
   119       case '^':
       
   120       case '~':
       
   121       case '%':
       
   122       case '+':
       
   123       case '/':
       
   124         fileName+="_";
       
   125         break;
       
   126       default:
       
   127         fileName+=c;
       
   128     }
       
   129   }
       
   130 
       
   131   QCString &manExtension = Config_getString("MAN_EXTENSION");
       
   132   if (convertToQCString(fileName.right(2))!=manExtension) 
       
   133   {
       
   134     fileName+=manExtension;
       
   135   }
       
   136 
       
   137   return fileName;
       
   138 }
       
   139 
       
   140 void ManGenerator::startFile(const char *,const char *manName,const char *)
       
   141 {
       
   142   startPlainFile( buildFileName( manName ) );
       
   143   firstCol=TRUE;
       
   144 }
       
   145 
       
   146 void ManGenerator::endFile()
       
   147 {
       
   148   t << endl;
       
   149   endPlainFile();
       
   150 }
       
   151 
       
   152 void ManGenerator::endTitleHead(const char *,const char *name)
       
   153 {
       
   154   t << ".TH \"" << name << "\" " << getExtension() << " \"" 
       
   155     << dateToString(FALSE) << "\" \"";
       
   156   if (!Config_getString("PROJECT_NUMBER").isEmpty())
       
   157     t << "Version " << Config_getString("PROJECT_NUMBER") << "\" \"";
       
   158   if (Config_getString("PROJECT_NAME").isEmpty()) 
       
   159     t << "Doxygen";
       
   160   else
       
   161     t << Config_getString("PROJECT_NAME");
       
   162   t << "\" \\\" -*- nroff -*-" << endl;
       
   163   t << ".ad l" << endl;
       
   164   t << ".nh" << endl;
       
   165   t << ".SH NAME" << endl;
       
   166   t << name << " \\- ";
       
   167   firstCol=FALSE;
       
   168   inHeader=TRUE;
       
   169 }
       
   170 
       
   171 void ManGenerator::newParagraph()
       
   172 {
       
   173   if (!paragraph)
       
   174   {
       
   175     if (!firstCol) t << endl;
       
   176     t << ".PP" << endl;
       
   177     firstCol=TRUE;
       
   178   }
       
   179   paragraph=TRUE;
       
   180 }
       
   181 
       
   182 void ManGenerator::startParagraph()
       
   183 {
       
   184   if (!paragraph)
       
   185   {
       
   186     if (!firstCol) t << endl;
       
   187     t << ".PP" << endl;
       
   188     firstCol=TRUE;
       
   189   }
       
   190   paragraph=TRUE;
       
   191 }
       
   192 
       
   193 void ManGenerator::endParagraph()
       
   194 {
       
   195 }
       
   196 
       
   197 void ManGenerator::writeString(const char *text)
       
   198 {
       
   199   docify(text);
       
   200 }
       
   201 
       
   202 void ManGenerator::startIndexItem(const char *,const char *)
       
   203 {
       
   204 }
       
   205 
       
   206 void ManGenerator::endIndexItem(const char *,const char *)
       
   207 {
       
   208 }
       
   209 
       
   210 void ManGenerator::writeStartAnnoItem(const char *,const char *,
       
   211                                        const char *,const char *)
       
   212 {
       
   213 }
       
   214 
       
   215 void ManGenerator::writeObjectLink(const char *,const char *,
       
   216                                     const char *, const char *name)
       
   217 {
       
   218   startBold(); docify(name); endBold();
       
   219 }
       
   220 
       
   221 void ManGenerator::writeCodeLink(const char *,const char *,
       
   222                                  const char *, const char *name,
       
   223                                  const char *)
       
   224 {
       
   225   docify(name);
       
   226 }
       
   227 
       
   228 void ManGenerator::startHtmlLink(const char *)
       
   229 {
       
   230 }
       
   231 
       
   232 void ManGenerator::endHtmlLink()
       
   233 {
       
   234 }
       
   235 
       
   236 //void ManGenerator::writeMailLink(const char *url)
       
   237 //{
       
   238 //  docify(url);
       
   239 //}
       
   240 
       
   241 void ManGenerator::startGroupHeader()
       
   242 {
       
   243   if (!firstCol) t << endl;
       
   244   t << ".SH \"";
       
   245   upperCase=TRUE;
       
   246   firstCol=FALSE;
       
   247 }
       
   248 
       
   249 void ManGenerator::endGroupHeader()
       
   250 {
       
   251   t << "\"\n.PP " << endl;
       
   252   firstCol=TRUE;
       
   253   paragraph=TRUE;
       
   254   upperCase=FALSE;
       
   255 }
       
   256 
       
   257 void ManGenerator::startMemberHeader()
       
   258 {
       
   259   if (!firstCol) t << endl;
       
   260   t << ".SS \"";
       
   261 }
       
   262 
       
   263 void ManGenerator::endMemberHeader()
       
   264 {
       
   265   t << "\"\n";
       
   266   firstCol=TRUE;
       
   267   paragraph=FALSE;
       
   268 }
       
   269 
       
   270 void ManGenerator::docify(const char *str)
       
   271 {
       
   272   if (str)
       
   273   {
       
   274     const char *p=str;
       
   275     char c=0;
       
   276     while ((c=*p++)) 
       
   277     {
       
   278       switch(c)
       
   279       {
       
   280         case '\\': t << "\\\\"; col++; break;
       
   281         case '\n': t << "\n"; col=0; break;
       
   282         case '\"':  c = '\''; // no break!
       
   283         default: t << c; col++; break;
       
   284       }
       
   285     }
       
   286     firstCol=(c=='\n');
       
   287     //printf("%s",str);fflush(stdout);
       
   288   }
       
   289   paragraph=FALSE;
       
   290 }
       
   291 
       
   292 void ManGenerator::codify(const char *str)
       
   293 {
       
   294   //static char spaces[]="        ";
       
   295   if (str)
       
   296   {
       
   297     const char *p=str;
       
   298     char c;
       
   299     int spacesToNextTabStop;
       
   300     while (*p)
       
   301     {
       
   302       c=*p++;
       
   303       switch(c)
       
   304       {
       
   305         case '\t':  spacesToNextTabStop =
       
   306                           Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
       
   307                     t << Doxygen::spaces.left(spacesToNextTabStop); 
       
   308                     col+=spacesToNextTabStop; 
       
   309                     break;
       
   310         case '\n':  t << "\n"; firstCol=TRUE; col=0; break;
       
   311         case '\\':  t << "\\"; col++; break;
       
   312         case '\"':  c = '\''; // no break!
       
   313         default:    t << c; firstCol=FALSE; col++; break;
       
   314       }
       
   315     }
       
   316     //printf("%s",str);fflush(stdout);
       
   317   }
       
   318   paragraph=FALSE;
       
   319 }
       
   320 
       
   321 void ManGenerator::writeChar(char c)
       
   322 {
       
   323   firstCol=(c=='\n');
       
   324   if (firstCol) col=0; else col++;
       
   325   switch (c)
       
   326   {
       
   327     case '\\': t << "\\\\"; break;
       
   328   case '\"': c = '\''; // no break!
       
   329     default:   t << c; break;
       
   330   }
       
   331   //printf("%c",c);fflush(stdout);
       
   332   paragraph=FALSE;
       
   333 }
       
   334 
       
   335 void ManGenerator::startDescList(SectionTypes)      
       
   336 {
       
   337   if (!firstCol) 
       
   338   { t << endl << ".PP" << endl; 
       
   339     firstCol=TRUE; paragraph=TRUE; 
       
   340     col=0;
       
   341   }
       
   342   paragraph=FALSE;
       
   343   startBold();
       
   344 }
       
   345 
       
   346 void ManGenerator::startTitle() 
       
   347 { 
       
   348   if (!firstCol) t << endl; 
       
   349   t << ".SH \""; 
       
   350   firstCol=FALSE;
       
   351   paragraph=FALSE;
       
   352 }
       
   353 
       
   354 void ManGenerator::endTitle()
       
   355 {
       
   356     t << "\"";
       
   357 }
       
   358 
       
   359 void ManGenerator::startItemListItem() 
       
   360 { 
       
   361   if (!firstCol) t << endl; 
       
   362   t << ".TP" << endl; 
       
   363   firstCol=TRUE;
       
   364   paragraph=FALSE;
       
   365   col=0;
       
   366 } 
       
   367 
       
   368 void ManGenerator::endItemListItem()
       
   369 {
       
   370 }
       
   371 
       
   372 void ManGenerator::startCodeFragment() 
       
   373 { 
       
   374   newParagraph();
       
   375   t << ".nf" << endl; 
       
   376   firstCol=TRUE;
       
   377   paragraph=FALSE;
       
   378 }
       
   379 
       
   380 void ManGenerator::endCodeFragment()   
       
   381 { 
       
   382   if (!firstCol) t << endl;
       
   383   t << ".fi" << endl; 
       
   384   firstCol=TRUE;
       
   385   paragraph=FALSE;
       
   386   col=0;
       
   387 }
       
   388 
       
   389 void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *) 
       
   390 { 
       
   391   if (!firstCol) t << endl;
       
   392   t << ".SS \""; 
       
   393   firstCol=FALSE;
       
   394   paragraph=FALSE;
       
   395 }
       
   396 
       
   397 void ManGenerator::startDoxyAnchor(const char *,const char *manName,
       
   398                                    const char *, const char *name,
       
   399                                    const char *)
       
   400 {
       
   401     // something to be done?
       
   402     if( !Config_getBool("MAN_LINKS") ) 
       
   403     {
       
   404 	return; // no
       
   405     }
       
   406 
       
   407     // the name of the link file is derived from the name of the anchor:
       
   408     // - truncate after an (optional) ::
       
   409     QCString baseName = name;
       
   410     int i=baseName.findRev(':');
       
   411     if (i!=-1) baseName=baseName.right(baseName.length()-i-1);
       
   412     
       
   413     // - remove dangerous characters and append suffix, then add dir prefix
       
   414     QCString fileName=dir+"/"+buildFileName( baseName );
       
   415     QFile linkfile( fileName );
       
   416     // - only create file if it doesn't exist already
       
   417     if ( !linkfile.open( IO_ReadOnly ) ) 
       
   418     {
       
   419 	if ( linkfile.open( IO_WriteOnly ) ) 
       
   420         {
       
   421 	      QTextStream linkstream;
       
   422 	      linkstream.setDevice(&linkfile);
       
   423 	      linkstream.setEncoding(QTextStream::UnicodeUTF8);
       
   424 	      linkstream << ".so man" << getExtension() << "/" << buildFileName( manName ) << endl;
       
   425 	}
       
   426     }
       
   427     linkfile.close();
       
   428 }
       
   429 
       
   430 void ManGenerator::endMemberDoc(bool)
       
   431 {
       
   432     t << "\"";
       
   433 }
       
   434 
       
   435 void ManGenerator::startSubsection()    
       
   436 { 
       
   437   if (!firstCol) t << endl;
       
   438   t << ".SS \""; 
       
   439   firstCol=FALSE;
       
   440   paragraph=FALSE;
       
   441 }
       
   442 
       
   443 void ManGenerator::endSubsection()
       
   444 {
       
   445   t << "\"";
       
   446 }
       
   447 
       
   448 
       
   449 void ManGenerator::startSubsubsection() 
       
   450 { 
       
   451   if (!firstCol) t << endl;
       
   452   t << "\n.SS \""; 
       
   453   firstCol=FALSE;
       
   454   paragraph=FALSE;
       
   455 }
       
   456 
       
   457 void ManGenerator::endSubsubsection()
       
   458 {
       
   459   t << "\"";
       
   460 }
       
   461 
       
   462 void ManGenerator::writeSynopsis()      
       
   463 { 
       
   464   if (!firstCol) t << endl;
       
   465   t << ".SH SYNOPSIS\n.br\n.PP\n"; 
       
   466   firstCol=TRUE;
       
   467   paragraph=FALSE;
       
   468 }
       
   469 
       
   470 void ManGenerator::startDescItem()
       
   471 {
       
   472   if (!firstCol) t << endl;
       
   473   t << ".IP \"";
       
   474   firstCol=FALSE;
       
   475 }
       
   476 
       
   477 //void ManGenerator::endDescTitle()
       
   478 //{
       
   479 //  endBold();
       
   480 //  paragraph=TRUE;
       
   481 //}
       
   482 
       
   483 void ManGenerator::startDescForItem()
       
   484 {
       
   485   if (!firstCol) t << endl;
       
   486   if (!paragraph) t << ".in -1c" << endl;
       
   487   t << ".in +1c" << endl;
       
   488   firstCol=TRUE;
       
   489   paragraph=FALSE;
       
   490   col=0;
       
   491 }
       
   492 
       
   493 void ManGenerator::endDescForItem()
       
   494 {
       
   495 }
       
   496 
       
   497 void ManGenerator::endDescItem()
       
   498 {
       
   499   t << "\" 1c" << endl;
       
   500   firstCol=TRUE;
       
   501 }
       
   502 
       
   503 void ManGenerator::startAnonTypeScope(int indentLevel)
       
   504 {
       
   505   if (indentLevel==0)
       
   506   {
       
   507     insideTabbing=TRUE;
       
   508   }
       
   509 }
       
   510 
       
   511 void ManGenerator::endAnonTypeScope(int indentLevel)
       
   512 {
       
   513   if (indentLevel==0)
       
   514   {
       
   515     insideTabbing=FALSE;
       
   516   }
       
   517 }
       
   518 
       
   519 
       
   520 void ManGenerator::startMemberItem(int) 
       
   521 { 
       
   522   if (firstCol && !insideTabbing) t << ".in +1c\n";
       
   523   t << "\n.ti -1c\n.RI \""; 
       
   524   firstCol=FALSE;
       
   525 }
       
   526 
       
   527 void ManGenerator::endMemberItem() 
       
   528 { 
       
   529   t << "\"\n.br"; 
       
   530 }
       
   531 
       
   532 void ManGenerator::startMemberList() 
       
   533 { 
       
   534   if (!insideTabbing)
       
   535   {
       
   536     t << "\n.in +1c"; firstCol=FALSE; 
       
   537   }
       
   538 }
       
   539 
       
   540 void ManGenerator::endMemberList() 
       
   541 { 
       
   542   if (!insideTabbing)
       
   543   {
       
   544     t << "\n.in -1c"; firstCol=FALSE; 
       
   545   }
       
   546 }
       
   547 
       
   548 void ManGenerator::startMemberGroupHeader(bool)
       
   549 {
       
   550   t << "\n.PP\n.RI \"\\fB";
       
   551 }
       
   552 
       
   553 void ManGenerator::endMemberGroupHeader()
       
   554 {
       
   555   t << "\\fP\"\n.br\n";
       
   556   firstCol=TRUE;
       
   557 }
       
   558 
       
   559 void ManGenerator::startMemberGroupDocs()
       
   560 {
       
   561 }
       
   562 
       
   563 void ManGenerator::endMemberGroupDocs()
       
   564 {
       
   565   t << "\n.PP";
       
   566 }
       
   567 
       
   568 void ManGenerator::startMemberGroup()
       
   569 {
       
   570   t << "\n.in +1c";
       
   571 }
       
   572 
       
   573 void ManGenerator::endMemberGroup(bool)
       
   574 {
       
   575   t << "\n.in -1c";
       
   576   firstCol=FALSE;
       
   577 }
       
   578 
       
   579 void ManGenerator::startSection(const char *,const char *,SectionInfo::SectionType type)
       
   580 {
       
   581   if( !inHeader ) 
       
   582   {
       
   583     switch(type)
       
   584     {
       
   585       case SectionInfo::Page:          startGroupHeader(); break;
       
   586       case SectionInfo::Section:       startGroupHeader(); break;
       
   587       case SectionInfo::Subsection:    startMemberHeader(); break;
       
   588       case SectionInfo::Subsubsection: startMemberHeader(); break;
       
   589       case SectionInfo::Paragraph:     startMemberHeader(); break;
       
   590       default: ASSERT(0); break;
       
   591     }
       
   592   }
       
   593 }
       
   594 
       
   595 void ManGenerator::endSection(const char *,SectionInfo::SectionType type)
       
   596 {
       
   597   if( !inHeader )
       
   598   {
       
   599     switch(type)
       
   600     {
       
   601       case SectionInfo::Page:          endGroupHeader(); break;
       
   602       case SectionInfo::Section:       endGroupHeader(); break;
       
   603       case SectionInfo::Subsection:    endMemberHeader(); break;
       
   604       case SectionInfo::Subsubsection: endMemberHeader(); break;
       
   605       case SectionInfo::Paragraph:     endMemberHeader(); break;
       
   606       default: ASSERT(0); break;
       
   607     }
       
   608   }
       
   609   else
       
   610   {
       
   611     t << "\n";
       
   612     firstCol=TRUE;
       
   613     paragraph=FALSE;
       
   614     inHeader=FALSE;
       
   615   }
       
   616 }
       
   617 
       
   618 void ManGenerator::startSimpleSect(SectionTypes,const char *,
       
   619                                    const char *,const char *title)
       
   620 {
       
   621   if (!firstCol) 
       
   622   { t << endl << ".PP" << endl; 
       
   623     firstCol=TRUE; paragraph=TRUE; 
       
   624     col=0;
       
   625   }
       
   626   paragraph=FALSE;
       
   627   startBold();
       
   628   docify(title);
       
   629   endBold();
       
   630   paragraph=TRUE;
       
   631 }
       
   632 
       
   633 void ManGenerator::endSimpleSect()
       
   634 {
       
   635 }
       
   636 
       
   637 void ManGenerator::startParamList(ParamListTypes,const char *title)
       
   638 {
       
   639   if (!firstCol) 
       
   640   { t << endl << ".PP" << endl; 
       
   641     firstCol=TRUE; paragraph=TRUE; 
       
   642     col=0;
       
   643   }
       
   644   paragraph=FALSE;
       
   645   startBold();
       
   646   docify(title);
       
   647   endBold();
       
   648   paragraph=TRUE;
       
   649 }
       
   650 
       
   651 void ManGenerator::endParamList()
       
   652 {
       
   653 }
       
   654 
       
   655 void ManGenerator::printDoc(DocNode *n,const char *langExt)
       
   656 {
       
   657   ManDocVisitor *visitor = new ManDocVisitor(t,*this,langExt);
       
   658   n->accept(visitor);
       
   659   delete visitor; 
       
   660   firstCol=FALSE;
       
   661   paragraph = FALSE;
       
   662 }
       
   663 
       
   664 void ManGenerator::startConstraintList(const char *header)
       
   665 {
       
   666   if (!firstCol) 
       
   667   { t << endl << ".PP" << endl; 
       
   668     firstCol=TRUE; paragraph=TRUE; 
       
   669     col=0;
       
   670   }
       
   671   paragraph=FALSE;
       
   672   startBold();
       
   673   docify(header);
       
   674   endBold();
       
   675   paragraph=TRUE;
       
   676 }
       
   677 
       
   678 void ManGenerator::startConstraintParam()
       
   679 {
       
   680   startItemListItem();
       
   681   startEmphasis();
       
   682 }
       
   683 
       
   684 void ManGenerator::endConstraintParam()
       
   685 {
       
   686   endEmphasis();
       
   687   endItemListItem();
       
   688   t << " : ";
       
   689 }
       
   690 
       
   691 void ManGenerator::startConstraintType()
       
   692 {
       
   693   startEmphasis();
       
   694 }
       
   695 
       
   696 void ManGenerator::endConstraintType()
       
   697 {
       
   698   endEmphasis();
       
   699 }
       
   700 
       
   701 void ManGenerator::startConstraintDocs()
       
   702 {
       
   703 }
       
   704 
       
   705 void ManGenerator::endConstraintDocs()
       
   706 {
       
   707   t << endl; firstCol=TRUE;
       
   708 }
       
   709 
       
   710 void ManGenerator::endConstraintList()
       
   711 {
       
   712 }
       
   713 
       
   714 
       
   715