home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / cplus / 15924 < prev    next >
Encoding:
Text File  |  1992-11-08  |  13.1 KB  |  404 lines

  1. Path: sparky!uunet!cimshop!davidm
  2. From: davidm@consilium.com (David S. Masterson)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Debugging output
  5. Message-ID: <DAVIDM.92Nov7163528@consilium.com>
  6. Date: 8 Nov 92 00:35:28 GMT
  7. References: <Bx93Mr.42r@cs.uiuc.edu> <5174@holden.lulea.trab.se>
  8. Sender: root@cimshop.UUCP
  9. Distribution: comp
  10. Organization: Consilium Inc., Mountain View, California
  11. Lines: 389
  12. In-reply-to: jbn@lulea.trab.se's message of 6 Nov 92 18:05:07 GMT
  13. X-Posting-Software: GNUS 3.13  [ NNTP-based News Reader for GNU Emacs ]
  14.  
  15. >>>>> On 6 Nov 92 18:05:07 GMT, jbn@lulea.trab.se (Johan Bengtsson) said:
  16.  
  17. > I much prefer saying
  18.  
  19. > DEBUG( cerr << "here\n" );
  20.  
  21. > Much easier to see what is going on (IMHO), and useful for other things
  22. > than printouts.
  23.  
  24. > #ifndef NDEBUG
  25. > #  define DEBUG(expr) if ( debug ) (expr)
  26. > #else
  27. > #  define DEBUG(expr) (0)
  28. > #endif
  29.  
  30. > Note that DEBUG code is generated per default.  Reversing that is trivial.
  31.  
  32. A very simple approach to debugging, but a very useful one.  In that vein, I
  33. got the idea for the below Tracer object from the ARM (chapter 3, I think) a
  34. few years ago.  Since you wanted to know about debugging and I saw this idea
  35. recently discussed by Andrew Koenig in JOOP, I thought I'd post this version
  36. of the Tracer object.  The capabilities of this object are:
  37.  
  38. 1. Print out function entry/exit of interesting functions.
  39. 2. Print out of interesting information.
  40. 3. Attach #2 messages to a bit flag.
  41. 4. Print out messages of specific bit flag(s).
  42. 5. Print out messages within context of a function.
  43. 6. Turn on and off tracing temporarily.
  44. 7. Compile out tracing code altogether.
  45.  
  46. I've added a number of things since this version of the code:
  47.  
  48. 1. Messages can be output to other than cout.
  49. 2. Environment variables can override initial tracing state.
  50.    (tried reading environment variable often so tracing could be changed,
  51.     but the getenv() cost was too great  ;-)
  52.  
  53. Anyway, here's the code.  Enjoy!
  54.  
  55. #!/bin/sh
  56. # This is a shell archive (produced by shar 3.49)
  57. # To extract the files from this archive, save it to a file, remove
  58. # everything above the "!/bin/sh" line above, and type "sh file_name".
  59. #
  60. # made 11/08/1992 00:17 UTC by davidm@prometheus
  61. # Source directory /slab/davidm/tmp
  62. #
  63. # existing files will NOT be overwritten unless -c is specified
  64. #
  65. # This shar contains:
  66. # length  mode       name
  67. # ------ ---------- ------------------------------------------
  68. #   5066 -rw-r--r-- tracer.cxx
  69. #   4466 -rw-r--r-- tracer.hxx
  70. #
  71. # ============= tracer.cxx ==============
  72. if test -f 'tracer.cxx' -a X"$1" != X"-c"; then
  73.     echo 'x - skipping tracer.cxx (File already exists)'
  74. else
  75. echo 'x - extracting tracer.cxx (Text)'
  76. sed 's/^X//' << 'SHAR_EOF' > 'tracer.cxx' &&
  77. /*
  78. ** File - tracer.cxx
  79. */
  80. X
  81. #ifndef TRACER_HXX
  82. #include "tracer.hxx"
  83. #endif
  84. X
  85. #include <iostream.h>
  86. #include <string.h>
  87. X
  88. X
  89. // ****************************************************************:
  90. //      Tracer
  91. //
  92. // Description:
  93. //      Initialize local as well as static information.  Set up
  94. //      for total cleanup at destruction.  Also outputs Tracer
  95. //      to stream using operator<<.  Implicit assumption is that
  96. //      this is only called once per run of a program.
  97. // ****************************************************************:
  98. Tracer::Tracer(char* s, const int n)
  99. {
  100. X        prog = func = s;        // Set program name
  101. X        mode = n;               // Initialize the tracing mode (no default).
  102. X        lmode = 1;              // Recognize this as top-level.
  103. X
  104. X        if (mode)               // Should we output?
  105. X                cout << *this << ": entered" << endl;
  106. }
  107. X
  108. X
  109. // ****************************************************************:
  110. //      Tracer
  111. //
  112. // Description:
  113. //      Initialize only local information.  No total cleanup
  114. //      at destuction.  Also outputs Tracer to stream using
  115. //      operator<<.  Also checks to see if input character
  116. //      string contains information that Tracer is watching
  117. //      for and turns tracing on if it does.  Implicit assumption
  118. //      is that this is the way Tracer will be set up when needed.
  119. // ****************************************************************:
  120. Tracer::Tracer(char* s)
  121. {
  122. X        func = s;               // Leave program alone, but set function
  123. X
  124. X        if (watch != 0)                 // Watching something?
  125. X        {
  126. X                if (strstr(func, watch) != 0)   // Watching for this?
  127. X                {                       // yes...
  128. X                        lmode = mode;   // remember global mode locally
  129. X                        mode = -1;      // turn tracing on
  130. X                }
  131. X        }
  132. X        else                            // no...
  133. X                lmode = 0;              // set local mode to not top level
  134. X
  135. X        if (mode)                       // Should we output?
  136. X                cout << *this << ": entered" << endl;
  137. }
  138. X
  139. X
  140. // ****************************************************************:
  141. //      ~Tracer
  142. //
  143. // Description:
  144. //      Check for totalcleanup flag and cleanup.
  145. //      Also outputs Tracer to stream using operator<<.
  146. // ****************************************************************:
  147. Tracer::~Tracer()
  148. {
  149. X        if (mode)                       // Should we output?
  150. X                cout << *this << ": exitted" << endl;
  151. X
  152. X        if (watch != 0)                 // Watching something?
  153. X        {
  154. X                if (strstr(func, watch) != 0)   // Watching for the function?
  155. X                {                       // yes...
  156. X                        mode = lmode;   // reset remembered global mode
  157. X                        lmode = 0;      // this is not the top level
  158. X                }
  159. X        }
  160. X
  161. X        if (lmode)                      // Is this top level?
  162. X                TotalCleanup();
  163. }
  164. X
  165. X
  166. // ****************************************************************:
  167. //              TotalCleanup
  168. //
  169. // Description:
  170. //      Do what's needed to finally cleanup Tracer.
  171. //      For instance, might be a close of a log file.
  172. // ****************************************************************:
  173. void
  174. Tracer::TotalCleanup()
  175. {
  176. X        if (watch)
  177. X                delete watch;
  178. }
  179. X
  180. X
  181. // ****************************************************************:
  182. //              SetMode
  183. //
  184. // Description:
  185. //      Change the global mode of Tracer.
  186. // ****************************************************************:
  187. void
  188. Tracer::SetMode(const int n)
  189. {
  190. X        mode = n;               // new mode
  191. }
  192. X
  193. X
  194. // ****************************************************************:
  195. //              GetMode
  196. //
  197. // Description:
  198. //      Determine the current global mode of Tracer.
  199. // ****************************************************************:
  200. int
  201. Tracer::GetMode()
  202. {
  203. X        return mode;            // what is the mode?
  204. }
  205. X
  206. X
  207. // ****************************************************************:
  208. //              SetWatch
  209. //
  210. // Description:
  211. //      Set a function name to watch trace on.
  212. // ****************************************************************:
  213. void
  214. Tracer::SetWatch(char* name)
  215. {
  216. X        if (watch)
  217. X                delete watch;
  218. X
  219. X        watch = new char[strlen(name)];
  220. X        strcpy(watch, name);
  221. }
  222. X
  223. X
  224. // ****************************************************************:
  225. //              GetWatch
  226. //
  227. // Description:
  228. //      Return the current function being watched for.
  229. // ****************************************************************:
  230. char*
  231. Tracer::GetWatch()
  232. {
  233. X        return watch;           // what we're watching for
  234. }
  235. X
  236. X
  237. // ****************************************************************:
  238. //              Operator<<
  239. //
  240. // Description:
  241. //      Puts Tracer into an output stream.
  242. // ****************************************************************:
  243. ostream&
  244. operator<<(ostream& str, Tracer& x)
  245. {
  246. X        return str << x.func;   // output the Tracer object to stream
  247. }
  248. SHAR_EOF
  249. chmod 0644 tracer.cxx ||
  250. echo 'restore of tracer.cxx failed'
  251. Wc_c="`wc -c < 'tracer.cxx'`"
  252. test 5066 -eq "$Wc_c" ||
  253.     echo 'tracer.cxx: original size 5066, current size' "$Wc_c"
  254. fi
  255. # ============= tracer.hxx ==============
  256. if test -f 'tracer.hxx' -a X"$1" != X"-c"; then
  257.     echo 'x - skipping tracer.hxx (File already exists)'
  258. else
  259. echo 'x - extracting tracer.hxx (Text)'
  260. sed 's/^X//' << 'SHAR_EOF' > 'tracer.hxx' &&
  261. /*
  262. ** Tracer object
  263. **
  264. ** Purpose:
  265. **      Mostly for tracing function calls, but may be adapted for
  266. **      logging a trace of a program to somewhere else.
  267. */
  268. X
  269. #ifndef TRACER_HXX
  270. #define TRACER_HXX
  271. X
  272. // .NAME Tracer - class to manage providing a trace of functions.
  273. // .LIBRARY util
  274. // .HEADER Utility Classes
  275. // .INCLUDE tracer.hxx
  276. // .FILE tracer.hxx
  277. // .FILE tracer.cxx
  278. X
  279. // .SECTION Description
  280. // This class makes use of some of the semantics of C++ to provide
  281. // a convenient way of tracing function calls.  This code was initially
  282. // suggested by Bjarne Stroustrup, but has now been modified to allow
  283. // control of when tracing takes place.  Tracing messages are sprinkled
  284. // about the user's code and, at the user's choosing, the type of
  285. // tracing is enabled.  Users of this object class will rarely (if
  286. // ever) directly see the class.  Instead, they will use the macro
  287. // interface defined with this class.
  288. X
  289. // .SECTION Tracing Types
  290. // Tracer may be set to output its tracing information according to the
  291. // type of mode it has been put into.  At the simplest level, Tracer may
  292. // be set to output all tracing information by setting its type to -1
  293. // (which is what TRACE_ON does).  At the next level, messages that
  294. // Tracer is told about may be given a positive integer type < 32.
  295. // Tracer may also be set to output only messages that are of certain
  296. // types (via bitwise AND of current type with message type).  Users
  297. // can, therefore, monitor all types of messages, some of the types,
  298. // or just one of the types depending on the user's interest.  The final
  299. // level is that a user may turn on monitoring of a function call by
  300. // telling Tracer the name of the function to WATCH.  When Tracer hits
  301. // the function in question, it turns TRACE_ON and turns TRACE_OFF when
  302. // it leaves the function (so, all lower functions are also traced).
  303. X
  304. #include <iostream.h>
  305. X
  306. X
  307. class Tracer
  308. {
  309. public:
  310. X        Tracer(char*, const int);       // Full tracer invocation
  311. X        Tracer(char*);                  // Lower level invocation
  312. X
  313. X        ~Tracer();                      // Close tracer invocation
  314. X
  315. X        void    TotalCleanup();         // Clean up when fully done
  316. X
  317. X        void    SetMode(const int);     // Set current mode of tracing
  318. X        int     GetMode();              // Determine current tracing mode
  319. X
  320. X        void    SetWatch(char*);        // Function name to begin tracing in
  321. X        char*   GetWatch();             // What we are watching for?
  322. X
  323. X        friend ostream& operator<<(ostream&, Tracer&);
  324. X                                        // Output tracing information
  325. X
  326. private:
  327. X        char*           func;           // function being worked on
  328. X        int             lmode;          // local mode of Tracer
  329. X        static char*    prog;           // program being worked on
  330. X        static int      mode;           // global mode of Tracer
  331. X        static char*    watch;          // function to watch for and trace
  332. X
  333. };
  334. X
  335. X
  336. // ****************************************************************
  337. //              Macro Interface to Tracer Object
  338. // ****************************************************************
  339. #ifndef NDEBUG
  340. X
  341. #define FTRACER(s,n)    /* Trace program s with type n */\
  342. X        Tracer  _trace(s, n);
  343. X
  344. #define TRACER(s)       /* Trace function s */\
  345. X        Tracer  _trace(s);
  346. X
  347. #define TRACE(s)        /* If TRACE_ON then output s */\
  348. X        if (_trace.GetMode()) cout << _trace << ": " << s << endl;
  349. X
  350. #define TRACEF(f)       /* If TRACE_ON then call function f */\
  351. X        if (_trace.GetMode()) f;
  352. X
  353. #define TRACE_ON        /* Turn tracing on */\
  354. X        _trace.SetMode(-1);
  355. X
  356. #define TRACE_OFF       /* Turn tracing off */\
  357. X        _trace.SetMode(0);
  358. X
  359. #define LTRACE(l,s)     /* If (TRACE_ON || type & l) then output s */\
  360. X        if (_trace.GetMode() < 0 || _trace.GetMode() & l) \
  361. X                cout << _trace << ": " << s << endl;
  362. X
  363. #define LTRACEF(l,f)    /* If (TRACE_ON || type & l) then call function f */\
  364. X        if (_trace.GetMode() < 0 || _trace.GetMode() & l) f;
  365. X
  366. #define STRACE(m)       /* Set tracing to type m */\
  367. X        _trace.SetMode(m);
  368. X
  369. #define WATCH(s)        /* Set function to watch to s */\
  370. X        _trace.SetWatch(s);
  371. X
  372. #else
  373. X
  374. #define FTRACER(s,n)    /**/
  375. #define TRACER(s)       /**/
  376. #define TRACE(s)        /**/
  377. #define TRACE_ON        /**/
  378. #define TRACE_OFF       /**/
  379. #define LTRACE(l,s)     /**/
  380. #define LTRACEF(l,s)    /**/
  381. #define STRACE(m)       /**/
  382. #define WATCH(s)        /**/
  383. X
  384. #endif
  385. X
  386. #endif
  387. SHAR_EOF
  388. chmod 0644 tracer.hxx ||
  389. echo 'restore of tracer.hxx failed'
  390. Wc_c="`wc -c < 'tracer.hxx'`"
  391. test 4466 -eq "$Wc_c" ||
  392.     echo 'tracer.hxx: original size 4466, current size' "$Wc_c"
  393. fi
  394. exit 0
  395. --
  396. ====================================================================
  397. David Masterson                    Consilium, Inc.
  398. (415) 691-6311                    640 Clyde Ct.
  399. davidm@consilium.com                Mtn. View, CA  94043
  400. ====================================================================
  401. People were out there looting their asses off... When they saw us,
  402. they shouted, `Viva Bush!'
  403.                 -- A US soldier present at the invasion of Panama.
  404.