[comp.lang.fortran] Function prototypes

schmidt@zola.ics.uci.edu (Doug Schmidt) (04/30/89)

I'm about to port a C++ program to C.  The original C++ program uses
function prototypes heavily.  It seems ashame to remove all the extra
type checking, but the port must run on both ANSI and non-ANSI C
compilers.  Therefore, I'd like to know whether anyone has devised a
useful set of preprocessor conventions that allow relatively
transparent conversion between compilers that accept prototypes and
those that don't.

Dealing with external declarations seems fairly straight-forward:

/* prototype.h */
#ifdef __STDC__
#define P(X) X
#else
#define P(X)
#endif

Then all extern decls could look like:

#include "prototype.h"
int foo (P(int foobar));

and the preprocessor will correctly substitute in a prototype for ANSI
compilers or do nothing, for non-ANSI compilers.  This should work in
general, right?

However, for function definitions things get messy.  For example, I
could use the old:

#ifdef __STDC__
int foo (int foobar)
#else
int foo (foobar)
    int foobar;        
#endif

trick, but this gets ugly real quick.

Does anyone have a set of macros that helps simplify and beautify the
process?!

thanks,

   Doug
--
On a clear day, under blue skies, there is no need to seek.
And asking about Buddha                +------------------------+
Is like proclaiming innocence,         | schmidt@ics.uci.edu    |
With loot in your pocket.              | office: (714) 856-4043 |

throopw@bert.dg.com (Wayne A. Throop) (05/08/89)

> schmidt@zola.ics.uci.edu (Doug Schmidt)
> I'd like to know whether anyone has devised a
> useful set of preprocessor conventions that allow relatively
> transparent conversion between compilers that accept prototypes and
> those that don't.

There are many tradeoffs to be made.  What I finally ended up using
for situations where non-ansi compilers had to be accomodated has
some drawbacks in that it requires some redundancy and prevents
accurate typechecking of some of it.  But it doesn't look too
terribly awful, and it allows declaration of routines and contracts.

It involves three macros, P, PT, and PP.  The first is used in declaring
functions.  Where one might declare

    int foo( short bar, long bletch )
    {
        ...
    }

one would write

    int foo P(( bar, bletch ),
                short bar PP
                long  bletch )
    {
        ...
    }
    
And in place of

    int (*foo)( short, long );

one would write

    int (*foo) PT(( short, long ));

The definitions of the macros is left as an excersize to the reader.
It isn't too difficult, basically setting the appropriate separators
for PP, deciding whether to expand the argument to PT, and finally
deciding whether to expand the first argument to P and what punctuation
to put around the second one.

--
If it could be demonstrated that any complex organ existed which coult not
possibly have been formed by numerous, successive, slight modifications,
my theory would absolutely break down.
                              --- Charles Darwin
--

Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw