🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

19 total messages Started by David Clunie Wed, 31 Aug 1988 12:41
Variable length arg lists for macros
#5316
Author: David Clunie
Date: Wed, 31 Aug 1988 12:41
30 lines
1276 bytes
How do people feel about the idea of preprocessor macros with variable
length argument lists ?

The concept has already been enshrined for true functions, allowing
protoypes for things like the printf() family of functions, and a set of
portable functions and macros to access the list of arguments.

However this can not be done with macro calls. Wouldn't it be nice to be
able to do something like ...


	#ifdef TRACE

	#define	tracef(s,...)	printf(s,...)

	#else

	#define	tracef(s,...)	/* nothing */

	#endif


At present, this CANNOT BE DONE, without nesting parentheses (clumsy) or
using a call to an empty function (inefficient, unless you have inline
integration in an optimizing compiler).

Just a thought. Probably a bit late for the ANSI standard. I am certainly
going to put it in my compiler though !!!

	Regards ... David Clunie
Re: Variable length arg lists for macros
#5317
Author: Doug Gwyn
Date: Thu, 01 Sep 1988 01:41
4 lines
673 bytes
In article <438@ucsvc.unimelb.edu.au> u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
>Just a thought. Probably a bit late for the ANSI standard.

It was brought up, thoroughly discussed, and eventually rejected by X3J11.
Re: Variable length arg lists for macros
#5319
Author: ML
Date: Thu, 01 Sep 1988 02:58
21 lines
1168 bytes
In a previous article u5565522@ucsvc.unimelb.edu.au (David Clunie) wrote:
>How do people feel about the idea of preprocessor macros with variable
>length argument lists ?


I for one would love it.  Plenty of times I've wanted macros like:

#define trace(...)  if (TraceFlag) fprintf(stderr, ...)
#define crash(rc,...)  { fprintf(stderr,...); return(rc); }

etc. etc.

This seems like it would be a simple and useful addition to the preprocessor,
and one which could be implemented in a fairly painless way.  Would it really
be that difficult to add to the standard?  (No flames please, that's a 
serious question based upon my own ignorance :-)

One yes vote here...

             Mark Lanzo
     borrowing      ...!mcnc!ece-csc!rss
Re: Variable length arg lists for macros
#5318
Author: Lawrence V. Cipriani
Date: Thu, 01 Sep 1988 12:19
39 lines
1539 bytes
In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
> How do people feel about the idea of preprocessor macros with variable
> length argument lists ?
I'd like it, but its not essential.  I don't mind using double parenthesis
to fake out the preprocessor.

> However this can not be done with macro calls. Wouldn't it be nice to be
> able to do something like ...
> 
> 	#ifdef TRACE
> 	#define	tracef(s,...)	printf(s,...)
> 	#else
> 	#define	tracef(s,...)	/* nothing */
> 	#endif
> 
> At present, this CANNOT BE DONE, without nesting parentheses (clumsy) or
> using a call to an empty function (inefficient, unless you have inline
> integration in an optimizing compiler).

Only clumsy for the uncoordinated :-)  You missed one more way:

	#ifdef TRACE
	#define trace(anything)	anything
	#else
	#define trace(anything)
	#endif

and you use it like this:

	c(i)
	{
		trace( if (i == 0) printf("boom\n");)
	}

The only restriction I can think of now is that you'll have to be careful
how the comma operator is used.

-- 
Larry Cipriani, AT&T Network Systems, Columbus OH, cbnews!lvc lvc@cbnews.ATT.COM
Re: Variable length arg lists for macros
#5320
Author: Glenn Fowler[eww]
Date: Thu, 01 Sep 1988 16:13
28 lines
1541 bytes
In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
> ... Wouldn't it be nice to be able to do something like ...
> 	#ifdef TRACE
> 	#define	tracef(s,...)	printf(s,...)
> 	#else
> 	#define	tracef(s,...)	/* nothing */
> 	#endif
> ... Probably a bit late for the ANSI standard ...

