]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/man/checkman.awk
libflate: force non-empty huffman table in mkzprecode() for deflate
[plan9front.git] / sys / lib / man / checkman.awk
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
9 BEGIN {
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         Skipdirs["X11"] = 1
26         Skipdirs["ape"] = 1
27         Skipdirs["aux"] = 1
28         Skipdirs["aviation"] = 1
29         Skipdirs["c++"] = 1
30         Skipdirs["fb"] = 1
31         Skipdirs["pub"] = 1
32         Skipdirs["games"] = 1
33         Skipdirs["gnu"] = 1
34         Skipdirs["lml"] = 1
35         Skipdirs["type1"] = 1
36         Skipdirs["service.alt"] = 1
37         Skipdirs["inst"] = 1
38
39         Omitted["411"] = 1
40         Omitted["Kill"] = 1
41         Omitted["cb"] = 1
42         Omitted["edmail"] = 1
43         Omitted["mousereset"] = 1
44         Omitted["postalias"] = 1
45         Omitted["mksacfs"] = 1
46         Omitted["sacfs"] = 1
47         Omitted["stock"] = 1
48         Omitted["eg"] = 1
49         Omitted["i"] = 1
50         Omitted["netlib_find"] = 1
51         Omitted["uuencode"] = 1
52         Omitted["uudecode"] = 1
53         Omitted["P"] = 1
54         Omitted["charon"] = 1
55         Omitted["tcp17032"] = 1
56         Omitted["tcp17033"] = 1
57         Omitted["tcp666"] = 1
58         Omitted["tcp667"] = 1
59         Omitted["tcp7330"] = 1
60         Omitted["tcp22"] = 1
61         Omitted["tcp79"] = 1
62         Omitted["tcp1723"] = 1
63         Omitted["pump"] = 1
64         Omitted["allmail"] = 1
65
66         Omittedlib["brk_"] = 1
67         Omittedlib["creadimage"] = 1
68         Omittedlib["main"] = 1
69         Omittedlib["oseek"] = 1
70         Omittedlib["sysr1"] = 1
71 }
72
73 FNR==1  {
74                 n = length(FILENAME)
75                 seclen = 0
76                 if (substr(FILENAME, 2, 1) == "/")
77                         seclen = 1
78                 else if (substr(FILENAME, 3, 1) == "/")
79                         seclen = 2
80                 if(seclen == 0)
81                         print "FILENAME", FILENAME, "not of form [0-9][0-9]?/*"
82                 else if(!(substr(FILENAME, seclen+2, n-seclen-1) ~ /^[A-Z]+(.html)?$/)){
83                         section = substr(FILENAME, 1, seclen)
84                         name = substr(FILENAME, seclen+2, n-seclen-1)
85                         if($1 != ".TH" || NF != 3)
86                                 print "First line of", FILENAME, "not a proper .TH"
87                         else if(($2!="INTRO" || name!="0intro") && ($2 != toupper(name) || substr($3, 1, seclen) != section)){
88                                 print ".TH of", FILENAME, "doesn't match filename"
89                         }else
90                                 Pages[section "/" $2] = 1
91                 }
92                 Sh = 0
93         }
94
95 $1 == ".SH" {
96                 if(inex)
97                         print "Unterminated .EX in", FILENAME, ":", $0
98                 inex = 0;
99                 if (substr($2, 1, 1) == "\"") {
100                         if (NF == 2) {
101                                 print "Unneeded quote in", FILENAME, ":", $0
102                                 $2 = substr($2, 2, length($2)-2)
103                         } else if (NF == 3) {
104                                 $2 = substr($2, 2) substr($3, 1, length($3)-1)
105                                 NF = 2
106                         }
107                 }
108                 if(Sh == 0 && $2 != "NAME")
109                         print FILENAME, "has no .SH NAME"
110                 w = Weight[$2]
111                 if (w) {
112                         if (w < Sh)
113                                 print "Heading", $2, "out of order in", FILENAME
114                         Sh += w
115                 }
116 }
117
118 $1 == ".EX" {
119                 if(inex)
120                         print "Nested .EX in", FILENAME, ":", $0
121                 inex = 1
122 }
123
124 $1 == ".EE" {
125                 if(!inex)
126                         print "Bad .EE in", FILENAME, ":", $0
127                 inex = 0;
128 }
129
130 $1 == ".TF" {
131                 smallspace = 1
132 }
133
134 $1 == ".PD" || $1 == ".SH" || $1 == ".SS" || $1 == ".TH" {
135                 smallspace = 0
136 }
137
138 $1 == ".RE" {
139                 lastre = 1
140 }
141
142 $1 == ".PP" {
143                 if(smallspace && !lastre)
144                         print "Possible missing .PD at " FILENAME ":" FNR
145                 smallspace = 0
146 }
147
148 $1 != ".RE" {
149                 lastre = 0
150 }
151
152 $0 ~ /^\.[A-Z].*\([1-9]\)/ {
153                 if ($1 == ".IR" && $3 ~ /\([0-9]\)/) {
154                         name = $2
155                         section = $3
156                 }else if ($1 == ".RI" && $2 == "(" && $4 ~ /\([0-9]\)/) {
157                         name = $3
158                         section = $4
159                 }else if ($1 == ".IR" && $3 ~ /9.\([0-9]\)/) {
160                         name = $2
161                         section = "9"
162                 }else if ($1 == ".RI" && $2 == "(" && $4 ~ /9.\([0-9]\)/) {
163                         name = $3
164                         section = "9"
165                 } else {
166                         print "Possible bad cross-reference format in", FILENAME ":" FNR
167                         print $0
168                         next
169                 }
170                 gsub(/[^0-9]/, "", section)
171                 Refs[section "/" toupper(name)]++
172 }
173
174 END {
175         print "Checking Cross-Referenced Pages"
176         for (i in Refs) {
177                 if (!(i in Pages)){
178                         split(tolower(i), a, "/")
179                         print "grep -in '" a[2] "[      ]*\\(" a[1] "' ?/* # Need " tolower(i)
180                 }
181         }
182         print ""
183         print "Checking commands"
184         getindex("/sys/man/1")
185         getindex("/sys/man/4")
186         getindex("/sys/man/7")
187         getindex("/sys/man/8")
188         getbinlist("/386/bin")
189         getbinlist("/rc/bin")
190         for (i in List) {
191                 if (!(i in Index) && !(i in Omitted))
192                         print "Need", i, "(in " List[i] ")"
193         }
194         print ""
195         for (i in List) {
196                 if (!(i in Index) && (i in Omitted))
197                         print "Omit", i, "(in " List[i] ")"
198         }
199         clearindex()
200         clearlist()
201         print ""
202         print "Checking libraries"
203         getindex("/sys/man/2")
204         getnmlist("/386/lib/lib9p.a")
205         getnmlist("/386/lib/libauth.a")
206         getnmlist("/386/lib/libauthsrv.a")
207         getnmlist("/386/lib/libbin.a")
208         getnmlist("/386/lib/libbio.a")
209         getnmlist("/386/lib/libc.a")
210         getnmlist("/386/lib/libcontrol.a")
211         getnmlist("/386/lib/libdisk.a")
212         getnmlist("/386/lib/libdraw.a")
213         getnmlist("/386/lib/libflate.a")
214         getnmlist("/386/lib/libframe.a")
215         getnmlist("/386/lib/libgeometry.a")
216         getnmlist("/386/lib/libhtml.a")
217         getnmlist("/386/lib/libhttpd.a")
218         getnmlist("/386/lib/libip.a")
219         getnmlist("/386/lib/libmach.a")
220         getnmlist("/386/lib/libmemdraw.a")
221         getnmlist("/386/lib/libmemlayer.a")
222         getnmlist("/386/lib/libmp.a")
223         getnmlist("/386/lib/libndb.a")
224         getnmlist("/386/lib/libplumb.a")
225         getnmlist("/386/lib/libregexp.a")
226         getnmlist("/386/lib/libsec.a")
227         getnmlist("/386/lib/libstdio.a")
228         getnmlist("/386/lib/libString.a")
229         getnmlist("/386/lib/libthread.a")
230         for (i in List) {
231                 if (!(i in Index) && !(i in Omittedlib))
232                         print "Need", i, "(in " List[i] ")"
233         }
234         print ""
235         for (i in List) {
236                 if (!(i in Index) && (i in Omittedlib))
237                         print "Omit", i, "(in " List[i] ")"
238         }
239 }
240
241 func getindex(dir,    fname)
242 {
243         fname = dir "/INDEX"
244         while ((getline < fname) > 0)
245                 Index[$1] = dir
246         close(fname)
247 }
248
249 func getbinlist(dir,    cmd, subdirs, nsd)
250 {
251         cmd = "ls -p -l " dir
252         nsd = 0
253         while (cmd | getline) {
254                 if ($1 ~ /^d/) {
255                         if (!($10 in Skipdirs))
256                                 subdirs[++nsd] = $10
257                 } else if ($10 !~ "^_")
258                         List[$10] = dir
259         }
260         for ( ; nsd > 0 ; nsd--)
261                 getbinlist(dir "/" subdirs[nsd])
262         close(cmd)
263 }
264
265 func getnmlist(lib,    cmd)
266 {
267         cmd = "nm -g -h " lib
268         while (cmd | getline) {
269                 if (($1 == "T" || $1 == "L") && $2 !~ "^_")
270                         List[$2] = lib
271         }
272         close(cmd)
273 }
274
275 func clearindex(    i)
276 {
277         for (i in Index)
278                 delete Index[i]
279 }
280
281 func clearlist(    i)
282 {
283         for (i in List)
284                 delete List[i]
285 }