[comp.lang.c] TRANSPARENTLY adding arguments to a functions arg list

john@fornax.UUCP (John Simmons) (08/18/90)

     I have a set of functions in a standard library.  The library is used in
writing proceduralized code for VLSI design.  The functions can be divided
into two main groups: those that take a fixed number of arguments and those
that take an indeterminate number of arguments.  An example of the former is
the function

      layer( arg1 );

which sets the current physical layer.  An example of the latter is the
function

     polygon( x1,y1, x2,y2, x3,y3, ... , xN,yN, END );

which creates a polygon with vertices (x1,y1), (x2,y2), (x3,y3), ... , (xN,yN).
The argument 'END' is a sentinel defined as follows:

     #define END  (   1 << ( 8*(sizeof(int) - 1 ))   )
-------------------------------------------------------------------------------

     I would like to modify all such functions so that they expect two
more arguments, namely the preprocessor macros __FILE__ and __LINE__ .
This would allow me to report to the user the location of any error that
the function's error-checking routines find.  It also has great potential
as a method of linking an object to the line of source code that created it.
Re-writing the functions is "easy".  The "trick" is that:

     1.) The user must NOT have to enter these new arguments when invoking
         the function.
              (It's "too much work" for them.)
              (They will probably forget at least some of the time.)
              (In general, it's something that should be transparent to them.)

     2.) While the functions themselves can be re-written, the existing
         source code that USES them cannot.  (It can be re-compiled, but
         the source itself cannot be changed.)
              (It would be "too much work".)
              (It would be "too hard" to contact all users.)
              (The BOSS SAYS SO!)

     3.) The macros MUST be the FIRST two arguments in the argument list.
              (It is often impractical to step through long argument lists
               more than once and the values of these macros are needed
               BEFORE the processing of the argument is finished.)



     For the functions that take a fixed number of arguments, the method
is easy, just use a defined macro like this:

     #define layer( arg1 )     layer_new( __FILE__, __LINE__, arg1 )


     For the functions that take an indeterminate number of arguments, I
cannot come up with a straight forward method because C apparently has no
mechanism for defining MACROS which take a variable number of arguments.
I have come up with two methods of getting around this.  The first is to
do this:
-------------------------------------------------------------------------------
     #define polygon        new_function( __FILE__, __LINE__ ); polygon_new

This has a severe problem because the macro "polygon" expands into TWO
statements which causes behavior that the user cannot anticipate in
situations like the following:

     if( condition ) polygon( x1,y1, x2,y2, x2,y3, END );

which expands to

     if( condition ) new_function( __FILE__, __LINE__ );
                     polygon_new( x1,y1, x2,y2, x2,y3, END );

and hence always executes the call to the 'polygon_new()' function.

It also makes it impossible for the 'polygon()' function to return a function
to the calling program.
-------------------------------------------------------------------------------



The second is to use the comma-operator and do this:
-------------------------------------------------------------------------------
     #define polygon     (    ( new_function(__FILE__,__LINE__), polygon_new

which requires that the sentinel also be redefined as:

     #define END  (   1 << ( 8*(sizeof(int) - 1 ))   )       ))
                                                             ^^
                                                             ||
                                                             Two NEW brackets.

While this eliminates both of the problems mentioned above it creates one
minor new one, namely that the values of __FILE__ and __LINE__ are not
directly available to the 'polygon()' function.  I can get around this
problem by having the function 'new_function()' assign those values to
global variables, but by then the solution is starting to look inelegant.
-------------------------------------------------------------------------------

Can anyone think of a way to include the two arguments at the beginning of
the variable-length argument list that satisfies all the criteria listed
above?

Thank you,
John L. Simmons, Department of Computing Science, Simon Fraser University
john@cs.sfu.ca