Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Macros for ANSI prototypes

27 views
Skip to first unread message

Howard Chu

unread,
Aug 11, 1992, 7:58:55 AM8/11/92
to
Well, since the topic has risen up again, here's a cheap way to write code
that works for either ANSI or K&R compilers...
##### cut here #####
/*
* ansi.h - macros for declaring functions and arguments with or without
* ANSI C prototypes. The __DECL macro is used to declare functions with
* prototypes. The __DEFN macro is used to actually define the functions.
* The behavior of the macros is determined based on the ANSIPROTO macro.
*
* The __DECL macro takes a single argument, which should be the function
* prototype/argument list, nested in parentheses.
*
* The __DEFN macro takes two arguments. The first argument is the list
* of comma-separated parameter names, nested in parentheses. The second
* argument lists the full parameter declarations, with each parameter
* separated by an underscore character.
*
* Example:
*
* int main __DECL ((int argc, char *argv[]));
*
* int
* main __DEFN ((argc, argv), int argc _ char *argv[])
* {
* blah;
* }
*
* -- Howard Chu, h...@hanauma.jpl.nasa.gov 10-2-91
*/

#ifdef ANSIPROTO
#define _ ,
#define __DECL(x) x
#define __DEFN(names,decls) (decls)
#else
#define _ ;
#define __DECL(x) ()
#define __DEFN(names,decls) names \
decls;
#endif
##### cut here #####

Sample output:

Script started on Tue Aug 11 00:50:25 1992
hanauma/local/src/x68/nos% cat j.c
#include "ansi.h"

int main __DECL((int argc, char *argv[]));

int
main __DEFN((argc, argv),
int argc _
char *argv[])
{}
hanauma/local/src/x68/nos% gcc -E j.c | uniq
# 1 "j.c"
# 1 "ansi.h" 1

# 1 "j.c" 2

int main () ;

int
main (argc, argv)
int argc ;
char *argv[];
{}
hanauma/local/src/x68/nos% gcc -E -DANSIPROTO j.c | uniq
# 1 "j.c"
# 1 "ansi.h" 1

# 1 "j.c" 2

int main (int argc, char *argv[]) ;

int
main (
int argc ,
char *argv[])
{}
hanauma/local/src/x68/nos%
script done on Tue Aug 11 00:51:01 1992
--
-- Howard Chu @ Jet Propulsion Laboratory, Pasadena, CA
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::To the owner of the blue Mazda, license 742-XLT, your headlights are on...::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Dave Schaumann

