为什么标题上有两个DATE(1) 的追踪过程
我们通过
man -aw date
得到
/usr/share/man/man1/date.1.gz
用zcat观察
zcat /usr/share/man/man1/date.1.gz |less
可以看到第一行是
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
.TH DATE "1" "February 2017" "GNU coreutils 8.25" "User Commands"
.SH NAME
date \- print or set the system date and time
.SH SYNOPSIS
.B date
[\fI\,OPTION\/\fR]... [\fI\,+FORMAT\/\fR]
.br
.B date
......
这里 .TH DATE "1"
便是DATE(1)的出处, 但为什两个呢? 继续挖
用grep过滤
zcat /usr/share/man/man1/date.1.gz | grep 'DATE \"1\"'
搜索仅有一行输出
查找man源码
$ which man
/usr/bin/man
$ dpkg --search /usr/bin/man
man-db: /usr/bin/man
$ apt-get source man-db
狂看一天之后, 发现man-db用的是pipeline,格式化和最终的输出调用的都是外部指令
/* Return pipeline to format file to stdout. */
static pipeline *make_roff_command (const char *dir, const char *file,
pipeline *decomp, const char *dbfilters,
char **result_encoding)
......
从这个函数的内容里, 发现主要是调用的roff/nroff/troff/groff
这一组格式化命令来完成的.
创建一个小文件a.txt,包含如下内容
.TH MAN 7 2012-08-05 "Linux" "Linux Programmer's Manual"
.SH NAME
man \- macros to format man pages
用groff试下
$ groff -mandoc -T ascii a.txt
输出了以下内容
MAN(7) Linux Programmer's Manual MAN(7)
NAME
man - macros to format man pages
Linux 2012-08-05 MAN(7)
果然是我想要的.
用strace查看调用过程
还是pipe调用....
下载groff源码
$ apt-get source groff
发现可以用-V
参数查看pipeline命令
$ groff -V -mandoc -T ascii a.txt
troff -mandoc -Tascii a.txt | grotty
单独执行troff
troff -mandoc -Tascii a.txt
得到
x T ascii
x res 240 24 40
x init
p1
x X tty: sgr 0
x font 1 R
f1
s10
V40
H0
md
DFd
tMAN(7)
h504
tLinux
wh24
tProgrammer's
wh24
tManual
h480
tMAN(7)
......
从这里可以看到在a.txt
里只出现一次的MAN(7)
被输出了两次.
troff源码分析
troff 源码也在groff包里.
搜索源码并没有找到直接处理.TH
标记的地方, 发现troff与man的宏有关.
troff与宏指令man macros
通过以下指令得到troff在运行过程中打开过的.tmac
宏文件
$ strace troff -mandoc -Tascii ~/a.txt 2>&1 |grep -v such | grep tmac
输出如下
open("/usr/share/groff/1.22.3/tmac/troffrc", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/composite.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/fallbacks.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/tty.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/hyphen.us", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/hyphenex.us", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/papersize.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/pspic.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/andoc.tmac", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/troffrc-end", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/an-old.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/devtag.tmac", O_RDONLY) = 5
open("/usr/share/groff/1.22.3/tmac/an-ext.tmac", O_RDONLY) = 5
open("/usr/share/groff/site-tmac/man.local", O_RDONLY) = 5
在相应目录下只找到少处和.TH
处理有关的片断
/usr/share/groff/1.22.3/tmac$ grep -w TH -R *
andoc.tmac:. als TH reload-man
andoc.tmac:. rm TH
andoc.tmac:\\*[TH]\\
andoc.tmac:.als TH reload-man
andoc.tmac:.\" dummy equation macros -- eqnrc is read before .TH or .Dd is parsed
an-old.tmac:.\" If you need to add things to TH, use `.am1 TH'.
an-old.tmac:.\" .TH title section extra1 extra2 extra3
an-old.tmac: TH
.tmac
文件格式在这里有详细的介绍:
doc.tmac 主手册宏包
mdoc.tmac 对 doc.tmac调用的封装
mdoc/doc-common 共用字符串,定义,与印刷输出相关内容.
mdoc/doc-nroff 用于 TTY设备输出的定义.
mdoc/doc-ditroff 用于其它设备输出的定义
mdoc.local 本地补充与客户化相关.
andoc.tmac 如果你搞不清是该用 -mdoc 还是 -man 包时就用这个.
真相大白
最终在an-old.tmac
层层定义的宏里找到了这行:
259 .de1 PT
260 . tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
261 ..
编辑保存, 果然如此
. tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]' [Eureka!] \\*[an-title](\\*[an-section])'
截图留念
这里有man-db有相关的中文文档.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。