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