peter@thirdi.UUCP (Peter Rowell) (09/02/88)
If the reason for variable arguments is to pass them to a routine that takes varargs, the following horrible hack seems not only to work but to be portable! #define d_printf(level, stuff) ((level>=debug_level)? printf stuff :level=level) Note: NO parentheses --> ^ ^ This is then invoked by: d_printf(8, ("foo overflow: %d > %d", some_foo, max_foo)); ^ <----- Note the parentheses -----------> ^ By placing parentheses around the args for printf, they become 1 arg from the point of view of the macro expander. The reason for the ?: usage is to allow this "if" anywhere a single expression could be without screwing up things like: if (cond) d_printf(x,("bummer")); else somehthingelse; ---------------------------------------------------------------------- Peter Rowell (You will need a bigger rock.) Third Eye Software, Inc. (415) 321-0967 Menlo Park, CA 94025 ...!pyramid!thirdi!peter
davidra@batcomputer.tn.cornell.edu (David A. Rabson) (09/02/88)
(Summary: people complain about lack of variable-length arg lists for macros. Standards people try to cover themselves. Other people point out that (( ... )) often works almost as well as variable-length arg list.) There is another way to fake out at least some preprocessors. I find the following useful in header files. The header file is included in several code files only one of which defines GLOBALS. #undef INIT #undef COMMA #define COMMA , #ifdef GLOBALS #define INIT(x) =x #else #define INIT(x) /*nop*/ #endif extern int x[2] INIT({1 COMMA 2}); Since the (( )) and COMMA kludges cover all the cases where I might have wanted variable-length argument lists in cpp macros, I have to agree that the extension would be unnecessary David Rabson Laboratory of Atomic and Solid State Physics
walker@island.uu.net (Richard Walker) (09/15/88)
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
chris@mimsy.UUCP (Chris Torek) (09/15/88)
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
scjones@sdrc.UUCP (Larry Jones) (09/16/88)
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
david@sun.uucp (David DiGiacomo) (09/16/88)
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)
jones@ingr.UUCP (Mark Jones) (09/16/88)
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.
karl@haddock.ima.isc.com (Karl Heuer) (09/17/88)
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