checking man page includes and prototypes?
Giorgos Keramidas
keramida at ceid.upatras.gr
Thu Jun 22 20:56:54 UTC 2006
On 2006-06-14 09:15, Rich Morin <rdm at cfcl.com> wrote:
> I'm doing a lot of editing of section 2 and 3 man pages, concentrating
> on the includes and prototypes. Although I'm trying to be careful,
> it's quite likely that some errors will slip past me. So, I'm casting
> about for a way to do an automated sanity check. Here's one idea:
>
> For each man page
> For each prototype
> Construct a C test file.
> Compile the test file.
> Look for nastygrams, etc.
>
> For example, the sysconf(3) SYNOPSIS contains the lines:
>
> #include <unistd.h>
>
> long
> sysconf(int name);
>
> I can turn this into the file test.c:
>
> #include <unistd.h>
>
> main() {
>
> int name;
> sysconf(name);
> }
>
> Compiling this (e.g., "cc test.c") finishes silently. So far, so
> good...
>
> Editing "sysconf" into "sysconfx" produces a promising nastygram:
>
> /usr/bin/ld: Undefined symbols:
> _sysconfx
> collect2: ld returned 1 exit status
>
>
> However, editing "int name;" into "float name;' does NOT cause a
> nastygram. So, it appears that prototype checking is not being done.
> The gcc(1) man page gave me the idea of trying
>
> gcc -pedantic -ansi test.c
>
> but this didn't make any visible difference. I see a bazillion other
> options, including a bunch of "-W..." goodies, but I'd rather not try
> them all at random. I tried "gcc -pedantic -ansi -Wstrict-prototypes
> test.c", but it only complained about my "main" statement (?):
>
> test.c:3: warning: function declaration isn't a prototype
>
> Any suggestions (general or specific) on how I might be able to cajole
> gcc (or whatever) into helping me?
This is a _great_ idea!
If it's not too much trouble to generate a `Makefile' along with your
test source file, you can generate something like:
# giorgos at gothmog:/var/tmp/testimdR$ cat -n Makefile
# 1 PROG= test-sysconf
# 2 NO_MAN= No manpage generated for automated test.
# 3
# 4 WARNS?= 6
# 5
# 6 .include <bsd.prog.mk>
# giorgos at gothmog:/var/tmp/testimdR$ cat -n test-sysconf.c
# 1 #include <unistd.h>
# 2
# 3 int
# 4 main(void)
# 5 {
# 6 int name = 0;
# 7
# 8 sysconf(name);
# 9 return 0;
# 10 }
# giorgos at gothmog:/var/tmp/testimdR$
This will let you catch *some* of the potential bugs, by reusing the
makefile magic of the bsd.prog.mk suite, i.e.:
# giorgos at gothmog:/var/tmp/testimdR$ env CFLAGS='-O -pipe -ansi -pedantic' make clean
# rm -f test-sysconf test-sysconf.o
# giorgos at gothmog:/var/tmp/testimdR$ env CFLAGS='-O -pipe -ansi -pedantic' make
# Warning: Object directory not changed from original /var/tmp/testimdR
# cc -O -pipe -ansi -pedantic -g -Wsystem-headers -Werror -Wall \
# -Wno-format-y2k -W -Wno-unused-parameter -Wstrict-prototypes \
# -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual \
# -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter \
# -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls \
# -c test-sysconf.c
# cc -O -pipe -ansi -pedantic -g -Wsystem-headers -Werror -Wall \
# -Wno-format-y2k -W -Wno-unused-parameter -Wstrict-prototypes \
# -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual \
# -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter \
# -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls \
# -o test-sysconf test-sysconf.o
# giorgos at gothmog:/var/tmp/testimdR$
Alas, this will not catch all type-errors too, because the compiler may
implicitly convert values. For instance, it doesn't catch the bug of
passing a `double' argument to sysconf() here:
# giorgos at gothmog:/var/tmp/testimdR$ cat -n test-sysconf.c
# 1 #include <unistd.h>
# 2
# 3 int
# 4 main(void)
# 5 {
# 6 double name = 123456789.0E10L;
# 7
# 8 sysconf(name);
# 9 return 0;
# 10 }
# giorgos at gothmog:/var/tmp/testimdR$ env CFLAGS='-O -pipe -ansi -pedantic' make clean all
# rm -f test-sysconf test-sysconf.o
# Warning: Object directory not changed from original /var/tmp/testimdR
# cc -O -pipe -ansi -pedantic -g -Wsystem-headers -Werror -Wall \
# -Wno-format-y2k -W -Wno-unused-parameter -Wstrict-prototypes \
# -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual \
# -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter \
# -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls \
# -c test-sysconf.c
# cc -O -pipe -ansi -pedantic -g -Wsystem-headers -Werror -Wall \
# -Wno-format-y2k -W -Wno-unused-parameter -Wstrict-prototypes \
# -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual \
# -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter \
# -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls \
# -o test-sysconf test-sysconf.o
# giorgos at gothmog:/var/tmp/testimdR$
The only good things about generating a temporary regression test in
`/var/tmp/testXXXX'-style directories, full with a minimal `Makefile'
and `test-foo.c' file are that:
* You can take advantage of the `clean' and `cleandir' targets to
rerun the test manually if it fails (as long as the test directory
is left untouched for inspection).
* You can take advantage of the existing `makefile magic' for
compiler options, flags, warning levels, etc.
* You can auto-generate the LDADD and DPADD parts of the Makefile
from the LIBRARY section of the manpage and see if that one os
correct too.
* etc.
There are probably other good reasons why a Makefile-based approach is
good, but unfortunately it still doesn't catch all possible errors (as
you can see above).
Regards,
Giorgos
More information about the freebsd-doc
mailing list