1 /******************************************************************************
5 * Copyright (C) 1997-2014 by Dimitri van Heesch.
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.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
18 /* http://www.cubic.org/source/archive/fileform/txt/man/ has some
19 nice introductions to groff and man pages. */
30 #include "docparser.h"
31 #include "mandocvisitor.h"
34 static QCString getExtension()
38 * in case of . missing, just ignore it
39 * in case number missing, just place a 3 in front of it
41 QCString ext = Config_getString("MAN_EXTENSION");
59 if (ext.at(0)<'0' || ext.at(0)>'9')
67 static QCString getSubdir()
69 QCString dir = Config_getString("MAN_SUBDIR");
72 dir = "man" + getExtension();
77 ManGenerator::ManGenerator() : OutputGenerator()
79 dir=Config_getString("MAN_OUTPUT") + "/" + getSubdir();
88 ManGenerator::~ManGenerator()
92 //void ManGenerator::append(const OutputGenerator *g)
94 // QCString r=g->getContents();
100 // firstCol = r.at(r.length()-1)=='\n';
102 // firstCol = ((ManGenerator *)g)->firstCol;
103 // col+=((ManGenerator *)g)->col;
104 // inHeader=((ManGenerator *)g)->inHeader;
108 void ManGenerator::init()
110 QCString ext = getExtension();
111 QCString &manOutput = Config_getString("MAN_OUTPUT");
114 if (!d.exists() && !d.mkdir(manOutput))
116 err("Could not create output directory %s\n",manOutput.data());
119 d.setPath(manOutput + "/" + getSubdir());
120 if (!d.exists() && !d.mkdir(manOutput + "/" + getSubdir()))
122 err("Could not create output directory %s/%s\n",manOutput.data(), getSubdir().data());
128 static QCString buildFileName(const char *name)
131 if (name==0) return "noname";
160 QCString manExtension = "." + getExtension();
161 if (fileName.right(manExtension.length())!=manExtension)
163 fileName+=manExtension;
169 void ManGenerator::startFile(const char *,const char *manName,const char *)
171 startPlainFile( buildFileName( manName ) );
175 void ManGenerator::endFile()
181 void ManGenerator::endTitleHead(const char *,const char *name)
183 t << ".TH \"" << name << "\" " << getExtension() << " \""
184 << dateToString(FALSE) << "\" \"";
185 if (!Config_getString("PROJECT_NUMBER").isEmpty())
186 t << "Version " << Config_getString("PROJECT_NUMBER") << "\" \"";
187 if (Config_getString("PROJECT_NAME").isEmpty())
190 t << Config_getString("PROJECT_NAME");
191 t << "\" \\\" -*- nroff -*-" << endl;
192 t << ".ad l" << endl;
194 t << ".SH NAME" << endl;
195 t << name << " \\- ";
200 void ManGenerator::newParagraph()
204 if (!firstCol) t << endl;
211 void ManGenerator::startParagraph()
215 if (!firstCol) t << endl;
222 void ManGenerator::endParagraph()
226 void ManGenerator::writeString(const char *text)
231 void ManGenerator::startIndexItem(const char *,const char *)
235 void ManGenerator::endIndexItem(const char *,const char *)
239 void ManGenerator::writeStartAnnoItem(const char *,const char *,
240 const char *,const char *)
244 void ManGenerator::writeObjectLink(const char *,const char *,
245 const char *, const char *name)
247 startBold(); docify(name); endBold();
250 void ManGenerator::writeCodeLink(const char *,const char *,
251 const char *, const char *name,
257 void ManGenerator::startHtmlLink(const char *)
261 void ManGenerator::endHtmlLink()
265 //void ManGenerator::writeMailLink(const char *url)
270 void ManGenerator::startGroupHeader(int)
272 if (!firstCol) t << endl;
278 void ManGenerator::endGroupHeader(int)
280 t << "\"\n.PP " << endl;
286 void ManGenerator::startMemberHeader(const char *)
288 if (!firstCol) t << endl;
292 void ManGenerator::endMemberHeader()
299 void ManGenerator::docify(const char *str)
309 case '.': t << "\\&."; break; // see bug652277
310 case '\\': t << "\\\\"; col++; break;
311 case '\n': t << "\n"; col=0; break;
312 case '\"': c = '\''; // no break!
313 default: t << c; col++; break;
317 //printf("%s",str);fflush(stdout);
322 void ManGenerator::codify(const char *str)
324 //static char spaces[]=" ";
329 int spacesToNextTabStop;
335 case '.': t << "\\&."; break; // see bug652277
336 case '\t': spacesToNextTabStop =
337 Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
338 t << Doxygen::spaces.left(spacesToNextTabStop);
339 col+=spacesToNextTabStop;
341 case '\n': t << "\n"; firstCol=TRUE; col=0; break;
342 case '\\': t << "\\"; col++; break;
343 case '\"': c = '\''; // no break!
344 default: p=writeUtf8Char(t,p-1); firstCol=FALSE; col++; break;
347 //printf("%s",str);fflush(stdout);
352 void ManGenerator::writeChar(char c)
355 if (firstCol) col=0; else col++;
358 case '\\': t << "\\\\"; break;
359 case '\"': c = '\''; // no break!
360 default: t << c; break;
362 //printf("%c",c);fflush(stdout);
366 void ManGenerator::startDescList(SectionTypes)
369 { t << endl << ".PP" << endl;
370 firstCol=TRUE; paragraph=TRUE;
377 void ManGenerator::startTitle()
379 if (!firstCol) t << endl;
385 void ManGenerator::endTitle()
390 void ManGenerator::startItemListItem()
392 if (!firstCol) t << endl;
399 void ManGenerator::endItemListItem()
403 void ManGenerator::startCodeFragment()
411 void ManGenerator::endCodeFragment()
413 if (!firstCol) t << endl;
420 void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *,bool)
422 if (!firstCol) t << endl;
428 void ManGenerator::startDoxyAnchor(const char *,const char *manName,
429 const char *, const char *name,
432 // something to be done?
433 if( !Config_getBool("MAN_LINKS") )
438 // the name of the link file is derived from the name of the anchor:
439 // - truncate after an (optional) ::
440 QCString baseName = name;
441 int i=baseName.findRev("::");
442 if (i!=-1) baseName=baseName.right(baseName.length()-i-2);
444 //printf("Converting man link '%s'->'%s'->'%s'\n",
445 // name,baseName.data(),buildFileName(baseName).data());
447 // - remove dangerous characters and append suffix, then add dir prefix
448 QCString fileName=dir+"/"+buildFileName( baseName );
449 QFile linkfile( fileName );
450 // - only create file if it doesn't exist already
451 if ( !linkfile.open( IO_ReadOnly ) )
453 if ( linkfile.open( IO_WriteOnly ) )
455 FTextStream linkstream;
456 linkstream.setDevice(&linkfile);
457 //linkstream.setEncoding(QTextStream::UnicodeUTF8);
458 linkstream << ".so " << getSubdir() << "/" << buildFileName( manName ) << endl;
464 void ManGenerator::endMemberDoc(bool)
469 void ManGenerator::startSubsection()
471 if (!firstCol) t << endl;
477 void ManGenerator::endSubsection()
483 void ManGenerator::startSubsubsection()
485 if (!firstCol) t << endl;
491 void ManGenerator::endSubsubsection()
496 void ManGenerator::writeSynopsis()
498 if (!firstCol) t << endl;
499 t << ".SH SYNOPSIS\n.br\n.PP\n";
504 void ManGenerator::startDescItem()
506 if (!firstCol) t << endl;
511 //void ManGenerator::endDescTitle()
517 void ManGenerator::startDescForItem()
519 if (!firstCol) t << endl;
520 if (!paragraph) t << ".in -1c" << endl;
521 t << ".in +1c" << endl;
527 void ManGenerator::endDescForItem()
531 void ManGenerator::endDescItem()
533 t << "\" 1c" << endl;
537 void ManGenerator::startAnonTypeScope(int indentLevel)
545 void ManGenerator::endAnonTypeScope(int indentLevel)
554 void ManGenerator::startMemberItem(const char *,int,const char *)
556 if (firstCol && !insideTabbing) t << ".in +1c\n";
557 t << "\n.ti -1c\n.RI \"";
561 void ManGenerator::endMemberItem()
566 void ManGenerator::startMemberList()
570 t << "\n.in +1c"; firstCol=FALSE;
574 void ManGenerator::endMemberList()
578 t << "\n.in -1c"; firstCol=FALSE;
582 void ManGenerator::startMemberGroupHeader(bool)
584 t << "\n.PP\n.RI \"\\fB";
587 void ManGenerator::endMemberGroupHeader()
589 t << "\\fP\"\n.br\n";
593 void ManGenerator::startMemberGroupDocs()
597 void ManGenerator::endMemberGroupDocs()
602 void ManGenerator::startMemberGroup()
607 void ManGenerator::endMemberGroup(bool)
613 void ManGenerator::startSection(const char *,const char *,SectionInfo::SectionType type)
619 case SectionInfo::Page: startGroupHeader(FALSE); break;
620 case SectionInfo::Section: startGroupHeader(FALSE); break;
621 case SectionInfo::Subsection: startMemberHeader(0); break;
622 case SectionInfo::Subsubsection: startMemberHeader(0); break;
623 case SectionInfo::Paragraph: startMemberHeader(0); break;
624 default: ASSERT(0); break;
629 void ManGenerator::endSection(const char *,SectionInfo::SectionType type)
635 case SectionInfo::Page: endGroupHeader(0); break;
636 case SectionInfo::Section: endGroupHeader(0); break;
637 case SectionInfo::Subsection: endMemberHeader(); break;
638 case SectionInfo::Subsubsection: endMemberHeader(); break;
639 case SectionInfo::Paragraph: endMemberHeader(); break;
640 default: ASSERT(0); break;
652 void ManGenerator::startSimpleSect(SectionTypes,const char *,
653 const char *,const char *title)
656 { t << endl << ".PP" << endl;
657 firstCol=TRUE; paragraph=TRUE;
667 void ManGenerator::endSimpleSect()
671 void ManGenerator::startParamList(ParamListTypes,const char *title)
674 { t << endl << ".PP" << endl;
675 firstCol=TRUE; paragraph=TRUE;
685 void ManGenerator::endParamList()
689 void ManGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
691 ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""));
698 void ManGenerator::startConstraintList(const char *header)
701 { t << endl << ".PP" << endl;
702 firstCol=TRUE; paragraph=TRUE;
712 void ManGenerator::startConstraintParam()
718 void ManGenerator::endConstraintParam()
725 void ManGenerator::startConstraintType()
730 void ManGenerator::endConstraintType()
735 void ManGenerator::startConstraintDocs()
739 void ManGenerator::endConstraintDocs()
741 t << endl; firstCol=TRUE;
744 void ManGenerator::endConstraintList()
749 void ManGenerator::startInlineHeader()
753 t << endl << ".PP" << endl << ".in -1c" << endl;
758 void ManGenerator::endInlineHeader()
760 t << "\\fP\"" << endl << ".in +1c" << endl;
764 void ManGenerator::startMemberDocSimple()
768 t << endl << ".PP" << endl;
771 docify(theTranslator->trCompoundMembers());
772 t << ":\\fP" << endl;
773 t << ".RS 4" << endl;
776 void ManGenerator::endMemberDocSimple()
778 if (!firstCol) t << endl;
784 void ManGenerator::startInlineMemberType()
788 void ManGenerator::endInlineMemberType()
793 void ManGenerator::startInlineMemberName()
798 void ManGenerator::endInlineMemberName()
803 void ManGenerator::startInlineMemberDoc()
807 void ManGenerator::endInlineMemberDoc()
809 if (!firstCol) t << endl;
815 void ManGenerator::startLabels()
819 void ManGenerator::writeLabel(const char *l,bool isLast)
821 t << "\\fC [" << l << "]\\fP";
822 if (!isLast) t << ", ";
825 void ManGenerator::endLabels()
829 void ManGenerator::endHeaderSection()
833 t<< endl; firstCol=TRUE;