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