home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume19 / dmake / part03 < prev    next >
Encoding:
Text File  |  1991-05-10  |  40.2 KB  |  1,459 lines

  1. Newsgroups: comp.sources.misc
  2. From: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  3. Subject:  v19i024:  dmake - dmake version 3.7, Part03/37
  4. Message-ID: <1991May9.192621.23446@sparky.IMD.Sterling.COM>
  5. Date: Thu, 9 May 1991 19:26:21 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7.  
  8. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  9. Posting-number: Volume 19, Issue 24
  10. Archive-name: dmake/part03
  11. Supersedes: dmake-3.6: Volume 15, Issue 52-77
  12.  
  13. ---- Cut Here and feed the following to sh ----
  14. #!/bin/sh
  15. # this is dmake.shar.03 (part 3 of a multipart archive)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file dmake/dbug/dbug/dbug.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 3; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test -f _shar_wnt_.tmp; then
  32. sed 's/^X//' << 'SHAR_EOF' >> 'dmake/dbug/dbug/dbug.c' &&
  33. X *    current process name, current source file name and line number,
  34. X *    and current function nesting depth.
  35. X *
  36. X */
  37. X  
  38. LOCAL VOID DoPrefix (_line_)
  39. int _line_;
  40. {
  41. X    lineno++;
  42. X    if (stack -> flags & NUMBER_ON) {
  43. X    (VOID) fprintf (_db_fp_, "%5d: ", lineno);
  44. X    }
  45. X    if (stack -> flags & PROCESS_ON) {
  46. X    (VOID) fprintf (_db_fp_, "%s: ", _db_process_);
  47. X    }
  48. X    if (stack -> flags & FILE_ON) {
  49. X    (VOID) fprintf (_db_fp_, "%14s: ", file);
  50. X    }
  51. X    if (stack -> flags & LINE_ON) {
  52. X    (VOID) fprintf (_db_fp_, "%5d: ", _line_);
  53. X    }
  54. X    if (stack -> flags & DEPTH_ON) {
  55. X    (VOID) fprintf (_db_fp_, "%4d: ", stack -> level);
  56. X    }
  57. X    (VOID) fflush (_db_fp_);
  58. }
  59. X
  60. X
  61. /*
  62. X *  FUNCTION
  63. X *
  64. X *    OpenFile    open new output stream for debugger output
  65. X *
  66. X *  SYNOPSIS
  67. X *
  68. X *    LOCAL VOID OpenFile (name)
  69. X *    char *name;
  70. X *
  71. X *  DESCRIPTION
  72. X *
  73. X *    Given name of a new file (or "-" for stdout) opens the file
  74. X *    and sets the output stream to the new file.
  75. X *
  76. X */
  77. X
  78. LOCAL VOID OpenFile (name)
  79. char *name;
  80. {
  81. X    REGISTER FILE *fp;
  82. X    REGISTER BOOLEAN newfile;
  83. X
  84. X    if (name != NULL) {
  85. X    if (strcmp (name, "-") == 0) {
  86. X        _db_fp_ = stdout;
  87. X        stack -> out_file = _db_fp_;
  88. X    } else {
  89. X        if (!Writable (name)) {
  90. X        (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
  91. X        perror ("");
  92. X        (VOID) fflush (_db_fp_);
  93. X        (VOID) XDelay (stack -> delay);
  94. X        } else {
  95. X        if (EXISTS (name)) {
  96. X            newfile = FALSE;
  97. X        } else {
  98. X            newfile = TRUE;
  99. X        }
  100. X        fp = fopen (name, "a");
  101. X        if (fp == NULL) {
  102. X             (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
  103. X            perror ("");
  104. X            (VOID) fflush (_db_fp_);
  105. X            (VOID) XDelay (stack -> delay);
  106. X        } else {
  107. X            _db_fp_ = fp;
  108. X            stack -> out_file = fp;
  109. X            if (newfile) {
  110. X            ChangeOwner (name);
  111. X            }
  112. X        }
  113. X        }
  114. X    }
  115. X    }
  116. }
  117. X
  118. X
  119. /*
  120. X *  FUNCTION
  121. X *
  122. X *    OpenProfile    open new output stream for profiler output
  123. X *
  124. X *  SYNOPSIS
  125. X *
  126. X *    LOCAL VOID OpenProfile (name)
  127. X *    char *name;
  128. X *
  129. X *  DESCRIPTION
  130. X *
  131. X *    Given name of a new file, opens the file
  132. X *    and sets the profiler output stream to the new file.
  133. X *
  134. X *    It is currently unclear whether the prefered behavior is
  135. X *    to truncate any existing file, or simply append to it.
  136. X *    The latter behavior would be desirable for collecting
  137. X *    accumulated runtime history over a number of separate
  138. X *    runs.  It might take some changes to the analyzer program
  139. X *    though, and the notes that Binayak sent with the profiling
  140. X *    diffs indicated that append was the normal mode, but this
  141. X *    does not appear to agree with the actual code. I haven't
  142. X *    investigated at this time [fnf; 24-Jul-87].
  143. X */
  144. X
  145. LOCAL VOID OpenProfile (name)
  146. char *name;
  147. {
  148. X    REGISTER FILE *fp;
  149. X    REGISTER BOOLEAN newfile;
  150. X
  151. X    if (name != NULL) {
  152. X    if (!Writable (name)) {
  153. X        (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
  154. X        perror ("");
  155. X        (VOID) fflush (_db_fp_);
  156. X        (VOID) XDelay (stack -> delay);
  157. X    } else {
  158. X        if (EXISTS (name)) {
  159. X        newfile = FALSE;
  160. X        } else {
  161. X        newfile = TRUE;
  162. X        }
  163. X        fp = fopen (name, "w");
  164. X        if (fp == NULL) {
  165. X        (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
  166. X        perror ("");
  167. X        (VOID) fflush (_db_fp_);
  168. X        (VOID) XDelay (stack -> delay);
  169. X        } else {
  170. X        _db_pfp_ = fp;
  171. X        stack -> prof_file = fp;
  172. X        if (newfile) {
  173. X            ChangeOwner (name);
  174. X        }
  175. X        }
  176. X    }
  177. X    }
  178. }
  179. X
  180. X
  181. /*
  182. X *  FUNCTION
  183. X *
  184. X *    CloseFile    close the debug output stream
  185. X *
  186. X *  SYNOPSIS
  187. X *
  188. X *    LOCAL VOID CloseFile (fp)
  189. X *    FILE *fp;
  190. X *
  191. X *  DESCRIPTION
  192. X *
  193. X *    Closes the debug output stream unless it is standard output
  194. X *    or standard error.
  195. X *
  196. X */
  197. X
  198. LOCAL VOID CloseFile (fp)
  199. FILE *fp;
  200. {
  201. X    if (fp != stderr && fp != stdout) {
  202. X    if (fclose (fp) == EOF) {
  203. X        (VOID) fprintf (stderr, ERR_CLOSE, _db_process_);
  204. X        perror ("");
  205. X        (VOID) fflush (stderr);
  206. X        (VOID) XDelay (stack -> delay);
  207. X    }
  208. X    }
  209. }
  210. X
  211. X
  212. /*
  213. X *  FUNCTION
  214. X *
  215. X *    DbugExit    print error message and exit
  216. X *
  217. X *  SYNOPSIS
  218. X *
  219. X *    LOCAL VOID DbugExit (why)
  220. X *    char *why;
  221. X *
  222. X *  DESCRIPTION
  223. X *
  224. X *    Prints error message using current process name, the reason for
  225. X *    aborting (typically out of memory), and exits with status 1.
  226. X *    This should probably be changed to use a status code
  227. X *    defined in the user's debugger include file.
  228. X *
  229. X */
  230. LOCAL VOID DbugExit (why)
  231. char *why;
  232. {
  233. X    (VOID) fprintf (stderr, ERR_ABORT, _db_process_, why);
  234. X    (VOID) fflush (stderr);
  235. X    (VOID) XDelay (stack -> delay);
  236. X    exit (1);
  237. }
  238. X
  239. X
  240. /*
  241. X *  FUNCTION
  242. X *
  243. X *    DbugMalloc    allocate memory for debugger runtime support
  244. X *
  245. X *  SYNOPSIS
  246. X *
  247. X *    LOCAL char *DbugMalloc (size)
  248. X *    int size;
  249. X *
  250. X *  DESCRIPTION
  251. X *
  252. X *    Allocate more memory for debugger runtime support functions.
  253. X *    Failure to to allocate the requested number of bytes is
  254. X *    immediately fatal to the current process.  This may be
  255. X *    rather unfriendly behavior.  It might be better to simply
  256. X *    print a warning message, freeze the current debugger state,
  257. X *    and continue execution.
  258. X *
  259. X */
  260. LOCAL char *DbugMalloc (size)
  261. int size;
  262. {
  263. X    register char *new;
  264. X
  265. X    new = malloc ( size );
  266. X    if (new == NULL) {
  267. X    DbugExit ("out of memory");
  268. X    }
  269. X    return (new);
  270. }
  271. X
  272. X
  273. /*
  274. X *    This function may be eliminated when strtok is available
  275. X *    in the runtime environment (missing from BSD4.1).
  276. X */
  277. X
  278. LOCAL char *strtok (s1, s2)
  279. char *s1, *s2;
  280. {
  281. X    static char *end = NULL;
  282. X    REGISTER char *rtnval;
  283. X
  284. X    rtnval = NULL;
  285. X    if (s2 != NULL) {
  286. X    if (s1 != NULL) {
  287. X        end = s1;
  288. X        rtnval = strtok ((char *) NULL, s2);
  289. X    } else if (end != NULL) {
  290. X        if (*end != EOS) {
  291. X        rtnval = end;
  292. X        while (*end != *s2 && *end != EOS) {end++;}
  293. X        if (*end != EOS) {
  294. X            *end++ = EOS;
  295. X        }
  296. X        }
  297. X    }
  298. X    }
  299. X    return (rtnval);
  300. }
  301. X
  302. X
  303. /*
  304. X *  FUNCTION
  305. X *
  306. X *    BaseName    strip leading pathname components from name
  307. X *
  308. X *  SYNOPSIS
  309. X *
  310. X *    LOCAL char *BaseName (pathname)
  311. X *    char *pathname;
  312. X *
  313. X *  DESCRIPTION
  314. X *
  315. X *    Given pointer to a complete pathname, locates the base file
  316. X *    name at the end of the pathname and returns a pointer to
  317. X *    it.
  318. X *
  319. X */
  320. X
  321. LOCAL char *BaseName (pathname)
  322. char *pathname;
  323. {
  324. X    register char *base;
  325. X
  326. X    base = strrchr (pathname, '/');
  327. X    if (base++ == NULL) {
  328. X    base = pathname;
  329. X    }
  330. X    return (base);
  331. }
  332. X
  333. X
  334. /*
  335. X *  FUNCTION
  336. X *
  337. X *    Writable    test to see if a pathname is writable/creatable
  338. X *
  339. X *  SYNOPSIS
  340. X *
  341. X *    LOCAL BOOLEAN Writable (pathname)
  342. X *    char *pathname;
  343. X *
  344. X *  DESCRIPTION
  345. X *
  346. X *    Because the debugger might be linked in with a program that
  347. X *    runs with the set-uid-bit (suid) set, we have to be careful
  348. X *    about opening a user named file for debug output.  This consists
  349. X *    of checking the file for write access with the real user id,
  350. X *    or checking the directory where the file will be created.
  351. X *
  352. X *    Returns TRUE if the user would normally be allowed write or
  353. X *    create access to the named file.  Returns FALSE otherwise.
  354. X *
  355. X */
  356. X
  357. LOCAL BOOLEAN Writable (pathname)
  358. char *pathname;
  359. {
  360. X    REGISTER BOOLEAN granted;
  361. #ifdef unix
  362. X    REGISTER char *lastslash;
  363. #endif
  364. X
  365. #ifndef unix
  366. X    granted = TRUE;
  367. #else
  368. X    granted = FALSE;
  369. X    if (EXISTS (pathname)) {
  370. X    if (WRITABLE (pathname)) {
  371. X        granted = TRUE;
  372. X    }
  373. X    } else {
  374. X    lastslash = strrchr (pathname, '/');
  375. X    if (lastslash != NULL) {
  376. X        *lastslash = EOS;
  377. X    } else {
  378. X        pathname = ".";
  379. X    }
  380. X    if (WRITABLE (pathname)) {
  381. X        granted = TRUE;
  382. X    }
  383. X    if (lastslash != NULL) {
  384. X        *lastslash = '/';
  385. X    }
  386. X    }
  387. #endif
  388. X    return (granted);
  389. }
  390. X
  391. X
  392. /*
  393. X *    This function may be eliminated when strrchr is available
  394. X *    in the runtime environment (missing from BSD4.1).
  395. X *    Alternately, you can use rindex() on BSD systems.
  396. X */
  397. X
  398. LOCAL char *strrchr (s, c)
  399. char *s;
  400. char c;
  401. {
  402. X    REGISTER char *scan;
  403. X
  404. X    for (scan = s; *scan != EOS; scan++) {;}
  405. X    while (scan > s && *--scan != c) {;}
  406. X    if (*scan != c) {
  407. X    scan = NULL;
  408. X    }
  409. X    return (scan);
  410. }
  411. X
  412. X
  413. /*
  414. X *  FUNCTION
  415. X *
  416. X *    ChangeOwner    change owner to real user for suid programs
  417. X *
  418. X *  SYNOPSIS
  419. X *
  420. X *    LOCAL VOID ChangeOwner (pathname)
  421. X *
  422. X *  DESCRIPTION
  423. X *
  424. X *    For unix systems, change the owner of the newly created debug
  425. X *    file to the real owner.  This is strictly for the benefit of
  426. X *    programs that are running with the set-user-id bit set.
  427. X *
  428. X *    Note that at this point, the fact that pathname represents
  429. X *    a newly created file has already been established.  If the
  430. X *    program that the debugger is linked to is not running with
  431. X *    the suid bit set, then this operation is redundant (but
  432. X *    harmless).
  433. X *
  434. X */
  435. X
  436. LOCAL VOID ChangeOwner (pathname)
  437. char *pathname;
  438. {
  439. #ifdef unix
  440. X    if (chown (pathname, getuid (), getgid ()) == -1) {
  441. X    (VOID) fprintf (stderr, ERR_CHOWN, _db_process_, pathname);
  442. X    perror ("");
  443. X    (VOID) fflush (stderr);
  444. X    (VOID) XDelay (stack -> delay);
  445. X    }
  446. #endif
  447. }
  448. X
  449. X
  450. /*
  451. X *  FUNCTION
  452. X *
  453. X *    _db_setjmp_    save debugger environment
  454. X *
  455. X *  SYNOPSIS
  456. X *
  457. X *    VOID _db_setjmp_ ()
  458. X *
  459. X *  DESCRIPTION
  460. X *
  461. X *    Invoked as part of the user's DBUG_SETJMP macro to save
  462. X *    the debugger environment in parallel with saving the user's
  463. X *    environment.
  464. X *
  465. X */
  466. X
  467. VOID _db_setjmp_ ()
  468. {
  469. X   jmplevel = stack -> level;
  470. X   jmpfunc = func;
  471. X   jmpfile = file;
  472. }
  473. X
  474. X
  475. /*
  476. X *  FUNCTION
  477. X *
  478. X *    _db_longjmp_    restore previously saved debugger environment
  479. X *
  480. X *  SYNOPSIS
  481. X *
  482. X *    VOID _db_longjmp_ ()
  483. X *
  484. X *  DESCRIPTION
  485. X *
  486. X *    Invoked as part of the user's DBUG_LONGJMP macro to restore
  487. X *    the debugger environment in parallel with restoring the user's
  488. X *    previously saved environment.
  489. X *
  490. X */
  491. X
  492. VOID _db_longjmp_ ()
  493. {
  494. X    stack -> level = jmplevel;
  495. X    if (jmpfunc) {
  496. X    func = jmpfunc;
  497. X    }
  498. X    if (jmpfile) {
  499. X    file = jmpfile;
  500. X    }
  501. }
  502. X
  503. X
  504. /*
  505. X *  FUNCTION
  506. X *
  507. X *    DelayArg   convert D flag argument to appropriate value
  508. X *
  509. X *  SYNOPSIS
  510. X *
  511. X *    LOCAL int DelayArg (value)
  512. X *    int value;
  513. X *
  514. X *  DESCRIPTION
  515. X *
  516. X *    Converts delay argument, given in tenths of a second, to the
  517. X *    appropriate numerical argument used by the system to delay
  518. X *    that that many tenths of a second.  For example, on the
  519. X *    AMIGA, there is a system call "Delay()" which takes an
  520. X *    argument in ticks (50 per second).  On unix, the sleep
  521. X *    command takes seconds.  Thus a value of "10", for one
  522. X *    second of delay, gets converted to 50 on the amiga, and 1
  523. X *    on unix.  Other systems will need to use a timing loop.
  524. X *
  525. X */
  526. X
  527. LOCAL int DelayArg (value)
  528. int value;
  529. {
  530. X    int delayarg = 0;
  531. X    
  532. #ifdef unix
  533. X    delayarg = value / 10;        /* Delay is in seconds for sleep () */
  534. #endif
  535. #ifdef AMIGA
  536. X    delayarg = (HZ * value) / 10;    /* Delay in ticks for XDelay () */
  537. #endif
  538. X    return (delayarg);
  539. }
  540. X
  541. X
  542. /*
  543. X *    A dummy delay stub for systems that do not support delays.
  544. X *    With a little work, this can be turned into a timing loop.
  545. X */
  546. X
  547. #ifndef unix
  548. #ifndef AMIGA
  549. XXDelay ()
  550. {
  551. }
  552. #endif
  553. #endif
  554. X
  555. X
  556. /*
  557. X *  FUNCTION
  558. X *
  559. X *    perror    perror simulation for systems that don't have it
  560. X *
  561. X *  SYNOPSIS
  562. X *
  563. X *    LOCAL VOID perror (s)
  564. X *    char *s;
  565. X *
  566. X *  DESCRIPTION
  567. X *
  568. X *    Perror produces a message on the standard error stream which
  569. X *    provides more information about the library or system error
  570. X *    just encountered.  The argument string s is printed, followed
  571. X *    by a ':', a blank, and then a message and a newline.
  572. X *
  573. X *    An undocumented feature of the unix perror is that if the string
  574. X *    's' is a null string (NOT a NULL pointer!), then the ':' and
  575. X *    blank are not printed.
  576. X *
  577. X *    This version just complains about an "unknown system error".
  578. X *
  579. X */
  580. X
  581. #if !unix && !(AMIGA || LATTICE || __TURBOC__ )
  582. LOCAL VOID perror (s)
  583. #if __STDC__
  584. const char *s;
  585. #else
  586. char *s;
  587. #endif
  588. {
  589. X    if (s && *s != EOS) {
  590. X    (VOID) fprintf (stderr, "%s: ", s);
  591. X    }
  592. X    (VOID) fprintf (stderr, "<unknown system error>\n");
  593. }
  594. #endif    /* !unix && !(AMIGA && LATTICE) */
  595. X
  596. /*
  597. X * Here we need the definitions of the clock routine.  Add your
  598. X * own for whatever system that you have.
  599. X */
  600. X
  601. #if unix
  602. X
  603. # include <sys/param.h>
  604. # if BSD4_3 || sun
  605. X
  606. /*
  607. X * Definition of the Clock() routine for 4.3 BSD.
  608. X */
  609. X
  610. #include <sys/time.h>
  611. #include <sys/resource.h>
  612. X
  613. /*
  614. X * Returns the user time in milliseconds used by this process so
  615. X * far.
  616. X */
  617. X
  618. LOCAL unsigned long Clock ()
  619. {
  620. X    struct rusage ru;
  621. X
  622. X    (VOID) getrusage (RUSAGE_SELF, &ru);
  623. X    return ((ru.ru_utime.tv_sec * 1000) + (ru.ru_utime.tv_usec / 1000));
  624. }
  625. X
  626. #else
  627. X
  628. LOCAL unsigned long Clock ()
  629. {
  630. X    return (0);
  631. }
  632. X
  633. # endif
  634. X
  635. #else
  636. X
  637. #if AMIGA
  638. X
  639. struct DateStamp {        /* Yes, this is a hack, but doing it right */
  640. X    long ds_Days;        /* is incredibly ugly without splitting this */
  641. X    long ds_Minute;        /* off into a separate file */
  642. X    long ds_Tick;
  643. };
  644. X
  645. static int first_clock = TRUE;
  646. static struct DateStamp begin;
  647. static struct DateStamp elapsed;
  648. X
  649. LOCAL unsigned long Clock ()
  650. {
  651. X    register struct DateStamp *now;
  652. X    register unsigned long millisec = 0;
  653. X    extern VOID *AllocMem ();
  654. X
  655. X    now = (struct DateStamp *) AllocMem ((long) sizeof (struct DateStamp), 0L);
  656. X    if (now != NULL) {
  657. X    if (first_clock == TRUE) {
  658. X        first_clock = FALSE;
  659. X        (VOID) DateStamp (now);
  660. X        begin = *now;
  661. X    }
  662. X    (VOID) DateStamp (now);
  663. X    millisec = 24 * 3600 * (1000 / HZ) * (now -> ds_Days - begin.ds_Days);
  664. X    millisec += 60 * (1000 / HZ) * (now -> ds_Minute - begin.ds_Minute);
  665. X    millisec += (1000 / HZ) * (now -> ds_Tick - begin.ds_Tick);
  666. X    (VOID) FreeMem (now, (long) sizeof (struct DateStamp));
  667. X    }
  668. X    return (millisec);
  669. }
  670. X
  671. #else
  672. X
  673. LOCAL unsigned long Clock ()
  674. {
  675. X    return (0);
  676. }
  677. X
  678. #endif    /* AMIGA */
  679. X
  680. #endif    /* unix */
  681. X
  682. #ifdef AMIGA
  683. XXDelay(x)
  684. int x;
  685. {
  686. X    if (x) Delay(x);    /* fix Delay bug in AmigaDOS */
  687. }
  688. #endif
  689. X
  690. SHAR_EOF
  691. chmod 0640 dmake/dbug/dbug/dbug.c ||
  692. echo 'restore of dmake/dbug/dbug/dbug.c failed'
  693. Wc_c="`wc -c < 'dmake/dbug/dbug/dbug.c'`"
  694. test 44504 -eq "$Wc_c" ||
  695.     echo 'dmake/dbug/dbug/dbug.c: original size 44504, current size' "$Wc_c"
  696. rm -f _shar_wnt_.tmp
  697. fi
  698. # ============= dmake/dbug/dbug/dbug.h ==============
  699. if test -f 'dmake/dbug/dbug/dbug.h' -a X"$1" != X"-c"; then
  700.     echo 'x - skipping dmake/dbug/dbug/dbug.h (File already exists)'
  701.     rm -f _shar_wnt_.tmp
  702. else
  703. > _shar_wnt_.tmp
  704. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.h' &&
  705. /******************************************************************************
  706. X *                                          *
  707. X *                               N O T I C E                      *
  708. X *                                          *
  709. X *                  Copyright Abandoned, 1987, Fred Fish              *
  710. X *                                          *
  711. X *                                          *
  712. X *    This previously copyrighted work has been placed into the  public     *
  713. X *    domain  by  the  author  and  may be freely used for any purpose,     *
  714. X *    private or commercial.                              *
  715. X *                                          *
  716. X *    Because of the number of inquiries I was receiving about the  use     *
  717. X *    of this product in commercially developed works I have decided to     *
  718. X *    simply make it public domain to further its unrestricted use.   I     *
  719. X *    specifically  would  be  most happy to see this material become a     *
  720. X *    part of the standard Unix distributions by AT&T and the  Berkeley     *
  721. X *    Computer  Science  Research Group, and a standard part of the GNU     *
  722. X *    system from the Free Software Foundation.                  *
  723. X *                                          *
  724. X *    I would appreciate it, as a courtesy, if this notice is  left  in     *
  725. X *    all copies and derivative works.  Thank you.                  *
  726. X *                                          *
  727. X *    The author makes no warranty of any kind  with  respect  to  this     *
  728. X *    product  and  explicitly disclaims any implied warranties of mer-     *
  729. X *    chantability or fitness for any particular purpose.              *
  730. X *                                          *
  731. X ******************************************************************************
  732. X */
  733. X
  734. X
  735. /*
  736. X *  FILE
  737. X *
  738. X *    dbug.h    user include file for programs using the dbug package
  739. X *
  740. X *  SYNOPSIS
  741. X *
  742. X *    #include <local/dbug.h>
  743. X *
  744. X *  SCCS ID
  745. X *
  746. X *    @(#)dbug.h    1.11 9/5/87
  747. X *
  748. X *  DESCRIPTION
  749. X *
  750. X *    Programs which use the dbug package must include this file.
  751. X *    It contains the appropriate macros to call support routines
  752. X *    in the dbug runtime library.
  753. X *
  754. X *    To disable compilation of the macro expansions define the
  755. X *    preprocessor symbol "DBUG_OFF".  This will result in null
  756. X *    macros expansions so that the resulting code will be smaller
  757. X *    and faster.  (The difference may be smaller than you think
  758. X *    so this step is recommended only when absolutely necessary).
  759. X *    In general, tradeoffs between space and efficiency are
  760. X *    decided in favor of efficiency since space is seldom a
  761. X *    problem on the new machines).
  762. X *
  763. X *    All externally visible symbol names follow the pattern
  764. X *    "_db_xxx..xx_" to minimize the possibility of a dbug package
  765. X *    symbol colliding with a user defined symbol.
  766. X *    
  767. X *    The DBUG_<N> style macros are obsolete and should not be used
  768. X *    in new code.  Macros to map them to instances of DBUG_PRINT
  769. X *    are provided for compatibility with older code.  They may go
  770. X *    away completely in subsequent releases.
  771. X *
  772. X *  AUTHOR
  773. X *
  774. X *    Fred Fish
  775. X *    (Currently employed by Motorola Computer Division, Tempe, Az.)
  776. X *    hao!noao!mcdsun!fnf
  777. X *    (602) 438-3614
  778. X *
  779. X */
  780. X
  781. X
  782. /*
  783. X *    Internally used dbug variables which must be global.
  784. X */
  785. X
  786. #ifndef DBUG_OFF
  787. X    extern int _db_on_;            /* TRUE if debug currently enabled */
  788. X    extern FILE *_db_fp_;        /* Current debug output stream */
  789. X    extern char *_db_process_;        /* Name of current process */
  790. X    extern int _db_keyword_ ();        /* Accept/reject keyword */
  791. X    extern void _db_push_ ();        /* Push state, set up new state */
  792. X    extern void _db_pop_ ();        /* Pop previous debug state */
  793. X    extern void _db_enter_ ();        /* New user function entered */
  794. X    extern void _db_return_ ();        /* User function return */
  795. X    extern void _db_pargs_ ();        /* Remember args for line */
  796. X    extern void _db_doprnt_ ();        /* Print debug output */
  797. X    extern void _db_setjmp_ ();        /* Save debugger environment */
  798. X    extern void _db_longjmp_ ();    /* Restore debugger environment */
  799. # endif
  800. X
  801. X
  802. /*
  803. X *    These macros provide a user interface into functions in the
  804. X *    dbug runtime support library.  They isolate users from changes
  805. X *    in the MACROS and/or runtime support.
  806. X *
  807. X *    The symbols "__LINE__" and "__FILE__" are expanded by the
  808. X *    preprocessor to the current source file line number and file
  809. X *    name respectively.
  810. X *
  811. X *    WARNING ---  Because the DBUG_ENTER macro allocates space on
  812. X *    the user function's stack, it must precede any executable
  813. X *    statements in the user function.
  814. X *
  815. X */
  816. X
  817. # ifdef DBUG_OFF
  818. #    define DBUG_ENTER(a1)
  819. #    define DBUG_MALLOC(a1)
  820. #    define DBUG_RETURN(a1) return(a1)
  821. #    define DBUG_VOID_RETURN return
  822. #    define DBUG_EXECUTE(keyword,a1)
  823. #    define DBUG_PRINT(keyword,arglist)
  824. #    define DBUG_2(keyword,format)        /* Obsolete */
  825. #    define DBUG_3(keyword,format,a1)        /* Obsolete */
  826. #    define DBUG_4(keyword,format,a1,a2)    /* Obsolete */
  827. #    define DBUG_5(keyword,format,a1,a2,a3)    /* Obsolete */
  828. #    define DBUG_PUSH(a1)
  829. #    define DBUG_POP()
  830. #    define DBUG_PROCESS(a1)
  831. #    define DBUG_FILE (stderr)
  832. #    define DBUG_SETJMP setjmp
  833. #    define DBUG_LONGJMP longjmp
  834. # else
  835. #    define DBUG_ENTER(a) \
  836. X    auto char *_db_func_, *_db_file_; \
  837. X    int _db_level_; \
  838. X    _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
  839. #    define DBUG_MALLOC(a) \
  840. X    auto char *_db_func_, *_db_file_; \
  841. X    int _db_level_; \
  842. X    malloc_init();\
  843. X    _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
  844. #    define DBUG_LEAVE \
  845. X    (_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
  846. #    define DBUG_RETURN(a1) return (DBUG_LEAVE, (a1))
  847. /*   define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);}  Alternate form */
  848. #    define DBUG_VOID_RETURN DBUG_LEAVE; return
  849. #    define DBUG_EXECUTE(keyword,a1) \
  850. X    {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
  851. #    define DBUG_PRINT(keyword,arglist) \
  852. X    {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
  853. #    define DBUG_2(keyword,format) \
  854. X    DBUG_PRINT(keyword,(format))        /* Obsolete */
  855. #    define DBUG_3(keyword,format,a1) \
  856. X    DBUG_PRINT(keyword,(format,a1))        /* Obsolete */
  857. #    define DBUG_4(keyword,format,a1,a2) \
  858. X    DBUG_PRINT(keyword,(format,a1,a2))    /* Obsolete */
  859. #    define DBUG_5(keyword,format,a1,a2,a3) \
  860. X    DBUG_PRINT(keyword,(format,a1,a2,a3))    /* Obsolete */
  861. #    define DBUG_PUSH(a1) _db_push_ (a1)
  862. #    define DBUG_POP() _db_pop_ ()
  863. #    define DBUG_PROCESS(a1) (_db_process_ = a1)
  864. #    define DBUG_FILE (_db_fp_)
  865. #    define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
  866. #    define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
  867. # endif
  868. X
  869. SHAR_EOF
  870. chmod 0640 dmake/dbug/dbug/dbug.h ||
  871. echo 'restore of dmake/dbug/dbug/dbug.h failed'
  872. Wc_c="`wc -c < 'dmake/dbug/dbug/dbug.h'`"
  873. test 6259 -eq "$Wc_c" ||
  874.     echo 'dmake/dbug/dbug/dbug.h: original size 6259, current size' "$Wc_c"
  875. rm -f _shar_wnt_.tmp
  876. fi
  877. # ============= dmake/dbug/dbug/dbug.p ==============
  878. if test -f 'dmake/dbug/dbug/dbug.p' -a X"$1" != X"-c"; then
  879.     echo 'x - skipping dmake/dbug/dbug/dbug.p (File already exists)'
  880.     rm -f _shar_wnt_.tmp
  881. else
  882. > _shar_wnt_.tmp
  883. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.p' &&
  884. X
  885. X
  886. X
  887. X                                 D B U G
  888. X
  889. X                       C Program Debugging Package
  890. X
  891. X                                    by
  892. X
  893. X                                Fred Fish
  894. X
  895. X
  896. X
  897. X
  898. X       IIIINNNNTTTTRRRROOOODDDDUUUUCCCCTTTTIIIIOOOONNNN
  899. X
  900. X
  901. X            Almost every program development environment worthy  of
  902. X       the  name provides some sort of debugging facility.  Usually
  903. X       this takes the  form  of  a  program  which  is  capable  of
  904. X       controlling  execution  of  other programs and examining the
  905. X       internal state of other executing programs.  These types  of
  906. X       programs will be referred to as external debuggers since the
  907. X       debugger is not part of the executing program.  Examples  of
  908. X       this  type  of  debugger  include  the aaaaddddbbbb and ssssddddbbbb debuggers
  909. X       provided with the UUUUNNNNIIIIXXXX811119 operating system.
  910. X
  911. X
  912. X            One of the problems associated with developing programs
  913. X       in  an  environment  with  good  external  debuggers is that
  914. X       developed programs  tend  to  have  little  or  no  internal
  915. X       instrumentation.   This  is  usually  not  a problem for the
  916. X       developer since he is, or at  least  should  be,  intimately
  917. X       familiar  with  the  internal organization, data structures,
  918. X       and control flow of the program being  debugged.   It  is  a
  919. X       serious   problem   for  maintenance  programmers,  who  are
  920. X       unlikely to have such familiarity  with  the  program  being
  921. X       maintained,  modified, or ported to another environment.  It
  922. X       is also a problem, even for the developer, when the  program
  923. X       is  moved  to  an environment with a primitive or unfamiliar
  924. X       debugger, or even no debugger.
  925. X
  926. X
  927. X            On the other hand, _d_b_u_g is an example  of  an  internal
  928. X       debugger.  Because it requires internal instrumentation of a
  929. X       program, and its  usage  does  not  depend  on  any  special
  930. X       capabilities  of  the  execution  environment,  it is always
  931. X       available and will  execute  in  any  environment  that  the
  932. X       program  itself will execute in.  In addition, since it is a
  933. X       complete  package  with  a  specific  user  interface,   all
  934. X       programs   which  use  it  will  be  provided  with  similar
  935. X       debugging capabilities.  This is in sharp contrast to  other
  936. X
  937. X
  938. X       __________
  939. X
  940. X        1. UNIX is a trademark of AT&T Bell Laboratories.
  941. X
  942. X
  943. X
  944. X
  945. X                                  - 1 -
  946. X
  947. X
  948. X
  949. X
  950. X
  951. X
  952. X
  953. X       DBUG User Manual                            October 29, 1986
  954. X
  955. X
  956. X
  957. X       forms of internal instrumentation where each  developer  has
  958. X       their  own, usually less capable, form of internal debugger.
  959. X       In summary, because _d_b_u_g is an internal debugger it provides
  960. X       consistency across operating environments, and because it is
  961. X       available to all developers it provides  consistency  across
  962. X       all programs in the same environment.
  963. X
  964. X
  965. X            The _d_b_u_g package imposes only a slight speed penalty on
  966. X       executing programs, typically much less than 10 percent, and
  967. X       a modest size penalty,  typically  10  to  20  percent.   By
  968. X       defining  a specific C preprocessor symbol both of these can
  969. X       be reduced to zero with no changes required  to  the  source
  970. X       code.
  971. X
  972. X
  973. X            The  following  list  is  a  quick   summary   of   the
  974. X       capabilities  of  the  _d_b_u_g package.  Each capability can be
  975. X       individually enabled or disabled at the time  a  program  is
  976. X       invoked   by   specifying   the   appropriate  command  line
  977. X       arguments.
  978. X
  979. X               o Execution trace  showing  function  level  control
  980. X                 flow    in   a   semi-graphically   manner   using
  981. X                 indentation to indicate nesting depth.
  982. X
  983. X               o Output the values of all, or any  subset  of,  key
  984. X                 internal variables.
  985. X
  986. X               o Limit  actions  to  a  specific   set   of   named
  987. X                 functions.
  988. X
  989. X               o Limit function trace to a specified nesting depth.
  990. X
  991. X               o Label each output line with source file  name  and
  992. X                 line number.
  993. X
  994. X               o Label  each  output  line  with  name  of  current
  995. X                 process.
  996. X
  997. X               o Push or pop  internal  debugging  state  to  allow
  998. X                 execution with built in debugging defaults.
  999. X
  1000. X               o Redirect  the  debug  output  stream  to  standard
  1001. X                 output  (stdout)  or  a  named  file.  The default
  1002. X                 output stream is  standard  error  (stderr).   The
  1003. X                 redirection mechanism is completely independent of
  1004. X                 normal command line redirection  to  avoid  output
  1005. X                 conflicts.
  1006. X
  1007. X
  1008. X
  1009. X
  1010. X
  1011. X                                  - 2 -
  1012. X
  1013. X
  1014. X
  1015. X
  1016. X
  1017. X
  1018. X
  1019. X       DBUG User Manual                            October 29, 1986
  1020. X
  1021. X
  1022. X
  1023. X       PPPPRRRRIIIIMMMMIIIITTTTIIIIVVVVEEEE DDDDEEEEBBBBUUUUGGGGGGGGIIIINNNNGGGG TTTTEEEECCCCHHHHNNNNIIIIQQQQUUUUEEEESSSS
  1024. X
  1025. X
  1026. X            Internal instrumentation is already a familiar  concept
  1027. X       to most programmers, since it is usually the first debugging
  1028. X       technique  learned.    Typically,   "print statements"   are
  1029. X       inserted  in the source code at interesting points, the code
  1030. X       is recompiled and executed,  and  the  resulting  output  is
  1031. X       examined in an attempt to determine where the problem is.
  1032. X
  1033. X       The procedure is iterative,  with  each  iteration  yielding
  1034. X       more  and  more  output,  and  hopefully  the  source of the
  1035. X       problem is discovered before the output becomes too large to
  1036. X       deal  with  or  previously  inserted  statements  need to be
  1037. X       removed.  Figure 1 is an example of this type  of  primitive
  1038. X       debugging technique.
  1039. X
  1040. X
  1041. X
  1042. X                 #include <stdio.h>
  1043. X
  1044. X                 main (argc, argv)
  1045. X                 int argc;
  1046. X                 char *argv[];
  1047. X                 {
  1048. X                     printf ("argv[0] = %d\n", argv[0]);
  1049. X                     /*
  1050. X                      *  Rest of program
  1051. X                      */
  1052. X                     printf ("== done ==\n");
  1053. X                 }
  1054. X
  1055. X
  1056. X                                   Figure 1
  1057. X                         Primitive Debugging Technique
  1058. X
  1059. X
  1060. X
  1061. X
  1062. X
  1063. X            Eventually,  and  usually  after   at   least   several
  1064. X       iterations,  the  problem  will  be found and corrected.  At
  1065. X       this point, the newly  inserted  print  statements  must  be
  1066. X       dealt  with.   One obvious solution is to simply delete them
  1067. X       all.  Beginners usually do this a few times until they  have
  1068. X       to  repeat  the entire process every time a new bug pops up.
  1069. X       The second most obvious solution is to somehow  disable  the
  1070. X       output,  either  through  the  source code comment facility,
  1071. X       creation of a debug variable to be switched on or off, or by
  1072. X       using  the  C  preprocessor.   Figure 2 is an example of all
  1073. X       three techniques.
  1074. X
  1075. X
  1076. X
  1077. X                                  - 3 -
  1078. X
  1079. X
  1080. X
  1081. X
  1082. X
  1083. X
  1084. X
  1085. X       DBUG User Manual                            October 29, 1986
  1086. X
  1087. X
  1088. X
  1089. X
  1090. X
  1091. X                 #include <stdio.h>
  1092. X
  1093. X                 int debug = 0;
  1094. X
  1095. X                 main (argc, argv)
  1096. X                 int argc;
  1097. X                 char *argv[];
  1098. X                 {
  1099. X                     /* printf ("argv = %x\n", argv) */
  1100. X                     if (debug) printf ("argv[0] = %d\n", argv[0]);
  1101. X                     /*
  1102. X                      *  Rest of program
  1103. X                      */
  1104. X                 #ifdef DEBUG
  1105. X                     printf ("== done ==\n");
  1106. X                 #endif
  1107. X                 }
  1108. X
  1109. X
  1110. X                                   Figure 2
  1111. X                           Debug Disable Techniques
  1112. X
  1113. X
  1114. X
  1115. X
  1116. X
  1117. X            Each technique has  its  advantages  and  disadvantages
  1118. X       with  respect  to  dynamic vs static activation, source code
  1119. X       overhead, recompilation requirements, ease of  use,  program
  1120. X       readability,  etc.   Overuse  of  the  preprocessor solution
  1121. X       quickly leads to problems with source code  readability  and
  1122. X       maintainability  when  multiple  ####iiiiffffddddeeeeffff  symbols  are  to be
  1123. X       defined or  undefined  based  on  specific  types  of  debug
  1124. X       desired.  The source code can be made slightly more readable
  1125. X       by suitable indentation of the ####iiiiffffddddeeeeffff arguments to match the
  1126. X       indentation  of  the code, but not all C preprocessors allow
  1127. X       this.   The  only  requirement  for  the  standard  UUUUNNNNIIIIXXXX   C
  1128. X       preprocessor is for the '#' character to appear in the first
  1129. X       column,  but  even  this  seems  like   an   arbitrary   and
  1130. X       unreasonable  restriction.   Figure  3 is an example of this
  1131. X       usage.
  1132. X
  1133. X
  1134. X
  1135. X
  1136. X
  1137. X
  1138. X
  1139. X
  1140. X
  1141. X
  1142. X
  1143. X                                  - 4 -
  1144. X
  1145. X
  1146. X
  1147. X
  1148. X
  1149. X
  1150. X
  1151. X       DBUG User Manual                            October 29, 1986
  1152. X
  1153. X
  1154. X
  1155. X
  1156. X
  1157. X                 #include <stdio.h>
  1158. X
  1159. X                 main (argc, argv)
  1160. X                 int argc;
  1161. X                 char *argv[];
  1162. X                 {
  1163. X                 #   ifdef DEBUG
  1164. X                     printf ("argv[0] = %d\n", argv[0]);
  1165. X                 #   endif
  1166. X                     /*
  1167. X                      *  Rest of program
  1168. X                      */
  1169. X                 #   ifdef DEBUG
  1170. X                     printf ("== done ==\n");
  1171. X                 #   endif
  1172. X                 }
  1173. X
  1174. X
  1175. X                                   Figure 3
  1176. X                       More Readable Preprocessor Usage
  1177. X
  1178. X
  1179. X
  1180. X
  1181. X
  1182. X
  1183. X
  1184. X
  1185. X
  1186. X
  1187. X
  1188. X
  1189. X
  1190. X
  1191. X
  1192. X
  1193. X
  1194. X
  1195. X
  1196. X
  1197. X
  1198. X
  1199. X
  1200. X
  1201. X
  1202. X
  1203. X
  1204. X
  1205. X
  1206. X
  1207. X
  1208. X
  1209. X                                  - 5 -
  1210. X
  1211. X
  1212. X
  1213. X
  1214. X
  1215. X
  1216. X
  1217. X       DBUG User Manual                            October 29, 1986
  1218. X
  1219. X
  1220. X
  1221. X       FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN TTTTRRRRAAAACCCCEEEE EEEEXXXXAAAAMMMMPPPPLLLLEEEE
  1222. X
  1223. X
  1224. X            We will start off learning about  the  capabilities  of
  1225. X       the  _d_b_u_g  package  by  using  a simple minded program which
  1226. X       computes the factorial of a  number.   In  order  to  better
  1227. X       demonstrate  the  function  trace mechanism, this program is
  1228. X       implemented recursively.  Figure 4 is the main function  for
  1229. X       this factorial program.
  1230. X
  1231. X
  1232. X
  1233. X                 #include <stdio.h>
  1234. X                 /* User programs should use <local/dbug.h> */
  1235. X                 #include "dbug.h"
  1236. X
  1237. X                 main (argc, argv)
  1238. X                 int argc;
  1239. X                 char *argv[];
  1240. X                 {
  1241. X                     register int result, ix;
  1242. X                     extern int factorial (), atoi ();
  1243. X
  1244. X                     DBUG_ENTER ("main");
  1245. X                     DBUG_PROCESS (argv[0]);
  1246. X                     for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
  1247. X                         switch (argv[ix][1]) {
  1248. X                             case '#':
  1249. X                                 DBUG_PUSH (&(argv[ix][2]));
  1250. X                                 break;
  1251. X                         }
  1252. X                     }
  1253. X                     for (; ix < argc; ix++) {
  1254. X                         DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
  1255. X                         result = factorial (atoi (argv[ix]));
  1256. X                         printf ("%d\n", result);
  1257. X                     }
  1258. X                     DBUG_RETURN (0);
  1259. X                 }
  1260. X
  1261. X
  1262. X                                   Figure 4
  1263. X                          Factorial Program Mainline
  1264. X
  1265. X
  1266. X
  1267. X
  1268. X
  1269. X            The mmmmaaaaiiiinnnn function is  responsible  for  processing  any
  1270. X       command   line  option  arguments  and  then  computing  and
  1271. X       printing the factorial of each non-option argument.
  1272. X
  1273. X
  1274. X
  1275. X                                  - 6 -
  1276. X
  1277. X
  1278. X
  1279. X
  1280. X
  1281. X
  1282. X
  1283. X       DBUG User Manual                            October 29, 1986
  1284. X
  1285. X
  1286. X
  1287. X            First of all, notice that all of the debugger functions
  1288. X       are  implemented  via  preprocessor  macros.   This does not
  1289. X       detract from the readability of the code and makes disabling
  1290. X       all debug compilation trivial (a single preprocessor symbol,
  1291. X       DDDDBBBBUUUUGGGG____OOOOFFFFFFFF, forces the macro expansions to be null).
  1292. X
  1293. X            Also notice the inclusion of  the  header  file  ddddbbbbuuuugggg....hhhh
  1294. X       from the local header file directory.  (The version included
  1295. X       here is the test version in  the  dbug  source  distribution
  1296. X       directory).   This file contains all the definitions for the
  1297. X       debugger macros, which all have the form DDDDBBBBUUUUGGGG____XXXXXXXX............XXXXXXXX.
  1298. X
  1299. X
  1300. X            The DDDDBBBBUUUUGGGG____EEEENNNNTTTTEEEERRRR macro informs that debugger that we have
  1301. X       entered  the function named mmmmaaaaiiiinnnn.  It must be the very first
  1302. X       "executable" line in a function, after all declarations  and
  1303. X       before any other executable line.  The DDDDBBBBUUUUGGGG____PPPPRRRROOOOCCCCEEEESSSSSSSS macro is
  1304. X       generally used only once per program to inform the  debugger
  1305. X       what name the program was invoked with.  The DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro
  1306. X       modifies the current debugger state by saving  the  previous
  1307. X       state  and  setting  a new state based on the control string
  1308. X       passed as its argument.  The DDDDBBBBUUUUGGGG____PPPPRRRRIIIINNNNTTTT  macro  is  used  to
  1309. X       print  the  values of each argument for which a factorial is
  1310. X       to be computed.  The DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN macro  tells  the  debugger
  1311. X       that  the  end  of the current function has been reached and
  1312. X       returns a value to  the  calling  function.   All  of  these
  1313. X       macros will be fully explained in subsequent sections.
  1314. X
  1315. X            To use the debugger, the factorial program  is  invoked
  1316. X       with a command line of the form:
  1317. X
  1318. X                          factorial -#d:t 1 2 3
  1319. X
  1320. X       The  mmmmaaaaiiiinnnn  function  recognizes  the  "-#d:t"  string  as  a
  1321. X       debugger  control  string, and passes the debugger arguments
  1322. X       ("d:t")  to  the  _d_b_u_g  runtime  support  routines  via  the
  1323. X       DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro.  This particular string enables output from
  1324. X       the DDDDBBBBUUUUGGGG____PPPPRRRRIIIINNNNTTTT macro with the 'd' flag and enables  function
  1325. X       tracing  with  the 't' flag.  The factorial function is then
  1326. X       called three times, with the arguments "1",  "2",  and  "3".
  1327. X       Note  that  the DBUG_PRINT takes exactly ttttwwwwoooo arguments, with
  1328. X       the second argument (a format string and list  of  printable
  1329. X       values) enclosed in parenthesis.
  1330. X
  1331. X            Debug control strings consist of a  header,  the  "-#",
  1332. X       followed  by  a  colon separated list of debugger arguments.
  1333. X       Each debugger argument is a single character  flag  followed
  1334. X       by an optional comma separated list of arguments specific to
  1335. X       the given flag.  Some examples are:
  1336. X
  1337. X
  1338. X
  1339. X
  1340. X
  1341. X                                  - 7 -
  1342. X
  1343. X
  1344. X
  1345. X
  1346. X
  1347. X
  1348. X
  1349. X       DBUG User Manual                            October 29, 1986
  1350. X
  1351. X
  1352. X
  1353. X                          -#d:t:o
  1354. X                          -#d,in,out:f,main:F:L
  1355. X
  1356. X       Note  that  previously  enabled  debugger  actions  can   be
  1357. X       disabled by the control string "-#".
  1358. X
  1359. X
  1360. X            The definition of the factorial function, symbolized as
  1361. X       "N!", is given by:
  1362. X
  1363. X                         N! = N * N-1 * ... 2 * 1
  1364. X
  1365. X       Figure 5 is the factorial  function  which  implements  this
  1366. X       algorithm  recursively.   Note  that this is not necessarily
  1367. X       the best way to  do  factorials  and  error  conditions  are
  1368. X       ignored completely.
  1369. X
  1370. X
  1371. X
  1372. X                 #include <stdio.h>
  1373. X                 /* User programs should use <local/dbug.h> */
  1374. X                 #include "dbug.h"
  1375. X
  1376. X                 int factorial (value)
  1377. X                 register int value;
  1378. X                 {
  1379. X                     DBUG_ENTER ("factorial");
  1380. X                     DBUG_PRINT ("find", ("find %d factorial", value));
  1381. X                     if (value > 1) {
  1382. X                         value *= factorial (value - 1);
  1383. X                     }
  1384. X                     DBUG_PRINT ("result", ("result is %d", value));
  1385. X                     DBUG_RETURN (value);
  1386. X                 }
  1387. X
  1388. X
  1389. X                                   Figure 5
  1390. X                              Factorial Function
  1391. X
  1392. X
  1393. X
  1394. X
  1395. X
  1396. X            One advantage (some may not consider it  so)  to  using
  1397. X       the  _d_b_u_g  package  is  that  it  strongly  encourages fully
  1398. X       structured coding with only one entry and one exit point  in
  1399. X       each  function.  Multiple exit points, such as early returns
  1400. X       to escape a loop, may be used, but each such point  requires
  1401. X       the  use  of  an appropriate DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN or DDDDBBBBUUUUGGGG____VVVVOOOOIIIIDDDD____RRRREEEETTTTUUUURRRRNNNN
  1402. X       macro.
  1403. X
  1404. X
  1405. X
  1406. X
  1407. X                                  - 8 -
  1408. X
  1409. X
  1410. X
  1411. X
  1412. X
  1413. X
  1414. X
  1415. X       DBUG User Manual                            October 29, 1986
  1416. X
  1417. X
  1418. X
  1419. X            To build  the  factorial  program  on  a  UUUUNNNNIIIIXXXX  system,
  1420. X       compile and link with the command:
  1421. X
  1422. X                cc -o factorial main.c factorial.c -ldbug
  1423. X
  1424. X       The "-ldbug" argument  tells  the  loader  to  link  in  the
  1425. X       runtime support modules for the _d_b_u_g package.  Executing the
  1426. X       factorial program with a command of the form:
  1427. X
  1428. X                           factorial 1 2 3 4 5
  1429. X
  1430. X       generates the output shown in figure 6.
  1431. X
  1432. X
  1433. X
  1434. X                 1
  1435. X                 2
  1436. X                 6
  1437. X                 24
  1438. X                 120
  1439. X
  1440. X
  1441. X                                   Figure 6
  1442. X                              factorial 1 2 3 4 5
  1443. SHAR_EOF
  1444. true || echo 'restore of dmake/dbug/dbug/dbug.p failed'
  1445. fi
  1446. echo 'End of part 3, continue with part 4'
  1447. echo 4 > _shar_seq_.tmp
  1448. exit 0
  1449.  
  1450. exit 0 # Just in case...
  1451. -- 
  1452. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1453. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1454. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1455. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1456.