#!/usr/bin/perl # errnotbl -1 file err.c err.h # errnotbl 2 intro err.c err.h # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This little program feeds its first two args to man(1) to get a page that # # contains this system's errno codes. It chews up man's output and extracts # # the error codes. It then puts them out as a C table that contains the # # symbolic name, the errno value, and the error message. It also adds a set # # of C routines that return an errno's name and message. # # # # If the section number is negative, we will treat the second arg as a file # # name and read from it. This way, we can process man pages copied from other # # machines. This is mostly useful if the local machine lacks man pages. # # # # Note that two files, are written by this program. Their names are err.c and # # err.h by default, but you can override them by including the file names on # # the command line. You should as usual include err.h in your C files that # # invoke either of the functions defined here. # # # # The above args are the defaults; you can override them if you wish. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # $s = $ARGV[0] || '2'; $m = $ARGV[1] || 'intro'; $c = $ARGV[2] || 'err.c'; $h = $ARGV[3] || 'err.h'; if ($s > 0) { # Do we have a man section? open(P,"man $s $m |") # Start up a man subprocess. || die "Can't run \"man $s $m\" [$!]\n"; print "\tUsing \"man $s $m\"\n"; } else { open(P,"<$m") # Read from file. || die "Can't read \"$m\" [$!]\n"; print "\tReading $m\n"; } open(C,">$c") || die "Can't write to $c [$!]\n"; open(H,">$h") || die "Can't write to $h [$!]\n"; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# # Here are the lines that we put out at the start. This writes to both # # a header file and to the start of the err.c file. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# @hdr = ( "#ifndef err_h\n", "#define err_h\n", "\n", "#define ERRTBL struct _errno_table_\n", "ERRTBL {\n", " int code;\n", " char *name;\n", " char *message;\n", "};\n", "#ifndef Errlist\n", "#define Errlist errno,sys_errname(errno),sys_errmessage(errno)\n", "#endif\n", "#ifndef Errinfo\n", "#define Errinfo errno,sys_errname(errno),sys_errmessage(errno)\n", "#endif\n", "\n", "extern int errno;\n", "extern char* sys_errmessage();\n", "extern char* sys_errname();\n", "extern char unknown[];\n", "\n", "#endif\n", ); for (@hdr) {print H;} @init = ( # " static char err_sccs_id[] = "%W% %G%";", "#include \"err.h\"\n", "\n", "ERRTBL sys_errtbl[] = {\n", "\t{ 0,\t\"EOK\",\t\"No problem\" },\n", ); for (@init) {print C;} # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# # Different systems need different patterns to recognize the # # error-message lines in the man page. The biggest pain is caused by # # the fact that the number and mnemonic may be in either order, so if # # you swap patters, you must also swap $e and $s in the printf call: # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# $patbsd = '^\s\s+(E[A-Z0-9]+)\s+([0-9]+)\s+(.*)'; # SunOS, Ultrix. $patusg = '^\s\s+([0-9]+)\s+(E[A-Z0-9]+)\s+(.*)'; # Solaris, Sys/V. $pataix = '^#define\s+(E[A-Z0-9]+)\s+([0-9]+)\s+\/\*\s*(.*)\s*\*\/'; # AIX's errno.h while ($l =
) { # Now read man's output and select the errno codes. $l =~ s/.//g; if (($s, $e, $m) = ($l =~ $patbsd)) { # Symbol, Errno, Message. $m =~ s/\s+/ /; printf(C "\t{%4d,\t\"%s\",\t\"%s\" },\n",$e,$s,$m); } elsif (($e, $s, $m) = ($l =~ $patusg)) { # Errno, Symbol, Message. $m =~ s/\s+/ /; printf(C "\t{%4d,\t\"%s\",\t\"%s\" },\n",$e,$s,$m); } elsif (($s, $e, $m) = ($l =~ $pataix)) { # Symbol, Errno, Message. $m =~ s/\s+/ /; printf(C "\t{%4d,\t\"%s\",\t\"%s\" },\n",$e,$s,$m); } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# # Here are the lines that we put out at the end. These include several # # lookup routines that search thru the table for a given error code or # # mnemonic and return the index or the message. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# @term = ( "{0,0,0}};\n", "\n", "char * sys_errname(e)\n", "{\tint i;\n", "\tfor (i=0; sys_errtbl[i].name;i++)\n", "\t\tif (e == sys_errtbl[i].code)\n", "\t\t\treturn sys_errtbl[i].name;\n", "\treturn unknown;\n", "}\n", "\n", "char * sys_errmessage(e)\n", "{\tint i;\n", "\tfor (i=0; sys_errtbl[i].message;i++)\n", "\t\tif (e == sys_errtbl[i].code)\n", "\t\t\treturn sys_errtbl[i].message;\n", "\treturn unknown;\n", "}\n", ); for (@term) {print C;}