mangen.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * $Id: htmlgen.cpp,v 1.17 1998/11/28 11:33:19 root Exp $
00004  *
00005  * Copyright (C) 1997-2008 by Dimitri van Heesch.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and its
00008  * documentation under the terms of the GNU General Public License is hereby 
00009  * granted. No representations are made about the suitability of this software 
00010  * for any purpose. It is provided "as is" without express or implied warranty.
00011  * See the GNU General Public License for more details.
00012  *
00013  * Documents produced by Doxygen are derivative works derived from the
00014  * input used in their production; they are not affected by this license.
00015  *
00016  */
00017 
00018 /* http://www.cubic.org/source/archive/fileform/txt/man/ has some
00019    nice introductions to groff and man pages. */
00020 
00021 #include <stdlib.h>
00022 
00023 #include "qtbc.h"
00024 #include <qdir.h>
00025 #include "message.h"
00026 #include "mangen.h"
00027 #include "config.h"
00028 #include "util.h"
00029 #include "doxygen.h"
00030 #include <string.h>
00031 #include "docparser.h"
00032 #include "mandocvisitor.h"
00033 
00034 static QCString getExtension()
00035 {
00036   QCString ext = Config_getString("MAN_EXTENSION");
00037   if( ext.length() >= 2 &&
00038       ext.data()[0] == '.')
00039   {
00040     ext = ext.mid(1, ext.length()-1);
00041   }
00042   else
00043   {
00044     ext = "3"; 
00045   }
00046   return ext;
00047 }
00048 
00049 ManGenerator::ManGenerator() : OutputGenerator()
00050 {
00051   dir=Config_getString("MAN_OUTPUT")+"/man" + getExtension();
00052   firstCol=TRUE;
00053   paragraph=FALSE;
00054   col=0;
00055   upperCase=FALSE;
00056   insideTabbing=FALSE;
00057   inHeader=FALSE;
00058 }
00059 
00060 ManGenerator::~ManGenerator()
00061 {
00062 }
00063 
00064 //void ManGenerator::append(const OutputGenerator *g)
00065 //{
00066 //  QCString r=g->getContents();
00067 //  if (upperCase)
00068 //    t << r.upper();
00069 //  else
00070 //    t << r;
00071 //  if (!r.isEmpty())
00072 //    firstCol = r.at(r.length()-1)=='\n';
00073 //  else
00074 //    firstCol = ((ManGenerator *)g)->firstCol;
00075 //  col+=((ManGenerator *)g)->col;
00076 //  inHeader=((ManGenerator *)g)->inHeader;
00077 //  paragraph=FALSE;
00078 //}
00079 
00080 void ManGenerator::init()
00081 {
00082   QCString ext = getExtension();
00083   QCString &manOutput = Config_getString("MAN_OUTPUT");
00084   
00085   QDir d(manOutput);
00086   if (!d.exists() && !d.mkdir(manOutput))
00087   {
00088     err("Could not create output directory %s\n",manOutput.data());
00089     exit(1);
00090   }
00091   d.setPath(manOutput+"/man"+ext);
00092   if (!d.exists() && !d.mkdir(manOutput+"/man"+ext))
00093   {
00094     err("Could not create output directory %s/man%s\n",manOutput.data(),ext.data());
00095     exit(1);
00096   }
00097   createSubDirs(d);
00098 }
00099 
00100 static QCString buildFileName(const char *name)
00101 {
00102   QCString fileName;
00103 
00104   const char *p=name;
00105   char c;
00106   while ((c=*p++))
00107   {
00108     switch (c)
00109     {
00110       case ':':
00111         fileName+="_";
00112         if (*p==':') p++;
00113         break;
00114       case '<':
00115       case '>':
00116       case '&':
00117       case '*':
00118       case '!':
00119       case '^':
00120       case '~':
00121       case '%':
00122       case '+':
00123       case '/':
00124         fileName+="_";
00125         break;
00126       default:
00127         fileName+=c;
00128     }
00129   }
00130 
00131   QCString &manExtension = Config_getString("MAN_EXTENSION");
00132   if (convertToQCString(fileName.right(2))!=manExtension) 
00133   {
00134     fileName+=manExtension;
00135   }
00136 
00137   return fileName;
00138 }
00139 
00140 void ManGenerator::startFile(const char *,const char *manName,const char *)
00141 {
00142   startPlainFile( buildFileName( manName ) );
00143   firstCol=TRUE;
00144 }
00145 
00146 void ManGenerator::endFile()
00147 {
00148   t << endl;
00149   endPlainFile();
00150 }
00151 
00152 void ManGenerator::endTitleHead(const char *,const char *name)
00153 {
00154   t << ".TH \"" << name << "\" " << getExtension() << " \"" 
00155     << dateToString(FALSE) << "\" \"";
00156   if (!Config_getString("PROJECT_NUMBER").isEmpty())
00157     t << "Version " << Config_getString("PROJECT_NUMBER") << "\" \"";
00158   if (Config_getString("PROJECT_NAME").isEmpty()) 
00159     t << "Doxygen";
00160   else
00161     t << Config_getString("PROJECT_NAME");
00162   t << "\" \\\" -*- nroff -*-" << endl;
00163   t << ".ad l" << endl;
00164   t << ".nh" << endl;
00165   t << ".SH NAME" << endl;
00166   t << name << " \\- ";
00167   firstCol=FALSE;
00168   inHeader=TRUE;
00169 }
00170 
00171 void ManGenerator::newParagraph()
00172 {
00173   if (!paragraph)
00174   {
00175     if (!firstCol) t << endl;
00176     t << ".PP" << endl;
00177     firstCol=TRUE;
00178   }
00179   paragraph=TRUE;
00180 }
00181 
00182 void ManGenerator::startParagraph()
00183 {
00184   if (!paragraph)
00185   {
00186     if (!firstCol) t << endl;
00187     t << ".PP" << endl;
00188     firstCol=TRUE;
00189   }
00190   paragraph=TRUE;
00191 }
00192 
00193 void ManGenerator::endParagraph()
00194 {
00195 }
00196 
00197 void ManGenerator::writeString(const char *text)
00198 {
00199   docify(text);
00200 }
00201 
00202 void ManGenerator::startIndexItem(const char *,const char *)
00203 {
00204 }
00205 
00206 void ManGenerator::endIndexItem(const char *,const char *)
00207 {
00208 }
00209 
00210 void ManGenerator::writeStartAnnoItem(const char *,const char *,
00211                                        const char *,const char *)
00212 {
00213 }
00214 
00215 void ManGenerator::writeObjectLink(const char *,const char *,
00216                                     const char *, const char *name)
00217 {
00218   startBold(); docify(name); endBold();
00219 }
00220 
00221 void ManGenerator::writeCodeLink(const char *,const char *,
00222                                  const char *, const char *name,
00223                                  const char *)
00224 {
00225   docify(name);
00226 }
00227 
00228 void ManGenerator::startHtmlLink(const char *)
00229 {
00230 }
00231 
00232 void ManGenerator::endHtmlLink()
00233 {
00234 }
00235 
00236 //void ManGenerator::writeMailLink(const char *url)
00237 //{
00238 //  docify(url);
00239 //}
00240 
00241 void ManGenerator::startGroupHeader()
00242 {
00243   if (!firstCol) t << endl;
00244   t << ".SH \"";
00245   upperCase=TRUE;
00246   firstCol=FALSE;
00247 }
00248 
00249 void ManGenerator::endGroupHeader()
00250 {
00251   t << "\"\n.PP " << endl;
00252   firstCol=TRUE;
00253   paragraph=TRUE;
00254   upperCase=FALSE;
00255 }
00256 
00257 void ManGenerator::startMemberHeader()
00258 {
00259   if (!firstCol) t << endl;
00260   t << ".SS \"";
00261 }
00262 
00263 void ManGenerator::endMemberHeader()
00264 {
00265   t << "\"\n";
00266   firstCol=TRUE;
00267   paragraph=FALSE;
00268 }
00269 
00270 void ManGenerator::docify(const char *str)
00271 {
00272   if (str)
00273   {
00274     const char *p=str;
00275     char c=0;
00276     while ((c=*p++)) 
00277     {
00278       switch(c)
00279       {
00280         case '\\': t << "\\\\"; col++; break;
00281         case '\n': t << "\n"; col=0; break;
00282         case '\"':  c = '\''; // no break!
00283         default: t << c; col++; break;
00284       }
00285     }
00286     firstCol=(c=='\n');
00287     //printf("%s",str);fflush(stdout);
00288   }
00289   paragraph=FALSE;
00290 }
00291 
00292 void ManGenerator::codify(const char *str)
00293 {
00294   //static char spaces[]="        ";
00295   if (str)
00296   {
00297     const char *p=str;
00298     char c;
00299     int spacesToNextTabStop;
00300     while (*p)
00301     {
00302       c=*p++;
00303       switch(c)
00304       {
00305         case '\t':  spacesToNextTabStop =
00306                           Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
00307                     t << spaces.left(spacesToNextTabStop); 
00308                     col+=spacesToNextTabStop; 
00309                     break;
00310         case '\n':  t << "\n"; firstCol=TRUE; col=0; break;
00311         case '\\':  t << "\\"; col++; break;
00312         case '\"':  c = '\''; // no break!
00313         default:    t << c; firstCol=FALSE; col++; break;
00314       }
00315     }
00316     //printf("%s",str);fflush(stdout);
00317   }
00318   paragraph=FALSE;
00319 }
00320 
00321 void ManGenerator::writeChar(char c)
00322 {
00323   firstCol=(c=='\n');
00324   if (firstCol) col=0; else col++;
00325   switch (c)
00326   {
00327     case '\\': t << "\\\\"; break;
00328   case '\"': c = '\''; // no break!
00329     default:   t << c; break;
00330   }
00331   //printf("%c",c);fflush(stdout);
00332   paragraph=FALSE;
00333 }
00334 
00335 void ManGenerator::startDescList(SectionTypes)      
00336 {
00337   if (!firstCol) 
00338   { t << endl << ".PP" << endl; 
00339     firstCol=TRUE; paragraph=TRUE; 
00340     col=0;
00341   }
00342   paragraph=FALSE;
00343   startBold();
00344 }
00345 
00346 void ManGenerator::startTitle() 
00347 { 
00348   if (!firstCol) t << endl; 
00349   t << ".SH \""; 
00350   firstCol=FALSE;
00351   paragraph=FALSE;
00352 }
00353 
00354 void ManGenerator::endTitle()
00355 {
00356     t << "\"";
00357 }
00358 
00359 void ManGenerator::writeListItem() 
00360 { 
00361   if (!firstCol) t << endl; 
00362   t << ".TP" << endl; 
00363   firstCol=TRUE;
00364   paragraph=FALSE;
00365   col=0;
00366 } 
00367 
00368 void ManGenerator::startCodeFragment() 
00369 { 
00370   newParagraph();
00371   t << ".nf" << endl; 
00372   firstCol=TRUE;
00373   paragraph=FALSE;
00374 }
00375 
00376 void ManGenerator::endCodeFragment()   
00377 { 
00378   if (!firstCol) t << endl;
00379   t << ".fi" << endl; 
00380   firstCol=TRUE;
00381   paragraph=FALSE;
00382   col=0;
00383 }
00384 
00385 void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *) 
00386 { 
00387   if (!firstCol) t << endl;
00388   t << ".SS \""; 
00389   firstCol=FALSE;
00390   paragraph=FALSE;
00391 }
00392 
00393 void ManGenerator::startDoxyAnchor(const char *,const char *manName,
00394                                    const char *, const char *name,
00395                                    const char *)
00396 {
00397     // something to be done?
00398     if( !Config_getBool("MAN_LINKS") ) 
00399     {
00400         return; // no
00401     }
00402 
00403     // the name of the link file is derived from the name of the anchor:
00404     // - truncate after an (optional) ::
00405     QCString baseName = name;
00406     int i=baseName.findRev(':');
00407     if (i!=-1) baseName=baseName.right(baseName.length()-i-1);
00408     
00409     // - remove dangerous characters and append suffix, then add dir prefix
00410     QCString fileName=dir+"/"+buildFileName( baseName );
00411     QFile linkfile( fileName );
00412     // - only create file if it doesn't exist already
00413     if ( !linkfile.open( IO_ReadOnly ) ) 
00414     {
00415         if ( linkfile.open( IO_WriteOnly ) ) 
00416         {
00417               QTextStream linkstream;
00418               linkstream.setDevice(&linkfile);
00419               linkstream.setEncoding(QTextStream::UnicodeUTF8);
00420               linkstream << ".so man" << getExtension() << "/" << buildFileName( manName ) << endl;
00421         }
00422     }
00423     linkfile.close();
00424 }
00425 
00426 void ManGenerator::endMemberDoc(bool)
00427 {
00428     t << "\"";
00429 }
00430 
00431 void ManGenerator::startSubsection()    
00432 { 
00433   if (!firstCol) t << endl;
00434   t << ".SS \""; 
00435   firstCol=FALSE;
00436   paragraph=FALSE;
00437 }
00438 
00439 void ManGenerator::endSubsection()
00440 {
00441   t << "\"";
00442 }
00443 
00444 
00445 void ManGenerator::startSubsubsection() 
00446 { 
00447   if (!firstCol) t << endl;
00448   t << "\n.SS \""; 
00449   firstCol=FALSE;
00450   paragraph=FALSE;
00451 }
00452 
00453 void ManGenerator::endSubsubsection()
00454 {
00455   t << "\"";
00456 }
00457 
00458 void ManGenerator::writeSynopsis()      
00459 { 
00460   if (!firstCol) t << endl;
00461   t << ".SH SYNOPSIS\n.br\n.PP\n"; 
00462   firstCol=TRUE;
00463   paragraph=FALSE;
00464 }
00465 
00466 void ManGenerator::startDescItem()
00467 {
00468   if (!firstCol) t << endl;
00469   t << ".IP \"";
00470   firstCol=FALSE;
00471 }
00472 
00473 //void ManGenerator::endDescTitle()
00474 //{
00475 //  endBold();
00476 //  paragraph=TRUE;
00477 //}
00478 
00479 void ManGenerator::writeDescItem()
00480 {
00481   if (!firstCol) t << endl;
00482   if (!paragraph) t << ".in -1c" << endl;
00483   t << ".in +1c" << endl;
00484   firstCol=TRUE;
00485   paragraph=FALSE;
00486   col=0;
00487 }
00488 
00489 void ManGenerator::endDescItem()
00490 {
00491   t << "\" 1c" << endl;
00492   firstCol=TRUE;
00493 }
00494 
00495 void ManGenerator::startAnonTypeScope(int indentLevel)
00496 {
00497   if (indentLevel==0)
00498   {
00499     insideTabbing=TRUE;
00500   }
00501 }
00502 
00503 void ManGenerator::endAnonTypeScope(int indentLevel)
00504 {
00505   if (indentLevel==0)
00506   {
00507     insideTabbing=FALSE;
00508   }
00509 }
00510 
00511 
00512 void ManGenerator::startMemberItem(int) 
00513 { 
00514   if (firstCol && !insideTabbing) t << ".in +1c\n";
00515   t << "\n.ti -1c\n.RI \""; 
00516   firstCol=FALSE;
00517 }
00518 
00519 void ManGenerator::endMemberItem() 
00520 { 
00521   t << "\"\n.br"; 
00522 }
00523 
00524 void ManGenerator::startMemberList() 
00525 { 
00526   if (!insideTabbing)
00527   {
00528     t << "\n.in +1c"; firstCol=FALSE; 
00529   }
00530 }
00531 
00532 void ManGenerator::endMemberList() 
00533 { 
00534   if (!insideTabbing)
00535   {
00536     t << "\n.in -1c"; firstCol=FALSE; 
00537   }
00538 }
00539 
00540 void ManGenerator::startMemberGroupHeader(bool)
00541 {
00542   t << "\n.PP\n.RI \"\\fB";
00543 }
00544 
00545 void ManGenerator::endMemberGroupHeader()
00546 {
00547   t << "\\fP\"\n.br\n";
00548   firstCol=TRUE;
00549 }
00550 
00551 void ManGenerator::startMemberGroupDocs()
00552 {
00553 }
00554 
00555 void ManGenerator::endMemberGroupDocs()
00556 {
00557   t << "\n.PP";
00558 }
00559 
00560 void ManGenerator::startMemberGroup()
00561 {
00562   t << "\n.in +1c";
00563 }
00564 
00565 void ManGenerator::endMemberGroup(bool)
00566 {
00567   t << "\n.in -1c";
00568   firstCol=FALSE;
00569 }
00570 
00571 void ManGenerator::startSection(const char *,const char *,SectionInfo::SectionType type)
00572 {
00573   if( !inHeader ) 
00574   {
00575     switch(type)
00576     {
00577       case SectionInfo::Page:          startGroupHeader(); break;
00578       case SectionInfo::Section:       startGroupHeader(); break;
00579       case SectionInfo::Subsection:    startMemberHeader(); break;
00580       case SectionInfo::Subsubsection: startMemberHeader(); break;
00581       case SectionInfo::Paragraph:     startMemberHeader(); break;
00582       default: ASSERT(0); break;
00583     }
00584   }
00585 }
00586 
00587 void ManGenerator::endSection(const char *,SectionInfo::SectionType type)
00588 {
00589   if( !inHeader )
00590   {
00591     switch(type)
00592     {
00593       case SectionInfo::Page:          endGroupHeader(); break;
00594       case SectionInfo::Section:       endGroupHeader(); break;
00595       case SectionInfo::Subsection:    endMemberHeader(); break;
00596       case SectionInfo::Subsubsection: endMemberHeader(); break;
00597       case SectionInfo::Paragraph:     endMemberHeader(); break;
00598       default: ASSERT(0); break;
00599     }
00600   }
00601   else
00602   {
00603     t << "\n";
00604     firstCol=TRUE;
00605     paragraph=FALSE;
00606     inHeader=FALSE;
00607   }
00608 }
00609 
00610 void ManGenerator::startSimpleSect(SectionTypes,const char *,
00611                                    const char *,const char *title)
00612 {
00613   if (!firstCol) 
00614   { t << endl << ".PP" << endl; 
00615     firstCol=TRUE; paragraph=TRUE; 
00616     col=0;
00617   }
00618   paragraph=FALSE;
00619   startBold();
00620   docify(title);
00621   endBold();
00622   paragraph=TRUE;
00623 }
00624 
00625 void ManGenerator::endSimpleSect()
00626 {
00627 }
00628 
00629 void ManGenerator::startParamList(ParamListTypes,const char *title)
00630 {
00631   if (!firstCol) 
00632   { t << endl << ".PP" << endl; 
00633     firstCol=TRUE; paragraph=TRUE; 
00634     col=0;
00635   }
00636   paragraph=FALSE;
00637   startBold();
00638   docify(title);
00639   endBold();
00640   paragraph=TRUE;
00641 }
00642 
00643 void ManGenerator::endParamList()
00644 {
00645 }
00646 
00647 void ManGenerator::printDoc(DocNode *n,const char *langExt)
00648 {
00649   ManDocVisitor *visitor = new ManDocVisitor(t,*this,langExt);
00650   n->accept(visitor);
00651   delete visitor; 
00652   firstCol=FALSE;
00653   paragraph = FALSE;
00654 }
00655 
00656 void ManGenerator::startConstraintList(const char *header)
00657 {
00658   if (!firstCol) 
00659   { t << endl << ".PP" << endl; 
00660     firstCol=TRUE; paragraph=TRUE; 
00661     col=0;
00662   }
00663   paragraph=FALSE;
00664   startBold();
00665   docify(header);
00666   endBold();
00667   paragraph=TRUE;
00668 }
00669 
00670 void ManGenerator::startConstraintParam()
00671 {
00672   writeListItem();
00673   startEmphasis();
00674 }
00675 
00676 void ManGenerator::endConstraintParam()
00677 {
00678   endEmphasis();
00679   t << " : ";
00680 }
00681 
00682 void ManGenerator::startConstraintType()
00683 {
00684   startEmphasis();
00685 }
00686 
00687 void ManGenerator::endConstraintType()
00688 {
00689   endEmphasis();
00690 }
00691 
00692 void ManGenerator::startConstraintDocs()
00693 {
00694 }
00695 
00696 void ManGenerator::endConstraintDocs()
00697 {
00698   t << endl; firstCol=TRUE;
00699 }
00700 
00701 void ManGenerator::endConstraintList()
00702 {
00703 }
00704 
00705 
00706 



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