1*150ed664SCharles.Forsyth# Usage: awk -f checkman.awk man?/*.? 2*150ed664SCharles.Forsyth# 3*150ed664SCharles.Forsyth# Checks: 4*150ed664SCharles.Forsyth# - .TH is first line, and has proper name section number 5*150ed664SCharles.Forsyth# - sections are in order NAME, SYNOPSIS, DESCRIPTION, EXAMPLES, 6*150ed664SCharles.Forsyth# FILES, SOURCE, SEE ALSO, DIAGNOSTICS, BUGS 7*150ed664SCharles.Forsyth# - there's a manual page for each cross-referenced page 8*150ed664SCharles.Forsyth 9*150ed664SCharles.ForsythBEGIN { 10*150ed664SCharles.Forsyth 11*150ed664SCharles.Forsyth# .SH sections should come in the following order 12*150ed664SCharles.Forsyth 13*150ed664SCharles.Forsyth Weight["NAME"] = 1 14*150ed664SCharles.Forsyth Weight["SYNOPSIS"] = 2 15*150ed664SCharles.Forsyth Weight["DESCRIPTION"] = 4 16*150ed664SCharles.Forsyth Weight["EXAMPLE"] = 8 17*150ed664SCharles.Forsyth Weight["EXAMPLES"] = 16 18*150ed664SCharles.Forsyth Weight["FILES"] = 32 19*150ed664SCharles.Forsyth Weight["SOURCE"] = 64 20*150ed664SCharles.Forsyth Weight["SEE ALSO"] = 128 21*150ed664SCharles.Forsyth Weight["DIAGNOSTICS"] = 256 22*150ed664SCharles.Forsyth Weight["SYSTEM CALLS"] = 512 23*150ed664SCharles.Forsyth Weight["BUGS"] = 1024 24*150ed664SCharles.Forsyth} 25*150ed664SCharles.Forsyth 26*150ed664SCharles.ForsythFNR==1 { 27*150ed664SCharles.Forsyth n = length(FILENAME) 28*150ed664SCharles.Forsyth seclen = 0 29*150ed664SCharles.Forsyth if (substr(FILENAME, 2, 1) == "/") 30*150ed664SCharles.Forsyth seclen = 1 31*150ed664SCharles.Forsyth else if (substr(FILENAME, 3, 1) == "/") 32*150ed664SCharles.Forsyth seclen = 2 33*150ed664SCharles.Forsyth if(seclen == 0) 34*150ed664SCharles.Forsyth print "FILENAME", FILENAME, "not of form [0-9][0-9]?/*" 35*150ed664SCharles.Forsyth else if(!(substr(FILENAME, seclen+2, n-seclen-1) ~ /^[A-Z]+$/)){ 36*150ed664SCharles.Forsyth section = substr(FILENAME, 1, seclen) 37*150ed664SCharles.Forsyth name = substr(FILENAME, seclen+2, n-seclen-1) 38*150ed664SCharles.Forsyth if($1 != ".TH" || NF != 3) 39*150ed664SCharles.Forsyth print "First line of", FILENAME, "not a proper .TH" 40*150ed664SCharles.Forsyth else if($2 != toupper(name) || substr($3, 1, seclen) != section){ 41*150ed664SCharles.Forsyth if($2!="INTRO" || name!="0intro") 42*150ed664SCharles.Forsyth print ".TH of", FILENAME, "doesn't match filename" 43*150ed664SCharles.Forsyth }else 44*150ed664SCharles.Forsyth Pages[section "/" $2] = 1 45*150ed664SCharles.Forsyth } 46*150ed664SCharles.Forsyth Sh = 0 47*150ed664SCharles.Forsyth } 48*150ed664SCharles.Forsyth 49*150ed664SCharles.Forsyth$1 == ".SH" { 50*150ed664SCharles.Forsyth if(inex) 51*150ed664SCharles.Forsyth print "Unterminated .EX in", FILENAME, ":", $0 52*150ed664SCharles.Forsyth inex = 0; 53*150ed664SCharles.Forsyth if (substr($2, 1, 1) == "\"") { 54*150ed664SCharles.Forsyth if (NF == 2) { 55*150ed664SCharles.Forsyth print "Unneeded quote in", FILENAME, ":", $0 56*150ed664SCharles.Forsyth $2 = substr($2, 2, length($2)-2) 57*150ed664SCharles.Forsyth } else if (NF == 3) { 58*150ed664SCharles.Forsyth $2 = substr($2, 2) substr($3, 1, length($3)-1) 59*150ed664SCharles.Forsyth NF = 2 60*150ed664SCharles.Forsyth } 61*150ed664SCharles.Forsyth } 62*150ed664SCharles.Forsyth w = Weight[$2] 63*150ed664SCharles.Forsyth if (w) { 64*150ed664SCharles.Forsyth if (w < Sh) 65*150ed664SCharles.Forsyth print "Heading", $2, "out of order in", FILENAME 66*150ed664SCharles.Forsyth Sh += w 67*150ed664SCharles.Forsyth } 68*150ed664SCharles.Forsyth} 69*150ed664SCharles.Forsyth 70*150ed664SCharles.Forsyth$1 == ".EX" { 71*150ed664SCharles.Forsyth if(inex) 72*150ed664SCharles.Forsyth print "Nested .EX in", FILENAME, ":", $0 73*150ed664SCharles.Forsyth inex = 1 74*150ed664SCharles.Forsyth} 75*150ed664SCharles.Forsyth 76*150ed664SCharles.Forsyth$1 == ".EE" { 77*150ed664SCharles.Forsyth if(!inex) 78*150ed664SCharles.Forsyth print "Bad .EE in", FILENAME, ":", $0 79*150ed664SCharles.Forsyth inex = 0; 80*150ed664SCharles.Forsyth} 81*150ed664SCharles.Forsyth 82*150ed664SCharles.Forsyth$0 ~ /^\..*\([0-9]\)/ { 83*150ed664SCharles.Forsyth if ($1 == ".IR" && $3 ~ /\([0-9]\)/) { 84*150ed664SCharles.Forsyth name = $2 85*150ed664SCharles.Forsyth section = $3 86*150ed664SCharles.Forsyth }else if ($1 == ".RI" && $2 == "(" && $4 ~ /\([0-9]\)/) { 87*150ed664SCharles.Forsyth name = $3 88*150ed664SCharles.Forsyth section = $4 89*150ed664SCharles.Forsyth }else if ($1 == ".IR" && $3 ~ /9.\([0-9]\)/) { 90*150ed664SCharles.Forsyth name = $2 91*150ed664SCharles.Forsyth section = "9" 92*150ed664SCharles.Forsyth }else if ($1 == ".RI" && $2 == "(" && $4 ~ /9.\([0-9]\)/) { 93*150ed664SCharles.Forsyth name = $3 94*150ed664SCharles.Forsyth section = "9" 95*150ed664SCharles.Forsyth } else { 96*150ed664SCharles.Forsyth print "Possible bad cross-reference format in", FILENAME 97*150ed664SCharles.Forsyth print $0 98*150ed664SCharles.Forsyth next 99*150ed664SCharles.Forsyth } 100*150ed664SCharles.Forsyth gsub(/[^0-9]/, "", section) 101*150ed664SCharles.Forsyth Refs[section "/" toupper(name)]++ 102*150ed664SCharles.Forsyth} 103*150ed664SCharles.Forsyth 104*150ed664SCharles.ForsythEND { 105*150ed664SCharles.Forsyth print "Checking Cross-Referenced Pages" 106*150ed664SCharles.Forsyth for (i in Refs) { 107*150ed664SCharles.Forsyth if (!(i in Pages)) 108*150ed664SCharles.Forsyth print "Need", tolower(i) 109*150ed664SCharles.Forsyth } 110*150ed664SCharles.Forsyth print "" 111*150ed664SCharles.Forsyth print "Checking commands" 112*150ed664SCharles.Forsyth getindex("/usr/inferno/doc/man/1") 113*150ed664SCharles.Forsyth getindex("/usr/inferno/doc/man/8") 114*150ed664SCharles.Forsyth Skipdirs["lib"] = 1 115*150ed664SCharles.Forsyth getbinlist("/usr/inferno/dis") 116*150ed664SCharles.Forsyth for (i in List) { 117*150ed664SCharles.Forsyth if (!(i in Index)) 118*150ed664SCharles.Forsyth print "Need", i, "(in " List[i] ")" 119*150ed664SCharles.Forsyth } 120*150ed664SCharles.Forsyth clearindex() 121*150ed664SCharles.Forsyth clearlist() 122*150ed664SCharles.Forsyth print "" 123*150ed664SCharles.Forsyth print "Checking libraries" 124*150ed664SCharles.Forsyth getindex("/usr/inferno/doc/man/2") 125*150ed664SCharles.Forsyth getbinlist("/usr/inferno/dis/lib") 126*150ed664SCharles.Forsyth for (i in List) { 127*150ed664SCharles.Forsyth if (!(i in Index)) 128*150ed664SCharles.Forsyth print "Need", i, "(in " List[i] ")" 129*150ed664SCharles.Forsyth } 130*150ed664SCharles.Forsyth} 131*150ed664SCharles.Forsyth 132*150ed664SCharles.Forsythfunc getindex(dir, fname) 133*150ed664SCharles.Forsyth{ 134*150ed664SCharles.Forsyth fname = dir "/INDEX" 135*150ed664SCharles.Forsyth while ((getline < fname) > 0) 136*150ed664SCharles.Forsyth Index[$1] = dir 137*150ed664SCharles.Forsyth close(fname) 138*150ed664SCharles.Forsyth} 139*150ed664SCharles.Forsyth 140*150ed664SCharles.Forsythfunc getindex9(dir, fname) 141*150ed664SCharles.Forsyth{ 142*150ed664SCharles.Forsyth fname = dir "/INDEX" 143*150ed664SCharles.Forsyth while ((getline < fname) > 0) 144*150ed664SCharles.Forsyth if($2 ~ "(getflags|picopen|getcmap)") 145*150ed664SCharles.Forsyth Index[$1] = dir 146*150ed664SCharles.Forsyth close(fname) 147*150ed664SCharles.Forsyth} 148*150ed664SCharles.Forsyth 149*150ed664SCharles.Forsythfunc getbinlist(dir, cmd, subdirs, nsd) 150*150ed664SCharles.Forsyth{ 151*150ed664SCharles.Forsyth cmd = "ls -p -l " dir 152*150ed664SCharles.Forsyth nsd = 0 153*150ed664SCharles.Forsyth while (cmd | getline) { 154*150ed664SCharles.Forsyth if ($1 ~ /^d/) { 155*150ed664SCharles.Forsyth if (!($10 in Skipdirs)) 156*150ed664SCharles.Forsyth subdirs[++nsd] = $10 157*150ed664SCharles.Forsyth } else { 158*150ed664SCharles.Forsyth sub(".dis", "", $10) 159*150ed664SCharles.Forsyth List[$10] = dir 160*150ed664SCharles.Forsyth } 161*150ed664SCharles.Forsyth } 162*150ed664SCharles.Forsyth for ( ; nsd > 0 ; nsd--) 163*150ed664SCharles.Forsyth getbinlist(dir "/" subdirs[nsd]) 164*150ed664SCharles.Forsyth close(cmd) 165*150ed664SCharles.Forsyth} 166*150ed664SCharles.Forsyth 167*150ed664SCharles.Forsythfunc getnmlist(lib, cmd) 168*150ed664SCharles.Forsyth{ 169*150ed664SCharles.Forsyth cmd = "nm -g -h " lib 170*150ed664SCharles.Forsyth while (cmd | getline) { 171*150ed664SCharles.Forsyth if (($1 == "T" || $1 == "L") && $2 !~ "^_") 172*150ed664SCharles.Forsyth List[$2] = lib 173*150ed664SCharles.Forsyth } 174*150ed664SCharles.Forsyth close(cmd) 175*150ed664SCharles.Forsyth} 176*150ed664SCharles.Forsyth 177*150ed664SCharles.Forsythfunc clearindex( i) 178*150ed664SCharles.Forsyth{ 179*150ed664SCharles.Forsyth for (i in Index) 180*150ed664SCharles.Forsyth delete Index[i] 181*150ed664SCharles.Forsyth} 182*150ed664SCharles.Forsyth 183*150ed664SCharles.Forsythfunc clearlist( i) 184*150ed664SCharles.Forsyth{ 185*150ed664SCharles.Forsyth for (i in List) 186*150ed664SCharles.Forsyth delete List[i] 187*150ed664SCharles.Forsyth} 188