drw@cullvax.UUCP (Dale Worley) (10/01/86)
What I want to do is to write a function call of a variable number of arguments: debug(x, y, z, ...) that will generate no code when the symbol DEBUG is not defined, but generate a call of some function (say, debug_()) when it is. If debug() always had the same number of arguments, we could use #ifdef DEBUG #define debug(x, y, z) debug_(x, y, z) #else #define debug(x, y, z) /* null */ but macros aren't allowed to have a variable number of arguments. The best solutions I've heard so far are: 1) We write debug(x Z y Z z) using "Z" instead of ",". Using the definitions #ifdef DEBUG #define debug(x) debug_(x) #define Z , #else #define debug(x) /* null */ #endif works, since the "Z"s are turned into "," after the call of debug() is expanded. This is ugly because you have to write "Z" instead of ",". 2) We write debug(x, y, z)) Using the definitions #ifdef DEBUG #define debug (debug_ #else #define debug debug1( #define debug1(x) /* null */ This works when DEBUG is off by replacing the call to debug() to a call to debug1() with one argument, which is then ignored. This ugly because of the mismatched parentheses. Is there a good way to do this? Dale
few@well.UUCP (Frank Whaley) (10/02/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >What I want to do is to write a function call of a variable number of >arguments: > debug(x, y, z, ...) >that will generate no code when the symbol DEBUG is not defined, but >generate a call of some function (say, debug_()) when it is. Numerous ugly examples deleted. I had to do this just recently, and took advantage of the fact that my compilers "optimize out" code like this: if (0) function(); So assuming: #ifdef DEBUG #define _DEBUG 1 extern void _debug(char *,) /* debugging printf() */ #else #define _DEBUG 0 #endif #define debug if(_DEBUG)_debug a statment like: debug("%d:%d:%d\n", a, b, c); becomes either: if(1)_debug("%d:%d:%d\n", a, b, c); or if(0)_debug("%d:%d:%d\n", a, b, c); /* no code generated */ All of my compilers generate the strings anyway, so I used a set of external strings (bracketed by #ifdef's) for all debugging messages. Some compilers require an optimizer pass to eat the dead code. -- Frank Whaley Senior Engineer, Beyond Words UUCP: hplabs! ihnp4!ptsfa! seismo!lll-crg!well!few ARPA: well!few@lll-crg.ARPA Water separates the people of the world; wine unites them.
marcus@ihlpl.UUCP (Hall) (10/02/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >What I want to do is to write a function call of a variable number of >arguments: > > debug(x, y, z, ...) > >that will generate no code when the symbol DEBUG is not defined, but >generate a call of some function (say, debug_()) when it is. If >debug() always had the same number of arguments, we could use > > #ifdef DEBUG > #define debug(x, y, z) debug_(x, y, z) > #else > #define debug(x, y, z) /* null */ > >but macros aren't allowed to have a variable number of arguments. How about this: #ifndef DEBUG #define debug #endif and writing in the code: debug(a,b,c) If DEBUG is turned on, nothing will happen to the debug statements, so a call to debug will be produced (as you would expect). If DEBUG isn't defined, the symbol "debug" will be pre-processed out of existance, so the compiler will see an expression like: (a,b,c) If the arguments don't produce any side effects, I believe that most decent compilers will not emit any code (or at least the optimizer should be able to detect a load of a useless register. If the debug function returns a value that is checked, when DEBUG is turned off, the value will be the last parameter, which will generate code, but I don't suppose that the debug routine actually returns a value. Simple expressions as arguments to the debug function should also produce no code if DEBUG is turned off, but it is possible that complex expressions could fool the compiler into generating code for parts of the expression then throwing the result away. One way that this could generate code is if the optimizer has to remove the useless loads and this is the last expression in the function (so that there isn't a return statement). If a value is loaded into the register that is used for the return value, the optimizer may think that that is the return value and thus it wouldn't think it was a useless load. If any of the arguments have side effects or involve function calls (with potential side effects there!), these will (and should) always be generated. However, I don't think that it is likely that you would want to be doing this sort of thing in a call to a debugging macro. Are there any problems with doing this? I suppose that some pre-processors could choke on the parenthesis after debug in the invocation, since debug is #defined as a parameter-less macro, but my pre-processor (SVR2) doesn't. Marcus Hall ..!ihnp4!ihlpl!marcus
geoff@ism780c.UUCP (Geoff Kimbrough) (10/02/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >What I want to do is to write a function call of a variable number of >arguments: > debug(x, y, z, ...) I've used this construction #if DEBUG #define debug(X) printf X /* note NO parentheses */ #else #define debug(X) #endif and written debug(( "stuff =%x blek = %d", var1,var2)) /* note double parentheses */ seems to work for me. You're welcome.
kenny@uiucdcsb.cs.uiuc.edu (10/03/86)
/* Written 12:44 pm Oct 2, 1986 by marcus@ihlpl.UUCP in uiucdcsb:net.lang.c */ >In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >>What I want to do is to write a function call of a variable number of >>arguments: >> >> debug(x, y, z, ...) >> >>that will generate no code when the symbol DEBUG is not defined, [...] >How about this: > >#ifndef DEBUG >#define debug >#endif > >and writing in the code: > > debug(a,b,c) > >If DEBUG is turned on, nothing will happen to the debug statements, so a >call to debug will be produced (as you would expect). If DEBUG isn't >defined, the symbol "debug" will be pre-processed out of existance, so >the compiler will see an expression like: > > (a,b,c) [...] >Are there any problems with doing this? I suppose that some pre-processors >could choke on the parenthesis after debug in the invocation, since debug >is #defined as a parameter-less macro, but my pre-processor (SVR2) doesn't. > >Marcus Hall /* End of text from uiucdcsb:net.lang.c */ If you invoke it in the code as debug (a, b, c) ^ Note the space! then no preprocessor should ever confuse it; macros with parameters are recognized only if no space intervenes between the macro name and the left parenthesis. Kevin Kenny UUCP: {ihnp4,pur-ee,convex}!uiucdcs!kenny University of Illinois at Urbana-Champaign CSNET: kenny@UIUC.CSNET ``Don't worry; I'm a New Yorker!'' ARPA: kenny@B.CS.UIUC.EDU (kenny@UIUC.ARPA)
plocher@puff.wisc.edu (John Plocher) (10/03/86)
<f u cn rd ths, u hv no ln etr> There were some debug routines posted in net.sources which use this format: #ifdef DEBUG # define TRACE printf #else # define TRACE #endif ... TRACE("The error '%s' is on line %d\n", errorname, lineno); ... which expands into printf(...) if DEBUG is defined, and into (...) if not. Note that (...) does NOT GENERATE CODE, but is rather just an expression. -- harvard-\ /- uwmacc!uwhsms!plocher (work) John Plocher seismo-->!uwvax!< topaz-/ \- puff!plocher (school) civil flames (ie. ones which are WORTH reading) only, please! "Never trust an idea you get sitting down" - Nietzche
franka@mmintl.UUCP (Frank Adams) (10/06/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP writes: >What I want to do is to write a function call of a variable number of >arguments: > > debug(x, y, z, ...) > >that will generate no code when the symbol DEBUG is not defined, but >generate a call of some function (say, debug_()) when it is. Here's a possibility which is slightly ugly, as all the others are, but the ugliness is in a different place. Write: #ifdef DEBUG #define debug(a) debug_ a #else #define debug(a) #endif Now, write your debug statements with an extra pair of parentheses: debug((x, y, z, ...)); I'm not necessarily recommending this; it's just an idea. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
drw@cullvax.UUCP (Dale Worley) (10/06/86)
I have received an elegant (and in retrospect, obvious) solution to this problem from someone whose name I can't remember: #ifdef DEBUG #define debug(x) debug_ x #else #define debug(x) /* null */ #endif You then write function calls: debug((a, b, c)) Dale
greg@utcsri.UUCP (Gregory Smith) (10/06/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >What I want to do is to write a function call of a variable number of >arguments: > > debug(x, y, z, ...) > >that will generate no code when the symbol DEBUG is not defined, but >generate a call of some function (say, debug_()) when it is. If You could write debug( ( x,y,z ) ); In the code, and #ifdef DEBUG # define debug(list) _debug list #else # define debug(list) #endif -- ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
faustus@ucbcad.BERKELEY.EDU (Wayne A. Christopher) (10/07/86)
I just thought of this one: #ifdef DEBUG #define debug debug_function #else #define debug sizeof #endif Wayne
john@frog.UUCP (John Woods, Software) (10/07/86)
> What I want to do is to write a function call of a variable number of > arguments: > debug(x, y, z, ...) > that will generate no code when the symbol DEBUG is not defined, but > generate a call of some function (say, debug_()) when it is. Try: #ifdef DEBUG #define debug(x) x #else #define debug(x) #endif debug( puts("Shut 'er down, Scotty, she's sucking mud again."); ) The extra layer of indirection may feel irritating, but it also allows debug( if (op == NULL) exit(puts("RATS RATS RATS [#566, para. 1]")); ) It's quick, it's easy, it works. -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA "Don't give me this intelligent life crap, just find me a planet I can blow up."
chris@umcp-cs.UUCP (Chris Torek) (10/08/86)
The problem: to include debug calls, with variable argument lists, such that they may be conditionally compiled (a la #if), but without cluttering the source with `#ifdef'. Two standard solutions, and their problems: 1: #ifdef DEBUG #define debug(x) debug_ x #else #define debug(x) /* null */ #endif ... foo(foostring, foovalue) char *foostring; int foovalue; { debug(("foo(%s, %d)", foostring, foovalue)); ... Problem: The call to `debug' `looks funny'. (This is not all that trivial; style is important to readability.) 2: #ifdef DEBUG #define debug #else #define debug debug_ #endif ... debug("foo(%s, %d)", foostring, foovalue); ... Problems: Some preprocessors apparently gripe about argument mismatches, requiring an extra space: `debug ("foo(%s, %d)", ...)'. Other compilers generate code and/or data even when DEBUG is turned off, since this preprocesses to ("foo(%s, %d)", foostring, foovalue); A third solution, which no one seems to have proposed here, is to write your own `pre-prepocessor processor'. Here for your amusment and/or edification is a lex specification that matches C code inputs. I used it for `grim', a program pessimiser. (An optimiser makes code better, so a pessimiser makes code worse. It was fun to write.) Caveat: the lexer matches comments in their entirety, and thus requires a large lex buffer. This can be avoided by using `BEGIN' and extra lex states, but I wanted the comment text too. It also does not match C perfectly, only as well as I needed. It should, however, suffice for a debug remover. %{ #undef YYLMAX #define YYLMAX 32768 #define yywrap() 1 %} id [a-zA-Z_][a-zA-Z0-9_]* whitespace [ \t\n] comment \/\*(\*[^/]|[^*])*\*+\/ charconst \'(\\\'|[^'])*\' strings \"(\\\"|[^"])*\" number [0-9]+ %% ^#[ \t]*define[ \t]+.* { MungeNumberDefine(); } ^#.* { printf("%s", yytext); } {comment} { MungeComment(); } {strings} { printf("%s", yytext); } {charconst} { printf("%s", yytext); } {id} { MungeID();} {whitespace} { putchar(yytext[0]); } {number}[lL] { printf("%s", yytext); } {number} { printf("%s", yytext); } . { putchar(yytext[0]); } %% -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
franka@mmintl.UUCP (Frank Adams) (10/08/86)
In article <3731@umcp-cs.UUCP> chris@umcp-cs.UUCP writes: >The problem: to include debug calls, with variable argument lists, >such that they may be conditionally compiled (a la #if), but without >cluttering the source with `#ifdef'. > >2: #ifdef DEBUG > #define debug > #else > #define debug debug_ > #endif > ... > debug("foo(%s, %d)", foostring, foovalue); > ... (the #defines here should be reversed) >Problems: [...] >Other compilers generate code and/or data even when DEBUG is turned >off, since this preprocesses to > > ("foo(%s, %d)", foostring, foovalue); This problem is not totally dependent on the quality of the compiler. If any of the arguments to the debug_ function involves a function call, the compiler *must* generate code for it. E.g., debug("x=%d, sin(x)=%d", x, sin(x)); Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
guido@mcvax.uucp (Guido van Rossum) (10/11/86)
In article <357@cullvax.UUCP> drw@cullvax.UUCP (Dale Worley) writes: >What I want to do is to write a function call of a variable number of >arguments: > > debug(x, y, z, ...) > >that will generate no code when the symbol DEBUG is not defined, but >generate a call of some function (say, debug_()) when it is. If >Is there a good way to do this? If you are willing to write extra parentheses but want them to match, write this: #ifdef DEBUG #define debug(x) debug_ x #else #define debug(x) /* empty */ #endif and call as follows: debug((x, y, z, ...)); -- Guido van Rossum, CWI, Amsterdam <guido@mcvax.uucp>
mcg@omepd.UUCP (10/13/86)
You guys are all thinking too hard. Even the venerable Chris Torek has proposed a solution more complex than needed. On any compiler likely to be used for production code, the optimizer will generate no code whatsoever for the following fragment: #define DEBUG 0 /* set to 1 to turn debugging on */ ... if (DEBUG) debug(...); Similarly, in the case of '#define DEBUG 1', the unneccesary test will be elided. In the idiom of the original posting, the example is: #define debug if(DEBUG) debug debug(x,y,z); Though care must be taken in using this form in un-braced if statements that have else clauses. The preprocessor solutions have the intoxicating air of complexity about them, but, in my experience, this solution proves easiest and most effective. Why look for trouble? Trouble will find you. S. McGeady
mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) (10/27/86)
In article <162@omepd> mcg@omepd.UUCP (Steven McGeady) writes: > >You guys are all thinking too hard. > > #define DEBUG 0 /* set to 1 to turn debugging on */ > ... > if (DEBUG) debug(...); > >Similarly, in the case of '#define DEBUG 1', the unneccesary test will >be elided. > >In the idiom of the original posting, the example is: > > #define debug if(DEBUG) debug > > debug(x,y,z); I came into this late, so you might already know this, but try this on for size anyway: # ifdef DEBUG # define debug(x) fprintf x # else # define debug(x) # endif ..... debug((stderr, "Control string", arg1, arg2, ... argn)); Cute, isn't it? I stole it out of the src to enscript (adobe something or other). -- Larry McVoy mcvoy@rsch.wisc.edu, {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy "They're coming soon! Quad-stated guru-gates!"
andy@Shasta.UUCP (10/28/86)
#define DEBUG 1 /* or 0 as appropriate */ #define debug if( DEBUG ) fprintf (Replace fprintf with the appropriate function.) Then you can write: debug( stderr, "wrong args %d, %s, %p\n", d, s, p ); /* %p is bogus */ Either your compiler eliminates dead code or it doesn't. If it doesn't, other dead code and missed opportunities to generate good code will swamp the overhead of checking if 0 is still 0 and skipping the fprintf. If it does, the fprintf (and its args) will be removed. -andy ps - Yes, I know my debug will pick up a following "else". I use "extra" {}'s and debug( <args> ) shouldn't be followed by an "else" anyway; I'll document that feature and let it slide. It is difficult to handle all possible constraints with something as limited as cpp; "debug( (<args>) )" grates on me. I'd rather write "if( DEBUG ) <code>" directly than "debug( <args> )" because it doesn't restrict <code>. -- Andy Freeman UUCP: ...!decwrl!shasta!andy forwards to ARPA: andy@sushi.stanford.edu (415) 329-1718/723-3088 home/cubicle