unread,
Aug 12, 1992, 5:17:07 AM8/12/92
to
In article <1992Aug11.0...@elroy.jpl.nasa.gov>, hyc@hanauma (Howard Chu) writes:
>Well, since the topic has risen up again, here's a cheap way to write code
>that works for either ANSI or K&R compilers...
>##### cut here #####
>/*
> * ansi.h - macros for declaring functions and arguments with or without
> * ANSI C prototypes. The __DECL macro is used to declare functions with
> * prototypes. The __DEFN macro is used to actually define the functions.
> * The behavior of the macros is determined based on the ANSIPROTO macro.
[remainder deleted]

In stead of obfuscating your code with macros that turn on and off
functio prototypes as the particular compiler requires, wouldn't it be
better to simply include one of the tools freely available to
automatically massage prototyped code into K&R acceptability.

The ability to write clear, easily understandable code should be a primary
goal of every programmer. Macro-izing away prototypes for compilers that
can't deal with them is a poor solution to a problem that is far better
dealt with by a program that requires no special changes to the code.

--
Essentia non sunt multiplicanda praeter necessitatum -- William of Ockham
(Fact need not be multiplied beyond necessity)

Robert Osborne

unread,
Aug 13, 1992, 4:49:39 PM8/13/92
to
da...@cs.arizona.edu (Dave Schaumann) writes:
> In stead of obfuscating your code with macros that turn on and off
> functio prototypes as the particular compiler requires, wouldn't it be
> better to simply include one of the tools freely available to
> automatically massage prototyped code into K&R acceptability.

What if the code needs to be compiled simultaneously on eight
architecutures; 4 K&R and 4 ANSI?

> The ability to write clear, easily understandable code should be a primary
> goal of every programmer. Macro-izing away prototypes for compilers that
> can't deal with them is a poor solution to a problem that is far better
> dealt with by a program that requires no special changes to the code.

Prototype checking is a great debugging tool; I'd hate to lose it
just because one of my architectures is K&R.

Rob.
--
Robert A. Osborne ...!uunet.ca!isgtec!robert or rob...@isgtec.com

Hallvard B Furuseth

unread,
Aug 14, 1992, 9:05:30 PM8/14/92
to
In article <1992Aug11.0...@elroy.jpl.nasa.gov>, hyc@hanauma (Howard Chu) writes:
>Well, since the topic has risen up again, here's a cheap way to write code
>that works for either ANSI or K&R compilers...
>##### cut here #####
>/*
> * ansi.h - macros for declaring functions and arguments with or without
> * ANSI C prototypes. The __DECL macro is used to declare functions with
> * prototypes. The __DEFN macro is used to actually define the functions.

Isn't the __ symbols reserved for the compiler? What do you do when you
stumble over a compiler which uses __DEFN for some assemby nonsense?

Here is another version. I'm sure we are a lot of people who have been
reinventing the wheel, is there more commonly used wheel out there?


In article <1992Aug12.0...@organpipe.uug.arizona.edu> da...@cs.arizona.edu (Dave Schaumann) writes:
> In stead of obfuscating your code with macros that turn on and off
> functio prototypes as the particular compiler requires, wouldn't it be
> better to simply include one of the tools freely available to
> automatically massage prototyped code into K&R acceptability.

And while working on this source tree whith both C++ and traditional C
files I'd need a different include-directory to build the C headers in,
'make' must re-install there after every change to the C++ headers, and
it gets worse if I want to test a change in one package before
installing the .h files.
I prefer an ansidef.h file. Or better cooperating compilers, of course.


/* ansidef.h -- compatibility macros for C++ / ANSI C / traditional C
*
* Usage examples:
* IF_CPLUSPLUS(extern "C" {, EMPTY_ARG) / * anti-#if fanatics * /
* extern int printf ARGDCL((CONST char *, ...));
* extern VOIDFN foo ARGDCL((VOIDDATA *, int)), bar (NOARGS);
* IF_CPLUSPLUS(}, EMPTY_ARG)
* VOIDFN foo ARGDEF((a,b), VOIDDATA *a ARG int b) { bar(); return VOIDVAL; }
* #if IF_ANSI(1,0) / * Safer than ie __STDC__ || __cplusplus * /
* / * because it matches what ansidef does * /
* # include <stdarg.h>
* #else
* # include <varargs.h> / * Sorry, varargs is not really portable * /
* #endif
* int xprintf VA_VARGDEF((fmt, va_alist), CONST char *fmt)
* {...VA_START(ap,fmt)...}
*
* Please add to this file to rope in more machine types and compilers.
* Hallvard B Furuseth <h...@usit.uio.no>, Mar 1992
*/

#ifndef ANSIDEF_H_
#define ANSIDEF_H_

/* Give this to preprocessors that do not grok empty macro args */
#define EMPTY_ARG

#ifdef __cplusplus
# define IF_CPLUSPLUS(cplpl,c) cplpl
# define INLINE inline /* *ATTEMPT* to make inline function */
#else
# define IF_CPLUSPLUS(cplpl,c) c
#if __GNUC__
# define INLINE static __inline__
#else
# define INLINE static /* Better than nothing */
#endif
#endif /* C++ */

