xref: /plan9/sys/lib/man/checkman.awk (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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
5219b2ee8SDavid du Colombier#	- sections are in order NAME, SYNOPSIS, DESCRIPTION, EXAMPLES,
6219b2ee8SDavid 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
19219b2ee8SDavid du Colombier	Weight["SOURCE"] = 64
20219b2ee8SDavid du Colombier	Weight["SEE ALSO"] = 128
21219b2ee8SDavid du Colombier	Weight["DIAGNOSTICS"] = 256
22219b2ee8SDavid du Colombier	Weight["SYSTEM CALLS"] = 512
23219b2ee8SDavid du Colombier	Weight["BUGS"] = 1024
24*9a747e4fSDavid du Colombier
25*9a747e4fSDavid du Colombier	Skipdirs["X11"] = 1
26*9a747e4fSDavid du Colombier	Skipdirs["ape"] = 1
27*9a747e4fSDavid du Colombier	Skipdirs["aux"] = 1
28*9a747e4fSDavid du Colombier	Skipdirs["aviation"] = 1
29*9a747e4fSDavid du Colombier	Skipdirs["c++"] = 1
30*9a747e4fSDavid du Colombier	Skipdirs["fb"] = 1
31*9a747e4fSDavid du Colombier	Skipdirs["pub"] = 1
32*9a747e4fSDavid du Colombier	Skipdirs["games"] = 1
33*9a747e4fSDavid du Colombier	Skipdirs["gnu"] = 1
34*9a747e4fSDavid du Colombier	Skipdirs["lml"] = 1
35*9a747e4fSDavid du Colombier	Skipdirs["type1"] = 1
36*9a747e4fSDavid du Colombier	Skipdirs["service.alt"] = 1
37*9a747e4fSDavid du Colombier
387dd7cddfSDavid du Colombier	Omitted["411"] = 1
397dd7cddfSDavid du Colombier	Omitted["Kill"] = 1
407dd7cddfSDavid du Colombier	Omitted["cb"] = 1
417dd7cddfSDavid du Colombier	Omitted["edmail"] = 1
427dd7cddfSDavid du Colombier	Omitted["mousereset"] = 1
437dd7cddfSDavid du Colombier	Omitted["postalias"] = 1
447dd7cddfSDavid du Colombier	Omitted["mksacfs"] = 1
457dd7cddfSDavid du Colombier	Omitted["sacfs"] = 1
467dd7cddfSDavid du Colombier	Omitted["stock"] = 1
477dd7cddfSDavid du Colombier	Omitted["eg"] = 1
487dd7cddfSDavid du Colombier	Omitted["i"] = 1
497dd7cddfSDavid du Colombier	Omitted["netlib_find"] = 1
507dd7cddfSDavid du Colombier	Omitted["uuencode"] = 1
517dd7cddfSDavid du Colombier	Omitted["uudecode"] = 1
527dd7cddfSDavid du Colombier	Omitted["P"] = 1
537dd7cddfSDavid du Colombier	Omitted["charon"] = 1
547dd7cddfSDavid du Colombier	Omitted["tcp17032"] = 1
557dd7cddfSDavid du Colombier	Omitted["tcp17033"] = 1
567dd7cddfSDavid du Colombier	Omitted["tcp666"] = 1
577dd7cddfSDavid du Colombier	Omitted["tcp667"] = 1
587dd7cddfSDavid du Colombier	Omitted["tcp7330"] = 1
597dd7cddfSDavid du Colombier	Omitted["tcp22"] = 1
607dd7cddfSDavid du Colombier	Omitted["tcp79"] = 1
617dd7cddfSDavid du Colombier	Omitted["tcp1723"] = 1
627dd7cddfSDavid du Colombier	Omitted["pump"] = 1
637dd7cddfSDavid du Colombier	Omitted["allmail"] = 1
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier	Omittedlib["brk_"] = 1
667dd7cddfSDavid du Colombier	Omittedlib["creadimage"] = 1
677dd7cddfSDavid du Colombier	Omittedlib["main"] = 1
687dd7cddfSDavid du Colombier	Omittedlib["opasstokey"] = 1
697dd7cddfSDavid du Colombier	Omittedlib["oseek"] = 1
707dd7cddfSDavid du Colombier	Omittedlib["sysr1"] = 1
713e12c5d1SDavid du Colombier}
723e12c5d1SDavid du Colombier
733e12c5d1SDavid du ColombierFNR==1	{
743e12c5d1SDavid du Colombier		n = length(FILENAME)
753e12c5d1SDavid du Colombier		seclen = 0
763e12c5d1SDavid du Colombier		if (substr(FILENAME, 2, 1) == "/")
773e12c5d1SDavid du Colombier			seclen = 1
783e12c5d1SDavid du Colombier		else if (substr(FILENAME, 3, 1) == "/")
793e12c5d1SDavid du Colombier			seclen = 2
803e12c5d1SDavid du Colombier		if(seclen == 0)
813e12c5d1SDavid du Colombier			print "FILENAME", FILENAME, "not of form [0-9][0-9]?/*"
827dd7cddfSDavid du Colombier		else if(!(substr(FILENAME, seclen+2, n-seclen-1) ~ /^[A-Z]+(.html)?$/)){
833e12c5d1SDavid du Colombier			section = substr(FILENAME, 1, seclen)
843e12c5d1SDavid du Colombier			name = substr(FILENAME, seclen+2, n-seclen-1)
853e12c5d1SDavid du Colombier			if($1 != ".TH" || NF != 3)
863e12c5d1SDavid du Colombier				print "First line of", FILENAME, "not a proper .TH"
873e12c5d1SDavid du Colombier			else if($2 != toupper(name) || substr($3, 1, seclen) != section){
883e12c5d1SDavid du Colombier				if($2!="INTRO" || name!="0intro")
893e12c5d1SDavid du Colombier					print ".TH of", FILENAME, "doesn't match filename"
903e12c5d1SDavid du Colombier			}else
913e12c5d1SDavid du Colombier				Pages[section "/" $2] = 1
923e12c5d1SDavid du Colombier		}
933e12c5d1SDavid du Colombier		Sh = 0
943e12c5d1SDavid du Colombier	}
953e12c5d1SDavid du Colombier
963e12c5d1SDavid du Colombier$1 == ".SH" {
97219b2ee8SDavid du Colombier		if(inex)
98219b2ee8SDavid du Colombier			print "Unterminated .EX in", FILENAME, ":", $0
99219b2ee8SDavid du Colombier		inex = 0;
1003e12c5d1SDavid du Colombier		if (substr($2, 1, 1) == "\"") {
1013e12c5d1SDavid du Colombier			if (NF == 2) {
1023e12c5d1SDavid du Colombier				print "Unneeded quote in", FILENAME, ":", $0
1033e12c5d1SDavid du Colombier				$2 = substr($2, 2, length($2)-2)
1043e12c5d1SDavid du Colombier			} else if (NF == 3) {
1053e12c5d1SDavid du Colombier				$2 = substr($2, 2) substr($3, 1, length($3)-1)
1063e12c5d1SDavid du Colombier				NF = 2
1073e12c5d1SDavid du Colombier			}
1083e12c5d1SDavid du Colombier		}
10959cc4ca5SDavid du Colombier		if(Sh == 0 && $2 != "NAME")
11059cc4ca5SDavid du Colombier			print FILENAME, "has no .SH NAME"
1113e12c5d1SDavid du Colombier		w = Weight[$2]
1123e12c5d1SDavid du Colombier		if (w) {
1133e12c5d1SDavid du Colombier			if (w < Sh)
1143e12c5d1SDavid du Colombier				print "Heading", $2, "out of order in", FILENAME
1153e12c5d1SDavid du Colombier			Sh += w
1163e12c5d1SDavid du Colombier		}
1173e12c5d1SDavid du Colombier}
1183e12c5d1SDavid du Colombier
119219b2ee8SDavid du Colombier$1 == ".EX" {
120219b2ee8SDavid du Colombier		if(inex)
121219b2ee8SDavid du Colombier			print "Nested .EX in", FILENAME, ":", $0
122219b2ee8SDavid du Colombier		inex = 1
123219b2ee8SDavid du Colombier}
124219b2ee8SDavid du Colombier
125219b2ee8SDavid du Colombier$1 == ".EE" {
126219b2ee8SDavid du Colombier		if(!inex)
127219b2ee8SDavid du Colombier			print "Bad .EE in", FILENAME, ":", $0
128219b2ee8SDavid du Colombier		inex = 0;
129219b2ee8SDavid du Colombier}
130219b2ee8SDavid du Colombier
13159cc4ca5SDavid du Colombier$1 == ".TF" {
13259cc4ca5SDavid du Colombier		smallspace = 1
13359cc4ca5SDavid du Colombier}
13459cc4ca5SDavid du Colombier
13559cc4ca5SDavid du Colombier$1 == ".PD" || $1 == ".SH" || $1 == ".SS" || $1 == ".TH" {
13659cc4ca5SDavid du Colombier		smallspace = 0
13759cc4ca5SDavid du Colombier}
13859cc4ca5SDavid du Colombier
13959cc4ca5SDavid du Colombier$1 == ".RE" {
14059cc4ca5SDavid du Colombier		lastre = 1
14159cc4ca5SDavid du Colombier}
14259cc4ca5SDavid du Colombier
14359cc4ca5SDavid du Colombier$1 == ".PP" {
14459cc4ca5SDavid du Colombier		if(smallspace && !lastre)
14559cc4ca5SDavid du Colombier			print "Possible missing .PD at " FILENAME ":" FNR
14659cc4ca5SDavid du Colombier		smallspace = 0
14759cc4ca5SDavid du Colombier}
14859cc4ca5SDavid du Colombier
14959cc4ca5SDavid du Colombier$1 != ".RE" {
15059cc4ca5SDavid du Colombier		lastre = 0
15159cc4ca5SDavid du Colombier}
15259cc4ca5SDavid du Colombier
1537dd7cddfSDavid du Colombier$0 ~ /^\.[A-Z].*\([1-9]\)/ {
1543e12c5d1SDavid du Colombier		if ($1 == ".IR" && $3 ~ /\([0-9]\)/) {
1553e12c5d1SDavid du Colombier			name = $2
1563e12c5d1SDavid du Colombier			section = $3
157219b2ee8SDavid du Colombier		}else if ($1 == ".RI" && $2 == "(" && $4 ~ /\([0-9]\)/) {
158219b2ee8SDavid du Colombier			name = $3
159219b2ee8SDavid du Colombier			section = $4
1603e12c5d1SDavid du Colombier		}else if ($1 == ".IR" && $3 ~ /9.\([0-9]\)/) {
1613e12c5d1SDavid du Colombier			name = $2
1623e12c5d1SDavid du Colombier			section = "9"
163219b2ee8SDavid du Colombier		}else if ($1 == ".RI" && $2 == "(" && $4 ~ /9.\([0-9]\)/) {
164219b2ee8SDavid du Colombier			name = $3
165219b2ee8SDavid du Colombier			section = "9"
1663e12c5d1SDavid du Colombier		} else {
1677dd7cddfSDavid du Colombier			print "Possible bad cross-reference format in", FILENAME ":" FNR
1683e12c5d1SDavid du Colombier			print $0
1693e12c5d1SDavid du Colombier			next
1703e12c5d1SDavid du Colombier		}
1713e12c5d1SDavid du Colombier		gsub(/[^0-9]/, "", section)
1723e12c5d1SDavid du Colombier		Refs[section "/" toupper(name)]++
1733e12c5d1SDavid du Colombier}
1743e12c5d1SDavid du Colombier
1753e12c5d1SDavid du ColombierEND {
1763e12c5d1SDavid du Colombier	print "Checking Cross-Referenced Pages"
1773e12c5d1SDavid du Colombier	for (i in Refs) {
178*9a747e4fSDavid du Colombier		if (!(i in Pages)){
179*9a747e4fSDavid du Colombier			split(tolower(i), a, "/")
180*9a747e4fSDavid du Colombier			print "grep -n " a[2] ".*" a[1] " ?/* # Need " tolower(i)
181*9a747e4fSDavid du Colombier		}
1823e12c5d1SDavid du Colombier	}
1833e12c5d1SDavid du Colombier	print ""
1843e12c5d1SDavid du Colombier	print "Checking commands"
1853e12c5d1SDavid du Colombier	getindex("/sys/man/1")
1863e12c5d1SDavid du Colombier	getindex("/sys/man/4")
1873e12c5d1SDavid du Colombier	getindex("/sys/man/7")
1883e12c5d1SDavid du Colombier	getindex("/sys/man/8")
1897dd7cddfSDavid du Colombier	getbinlist("/386/bin")
1903e12c5d1SDavid du Colombier	getbinlist("/rc/bin")
1913e12c5d1SDavid du Colombier	for (i in List) {
1927dd7cddfSDavid du Colombier		if (!(i in Index) && !(i in Omitted))
1933e12c5d1SDavid du Colombier			print "Need", i, "(in " List[i] ")"
1943e12c5d1SDavid du Colombier	}
1957dd7cddfSDavid du Colombier	print ""
1967dd7cddfSDavid du Colombier	for (i in List) {
1977dd7cddfSDavid du Colombier		if (!(i in Index) && (i in Omitted))
1987dd7cddfSDavid du Colombier			print "Omit", i, "(in " List[i] ")"
1997dd7cddfSDavid du Colombier	}
2003e12c5d1SDavid du Colombier	clearindex()
2013e12c5d1SDavid du Colombier	clearlist()
2023e12c5d1SDavid du Colombier	print ""
2033e12c5d1SDavid du Colombier	print "Checking libraries"
2043e12c5d1SDavid du Colombier	getindex("/sys/man/2")
20580ee5cbfSDavid du Colombier	getnmlist("/386/lib/lib9p.a")
2067dd7cddfSDavid du Colombier	getnmlist("/386/lib/libauth.a")
207*9a747e4fSDavid du Colombier	getnmlist("/386/lib/libauthsrv.a")
20880ee5cbfSDavid du Colombier	getnmlist("/386/lib/libbin.a")
2097dd7cddfSDavid du Colombier	getnmlist("/386/lib/libbio.a")
2107dd7cddfSDavid du Colombier	getnmlist("/386/lib/libc.a")
21180ee5cbfSDavid du Colombier	getnmlist("/386/lib/libcontrol.a")
21280ee5cbfSDavid du Colombier	getnmlist("/386/lib/libdisk.a")
2137dd7cddfSDavid du Colombier	getnmlist("/386/lib/libdraw.a")
21480ee5cbfSDavid du Colombier	getnmlist("/386/lib/libflate.a")
2157dd7cddfSDavid du Colombier	getnmlist("/386/lib/libframe.a")
2167dd7cddfSDavid du Colombier	getnmlist("/386/lib/libgeometry.a")
217*9a747e4fSDavid du Colombier	getnmlist("/386/lib/libhtml.a")
21880ee5cbfSDavid du Colombier	getnmlist("/386/lib/libhttpd.a")
2197dd7cddfSDavid du Colombier	getnmlist("/386/lib/libip.a")
2207dd7cddfSDavid du Colombier	getnmlist("/386/lib/libmach.a")
2217dd7cddfSDavid du Colombier	getnmlist("/386/lib/libmemdraw.a")
2227dd7cddfSDavid du Colombier	getnmlist("/386/lib/libmemlayer.a")
2237dd7cddfSDavid du Colombier	getnmlist("/386/lib/libmp.a")
2247dd7cddfSDavid du Colombier	getnmlist("/386/lib/libndb.a")
2257dd7cddfSDavid du Colombier	getnmlist("/386/lib/libplumb.a")
2267dd7cddfSDavid du Colombier	getnmlist("/386/lib/libregexp.a")
2277dd7cddfSDavid du Colombier	getnmlist("/386/lib/libsec.a")
2287dd7cddfSDavid du Colombier	getnmlist("/386/lib/libstdio.a")
22980ee5cbfSDavid du Colombier	getnmlist("/386/lib/libString.a")
2307dd7cddfSDavid du Colombier	getnmlist("/386/lib/libthread.a")
2313e12c5d1SDavid du Colombier	for (i in List) {
2327dd7cddfSDavid du Colombier		if (!(i in Index) && !(i in Omittedlib))
2333e12c5d1SDavid du Colombier			print "Need", i, "(in " List[i] ")"
2343e12c5d1SDavid du Colombier	}
2357dd7cddfSDavid du Colombier	print ""
2367dd7cddfSDavid du Colombier	for (i in List) {
2377dd7cddfSDavid du Colombier		if (!(i in Index) && (i in Omittedlib))
2387dd7cddfSDavid du Colombier			print "Omit", i, "(in " List[i] ")"
2397dd7cddfSDavid du Colombier	}
2403e12c5d1SDavid du Colombier}
2413e12c5d1SDavid du Colombier
2423e12c5d1SDavid du Colombierfunc getindex(dir,    fname)
2433e12c5d1SDavid du Colombier{
2443e12c5d1SDavid du Colombier	fname = dir "/INDEX"
2453e12c5d1SDavid du Colombier	while ((getline < fname) > 0)
2463e12c5d1SDavid du Colombier		Index[$1] = dir
2473e12c5d1SDavid du Colombier	close(fname)
2483e12c5d1SDavid du Colombier}
2493e12c5d1SDavid du Colombier
2503e12c5d1SDavid du Colombierfunc getbinlist(dir,    cmd, subdirs, nsd)
2513e12c5d1SDavid du Colombier{
2523e12c5d1SDavid du Colombier	cmd = "ls -p -l " dir
2533e12c5d1SDavid du Colombier	nsd = 0
2543e12c5d1SDavid du Colombier	while (cmd | getline) {
2553e12c5d1SDavid du Colombier		if ($1 ~ /^d/) {
2563e12c5d1SDavid du Colombier			if (!($10 in Skipdirs))
2573e12c5d1SDavid du Colombier				subdirs[++nsd] = $10
2587dd7cddfSDavid du Colombier		} else if ($10 !~ "^_")
2593e12c5d1SDavid du Colombier			List[$10] = dir
2603e12c5d1SDavid du Colombier	}
2613e12c5d1SDavid du Colombier	for ( ; nsd > 0 ; nsd--)
2623e12c5d1SDavid du Colombier		getbinlist(dir "/" subdirs[nsd])
2633e12c5d1SDavid du Colombier	close(cmd)
2643e12c5d1SDavid du Colombier}
2653e12c5d1SDavid du Colombier
2663e12c5d1SDavid du Colombierfunc getnmlist(lib,    cmd)
2673e12c5d1SDavid du Colombier{
2683e12c5d1SDavid du Colombier	cmd = "nm -g -h " lib
2693e12c5d1SDavid du Colombier	while (cmd | getline) {
2703e12c5d1SDavid du Colombier		if (($1 == "T" || $1 == "L") && $2 !~ "^_")
2713e12c5d1SDavid du Colombier			List[$2] = lib
2723e12c5d1SDavid du Colombier	}
2733e12c5d1SDavid du Colombier	close(cmd)
2743e12c5d1SDavid du Colombier}
2753e12c5d1SDavid du Colombier
2763e12c5d1SDavid du Colombierfunc clearindex(    i)
2773e12c5d1SDavid du Colombier{
2783e12c5d1SDavid du Colombier	for (i in Index)
2793e12c5d1SDavid du Colombier		delete Index[i]
2803e12c5d1SDavid du Colombier}
2813e12c5d1SDavid du Colombier
2823e12c5d1SDavid du Colombierfunc clearlist(    i)
2833e12c5d1SDavid du Colombier{
2843e12c5d1SDavid du Colombier	for (i in List)
2853e12c5d1SDavid du Colombier		delete List[i]
2863e12c5d1SDavid du Colombier}
287