xref: /plan9/sys/lib/man/checkman.awk (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier# Usage: awk -f checkman.awk man?/*.?
23e12c5d1SDavid du Colombier#
33e12c5d1SDavid du Colombier# Checks:
43e12c5d1SDavid du Colombier#	- .TH is first line, and has proper name section number
5*219b2ee8SDavid du Colombier#	- sections are in order NAME, SYNOPSIS, DESCRIPTION, EXAMPLES,
6*219b2ee8SDavid du Colombier#		FILES, SOURCE, SEE ALSO, DIAGNOSTICS, BUGS
73e12c5d1SDavid du Colombier#	- there's a manual page for each cross-referenced page
83e12c5d1SDavid du Colombier
93e12c5d1SDavid du ColombierBEGIN {
103e12c5d1SDavid du Colombier
113e12c5d1SDavid du Colombier#	.SH sections should come in the following order
123e12c5d1SDavid du Colombier
133e12c5d1SDavid du Colombier	Weight["NAME"] = 1
143e12c5d1SDavid du Colombier	Weight["SYNOPSIS"] = 2
153e12c5d1SDavid du Colombier	Weight["DESCRIPTION"] = 4
163e12c5d1SDavid du Colombier	Weight["EXAMPLE"] = 8
173e12c5d1SDavid du Colombier	Weight["EXAMPLES"] = 16
183e12c5d1SDavid du Colombier	Weight["FILES"] = 32
19*219b2ee8SDavid du Colombier	Weight["SOURCE"] = 64
20*219b2ee8SDavid du Colombier	Weight["SEE ALSO"] = 128
21*219b2ee8SDavid du Colombier	Weight["DIAGNOSTICS"] = 256
22*219b2ee8SDavid du Colombier	Weight["SYSTEM CALLS"] = 512
23*219b2ee8SDavid du Colombier	Weight["BUGS"] = 1024
243e12c5d1SDavid du Colombier}
253e12c5d1SDavid du Colombier
263e12c5d1SDavid du ColombierFNR==1	{
273e12c5d1SDavid du Colombier		n = length(FILENAME)
283e12c5d1SDavid du Colombier		seclen = 0
293e12c5d1SDavid du Colombier		if (substr(FILENAME, 2, 1) == "/")
303e12c5d1SDavid du Colombier			seclen = 1
313e12c5d1SDavid du Colombier		else if (substr(FILENAME, 3, 1) == "/")
323e12c5d1SDavid du Colombier			seclen = 2
333e12c5d1SDavid du Colombier		if(seclen == 0)
343e12c5d1SDavid du Colombier			print "FILENAME", FILENAME, "not of form [0-9][0-9]?/*"
353e12c5d1SDavid du Colombier		else if(!(substr(FILENAME, seclen+2, n-seclen-1) ~ /^[A-Z]+$/)){
363e12c5d1SDavid du Colombier			section = substr(FILENAME, 1, seclen)
373e12c5d1SDavid du Colombier			name = substr(FILENAME, seclen+2, n-seclen-1)
383e12c5d1SDavid du Colombier			if($1 != ".TH" || NF != 3)
393e12c5d1SDavid du Colombier				print "First line of", FILENAME, "not a proper .TH"
403e12c5d1SDavid du Colombier			else if($2 != toupper(name) || substr($3, 1, seclen) != section){
413e12c5d1SDavid du Colombier				if($2!="INTRO" || name!="0intro")
423e12c5d1SDavid du Colombier					print ".TH of", FILENAME, "doesn't match filename"
433e12c5d1SDavid du Colombier			}else
443e12c5d1SDavid du Colombier				Pages[section "/" $2] = 1
453e12c5d1SDavid du Colombier		}
463e12c5d1SDavid du Colombier		Sh = 0
473e12c5d1SDavid du Colombier	}
483e12c5d1SDavid du Colombier
493e12c5d1SDavid du Colombier$1 == ".SH" {
50*219b2ee8SDavid du Colombier		if(inex)
51*219b2ee8SDavid du Colombier			print "Unterminated .EX in", FILENAME, ":", $0
52*219b2ee8SDavid du Colombier		inex = 0;
533e12c5d1SDavid du Colombier		if (substr($2, 1, 1) == "\"") {
543e12c5d1SDavid du Colombier			if (NF == 2) {
553e12c5d1SDavid du Colombier				print "Unneeded quote in", FILENAME, ":", $0
563e12c5d1SDavid du Colombier				$2 = substr($2, 2, length($2)-2)
573e12c5d1SDavid du Colombier			} else if (NF == 3) {
583e12c5d1SDavid du Colombier				$2 = substr($2, 2) substr($3, 1, length($3)-1)
593e12c5d1SDavid du Colombier				NF = 2
603e12c5d1SDavid du Colombier			}
613e12c5d1SDavid du Colombier		}
623e12c5d1SDavid du Colombier		w = Weight[$2]
633e12c5d1SDavid du Colombier		if (w) {
643e12c5d1SDavid du Colombier			if (w < Sh)
653e12c5d1SDavid du Colombier				print "Heading", $2, "out of order in", FILENAME
663e12c5d1SDavid du Colombier			Sh += w
673e12c5d1SDavid du Colombier		}
683e12c5d1SDavid du Colombier}
693e12c5d1SDavid du Colombier
70*219b2ee8SDavid du Colombier$1 == ".EX" {
71*219b2ee8SDavid du Colombier		if(inex)
72*219b2ee8SDavid du Colombier			print "Nested .EX in", FILENAME, ":", $0
73*219b2ee8SDavid du Colombier		inex = 1
74*219b2ee8SDavid du Colombier}
75*219b2ee8SDavid du Colombier
76*219b2ee8SDavid du Colombier$1 == ".EE" {
77*219b2ee8SDavid du Colombier		if(!inex)
78*219b2ee8SDavid du Colombier			print "Bad .EE in", FILENAME, ":", $0
79*219b2ee8SDavid du Colombier		inex = 0;
80*219b2ee8SDavid du Colombier}
81*219b2ee8SDavid du Colombier
823e12c5d1SDavid du Colombier$0 ~ /^\..*\([0-9]\)/ {
833e12c5d1SDavid du Colombier		if ($1 == ".IR" && $3 ~ /\([0-9]\)/) {
843e12c5d1SDavid du Colombier			name = $2
853e12c5d1SDavid du Colombier			section = $3
86*219b2ee8SDavid du Colombier		}else if ($1 == ".RI" && $2 == "(" && $4 ~ /\([0-9]\)/) {
87*219b2ee8SDavid du Colombier			name = $3
88*219b2ee8SDavid du Colombier			section = $4
893e12c5d1SDavid du Colombier		}else if ($1 == ".IR" && $3 ~ /9.\([0-9]\)/) {
903e12c5d1SDavid du Colombier			name = $2
913e12c5d1SDavid du Colombier			section = "9"
92*219b2ee8SDavid du Colombier		}else if ($1 == ".RI" && $2 == "(" && $4 ~ /9.\([0-9]\)/) {
93*219b2ee8SDavid du Colombier			name = $3
94*219b2ee8SDavid du Colombier			section = "9"
953e12c5d1SDavid du Colombier		} else {
963e12c5d1SDavid du Colombier			print "Possible bad cross-reference format in", FILENAME
973e12c5d1SDavid du Colombier			print $0
983e12c5d1SDavid du Colombier			next
993e12c5d1SDavid du Colombier		}
1003e12c5d1SDavid du Colombier		gsub(/[^0-9]/, "", section)
1013e12c5d1SDavid du Colombier		Refs[section "/" toupper(name)]++
1023e12c5d1SDavid du Colombier}
1033e12c5d1SDavid du Colombier
1043e12c5d1SDavid du ColombierEND {
1053e12c5d1SDavid du Colombier	print "Checking Cross-Referenced Pages"
1063e12c5d1SDavid du Colombier	for (i in Refs) {
1073e12c5d1SDavid du Colombier		if (!(i in Pages))
1083e12c5d1SDavid du Colombier			print "Need", tolower(i)
1093e12c5d1SDavid du Colombier	}
1103e12c5d1SDavid du Colombier	print ""
1113e12c5d1SDavid du Colombier	print "Checking commands"
1123e12c5d1SDavid du Colombier	getindex("/sys/man/1")
1133e12c5d1SDavid du Colombier	getindex("/sys/man/4")
1143e12c5d1SDavid du Colombier	getindex("/sys/man/7")
1153e12c5d1SDavid du Colombier	getindex("/sys/man/8")
1163e12c5d1SDavid du Colombier	getindex("/sys/man/9")
1173e12c5d1SDavid du Colombier	getindex("/sys/man/10")
1183e12c5d1SDavid du Colombier	Skipdirs["X11"] = 1
1193e12c5d1SDavid du Colombier	Skipdirs["ape"] = 1
1203e12c5d1SDavid du Colombier	Skipdirs["aux"] = 1
1213e12c5d1SDavid du Colombier	Skipdirs["c++"] = 1
1223e12c5d1SDavid du Colombier	Skipdirs["help"] = 1
1233e12c5d1SDavid du Colombier	Skipdirs["lbp"] = 1
1243e12c5d1SDavid du Colombier	Skipdirs["m"] = 1
1253e12c5d1SDavid du Colombier	Skipdirs["scsi"] = 1
1263e12c5d1SDavid du Colombier	getbinlist("/mips/bin")
1273e12c5d1SDavid du Colombier	getbinlist("/rc/bin")
1283e12c5d1SDavid du Colombier	for (i in List) {
1293e12c5d1SDavid du Colombier		if (!(i in Index))
1303e12c5d1SDavid du Colombier			print "Need", i, "(in " List[i] ")"
1313e12c5d1SDavid du Colombier	}
1323e12c5d1SDavid du Colombier	clearindex()
1333e12c5d1SDavid du Colombier	clearlist()
1343e12c5d1SDavid du Colombier	print ""
1353e12c5d1SDavid du Colombier	print "Checking libraries"
1363e12c5d1SDavid du Colombier	getindex("/sys/man/2")
1373e12c5d1SDavid du Colombier	getindex9("/sys/man/9")
1383e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libauth.a")
1393e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libbio.a")
1403e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libc.a")
1413e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libfb.a")
1423e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libframe.a")
1433e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libg.a")
1443e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libip.a")
1453e12c5d1SDavid du Colombier	getnmlist("/mips/lib/liblayer.a")
1463e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libmach.a")
1473e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libndb.a")
1483e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libregexp.a")
1493e12c5d1SDavid du Colombier	getnmlist("/mips/lib/libstdio.a")
150*219b2ee8SDavid du Colombier	getnmlist("/mips/lib/libpanel.a")
1513e12c5d1SDavid du Colombier	for (i in List) {
1523e12c5d1SDavid du Colombier		if (!(i in Index))
1533e12c5d1SDavid du Colombier			print "Need", i, "(in " List[i] ")"
1543e12c5d1SDavid du Colombier	}
1553e12c5d1SDavid du Colombier}
1563e12c5d1SDavid du Colombier
1573e12c5d1SDavid du Colombierfunc getindex(dir,    fname)
1583e12c5d1SDavid du Colombier{
1593e12c5d1SDavid du Colombier	fname = dir "/INDEX"
1603e12c5d1SDavid du Colombier	while ((getline < fname) > 0)
1613e12c5d1SDavid du Colombier		Index[$1] = dir
1623e12c5d1SDavid du Colombier	close(fname)
1633e12c5d1SDavid du Colombier}
1643e12c5d1SDavid du Colombier
1653e12c5d1SDavid du Colombierfunc getindex9(dir,    fname)
1663e12c5d1SDavid du Colombier{
1673e12c5d1SDavid du Colombier	fname = dir "/INDEX"
1683e12c5d1SDavid du Colombier	while ((getline < fname) > 0)
1693e12c5d1SDavid du Colombier		if($2 ~ "(getflags|picopen|getcmap)")
1703e12c5d1SDavid du Colombier			Index[$1] = dir
1713e12c5d1SDavid du Colombier	close(fname)
1723e12c5d1SDavid du Colombier}
1733e12c5d1SDavid du Colombier
1743e12c5d1SDavid du Colombierfunc getbinlist(dir,    cmd, subdirs, nsd)
1753e12c5d1SDavid du Colombier{
1763e12c5d1SDavid du Colombier	cmd = "ls -p -l " dir
1773e12c5d1SDavid du Colombier	nsd = 0
1783e12c5d1SDavid du Colombier	while (cmd | getline) {
1793e12c5d1SDavid du Colombier		if ($1 ~ /^d/) {
1803e12c5d1SDavid du Colombier			if (!($10 in Skipdirs))
1813e12c5d1SDavid du Colombier				subdirs[++nsd] = $10
1823e12c5d1SDavid du Colombier		} else
1833e12c5d1SDavid du Colombier			List[$10] = dir
1843e12c5d1SDavid du Colombier	}
1853e12c5d1SDavid du Colombier	for ( ; nsd > 0 ; nsd--)
1863e12c5d1SDavid du Colombier		getbinlist(dir "/" subdirs[nsd])
1873e12c5d1SDavid du Colombier	close(cmd)
1883e12c5d1SDavid du Colombier}
1893e12c5d1SDavid du Colombier
1903e12c5d1SDavid du Colombierfunc getnmlist(lib,    cmd)
1913e12c5d1SDavid du Colombier{
1923e12c5d1SDavid du Colombier	cmd = "nm -g -h " lib
1933e12c5d1SDavid du Colombier	while (cmd | getline) {
1943e12c5d1SDavid du Colombier		if (($1 == "T" || $1 == "L") && $2 !~ "^_")
1953e12c5d1SDavid du Colombier			List[$2] = lib
1963e12c5d1SDavid du Colombier	}
1973e12c5d1SDavid du Colombier	close(cmd)
1983e12c5d1SDavid du Colombier}
1993e12c5d1SDavid du Colombier
2003e12c5d1SDavid du Colombierfunc clearindex(    i)
2013e12c5d1SDavid du Colombier{
2023e12c5d1SDavid du Colombier	for (i in Index)
2033e12c5d1SDavid du Colombier		delete Index[i]
2043e12c5d1SDavid du Colombier}
2053e12c5d1SDavid du Colombier
2063e12c5d1SDavid du Colombierfunc clearlist(    i)
2073e12c5d1SDavid du Colombier{
2083e12c5d1SDavid du Colombier	for (i in List)
2093e12c5d1SDavid du Colombier		delete List[i]
2103e12c5d1SDavid du Colombier}
211