full lint() type checking with /*VARARGS*/ calls
Jim Franklin
jwf at munsell.UUCP
Wed Feb 24 09:53:50 AEST 1988
Summary: you can use some simple #define macros to let lint do full type
checking on /*VARARGS*/ procedure calls with (keyword, value) parameters.
Read on (about 100 lines) for the details ...
We have some procedures that take a lot of optional arguments. We
clearly want to use varargs.h, and we like the style used by SUN in the
various windowing functions, i.e., a zero-terminated list of (keyword,
value) pairs. The (keyword, value) pairs improve readability and permit
procedure parameters to be specified in any order. For example,
#define PIC_COLOR_MODEL_VALUE 1
#define PIC_ADDR_VALUE 2
#define PIC_ACTIVE_IMAGES_VALUE 3
enum color_model_e {
color_xyz, color_abc
};
#define ACTIVE_X 1
#define ACTIVE_Y 2
#define ACTIVE_Z 4
main ()
{
char *pic_addr = NULL;
alloc_picture (PIC_COLOR_MODEL_VALUE, color_xyz,
PIC_ADDR_VALUE, pic_addr,
PIC_ACTIVE_IMAGES_VALUE, ACTIVE_X + ACTIVE_Y,
0);
}
The problem with this is that because alloc_picture() must be declared
/*VARARGS*/, you lose all type checking from lint. This makes errors in
the calling parameters very difficult to find. However, with some #define
trickery, I found that you can have varargs and keyword parameters and
type checking, with no runtime penalty.
You need one #define macro for each (keyword, value) pair, and a collection
of functions of the form
<type>
<type>_arg (x)
<type> x;
{
return (x);
}
where <type> is the data type of your parameters (int, char *, etc.).
For the example above, you define
#ifndef lint
#define PIC_COLOR_MODEL(x) PIC_COLOR_MODEL_VALUE, (x)
#define PIC_ADDR(x) PIC_ADDR_VALUE, (x)
#define PIC_ACTIVE_IMAGES(x) PIC_ACTIVE_IMAGES_VALUE, (x)
#else
#define PIC_COLOR_MODEL(x) \
PIC_COLOR_MODEL_VALUE, color_model_e_arg(x)
#define PIC_ADDR(x) PIC_ADDR_VALUE, char_p_arg(x)
#define PIC_ACTIVE_IMAGES(x) PIC_ACTIVE_IMAGES_VALUE, int_arg(x)
enum color_model_e
color_model_e_arg (x)
enum color_model_e x;
{
return (x);
}
int
int_arg (x)
int x;
{
return (x);
}
char *
char_p_arg (x)
char *x;
{
return (x);
}
#endif
main ()
{
char *pic_addr = NULL;
alloc_picture (PIC_COLOR_MODEL (color_xyz),
PIC_ADDR (pic_addr),
PIC_ACTIVE_IMAGES (ACTIVE_X + ACTIVE_Y),
0);
}
If lint is undefined (i.e., you are just compiling) then the call to
alloc_picture() expands to
alloc_picture ( 1, (color_xyz),
2, (pic_addr),
3, ( 1 + 2),
0);
If lint is defined, it expands to
... all the <type>_arg() functions (deleted for brevity)
alloc_picture ( 1, color_model_e_arg(color_xyz),
2, char_p_arg(pic_addr),
3, int_arg( 1 + 2),
0);
Lint can now do full type checking on alloc_picture's variable argument list.
This is nice ...
-----
{harvard!adelie,{decvax,allegra,talcott}!encore}!munsell!jwf
Jim Franklin, Eikonix/EPPS, 23 Crosby Drive, Bedford, MA 01730
Phone: (617) 663-2115 x4015
More information about the Comp.lang.c
mailing list