#!/usr/bin/perl # Produces formatted report of errno definitions use strict; use warnings qw/all/; # errno.h is typically a whole bunch of other includes; rather than trying to process # it ourselves, let's get the C-preprocessor to tell us where the includes are my $child; open($child, "-|", "echo '#include ' | gcc -E -") // die("Can't exec gcc: $!"); my @includes; while(<$child>) { if (/^# \d* "(\/[^"]*errno[^"]*)" 1/) { # For example: # 1 "/usr/include/errno.h" 1 3 4 # The 1 after the filename means "new file" push(@includes, $1); } } close($child); my @errno; my %no = (); my ($fh, $line); # As we grind over the error definitions, let's keep track of the maximum field length; # this is for the purpose of constructing formats later my ($maxN, $maxC, $maxD) = (0, 0, 0); my ($const, $val, $desc); for my $inc (@includes) { open($fh, "<", $inc) or die("Unable to read $inc: $!"); while ($line = <$fh>) { if ($line =~ /^#define\s*([A-Z]*)\s*(\d*)\s*\/\*\s*([^\*]*)\*/) { ($const, $val, $desc) = ($1, $2 + 0, $3); # Lose whitespace from the end of the description field $desc =~ s/\s*$//; $no{$const} = $val; push(@errno, { const => $const, errno => $val, desc => $desc }); } elsif ($line =~ /^#define\s*([A-Z]*)\s*([A-Z]*)\s*\/\*\s*([^\*]*)\*/) { # For example: #define EWOULDBLOCK EAGAIN /* Operation would block */ ($const, $val, $desc) = ($1, $2, $3); if (exists($no{$val})) { # Resolve the errno $val = $no{$val}; $desc =~ s/\s*$//; push(@errno, { const => $const, errno => $val, desc => $desc }); } } else { next; } if (length($val) > $maxN) { $maxN = length($val); } if (length($const) > $maxC) { $maxC = length($const); } if (length($desc) > $maxD) { $maxD = length($desc); } } close($fh); } @errno = sort { $a->{errno} <=> $b->{errno} } @errno; # Build up formats; # field is right aligned my $fmt = '@' . ('>' x ($maxN - 1)) . " @" . ('<' x ($maxC - 1)) . " @" . ('<' x ($maxD - 1)) . "\n\$val, \$const, \$desc\n."; my $fmtHdr = '@' . ('>' x ($maxN - 1)) . " @" . ('<' x ($maxC - 1)) . " @" . ('<' x ($maxD - 1)) . "\n'#', '#define', 'Description'\n" . ('-' x ($maxN + $maxC + $maxD + 4)) . "\n."; eval("format STDOUT =\n$fmt\n"); eval("format STDOUT_TOP =\n$fmtHdr\n"); $= = 2 + scalar(@errno); for my $errInf (@errno) { $val = $errInf->{errno}; $const = $errInf->{const}; $desc = $errInf->{desc}; write(); }