#if defined(__STDC__) || defined(__cplusplus)
# define IF_ANSI(ansi,trad) ansi
# define ARGDCL(args) args /* Arguments in function declaration */
# define ARGDEF(args,defs) (defs) /* Arguments in function definition */
# define ARG , /* Argument separator in definitions */
# define NOARGS void /* Arg to function with no arguments */
# define VA_ARGDEF(args,defs) (defs, ...) /* Args to variable arguments fn */
# define VA_START va_start /* Use this instead of va_start */
# define CONST const /* Qualifiers - need a type as well */
# define SIGNED signed
# define VOLATILE volatile
# define HAS_VOID 1
#else
# define IF_ANSI(ansi,trad) trad
# define ARGDCL(args) ()
# define ARGDEF(args,defs) args defs;
# define ARG ;
# define NOARGS
# define VA_ARGDEF(args,defs) args defs; va_dcl
# define VA_START(ptr,last) va_start((ptr))
# define CONST
# define SIGNED
# define VOLATILE
#endif /* ANSI/C++ */

#if HAS_VOID ||\
defined(ultrix) || defined(sun) ||\
defined(__ultrix__) || defined(__sun__) /* gcc versions */
# define HAS_VOID 1 /* True if 'void' exists */
# define VOIDDATA void /* Data type of void* "contents" */
# define VOIDFN void /* Return type for void functions */
# define VOIDVAL /* Return value for void functions */
#else
# define VOIDDATA char
# define VOIDFN int
# define VOIDVAL 0
#endif /* HAS_VOID */

#endif /* ANSIDEF_H_ */
--

Hallvard

D'Arcy J.M. Cain

unread,
Aug 14, 1992, 7:40:33 PM8/14/92
to
rob...@isgtec.com (Robert Osborne) writes:
>da...@cs.arizona.edu (Dave Schaumann) writes:
>> In stead of obfuscating your code with macros that turn on and off
>> functio prototypes as the particular compiler requires, wouldn't it be
>> better to simply include one of the tools freely available to
>> automatically massage prototyped code into K&R acceptability.
>
>What if the code needs to be compiled simultaneously on eight
>architecutures; 4 K&R and 4 ANSI?

You may misunderstand what Dave (from *my* understanding) is saying. Just
because you have an ANSI --> K&R converter doesn't mean that you throw
away the ANSI code. The K&R code just becomes one of the stages of the
compilation. For example, a standard compile might be:

ANSI C --> Assembler --> a.out

but for another system it becomes:

ANSI C --> K&R C --> Assembler --> a.out

You see the K&R is simply an intermediate stage and is thrown out after
along with the .s and .o files. How you do this of course is a matter
for you to set up in your own environment. As an example, I have hacked
Gnu C to allow me to make Minix programs on my ANSI development system.
The flow is:

ANSI C (.c) --> K&R C (.m) --> Copy to Minix machine (.c) --> Compile

This is all more or less automated.

>Prototype checking is a great debugging tool; I'd hate to lose it
>just because one of my architectures is K&R.

And there is no need to.

--
D'Arcy J.M. Cain (da...@druid.com) |
D'Arcy Cain Consulting | There's no government
Toronto, Ontario, Canada | like no government!
+1 416 424 2871 DoD#0082 |

Robert Osborne

