[net.lang.c] How to let lint check your format strings

aeb@mcvax.UUCP (Andries Brouwer) (03/31/85)

In order to enable lint to check the correspondence between
the format specifications of printf-like functions (like %d, %ld, %s)
and the number and type of actual arguments one might do the following.
Replace each call
    sprintf(buf, "A %20s%*d", s, m, n);
by
    sprintf(buf, "A %20s%*d", procent_s(s), procent_d(m), procent_d(n));
The routines procent.. are declared in a file procent.c with a content like
    int procent_d(d) int d; { return(d); }
    long procent_D(D) long D; { return(D); }
    unsigned long procent_U(U) unsigned long U; { return(U); }
    char procent_c(c) char c; { return(c); }
    char *procent_s(s) char *s; { return(s); }
and in each source file one adds a first line
    #include "procent.h"
where procent.h is a file like
    extern int procent_d();
    extern long procent_D();
    extern unsigned long procent_U();
    extern char procent_c();
    extern char *procent_s();
Now lint can do the checking (with
    lint -options procent.c other_sources ...
).

I just posted a program (called printfck.c) doing this to net.sources.

(It works fine on the Hack & Quest sources, which is more than 20000 lines
 of code, but no guarantees are given. One has to be careful with the
 interaction with the C preprocessor. With lines like
    #define QUOTE "
 you'll run into obvious problems.)
        
        
[P.S. Yes, I know, for most C compilers the parentheses in  return (x)
 are superfluous.]

david@ukma.UUCP (David Herron, NPR Lover) (04/06/85)

Something that may not have been obvious....to turn it back off
when the code is de-linted, have another .h file like this:

#define procent_a(a)	a
#define procent_b(a)	a

And so forth.  I'm planning on doing something of this sort with
C++ when our copy arrives.  Specifically, it ought to be possible
to have a C++ .h file which will do array bounds checking for you.
And have a different .h file which won't.  Both would have the
same syntax for doing everything, and the syntax should be
the same as for in C also.

Use both the same way.  Enable the strict mode for testing then loosen
it up for production code so you don't have any overhead.
-- 
--- David Herron
--- ARPA-> ukma!david<@ANL-MCS> or david%ukma.uucp@anl-mcs.arpa
---        Or even anlams!ukma!david@ucbvax.arpa
--- UUCP-> {ucbvax,unmvax,boulder,oddjob}!anlams!ukma!david
---        cbosgd!ukma!david

	"The home of poly-unsaturated thinking".

brooks@lll-crg.ARPA (Eugene D. Brooks III) (04/10/85)

> Something that may not have been obvious....to turn it back off
> when the code is de-linted, have another .h file like this:
> 
> #define procent_a(a)	a
> #define procent_b(a)	a

The idea of having lint use constant format strings to check types and
arg counts is a great one.  I have wanted to do this for many years as
argument types and counts for printf and its buddies are one of my more
frequent errors.  Could we come up with a system that does not require any
includes or modifications to the code to do it?  This would be great!

guy@sun.uucp (Guy Harris) (04/11/85)

> The idea of having lint use constant format strings to check types and
> arg counts is a great one.  I have wanted to do this for many years as
> argument types and counts for printf and its buddies are one of my more
> frequent errors.  Could we come up with a system that does not require any
> includes or modifications to the code to do it?  This would be great!

Somebody did - AT&T to be specific.  The system is called "UNIX System V
Release 2".  "lint" was enhanced with a /*PRINTFLIKE*/ pragma; it's like
/*VARARGS*/, only it declares the routine as being like "printf".  The
argument list is checked against the format string.

	Guy Harris
	sun!guy

aeb@mcvax.UUCP (Andries Brouwer) (04/11/85)

In article <518@lll-crg.ARPA> brooks@lll-crg.ARPA (Eugene D. Brooks III) writes:
>> Something that may not have been obvious....to turn it back off
>> when the code is de-linted, have another .h file like this:
>> 
>> #define procent_a(a)	a
>> #define procent_b(a)	a
>
>The idea of having lint use constant format strings to check types and
>arg counts is a great one.  I have wanted to do this for many years as
>argument types and counts for printf and its buddies are one of my more
>frequent errors.  Could we come up with a system that does not require any
>includes or modifications to the code to do it?  This would be great!

The way I use printfck is to run my code through it, feed the result to lint
and then throw all this garbage away again. Code full of procent_x() calls
is good for lint but not for me when I want a nicely formatted listing.

People who not only like the idea but also want to actually use it may like
to know that guido@mcvax improved my version - ask him before you start
polishing printfck.c.