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