My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mandocvisitor.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  *
6  * Copyright (C) 1997-2015 by Dimitri van Heesch.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation under the terms of the GNU General Public License is hereby
10  * granted. No representations are made about the suitability of this software
11  * for any purpose. It is provided "as is" without express or implied warranty.
12  * See the GNU General Public License for more details.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18 
19 #include <qfileinfo.h>
20 
21 #include "mandocvisitor.h"
22 #include "docparser.h"
23 #include "language.h"
24 #include "doxygen.h"
25 #include "outputgen.h"
26 #include "code.h"
27 #include "dot.h"
28 #include "util.h"
29 #include "message.h"
30 #include "parserintf.h"
31 #include "filedef.h"
32 #include "htmlentity.h"
33 
35  const char *langExt)
36  : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE),
37  m_indent(0), m_langExt(langExt)
38 {
39 }
40 
41  //--------------------------------------
42  // visitor functions for leaf nodes
43  //--------------------------------------
44 
46 {
47  if (m_hide) return;
48  filter(w->word());
49  m_firstCol=FALSE;
50 }
51 
53 {
54  if (m_hide) return;
55  m_t << "\\fB";
56  filter(w->word());
57  m_t << "\\fP";
58  m_firstCol=FALSE;
59 }
60 
62 {
63  if (m_hide) return;
64  if (m_insidePre)
65  {
66  m_t << w->chars();
67  m_firstCol=w->chars().at(w->chars().length()-1)=='\n';
68  }
69  else
70  {
71  m_t << " ";
72  m_firstCol=FALSE;
73  }
74 }
75 
77 {
78  if (m_hide) return;
79  const char *res = HtmlEntityMapper::instance()->man(s->symbol());
80  if (res)
81  {
82  m_t << res;
83  }
84  else
85  {
86  // no error or warning to be supplied
87  // err("man: non supported HTML-entity found: &%s;\n",get_symbol_item(s->symbol()));
88  }
89  m_firstCol=FALSE;
90 }
91 
93 {
94  if (m_hide) return;
95  m_t << u->url();
96  m_firstCol=FALSE;
97 }
98 
100 {
101  if (m_hide) return;
102  m_t << endl << ".br" << endl;
103  m_firstCol=TRUE;
104 }
105 
107 {
108  if (m_hide) return;
109  if (!m_firstCol) m_t << endl;
110  m_t << ".PP" << endl;
111  m_firstCol=TRUE;
112 }
113 
115 {
116  if (m_hide) return;
117  switch (s->style())
118  {
120  if (s->enable()) m_t << "\\fB"; else m_t << "\\fP";
121  m_firstCol=FALSE;
122  break;
124  if (s->enable()) m_t << "\\fI"; else m_t << "\\fP";
125  m_firstCol=FALSE;
126  break;
128  if (s->enable()) m_t << "\\fC"; else m_t << "\\fP";
129  m_firstCol=FALSE;
130  break;
132  if (s->enable()) m_t << "\\*<"; else m_t << "\\*> ";
133  m_firstCol=FALSE;
134  break;
136  if (s->enable()) m_t << "\\*{"; else m_t << "\\*} ";
137  m_firstCol=FALSE;
138  break;
140  /* not supported */
141  break;
143  /* not supported */
144  break;
146  if (s->enable())
147  {
148  if (!m_firstCol) m_t << endl;
149  m_t << ".PP" << endl;
150  m_t << ".nf" << endl;
151  m_insidePre=TRUE;
152  }
153  else
154  {
155  m_insidePre=FALSE;
156  if (!m_firstCol) m_t << endl;
157  m_t << ".fi" << endl;
158  m_t << ".PP" << endl;
159  m_firstCol=TRUE;
160  }
161  break;
162  case DocStyleChange::Div: /* HTML only */ break;
163  case DocStyleChange::Span: /* HTML only */ break;
164  }
165 }
166 
168 {
169  if (m_hide) return;
170  QCString lang = m_langExt;
171  if (!s->language().isEmpty()) // explicit language setting
172  {
173  lang = s->language();
174  }
175  SrcLangExt langExt = getLanguageFromFileName(lang);
176  switch (s->type())
177  {
178  case DocVerbatim::Code: // fall though
179  if (!m_firstCol) m_t << endl;
180  m_t << ".PP" << endl;
181  m_t << ".nf" << endl;
183  ->parseCode(m_ci,s->context(),s->text(),
184  langExt,
185  s->isExample(),s->exampleFile());
186  if (!m_firstCol) m_t << endl;
187  m_t << ".fi" << endl;
188  m_t << ".PP" << endl;
189  m_firstCol=TRUE;
190  break;
191  case DocVerbatim::Verbatim:
192  if (!m_firstCol) m_t << endl;
193  m_t << ".PP" << endl;
194  m_t << ".nf" << endl;
195  m_t << s->text();
196  if (!m_firstCol) m_t << endl;
197  m_t << ".fi" << endl;
198  m_t << ".PP" << endl;
199  m_firstCol=TRUE;
200  break;
201  case DocVerbatim::ManOnly:
202  m_t << s->text();
203  break;
204  case DocVerbatim::HtmlOnly:
205  case DocVerbatim::XmlOnly:
209  case DocVerbatim::Dot:
210  case DocVerbatim::Msc:
211  case DocVerbatim::PlantUML:
212  /* nothing */
213  break;
214  }
215 }
216 
218 {
219  /* no support for anchors in man pages */
220 }
221 
223 {
224  if (m_hide) return;
225  SrcLangExt langExt = getLanguageFromFileName(inc->extension());
226  switch(inc->type())
227  {
229  {
230  if (!m_firstCol) m_t << endl;
231  m_t << ".PP" << endl;
232  m_t << ".nf" << endl;
233  QFileInfo cfi( inc->file() );
234  FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
236  ->parseCode(m_ci,inc->context(),
237  inc->text(),
238  langExt,
239  inc->isExample(),
240  inc->exampleFile(),
241  &fd, // fileDef,
242  -1, // start line
243  -1, // end line
244  FALSE, // inline fragment
245  0, // memberDef
246  TRUE
247  );
248  if (!m_firstCol) m_t << endl;
249  m_t << ".fi" << endl;
250  m_t << ".PP" << endl;
251  m_firstCol=TRUE;
252  }
253  break;
254  case DocInclude::Include:
255  if (!m_firstCol) m_t << endl;
256  m_t << ".PP" << endl;
257  m_t << ".nf" << endl;
259  ->parseCode(m_ci,inc->context(),
260  inc->text(),
261  langExt,
262  inc->isExample(),
263  inc->exampleFile(),
264  0, // fileDef
265  -1, // startLine
266  -1, // endLine
267  TRUE, // inlineFragment
268  0, // memberDef
269  FALSE
270  );
271  if (!m_firstCol) m_t << endl;
272  m_t << ".fi" << endl;
273  m_t << ".PP" << endl;
274  m_firstCol=TRUE;
275  break;
277  break;
279  break;
281  break;
283  if (!m_firstCol) m_t << endl;
284  m_t << ".PP" << endl;
285  m_t << ".nf" << endl;
286  m_t << inc->text();
287  if (!m_firstCol) m_t << endl;
288  m_t << ".fi" << endl;
289  m_t << ".PP" << endl;
290  m_firstCol=TRUE;
291  break;
292  case DocInclude::Snippet:
293  if (!m_firstCol) m_t << endl;
294  m_t << ".PP" << endl;
295  m_t << ".nf" << endl;
297  ->parseCode(m_ci,
298  inc->context(),
299  extractBlock(inc->text(),inc->blockId()),
300  langExt,
301  inc->isExample(),
302  inc->exampleFile()
303  );
304  if (!m_firstCol) m_t << endl;
305  m_t << ".fi" << endl;
306  m_t << ".PP" << endl;
307  m_firstCol=TRUE;
308  break;
311  err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
312  "Please create a bug report\n",__FILE__);
313  break;
314  }
315 }
316 
318 {
320  //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
321  // op->type(),op->isFirst(),op->isLast(),op->text().data());
322  if (op->isFirst())
323  {
324  if (!m_hide)
325  {
326  if (!m_firstCol) m_t << endl;
327  m_t << ".PP" << endl;
328  m_t << ".nf" << endl;
329  }
330  pushEnabled();
331  m_hide = TRUE;
332  }
333  if (op->type()!=DocIncOperator::Skip)
334  {
335  popEnabled();
336  if (!m_hide)
337  {
339  ->parseCode(m_ci,op->context(),op->text(),langExt,
340  op->isExample(),op->exampleFile());
341  }
342  pushEnabled();
343  m_hide=TRUE;
344  }
345  if (op->isLast())
346  {
347  popEnabled();
348  if (!m_hide)
349  {
350  if (!m_firstCol) m_t << endl;
351  m_t << ".fi" << endl;
352  m_t << ".PP" << endl;
353  m_firstCol=TRUE;
354  }
355  }
356  else
357  {
358  if (!m_hide) m_t << endl;
359  }
360 }
361 
363 {
364  if (m_hide) return;
365  m_t << f->text();
366 }
367 
369 {
370 }
371 
373 {
374 }
375 
377 {
378  if (m_hide) return;
379  m_t << "\\fB";
380  if (cite->file().isEmpty()) m_t << "[";
381  filter(cite->text());
382  if (cite->file().isEmpty()) m_t << "]";
383  m_t << "\\fP";
384 }
385 
386 
387 //--------------------------------------
388 // visitor functions for compound nodes
389 //--------------------------------------
390 
392 {
393  if (m_hide) return;
394  m_indent+=2;
395 }
396 
398 {
399  if (m_hide) return;
400  m_indent-=2;
401  m_t << ".PP" << endl;
402 }
403 
405 {
406  if (m_hide) return;
407  QCString ws;
408  ws.fill(' ',m_indent-2);
409  if (!m_firstCol) m_t << endl;
410  m_t << ".IP \"" << ws;
411  if (((DocAutoList *)li->parent())->isEnumList())
412  {
413  m_t << li->itemNumber() << ".\" " << m_indent+2;
414  }
415  else // bullet list
416  {
417  m_t << "\\(bu\" " << m_indent;
418  }
419  m_t << endl;
420  m_firstCol=TRUE;
421 }
422 
424 {
425  if (m_hide) return;
426  m_t << endl;
427  m_firstCol=TRUE;
428 }
429 
431 {
432 }
433 
435 {
436  if (m_hide) return;
437  if (!p->isLast() && // omit <p> for last paragraph
438  !(p->parent() && // and for parameter sections
440  )
441  )
442  {
443  if (!m_firstCol) m_t << endl;
444  m_t << ".PP" << endl;
445  m_firstCol=TRUE;
446  }
447 }
448 
450 {
451 }
452 
454 {
455 }
456 
458 {
459  if (m_hide) return;
460  if (!m_firstCol)
461  {
462  m_t << endl;
463  m_t << ".PP" << endl;
464  }
465  m_t << "\\fB";
466  switch(s->type())
467  {
468  case DocSimpleSect::See:
469  m_t << theTranslator->trSeeAlso(); break;
470  case DocSimpleSect::Return:
471  m_t << theTranslator->trReturns(); break;
472  case DocSimpleSect::Author:
473  m_t << theTranslator->trAuthor(TRUE,TRUE); break;
475  m_t << theTranslator->trAuthor(TRUE,FALSE); break;
477  m_t << theTranslator->trVersion(); break;
478  case DocSimpleSect::Since:
479  m_t << theTranslator->trSince(); break;
480  case DocSimpleSect::Date:
481  m_t << theTranslator->trDate(); break;
482  case DocSimpleSect::Note:
483  m_t << theTranslator->trNote(); break;
485  m_t << theTranslator->trWarning(); break;
486  case DocSimpleSect::Pre:
487  m_t << theTranslator->trPrecondition(); break;
488  case DocSimpleSect::Post:
489  m_t << theTranslator->trPostcondition(); break;
491  m_t << theTranslator->trCopyright(); break;
493  m_t << theTranslator->trInvariant(); break;
495  m_t << theTranslator->trRemarks(); break;
497  m_t << theTranslator->trAttention(); break;
498  case DocSimpleSect::User: break;
499  case DocSimpleSect::Rcs: break;
500  case DocSimpleSect::Unknown: break;
501  }
502 
503  // special case 1: user defined title
504  if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
505  {
506  m_t << ":\\fP" << endl;
507  m_t << ".RS 4" << endl;
508  }
509 }
510 
512 {
513  if (m_hide) return;
514  if (!m_firstCol) m_t << endl;
515  m_t << ".RE" << endl;
516  m_t << ".PP" << endl;
517  m_firstCol=TRUE;
518 }
519 
521 {
522 }
523 
525 {
526  if (m_hide) return;
527  m_t << "\\fP" << endl;
528  m_t << ".RS 4" << endl;
529 }
530 
532 {
533  if (m_hide) return;
534  m_indent+=2;
535  if (!m_firstCol) m_t << endl;
536  m_t << ".PD 0" << endl;
537 }
538 
540 {
541  if (m_hide) return;
542  m_indent-=2;
543  m_t << ".PP" << endl;
544 }
545 
547 {
548  if (m_hide) return;
549  QCString ws;
550  ws.fill(' ',m_indent-2);
551  if (!m_firstCol) m_t << endl;
552  m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
553  m_firstCol=TRUE;
554 }
555 
557 {
558  if (m_hide) return;
559  m_t << endl;
560  m_firstCol=TRUE;
561 }
562 
564 {
565  if (m_hide) return;
566  if (!m_firstCol) m_t << endl;
567  if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
568  m_t << " \"";
569  filter(s->title());
570  m_t << "\"" << endl;
571  if (s->level()==1) m_t << ".PP" << endl;
572  m_firstCol=TRUE;
573 }
574 
576 {
577 }
578 
580 {
581  if (m_hide) return;
582  m_indent+=2;
583  if (!m_firstCol) m_t << endl;
584  m_t << ".PD 0" << endl;
585 }
586 
588 {
589  if (m_hide) return;
590  m_indent-=2;
591  if (!m_firstCol) m_t << endl;
592  m_t << ".PP" << endl;
593 }
594 
596 {
597  if (m_hide) return;
598  QCString ws;
599  ws.fill(' ',m_indent-2);
600  if (!m_firstCol) m_t << endl;
601  m_t << ".IP \"" << ws;
602  if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
603  {
604  m_t << li->itemNumber() << ".\" " << m_indent+2;
605  }
606  else // bullet list
607  {
608  m_t << "\\(bu\" " << m_indent;
609  }
610  m_t << endl;
611  m_firstCol=TRUE;
612 }
613 
615 {
616  if (m_hide) return;
617  m_t << endl;
618  m_firstCol=TRUE;
619 }
620 
621 //void ManDocVisitor::visitPre(DocHtmlPre *)
622 //{
623 // if (!m_firstCol) m_t << endl;
624 // m_t << ".PP" << endl;
625 // m_t << ".nf" << endl;
626 // m_insidePre=TRUE;
627 //}
628 //
629 //void ManDocVisitor::visitPost(DocHtmlPre *)
630 //{
631 // m_insidePre=FALSE;
632 // if (!m_firstCol) m_t << endl;
633 // m_t << ".fi" << endl;
634 // m_t << ".PP" << endl;
635 // m_firstCol=TRUE;
636 //}
637 
639 {
640 }
641 
643 {
644  if (m_hide) return;
645  if (!m_firstCol) m_t << endl;
646  m_t << ".PP" << endl;
647  m_firstCol=TRUE;
648 }
649 
651 {
652  if (m_hide) return;
653  if (!m_firstCol) m_t << endl;
654  m_t << ".IP \"\\fB";
655  m_firstCol=FALSE;
656 }
657 
659 {
660  if (m_hide) return;
661  m_t << "\\fP\" 1c" << endl;
662  m_firstCol=TRUE;
663 }
664 
666 {
667 }
668 
670 {
671 }
672 
674 {
675 }
676 
678 {
679 }
680 
682 {
683 }
684 
686 {
687 }
688 
690 {
691 }
692 
694 {
695 }
696 
698 {
699 }
700 
702 {
703 }
704 
706 {
707  if (m_hide) return;
708  //if (!m_firstCol) m_t << endl;
709  //m_t << ".PP" << endl;
710  //m_t << "\\fB" << theTranslator->trForInternalUseOnly() << "\\fP" << endl;
711  //m_t << ".RS 4" << endl;
712 }
713 
715 {
716  if (m_hide) return;
717  //if (!m_firstCol) m_t << endl;
718  //m_t << ".RE" << endl;
719  //m_t << ".PP" << endl;
720  //m_firstCol=TRUE;
721 }
722 
724 {
725  if (m_hide) return;
726  m_t << "\\fC";
727 }
728 
730 {
731  if (m_hide) return;
732  m_t << "\\fP";
733 }
734 
736 {
737  if (m_hide) return;
738  if (!m_firstCol) m_t << endl;
739  if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
740  m_t << " \"";
741 }
742 
744 {
745  if (m_hide) return;
746  m_t << "\"" << endl;
747  if (header->level()==1) m_t << ".PP" << endl;
748  m_firstCol=TRUE;
749 }
750 
752 {
753 }
754 
756 {
757 }
758 
760 {
761 }
762 
764 {
765 }
767 {
768 }
769 
771 {
772 }
773 
775 {
776 }
777 
779 {
780 }
781 
783 {
784  if (m_hide) return;
785  m_t << "\\fB";
786 }
787 
789 {
790  if (m_hide) return;
791  m_t << "\\fP";
792 }
793 
795 {
796  if (m_hide) return;
797  m_t << "\\fB";
798  if (!ref->hasLinkText()) filter(ref->targetTitle());
799 }
800 
802 {
803  if (m_hide) return;
804  m_t << "\\fP";
805 }
806 
808 {
809  if (m_hide) return;
810  QCString ws;
811  ws.fill(' ',m_indent-2);
812  if (!m_firstCol) m_t << endl;
813  m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
814  m_firstCol=TRUE;
815 }
816 
818 {
819  if (m_hide) return;
820  m_t << endl;
821  m_firstCol=TRUE;
822 }
823 
825 {
826  if (m_hide) return;
827  m_indent+=2;
828 }
829 
831 {
832  if (m_hide) return;
833  m_indent-=2;
834  if (!m_firstCol) m_t << endl;
835  m_t << ".PP" << endl;
836 }
837 
838 //void ManDocVisitor::visitPre(DocLanguage *l)
839 //{
840 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
841 // if (l->id().lower()!=langId.lower())
842 // {
843 // pushEnabled();
844 // m_hide = TRUE;
845 // }
846 //}
847 //
848 //void ManDocVisitor::visitPost(DocLanguage *l)
849 //{
850 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
851 // if (l->id().lower()!=langId.lower())
852 // {
853 // popEnabled();
854 // }
855 //}
856 
858 {
859  if (m_hide) return;
860  if (!m_firstCol)
861  {
862  m_t << endl;
863  m_t << ".PP" << endl;
864  }
865  m_t << "\\fB";
866  switch(s->type())
867  {
868  case DocParamSect::Param:
869  m_t << theTranslator->trParameters(); break;
870  case DocParamSect::RetVal:
871  m_t << theTranslator->trReturnValues(); break;
873  m_t << theTranslator->trExceptions(); break;
875  /* TODO: add this
876  m_t << theTranslator->trTemplateParam(); break;
877  */
878  m_t << "Template Parameters"; break;
879  default:
880  ASSERT(0);
881  }
882  m_t << ":\\fP" << endl;
883  m_t << ".RS 4" << endl;
884 }
885 
887 {
888  if (m_hide) return;
889  if (!m_firstCol) m_t << endl;
890  m_t << ".RE" << endl;
891  m_t << ".PP" << endl;
892  m_firstCol=TRUE;
893 }
894 
896 {
897  if (m_hide) return;
898  m_t << "\\fI";
899  //QStrListIterator li(pl->parameters());
900  //const char *s;
901  QListIterator<DocNode> li(pl->parameters());
902  DocNode *param;
903  bool first=TRUE;
904  for (li.toFirst();(param=li.current());++li)
905  {
906  if (!first) m_t << ","; else first=FALSE;
907  if (param->kind()==DocNode::Kind_Word)
908  {
909  visit((DocWord*)param);
910  }
911  else if (param->kind()==DocNode::Kind_LinkedWord)
912  {
913  visit((DocLinkedWord*)param);
914  }
915  }
916  m_t << "\\fP ";
917 }
918 
920 {
921  if (m_hide) return;
922  if (!pl->isLast())
923  {
924  if (!m_firstCol) m_t << endl;
925  m_t << ".br" << endl;
926  }
927 }
928 
930 {
931  if (m_hide) return;
932  if (x->title().isEmpty()) return;
933  if (!m_firstCol)
934  {
935  m_t << endl;
936  m_t << ".PP" << endl;
937  }
938  m_t << "\\fB";
939  filter(x->title());
940  m_t << "\\fP" << endl;
941  m_t << ".RS 4" << endl;
942 }
943 
945 {
946  if (m_hide) return;
947  if (x->title().isEmpty()) return;
948  if (!m_firstCol) m_t << endl;
949  m_t << ".RE" << endl;
950  m_t << ".PP" << endl;
951  m_firstCol=TRUE;
952 }
953 
955 {
956  if (m_hide) return;
957  m_t << "\\fB";
958 }
959 
961 {
962  if (m_hide) return;
963  m_t << "\\fP";
964 }
965 
967 {
968 }
969 
971 {
972 }
973 
975 {
976 }
977 
979 {
980 }
981 
983 {
984  if (m_hide) return;
985  if (!m_firstCol)
986  {
987  m_t << endl;
988  m_t << ".PP" << endl;
989  }
990  m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
991 }
992 
994 {
995  if (m_hide) return;
996  if (!m_firstCol) m_t << endl;
997  m_t << ".RE" << endl;
998  m_t << ".PP" << endl;
999  m_firstCol=TRUE;
1000 }
1001 
1003 {
1004 }
1005 
1007 {
1008 }
1009 
1011 {
1012 }
1013 
1015 {
1016 }
1017 
1018 
1019 void ManDocVisitor::filter(const char *str)
1020 {
1021  if (str)
1022  {
1023  const char *p=str;
1024  char c=0;
1025  while ((c=*p++))
1026  {
1027  switch(c)
1028  {
1029  case '.': m_t << "\\&."; break; // see bug652277
1030  case '\\': m_t << "\\\\"; break;
1031  case '"': c = '\''; // fall through
1032  default: m_t << c; break;
1033  }
1034  }
1035  }
1036 }
1037 
1039 {
1040  m_enabled.push(new bool(m_hide));
1041 }
1042 
1044 {
1045  bool *v=m_enabled.pop();
1046  ASSERT(v!=0);
1047  m_hide = *v;
1048  delete v;
1049 }
1050