gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) (05/03/90)
I want to have a DEBUG flag which controls whether diagnostic printfs are executed or not. The obvious way to do this is: #ifdef DEBUG printf ("debugging information"); #endif DEBUG But its a pain to have to type the #ifdef ... #endif all the time, and its less readable than simply having: DEBUG ("debugging information"); Now, I can use the latter format if I #define DEBUG printf but then how do I turn DEBUG off? I have though of doing the following (which is not very elegant but I thought it would work): #ifdef DODEBUG # define DEBUG printf # define ENDDEBUG ; #else # define DEBUG /* # define ENDDEBUG */ #endif DODEBUG which would allow the following syntax for debugging DEBUG ("the value is %d", val); ENDDEBUG Unfortunately, I can't figure out how to #define something to be equal to "/*" sinece "/*" always seems to be interpreted as the start of a comment. Well, I've been rambling trying to describe the problem. Basically, does anyone have an idea how I can do the above easily and elegantly? Thanks for reading. - Jeff
gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) (05/03/90)
I forgot to mention, the DEBUG should take an arbitrary number of arguments (just like printf). - Jeff
wallyk@tekfdi.FDI.TEK.COM (Wally Kramer) (05/04/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. How about writing your diagnostic statements "thusly": DEBUG (("informative message #1: j = %d, k = %d", j, k)); /* note extra parens surrounding normal printf parameters */ To enable debugging statements: #define DEBUG(x) printf x To disable: #define DEBUG(x) Lint note: you should define debug on when you run this through lint. wallyk@tekfdi.fdi.tek.com (Wally Kramer) Contractor to Tektronix from Step Technology, Inc. 503 244 1239
thornley@cs.umn.edu (David H. Thornley) (05/04/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. > >The obvious way to do this is: > >#ifdef DEBUG > printf ("debugging information"); >#endif DEBUG How about #ifdef DEBUG #define D(X) X #else #define D(X) #endif and D(printf("debugging information\n");) If DEBUG is defined, anything in D() is used as is; if not, anything in D() is disregarded. It seems to work for me. David Thornley
CMH117@psuvm.psu.edu (Charles Hannum) (05/04/90)
#ifdef DEBUG #define debug(x) printf x #else #define debug(x) #endif Then, you can just use something like: debug(("%s\n","This is a test.")); (<=== This is an EXAMPLE; it's not meant to be efficient, just to emphasize the syntax!!!!) in your code. Just like printf(), except you need *two* parentheses around the argument list. I've been using this trick for years. Virtually, - Charles Martin Hannum II PennMUD Design Team - (Resident) Programmer (That's Charles to you!) "Those who say a thing cannot be done should Please send mail to: under no circumstances stand in the way of hannum@haydn.psu.edu he who is doing it." - a misquote
karl@MorningStar.Com (Karl Fox) (05/04/90)
In article <40628@cornell.UUCP> gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes:
I want to have a DEBUG flag which controls whether diagnostic printfs
are executed or not.
The obvious way to do this is:
#ifdef DEBUG
printf ("debugging information");
#endif DEBUG
But its a pain to have to type the #ifdef ... #endif all the time, and
its less readable than simply having:
DEBUG ("debugging information");
Now, I can use the latter format if I
#define DEBUG printf
but then how do I turn DEBUG off?
Here is a not-too-gross method I have seen suggested (and used):
# define DEBUG(a) printf a
or, to disable it,
# define DEBUG(a)
Then, call it with a double set of outer parentheses:
DEBUG(("Warning: user %s has an ugly face!\n", user_name));
It even works as the THEN clause of an IF statement.
--
Karl Fox, Morning Star Technologies karl@MorningStar.COM
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/04/90)
Organization: U.S. Army Ballistic Research Laboratory In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: > DEBUG ("debugging information"); >Well, I've been rambling trying to describe the problem. Basically, >does anyone have an idea how I can do the above easily and elegantly? There are several viable approaches, but PLEASE don't carry on this discussion in all the groups you posted to: comp.lang.c,comp.unix.wizards,alt.sources,comp.sources.d,misc.misc when comp.lang.c is the proper forum. The simplest solution in the terms in which you originally designed your use of DEBUG is to #define DEBUG or #define DEBUG (void) to turn off the printf.
wallace@oldtmr.enet.dec.com (Ray Wallace) (05/04/90)
In article <4247@tekfdi.FDI.TEK.COM>, wallyk@tekfdi.FDI.TEK.COM (Wally Kramer) writes... >In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) >writes: >>I want to have a DEBUG flag which controls whether diagnostic printfs >>are executed or not. > DEBUG (("informative message #1: j = %d, k = %d", j, k)); > /* note extra parens surrounding normal printf parameters */ Why not just do this - #define BITCH /* IE: don't print it */ #define DEBUG printf /* IE: do print it */ main( ) { BITCH( "What the <%s> is going on?\n", "hell" ); DEBUG( "%d - nothing.\n%d - something.\n", 1, 2 ); } When the "debug" macro is defined as nothing then the stuff in paranthesis gets eveluated as an expresion(s) but thats all. When the "debug" macro is defined as printf then your standard function call to printf occurs. There is no need for an extra set of parenthesis. --- Ray Wallace (INTERNET,UUCP) wallace@oldtmr.enet.dec.com (UUCP) ...!decwrl!oldtmr.enet!wallace (INTERNET) wallace%oldtmr.enet@decwrl.dec.com ---
randy@csseq.cs.tamu.edu (Randy Hutson) (05/04/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) wri tes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. I use something like the following: #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF if(0) printf #endif Now there's no need to put an extra set of parentheses about DPRINTF's arguments. As for any efficiency concerns, no compiler I regularly use (gcc, Sequent cc, and sun cc) generates an explicit comparison to 0. However, they do leave in the dead code (calls to printf) unless the optimizer is invoked, so this method could make your executables larger if your C compiler doesn't have an optimizer which eliminates dead code.
escher@Apple.COM (Michael Crawford) (05/04/90)
In article <1990May3.192347.12973@cs.umn.edu> thornley@cs.umn.edu (David H. Thornley) writes: >In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: >>I want to have a DEBUG flag which controls whether diagnostic printfs >>are executed or not. >> >>The obvious way to do this is: >> >>#ifdef DEBUG >> printf ("debugging information"); >>#endif DEBUG > >How about >#ifdef DEBUG >#define D(X) X >#else >#define D(X) >#endif > >and >D(printf("debugging information\n");) more elegant still: #ifdef DEBUG #define fDebug( x ) fprintf x #define Debug( x ) printf x #else #define fDebug( x ) #define Debug( x ) #endif fDebug(( stderr, "debugging info" )); Debug(( "debugging info" )); be sure to do the defining of DEBUG on the CC command line, with a nifty setup in your makefile: D= CFLAGS = ${D} foo: foo.o cc -o foo foo.o foo.o: foo.c cc -c ${CFLAGS} foo.c Then your command line might be: alias md 'make D=-DDEBUG' touch foo.c md and you will turn on debugging in foo.c. Read Robert Ward's book "Debugging C". It is a gold mine. Mostly oriented toward DOS, but much of what is in it is applicable anywhere. Also, get a source level debugger. You may have sdb or dbx on Unix systems, SADE or ThinkC on Macintosh, or Codeview, and I think Turbo C, on the PC. The Free Software Foundation's GDB is available for Unix for free and is much better than dbx or sdb, IMHO. When you learn to use them effectively, it is a lot better than embedding code in your source -- less recompiling. -- Michael D. Crawford Oddball Enterprises Consulting for Apple Computer Inc. 606 Modesto Avenue escher@apple.com Santa Cruz, CA 95060 Applelink: escher@apple.com@INTERNET# oddball!mike@ucscc.ucsc.edu The opinions expressed here are solely my own. Free Lithuania.
ronnie@mindcrf.UUCP (Ronnie Kon) (05/04/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. > [ lots of stuff deleted ] How about: #if WANT_DEBUGGING # define DEBUG(a,b,c,d,e) printf(a,b,c,d,e) #else # define DEBUG(a,b,c,d,e) #endif This is ugly, in that you must always supply a fixed number of parameters, but it's quick and easy. You can also use multiple definitions, DEBUG1, DEBUG2, etc, each taking a different number of parameters. If your application is not real-time, you can also make DEBUG a real routine, which does nothing if your definition is not turned on, and a printf if it is. This causes an overhead of a few microseconds on an average machine (say a 10MHz 68000) each call. Hope this helps. Ronnie -- ------------------------------------------------------------------------------- Ronnie B. Kon | "The answers to life's problems aren't at kon@mindcraft.com | the bottom of a bottle: they're on TV!" ...!{decwrl,ames}!mindcrf!ronnie | -- Homer Simpson -------------------------------------------------------------------------------
jik@athena.mit.edu (Jonathan I. Kamens) (05/04/90)
In article <1717@engage.enet.dec.com>, wallace@oldtmr.enet.dec.com (Ray Wallace) writes: |> Why not just do this - |> |> #define BITCH /* IE: don't print it */ |> #define DEBUG printf /* IE: do print it */ |> main( ) |> { |> BITCH( "What the <%s> is going on?\n", "hell" ); |> DEBUG( "%d - nothing.\n%d - something.\n", 1, 2 ); |> } Because it's sloppy and causes good compilers to complain. Compiling your program on an IBM RT/PC running AOS4.3 with MetaWare's High C compiler (version 2.1y) works, but produces the following warnings: w "foo.c",L5/C8: "What the <%s> is going on?\n" | Expression has no side-effects. w "foo.c",L5/C8: Expression has no side-effects. It's stupid to write code that makes the compiler bitch when it's possible to accomplish the same purpose without the compiler complaining at all. The more a compiler is forced to bitch, the more programmers come to expect compiler error messages, and therefore the less seriously they take them. I personally make it a policy never to write any "real" code (i.e. code that I expect anyone else to ever see; and please let's not get into the debate of one-time-only programs again) that won't compile with High C without any errors. I wish more programmers had better compilers to check their code with, and/or ran their code through lint more often, because it's a rare program I get off the net that doesn't cause compiler errors or warnings when I compiler it on my system. Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8495 Home: 617-782-0710
davidsen@sixhub.UUCP (Wm E. Davidsen Jr) (05/04/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: | I want to have a DEBUG flag which controls whether diagnostic printfs | are executed or not. #ifdef DEBUG #undef DEBUG /* prevent warning from redef */ #define DEBUG(x) printf x #else #define DEBUG(x) #endif To use: DEBUG(("Any # of args: %d\n", whatever)); The secret is in having the 2nd level of parens in the invocation of DEBUG and no parens in the expansion. Works like a charm! -- bill davidsen - davidsen@sixhub.uucp (uunet!crdgw1!sixhub!davidsen) sysop *IX BBS and Public Access UNIX moderator of comp.binaries.ibm.pc and 80386 mailing list "Stupidity, like virtue, is its own reward" -me
dig@peritek.UUCP (Dave Gotwisner) (05/04/90)
In article <40628@cornell.UUCP>, gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: > I want to have a DEBUG flag which controls whether diagnostic printfs > are executed or not. > > The obvious way to do this is: > > #ifdef DEBUG > printf ("debugging information"); > #endif DEBUG > > But its a pain to have to type the #ifdef ... #endif all the time, and > its less readable than simply having: > > DEBUG ("debugging information"); Agreed. > > Now, I can use the latter format if I > > #define DEBUG printf > > but then how do I turn DEBUG off? Having read some of the other responses, I have yet to see the one I use: #ifdef DEBUG # define Dprintf printf #else # define Dprintf if #endif This only needs to be included in a common header file, then, if you do: Dprintf("Input value is %d\n", 10); you get the following if DEBUG is defined: printf("Input value is %d\n", 10); and the following if DEBUG is not defined: if ("Input value is %d\n", 10); The semicolon will terminate the if, so, unless the debug printf has an else immediatly after it, this will work. There is some run time overhead (unless your compiler optimizes "if (statement);" away because it never does anything), but the overhead should be small. -- ------------------------------------------------------------------------------ Dave Gotwisner UUCP: ...!unisoft!peritek!dig Peritek Corporation ...!vsi1!peritek!dig 5550 Redwood Road Oakland, CA 94619 Phone: 1-415-531-6500
dsmythe@netcom.UUCP (Dave Smythe) (05/04/90)
It seems to me that if you want to go the instrumentation route, as opposed to the debugger route, then you might want to look at the dbugsys package (I think that there were at least 2 kinds) posted a while back to c.s.misc or c.s.unix. If I recall correctly, it does all of that kind of DEBUG stuff as well as giving you run-time control of the level of debugging info that you want to see (foo -x4 , or something like that). There were quite a variety of functions there for many other purposes as well. D
dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) (05/04/90)
In article <90123.152729CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes: > >#ifdef DEBUG >#define debug(x) printf x >#else >#define debug(x) >#endif > On UNIX you might want to do something like: #ifdef DEBUG #define debug(x) printf x, fflush (stdout) #else #define debug(x) #endif or put an #ifdef DEBUG setbuf (stdout, NULL); #endif near the beginning of main. Otherwise you have no way of knowing where in the program it crashed. -- Dave Eisen Home: (415) 323-9757 dkeisen@Gang-of-Four.Stanford.EDU Office: (415) 967-5644 "I drive a brand new BMW and I wear an unusually large shoe..."
rob@icarus.inmos.co.uk (Robin Pickering) (05/04/90)
In article <1717@engage.enet.dec.com> wallace@oldtmr.enet.dec.com (Ray Wallace) writes: > >Why not just do this - > >#define BITCH /* IE: don't print it */ >#define DEBUG printf /* IE: do print it */ >main( ) >{ > BITCH( "What the <%s> is going on?\n", "hell" ); > DEBUG( "%d - nothing.\n%d - something.\n", 1, 2 ); >} The trouble with this approach is that the debug strings and the cost of evaluating the expr, still get compiled in whether debug is on or not. This may not be a problem in some applications, but if you don't mind the debug information always being in the code then why not turn it on at runtime by making DEBUG a function whose operation is controlled by a runtime switch (much more flexible and at least there is the possibilty of making those compiled in strings work for a living occaisionally). If you do use the above approach, might I suggest: #define BITCH (void) /* IE: do nothing, but dont make lint scream about each debug line */ Rob Pickering. -- JANET: ROB@UK.CO.INMOS | Snail: 1000 Aztec West Internet: rob@inmos.com | Almondsbury Path: ukc!inmos!rob or uunet!inmos-c!rob | Bristol BS12 4SQ Phone: +44 454 611638 | UK
silvert@cs.dal.ca (Bill Silvert) (05/04/90)
In the recent postings there were a number of solutions to the problem of defining a function DEBUG which optionally works like printf. Only one addresses the fact that debugging information should preferably go to stderr: In article <8060@goofy.Apple.COM> escher@Apple.COM (Michael Crawford) writes: >more elegant still: > >#ifdef DEBUG >#define fDebug( x ) fprintf x >#define Debug( x ) printf x >#else >#define fDebug( x ) >#define Debug( x ) >#endif > >fDebug(( stderr, "debugging info" )); >Debug(( "debugging info" )); Is there a way to define Debug so that Debug(x, y, z,...) can optionally either do nothing or generate fprintf(stderr, x, y, z,...) with an arbitrary number of arguments? Crawford's method still requires specific mention of stderr in each debug line. -- William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2. Tel. (902)426-1577 UUCP=..!{uunet|watmath}!dalcs!biomel!bill BITNET=bill%biomel%dalcs@dalac InterNet=bill%biomel@cs.dal.ca
jmoore@cidmac.ecn.purdue.edu (James D Moore) (05/04/90)
In article <1717@engage.enet.dec.com> wallace@oldtmr.enet.dec.com (Ray Wallace) writes: > >In article <4247@tekfdi.FDI.TEK.COM>, wallyk@tekfdi.FDI.TEK.COM (Wally Kramer) >writes... >>In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) >>writes: >>>I want to have a DEBUG flag which controls whether diagnostic printfs >>>are executed or not. Several people have pointed out several ways to use the #define to equate DEBUG to printf. I personaly feel that using the standard #ifdef and using the the "-D<flag>" option at compile time is the best way to do it. Am I missing something here ? I do this with different levels of debugging so I can have several flags. Anyway that is my $0.2 worth. Jim Moore Purdue University jmoore@cidmac.ecn.purdue.edu
passaret@brahe.crd.ge.com ("Mr. Mike" Passaretti) (05/04/90)
In article <40628@cornell.UUCP> gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: # # I want to have a DEBUG flag which controls whether diagnostic printfs # are executed or not. # # [....] # # - Jeff Fred Fish has produced an excellent set of macros for C which do just this and a lot more. The basic form of use is as follows (forgive me if this is a bit long). #include "dbug.h" main(argc, argv) int argc; char *argv[]; { int foo; DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); for (i=1;i<argc && argv[i][0]=='-';i++) { switch(argv[i][1]) { case '#' : { DBUG_PUSH(&(argv[i][2])); } break; [...] } } foo = bar_bar_bar(); DBUG_PRINT("bar", ("Foo = %d\n", foo)); foo = blah_blah_blah(); DBUG_PRINT("blah", ("Foo = %d\n", foo)); DBUG_VOID_RETURN(0); } Now, at run-time the program can be called with a command line like 'a.out #d:t mumble'. This is a flag which the DBUG macros use (through DBUG_PROCESS and DBUG_PUSH) to enable and disable various functions. There is tracing, which is an output like >main ->bar_bar_bar -<bar_bar_bar ->blah_blah_blah -<blah_blah_blah <main for simple level tracing. There is also "flag" type printf enabling, where a command line like 'a.out #dbar,:t mumble' would cause all DBUG_PRINTFs with the keyword (1st arg) "bar" to get printed. There are also global enables and disables, including the #define DBUG_OFF, which removes all of the debug code entirely (for production usage). my dbug.h has the following author notice in it, but I think it's outdated. Fred's whereabouts should be easy to determine, if by no other method than eavesdropping on comp.sys.amiga for a while. * AUTHOR * * Fred Fish * (Currently employed by Motorola Computer Division, Tempe, Az.) * hao!noao!mcdsun!fnf * (602) 438-3614 - MM -- passaretti@crd.ge.com {whatever}!crdgw1!brahe!passaret
rosenber@ra.abo.fi (Robin Rosenberg INF) (05/04/90)
>I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. I have used the following macros for a while now and they work fine. /* tdebug.h -- tracing & debugging macros * */ #if TDEBUG #define T(s) {dprintf("\033[33m(\033[0m%s\033[0m",#s);{s} dprintf("\033[33m)\033[0m\r\n");} #define D(s) s #define P(a) dprintf a #define V(n,x) {if (debuglevel>=n) dprintf("%s\r\n",x);} #else #define T(s) {s} /* ! trace execution of statements */ #define D(s) ; /* ! execute only when debugging */ #define P(a) /* ! printf when debugging */ #define V1(n,x) {} #endif TDEBUG /* eof */ dprintf has the same synopsis as printf, however if may be some other function. Which function it is is defined at link time. Usually dprintf asks another process to print the debugging info for me. If your system does not allow you to define symbols at link time, replace dprintf with the funtion you want in tdebug.h Note however that the T() macro doesn't work in all cases. Most notably it may have to be written differently for other compilers and may not work if the statement beging traced contains double quotes. Also, the ANSI escape sequences used in the T() macro is to help matching parentheses in the trace output. Here is a sample (not useful) program using these macros #define TDEBUG 1 /* or 0 if debugging is not wanted */ #include "tdebug.h" int debuglevel; main(int argc,char **argv) { debuglevel = atoi(argv[1]); P(("This is a demo. Prog =%s\n",argv[0])); T(subroutine(argc,argv);) V(1,"I will now fall off the e"); } You may use or modify these macros as you like according to your needs. Enjoy! ----------- Robin Rosenberg
travis@cs.columbia.edu (Travis Lee Winfrey) (05/04/90)
In article <40628@cornell.UUCP>, >gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: > > I want to have a DEBUG flag which controls whether diagnostic printfs > are executed or not. Well, another variation on the debug macro with two parentheses is to have a first argument that specifies the current level of interest. This argument can be compared with whatever you need: a module-specific #define, a module-specific variable, a global variable. The two biggest problems with this method are the complaints from lint about constants appearing in an if-statement, and that some compilers may not strip out the code when you don't want the output. A sample follow. Note that the numbers here range from 1 to 4 because I define DEBUG on a per-module basis. Some other people specify their interest in debugging information in terms of percentages, i.e., show me 50% of everything you have in this module. that's not intuitive for me. (I'm sorry if anyone else has already described this particular fillip; I looked through all the messages posted so far, as many of the previous posters should have done.) /* * debugging macros. the dprintf macro takes two arguments, a * debugging level (1, 2, 3, 4) and a list of ordinary printf * arguments in parentheses, e.g., * dprintf(1, ("proc_kill_module: sys_ptr is NULL!\n")); * * debugging levels: * level 1: ordinary unexpected events which the programmer may want * to know, but a user will not. all "oh no!" type * information should be marked with this. * level 2: more detailed, usually per-module information that * will a programmer will not want to know *unless* he or * she is debugging that module. * Level 3: more detailed than 2, usually per-procedure * debugging information. debugging statements this * low-level will be removed once gross errors are * found and removed. * Level 4: just a level for demarcating extremely low-level, * usually inner-loop information. removed as level 3 messages. * */ # ifdef DEBUG # define dprintf(dlevel,printfargs) if (dlevel <= DEBUG ) \ printf printfargs # else /* DEBUG */ # define dprintf(a,b) # endif /* DEBUG */ -- Arpa: travis@cs.columbia.edu Usenet: rutgers!columbia!travis
tif@commlab1..austin.ibm.com (/32767) (05/05/90)
In article <40628@cornell.UUCP> gordon@cs.cornell.edu (Jeffrey Adam Gordon) writes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. > DEBUG ("debugging information"); >but then how do I turn DEBUG off? Actually it's easier than you thought: #define DEBUG will turn it off although the string will still be put in your executable (unless your optimizer is better than mine). ("xx") is a parenthesised pointer expression which is a valid C statement. Most people I know of do #define DEBUG(xx) printf xx and then DEBUG(("the flag is %d\n", flag)); The whole thing is completely removed with #define DEBUG(xx) Paul Chamberlain tif@doorstop.austin.ibm.com tif@commlab1.austin.ibm.com sc30661@ausvm6
bjstaff@zds-ux.UUCP (Brad Staff) (05/05/90)
I add some declarations that look something like the following: #ifdef PRODUCTION #define DEBUG 0 #else int DEBUG = FLAG1 | FLAG2 | ... | FLAGn; #endif /* PRODUCTION */ Then I do it like this: if (DEBUG & FLAGx) printf(...); This way the debug statements look more like regular C code, which is more aesthetically pleasing to my eyes. :-) This method allows you to turn debug printfs on and off in a running system by patching the DEBUG variable with a kernel debugger or adb. When you #define PRODUCTION, any compiler worth using (IMHO) will optimize away both the test and the printf itself, for a zero performance penalty. -- Brad Staff | Zenith Data Systems | "A government that can forbid certain 616-982-5791 | psychoactive drugs can mandate others." bjstaff@zds-ux.zds.com | - Russell Turpin
jkimble@nostromo.austin.ibm.com (The Programmer Guy) (05/05/90)
> [quick DEBUG method within programs]
Here's how I usually do it:
#define DEBUG(l, f, s) if (Debug >= l) fprintf(stderr, f, s)
You will have to have "int Debug;" somewhere, usually as a global.
Now you just change (int)Debug to be whatever you want; I usually
have a command-line option that allows me to specify it in levels (ala
UUCP). For example: program -x9 (Debug will be set to 9, maximum debug)
program -x5 (Debug will be set to 5, medium debug)
program -x1 (Debug will be set to 1, minimum debug)
Your DEBUG statements look like so within the program:
DEBUG(7, "Number of elements within array = %d\n", nmbr);
DEBUG(5, "Pointer a = |%s|\n", a);
etc., etc., etc.,
Caveats:
If you just have an information message and don't want any
data passed, make sure you do something like this:
DEBUG(7, "We're in rmdir()...\n", "");
[note the second set of ""]
The final caveat is that you can only pass one parameter per DEBUG()
statement; therefore if you have multiple variables to print you're
going to have to use more than one DEBUG statement. However, I think
this is the cleanest way to handle this sort of stuff. (But I am sure
we're going to see plenty of other methods coming back from The Net).
Hope this helps!
--Jim Kimble, Phone: 512/823-4479 (work)
Yet Another IBM Contractor UUCP: ibmaus!jkimble@cs.utexas.edu
TCP/IP Development, RISC System/6000, RT++, RS/6000, etc.
IBM Austin, TX
"ALPO is 99 cents a can. That's almost SEVEN dog dollars!"
new@udel.EDU (Darren New) (05/05/90)
>>gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: >> >> I want to have a DEBUG flag which controls whether diagnostic printfs >> are executed or not. I have a version that interactively lets you specify the level of detail desired, allows part or all to be redirected to the printer or a file, and so on. It is somewhat AmigaDOS specific in terms of I/O handling, but if you can open a separate window on your platform, it shouldn't be a problem. If anybody wants it, let me know and I will post it to someplace appropriate (alt.sources.amiga?) -- Darren
wayne@ultra.com (Wayne Hathaway) (05/05/90)
travis@cs.columbia.edu (Travis Lee Winfrey) suggests: # ifdef DEBUG # define dprintf(dlevel,printfargs) if (dlevel <= DEBUG ) \ printf printfargs # else /* DEBUG */ # define dprintf(a,b) # endif /* DEBUG */ A good idea, and one which I also use (slightly more generalized, of course; I just can't resist getting too damn fancy for my own good!). I do have one nit, though: I would suggest defining "dprintf" as: define dprintf(dlevel,printfargs) if (dlevel > DEBUG) ; \ else printf printfargs Why? Consider the following: if ( <some_strange_situation> ) dprintf(1, ("oh no! just had some strange situation\n")); else <regular_processing>; You see, I just HATE programs that stop working when you turn on the DEBUG flag! :-) wayne Wayne Hathaway Ultra Network Technologies domain: wayne@Ultra.COM 101 Daggett Drive Internet: ultra!wayne@Ames.ARC.NASA.GOV San Jose, CA 95134 uucp: ...!ames!ultra!wayne 408-922-0100
gar@spiff.UUCP (Gordon Runkle) (05/05/90)
In article <40628@cornell.UUCP> gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: I want to have a DEBUG flag which controls whether diagnostic printfs are executed or not. But its a pain to have to type the #ifdef ... #endif all the time, and its less readable than simply having: DEBUG ("debugging information"); Now, I can use the latter format if I #define DEBUG printf but then how do I turn DEBUG off? I have though of doing the following (which is not very elegant but I thought it would work): [ valiant attempt...] There is a simple solution. Get the book "Debugging C" by Robert Ward (Que, Indianapolis, Indiana, ISBN: 0-88022-261-1). On page 106 is an example of exactly your problem. I will explian it, but I strongly recommend you buy the book. It's very useful. #ifdef TESTING # define TRACE(args) fprintf args #else # define TRACE(args) #endif This macro means that TRACE(args) will have a value if TESTING is defined. Otherwise, TRACE(args) will have no value, and the preprocesor will eliminate it. You want args to be affected too, for obvious reasons. When you use it, use *2 sets* of parentheses around the args, to insure that the entire list of args is given to fprintf(): main(argc, argv) int argc; char *argv[]; { TRACE((stderr, "argc is %d\n", argc)); if (argc > 1) printf ("hello world\n"); } In this example, if TESTING is defined, the TRACE statement will be converted to: fprintf (stderr, "argc is %d\n", argc); otherwise, it will be reduced to ";", an empty statement. It's pretty simple, really. Again, I really recommend the book. -=gordon=- <Gordon Runkle> -- UUCP: uunet!men2a!spiff!gar ARPA: men2a!spiff!gar@uunet.uu.net Management Information Consulting, Inc. HOME PH: 703-522-0825 2602 Lee Hwy, # 204, Arlington, VA 22201 WORK PH: 202-566-4382 "Just once I'd like to run across an alien menace that isn't immune to bullets." -- The Brigadier
markb@giga.slc.unisys.com (Mark Baranowski) (05/05/90)
References: <11290@hoptoad.uucp> <40628@cornell.UUCP> <1427@peritek.UUCP> Has any one of you knuckleheads posting followups to this thread taken a look at the header and realized what groups you are cross posting to? I have deleted the cross postings from the newsgroups in this article so as not to further this distribution of this asinine thread, but here is what it said: Newsgroups: comp.lang.c,comp.unix.wizards,alt.sources,comp.sources.d,misc.misc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do you think the unix wizards want to ponder the nifty things you can do with defines? Do you think people want to read about defines in alt.sources where only source code and nothing else is to be posted? Is this a discussion about some piece of source code in comp.sources? (comp.sources.d is for discussions about any old piece of software, right?) This is certainly miscellaneous information so why not include misc.misc, right? Anyone who posts a follow up to an article without checking the relevancy of the Newsgroups being cross-posted to is a knucklehead. -- Internet: markb@slc.unisys.com uucp: ...!giga!markb markb@signus.utah.edu Quote: Mutate or die! -- Howard Faxon
kc@oz.rci.dk (Knud Christensen) (05/07/90)
gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: >I want to have a DEBUG flag which controls whether diagnostic printfs >are executed or not. >The obvious way to do this is: >#ifdef DEBUG > printf ("debugging information"); >#endif DEBUG >But its a pain to have to type the #ifdef ... #endif all the time, and >its less readable than simply having: > DEBUG ("debugging information"); >Now, I can use the latter format if I >#define DEBUG printf >but then how do I turn DEBUG off? >I have though of doing the following (which is not very elegant but I >thought it would work): >#ifdef DODEBUG ># define DEBUG printf ># define ENDDEBUG ; >#else ># define DEBUG /* ># define ENDDEBUG */ >#endif DODEBUG >which would allow the following syntax for debugging > DEBUG ("the value is %d", val); ENDDEBUG >Unfortunately, I can't figure out how to #define something to be equal >to "/*" sinece "/*" always seems to be interpreted as the start of a >comment. >Well, I've been rambling trying to describe the problem. Basically, >does anyone have an idea how I can do the above easily and elegantly? >Thanks for reading. >- Jeff > The following, which i found in a magazine solves the problem very elegantly i think: /* debug.h This header file gives a number of usefull definitions for debugging */ #ifdef debug # define DFPRINTF(x) fprintf x # define DTRACE fprintf(stderr, "Trace line %d\n", __LINE__) # define DTRINT(var) fprintf(stderr, "Trace line %d var = %d\n", __LINE__, var) #else # define DFPRINTF(x) # define DTRACE # define DTRINT(var) #endif /* End of debug facility definitions */ C-program #define debug #include "debug.h" int i,j; main() { DFPRINTF((stdout,"This is a test %d", i)); } ---- Knud Christensen RC International, Denmark kc@rci.dk It is better to keep your mouth shut, and look like a fool than to open it, and remove all doubt! - Marx - (Groucho not Karl).
tsnider@enprt.Wichita.NCR.COM (Tim Snider) (05/07/90)
I was reading the stuff about DEBUG and here's what we do: #define DEB(n,a) if ( ldebug > n ) prt a The debugs can be turned on and off interactively by setting n to the desired value. You don't have to take old debug statements out just turn up the value for n so they won't print. The prt function is just a shell for the appropriate printf or fprintf statements depending on where/how the code is being executed. A typical DEBUG statment looks like: DEB (0, (" glorp %x glob %x splat %x", glorp, glob, splat)); The only negative thing about this method is that braces must be used around ifs etc. ------------------------------------------------------------------------- Tim Snider NCR Peripherial Products Div. Wichita Ks. tsnider@wichita.NCR.COM
robwah@auto-trol.UUCP (Robert Wahl) (05/08/90)
William Silver writes: >Is there a way to define Debug so that Debug(x, y, z,...) can optionally >either do nothing or generate fprintf(stderr, x, y, z,...) with an >arbitrary number of arguments? Crawford's method still requires >specific mention of stderr in each debug line. Consider the basic setup which is required to use a variable argument list in a macro. The list must be used as the argument list of a function call, and no other arguments can be added. However, that function need not be printf: #ifdef DEBUG #define DPRINTF(list) (dprintf list) #else #define DPRINTF(list) (1) /* Allows use of DPRINTF in expressions */ #endif DPRINTF ((fmtstr, arg1, arg2, arg3)); Writing "dprintf" is left as an exercise for the reader. Using assembly language, it may be an easy thing to prepend stderr to the variable argument list and then call "fprintf". Most likely, though, you will have to parse the format string for the number and type of arguments in order to set up the call to "fprintf". If so, you might as well do it all in C (which at least is portable), and do your output in stages. Here's a simply coded, but dreadfully hacky solution: temporarily replace stdout with stderr, then use printf as suggested before. This is inherently non-portable, inefficient, risky and generates lots of code. #ifdef DEBUG static FILE dprintf_stdout; static int dprintf_retval; #define DPRINTF(list) (dprintf_stdout = *stdout, *stdout = *stderr, \ dprintf_retval = printf list, *stdout = dprintf_stdout), dprintf_retval) #else #define DPRINTF(list) (1) /* Allows use of DPRINTF in expressions */ #endif If you do use this method, forget that you heard of it from me. Perhaps the best solution is just to use fixed argument lists; after all, how many values do you typically output in one debug statement? #ifdef DEBUG #define Debug0(fmt) (fprintf (stderr, fmt)) #define Debug1(fmt,val1) (fprintf (stderr, fmt, val1)) #define Debug2(fmt,val1,val2) (fprintf (stderr, fmt, val1, val2)) ... #else #define Debug0(fmt) (1) #define Debug1(fmt,val1) (1) #define Debug2(fmt,val1,val2) (1) ... #endif Debug3 ("Name is %s, value is %d (0x%x)\n", name, val, val); or Debug1 ("Name is %s, ", name); /* Note lack of newline in format string */ Debug2 ("value is %d (0x%x)\n", val, val); -- Rob Wahl =:-> {robwah@auto-trol.com | ...!ncar!ico!auto-trol|robwah}
versto@cs.vu.nl (Verstoep C) (05/08/90)
About one year ago a public domain package written by Fred Fish, appropriately called DBUG, appeared on the net. It's main feature is that it you can select, as a commandline option, the debug statements you want. For example (just snapped from another window): DBUG_PRINT("cluster", ("re-evaluating parameter `%s'", param->par_idp->id_text)); or DBUG_EXECUTE("objects", { PrintObject(obj); }); On the commandline you can then say (amake being the program I'm working on): amake -%d,cluster or amake -%d,cluster,objects which means that only the debug statements with the keywords mentioned will be executed. As shown above, a debug statement can be a generic print statement or an arbitrary piece of code by means of a DBUG_EXECUTE. If the program is compiled with the -DDBUG_OFF flags, all debugging code is automatically excluded, so you'll never have to remove a debug statement for efficiency reasons. Needless to say, this package is especially great for large programs under development. Besides the features mentioned it also has a kind of profiler and function tracer built-in, although I don't use those currently. If you're interested in the package, you could try to get it from one of the archives, or else contact me. Kees Verstoep (versto@cs.vu.nl)
kla@physc1.byu.edu (05/08/90)
I'm Sorry I just couln't resist this discussion. I have been using this type of Debugging statements for quite some time with a great deal of success. It all started when CodeView couldn't fit into the same 640K as the rest of my program, but I now use it in even my unix programs even when I also use a source level debugger. I tried to use debugging levels, as in: Debug(level,("%d %c %f",a,b,c)); but found that this was too much of a regimen for me. I finally settled for the following in a header file. static int __bug__ = 1; #define bug(); __bug__ = 1; #define bugoff(); __bug__ = 0; #ifdef DEBUG #define Debug(cmdstr) if(__bug__) { printf cmdstr ; fflush(stdout); } #else #define Debug(cmdstr) #endif The difference between this and the other things offered is slight, but important for Object Oriented programming. It is the bug() and bugoff() routines. This way you can debug a certain object WITHIN THE CONTEXT OF A BIG REAL LIFE PROGRAM without wading through piles of similar printouts of other already debugged modules. The __bug__ variable is defined as statically global to each and every module separately. This is a fine point, but it is important. Also, if you get into the source level debugger, and you find that there may be a problem in another module which was unexpected, you can turn on its debugging by toggling its __bug__ variable and watching the output for a while. The other thing which no one has mentioned, is that this type of statement should not be removed from production code. It is very useful as internal documentation. If a new programmer comes on and wants to figure out a new piece of code, he can just look at the Debug statements to find out what was in the mind of the YoYo that wrote it. He can also turn on the debug statements of one module to watch how that module interacts with other parts of the program. This could be made a lot more sophisticated as necessary. Thanks for your attention for this little addition to the Debug lore. One thing I haven't figured out yet. How to do this elegantly while debugging a user interface. Nothings perfect, but a log file might work by just redirecting stdout since most user interfaces don't use the standard printf. -Kelly -Just a few bats from the belfrey. kla@batman.byu.edu
fenske@dfsun1.electro.swri.edu (Robert Fenske Jr) (05/08/90)
In article <801@oz.rci.dk> kc@oz.rci.dk (Knud Christensen) writes: >gordon@mimir.cs.cornell.edu (Jeffrey Adam Gordon) writes: > >>I want to have a DEBUG flag which controls whether diagnostic printfs >>are executed or not. > How 'bout this: #define DPRINTF(s) if (DEBUG) printf(s) which can't be used in "if" statements for example--but still useful--or this: #define DPRINTF(s) (DEBUG ? printf(s) : 0) with perhaps some compilers complaining about a useless statement when debug is zero. DEBUG could be a #define or a variable and can be easily taken care of on the compiler command line. -- Robert Fenske, Jr. Sw | The Taming the C*sm*s series: Electromagnetics Division /R---\ | Southwest Research Institute | I | | "The Martian canals were the dfsun1.electro.swri.edu 129.162.160.4 \----/ | Martians' last ditch effort."
jmm@eci386.uucp (John Macdonald) (05/08/90)
In article <2294@awdprime.UUCP> tif@awdprime.austin.ibm.com.UUCP (/32767) writes: |Most people I know of do | #define DEBUG(xx) printf xx |and then | DEBUG(("the flag is %d\n", flag)); |The whole thing is completely removed with | #define DEBUG(xx) The same sequence has been suggested numerous times in previous messages. The double parentheses in this solution are annoying, and error-prone, and not really required. Try the following instead: #ifdef DEBUG_PRINT_ON # define DEBUG printf #else # define DEBUG(ignore) #endif To insert a DEBUG-conditional printf use: DEBUG( "format", args, ... ); (no double parens or other funny syntax required, it just looks like a function call) If you prefer, you can comment out one of the defines rather than controlling it with an ifdef. -- Algol 60 was an improvment on most | John Macdonald of its successors - C.A.R. Hoare | jmm@eci386
robinson (Jim Robinson) (05/09/90)
In article <801@oz.rci.dk> kc@oz.rci.dk (Knud Christensen) writes: >The following, which i found in a magazine solves the problem very elegantly i >think: > >/* > debug.h > > This header file gives a number of usefull definitions for debugging >*/ > >#ifdef debug ># define DFPRINTF(x) fprintf x ># define DTRACE fprintf(stderr, "Trace line %d\n", __LINE__) ># define DTRINT(var) fprintf(stderr, "Trace line %d var = %d\n", __LINE__, var) >#else ># define DFPRINTF(x) ># define DTRACE ># define DTRINT(var) >#endif > >/* > End of debug facility definitions >*/ Isn't the use of __LINE__ non-portable? -- Jim Robinson {uunet,ubc-cs}!van-bc!mdivax1!robinson
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/09/90)
In article <1990May8.183211.2661@mdivax1.uucp> mdivax1!robinson (Jim Robinson) writes: >Isn't the use of __LINE__ non-portable? I guess it depends on your definition of portable. The C standard requires that __LINE__ be supported by every conforming implementation.
robinson (Jim Robinson) (05/09/90)
In article <12814@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >In article <1990May8.183211.2661@mdivax1.uucp> mdivax1!robinson (Jim Robinson) writes: >>Isn't the use of __LINE__ non-portable? > >I guess it depends on your definition of portable. >The C standard requires that __LINE__ be supported by every conforming >implementation. Is this the ANSI C Standard? An admittedly cursory look thru a copy of the K&R C manual (first edition) did not produce any mention of __LINE__. And, is __FILE__ required to be supported? -- Jim Robinson {uunet,ubc-cs}!van-bc!mdivax1!robinson
jmm@eci386.uucp (John Macdonald) (05/09/90)
In article <1990May8.133742.10584@eci386.uucp> I wrote: | |The double parentheses in this solution are annoying, and error-prone, |and not really required. | |Try the following instead: | | #ifdef DEBUG_PRINT_ON | # define DEBUG printf | #else | # define DEBUG(ignore) | #endif | |To insert a DEBUG-conditional printf use: | | DEBUG( "format", args, ... ); without checking whether it worked. Well it used to work back when I was running on an old system, with an older preprocessor, but nowadays on many preprocessors you get an error message about a mismatch in the number of arguments when you have debugging turned off. Here I go, crawling into a cave and pulling the opening in after me... -- Algol 60 was an improvment on most | John Macdonald of its successors - C.A.R. Hoare | jmm@eci386
henley@motcid.UUCP (Aaron Henley) (05/09/90)
kla@physc1.byu.edu writes: >static int __bug__ = 1; >#define bug(); __bug__ = 1; >#define bugoff(); __bug__ = 0; >#ifdef DEBUG >#define Debug(cmdstr) if(__bug__) { printf cmdstr ; fflush(stdout); } >#else >#define Debug(cmdstr) >#endif >Also, if you get into the source level debugger, and you find that >there may be a problem in another module which was unexpected, you >can turn on its debugging by toggling its __bug__ variable and watching >the output for a while. Looks pretty good, but I would change it a little to like this: #ifdef DEBUG static int __bug__ = 1; #define bug(); __bug__ = 1; #define bugoff(); __bug__ = 0; #define Debug(cmdstr) if(__bug__) { printf cmdstr ; fflush(stdout); } #else #define Debug(cmdstr) #define bug(); #define bugoff(); #endif This way if DEBUG is set off you have no impact at all from the debug statements. Also put this code in a special header file "debug.h" so you can insure that the variables needed are defined properly. Besides your macros Debug, bug, and bugoff hide the functionality of the DEBUG statements so why not hide them all together. -- ___________________________________________________________________ / Aaron Henley, Motorola Inc. DISCLAIMER: std.disclaimer / / Cellular Infrastructure Division UUCP: ...!uunet!motcid!henley / /__________________________________________________________________/
steve@groucho.ucar.edu (Steve Emmerson) (05/10/90)
jmm@eci386.uucp (John Macdonald) writes: >Try the following instead: > #ifdef DEBUG_PRINT_ON > # define DEBUG printf > #else > # define DEBUG(ignore) > #endif >To insert a DEBUG-conditional printf use: > DEBUG( "format", args, ... ); >(no double parens or other funny syntax required, it just looks like >a function call) Be aware that some C compilers will have problems with the above due to an "argument mismatch" between the usage of the macro and its definition. Steve Emmerson steve@unidata.ucar.edu ...!ncar!unidata!steve
guy@auspex.auspex.com (Guy Harris) (05/10/90)
>Isn't the use of __LINE__ non-portable?
The use of __LINE__ is portable to all ANSI C implementations, and to
many non-ANSI C implementations (including most, if not all, UNIX ones).