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