home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff232.lzh / Dbug / user.r < prev    next >
Text File  |  1989-08-02  |  26KB  |  944 lines

  1. .\"    @(#)user.r    1.16 8/7/88
  2. .\"
  3. .\"    DBUG (Macro Debugger Package) nroff source
  4. .\"
  5. .\"    nroff -mm user.r >user.t
  6. .\"
  7. .\" ===================================================
  8. .\"
  9. .\"    === Some sort of black magic, but I forget...
  10. .tr ~
  11. .\"    === Hyphenation control (1 = on)
  12. .\".nr Hy 1
  13. .\"    === Force all first level headings to start on new page
  14. .nr Ej 1
  15. .\"    === Set for breaks after headings for levels 1-3
  16. .nr Hb 3
  17. .\"    === Set for space after headings for levels 1-3
  18. .nr Hs 3
  19. .\"    === Set standard indent for one/half inch
  20. .nr Si 10
  21. .\"    === Set page header
  22. .PH "/DBUG User Manual//\*(DT/"
  23. .\"    === Set page footer
  24. .PF "// - % - //"
  25. .\"    === Set page offset
  26. .\".po 0.60i
  27. .\"    === Set line length
  28. .\".ll 6.5i
  29. .TL
  30. D B U G
  31. .P 0
  32. C Program Debugging Package
  33. .P 0
  34. by
  35. .AU "Fred Fish"
  36. .AF ""
  37. .SA 1
  38. .\"    === All paragraphs indented.
  39. .nr Pt 1
  40. .AS 1
  41. This document introduces
  42. .I dbug ,
  43. a macro based C debugging
  44. package which has proven to be a very flexible and useful tool
  45. for debugging, testing, and porting C programs.
  46.  
  47. .P
  48. All of the features of the
  49. .I dbug
  50. package can be enabled or disabled dynamically at execution time.
  51. This means that production programs will run normally when
  52. debugging is not enabled, and eliminates the need to maintain two
  53. separate versions of a program.
  54.  
  55. .P
  56. Many of the things easily accomplished with conventional debugging
  57. tools, such as symbolic debuggers, are difficult or impossible with this
  58. package, and vice versa.
  59. Thus the
  60. .I dbug
  61. package should 
  62. .I not
  63. be thought of as a replacement or substitute for
  64. other debugging tools, but simply as a useful
  65. .I addition
  66. to the
  67. program development and maintenance environment.
  68.  
  69. .AE
  70. .MT 4
  71. .SK
  72. .B
  73. INTRODUCTION
  74. .R
  75.  
  76. .P
  77. Almost every program development environment worthy of the name
  78. provides some sort of debugging facility.
  79. Usually this takes the form of a program which is capable of
  80. controlling execution of other programs and examining the internal
  81. state of other executing programs.
  82. These types of programs will be referred to as external debuggers
  83. since the debugger is not part of the executing program.
  84. Examples of this type of debugger include the
  85. .B adb
  86. and
  87. .B sdb
  88. debuggers provided with the 
  89. .B UNIX\*F
  90. .FS
  91. UNIX is a trademark of AT&T Bell Laboratories.
  92. .FE
  93. operating system.
  94.  
  95. .P
  96. One of the problems associated with developing programs in an environment
  97. with good external debuggers is that developed programs tend to have 
  98. little or no internal instrumentation.
  99. This is usually not a problem for the developer since he is,
  100. or at least should be, intimately familiar with the internal organization,
  101. data structures, and control flow of the program being debugged.
  102. It is a serious problem for maintenance programmers, who
  103. are unlikely to have such familiarity with the program being
  104. maintained, modified, or ported to another environment.
  105. It is also a problem, even for the developer, when the program is
  106. moved to an environment with a primitive or unfamiliar debugger,
  107. or even no debugger.
  108.  
  109. .P
  110. On the other hand,
  111. .I dbug
  112. is an example of an internal debugger.
  113. Because it requires internal instrumentation of a program,
  114. and its usage does not depend on any special capabilities of
  115. the execution environment, it is always available and will
  116. execute in any environment that the program itself will
  117. execute in.
  118. In addition, since it is a complete package with a specific
  119. user interface, all programs which use it will be provided
  120. with similar debugging capabilities.
  121. This is in sharp contrast to other forms of internal instrumentation
  122. where each developer has their own, usually less capable, form
  123. of internal debugger.
  124. In summary,
  125. because 
  126. .I dbug
  127. is an internal debugger it provides consistency across operating
  128. environments, 
  129. and because it is available to all developers it provides
  130. consistency across all programs in the same environment.
  131.  
  132. .P
  133. The
  134. .I dbug
  135. package imposes only a slight speed penalty on executing
  136. programs, typically much less than 10 percent, and a modest size
  137. penalty, typically 10 to 20 percent.
  138. By defining a specific C preprocessor symbol both of these
  139. can be reduced to zero with no changes required to the
  140. source code.
  141.  
  142. .P
  143. The following list is a quick summary of the capabilities
  144. of the
  145. .I dbug
  146. package.
  147. Each capability can be individually enabled or disabled
  148. at the time a program is invoked by specifying the appropriate
  149. command line arguments.
  150. .SP 1
  151. .ML o 1i
  152. .LI
  153. Execution trace showing function level control flow in a
  154. semi-graphically manner using indentation to indicate nesting
  155. depth.
  156. .LI
  157. Output the values of all, or any subset of, key internal variables.
  158. .LI
  159. Limit actions to a specific set of named functions.
  160. .LI
  161. Limit function trace to a specified nesting depth.
  162. .LI
  163. Label each output line with source file name and line number.
  164. .LI
  165. Label each output line with name of current process.
  166. .LI
  167. Push or pop internal debugging state to allow execution with
  168. built in debugging defaults.
  169. .LI
  170. Redirect the debug output stream to standard output (stdout)
  171. or a named file.
  172. The default output stream is standard error (stderr).
  173. The redirection mechanism is completely independent of
  174. normal command line redirection to avoid output conflicts.
  175. .LE
  176.  
  177. .SK
  178. .B
  179. PRIMITIVE DEBUGGING TECHNIQUES
  180. .R
  181.  
  182. .P
  183. Internal instrumentation is already a familiar concept
  184. to most programmers, since it is usually the first debugging
  185. technique learned.
  186. Typically, "print\ statements" are inserted in the source
  187. code at interesting points, the code is recompiled and executed,
  188. and the resulting output is examined in an attempt to determine
  189. where the problem is.
  190.  
  191. The procedure is iterative, with each iteration yielding more
  192. and more output, and hopefully the source of the problem is
  193. discovered before the output becomes too large to deal with
  194. or previously inserted statements need to be removed.
  195. Figure 1 is an example of this type of primitive debugging
  196. technique.
  197. .DS I N
  198. .SP 2
  199. .so example1.r
  200. .SP 2
  201. .ll -5
  202. .ce
  203. Figure 1
  204. .ce
  205. Primitive Debugging Technique
  206. .ll +5
  207. .SP 2
  208. .DE
  209.  
  210. .P
  211. Eventually, and usually after at least several iterations, the
  212. problem will be found and corrected.
  213. At this point, the newly inserted print statements must be 
  214. dealt with.
  215. One obvious solution is to simply delete them all.
  216. Beginners usually do this a few times until they have to
  217. repeat the entire process every time a new bug pops up.
  218. The second most obvious solution is to somehow disable
  219. the output, either through the source code comment facility,
  220. creation of a debug variable to be switched on or off, or by using the
  221. C preprocessor.
  222. Figure 2 is an example of all three techniques.
  223. .DS I N
  224. .SP 2
  225. .so example2.r
  226. .SP 2
  227. .ll -5
  228. .ce
  229. Figure 2
  230. .ce
  231. Debug Disable Techniques
  232. .ll +5
  233. .SP 2
  234. .DE
  235.  
  236. .P
  237. Each technique has its advantages and disadvantages with respect
  238. to dynamic vs static activation, source code overhead, recompilation
  239. requirements, ease of use, program readability, etc.
  240. Overuse of the preprocessor solution quickly leads to problems with
  241. source code readability and maintainability when multiple 
  242. .B #ifdef
  243. symbols are to be defined or undefined based on specific types
  244. of debug desired.
  245. The source code can be made slightly more readable by suitable indentation
  246. of the 
  247. .B #ifdef
  248. arguments to match the indentation of the code, but
  249. not all C preprocessors allow this.
  250. The only requirement for the standard 
  251. .B UNIX
  252. C preprocessor is for the '#' character to appear
  253. in the first column, but even this seems
  254. like an arbitrary and unreasonable restriction.
  255. Figure 3 is an example of this usage.
  256. .DS I N
  257. .SP 2
  258. .so example3.r
  259. .SP 2
  260. .ll -5
  261. .ce
  262. Figure 3
  263. .ce
  264. More Readable Preprocessor Usage
  265. .ll +5
  266. .SP 2
  267. .DE
  268.  
  269. .SK
  270. .B
  271. FUNCTION TRACE EXAMPLE
  272. .R
  273.  
  274. .P
  275. We will start off learning about the capabilities of the
  276. .I dbug
  277. package by using a simple minded program which computes the
  278. factorial of a number.
  279. In order to better demonstrate the function trace mechanism, this
  280. program is implemented recursively.
  281. Figure 4 is the main function for this factorial program.
  282. .DS I N
  283. .SP 2
  284. .so main.r
  285. .SP 2
  286. .ll -5
  287. .ce
  288. Figure 4
  289. .ce
  290. Factorial Program Mainline
  291. .ll +5
  292. .SP 2
  293. .DE
  294.  
  295. .P
  296. The 
  297. .B main
  298. function is responsible for processing any command line
  299. option arguments and then computing and printing the factorial of
  300. each non-option argument.
  301. .P
  302. First of all, notice that all of the debugger functions are implemented
  303. via preprocessor macros.
  304. This does not detract from the readability of the code and makes disabling
  305. all debug compilation trivial (a single preprocessor symbol, 
  306. .B DBUG_OFF ,
  307. forces the macro expansions to be null).
  308. .P
  309. Also notice the inclusion of the header file
  310. .B dbug.h
  311. from the local header file directory.
  312. (The version included here is the test version in the dbug source
  313. distribution directory).
  314. This file contains all the definitions for the debugger macros, which
  315. all have the form 
  316. .B DBUG_XX...XX .
  317.  
  318. .P
  319. The 
  320. .B DBUG_ENTER 
  321. macro informs that debugger that we have entered the
  322. function named 
  323. .B main .
  324. It must be the very first "executable" line in a function, after
  325. all declarations and before any other executable line.
  326. The 
  327. .B DBUG_PROCESS
  328. macro is generally used only once per program to
  329. inform the debugger what name the program was invoked with.
  330. The
  331. .B DBUG_PUSH
  332. macro modifies the current debugger state by
  333. saving the previous state and setting a new state based on the
  334. control string passed as its argument.
  335. The
  336. .B DBUG_PRINT
  337. macro is used to print the values of each argument
  338. for which a factorial is to be computed.
  339. The 
  340. .B DBUG_RETURN
  341. macro tells the debugger that the end of the current
  342. function has been reached and returns a value to the calling
  343. function.
  344. All of these macros will be fully explained in subsequent sections.
  345. .P
  346. To use the debugger, the factorial program is invoked with a command
  347. line of the form:
  348. .DS CB N
  349. factorial -#d:t 1 2 3
  350. .DE
  351. The 
  352. .B main
  353. function recognizes the "-#d:t" string as a debugger control
  354. string, and passes the debugger arguments ("d:t") to the 
  355. .I dbug
  356. runtime support routines via the
  357. .B DBUG_PUSH 
  358. macro.
  359. This particular string enables output from the
  360. .B DBUG_PRINT
  361. macro with the 'd' flag and enables function tracing with the 't' flag.
  362. The factorial function is then called three times, with the arguments
  363. "1", "2", and "3".
  364. Note that the DBUG_PRINT takes exactly
  365. .B two
  366. arguments, with the second argument (a format string and list
  367. of printable values) enclosed in parenthesis.
  368. .P
  369. Debug control strings consist of a header, the "-#", followed
  370. by a colon separated list of debugger arguments.
  371. Each debugger argument is a single character flag followed
  372. by an optional comma separated list of arguments specific
  373. to the given flag.
  374. Some examples are:
  375. .DS CB N
  376. -#d:t:o
  377. -#d,in,out:f,main:F:L
  378. .DE
  379. Note that previously enabled debugger actions can be disabled by the
  380. control string "-#".
  381.  
  382. .P
  383. The definition of the factorial function, symbolized as "N!", is
  384. given by:
  385. .DS CB N
  386. N! = N * N-1 * ... 2 * 1
  387. .DE
  388. Figure 5 is the factorial function which implements this algorithm
  389. recursively.
  390. Note that this is not necessarily the best way to do factorials
  391. and error conditions are ignored completely.
  392. .DS I N
  393. .SP 2
  394. .so factorial.r
  395. .SP 2
  396. .ll -5
  397. .ce
  398. Figure 5
  399. .ce
  400. Factorial Function
  401. .ll +5
  402. .SP 2
  403. .DE
  404.  
  405. .P
  406. One advantage (some may not consider it so) to using the
  407. .I dbug
  408. package is that it strongly encourages fully structured coding
  409. with only one entry and one exit point in each function.
  410. Multiple exit points, such as early returns to escape a loop,
  411. may be used, but each such point requires the use of an
  412. appropriate 
  413. .B DBUG_RETURN
  414. or
  415. .B DBUG_VOID_RETURN
  416. macro.
  417.  
  418. .P
  419. To build the factorial program on a 
  420. .B UNIX
  421. system, compile and
  422. link with the command:
  423. .DS CB N
  424. cc -o factorial main.c factorial.c -ldbug
  425. .DE
  426. The "-ldbug" argument tells the loader to link in the
  427. runtime support modules for the
  428. .I dbug
  429. package.
  430. Executing the factorial program with a command of the form:
  431. .DS CB N
  432. factorial 1 2 3 4 5
  433. .DE
  434. generates the output shown in figure 6.
  435. .DS I N
  436. .SP 2
  437. .so output1.r
  438. .SP 2
  439. .ll -5
  440. .ce
  441. Figure 6
  442. .ce
  443. factorial 1 2 3 4 5
  444. .ll +5
  445. .SP 2
  446. .DE
  447.  
  448. .P
  449. Function level tracing is enabled by passing the debugger
  450. the 't' flag in the debug control string.
  451. Figure 7 is the output resulting from the command
  452. "factorial\ -#t:o\ 3\ 2".
  453. .DS I N
  454. .SP 2
  455. .so output2.r
  456. .SP 2
  457. .ll -5
  458. .ce
  459. Figure 7
  460. .ce
  461. factorial -#t:o 3 2
  462. .ll +5
  463. .SP 2
  464. .DE
  465.  
  466. .P
  467. Each entry to or return from a function is indicated by '>' for the
  468. entry point and '<' for the exit point, connected by
  469. vertical bars to allow matching points to be easily found
  470. when separated by large distances.
  471.  
  472. .P
  473. This trace output indicates that there was an initial call
  474. to factorial from main (to compute 2!), followed by
  475. a single recursive call to factorial to compute 1!.
  476. The main program then output the result for 2! and called the
  477. factorial function again with the second argument, 3.
  478. Factorial called itself recursively to compute 2! and 1!, then
  479. returned control to main, which output the value for 3! and exited.
  480.  
  481. .P
  482. Note that there is no matching entry point "main>" for the
  483. return point "<main" because at the time the 
  484. .B DBUG_ENTER
  485. macro was reached in main, tracing was not enabled yet.
  486. It was only after the macro
  487. .B DBUG_PUSH
  488. was executing that tracing became enabled.
  489. This implies that the argument list should be processed as early as
  490. possible since all code preceding the first call to
  491. .B DBUG_PUSH 
  492. is
  493. essentially invisible to 
  494. .B dbug
  495. (this can be worked around by
  496. inserting a temporary 
  497. .B DBUG_PUSH(argv[1])
  498. immediately after the
  499. .B DBUG_ENTER("main")
  500. macro.
  501.  
  502. .P
  503. One last note,
  504. the trace output normally comes out on the standard error.
  505. Since the factorial program prints its result on the standard
  506. output, there is the possibility of the output on the terminal
  507. being scrambled if the two streams are not synchronized.
  508. Thus the debugger is told to write its output on the standard
  509. output instead, via the 'o' flag character.
  510. Note that no 'o' implies the default (standard error), a 'o' 
  511. with no arguments means standard output, and a 'o' 
  512. with an argument means used the named file.
  513. I.E, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
  514. output in "logfile".
  515. Because of 
  516. .B UNIX
  517. implementation details, programs usually run
  518. faster when writing to stdout rather than stderr, though this
  519. is not a prime consideration in this example.
  520.  
  521. .SK
  522. .B
  523. USE OF DBUG_PRINT MACRO
  524. .R
  525.  
  526. .P
  527. The mechanism used to produce "printf" style output is the
  528. .B DBUG_PRINT
  529. macro.
  530.  
  531. .P
  532. To allow selection of output from specific macros, the first argument
  533. to every 
  534. .B DBUG_PRINT
  535. macro is a 
  536. .I dbug
  537. keyword.
  538. When this keyword appears in the argument list of the 'd' flag in
  539. a debug control string, as in "-#d,keyword1,keyword2,...:t",
  540. output from the corresponding macro is enabled.
  541. The default when there is no 'd' flag in the control string is to
  542. enable output from all 
  543. .B DBUG_PRINT
  544. macros.
  545.  
  546. .P
  547. Typically, a program will be run once, with no keywords specified,
  548. to determine what keywords are significant for the current problem
  549. (the keywords are printed in the macro output line).
  550. Then the program will be run again, with the desired keywords,
  551. to examine only specific areas of interest.
  552.  
  553. .P
  554. The second argument to a
  555. .B DBUG_PRINT 
  556. macro is a standard printf style
  557. format string and one or more arguments to print, all
  558. enclosed in parenthesis so that they collectively become a single macro
  559. argument.
  560. This is how variable numbers of printf arguments are supported.
  561. Also note that no explicit newline is required at the end of the format string.
  562. As a matter of style, two or three small 
  563. .B DBUG_PRINT
  564. macros are preferable
  565. to a single macro with a huge format string.
  566. Figure 8 shows the output for default tracing and debug.
  567. .DS I N
  568. .SP 2
  569. .so output3.r
  570. .SP 2
  571. .ll -5
  572. .ce
  573. Figure 8
  574. .ce
  575. factorial -#d:t:o 3
  576. .ll +5
  577. .SP 2
  578. .DE
  579.  
  580. .P
  581. The output from the 
  582. .B DBUG_PRINT
  583. macro is indented to match the trace output
  584. for the function in which the macro occurs.
  585. When debugging is enabled, but not trace, the output starts at the left
  586. margin, without indentation.
  587.  
  588. .P
  589. To demonstrate selection of specific macros for output, figure
  590. 9 shows the result when the factorial program is invoked with
  591. the debug control string "-#d,result:o".
  592. .DS I N
  593. .SP 2
  594. .so output4.r
  595. .SP 2
  596. .ll -5
  597. .ce
  598. Figure 9
  599. .ce
  600. factorial -#d,result:o 4
  601. .ll +5
  602. .SP 2
  603. .DE
  604.  
  605. .P
  606. It is sometimes desirable to restrict debugging and trace actions
  607. to a specific function or list of functions.
  608. This is accomplished with the 'f' flag character in the debug
  609. control string.
  610. Figure 10 is the output of the factorial program when run with the
  611. control string "-#d:f,factorial:F:L:o".
  612. The 'F' flag enables printing of the source file name and the 'L'
  613. flag enables printing of the source file line number.
  614. .DS I N
  615. .SP 2
  616. .so output5.r
  617. .SP 2
  618. .ll -5
  619. .ce
  620. Figure 10
  621. .ce
  622. factorial -#d:f,factorial:F:L:o 3
  623. .ll +5
  624. .SP 2
  625. .DE
  626.  
  627. .P
  628. The output in figure 10 shows that the "find" macro is in file
  629. "factorial.c" at source line 8 and the "result" macro is in the same
  630. file at source line 12.
  631.  
  632. .SK
  633. .B
  634. SUMMARY OF MACROS
  635. .R
  636.  
  637. .P
  638. This section summarizes the usage of all currently defined macros
  639. in the 
  640. .I dbug
  641. package.
  642. The macros definitions are found in the user include file
  643. .B dbug.h
  644. from the standard include directory.
  645.  
  646. .SP 2
  647. .BL 20
  648. .LI DBUG_ENTER\ 
  649. Used to tell the runtime support module the name of the function
  650. being entered.
  651. The argument must be of type "pointer to character".
  652. The 
  653. DBUG_ENTER
  654. macro must precede all executable lines in the
  655. function just entered, and must come after all local declarations.
  656. Each 
  657. DBUG_ENTER
  658. macro must have a matching 
  659. DBUG_RETURN 
  660. or
  661. DBUG_VOID_RETURN
  662. macro 
  663. at the function exit points.
  664. DBUG_ENTER 
  665. macros used without a matching 
  666. DBUG_RETURN 
  667. or 
  668. DBUG_VOID_RETURN
  669. macro 
  670. will cause warning messages from the 
  671. .I dbug
  672. package runtime support module.
  673. .SP 1
  674. EX:\ DBUG_ENTER\ ("main");
  675. .SP 1
  676. .LI DBUG_RETURN\ 
  677. Used at each exit point of a function containing a 
  678. DBUG_ENTER 
  679. macro
  680. at the entry point.
  681. The argument is the value to return.
  682. Functions which return no value (void) should use the 
  683. DBUG_VOID_RETURN
  684. macro.
  685. It 
  686. is an error to have a 
  687. DBUG_RETURN 
  688. or 
  689. DBUG_VOID_RETURN 
  690. macro in a function
  691. which has no matching 
  692. DBUG_ENTER 
  693. macro, and the compiler will complain
  694. if the macros are actually used (expanded).
  695. .SP 1
  696. EX:\ DBUG_RETURN\ (value);
  697. .br
  698. EX:\ DBUG_VOID_RETURN;
  699. .SP 1
  700. .LI DBUG_PROCESS\ 
  701. Used to name the current process being executed.
  702. A typical argument for this macro is "argv[0]", though
  703. it will be perfectly happy with any other string.
  704. .SP 1
  705. EX:\ DBUG_PROCESS\ (argv[0]);
  706. .SP 1
  707. .LI DBUG_PUSH\ 
  708. Sets a new debugger state by pushing the current
  709. .B dbug
  710. state onto an
  711. internal stack and setting up the new state using the debug control
  712. string passed as the macro argument.
  713. The most common usage is to set the state specified by a debug
  714. control string retrieved from the argument list.
  715. Note that the leading "-#" in a debug control string specified
  716. as a command line argument must
  717. .B not
  718. be passed as part of the macro argument.
  719. The proper usage is to pass a pointer to the first character
  720. .B after
  721. the "-#" string.
  722. .SP 1
  723. EX:\ DBUG_PUSH\ (\&(argv[i][2]));
  724. .br
  725. EX:\ DBUG_PUSH\ ("d:t");
  726. .br
  727. EX:\ DBUG_PUSH\ ("");
  728. .SP 1
  729. .LI DBUG_POP\ 
  730. Restores the previous debugger state by popping the state stack.
  731. Attempting to pop more states than pushed will be ignored and no
  732. warning will be given.
  733. The 
  734. DBUG_POP 
  735. macro has no arguments.
  736. .SP 1
  737. EX:\ DBUG_POP\ ();
  738. .SP 1
  739. .LI DBUG_FILE\ 
  740. The 
  741. DBUG_FILE 
  742. macro is used to do explicit I/O on the debug output
  743. stream.
  744. It is used in the same manner as the symbols "stdout" and "stderr"
  745. in the standard I/O package.
  746. .SP 1
  747. EX:\ fprintf\ (DBUG_FILE,\ "Doing my own I/O!\n");
  748. .SP 1
  749. .LI DBUG_EXECUTE\ 
  750. The DBUG_EXECUTE macro is used to execute any arbitrary C code.
  751. The first argument is the debug keyword, used to trigger execution
  752. of the code specified as the second argument.
  753. This macro must be used cautiously because, like the 
  754. DBUG_PRINT 
  755. macro,
  756. it is automatically selected by default whenever the 'd' flag has
  757. no argument list (I.E., a "-#d:t" control string).
  758. .SP 1
  759. EX:\ DBUG_EXECUTE\ ("abort",\ abort\ ());
  760. .SP 1
  761. .LI DBUG_N\ 
  762. These macros, where N is in the range 2-5, are currently obsolete
  763. and will be removed in a future release.
  764. Use the new DBUG_PRINT macro.
  765. .LI DBUG_PRINT\ 
  766. Used to do printing via the "fprintf" library function on the
  767. current debug stream,
  768. DBUG_FILE.
  769. The first argument is a debug keyword, the second is a format string
  770. and the corresponding argument list.
  771. Note that the format string and argument list are all one macro argument
  772. and
  773. .B must
  774. be enclosed in parenthesis.
  775. .SP 1
  776. EX:\ DBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));
  777. .br
  778. EX:\ DBUG_PRINT\ ("type",\ ("type\ is\ %x", type));
  779. .br
  780. EX:\ DBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));
  781. .LI DBUG_SETJMP\ 
  782. Used in place of the setjmp() function to first save the current
  783. debugger state and then execute the standard setjmp call.
  784. This allows the debugger to restore its state when the
  785. DBUG_LONGJMP macro is used to invoke the standard longjmp() call.
  786. Currently all instances of DBUG_SETJMP must occur within the
  787. same function and at the same function nesting level.
  788. .SP 1
  789. EX:\ DBUG_SETJMP\ (env);
  790. .LI DBUG_LONGJMP\ 
  791. Used in place of the longjmp() function to first restore the
  792. previous debugger state at the time of the last DBUG_SETJMP
  793. and then execute the standard longjmp() call.
  794. Note that currently all DBUG_LONGJMP macros restore the state
  795. at the time of the last DBUG_SETJMP.
  796. It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP
  797. pairs by having the debugger runtime support module use the first
  798. argument to differentiate the pairs.
  799. .SP 1
  800. EX:\ DBUG_LONGJMP\ (env,val);
  801. .LE
  802.  
  803. .SK
  804. .B
  805. DEBUG CONTROL STRING
  806. .R
  807.  
  808. .P
  809. The debug control string is used to set the state of the debugger
  810. via the 
  811. .B DBUG_PUSH 
  812. macro.
  813. This section summarizes the currently available debugger options
  814. and the flag characters which enable or disable them.
  815. Argument lists enclosed in '[' and ']' are optional.
  816. .SP 2
  817. .BL 22
  818. .LI d[,keywords]
  819. Enable output from macros with specified keywords.
  820. A null list of keywords implies that all keywords are selected.
  821. .LI D[,time]
  822. Delay for specified time after each output line, to let output drain.
  823. Time is given in tenths of a second (value of 10 is one second).
  824. Default is zero.
  825. .LI f[,functions]
  826. Limit debugger actions to the specified list of functions.
  827. A null list of functions implies that all functions are selected.
  828. .LI F
  829. Mark each debugger output line with the name of the source file
  830. containing the macro causing the output.
  831. .LI g
  832. Turn on machine independent profiling.
  833. A profiling data collection file, named dbugmon.out, will be written
  834. for postprocessing by the "analyze" program.
  835. The accuracy of this feature is relatively unknown at this time.
  836. .LI i
  837. Identify the process emitting each line of debug or trace output
  838. with the process id for that process.
  839. .LI L
  840. Mark each debugger output line with the source file line number of
  841. the macro causing the output.
  842. .LI n
  843. Mark each debugger output line with the current function nesting depth.
  844. .LI N
  845. Sequentially number each debugger output line starting at 1.
  846. This is useful for reference purposes when debugger output is
  847. interspersed with program output.
  848. .LI o[,file]
  849. Redirect the debugger output stream to the specified file.
  850. The default output stream is stderr.
  851. A null argument list causes output to be redirected to stdout.
  852. .LI p[,processes]
  853. Limit debugger actions to the specified processes.
  854. A null list implies all processes.
  855. This is useful for processes which run child processes.
  856. Note that each debugger output line can be marked with the name of
  857. the current process via the 'P' flag.
  858. The process name must match the argument passed to the
  859. .B DBUG_PROCESS
  860. macro.
  861. .LI P
  862. Mark each debugger output line with the name of the current process
  863. from argv[0].
  864. Most useful when used with a process which runs child processes that
  865. are also being debugged.
  866. Note that the parent process must arrange for the debugger control
  867. string to be passed to the child processes.
  868. .LI r
  869. Used in conjunction with the 
  870. .B DBUG_PUSH 
  871. macro to reset the current
  872. indentation level back to zero.
  873. Most useful with 
  874. .B DBUG_PUSH 
  875. macros used to temporarily alter the
  876. debugger state.
  877. .LI t[,N]
  878. Enable function control flow tracing.
  879. The maximum nesting depth is specified by N, and defaults to
  880. 200.
  881. .LE
  882. .SK
  883. .B
  884. HINTS AND MISCELLANEOUS
  885. .R
  886.  
  887. .P
  888. One of the most useful capabilities of the 
  889. .I dbug 
  890. package is to compare the executions of a given program in two
  891. different environments.
  892. This is typically done by executing the program in the environment
  893. where it behaves properly and saving the debugger output in a
  894. reference file.
  895. The program is then run with identical inputs in the environment where 
  896. it misbehaves and the output is again captured in a reference file.
  897. The two reference files can then be differentially compared to
  898. determine exactly where execution of the two processes diverges.
  899.  
  900. .P
  901. A related usage is regression testing where the execution of a current
  902. version is compared against executions of previous versions.
  903. This is most useful when there are only minor changes.
  904.  
  905. .P
  906. It is not difficult to modify an existing compiler to implement
  907. some of the functionality of the 
  908. .I dbug
  909. package automatically, without source code changes to the
  910. program being debugged.
  911. In fact, such changes were implemented in a version of the
  912. Portable C Compiler by the author in less than a day.
  913. However, it is strongly encouraged that all newly
  914. developed code continue to use the debugger macros
  915. for the portability reasons noted earlier.
  916. The modified compiler should be used only for testing existing
  917. programs.
  918.  
  919. .SK
  920. .B
  921. CAVEATS
  922. .R
  923.  
  924. .P
  925. The 
  926. .I dbug
  927. package works best with programs which have "line\ oriented"
  928. output, such as text processors, general purpose utilities, etc.
  929. It can be interfaced with screen oriented programs such as
  930. visual editors by redefining the appropriate macros to call
  931. special functions for displaying the debugger results.
  932. Of course, this caveat is not applicable if the debugger output
  933. is simply dumped into a file for post-execution examination.
  934.  
  935. .P
  936. Programs which use memory allocation functions other than
  937. .B malloc
  938. will usually have problems using the standard
  939. .I dbug
  940. package.
  941. The most common problem is multiply allocated memory.
  942. .SP 2
  943. .CS
  944.