unread,
Aug 17, 1992, 2:15:15 PM8/17/92
to
da...@druid.uucp (D'Arcy J.M. Cain) writes:
> rob...@isgtec.com (Robert Osborne) writes:
> >da...@cs.arizona.edu (Dave Schaumann) writes:
> >> In stead of obfuscating your code with macros that turn on and off
> >> functio prototypes as the particular compiler requires, wouldn't it be
> >> better to simply include one of the tools freely available to
> >> automatically massage prototyped code into K&R acceptability.
> >
> >What if the code needs to be compiled simultaneously on eight
> >architecutures; 4 K&R and 4 ANSI?
>
> You may misunderstand what Dave (from *my* understanding) is saying.
> [...] The K&R code just becomes one of the stages of the
> compilation. [...]

>
> ANSI C --> K&R C --> Assembler --> a.out
>
> You see the K&R is simply an intermediate stage and is thrown out after
> along with the .s and .o files.

Gaak! This is gross.

You can't throw away the K&R step because you need the source for
debuggers.

The K&R systems are used also for development; there are enough
problems with the compilers and with the speed of compile without
adding yet another preprocessing step.

It would only take one major bug introduced by the ANSI to K&R
step to remove the developer time savings.

The ANSI source and the K&R source are now distinct between
platforms. This does NOT leave me with any warm fuzzies.

I do not consider this even remotely as elegant as the prototype macros.

Karl Heuer

unread,
Aug 18, 1992, 6:37:20 PM8/18/92
to
In article <31...@isgtec.isgtec.com> rob...@isgtec.com (Robert Osborne) writes:
>da...@druid.uucp (D'Arcy J.M. Cain) writes:
>> ANSI C --> K&R C --> Assembler --> a.out

This is exactly what I do, too.

>Gaak! This is gross.
>
>You can't throw away the K&R step because you need the source for debuggers.

Why? The debuggers that I use don't care about anything except the line
numbers. They don't actually interpret the source code. (In any case, it's
easy enough to keep the intermediate file around during the debugging phases.)

>It would only take one major bug introduced by the ANSI to K&R
>step to remove the developer time savings.

My deprotoizer is only 137 lines long, including comments. It's deliberately
simplified. If it fails to recognize something, it will almost certainly
cause the next phase of compilation to complain, rather than produce a wrong
answer.

>I do not consider this even remotely as elegant as the prototype macros.

Well, that's your choice, I guess.

Karl W. Z. Heuer (ka...@ima.isc.com or uunet!ima!karl), The Walking Lint

D'Arcy J.M. Cain

unread,
Aug 18, 1992, 5:01:08 PM8/18/92
to
rob...@isgtec.com (Robert Osborne) writes:
>da...@druid.uucp (D'Arcy J.M. Cain) writes:
>> [...] The K&R code just becomes one of the stages of the
>> compilation. [...]
>> ANSI C --> K&R C --> Assembler --> a.out
>> You see the K&R is simply an intermediate stage and is thrown out after
>> along with the .s and .o files.
>Gaak! This is gross.
>You can't throw away the K&R step because you need the source for
>debuggers.

Who said you had to throw it away immediately? In fact the example I use
later involved copying the K&R code to another box and compiling there. By
"after" I meant "after it is no longer needed." I kind of thought that was
obvious.

>The K&R systems are used also for development; there are enough
>problems with the compilers and with the speed of compile without
>adding yet another preprocessing step.
>
>It would only take one major bug introduced by the ANSI to K&R
>step to remove the developer time savings.

If your tools don't work then get ones that do. I mean if we are going
to discuss the use of various tools we have to assume that cpp does macro
processing by the accepted rules, cc compiles C code and all the other
tools perform as advertised. I don't think it matters where a major bug
is introduced. If a tool is broken it will cost the developer time.
Just ask anyone who does development using compilers from you-know-who
with a version number of x.0.

>The ANSI source and the K&R source are now distinct between
>platforms. This does NOT leave me with any warm fuzzies.

Say what? There is *one* source. It goes through X translation phases
on its way to becoming an executable. You aren't supposed to further
develop with the intermediate stages. Changing the K&R code would be
just as bad as if you had to modify the assembler.

>I do not consider this even remotely as elegant as the prototype macros.

My way:

int foo(char *, int);
...
int foo(char *bar, int n)
{
/* stuff */
}

Your way: (I don't have the original message but I think this is close)

int foo(__DECL((char *, int));
...
int foo __DEFN((char *bar __ int n))
{
/* stuff */
}

What is your definition of elegant?

Subrahmanyam Darbha

unread,
Aug 19, 1992, 3:35:26 AM8/19/92
to
I have a problem with three dimensional linked lists
I am having to write a linked list only because of the memory problem
as otherwise I would have to declare a two dimensional pointer of the
order *M[1000][1000][4]
For example I will write a two dimensional linked list like this
typedef struct array
{
int ycoord;
int val;
array *next;
}
struct *M[1000]
Where The array gives me the first coordinate and the ycoord gives me
the second degree of freedom
I would like to expand this to a three dimensional pointer

Any suggestions are highly welcome.
Thanks much in advance.

Subrahmanyam. Darbha.
--
*************************** Who else But Darbha *******************************
sda...@buster.eng.ua.edu Res: (205) 349 - 5143 Off: (205) 348-9289
*******************************************************************************

Subrahmanyam Darbha

unread,
Aug 19, 1992, 3:48:41 AM8/19/92
to
I have a problem understanding the difference between calloc and malloc
because in my code malloc seems to be working and calloc does not seem to be
Can anybody enlighten me on this ?
Thank you

Robert Osborne

unread,
Aug 20, 1992, 3:04:10 PM8/20/92
to
da...@druid.uucp (D'Arcy J.M. Cain) writes:
#rob...@isgtec.com (Robert Osborne) writes:
#>da...@druid.uucp (D'Arcy J.M. Cain) writes:
#>> [...] The K&R code just becomes one of the stages of the
#>> compilation. [...]
#>> ANSI C --> K&R C --> Assembler --> a.out
#>> You see the K&R is simply an intermediate stage and is thrown out after
#>> along with the .s and .o files.
#>Gaak! This is gross.
#>You can't throw away the K&R step because you need the source for
#>debuggers.
#
#Who said you had to throw it away immediately? In fact the example I use
#later involved copying the K&R code to another box and compiling there. By
#"after" I meant "after it is no longer needed." I kind of thought that was
#obvious.

Well since the K&R code is always needed while the .s and .o are not
this wasn't that 'obvious'.

#>The K&R systems are used also for development; there are enough
#>problems with the compilers and with the speed of compile without
#>adding yet another preprocessing step.
#>
#>It would only take one major bug introduced by the ANSI to K&R
#>step to remove the developer time savings.
#
#If your tools don't work then get ones that do. I mean if we are going
#to discuss the use of various tools we have to assume that cpp does macro
#processing by the accepted rules, cc compiles C code and all the other
#tools perform as advertised. I don't think it matters where a major bug
#is introduced. If a tool is broken it will cost the developer time.
#Just ask anyone who does development using compilers from you-know-who
#with a version number of x.0.

Get a grip. I was just saying the cost of the added complexity of a
extra preprocessing step has to be weighed against the cost of not
using it. If the minor difficulties caused by cpp were not grossly
overwhelmed by being able to conditionally compile and #include files
would you use it? If the development ease/speed gains from using C
didn't overwhelm the power of assembler would you use C?

#>I do not consider this even remotely as elegant as the prototype macros.
#
#My way:
#
#int foo(char *, int);
#...
#int foo(char *bar, int n)
#{
# /* stuff */
#}
#
#Your way: (I don't have the original message but I think this is close)
#
#int foo(__DECL((char *, int));
#...
#int foo __DEFN((char *bar __ int n))
#{
# /* stuff */
#}

I agree the original method, not mine, suggested was very (VERY!) ugly.
I don't use the ANSI style for function arguments so...
My way:

--- in some include ---
#ifdef HAS_PROTOTYPES
#define PROTO(s) s
#else
#define PROTO(s) ()
#endif

--- in junk.c ---
int foo PROTO((char *, int));

int foo(bar, n)
char *bar;
int n;
{
}

Since prototypes are generated by a tool (mkptypes in our case)
this is easier and more elegant (in my mind and that in those of
the rest of our group) than either of the above methods.

0 new messages