Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

# Usage: awk -f 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["X11"] = 1
        Skipdirs["ape"] = 1
        Skipdirs["aux"] = 1
        Skipdirs["aviation"] = 1
        Skipdirs["c++"] = 1
        Skipdirs["fb"] = 1
        Skipdirs["pub"] = 1
        Skipdirs["games"] = 1
        Skipdirs["gnu"] = 1
        Skipdirs["lml"] = 1
        Skipdirs["type1"] = 1
        Skipdirs["service.alt"] = 1

        Omitted["411"] = 1
        Omitted["Kill"] = 1
        Omitted["cb"] = 1
        Omitted["edmail"] = 1
        Omitted["mousereset"] = 1
        Omitted["postalias"] = 1
        Omitted["mksacfs"] = 1
        Omitted["sacfs"] = 1
        Omitted["stock"] = 1
        Omitted["eg"] = 1
        Omitted["i"] = 1
        Omitted["netlib_find"] = 1
        Omitted["uuencode"] = 1
        Omitted["uudecode"] = 1
        Omitted["P"] = 1
        Omitted["charon"] = 1
        Omitted["tcp17032"] = 1
        Omitted["tcp17033"] = 1
        Omitted["tcp666"] = 1
        Omitted["tcp667"] = 1
        Omitted["tcp7330"] = 1
        Omitted["tcp22"] = 1
        Omitted["tcp79"] = 1
        Omitted["tcp1723"] = 1
        Omitted["pump"] = 1
        Omitted["allmail"] = 1

        Omittedlib["brk_"] = 1
        Omittedlib["creadimage"] = 1
        Omittedlib["main"] = 1
        Omittedlib["opasstokey"] = 1
        Omittedlib["oseek"] = 1
        Omittedlib["sysr1"] = 1
}

FNR==1  {
                n = length(FILENAME)
                seclen = 0
                if (substr(FILENAME, 2, 1) == "/")
                        seclen = 1
                else if (substr(FILENAME, 3, 1) == "/")
                        seclen = 2
                if(seclen == 0)
                        print "FILENAME", FILENAME, "not of form [0-9][0-9]?/*"
                else if(!(substr(FILENAME, seclen+2, n-seclen-1) ~ /^[A-Z]+(.html)?$/)){
                        section = substr(FILENAME, 1, seclen)
                        name = substr(FILENAME, seclen+2, n-seclen-1)
                        if($1 != ".TH" || NF != 3)
                                print "First line of", FILENAME, "not a proper .TH"
                        else if($2 != toupper(name) || substr($3, 1, seclen) != section){
                                if($2!="INTRO" || name!="0intro")
                                        print ".TH of", FILENAME, "doesn't match filename"
                        }else
                                Pages[section "/" $2] = 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
                }
}

$1 == ".EX" {
                if(inex)
                        print "Nested .EX in", FILENAME, ":", $0
                inex = 1
}

$1 == ".EE" {
                if(!inex)
                        print "Bad .EE in", FILENAME, ":", $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
}

$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[section "/" toupper(name)]++
}

END {
        print "Checking Cross-Referenced Pages"
        for (i in Refs) {
                if (!(i in Pages)){
                        split(tolower(i), a, "/")
                        print "grep -n " a[2] ".*" a[1] " ?/* # Need " tolower(i)
                }
        }
        print ""
        print "Checking commands"
        getindex("/sys/man/1")
        getindex("/sys/man/4")
        getindex("/sys/man/7")
        getindex("/sys/man/8")
        getbinlist("/386/bin")
        getbinlist("/rc/bin")
        for (i in List) {
                if (!(i in Index) && !(i in Omitted))
                        print "Need", i, "(in " List[i] ")"
        }
        print ""
        for (i in List) {
                if (!(i in Index) && (i in Omitted))
                        print "Omit", i, "(in " List[i] ")"
        }
        clearindex()
        clearlist()
        print ""
        print "Checking libraries"
        getindex("/sys/man/2")
        getnmlist("/386/lib/lib9p.a")
        getnmlist("/386/lib/libauth.a")
        getnmlist("/386/lib/libauthsrv.a")
        getnmlist("/386/lib/libbin.a")
        getnmlist("/386/lib/libbio.a")
        getnmlist("/386/lib/libc.a")
        getnmlist("/386/lib/libcontrol.a")
        getnmlist("/386/lib/libdisk.a")
        getnmlist("/386/lib/libdraw.a")
        getnmlist("/386/lib/libflate.a")
        getnmlist("/386/lib/libframe.a")
        getnmlist("/386/lib/libgeometry.a")
        getnmlist("/386/lib/libhtml.a")
        getnmlist("/386/lib/libhttpd.a")
        getnmlist("/386/lib/libip.a")
        getnmlist("/386/lib/libmach.a")
        getnmlist("/386/lib/libmemdraw.a")
        getnmlist("/386/lib/libmemlayer.a")
        getnmlist("/386/lib/libmp.a")
        getnmlist("/386/lib/libndb.a")
        getnmlist("/386/lib/libplumb.a")
        getnmlist("/386/lib/libregexp.a")
        getnmlist("/386/lib/libsec.a")
        getnmlist("/386/lib/libstdio.a")
        getnmlist("/386/lib/libString.a")
        getnmlist("/386/lib/libthread.a")
        for (i in List) {
                if (!(i in Index) && !(i in Omittedlib))
                        print "Need", i, "(in " List[i] ")"
        }
        print ""
        for (i in List) {
                if (!(i in Index) && (i in Omittedlib))
                        print "Omit", i, "(in " List[i] ")"
        }
}

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 -h " lib
        while (cmd | getline) {
                if (($1 == "T" || $1 == "L") && $2 !~ "^_")
                        List[$2] = lib
        }
        close(cmd)
}

func clearindex(    i)
{
        for (i in Index)
                delete Index[i]
}

func clearlist(    i)
{
        for (i in List)
                delete List[i]
}