Changeset 62 in openpam


Ignore:
Timestamp:
Feb 18, 2002, 7:08:28 PM (16 years ago)
Author:
Dag-Erling Smørgrav
Message:

Teach gendoc to parse a simple syntax for inline documentation.

Sponsored by: DARPA, NAI Labs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/misc/gendoc.pl

    r44 r62  
    3939use Fcntl;
    4040use POSIX qw(strftime);
    41 use vars qw($COPYRIGHT $TODAY %FUNCTIONS);
    42 
    43 sub gendoc($) {
     41use vars qw($COPYRIGHT $TODAY %FUNCTIONS %PAMERR);
     42
     43%PAMERR = (
     44    PAM_SUCCESS                 => "Success",
     45    PAM_OPEN_ERR                => "Failed to load module",
     46    PAM_SYMBOL_ERR              => "Invalid symbol",
     47    PAM_SERVICE_ERR             => "Error in service module",
     48    PAM_SYSTEM_ERR              => "System error",
     49    PAM_BUF_ERR                 => "Memory buffer error",
     50    PAM_CONV_ERR                => "Conversation failure",
     51    PAM_PERM_DENIED             => "Permission denied",
     52    PAM_MAXTRIES                => "Maximum number of tries exceeded",
     53    PAM_AUTH_ERR                => "Authentication error",
     54    PAM_NEW_AUTHTOK_REQD        => "New authentication token required",
     55    PAM_CRED_INSUFFICIENT       => "Insufficient credentials",
     56    PAM_AUTHINFO_UNAVAIL        => "Authentication information is unavailable",
     57    PAM_USER_UNKNOWN            => "Unknown user",
     58    PAM_CRED_UNAVAIL            => "Failed to retrieve user credentials",
     59    PAM_CRED_EXPIRED            => "User credentials have expired",
     60    PAM_CRED_ERR                => "Failed to set user credentials",
     61    PAM_ACCT_EXPIRED            => "User accound has expired",
     62    PAM_AUTHTOK_EXPIRED         => "Password has expired",
     63    PAM_SESSION_ERR             => "Session failure",
     64    PAM_AUTHTOK_ERR             => "Authentication token failure",
     65    PAM_AUTHTOK_RECOVERY_ERR    => "Failed to recover old authentication token",
     66    PAM_AUTHTOK_LOCK_BUSY       => "Authentication token lock busy",
     67    PAM_AUTHTOK_DISABLE_AGING   => "Authentication token aging disabled",
     68    PAM_NO_MODULE_DATA          => "Module data not found",
     69    PAM_IGNORE                  => "Ignore this module",
     70    PAM_ABORT                   => "General failure",
     71    PAM_TRY_AGAIN               => "Try again",
     72    PAM_MODULE_UNKNOWN          => "Unknown module type",
     73    PAM_DOMAIN_UNKNOWN          => "Unknown authentication domain",
     74);
     75
     76sub parse_source($) {
    4477    my $fn = shift;
    4578
    4679    local *FILE;
    4780    my $source;
    48     my $mdoc;
    4981    my $func;
    5082    my $descr;
    5183    my $type;
    5284    my $args;
    53     my $name;
     85    my $argnames;
     86    my $man;
     87    my $inlist;
     88    my $inliteral;
     89    my %xref;
     90    my @errors;
    5491
    5592    if ($fn !~ m,\.c$,) {
     
    5794        return;
    5895    }
    59    
     96
    6097    sysopen(FILE, $fn, O_RDONLY)
    6198        or die("$fn: open(): $!\n");
     
    63100    close(FILE);
    64101
    65     if ($source =~ m,^(/\*-\n.*?)\s*\*/,s) {
    66         $mdoc = $1;
    67         $mdoc =~ s,^.\*,.\\\",gm;
    68         $mdoc .= "\n.\\\"\n";
    69         $COPYRIGHT = $mdoc;
    70     } else {
    71         $mdoc = ".\\\" \$" . "Id" . "\$\n";
     102    return if ($source =~ m/^ \* NOPARSE\s*$/m);
     103
     104    if (!defined($COPYRIGHT) && $source =~ m,^(/\*-\n.*?)\s*\*/,s) {
     105        $COPYRIGHT = $1;
     106        $COPYRIGHT =~ s,^.\*,.\\\",gm;
     107        $COPYRIGHT =~ s,(\$Id).*?\$,$1\$,;
     108        $COPYRIGHT .= "\n.\\\"";
    72109    }
    73110    $func = $fn;
     
    86123    $args = "\"$args\"";
    87124
    88     $FUNCTIONS{$func} = [ $type, $args ];
    89    
    90     $mdoc .= ".Dd $TODAY
    91 .Dt " . uc($func) . " 3
     125    %xref = (
     126        "pam 3" => 1
     127    );
     128
     129    if ($type eq "int") {
     130        foreach (split("\n", $source)) {
     131            next unless (m/^ \*\s+(!?PAM_[A-Z_]+|=[a-z_]+)\s*$/);
     132            push(@errors, $1);
     133        }
     134        $xref{"pam_strerror 3"} = 1;
     135    }
     136
     137    $argnames = $args;
     138    $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g;
     139    $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g;
     140    $argnames =~ s/\" \"/|/g;
     141    $argnames =~ s/^\"(.*)\"$/($1)/;
     142    foreach (split("\n", $source)) {
     143        s/\s*$//;
     144        if (!defined($man)) {
     145            if (m/^\/\*\*$/) {
     146                $man = "";
     147            }
     148            next;
     149        }
     150        last if (m/^ \*\/$/);
     151        s/^ \* ?//;
     152        s/\\(.)/$1/gs;
     153        if (m/^$/) {
     154            if ($man ne "" && $man !~ m/\.Pp\n$/s) {
     155                if ($inliteral) {
     156                    $man .= "\0\n";
     157                } elsif ($inlist) {
     158                    $man .= ".El\n";
     159                    $inlist = 0;
     160                } else {
     161                    $man .= ".Pp\n";
     162                }
     163            }
     164            next;
     165        }
     166        if (m/^>(\w+)(?:\s+(\d))?$/) {
     167            ++$xref{$2 ? "$1 $2" : "$1 3"};
     168            next;
     169        }
     170        if (s/^\s+(=?\w+):\s*/.It $1/) {
     171            if ($inliteral) {
     172                $man .= ".Ed\n";
     173                $inliteral = 0;
     174            }
     175            if (!$inlist) {
     176                $man =~ s/\.Pp\n$//s;
     177                $man .= ".Bl -tag -width 18n\n";
     178                $inlist = 1;
     179            }
     180            s/^\.It =([A-Z][A-Z_]+)$/.It Dv $1/gs;
     181            $man .= "$_\n";
     182            next;
     183        } elsif ($inlist && m/^\S/) {
     184            $man .= ".El\n";
     185            $inlist = 0;
     186        } elsif ($inliteral && m/^\S/) {
     187            $man .= ".Ed\n";
     188            $inlist = 0;
     189        } elsif ($inliteral) {
     190            $man .= "$_\n";
     191            next;
     192        } elsif ($inlist) {
     193            s/^\s+//;
     194        } elsif (m/^\s+/) {
     195            $man .= ".Bd -literal\n";
     196            $inliteral = 1;
     197            $man .= "$_\n";
     198            next;
     199        }
     200        s/\s*=$func\b\s*/\n.Nm\n/gs;
     201        s/\s*=$argnames\b\s*/\n.Va $1\n/gs;
     202        s/\s*=(struct \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs;
     203        if (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/gs) {
     204            ++$xref{"$1 3"};
     205        }
     206        s/\s*\"(?=\w)/\n.Do\n/gs;
     207        s/\"(?!\w)\s*/\n.Dc\n/gs;
     208        s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs;
     209        s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs;
     210        s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs;
     211        $man .= "$_\n";
     212    }
     213    if (defined($man)) {
     214        $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([\.,:;-]\S*)\s*/$1 $2\n/gs;
     215        $man =~ s/\s*$/\n/gm;
     216        $man =~ s/\n+/\n/gs;
     217        $man =~ s/\0//gs;
     218        chomp($man);
     219    } else {
     220        $man = "No description available.";
     221    }
     222
     223    $FUNCTIONS{$func} = {
     224        'name'          => $func,
     225        'descr'         => $descr,
     226        'type'          => $type,
     227        'args'          => $args,
     228        'man'           => $man,
     229        'xref'          => \%xref,
     230        'errors'        => \@errors,
     231    };
     232    if ($source =~ m/^ \* NODOC\s*$/m) {
     233        $FUNCTIONS{$func}->{'nodoc'} = 1;
     234        $FUNCTIONS{$func}->{'nolist'} = 1;
     235    }
     236    if ($source =~ m/^ \* NOLIST\s*$/m) {
     237        $FUNCTIONS{$func}->{'nolist'} = 1;
     238    }
     239}
     240
     241sub expand_errors($);
     242sub expand_errors($) {
     243    my $func = shift;           # Ref to function hash
     244
     245    my %errors;
     246
     247    if (defined($func->{'recursed'})) {
     248        warn("$func->{'name'}(): loop in error spec\n");
     249        return qw();
     250    }
     251    $func->{'recursed'} = 1;
     252
     253    foreach (@{$func->{'errors'}}) {
     254        if (m/^(PAM_[A-Z_]+)$/) {
     255            if (!defined($PAMERR{$1})) {
     256                warn("$func->{'name'}(): unrecognized error: $1\n");
     257                next;
     258            }
     259            $errors{$1} = 1;
     260        } elsif (m/^!(PAM_[A-Z_]+)$/) {
     261            # treat negations separately
     262        } elsif (m/^=([a-z_]+)$/) {
     263            if (!defined($FUNCTIONS{$1})) {
     264                warn("$func->{'name'}(): reference to unknown $1()\n");
     265                next;
     266            }
     267            foreach (expand_errors($FUNCTIONS{$1})) {
     268                $errors{$_} = 1;
     269            }
     270        } else {
     271            warn("$func->{'name'}(): invalid error specification: $_\n");
     272        }
     273    }
     274    foreach (@{$func->{'errors'}}) {
     275        if (m/^!(PAM_[A-Z_]+)$/) {
     276            delete($errors{$1});
     277        }
     278    }
     279    delete($func->{'recursed'});
     280    return (sort(keys(%errors)));
     281}
     282
     283sub gendoc($) {
     284    my $func = shift;           # Ref to function hash
     285
     286    local *FILE;
     287    my $mdoc;
     288    my $fn;
     289
     290    return if defined($func->{'nodoc'});
     291
     292    $mdoc = "$COPYRIGHT
     293.Dd $TODAY
     294.Dt " . uc($func->{'name'}) . " 3
    92295.Os
    93296.Sh NAME
    94 .Nm $func
    95 .Nd $descr
     297.Nm $func->{'name'}
     298.Nd $func->{'descr'}
    96299.Sh LIBRARY
    97300.Lb libpam
    98301.Sh SYNOPSIS
    99302.In security/pam_appl.h
    100 .Ft $type
    101 .Fn $func $args
     303";
     304    if ($func->{'name'} =~ m/_sm_/) {
     305        $mdoc .= ".In security/pam_modules.h\n"
     306    }
     307    $mdoc .= ".Ft $func->{'type'}
     308.Fn $func->{'name'} $func->{'args'}
    102309.Sh DESCRIPTION
     310$func->{'man'}
     311";
     312    if ($func->{'type'} eq "int") {
     313        $mdoc .= ".Sh RETURN VALUES
    103314The
    104315.Nm
    105 function is not yet documented.
    106 .Sh RETURN VALUES
     316function returns one of the following values:
     317.Bl -tag -width 18n
     318";
     319        my @errors = expand_errors($func);
     320        warn("$func->{'name'}(): no error specification\n")
     321            unless(@errors);
     322        foreach (@errors) {
     323            $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n";
     324        }
     325        $mdoc .= ".El\n";
     326    } else {
     327        if ($func->{'type'} =~ m/\*$/) {
     328            $mdoc .= ".Sh RETURN VALUES
    107329The
    108 .Fn
    109 function returns one of the following values:
    110 .Bl -tag -width PAM_AUTHTOK_DISABLE_AGING
    111 .El
    112 .Sh SEE ALSO
    113 .Xr pam_strerror 3 ,
    114 .Xr pam 3
    115 .Sh STANDARDS
     330.Nm
     331function returns
     332.Dv NULL
     333on failure.
     334";
     335        }
     336    }
     337    $mdoc .= ".Sh SEE ALSO\n";
     338    my @xref = sort(keys(%{$func->{'xref'}}));
     339    while (@xref) {
     340        $mdoc .= ".Xr " . shift(@xref) . (@xref ? " ,\n" : "\n");
     341    }
     342    $mdoc .= ".Sh STANDARDS
    116343.Rs
    117344.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
     
    128355";
    129356
    130      $fn = "$func.3";
    131      sysopen(FILE, $fn, O_RDWR|O_CREAT|O_TRUNC)
     357    $fn = "$func->{'name'}.3";
     358    sysopen(FILE, $fn, O_RDWR|O_CREAT|O_TRUNC)
    132359        or die("$fn: open(): $!\n");
    133      print(FILE $mdoc);
    134      close(FILE);
     360    print(FILE $mdoc);
     361    close(FILE);
    135362}
    136363
    137364sub gensummary() {
    138365
    139     print "$COPYRIGHT";
    140     print ".Dd $TODAY
     366    my $func;
     367
     368    print "$COPYRIGHT
     369.Dd $TODAY
    141370.Dt PAM 3
    142371.Os
     
    144373";
    145374    my @funcs = sort(keys(%FUNCTIONS));
    146     while (@funcs) {
    147         print ".Nm " . shift(@funcs) . (@funcs ? " ,\n" : "\n");
     375    while ($func = shift(@funcs)) {
     376        next if (defined($FUNCTIONS{$func}->{'nolist'}));
     377        print ".Nm $func". (@funcs ? " ,\n" : "\n");
    148378    }
    149379    print ".Nd Pluggable Authentication Modules Library
     
    153383.In security/pam_appl.h
    154384";
    155     foreach my $func (sort(keys(%FUNCTIONS))) {
    156         print ".Ft $FUNCTIONS{$func}->[0]\n";
    157         print ".Fn $func $FUNCTIONS{$func}->[1]\n";
     385    foreach $func (sort(keys(%FUNCTIONS))) {
     386        next if (defined($FUNCTIONS{$func}->{'nolist'}));
     387        print ".Ft $FUNCTIONS{$func}->{'type'}\n";
     388        print ".Fn $func $FUNCTIONS{$func}->{'args'}\n";
    158389    }
    159390    print ".Sh DESCRIPTION
    160391.Sh RETURN VALUES
     392The following return codes are defined in the
     393.In security/pam_constants.h
     394header:
     395.Bl -tag -width 18n
     396";
     397    foreach (sort(keys(%PAMERR))) {
     398        print ".It Bq Er $_\n$PAMERR{$_}.\n";
     399    }
     400    print ".El
    161401.Sh SEE ALSO
    162402";
    163     foreach my $func (sort(keys(%FUNCTIONS))) {
     403    foreach $func (sort(keys(%FUNCTIONS))) {
     404        next if (defined($FUNCTIONS{$func}->{'nolist'}));
    164405        print ".Xr $func 3 ,\n";
    165406    }
     
    184425    $TODAY =~ s,\s+, ,g;
    185426    foreach my $fn (@ARGV) {
    186         gendoc($fn);
     427        parse_source($fn);
     428    }
     429    foreach my $func (values(%FUNCTIONS)) {
     430        gendoc($func);
    187431    }
    188432    gensummary();
Note: See TracChangeset for help on using the changeset viewer.