commit 02f38ca68ce484b2aad15fad4d59c4d43ef7eb1b from: rsc date: Tue Jan 04 22:33:11 2005 UTC man page checking commit - 3e1c71811965930d52db3df4d57acb9d9020f8df commit + 02f38ca68ce484b2aad15fad4d59c4d43ef7eb1b blob - /dev/null blob + 4d682cab050db5d3f6bcc50231fd821d1e5810d0 (mode 644) --- /dev/null +++ dist/checkman.awk @@ -0,0 +1,453 @@ +# Usage: cd $PLAN9; awk -f dist/checkman.awk man?/*.? +# +# Checks: +# - .TH is first line, and has proper name section number +# - sections are in order NAME, SYNOPSIS, DESCRIPTION, EXAMPLES, +# FILES, SOURCE, SEE ALSO, DIAGNOSTICS, BUGS +# - there's a manual page for each cross-referenced page + +BEGIN { + +# .SH sections should come in the following order + + Weight["NAME"] = 1 + Weight["SYNOPSIS"] = 2 + Weight["DESCRIPTION"] = 4 + Weight["EXAMPLE"] = 8 + Weight["EXAMPLES"] = 16 + Weight["FILES"] = 32 + Weight["SOURCE"] = 64 + Weight["SEE ALSO"] = 128 + Weight["DIAGNOSTICS"] = 256 + Weight["SYSTEM CALLS"] = 512 + Weight["BUGS"] = 1024 + + Skipdirs["CVS"] = 1 + + # allow references to pages provded + # by the underlying Unix system + Omitman["awk(1)"] = 1 + Omitman["bash(1)"] = 1 + Omitman["chmod(1)"] = 1 + Omitman["compress(1)"] = 1 + Omitman["cp(1)"] = 1 + Omitman["egrep(1)"] = 1 + Omitman["gs(1)"] = 1 + Omitman["gv(1)"] = 1 + Omitman["lex(1)"] = 1 + Omitman["lp(1)"] = 1 + Omitman["lpr(1)"] = 1 + Omitman["mail(1)"] = 1 + Omitman["nm(1)"] = 1 + Omitman["prof(1)"] = 1 + Omitman["pwd(1)"] = 1 + Omitman["sh(1)"] = 1 + Omitman["ssh(1)"] = 1 + Omitman["tar(1)"] = 1 + Omitman["tex(1)"] = 1 + Omitman["unutf(1)"] = 1 + Omitman["xterm(1)"] = 1 + + Omitman["access(2)"] = 1 + Omitman["brk(2)"] = 1 + Omitman["close(2)"] = 1 + Omitman["connect(2)"] = 1 + Omitman["fork(2)"] = 1 + Omitman["gethostname(2)"] = 1 + Omitman["getpid(2)"] = 1 + Omitman["getuid(2)"] = 1 + Omitman["open(2)"] = 1 + Omitman["pipe(2)"] = 1 + Omitman["ptrace(2)"] = 1 + Omitman["rmdir(2)"] = 1 + Omitman["send(2)"] = 1 + Omitman["signal(2)"] = 1 + Omitman["sigprocmask(2)"] = 1 + Omitman["socketpair(2)"] = 1 + Omitman["unlink(2)"] = 1 + + Omitman["abort(3)"] = 1 + Omitman["assert(3)"] = 1 + Omitman["fprintf(3)"] = 1 + Omitman["fscanf(3)"] = 1 + Omitman["fopen(3)"] = 1 + Omitman["isalpha(3)"] = 1 + Omitman["malloc(3)"] = 1 + Omitman["perror(3)"] = 1 + Omitman["remove(3)"] = 1 + Omitman["sin(3)"] = 1 + Omitman["strerror(3)"] = 1 + + Omitman["factotum(4)"] = 1 # for now leave undocumented + + Omitman["core(5)"] = 1 + Omitman["passwd(5)"] = 1 + + Omitman["signal(7)"] = 1 + + Omitman["cron(8)"] = 1 + + # don't need documentation for these in bin + Omitted[".cvsignore"] = 1 + Omitted["Getdir"] = 1 + Omitted["9grep"] = 1 # is in grep(1) + Omitted["9sed"] = 1 # is in sed(1) + Omitted["9lex"] = 1 # is in lex(1) + Omitted["9yacc"] = 1 # is in yacc(1) + + # not for users + Omittedlib["creadimage"] = 1 + Omittedlib["pixelbits"] = 1 + Omittedlib["bouncemouse"] = 1 + Omittedlib["main"] = 1 # in libthread + + # functions provided for -lthread_db + Omittedlib["ps_get_thread_area"] = 1 + Omittedlib["ps_getpid"] = 1 + Omittedlib["ps_lcontinue"] = 1 + Omittedlib["ps_lgetfpregs"] = 1 + Omittedlib["ps_lgetregs"] = 1 + Omittedlib["ps_lsetfpregs"] = 1 + Omittedlib["ps_lsetregs"] = 1 + Omittedlib["ps_lstop"] = 1 + Omittedlib["ps_pcontinue"] = 1 + Omittedlib["ps_pdread"] = 1 + Omittedlib["ps_pdwrite"] = 1 + Omittedlib["ps_pglobal_lookup"] = 1 + Omittedlib["ps_pstop"] = 1 + Omittedlib["ps_ptread"] = 1 + Omittedlib["ps_ptwrite"] = 1 + + # libmach includes a small dwarf and elf library + Omittedlib["corecmdfreebsd386"] = 1 + Omittedlib["corecmdlinux386"] = 1 + Omittedlib["coreregsfreebsd386"] = 1 + Omittedlib["coreregslinux386"] = 1 + Omittedlib["coreregsmachopower"] = 1 + Omittedlib["crackelf"] = 1 + Omittedlib["crackmacho"] = 1 + Omittedlib["dwarfaddrtounit"] = 1 + Omittedlib["dwarfclose"] = 1 + Omittedlib["dwarfenum"] = 1 + Omittedlib["dwarfenumunit"] = 1 + Omittedlib["dwarfget1"] = 1 + Omittedlib["dwarfget128"] = 1 + Omittedlib["dwarfget128s"] = 1 + Omittedlib["dwarfget2"] = 1 + Omittedlib["dwarfget4"] = 1 + Omittedlib["dwarfget8"] = 1 + Omittedlib["dwarfgetabbrev"] = 1 + Omittedlib["dwarfgetaddr"] = 1 + Omittedlib["dwarfgetn"] = 1 + Omittedlib["dwarfgetnref"] = 1 + Omittedlib["dwarfgetstring"] = 1 + Omittedlib["dwarflookupfn"] = 1 + Omittedlib["dwarflookupname"] = 1 + Omittedlib["dwarflookupnameinunit"] = 1 + Omittedlib["dwarflookupsubname"] = 1 + Omittedlib["dwarflookuptag"] = 1 + Omittedlib["dwarfnextsym"] = 1 + Omittedlib["dwarfnextsymat"] = 1 + Omittedlib["dwarfopen"] = 1 + Omittedlib["dwarfpctoline"] = 1 + Omittedlib["dwarfseeksym"] = 1 + Omittedlib["dwarfskip"] = 1 + Omittedlib["dwarfunwind"] = 1 + Omittedlib["elfclose"] = 1 + Omittedlib["elfdl386mapdl"] = 1 + Omittedlib["elfinit"] = 1 + Omittedlib["elfmachine"] = 1 + Omittedlib["elfmap"] = 1 + Omittedlib["elfopen"] = 1 + Omittedlib["elfsection"] = 1 + Omittedlib["elfsym"] = 1 + Omittedlib["elfsymlookup"] = 1 + Omittedlib["elftype"] = 1 + Omittedlib["machoclose"] = 1 + Omittedlib["machoinit"] = 1 + Omittedlib["machoopen"] = 1 + Omittedlib["stabsym"] = 1 + Omittedlib["symdwarf"] = 1 + Omittedlib["symelf"] = 1 + Omittedlib["symmacho"] = 1 + Omittedlib["symstabs"] = 1 + + Renamelib["chanalt"] = "alt" + Renamelib["channbrecv"] = "nbrecv" + Renamelib["channbrecvp"] = "nbrecvp" + Renamelib["channbrecvul"] = "nbrecvul" + Renamelib["channbsend"] = "nbsend" + Renamelib["channbsendp"] = "nbsendp" + Renamelib["channbsendul"] = "nbsendul" + Renamelib["chanrecv"] = "recv" + Renamelib["chanrecvp"] = "recvp" + Renamelib["chanrecvul"] = "recvul" + Renamelib["chansend"] = "send" + Renamelib["chansendp"] = "sendp" + Renamelib["chansendul"] = "sendul" + Renamelib["threadyield"] = "yield" + + Renamelib["fmtcharstod"] = "charstod" + Renamelib["fmtstrtod"] = "strtod" + + Renamelib["regcomp9"] = "regcomp" + Renamelib["regcomplit9"] = "regcomplit" + Renamelib["regcompnl9"] = "regcompnl" + Renamelib["regerror9"] = "regerror" + Renamelib["regexec9"] = "regexec" + Renamelib["regsub9"] = "regsub" + Renamelib["rregexec9"] = "rregexec" + Renamelib["rregsub9"] = "rregsub" +} + +FNR==1 { + n = length(FILENAME) + nam = FILENAME + if(nam ~ /\.html$/) + next + if(nam !~ /^man\/man(.*)\/(.*)\.(.*)$/){ + print "nam", nam, "not of form [0-9][0-9]?/*" + next + } + nam = substr(nam, 8) + gsub("[/.]", " ", nam); + n = split(nam, a) + sec = a[1] + name = a[2] + section = a[3] + if($1 != ".TH" || NF != 3) + print "First line of", FILENAME, "not a proper .TH" + else if(($2 != toupper(name) || substr($3, 1, length(sec)) != sec || $3 != toupper(section)) \ + && ($2!="INTRO" || name!="0intro") \ + && (name !~ /^9/ || $2!=toupper(substr(name, 2)))){ + print ".TH of", FILENAME, "doesn't match filename" + }else + Pages[tolower($2) "(" tolower($3) ")"] = 1 + Sh = 0 +} + +$1 == ".SH" { + if(inex) + print "Unterminated .EX in", FILENAME, ":", $0 + inex = 0; + if (substr($2, 1, 1) == "\"") { + if (NF == 2) { + print "Unneeded quote in", FILENAME, ":", $0 + $2 = substr($2, 2, length($2)-2) + } else if (NF == 3) { + $2 = substr($2, 2) substr($3, 1, length($3)-1) + NF = 2 + } + } + if(Sh == 0 && $2 != "NAME") + print FILENAME, "has no .SH NAME" + w = Weight[$2] + if (w) { + if (w < Sh) + print "Heading", $2, "out of order in", FILENAME + Sh += w + } + sh = $2 +} + +$1 == ".EX" { + if(inex) + print "Nested .EX in", FILENAME ":" FNR, ":", $0 + inex = 1 +} + +$1 == ".EE" { + if(!inex) + print "Bad .EE in", FILENAME ":" FNR ":", $0 + inex = 0; +} + +$1 == ".TF" { + smallspace = 1 +} + +$1 == ".PD" || $1 == ".SH" || $1 == ".SS" || $1 == ".TH" { + smallspace = 0 +} + +$1 == ".RE" { + lastre = 1 +} + +$1 == ".PP" { + if(smallspace && !lastre) + print "Possible missing .PD at " FILENAME ":" FNR + smallspace = 0 +} + +$1 != ".RE" { + lastre = 0 +} + +sh == "SOURCE" && $1 ~ /^\// { + Sources[$1] = 1 +} + +sh == "SOURCE" && $2 ~ /^\// { + Sources[$2] = 1 +} + +$0 ~ /^\.[A-Z].*\([1-9]\)/ { + if ($1 == ".IR" && $3 ~ /\([0-9]\)/) { + name = $2 + section = $3 + }else if ($1 == ".RI" && $2 == "(" && $4 ~ /\([0-9]\)/) { + name = $3 + section = $4 + }else if ($1 == ".IR" && $3 ~ /9.\([0-9]\)/) { + name = $2 + section = "9" + }else if ($1 == ".RI" && $2 == "(" && $4 ~ /9.\([0-9]\)/) { + name = $3 + section = "9" + } else { + print "Possible bad cross-reference format in", FILENAME ":" FNR + print $0 + next + } + gsub(/[^0-9]/, "", section) + Refs[toupper(name) "(" section ")"]++ +} + +END { + print "Checking Source References" + cmd = "xargs -n 100 ls -d 2>&1 >/dev/null | sed 's/^ls: / /; s/: .*//'" + for (i in Sources) { + print i |cmd + } + close(cmd) + print "" + print "Checking Cross-Referenced Pages" + for (i in Refs) { + if (!(tolower(i) in Pages) && !(tolower(i) in Omitman)){ + b = tolower(i) + gsub("\\(", " \\(", b) + gsub("\\)", "\\)", b) + split(tolower(i), a, "/") + print "egrep -in '^\\.IR.*" b "' $PLAN9/man/man*/* # Need " tolower(i) |"sort" + } + } + close("sort") + print "" + print "Checking commands" + getindex("man/man1") + getindex("man/man4") + getindex("man/man7") + getindex("man/man8") + getbinlist("bin") + for (i in List) { + if (!(i in Index) && !(i in Omitted)) + print "Need", i, "(in " List[i] ")" |"sort" + } + close("sort") + print "" + for (i in List) { + if (!(i in Index) && (i in Omitted)) + print "Omit", i, "(in " List[i] ")" |"sort" + } + close("sort") + clearindex() + clearlist() + print "" + print "Checking libraries" + getindex("man/man3") + getnmlist("lib/lib9.a") + getnmlist("lib/lib9p.a") + getnmlist("lib/lib9pclient.a") + getnmlist("lib/libString.a") + # getnmlist("lib/libauth.a") + # getnmlist("lib/libauthsrv.a") + getnmlist("lib/libbin.a") + getnmlist("lib/libbio.a") + getnmlist("lib/libcomplete.a") + # getnmlist("lib/libcontrol.a") + getnmlist("lib/libdisk.a") + getnmlist("lib/libdraw.a") + getnmlist("lib/libflate.a") + getnmlist("lib/libframe.a") + getnmlist("lib/libgeometry.a") + getnmlist("lib/libhtml.a") + # getnmlist("lib/libhttpd.a") + getnmlist("lib/libip.a") + getnmlist("lib/libmach.a") + # getnmlist("lib/libmemdraw.a") + # getnmlist("lib/libmemlayer.a") + getnmlist("lib/libmp.a") + getnmlist("lib/libmux.a") + # getnmlist("lib/libndb.a") + getnmlist("lib/libplumb.a") + getnmlist("lib/libregexp9.a") + getnmlist("lib/libsec.a") + getnmlist("lib/libthread.a") + # getnmlist("lib/libventi.a") + for (i in List) { + if (!(i in Index) && !(i in Omittedlib)) + print "Need", List[i], i |"sort" + # print "Need", i, "(in " List[i] ")" |"sort" + } + close("sort") + print "" + for (i in List) { + if (!(i in Index) && (i in Omittedlib)) + print "Omit", List[i], i |"sort" + # print "Omit", i, "(in " List[i] ")" |"sort" + } + close("sort") +} + +func getindex(dir, fname) +{ + fname = dir "/INDEX" + while ((getline < fname) > 0) + Index[$1] = dir + close(fname) +} + +func getbinlist(dir, cmd, subdirs, nsd) +{ + cmd = "ls -p -l " dir + nsd = 0 + while (cmd | getline) { + if ($1 ~ /^d/) { + if (!($10 in Skipdirs)) + subdirs[++nsd] = $10 + } else if ($10 !~ "^_") + List[$10] = dir + } + for ( ; nsd > 0 ; nsd--) + getbinlist(dir "/" subdirs[nsd]) + close(cmd) +} + +func getnmlist(lib, cmd) +{ + cmd = "nm -g " lib + while (cmd | getline) { + if (($2 == "T" || $2 == "L") && $3 !~ "^_"){ + sym = $3 + sub("^p9", "", sym) + if(sym in Renamelib) + List[Renamelib[sym]] = lib " as " sym + else + List[sym] = lib + } + } + close(cmd) +} + +func clearindex( i) +{ + for (i in Index) + delete Index[i] +} + +func clearlist( i) +{ + for (i in List) + delete List[i] +} blob - /dev/null blob + 5e679d52dd0f85ae1f9983041b820d2b129c95cf (mode 644) --- /dev/null +++ dist/mkfile @@ -0,0 +1,5 @@ +check.out:V: + cd ../man; mk indices + cd .. + awk -f dist/checkman.awk man/man*/*.* >dist/check.out +