1.\"           @(#)user.r      1.13 10/29/86
2.\"
3.\" 2004-10-29: documented features implemented since 10/29/86
4.\"             formatting cleanup
5.\"                                               - Sergei Golubchik
6.\"
7.\"           DBUG (Macro Debugger Package) nroff source
8.\"
9.\"           nroff -mm user.r >user.t
10.\"           groff -mm user.r >user.ps
11.\"
12.\" ===================================================
13.\"
14.\"           === Some sort of black magic, but I forget...
15.tr ~
16.\"           === Hyphenation control (1 = on)
17.\".nr Hy 1
18.\"           === Force all first level headings to start on new page
19.nr Ej 1
20.\"           === Set for breaks after headings for levels 1-3
21.nr Hb 3
22.\"           === Set for space after headings for levels 1-3
23.nr Hs 3
24.\"           === Set standard indent for one/half inch
25.nr Si 10
26.\"           === Set page header
27.PH "/DBUG User Manual//\*(DT/"
28.\"           === Set page footer
29.PF "// - % - //"
30.\"           === Set page offset
31.\".po 0.60i
32.\"           === Set line length
33.\".ll 6.5i
34.TL
35.warn 0
36D B U G
37.P 0
38C Program Debugging Package
39.P 0
40by
41.AU "Fred Fish"
42.AF ""
43.SA 1
44.\"           === All paragraphs indented.
45.nr Pt 1
46.AS 1
47This document introduces
48.I dbug ,
49a macro based C debugging
50package which has proven to be a very flexible and useful tool
51for debugging, testing, and porting C programs.
52
53.P
54All of the features of the
55.I dbug
56package can be enabled or disabled dynamically at execution time.
57This means that production programs will run normally when
58debugging is not enabled, and eliminates the need to maintain two
59separate versions of a program.
60
61.P
62Many of the things easily accomplished with conventional debugging
63tools, such as symbolic debuggers, are difficult or impossible with this
64package, and vice versa.
65Thus the
66.I dbug
67package should
68.I not
69be thought of as a replacement or substitute for
70other debugging tools, but simply as a useful
71.I addition
72to the
73program development and maintenance environment.
74
75.AE
76.MT 4
77.SK
78.B
79INTRODUCTION
80.R
81
82.P
83Almost every program development environment worthy of the name
84provides some sort of debugging facility.
85Usually this takes the form of a program which is capable of
86controlling execution of other programs and examining the internal
87state of other executing programs.
88These types of programs will be referred to as external debuggers
89since the debugger is not part of the executing program.
90Examples of this type of debugger include the
91.B adb
92and
93.B sdb
94debuggers provided with the
95.B UNIX\*F
96.FS
97UNIX is a trademark of AT&T Bell Laboratories.
98.FE
99operating system.
100
101.P
102One of the problems associated with developing programs in an environment
103with good external debuggers is that developed programs tend to have
104little or no internal instrumentation.
105This is usually not a problem for the developer since he is,
106or at least should be, intimately familiar with the internal organization,
107data structures, and control flow of the program being debugged.
108It is a serious problem for maintenance programmers, who
109are unlikely to have such familiarity with the program being
110maintained, modified, or ported to another environment.
111It is also a problem, even for the developer, when the program is
112moved to an environment with a primitive or unfamiliar debugger,
113or even no debugger.
114
115.P
116On the other hand,
117.I dbug
118is an example of an internal debugger.
119Because it requires internal instrumentation of a program,
120and its usage does not depend on any special capabilities of
121the execution environment, it is always available and will
122execute in any environment that the program itself will
123execute in.
124In addition, since it is a complete package with a specific
125user interface, all programs which use it will be provided
126with similar debugging capabilities.
127This is in sharp contrast to other forms of internal instrumentation
128where each developer has their own, usually less capable, form
129of internal debugger.
130In summary,
131because
132.I dbug
133is an internal debugger it provides consistency across operating
134environments,
135and because it is available to all developers it provides
136consistency across all programs in the same environment.
137
138.P
139The
140.I dbug
141package imposes only a slight speed penalty on executing
142programs, typically much less than 10 percent, and a modest size
143penalty, typically 10 to 20 percent.
144By defining a specific C preprocessor symbol both of these
145can be reduced to zero with no changes required to the
146source code.
147
148.P
149The following list is a quick summary of the capabilities
150of the
151.I dbug
152package.
153Each capability can be individually enabled or disabled
154at the time a program is invoked by specifying the appropriate
155command line arguments.
156.SP 1
157.ML o 1i
158.LI
159Execution trace showing function level control flow in a
160semi-graphically manner using indentation to indicate nesting
161depth.
162.LI
163Output the values of all, or any subset of, key internal variables.
164.LI
165Limit actions to a specific set of named functions.
166.LI
167Limit function trace to a specified nesting depth.
168.LI
169Label each output line with source file name and line number.
170.LI
171Label each output line with name of current process.
172.LI
173Push or pop internal debugging state to allow execution with
174built in debugging defaults.
175.LI
176Redirect the debug output stream to standard output (stdout)
177or a named file.
178The default output stream is standard error (stderr).
179The redirection mechanism is completely independent of
180normal command line redirection to avoid output conflicts.
181.LE
182
183.SK
184.B
185PRIMITIVE DEBUGGING TECHNIQUES
186.R
187
188.P
189Internal instrumentation is already a familiar concept
190to most programmers, since it is usually the first debugging
191technique learned.
192Typically, "print\ statements" are inserted in the source
193code at interesting points, the code is recompiled and executed,
194and the resulting output is examined in an attempt to determine
195where the problem is.
196
197The procedure is iterative, with each iteration yielding more
198and more output, and hopefully the source of the problem is
199discovered before the output becomes too large to deal with
200or previously inserted statements need to be removed.
201Figure 1 is an example of this type of primitive debugging
202technique.
203.DS I N
204.SP 2
205\fC
206.so example1.r
207\fR
208.SP 2
209.ll -5
210.ce
211Figure 1
212.ce
213Primitive Debugging Technique
214.ll +5
215.SP 2
216.DE
217
218.P
219Eventually, and usually after at least several iterations, the
220problem will be found and corrected.
221At this point, the newly inserted print statements must be
222dealt with.
223One obvious solution is to simply delete them all.
224Beginners usually do this a few times until they have to
225repeat the entire process every time a new bug pops up.
226The second most obvious solution is to somehow disable
227the output, either through the source code comment facility,
228creation of a debug variable to be switched on or off, or by using the
229C preprocessor.
230Figure 2 is an example of all three techniques.
231.DS I N
232.SP 2
233\fC
234.so example2.r
235\fR
236.SP 2
237.ll -5
238.ce
239Figure 2
240.ce
241Debug Disable Techniques
242.ll +5
243.SP 2
244.DE
245
246.P
247Each technique has its advantages and disadvantages with respect
248to dynamic vs static activation, source code overhead, recompilation
249requirements, ease of use, program readability, etc.
250Overuse of the preprocessor solution quickly leads to problems with
251source code readability and maintainability when multiple
252.B #ifdef
253symbols are to be defined or undefined based on specific types
254of debug desired.
255The source code can be made slightly more readable by suitable indentation
256of the
257.B #ifdef
258arguments to match the indentation of the code, but
259not all C preprocessors allow this.
260The only requirement for the standard
261.B UNIX
262C preprocessor is for the '#' character to appear
263in the first column, but even this seems
264like an arbitrary and unreasonable restriction.
265Figure 3 is an example of this usage.
266.DS I N
267.SP 2
268\fC
269.so example3.r
270\fR
271.SP 2
272.ll -5
273.ce
274Figure 3
275.ce
276More Readable Preprocessor Usage
277.ll +5
278.SP 2
279.DE
280
281.SK
282.B
283FUNCTION TRACE EXAMPLE
284.R
285
286.P
287We will start off learning about the capabilities of the
288.I dbug
289package by using a simple minded program which computes the
290factorial of a number.
291In order to better demonstrate the function trace mechanism, this
292program is implemented recursively.
293Figure 4 is the main function for this factorial program.
294.DS I N
295.SP 2
296\fC
297.so main.r
298\fR
299.SP 2
300.ll -5
301.ce
302Figure 4
303.ce
304Factorial Program Mainline
305.ll +5
306.SP 2
307.DE
308
309.P
310The
311.B main
312function is responsible for processing any command line
313option arguments and then computing and printing the factorial of
314each non-option argument.
315.P
316First of all, notice that all of the debugger functions are implemented
317via preprocessor macros.
318This does not detract from the readability of the code and makes disabling
319all debug compilation trivial (a single preprocessor symbol,
320.B NDEBUG ,
321forces the macro expansions to be null).
322.P
323Also notice the inclusion of the header file
324.B dbug.h
325from the local header file directory.
326(The version included here is the test version in the dbug source
327distribution directory).
328This file contains all the definitions for the debugger macros, which
329all have the form
330.B DBUG_XX...XX .
331
332.P
333The
334.B DBUG_ENTER
335macro informs that debugger that we have entered the
336function named
337.B main .
338It must be the very first "executable" line in a function, after
339all declarations and before any other executable line.
340The
341.B DBUG_PROCESS
342macro is generally used only once per program to
343inform the debugger what name the program was invoked with.
344The
345.B DBUG_PUSH
346macro modifies the current debugger state by
347saving the previous state and setting a new state based on the
348control string passed as its argument.
349The
350.B DBUG_PRINT
351macro is used to print the values of each argument
352for which a factorial is to be computed.
353The
354.B DBUG_RETURN
355macro tells the debugger that the end of the current
356function has been reached and returns a value to the calling
357function.
358All of these macros will be fully explained in subsequent sections.
359.P
360To use the debugger, the factorial program is invoked with a command
361line of the form:
362.DS CB N
363\fCfactorial -#d:t 1 2 3
364.DE
365The
366.B main
367function recognizes the "-#d:t" string as a debugger control
368string, and passes the debugger arguments ("d:t") to the
369.I dbug
370runtime support routines via the
371.B DBUG_PUSH
372macro.
373This particular string enables output from the
374.B DBUG_PRINT
375macro with the 'd' flag and enables function tracing with the 't' flag.
376The factorial function is then called three times, with the arguments
377"1", "2", and "3".
378Note that the DBUG_PRINT takes exactly
379.B two
380arguments, with the second argument (a format string and list
381of printable values) enclosed in parentheses.
382.P
383Debug control strings consist of a header, the "-#", followed
384by a colon separated list of debugger arguments.
385Each debugger argument is a single character flag followed
386by an optional comma separated list of arguments specific
387to the given flag.
388Some examples are:
389.DS CB N
390\fC
391-#d:t:o
392-#d,in,out:f,main:F:L
393.DE
394Note that previously enabled debugger actions can be disabled by the
395control string "-#".
396
397.P
398The definition of the factorial function, symbolized as "N!", is
399given by:
400.DS CB N
401N! = N * N-1 * ... 2 * 1
402.DE
403Figure 5 is the factorial function which implements this algorithm
404recursively.
405Note that this is not necessarily the best way to do factorials
406and error conditions are ignored completely.
407.DS I N
408.SP 2
409\fC
410.so factorial.r
411\fR
412.SP 2
413.ll -5
414.ce
415Figure 5
416.ce
417Factorial Function
418.ll +5
419.SP 2
420.DE
421
422.P
423One advantage (some may not consider it so) to using the
424.I dbug
425package is that it strongly encourages fully structured coding
426with only one entry and one exit point in each function.
427Multiple exit points, such as early returns to escape a loop,
428may be used, but each such point requires the use of an
429appropriate
430.B DBUG_RETURN
431or
432.B DBUG_VOID_RETURN
433macro.
434
435.P
436To build the factorial program on a
437.B UNIX
438system, compile and
439link with the command:
440.DS CB N
441\fCcc -o factorial main.c factorial.c -ldbug
442.DE
443The "-ldbug" argument tells the loader to link in the
444runtime support modules for the
445.I dbug
446package.
447Executing the factorial program with a command of the form:
448.DS CB N
449\fCfactorial 1 2 3 4 5
450.DE
451generates the output shown in figure 6.
452.DS I N
453.SP 2
454\fC
455.so output1.r
456\fR
457.SP 2
458.ll -5
459.ce
460Figure 6
461.ce
462\fCfactorial 1 2 3 4 5
463.ll +5
464.SP 2
465.DE
466
467.P
468Function level tracing is enabled by passing the debugger
469the 't' flag in the debug control string.
470Figure 7 is the output resulting from the command
471"factorial\ -#t:o\ 2\ 3".
472.DS I N
473.SP 2
474\fC
475.so output2.r
476\fR
477.SP 2
478.ll -5
479.ce
480Figure 7
481.ce
482\fCfactorial -#t:o 2 3
483.ll +5
484.SP 2
485.DE
486
487.P
488Each entry to or return from a function is indicated by '>' for the
489entry point and '<' for the exit point, connected by
490vertical bars to allow matching points to be easily found
491when separated by large distances.
492
493.P
494This trace output indicates that there was an initial call
495to factorial from main (to compute 2!), followed by
496a single recursive call to factorial to compute 1!.
497The main program then output the result for 2! and called the
498factorial function again with the second argument, 3.
499Factorial called itself recursively to compute 2! and 1!, then
500returned control to main, which output the value for 3! and exited.
501
502.P
503Note that there is no matching entry point "main>" for the
504return point "<main" because at the time the
505.B DBUG_ENTER
506macro was reached in main, tracing was not enabled yet.
507It was only after the macro
508.B DBUG_PUSH
509was executing that tracing became enabled.
510This implies that the argument list should be processed as early as
511possible since all code preceding the first call to
512.B DBUG_PUSH
513is
514essentially invisible to
515.I dbug
516(this can be worked around by
517inserting a temporary
518.B DBUG_PUSH(argv[1])
519immediately after the
520.B DBUG_ENTER("main")
521macro.
522
523.P
524One last note,
525the trace output normally comes out on the standard error.
526Since the factorial program prints its result on the standard
527output, there is the possibility of the output on the terminal
528being scrambled if the two streams are not synchronized.
529Thus the debugger is told to write its output on the standard
530output instead, via the 'o' flag character.
531Note that no 'o' implies the default (standard error), a 'o'
532with no arguments means standard output, and a 'o'
533with an argument means used the named file.
534i.e, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
535output in "logfile".
536Because of
537.B UNIX
538implementation details, programs usually run
539faster when writing to stdout rather than stderr, though this
540is not a prime consideration in this example.
541
542.SK
543.B
544USE OF DBUG_PRINT MACRO
545.R
546
547.P
548The mechanism used to produce "printf" style output is the
549.B DBUG_PRINT
550macro.
551
552.P
553To allow selection of output from specific macros, the first argument
554to every
555.B DBUG_PRINT
556macro is a
557.I dbug
558keyword.
559When this keyword appears in the argument list of the 'd' flag in
560a debug control string, as in "-#d,keyword1,keyword2,...:t",
561output from the corresponding macro is enabled.
562The default when there is no 'd' flag in the control string is to
563enable output from all
564.B DBUG_PRINT
565macros.
566
567.P
568Typically, a program will be run once, with no keywords specified,
569to determine what keywords are significant for the current problem
570(the keywords are printed in the macro output line).
571Then the program will be run again, with the desired keywords,
572to examine only specific areas of interest.
573
574.P
575The second argument to a
576.B DBUG_PRINT
577macro is a standard printf style
578format string and one or more arguments to print, all
579enclosed in parentheses so that they collectively become a single macro
580argument.
581This is how variable numbers of printf arguments are supported.
582Also note that no explicit newline is required at the end of the format string.
583As a matter of style, two or three small
584.B DBUG_PRINT
585macros are preferable
586to a single macro with a huge format string.
587Figure 8 shows the output for default tracing and debug.
588.DS I N
589.SP 2
590\fC
591.so output3.r
592\fR
593.SP 2
594.ll -5
595.ce
596Figure 8
597.ce
598\fCfactorial -#d:t:o 3
599.ll +5
600.SP 2
601.DE
602
603.P
604The output from the
605.B DBUG_PRINT
606macro is indented to match the trace output
607for the function in which the macro occurs.
608When debugging is enabled, but not trace, the output starts at the left
609margin, without indentation.
610
611.P
612To demonstrate selection of specific macros for output, figure
6139 shows the result when the factorial program is invoked with
614the debug control string "-#d,result:o".
615.DS I N
616.SP 2
617\fC
618.so output4.r
619\fR
620.SP 2
621.ll -5
622.ce
623Figure 9
624.ce
625\fCfactorial -#d,result:o 4
626.ll +5
627.SP 2
628.DE
629
630.P
631It is sometimes desirable to restrict debugging and trace actions
632to a specific function or list of functions.
633This is accomplished with the 'f' flag character in the debug
634control string.
635Figure 10 is the output of the factorial program when run with the
636control string "-#d:f,factorial:F:L:o".
637The 'F' flag enables printing of the source file name and the 'L'
638flag enables printing of the source file line number.
639.DS I N
640.SP 2
641\fC
642.so output5.r
643\fR
644.SP 2
645.ll -5
646.ce
647Figure 10
648.ce
649\fCfactorial -#d:f,factorial:F:L:o 3
650.ll +5
651.SP 2
652.DE
653
654.P
655The output in figure 10 shows that the "find" macro is in file
656"factorial.c" at source line 8 and the "result" macro is in the same
657file at source line 12.
658
659.SK
660.B
661SUMMARY OF MACROS
662.R
663
664.P
665This section summarizes the usage of all currently defined macros
666in the
667.I dbug
668package.
669The macros definitions are found in the user include file
670.B dbug.h
671from the standard include directory.
672
673.SP 2
674.BL 20
675.LI DBUG_ENTER\
676Used to tell the runtime support module the name of the function being
677entered.  The argument must be of type "pointer to character".  The
678DBUG_ENTER macro must precede all executable lines in the function
679just entered, and must come after all local declarations.  Each
680DBUG_ENTER macro must have a matching DBUG_RETURN or DBUG_VOID_RETURN
681macro at the function exit points.  DBUG_ENTER macros used without a
682matching DBUG_RETURN or DBUG_VOID_RETURN macro will cause warning
683messages from the
684.I dbug
685package runtime support module.
686.SP 1
687EX:\ \fCDBUG_ENTER\ ("main");\fR
688.SP 1
689.LI DBUG_RETURN\
690Used at each exit point of a function containing a DBUG_ENTER macro at
691the entry point.  The argument is the value to return.  Functions
692which return no value (void) should use the DBUG_VOID_RETURN macro.
693It is an error to have a DBUG_RETURN or DBUG_VOID_RETURN macro in a
694function which has no matching DBUG_ENTER macro, and the compiler will
695complain if the macros are actually used (expanded).
696.SP 1
697EX:\ \fCDBUG_RETURN\ (value);\fR
698.br
699EX:\ \fCDBUG_VOID_RETURN;\fR
700.SP 1
701.LI DBUG_PROCESS\
702Used to name the current process being executed.
703A typical argument for this macro is "argv[0]", though
704it will be perfectly happy with any other string.
705Im multi-threaded environment threads may have different names.
706.SP 1
707EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR
708.SP 1
709.LI DBUG_PUSH\
710Sets a new debugger state by pushing the current
711.I dbug
712state onto an internal stack and setting up the new state using the
713debug control string passed as the macro argument.  The most common
714usage is to set the state specified by a debug control string
715retrieved from the argument list. If the control string is
716.I incremental,
717the new state is a copy of the old state, modified by the control
718string.
719.SP 1
720EX:\ \fCDBUG_PUSH\ (\&(argv[i][2]));\fR
721.br
722EX:\ \fCDBUG_PUSH\ ("d:t");\fR
723.br
724EX:\ \fCDBUG_PUSH\ ("");\fR
725.SP 1
726.LI DBUG_POP\
727Restores the previous debugger state by popping the state stack.
728Attempting to pop more states than pushed will be ignored and no
729warning will be given.  The DBUG_POP macro has no arguments.
730.SP 1
731EX:\ \fCDBUG_POP\ ();\fR
732.SP 1
733.LI DBUG_SET\
734Modifies the current debugger state on top of the stack or pushes
735a new state if the current is set to the initial settings, using
736the debug control string passed as the macro argument.  Unless
737.I incremental
738control string is used (see below), it's equivalent to a combination of
739DBUG_POP and DBUG_PUSH.
740.SP 1
741EX:\ \fCDBUG_SET\ ("d:t");\fR
742.br
743EX:\ \fCDBUG_SET\ ("+d,info");\fR
744.br
745EX:\ \fCDBUG_SET\ ("+t:-d");\fR
746.SP 1
747.LI DBUG_FILE\
748The DBUG_FILE macro is used to do explicit I/O on the debug output
749stream.  It is used in the same manner as the symbols "stdout" and
750"stderr" in the standard I/O package.
751.SP 1
752EX:\ \fCfprintf\ (DBUG_FILE,\ "Doing\ my\ own\ I/O!\\n");\fR
753.SP 1
754.LI DBUG_EXECUTE\
755The DBUG_EXECUTE macro is used to execute any arbitrary C code.  The
756first argument is the debug keyword, used to trigger execution of the
757code specified as the second argument.  This macro must be used
758cautiously because, like the DBUG_PRINT macro, it is automatically
759selected by default whenever the 'd' flag has no argument list (i.e.,
760a "-#d:t" control string).
761.SP 1
762EX:\ \fCDBUG_EXECUTE\ ("status",\ print_status\ ());\fR
763.SP 1
764.LI DBUG_EXECUTE_IF\
765Works like DBUG_EXECUTE macro, but the code is
766.B not
767executed "by default", if the keyword is not explicitly listed in
768the 'd' flag. Used to conditionally execute "dangerous" actions, e.g
769to crash the program testing how recovery works, or to introduce an
770artificial delay checking for race conditions.
771.SP 1
772EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ DBUG_ABORT()\ ());\fR
773.SP 1
774.LI DBUG_EVALUATE\
775The DBUG_EVALUATE macro is similar to DBUG_EXECUTE, but it can be used in
776the expression context. The first argument is the debug keyword that is used to
777choose whether the second (keyword is enabled) or the third (keyword is not
778enabled) argument is evaluated. When
779.I dbug
780is compiled off, the third argument is evaluated.
781.SP 1
782EX:\fC
783.br
784  printf("Info-debug is %s",
785.br
786         DBUG_EVALUATE\ ("info", "ON", "OFF"));\fR
787.SP 1
788.LI DBUG_EVALUATE_IF\
789Works like DBUG_EVALUATE macro, but the second argument is
790.B not
791evaluated, if the keyword is not explicitly listed in
792the 'd' flag. Like DBUG_EXECUTE_IF this could be used to conditionally execute
793"dangerous" actions.
794.SP 1
795EX:\fC
796.br
797    if (prepare_transaction () ||
798.br
799        DBUG_EVALUATE ("crashme", (DBUG_ABORT(), 0), 0) ||
800.br
801        commit_transaction () )\fR
802.SP 1
803.LI DBUG_PRINT\
804Used to do printing via the "fprintf" library function on the current
805debug stream, DBUG_FILE.  The first argument is a debug keyword, the
806second is a format string and the corresponding argument list.  Note
807that the format string and argument list are all one macro argument
808and
809.B must
810be enclosed in parentheses.
811.SP 1
812EX:\ \fCDBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));\fR
813.br
814EX:\ \fCDBUG_PRINT\ ("type",\ ("type\ is\ %x", type));\fR
815.br
816EX:\ \fCDBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));\fR
817.SP 1
818.LI DBUG_DUMP\
819Used to dump a memory block in hex via the "fprintf" library function
820on the current debug stream, DBUG_FILE.  The first argument is a debug
821keyword, the second is a pointer to a memory to dump, the third is a
822number of bytes to dump.
823.SP 1
824EX: \fCDBUG_DBUG\ ("net",\ packet,\ len);\fR
825.SP 1
826.LI DBUG_SETJMP\
827Used in place of the setjmp() function to first save the current
828debugger state and then execute the standard setjmp call.
829This allows to the debugger to restore its state when the
830DBUG_LONGJMP macro is used to invoke the standard longjmp() call.
831Currently all instances of DBUG_SETJMP must occur within the
832same function and at the same function nesting level.
833.SP 1
834EX: \fCDBUG_SETJMP\ (env);\fR
835.SP 1
836.LI DBUG_LONGJMP\
837Used in place of the longjmp() function to first restore the
838previous debugger state at the time of the last DBUG_SETJMP
839and then execute the standard longjmp() call.
840Note that currently all DBUG_LONGJMP macros restore the state
841at the time of the last DBUG_SETJMP.
842It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP
843pairs by having the debugger runtime support module use the first
844argument to differentiate the pairs.
845.SP 1
846EX: \fCDBUG_LONGJMP\ (env,val);\fR
847.SP 1
848.LI DBUG_LOCK_FILE\
849Used in multi-threaded environment to lock DBUG_FILE stream.
850It can be used, for example, in functions that need to write something to a
851debug stream more than in one fprintf() call and want to ensure that no other
852thread will write something in between.
853.SP 1
854EX:\fC
855.br
856  DBUG_LOCK_FILE;
857.br
858  fprintf (DBUG_FILE, "a=[");
859.br
860  for (int i=0; i < a_length; i++)
861.br
862    fprintf (DBUG_FILE, "0x%03x ", a[i]);
863.br
864  fprintf (DBUG_FILE, "]");
865.br
866  DBUG_UNLOCK_FILE;\fR
867.SP 1
868.LI DBUG_UNLOCK_FILE\
869Unlocks DBUG_FILE stream, that was locked with a DBUG_LOCK_FILE.
870.LI DBUG_ABORT\
871This macro could be used instead of abort(). It flushes DBUG_FILE stream
872to ensure that no
873.I dbug
874output is lost and then calls abort().
875.SP 1
876.LI DBUG_EXPLAIN\
877Generates control string corresponding to the current debug state.
878The macro takes two arguments - a buffer to store the result string
879into and its length. The macro (which could be used as a function)
880returns 1 if the control string didn't fit into the buffer and was
881truncated and 0 otherwise.
882.SP 1
883EX:\fC
884.br
885  char buf[256];
886.br
887  DBUG_EXPLAIN( buf, sizeof(buf) );\fR
888.SP 1
889.LI DBUG_SET_INITIAL\
890.LI DBUG_EXPLAIN_INITIAL\
891.br
892These two macros are identical to DBUG_SET and DBUG_EXPLAIN, but they
893operate on the debug state that any new thread starts from.
894Modifying
895.I initial
896value does not affect threads that are already running. Obviously,
897these macros are only useful in the multi-threaded environment.
898.LE
899
900.SK
901.B
902DEBUG CONTROL STRING
903.R
904
905.P
906The debug control string is used to set the state of the debugger
907via the
908.B DBUG_PUSH
909or
910.B DBUG_SET
911macros. Control string consists of colon separated flags.  Colons
912that are part of ':\\',  ':/', or '::' are not considered flag
913separators. A flag may take an argument or a list of arguments.
914If a control string starts from a '+' sign it works
915.I incrementally,
916that is, it can modify existing state without overriding it.  Every
917flag may be preceded by a '+' or '-' to enable or disable a
918corresponding option in the debugger state or to add or remove
919arguments to the list. This section summarizes the currently available
920debugger options and the flag characters which enable or disable them.
921Argument lists enclosed in '[' and ']' are optional.
922.SP 2
923.BL 22
924.LI a[,file]
925Redirect the debugger output stream and append it to the specified
926file.  The default output stream is stderr.  A null argument list
927causes output to be redirected to stdout.
928.SP 1
929EX: \fCa,C:\\tmp\\log\fR
930.LI A[,file]
931Like 'a[,file]' but ensure that data are written after each write
932(this typically implies flush or close/reopen). It helps to get
933a complete log file in case of crashes. This mode is implicit in
934multi-threaded environment.
935.LI d[,keywords]
936Enable output from macros with specified keywords.
937Every keyword can be a
938.I glob(7)
939pattern.
940An empty list of keywords implies that all keywords are selected.
941.LI D[,time]
942Delay for specified time after each output line, to let output drain.
943Time is given in tenths of a second (value of 10 is one second).
944Default is zero.
945.LI f[,functions]
946Limit debugger actions to the specified list of functions.
947Every function can be a
948.I glob(7)
949pattern.
950An empty list of functions implies that all functions are selected.
951Every function in the list may optionally be followed by a '/' -
952this will implicitly select all the functions down the call stack.
953.SP 1
954EX: \fCf,func1,func2/:-f,func3,func4/\fR
955.SP 1
956This would enable debugger in functions 'func1()', 'func2()' and all
957functions called from it (directly or indirectly). But not in
958functions 'func3()' or 'func4()' and all functions called from
959it.
960.LI F
961Mark each debugger output line with the name of the source file
962containing the macro causing the output.
963.LI i
964Mark each debugger output line with the PID (or thread ID) of the
965current process.
966.LI g,[functions]
967Enable profiling for the specified list of functions.
968Every function can be a
969.I glob(7)
970pattern.
971An empty list of functions enables profiling for all functions.
972See
973.B PROFILING\ WITH\ DBUG
974below.
975.LI L
976Mark each debugger output line with the source file line number of
977the macro causing the output.
978.LI n
979Mark each debugger output line with the current function nesting depth.
980.LI N
981Sequentially number each debugger output line starting at 1.
982This is useful for reference purposes when debugger output is
983interspersed with program output.
984.LI o[,file]
985Like 'a[,file]' but overwrite old file, do not append.
986.LI O[,file]
987Like 'A[,file]' but overwrite old file, do not append.
988.LI p[,processes]
989Limit debugger actions to the specified processes.
990Every name can be a
991.I glob(7)
992pattern.
993An empty list
994implies all processes.  This is useful for processes which run child
995processes.  Note that each debugger output line can be marked with the
996name of the current process via the 'P' flag.  The process name must
997match the argument passed to the
998.B DBUG_PROCESS
999macro.
1000.LI P
1001Mark each debugger output line with the name of the current process.
1002Most useful when used with a process which runs child processes that
1003are also being debugged.  Note that the parent process must arrange
1004for the debugger control string to be passed to the child processes.
1005.LI r
1006Used in conjunction with the
1007.B DBUG_PUSH
1008macro to reset the current
1009indentation level back to zero.
1010Most useful with
1011.B DBUG_PUSH
1012macros used to temporarily alter the
1013debugger state.
1014.LI t[,N]
1015Enable function control flow tracing.
1016The maximum nesting depth is specified by N, and defaults to
1017200.
1018.LI T
1019Mark each debugger output line with the current timestamp.
1020The value is printed with microsecond resolution, as returned by
1021.I gettimeofday()
1022system call. The actual resolution is OS- and hardware-dependent.
1023.LE
1024
1025.SK
1026.B
1027MULTI-THREADED DEBUGGING
1028.R
1029
1030.P
1031When
1032.I dbug
1033is used in a multi-threaded environment there are few differences from a single-threaded
1034case to keep in mind. This section tries to summarize them.
1035.SP 2
1036.BL 5
1037.LI
1038Every thread has its own stack of debugger states.
1039.B DBUG_PUSH
1040and
1041.B DBUG_POP
1042affect only the thread that executed them.
1043.LI
1044At the bottom of the stack for all threads there is the common
1045.I initial
1046state. Changes to this state (for example, with
1047.B DBUG_SET_INITIAL
1048macro) affect all new threads and all running threads that didn't
1049.B DBUG_PUSH
1050yet.
1051.LI
1052Every thread can have its own name, that can be set with
1053.B DBUG_PROCESS
1054macro. Thus, "-#p,name1,name2" can be used to limit the output to specific threads.
1055.LI
1056When printing directly to
1057.B DBUG_FILE
1058it may be necessary to prevent other threads from writing something between two parts
1059of logically indivisible output. It is done with
1060.B DBUG_LOCK_FILE
1061and
1062.B DBUG_UNLOCK_FILE
1063macors. See the appropriate section for examples.
1064.LI
1065"-#o,file" and "-#O,file" are treated as "-#a,file" and "-#A,file" respectively. That is
1066all writes to a file are always followed by a flush.
1067.LI
1068"-#i" prints not a PID but a thread id in the form of "T@nnn"
1069.LE
1070
1071.SK
1072.B
1073PROFILING WITH DBUG
1074.R
1075
1076.P
1077With
1078.I dbug
1079one can do profiling in a machine independent fashion,
1080without a need for profiled version of system libraries.
1081For this,
1082.I dbug
1083can write out a file
1084called
1085.B dbugmon.out
1086(by default).  This is an ascii file containing lines of the form:
1087.DS CB N
1088\fC<function-name> E <time-entered>
1089<function-name> X <time-exited>
1090.DE
1091
1092.P
1093A second program (\fBanalyze\fR) reads this file, and produces a report on
1094standard output.
1095
1096.P
1097Profiling is enabled through the
1098.B g
1099flag.  It can take a list of
1100function names for which profiling is enabled.  By default, it
1101profiles all functions.
1102
1103.P
1104The profile file is opened for appending.  This
1105is in order that one can run a program several times, and get the
1106sum total of all the times, etc.
1107
1108.P
1109An example of the report generated follows:
1110.DS CB N
1111\fC
1112            Profile of Execution
1113            Execution times are in milliseconds
1114
1115                Calls                        Time
1116                -----                        ----
1117            Times   Percentage   Time Spent    Percentage
1118Function    Called  of total     in Function   of total    Importance
1119========    ======  ==========   ===========   ==========  ==========
1120factorial        5       83.33            30       100.00        8333
1121main             1       16.67             0         0.00           0
1122========    ======  ==========   ===========   ==========
1123Totals           6      100.00            30       100.00
1124.DE
1125.P
1126As you can see, it's quite self-evident.  The
1127.B Importance
1128column is a
1129metric obtained by multiplying the percentage of the calls and the percentage
1130of the time.  Functions with higher 'importance' benefit the most from
1131being sped up.
1132
1133.P
1134As a limitation - setjmp/longjmp, or child processes, are ignored
1135for the time being. Also, profiling does not work
1136in a multi-threaded environment.
1137
1138.P
1139Profiling code is (c) Binayak Banerjee.
1140
1141.SK
1142.B
1143HINTS AND MISCELLANEOUS
1144.R
1145
1146.P
1147One of the most useful capabilities of the
1148.I dbug
1149package is to compare the executions of a given program in two
1150different environments.
1151This is typically done by executing the program in the environment
1152where it behaves properly and saving the debugger output in a
1153reference file.
1154The program is then run with identical inputs in the environment where
1155it misbehaves and the output is again captured in a reference file.
1156The two reference files can then be differentially compared to
1157determine exactly where execution of the two processes diverges.
1158
1159.P
1160A related usage is regression testing where the execution of a current
1161version is compared against executions of previous versions.
1162This is most useful when there are only minor changes.
1163
1164.P
1165It is not difficult to modify an existing compiler to implement
1166some of the functionality of the
1167.I dbug
1168package automatically, without source code changes to the
1169program being debugged.
1170In fact, such changes were implemented in a version of the
1171Portable C Compiler by the author in less than a day.
1172However, it is strongly encouraged that all newly
1173developed code continue to use the debugger macros
1174for the portability reasons noted earlier.
1175The modified compiler should be used only for testing existing
1176programs.
1177
1178.SK
1179.B
1180CAVEATS
1181.R
1182
1183.P
1184The
1185.I dbug
1186package works best with programs which have "line\ oriented"
1187output, such as text processors, general purpose utilities, etc.
1188It can be interfaced with screen oriented programs such as
1189visual editors by redefining the appropriate macros to call
1190special functions for displaying the debugger results.
1191Of course, this caveat is not applicable if the debugger output
1192is simply dumped into a file for post-execution examination.
1193
1194.P
1195Programs which use memory allocation functions other than
1196.B malloc
1197will usually have problems using the standard
1198.I dbug
1199package.
1200The most common problem is multiply allocated memory.
1201.SP 2
1202.\" .DE nroff dident like this. davida 900108
1203.CS
1204
1205.\" vim:filetype=nroff
1206