too late, but here is the description of macro `...' args for
a local preprocessor extension:

	If the last formal argument is followed by the `...'
	token then it is replaced by the expanded value
	of all remaining actual arguments and intervening `,'
	tokens from the macro call.  If there is only one formal
	argument then the macro may be called with no actual
	arguments, otherwise there must be at least one actual
	argument for the last formal argument.

this would change the tracef() macro definition to

	#define tracef(s,...)	printf(s)

the `,' before the `...' is optional to satisfy all tastes
-- 
    Glenn Fowler                    AT&T Bell Laboratories, Murray Hill
    {ihnp4,allegra}!ulysses!gsf                          (201)-582-2195
RE: Variable length arg lists for macros
#5322
Author: Kristian Wedberg
Date: Fri, 02 Sep 1988 02:58
81 lines
2481 bytes
In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
> How do people feel about the idea of preprocessor macros with variable
> length argument lists ?
> 
> The concept has already been enshrined for true functions, allowing
> protoypes for things like the printf() family of functions, and a set of
> portable functions and macros to access the list of arguments.
> 
> However this can not be done with macro calls. Wouldn't it be nice to be
> able to do something like ...
> 
> 
> 	#ifdef TRACE
> 
> 	#define	tracef(s,...)	printf(s,...)
> 
> 	#else
> 
> 	#define	tracef(s,...)	/* nothing */
> 
> 	#endif
> 
	...
 
> 	Regards ... David Clunie


My solution for the debugging-part of this is to use several macros.
The following is a (very) small extract from my debug-includefile:


#ifndef DEBUG_H
#define DEBUG_H

/* name:  debug.h
 *
 * description:  Header-file with debug-macros & prototypes.
 *
	pr(text)		: print text (no " " or \n, & NO COMMAS!)
	pr0("..\n") - pr6(...)	: print string (with 0 - 6 arguments)
 *
 * problems:
 *	??? No commas in pr() ???
 */

/* pr(), pr1() -> pr6()
 * Produces no code when NPRINTING is defined! Just an empty statement
 * from the semicolon.
 */

/*	Print without arguments. "..." NOT needed */
#ifndef NPRINTING
#define pr(s)	printf("s\n")
#else
#define pr(x)
#endif

/*	Print with 0 to 6 arguments & "...\n" */
#ifndef NPRINTING
#define pr0(s)				printf(s)
#define pr1(s,a1)			printf(s,a1)
#define pr1(s,a1)			printf(s,a1)
#define pr2(s,a1,a2)			printf(s,a1,a2)
#define pr3(s,a1,a2,a3)			printf(s,a1,a2,a3)
#define pr4(s,a1,a2,a3,a4)		printf(s,a1,a2,a3,a4)
#define pr5(s,a1,a2,a3,a4,a5)		printf(s,a1,a2,a3,a4,a5)
#define pr6(s,a1,a2,a3,a4,a5,a6)	printf(s,a1,a2,a3,a4,a5,a6)
#else
#define pr0(x)
#define pr1(x,x1)
#define pr2(x,x1,x2)
#define pr3(x,x1,x2,x3)
#define pr4(x,x1,x2,x3,x4)
#define pr5(x,x1,x2,x3,x4,x5)
#define pr6(x,x1,x2,x3,x4,x5,x6)
#endif


Hope you'll find it useful...

					Kristian Wedberg
Re: Variable length arg lists for macros
#5323
Author: Michael Meissner
Date: Sat, 03 Sep 1988 14:10
20 lines
1490 bytes
In article <438@ucsvc.unimelb.edu.au> u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
| How do people feel about the idea of preprocessor macros with variable
| length argument lists ?
| 
| The concept has already been enshrined for true functions, allowing
| protoypes for things like the printf() family of functions, and a set of
| portable functions and macros to access the list of arguments.

As Doug mentioned this has come before the ANSI committee and did not get
the necessary 2/3 vote to get it in.  Let me mention something that came
up in our discussion:  Namely that it is desirable that you have two
different forms of this, one for the times that you want the comma supplied
if there are extra arguments, and the other for times when you don't want
the comma.  Otherwise you could get compilation errors if no extra arguments
were passed.
-- 
Michael Meissner, Data General.

