為什麼標題上有兩個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有相關的中文文件.