#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...::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
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)
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
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
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 |
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.
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
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.
--
*************************** Who else But Darbha *******************************
sda...@buster.eng.ua.edu Res: (205) 349 - 5143 Off: (205) 348-9289
*******************************************************************************
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.