Uucp:	...!mcnc!rti!xyzzy!meissner
Arpa:	meissner@dg-rtp.DG.COM   (or) meissner%dg-rtp.DG.COM@relay.cs.net
Re: Variable length arg lists for macros
#5349
Author: Steve C. Simmons
Date: Tue, 06 Sep 1988 00:30
46 lines
1961 bytes
In article <1036@cbnews.ATT.COM> lvc@cbnews.ATT.COM (Lawrence V. Cipriani) writes:
-In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
-> How do people feel about the idea of preprocessor macros with variable
-> length argument lists ?
-> 
-> At present, this CANNOT BE DONE, without nesting parentheses (clumsy) or
-> using a call to an empty function (inefficient, unless you have inline
-> integration in an optimizing compiler).
-
-Only clumsy for the uncoordinated :-)  You missed one more way:
-
-	#ifdef TRACE
-	#define trace(anything)	anything
-	#else
-	#define trace(anything)
-	#endif
-
-and you use it like this:
-
-	c(i)
-	{
-		trace( if (i == 0) printf("boom\n");)
-	}
-
-The only restriction I can think of now is that you'll have to be careful
-how the comma operator is used.
-
-Larry Cipriani, cbnews!lvc lvc@cbnews.ATT.COM

A nice hack, but one additional word of warning -- the disappearing line
of code can cause some interesting and obscure bugs.  I had one program
that worked with the trace code but failed oddly without it.  The exact
form escapes me, but it was something like

	. . .
	if ( x == m )
		trace( printf( "the consequences\n) ; )
	froob( some function ) ;

This produced rather different programs depending on the definition of
'trace'!

-- 
Steve Simmons		...!umix!itivax!vax3!scs
Industrial Technology Institute, Ann Arbor, MI.
"You can't get here from here."
Re: Variable length arg lists for macros
#5326
Author: Brian Westley
Date: Tue, 06 Sep 1988 02:34
34 lines
1095 bytes
There is a way to do this, but it's ugly, dangerous,
noisy, and not portable...

short	_NARGS_;
#define	max(a,b,c,d,e) \
    (_NARGS_=5,-a-_NARGS_,-b-_NARGS_,-c-_NARGS_,-d-_NARGS_,-e-_NARGS_,\
    _max(_NARGS_,a-0,b-0,c-0,d-0,e-0))

main()
{
	int x,y;

	printf("%d ",max(3,5,4));
	x = max((-9),(-11),2*6-55);
	y = max(4,2-x,(-6),999,5-9);
	printf("%d %d %d\n",x,y,max(x,y-3));
}

_max(n,a,b,c,d,e)
int n;
int a,b,c,d,e;
{
	int result;

	result = a;
	if (--n>0 && b>result) result=b;
	if (--n>0 && c>result) result=c;
	if (--n>0 && d>result) result=d;
	if (--n>0 && e>result) result=e;
	return result;
}

----
Merlyn LeRoy
types of optional arguments in stdarg.h
#5327
Author: Ray Butterworth
Date: Tue, 06 Sep 1988 14:04
19 lines
1230 bytes
In article <1067@xyzzy.UUCP>, meissner@xyzzy.UUCP (Michael Meissner) writes:
> Let me mention something that came
> up in our discussion:  Namely that it is desirable that you have two
> different forms of this, one for the times that you want the comma supplied
> if there are extra arguments, and the other for times when you don't want
> the comma.  Otherwise you could get compilation errors if no extra arguments
> were passed.

That reminds me of something I'd like to see as an extension
to the variable argument prototypes in some future version
of the Standard.

extern void func(type1, type2, ...);  /* usual meaning */

extern void func(type1, type2  ...);
                             ^
                             No comma.
The missing comma would indicate that all the optional "..." args
must have the same type as the second argument.
Re: types of optional arguments in stdarg.h
#5342
Author: Karl Heuer
Date: Wed, 07 Sep 1988 19:14
19 lines
1417 bytes
rbutterworth@watmath.waterloo.edu (Ray Butterworth) writes:
>[proposal for some future version of the Standard:]
>extern void func(type1, type2, ...);  /* usual meaning */
>extern void func(type1, type2  ...);  /* no trailing comma */
>The missing comma would indicate that all the optional "..." args
>must have the same type as the [last declared] argument.

I independently came up with this same idea.  I think the concept is right,
but the syntax is lousy -- it's too easy to add/delete that comma and
accidentally change the meaning of the declaration.

Also, in C++ the comma is optional (Bjarne wanted it to be forbidden, but
X3J11 made him fix it).  It would not be wise to make a syntax change to C
that is in direct conflict with existing practice in C++.

(Meanwhile, lobby your lint vendor for a /*MONOMORPHIC*/ lintpragma that will
check this for you.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
Re: Variable length arg lists for macros
#5343
Author: Paul Gluckauf Haahr
Date: Wed, 07 Sep 1988 22:07
48 lines
1793 bytes
> How do people feel about the idea of preprocessor macros with variable
> length argument lists ?
> 
> However this can not be done with macro calls. Wouldn't it be nice to be
> able to do something like ...
> 
> 
> 	#ifdef TRACE
> 	#define	tracef(s,...)	printf(s,...)
> 	#else
> 	#define	tracef(s,...)	/* nothing */
> 	#endif
> 
> At present, this CANNOT BE DONE, without nesting parentheses (clumsy) or
> using a call to an empty function (inefficient, unless you have inline
> integration in an optimizing compiler).

well, if your trace function has no more arguments than printf,
you can always do

	#ifdef	TRACE
	#define	tracef	printf
	#else
	#define	tracef	1 ? 0 :
	#endif

note the complete absence of parenthese.  if you want arguments,
the syntax gets ugly, but can work.  for example,

	#ifdef	TRACE
	#define	trace(n)	(debug > n) ? 0 : printf
	#else
	#define	trace(n)	1 ? 0 :
	#endif

usage is then

	trace(3)("n = %d\n", n)

making that print to stderr probably requires an additional function
call, but only when tracing is enabled.

[ this trick is not my own.  peter honeyman (now umix!honey) showed me
a variant in 1984 that is in the hdb uucp sources, used to implement
logging for uucico -x<number> ]

paul haahr
princeton!haahr		haahr@princeton.edu
Re: Variable length arg lists for macros
#5348
Author: Mark Jones
Date: Thu, 08 Sep 1988 16:28
45 lines
1416 bytes
In article <3604@phoenix.Princeton.EDU>, haahr@phoenix.Princeton.EDU (Paul Gluckauf Haahr) writes:
> > How do people feel about the idea of preprocessor macros with variable
> > length argument lists ?
> > 
> > However this can not be done with macro calls. Wouldn't it be nice to be
> > able to do something like ...
> > 
> > 
> > 	#ifdef TRACE
> > 	#define	tracef(s,...)	printf(s,...)
> > 	#else
> > 	#define	tracef(s,...)	/* nothing */
> > 	#endif
> > 
> > At present, this CANNOT BE DONE, without nesting parentheses (clumsy) or
> > using a call to an empty function (inefficient, unless you have inline
> > integration in an optimizing compiler).


If you want a trace function, try this one

#ifdef TRACE
#define TR(x) x
#else
#define TR(x)
#endif

	Now, you can just say
	

	.
	.
	.
	TR(printf("entering buggy function"));
	.
	.
	.

and all is well!


Bought from Dr Dobbs Journal, Only good thing to come out of that
magazine in months.(Did BYTE buy them out?)  <-- Rhetorical question

Mark Jones
Re: Variable length arg lists for macros
#5330
Author: Richard Walker
Date: Wed, 14 Sep 1988 21:49
33 lines
1650 bytes
In article <228@itivax.UUCP> scs@itivax.UUCP (Steve C. Simmons) writes:
>In article <1036@cbnews.ATT.COM> lvc@cbnews.ATT.COM (Lawrence V. Cipriani) writes:
>-In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
>-
>-	#ifdef TRACE
>-	#define trace(anything)	anything
>-	#else
>-	#define trace(anything)
>-	#endif
>-
>	if ( x == m )
>		trace( printf( "the consequences\n) ; )
>	froob( some function ) ;
>
>This produced rather different programs depending on the definition of
>'trace'!

The problem illustrated above is caused by the bad usage of the macro. The
macro call should be formed as a statement to avoid the flow control problem.
In other words, the errors above are caused by the missing ';' at the end
of the trace macro call.

Especially, macros which expand into code with flow control
should be formed such that the semicolon cleanly terminates
the flow, e.g.:

#define COMPLEX_MACRO(foo) (if(SOME_TEST(foo)) {statements;}else)

Then the correct usage of COMPLEX_MACRO would be:
COMPLEX_MACRO(foo);
which also handles the case where COMPLEX_MACRO expands into nothing.

cat <flames_about_crufty_usage_of_code_in_macros >/dev/null
Re: Variable length arg lists for macros
#5333
Author: Chris Torek
Date: Thu, 15 Sep 1988 13:50
27 lines
1322 bytes
In article <362@island.uu.net> walker@island.uu.net (Richard Walker)
suggests that
>... macros which expand into code with flow control
>should be formed such that the semicolon cleanly terminates
>the flow, e.g.:
>
>#define COMPLEX_MACRO(foo) (if(SOME_TEST(foo)) {statements;}else)

This works (after correcting the syntax), but I recommend instead

	#define MAC() if (!(normal_test)) /*void*/; else mac_statement

or, if you need {}s,

	#define	MAC() do { mac_statements } while (0)

These have the advantage over the one above that

	MAC()		/* missing semicolon */
	next_stmt;

produces a syntax error, rather than code that reads

	if (some_test) { statements; } else next_stmt;
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris
Re: Variable length arg lists for macros
#5332
Author: Larry Jones
Date: Thu, 15 Sep 1988 22:40
28 lines
1711 bytes
In article <362@island.uu.net>, walker@island.uu.net (Richard Walker) writes:
> The problem illustrated above is caused by the bad usage of the macro. The
> macro call should be formed as a statement to avoid the flow control problem.
> In other words, the errors above are caused by the missing ';' at the end
> of the trace macro call.
> 
> Especially, macros which expand into code with flow control
> should be formed such that the semicolon cleanly terminates
> the flow, e.g.:
> 
> #define COMPLEX_MACRO(foo) (if(SOME_TEST(foo)) {statements;}else)

Well, it's a good idea, but the example could be better - it could be valid
C if the replacement text didn't have the parentheses around a partial
statement!  In any case, the preferred definition of statement macros is:

#define COMPLEX_MACRO(foo) do { whatever } while (0)

That way the macro expands into a single statement, eats the following semi-
colon, and causes a syntax error if there isn't one instead of accidentally
swallowing the following statement.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.uucp
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"Save the Quayles" - Mark Russell
Re: Variable length arg lists for macros
#5334
Author: David DiGiacomo
Date: Thu, 15 Sep 1988 23:23
17 lines
830 bytes
In article <13573@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>or, if you need {}s,
>
>	#define	MAC() do { mac_statements } while (0)

That's nice, but lint churlishly complains about "constant in conditional
context".  To avoid this, use:

#ifdef lint
int _ZERO_;
#else
#define _ZERO_ 0
#endif

#define _STMT(op)	do { op } while (_ZERO_)

#define	MAC()		_STMT(mac_statements)
Re: Variable length arg lists for macros
#5337
Author: Mark Jones
Date: Fri, 16 Sep 1988 15:56
34 lines
1188 bytes
In article <228@itivax.UUCP> scs@itivax.UUCP (Steve C. Simmons) writes:
>In article <1036@cbnews.ATT.COM> lvc@cbnews.ATT.COM (Lawrence V. Cipriani) writes:
>-In article <438@ucsvc.unimelb.edu.au>, u5565522@ucsvc.unimelb.edu.au (David Clunie) writes:
>-
>-	#ifdef TRACE
>-	#define trace(anything)	anything
>-	#else
>-	#define trace(anything)
>-	#endif
>-
>	if ( x == m )
>		trace( printf( "the consequences\n) ; )
>	froob( some function ) ;
>
This produced rather different programs depending on the definition of
'trace'!
 
Try rephrasing it as

	if(x == m)
		trace(printf("the consequences\n"));
						   ^
						   ^
						   ^
This will evaluate to:

	if(x == m)
		;
or
	if(x == m)
		printf("the cosequences\n");
				
						  
which will not affect the surrounding code.
Re: Variable length arg lists for macros
#5336
Author: Karl Heuer
Date: Fri, 16 Sep 1988 20:12
6 lines
893 bytes
The original question in this thread, concerning an idea for compiler support
for variadic macros, was appropriate for comp.std.c.  The stream of replies
that look like `This is how I like to work around the problem' are not; these
should be confined to comp.lang.c.  Please stop the crossposting.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads