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

  1. Newsgroups: comp.sources.misc
  2. From: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  3. Subject:  v19i023:  dmake - dmake version 3.7, Part02/37
  4. Message-ID: <1991May9.192600.23384@sparky.IMD.Sterling.COM>
  5. Date: Thu, 9 May 1991 19:26:00 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7.  
  8. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  9. Posting-number: Volume 19, Issue 23
  10. Archive-name: dmake/part02
  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.02 (part 2 of a multipart archive)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file dmake/dag.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" != 2; 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/dag.c' &&
  33. X      switch( *rp++ )
  34. X      {
  35. X     case '@' : flag |= A_SILENT; break;
  36. X     case '-' : flag |= A_IGNORE; break;
  37. X     case '+' : flag |= A_SHELL;  break;
  38. X     case '%' : flag |= A_SWAP;   break;
  39. X
  40. X     case ' ' :
  41. X     case '\t': break;
  42. X
  43. X     default: done = TRUE; break;
  44. X      }
  45. X
  46. X   return(flag);
  47. }
  48. SHAR_EOF
  49. chmod 0640 dmake/dag.c ||
  50. echo 'restore of dmake/dag.c failed'
  51. Wc_c="`wc -c < 'dmake/dag.c'`"
  52. test 13797 -eq "$Wc_c" ||
  53.     echo 'dmake/dag.c: original size 13797, current size' "$Wc_c"
  54. rm -f _shar_wnt_.tmp
  55. fi
  56. # ============= dmake/db.h ==============
  57. if test -f 'dmake/db.h' -a X"$1" != X"-c"; then
  58.     echo 'x - skipping dmake/db.h (File already exists)'
  59.     rm -f _shar_wnt_.tmp
  60. else
  61. > _shar_wnt_.tmp
  62. sed 's/^X//' << 'SHAR_EOF' > 'dmake/db.h' &&
  63. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/db.h,v 1.1 91/05/06 15:23:05 dvadura Exp $
  64. -- SYNOPSIS -- front end to DBUG macros.
  65. -- 
  66. -- DESCRIPTION
  67. --    This is a front end to Fred Fish's DBUG macros.  The intent was
  68. --    to provide an interface so that if you don't have the DBUG code
  69. --    you can still compile dmake, by undefining DBUG, if you do have
  70. --    the code then you can use Fred Fish's DBUG package.  Originally
  71. --    the DBUG stuff was copyrighted, it is now in the public domain
  72. --    so the need for this is not as apparent.
  73. -- 
  74. -- AUTHOR
  75. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  76. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  77. --
  78. -- COPYRIGHT
  79. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  80. -- 
  81. --      This program is free software; you can redistribute it and/or
  82. --      modify it under the terms of the GNU General Public License
  83. --      (version 1), as published by the Free Software Foundation, and
  84. --      found in the file 'LICENSE' included with this distribution.
  85. -- 
  86. --      This program is distributed in the hope that it will be useful,
  87. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  88. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  89. --      GNU General Public License for more details.
  90. -- 
  91. --      You should have received a copy of the GNU General Public License
  92. --      along with this program;  if not, write to the Free Software
  93. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  94. --
  95. -- LOG
  96. --     $Log:    db.h,v $
  97. X * Revision 1.1  91/05/06  15:23:05  dvadura
  98. X * dmake Release Version 3.7
  99. X * 
  100. */
  101. X
  102. #ifndef    DB_h
  103. #define    DB_h
  104. X
  105. #ifdef DBUG
  106. X
  107. #  include "dbug.h"
  108. X
  109. #  define DB_ENTER(a1)                DBUG_ENTER(a1)
  110. #  define DB_RETURN(a1)               DBUG_RETURN(a1)
  111. #  define DB_VOID_RETURN              DBUG_VOID_RETURN
  112. #  define DB_EXECUTE(keyword, a1)     DBUG_EXECUTE(keyword,a1)
  113. #  define DB_PRINT(keyword,arglist)   DBUG_PRINT(keyword,arglist)
  114. #  define DB_PUSH(a1)                 DBUG_PUSH(a1)
  115. #  define DB_POP()                    DBUG_POP()
  116. #  define DB_PROCESS(a1)              DBUG_PROCESS(a1)
  117. #  define DB_FILE (stderr)            DBUG_FILE(stderr)
  118. #  define DB_SETJMP                   DBUG_SETJMP
  119. #  define DB_LONGJMP                  DBUG_LONGJMP
  120. X
  121. #else
  122. X
  123. #  define DB_ENTER(a1)
  124. #  define DB_RETURN(a1)               return (a1)
  125. #  define DB_VOID_RETURN              return
  126. #  define DB_EXECUTE(keyword, a1)
  127. #  define DB_PRINT(keyword,arglist)
  128. #  define DB_PUSH(a1)
  129. #  define DB_POP()
  130. #  define DB_PROCESS(a1)
  131. #  define DB_FILE(stderr)
  132. #  define DB_SETJMP                   setjmp
  133. #  define DB_LONGJMP                  longjmp
  134. X
  135. #endif
  136. #endif
  137. X
  138. SHAR_EOF
  139. chmod 0640 dmake/db.h ||
  140. echo 'restore of dmake/db.h failed'
  141. Wc_c="`wc -c < 'dmake/db.h'`"
  142. test 2696 -eq "$Wc_c" ||
  143.     echo 'dmake/db.h: original size 2696, current size' "$Wc_c"
  144. rm -f _shar_wnt_.tmp
  145. fi
  146. # ============= dmake/dbug/README ==============
  147. if test ! -d 'dmake/dbug'; then
  148.     mkdir 'dmake/dbug'
  149. fi
  150. if test -f 'dmake/dbug/README' -a X"$1" != X"-c"; then
  151.     echo 'x - skipping dmake/dbug/README (File already exists)'
  152.     rm -f _shar_wnt_.tmp
  153. else
  154. > _shar_wnt_.tmp
  155. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/README' &&
  156. This directory contains two public domain debugging packages.
  157. X
  158. X    1. Fred Fishes DEBUG macros.
  159. X    2. Connor P. Cahills malloc library.
  160. X
  161. Descriptions of both can be found in their respective sub-directories.  dbug
  162. for the DEBUG macros and malloc for the malloc library.  I have left the
  163. malloc distribution intact as it comes from the net except for the changes
  164. noted in the _changes file.
  165. X
  166. I thank the authors for making them available for others to use.
  167. X
  168. -dennis
  169. SHAR_EOF
  170. chmod 0640 dmake/dbug/README ||
  171. echo 'restore of dmake/dbug/README failed'
  172. Wc_c="`wc -c < 'dmake/dbug/README'`"
  173. test 460 -eq "$Wc_c" ||
  174.     echo 'dmake/dbug/README: original size 460, current size' "$Wc_c"
  175. rm -f _shar_wnt_.tmp
  176. fi
  177. # ============= dmake/dbug/dbug.mk ==============
  178. if test -f 'dmake/dbug/dbug.mk' -a X"$1" != X"-c"; then
  179.     echo 'x - skipping dmake/dbug/dbug.mk (File already exists)'
  180.     rm -f _shar_wnt_.tmp
  181. else
  182. > _shar_wnt_.tmp
  183. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug.mk' &&
  184. # Set the proper macros based on whether we are making the debugging version
  185. # or not.  The valid parameters to this file are:
  186. #
  187. #    DEBUG=1        ==> enable the making of the DBUG version
  188. #    DBMALLOC=1    ==> enable DBUG version with extensive MALLOC checking
  189. #
  190. #    DB_CFLAGS    ==> CFLAGS is set to this value at the end if DEBUG=1
  191. #    DB_LDFLAGS    ==> LDFLAGS is set to this at the end if DEBUG=1
  192. #    DB_LDLIBS       ==> LDLIBS is set to this at end if DEBUG=1
  193. #
  194. # The non debug versions of the above three macros are:
  195. #
  196. #    NDB_CFLAGS
  197. #    NDB_LDFLAGS
  198. #    NDB_LDLIBS
  199. #
  200. # One of the set of three should have values set appropriately prior to
  201. # sourcing this file.
  202. X
  203. .IF $(DEBUG)
  204. X   DBUG_SRC    += dbug.c
  205. X   DB_CFLAGS    += -Idbug/dbug
  206. X
  207. X   .SETDIR=dbug/dbug : $(DBUG_SRC)
  208. X
  209. X   # If DBMALLOC is requested (ie non-NULL) then include the sources for
  210. X   # compilation.  BSD 4.3 needs the getwd.c source compiled in due to a bug
  211. X   # in the clib getwd routine.
  212. X   .IF $(DBMALLOC)
  213. X      # Serious bug in bsd43 getwd.c would free a string and then use its
  214. X      # value.  The DBMALLOC code clears a string when it is free'd so the
  215. X      # value was no longer valid and the returned path for the current
  216. X      # directory was now completely wrong.
  217. X      .IF $(OSRELEASE) == bsd43
  218. X     GETWD_SRC += getwd.c
  219. X     .SETDIR=dbug : $(GETWD_SRC)
  220. X      .END
  221. X
  222. X      MLC_SRC   += malloc.c free.c realloc.c calloc.c string.c\
  223. X           mlc_chk.c mlc_chn.c memory.c tostring.c m_perror.c\
  224. X           m_init.c mallopt.c dump.c
  225. X
  226. X      .SETDIR=dbug/malloc : $(MLC_SRC)
  227. X
  228. X      DB_CFLAGS += -Idbug/malloc
  229. X   .END
  230. X
  231. X   SRC          += $(DBUG_SRC) $(MLC_SRC) $(GETWD_SRC)
  232. X   HDR        += db.h 
  233. X
  234. X   LDFLAGS    += $(DB_LDFLAGS)
  235. X   LDLIBS    += $(DB_LDLIBS)
  236. X
  237. X   SILENT    := $(.SILENT)
  238. X   .SILENT    := yes
  239. X   TARGET    := db$(TARGET)
  240. X   OBJDIR    := $(OBJDIR).dbg
  241. X   .SILENT    := $(SILENT)
  242. X
  243. X   CFLAGS    += $(DB_CFLAGS)
  244. X   .KEEP_STATE  := _dbstate.mk
  245. .ELSE
  246. X   CFLAGS       += $(NDB_CFLAGS)
  247. X   LDFLAGS      += $(NDB_LDFLAGS)
  248. X   LDLIBS       += $(NDB_LDLIBS)
  249. .END
  250. SHAR_EOF
  251. chmod 0640 dmake/dbug/dbug.mk ||
  252. echo 'restore of dmake/dbug/dbug.mk failed'
  253. Wc_c="`wc -c < 'dmake/dbug/dbug.mk'`"
  254. test 1955 -eq "$Wc_c" ||
  255.     echo 'dmake/dbug/dbug.mk: original size 1955, current size' "$Wc_c"
  256. rm -f _shar_wnt_.tmp
  257. fi
  258. # ============= dmake/dbug/dbug/dbug.c ==============
  259. if test ! -d 'dmake/dbug/dbug'; then
  260.     mkdir 'dmake/dbug/dbug'
  261. fi
  262. if test -f 'dmake/dbug/dbug/dbug.c' -a X"$1" != X"-c"; then
  263.     echo 'x - skipping dmake/dbug/dbug/dbug.c (File already exists)'
  264.     rm -f _shar_wnt_.tmp
  265. else
  266. > _shar_wnt_.tmp
  267. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.c' &&
  268. /******************************************************************************
  269. X *                                          *
  270. X *                               N O T I C E                      *
  271. X *                                          *
  272. X *                  Copyright Abandoned, 1987, Fred Fish              *
  273. X *                                          *
  274. X *                                          *
  275. X *    This previously copyrighted work has been placed into the  public     *
  276. X *    domain  by  the  author  and  may be freely used for any purpose,     *
  277. X *    private or commercial.                              *
  278. X *                                          *
  279. X *    Because of the number of inquiries I was receiving about the  use     *
  280. X *    of this product in commercially developed works I have decided to     *
  281. X *    simply make it public domain to further its unrestricted use.   I     *
  282. X *    specifically  would  be  most happy to see this material become a     *
  283. X *    part of the standard Unix distributions by AT&T and the  Berkeley     *
  284. X *    Computer  Science  Research Group, and a standard part of the GNU     *
  285. X *    system from the Free Software Foundation.                  *
  286. X *                                          *
  287. X *    I would appreciate it, as a courtesy, if this notice is  left  in     *
  288. X *    all copies and derivative works.  Thank you.                  *
  289. X *                                          *
  290. X *    The author makes no warranty of any kind  with  respect  to  this     *
  291. X *    product  and  explicitly disclaims any implied warranties of mer-     *
  292. X *    chantability or fitness for any particular purpose.              *
  293. X *                                          *
  294. X ******************************************************************************
  295. X */
  296. X
  297. X
  298. /*
  299. X *  FILE
  300. X *
  301. X *    dbug.c   runtime support routines for dbug package
  302. X *
  303. X *  SCCS
  304. X *
  305. X *    @(#)dbug.c    1.19 9/5/87
  306. X *
  307. X *  DESCRIPTION
  308. X *
  309. X *    These are the runtime support routines for the dbug package.
  310. X *    The dbug package has two main components; the user include
  311. X *    file containing various macro definitions, and the runtime
  312. X *    support routines which are called from the macro expansions.
  313. X *
  314. X *    Externally visible functions in the runtime support module
  315. X *    use the naming convention pattern "_db_xx...xx_", thus
  316. X *    they are unlikely to collide with user defined function names.
  317. X *
  318. X *  AUTHOR(S)
  319. X *
  320. X *    Fred Fish        (base code)
  321. X *    (Currently at Motorola Computer Division, Tempe, Az.)
  322. X *    hao!noao!mcdsun!fnf
  323. X *    (602) 438-3614
  324. X *
  325. X *    Binayak Banerjee    (profiling enhancements)
  326. X *    seismo!bpa!sjuvax!bbanerje
  327. X */
  328. X
  329. X
  330. #include <stdio.h>
  331. #ifdef amiga
  332. #define AMIGA
  333. #endif
  334. X
  335. #ifdef AMIGA
  336. #define HZ (50)            /* Probably in some header somewhere */
  337. #endif
  338. X
  339. /*
  340. X *    Manifest constants that should not require any changes.
  341. X */
  342. X
  343. #define FALSE        0    /* Boolean FALSE */
  344. #define TRUE        1    /* Boolean TRUE */
  345. #define EOS        '\000'    /* End Of String marker */
  346. X
  347. /*
  348. X *    Manifest constants which may be "tuned" if desired.
  349. X */
  350. X
  351. #define PRINTBUF    1024    /* Print buffer size */
  352. #define INDENT        4    /* Indentation per trace level */
  353. #define MAXDEPTH    200    /* Maximum trace depth default */
  354. X
  355. /*
  356. X *    The following flags are used to determine which
  357. X *    capabilities the user has enabled with the state
  358. X *    push macro.
  359. X */
  360. X
  361. #define TRACE_ON    000001    /* Trace enabled */
  362. #define DEBUG_ON    000002    /* Debug enabled */
  363. #define FILE_ON     000004    /* File name print enabled */
  364. #define LINE_ON        000010    /* Line number print enabled */
  365. #define DEPTH_ON    000020    /* Function nest level print enabled */
  366. #define PROCESS_ON    000040    /* Process name print enabled */
  367. #define NUMBER_ON    000100    /* Number each line of output */
  368. #define PROFILE_ON    000200    /* Print out profiling code */
  369. X
  370. #define TRACING (stack -> flags & TRACE_ON)
  371. #define DEBUGGING (stack -> flags & DEBUG_ON)
  372. #define PROFILING (stack -> flags & PROFILE_ON)
  373. #define STREQ(a,b) (strcmp(a,b) == 0)
  374. X
  375. /*
  376. X *    Typedefs to make things more obvious.
  377. X */
  378. X
  379. #define VOID void        /* Can't use typedef for most compilers */
  380. typedef int BOOLEAN;
  381. X
  382. /*
  383. X *    Make it easy to change storage classes if necessary.
  384. X */
  385. X
  386. #define LOCAL static        /* Names not needed by outside world */
  387. #define IMPORT extern        /* Names defined externally */
  388. #define EXPORT            /* Allocated here, available globally */
  389. #define AUTO auto        /* Names to be allocated on stack */
  390. #define REGISTER register    /* Names to be placed in registers */
  391. X
  392. /*
  393. X *    The following define is for the variable arguments kluge, see
  394. X *    the comments in _db_doprnt_().
  395. X *
  396. X *    Also note that the longer this list, the less prone to failing
  397. X *    on long argument lists, but the more stuff that must be moved
  398. X *    around for each call to the runtime support routines.  The
  399. X *    length may really be critical if the machine convention is
  400. X *    to pass arguments in registers.
  401. X *
  402. X *    Note that the default define allows up to 16 integral arguments,
  403. X *    or 8 floating point arguments (doubles), on most machines.
  404. X *
  405. X *    Someday this may be replaced with true varargs support, when
  406. X *    ANSI C has had time to take root.
  407. X */
  408. X
  409. #define ARGLIST a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15
  410. X
  411. /*
  412. X * The default file for profiling.  Could also add another flag
  413. X * (G?) which allowed the user to specify this.
  414. X */
  415. X
  416. #define PROF_FILE    "dbugmon.out"
  417. X
  418. /*
  419. X *    Variables which are available externally but should only
  420. X *    be accessed via the macro package facilities.
  421. X */
  422. X
  423. EXPORT FILE *_db_fp_ = stderr;        /* Output stream, default stderr */
  424. EXPORT FILE *_db_pfp_ = (FILE *)0;    /* Profile stream, 'dbugmon.out' */
  425. EXPORT char *_db_process_ = "dbug";    /* Pointer to process name; argv[0] */
  426. EXPORT BOOLEAN _db_on_ = FALSE;        /* TRUE if debugging currently on */
  427. EXPORT BOOLEAN _db_pon_ = FALSE;    /* TRUE if debugging currently on */
  428. X
  429. /*
  430. X *    Externally supplied functions.
  431. X */
  432. X
  433. #ifdef unix            /* Only needed for unix */
  434. IMPORT VOID perror ();        /* Print system/library error */
  435. IMPORT int chown ();        /* Change owner of a file */
  436. IMPORT int getgid ();        /* Get real group id */
  437. IMPORT int getuid ();        /* Get real user id */
  438. IMPORT int access ();        /* Test file for access */
  439. #else
  440. #if !(AMIGA || LATTICE || __TURBOC__)
  441. LOCAL VOID perror ();        /* Fake system/library error print routine */
  442. #endif
  443. #endif
  444. X
  445. # if BSD4_3 || sun
  446. IMPORT int getrusage ();
  447. #endif
  448. X
  449. IMPORT int atoi ();        /* Convert ascii to integer */
  450. IMPORT VOID exit ();        /* Terminate execution */
  451. IMPORT int fclose ();        /* Close a stream */
  452. IMPORT FILE *fopen ();        /* Open a stream */
  453. #if !defined(__BORLANDC__)
  454. IMPORT int fprintf ();        /* Formatted print on file */
  455. #endif
  456. IMPORT VOID free ();
  457. IMPORT char *malloc ();        /* Allocate memory */
  458. IMPORT int strcmp ();        /* Compare strings */
  459. IMPORT char *strcpy ();        /* Copy strings around */
  460. IMPORT int strlen ();        /* Find length of string */
  461. X
  462. #ifndef fflush            /* This is sometimes a macro */
  463. IMPORT int fflush ();        /* Flush output for stream */
  464. #endif
  465. X
  466. X
  467. /*
  468. X *    The user may specify a list of functions to trace or 
  469. X *    debug.  These lists are kept in a linear linked list,
  470. X *    a very simple implementation.
  471. X */
  472. X
  473. struct link {
  474. X    char *string;        /* Pointer to link's contents */
  475. X    struct link *next_link;    /* Pointer to the next link */
  476. };
  477. X
  478. X
  479. /*
  480. X *    Debugging states can be pushed or popped off of a
  481. X *    stack which is implemented as a linked list.  Note
  482. X *    that the head of the list is the current state and the
  483. X *    stack is pushed by adding a new state to the head of the
  484. X *    list or popped by removing the first link.
  485. X */
  486. X
  487. struct state {
  488. X    int flags;                /* Current state flags */
  489. X    int maxdepth;            /* Current maximum trace depth */
  490. X    unsigned int delay;            /* Delay after each output line */
  491. X    int level;                /* Current function nesting level */
  492. X    FILE *out_file;            /* Current output stream */
  493. X    FILE *prof_file;            /* Current profiling stream */
  494. X    struct link *functions;        /* List of functions */
  495. X    struct link *p_functions;        /* List of profiled functions */
  496. X    struct link *keywords;        /* List of debug keywords */
  497. X    struct link *processes;        /* List of process names */
  498. X    struct state *next_state;        /* Next state in the list */
  499. };
  500. X
  501. LOCAL struct state *stack = NULL;    /* Linked list of stacked states */
  502. X
  503. /*
  504. X *    Local variables not seen by user.
  505. X */
  506. X
  507. LOCAL int lineno = 0;        /* Current debugger output line number */
  508. LOCAL char *func = "?func";    /* Name of current user function */
  509. LOCAL char *file = "?file";    /* Name of current user file */
  510. LOCAL BOOLEAN init_done = FALSE;/* Set to TRUE when initialization done */
  511. X
  512. /*#if unix || AMIGA || M_I86*/
  513. LOCAL int jmplevel;        /* Remember nesting level at setjmp () */
  514. LOCAL char *jmpfunc;        /* Remember current function for setjmp */
  515. LOCAL char *jmpfile;        /* Remember current file for setjmp */
  516. /*#endif*/
  517. X
  518. LOCAL struct link *ListParse ();/* Parse a debug command string */
  519. LOCAL char *StrDup ();        /* Make a fresh copy of a string */
  520. LOCAL VOID OpenFile ();        /* Open debug output stream */
  521. LOCAL VOID OpenProfile ();    /* Open profile output stream */
  522. LOCAL VOID CloseFile ();    /* Close debug output stream */
  523. LOCAL VOID PushState ();    /* Push current debug state */
  524. LOCAL VOID ChangeOwner ();    /* Change file owner and group */
  525. LOCAL BOOLEAN DoTrace ();    /* Test for tracing enabled */
  526. LOCAL BOOLEAN Writable ();    /* Test to see if file is writable */
  527. LOCAL unsigned long Clock ();    /* Return current user time (ms) */
  528. LOCAL char *DbugMalloc ();    /* Allocate memory for runtime support */
  529. LOCAL char *BaseName ();    /* Remove leading pathname components */
  530. LOCAL VOID DoPrefix ();        /* Print debugger line prefix */
  531. LOCAL VOID FreeList ();        /* Free memory from linked list */
  532. LOCAL VOID Indent ();        /* Indent line to specified indent */
  533. X
  534. X                /* Supplied in Sys V runtime environ */
  535. LOCAL char *strtok ();        /* Break string into tokens */
  536. LOCAL char *strrchr ();        /* Find last occurance of char */
  537. X
  538. /*
  539. X *    The following local variables are used to hold the state information
  540. X *    between the call to _db_pargs_() and _db_doprnt_(), during
  541. X *    expansion of the DBUG_PRINT macro.  This is the only macro
  542. X *    that currently uses these variables.  The DBUG_PRINT macro
  543. X *    and the new _db_doprnt_() routine replace the older DBUG_N macros
  544. X *    and their corresponding runtime support routine _db_printf_().
  545. X *
  546. X *    These variables are currently used only by _db_pargs_() and
  547. X *    _db_doprnt_().
  548. X */
  549. X
  550. LOCAL int u_line = 0;        /* User source code line number */
  551. LOCAL char *u_keyword = "?";    /* Keyword for current macro */
  552. X
  553. /*
  554. X *    Miscellaneous printf format strings.
  555. X */
  556. #define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
  557. #define ERR_OPEN "%s: can't open debug output stream \"%s\": "
  558. #define ERR_CLOSE "%s: can't close debug file: "
  559. #define ERR_ABORT "%s: debugger aborting because %s\n"
  560. #define ERR_CHOWN "%s: can't change owner/group of \"%s\": "
  561. #define ERR_PRINTF "%s: obsolete object file for '%s', please recompile!\n"
  562. X
  563. /*
  564. X *    Macros and defines for testing file accessibility under UNIX.
  565. X */
  566. X
  567. #ifdef unix
  568. #  define A_EXISTS    00        /* Test for file existance */
  569. #  define A_EXECUTE    01        /* Test for execute permission */
  570. #  define A_WRITE    02        /* Test for write access */
  571. #  define A_READ    03        /* Test for read access */
  572. #  define EXISTS(pathname) (access (pathname, A_EXISTS) == 0)
  573. #  define WRITABLE(pathname) (access (pathname, A_WRITE) == 0)
  574. #else
  575. #  define EXISTS(pathname) (FALSE)    /* Assume no existance */
  576. #endif
  577. X
  578. /*
  579. X *    Translate some calls among different systems.
  580. X */
  581. X
  582. #ifdef unix
  583. # define XDelay sleep
  584. IMPORT unsigned int sleep ();    /* Pause for given number of seconds */
  585. #endif
  586. X
  587. #ifdef AMIGA
  588. IMPORT int XDelay ();        /* Pause for given number of ticks */
  589. #endif
  590. X
  591. X
  592. /*
  593. X *  FUNCTION
  594. X *
  595. X *    _db_push_    push current debugger state and set up new one
  596. X *
  597. X *  SYNOPSIS
  598. X *
  599. X *    VOID _db_push_ (control)
  600. X *    char *control;
  601. X *
  602. X *  DESCRIPTION
  603. X *
  604. X *    Given pointer to a debug control string in "control", pushes
  605. X *    the current debug state, parses the control string, and sets
  606. X *    up a new debug state.
  607. X *
  608. X *    The only attribute of the new state inherited from the previous
  609. X *    state is the current function nesting level.  This can be
  610. X *    overridden by using the "r" flag in the control string.
  611. X *
  612. X *    The debug control string is a sequence of colon separated fields
  613. X *    as follows:
  614. X *
  615. X *        <field_1>:<field_2>:...:<field_N>
  616. X *
  617. X *    Each field consists of a mandatory flag character followed by
  618. X *    an optional "," and comma separated list of modifiers:
  619. X *
  620. X *        flag[,modifier,modifier,...,modifier]
  621. X *
  622. X *    The currently recognized flag characters are:
  623. X *
  624. X *        d    Enable output from DBUG_<N> macros for
  625. X *            for the current state.  May be followed
  626. X *            by a list of keywords which selects output
  627. X *            only for the DBUG macros with that keyword.
  628. X *            A null list of keywords implies output for
  629. X *            all macros.
  630. X *
  631. X *        D    Delay after each debugger output line.
  632. X *            The argument is the number of tenths of seconds
  633. X *            to delay, subject to machine capabilities.
  634. X *            I.E.  -#D,20 is delay two seconds.
  635. X *
  636. X *        f    Limit debugging and/or tracing, and profiling to the
  637. X *            list of named functions.  Note that a null list will
  638. X *            disable all functions.  The appropriate "d" or "t"
  639. X *            flags must still be given, this flag only limits their
  640. X *            actions if they are enabled.
  641. X *
  642. X *        F    Identify the source file name for each
  643. X *            line of debug or trace output.
  644. X *
  645. X *        g    Enable profiling.  Create a file called 'dbugmon.out'
  646. X *            containing information that can be used to profile
  647. X *            the program.  May be followed by a list of keywords
  648. X *            that select profiling only for the functions in that
  649. X *            list.  A null list implies that all functions are
  650. X *            considered.
  651. X *
  652. X *        L    Identify the source file line number for
  653. X *            each line of debug or trace output.
  654. X *
  655. X *        n    Print the current function nesting depth for
  656. X *            each line of debug or trace output.
  657. X *    
  658. X *        N    Number each line of dbug output.
  659. X *
  660. X *        p    Limit debugger actions to specified processes.
  661. X *            A process must be identified with the
  662. X *            DBUG_PROCESS macro and match one in the list
  663. X *            for debugger actions to occur.
  664. X *
  665. X *        P    Print the current process name for each
  666. X *            line of debug or trace output.
  667. X *
  668. X *        r    When pushing a new state, do not inherit
  669. X *            the previous state's function nesting level.
  670. X *            Useful when the output is to start at the
  671. X *            left margin.
  672. X *
  673. X *        t    Enable function call/exit trace lines.
  674. X *            May be followed by a list (containing only
  675. X *            one modifier) giving a numeric maximum
  676. X *            trace level, beyond which no output will
  677. X *            occur for either debugging or tracing
  678. X *            macros.  The default is a compile time
  679. X *            option.
  680. X *
  681. X *    Some examples of debug control strings which might appear
  682. X *    on a shell command line (the "-#" is typically used to
  683. X *    introduce a control string to an application program) are:
  684. X *
  685. X *        -#d:t
  686. X *        -#d:f,main,subr1:F:L:t,20
  687. X *        -#d,input,output,files:n
  688. X *
  689. X *    For convenience, any leading "-#" is stripped off.
  690. X *
  691. X */
  692. X
  693. X
  694. VOID _db_push_ (control)
  695. char *control;
  696. {
  697. X    REGISTER char *scan;
  698. X    REGISTER struct link *temp;
  699. X
  700. X    if (control && *control == '-') {
  701. X    if (*++control == '#') {
  702. X        control++;
  703. X    }    
  704. X    }
  705. X    control = StrDup (control);
  706. X    PushState ();
  707. X    scan = strtok (control, ":");
  708. X    for (; scan != NULL; scan = strtok ((char *)NULL, ":")) {
  709. X    switch (*scan++) {
  710. X        case 'd': 
  711. X        _db_on_ = TRUE;
  712. X        stack -> flags |= DEBUG_ON;
  713. X        if (*scan++ == ',') {
  714. X            stack -> keywords = ListParse (scan);
  715. X        }
  716. X            break;
  717. X        case 'D': 
  718. X        stack -> delay = 0;
  719. X        if (*scan++ == ',') {
  720. X            temp = ListParse (scan);
  721. X            stack -> delay = DelayArg (atoi (temp -> string));
  722. X            FreeList (temp);
  723. X        }
  724. X        break;
  725. X        case 'f': 
  726. X        if (*scan++ == ',') {
  727. X            stack -> functions = ListParse (scan);
  728. X        }
  729. X        break;
  730. X        case 'F': 
  731. X        stack -> flags |= FILE_ON;
  732. X        break;
  733. X        case 'g': 
  734. X        _db_pon_ = TRUE;
  735. X        OpenProfile(PROF_FILE);
  736. X        stack -> flags |= PROFILE_ON;
  737. X        if (*scan++ == ',') {
  738. X            stack -> p_functions = ListParse (scan);
  739. X        }
  740. X        break;
  741. X        case 'L': 
  742. X        stack -> flags |= LINE_ON;
  743. X        break;
  744. X        case 'n': 
  745. X        stack -> flags |= DEPTH_ON;
  746. X        break;
  747. X        case 'N':
  748. X        stack -> flags |= NUMBER_ON;
  749. X        break;
  750. X        case 'o': 
  751. X        if (*scan++ == ',') {
  752. X            temp = ListParse (scan);
  753. X            OpenFile (temp -> string);
  754. X            FreeList (temp);
  755. X        } else {
  756. X            OpenFile ("-");
  757. X        }
  758. X        break;
  759. X        case 'p':
  760. X        if (*scan++ == ',') {
  761. X            stack -> processes = ListParse (scan);
  762. X        }
  763. X        break;
  764. X        case 'P': 
  765. X        stack -> flags |= PROCESS_ON;
  766. X        break;
  767. X        case 'r': 
  768. X        stack -> level = 0;
  769. X        break;
  770. X        case 't': 
  771. X        stack -> flags |= TRACE_ON;
  772. X        if (*scan++ == ',') {
  773. X            temp = ListParse (scan);
  774. X            stack -> maxdepth = atoi (temp -> string);
  775. X            FreeList (temp);
  776. X        }
  777. X        break;
  778. X    }
  779. X    }
  780. X    free (control);
  781. }
  782. X
  783. X
  784. X
  785. /*
  786. X *  FUNCTION
  787. X *
  788. X *    _db_pop_    pop the debug stack
  789. X *
  790. X *  DESCRIPTION
  791. X *
  792. X *    Pops the debug stack, returning the debug state to its
  793. X *    condition prior to the most recent _db_push_ invocation.
  794. X *    Note that the pop will fail if it would remove the last
  795. X *    valid state from the stack.  This prevents user errors
  796. X *    in the push/pop sequence from screwing up the debugger.
  797. X *    Maybe there should be some kind of warning printed if the
  798. X *    user tries to pop too many states.
  799. X *
  800. X */
  801. X
  802. VOID _db_pop_ ()
  803. {
  804. X    REGISTER struct state *discard;
  805. X
  806. X    discard = stack;
  807. X    if (discard != NULL && discard -> next_state != NULL) {
  808. X    stack = discard -> next_state;
  809. X    _db_fp_ = stack -> out_file;
  810. X    _db_pfp_ = stack -> prof_file;
  811. X    if (discard -> keywords != NULL) {
  812. X        FreeList (discard -> keywords);
  813. X    }
  814. X    if (discard -> functions != NULL) {
  815. X        FreeList (discard -> functions);
  816. X    }
  817. X    if (discard -> processes != NULL) {
  818. X        FreeList (discard -> processes);
  819. X    }
  820. X    if (discard -> p_functions != NULL) {
  821. X        FreeList (discard -> p_functions);
  822. X    }
  823. X    CloseFile (discard -> out_file);
  824. X    CloseFile (discard -> prof_file);
  825. X    free ((char *) discard);
  826. X    }
  827. }
  828. X
  829. X
  830. /*
  831. X *  FUNCTION
  832. X *
  833. X *    _db_enter_    process entry point to user function
  834. X *
  835. X *  SYNOPSIS
  836. X *
  837. X *    VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
  838. X *    char *_func_;        points to current function name
  839. X *    char *_file_;        points to current file name
  840. X *    int _line_;        called from source line number
  841. X *    char **_sfunc_;        save previous _func_
  842. X *    char **_sfile_;        save previous _file_
  843. X *    int *_slevel_;        save previous nesting level
  844. X *
  845. X *  DESCRIPTION
  846. X *
  847. X *    Called at the beginning of each user function to tell
  848. X *    the debugger that a new function has been entered.
  849. X *    Note that the pointers to the previous user function
  850. X *    name and previous user file name are stored on the
  851. X *    caller's stack (this is why the ENTER macro must be
  852. X *    the first "executable" code in a function, since it
  853. X *    allocates these storage locations).  The previous nesting
  854. X *    level is also stored on the callers stack for internal
  855. X *    self consistency checks.
  856. X *
  857. X *    Also prints a trace line if tracing is enabled and
  858. X *    increments the current function nesting depth.
  859. X *
  860. X *    Note that this mechanism allows the debugger to know
  861. X *    what the current user function is at all times, without
  862. X *    maintaining an internal stack for the function names.
  863. X *
  864. X */
  865. X
  866. VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
  867. char *_func_;
  868. char *_file_;
  869. int _line_;
  870. char **_sfunc_;
  871. char **_sfile_;
  872. int *_slevel_;
  873. {
  874. X    if (!init_done) {
  875. X    _db_push_ ("");
  876. X    }
  877. X    *_sfunc_ = func;
  878. X    *_sfile_ = file;
  879. X    func = _func_;
  880. X    file = BaseName (_file_);
  881. X    stack -> level++;
  882. X    *_slevel_ = stack -> level;
  883. X    if (DoProfile ()) {
  884. X    (VOID) fprintf (_db_pfp_, "%s\tE\t%ld\n",func, Clock());
  885. X    (VOID) fflush (_db_pfp_);
  886. X    }
  887. X    if (DoTrace ()) {
  888. X    DoPrefix (_line_);
  889. X    Indent (stack -> level);
  890. X    (VOID) fprintf (_db_fp_, ">%s\n", func);
  891. X    (VOID) fflush (_db_fp_);
  892. X    (VOID) XDelay (stack -> delay);
  893. X    }
  894. }
  895. X
  896. X
  897. /*
  898. X *  FUNCTION
  899. X *
  900. X *    _db_return_    process exit from user function
  901. X *
  902. X *  SYNOPSIS
  903. X *
  904. X *    VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
  905. X *    int _line_;        current source line number
  906. X *    char **_sfunc_;        where previous _func_ is to be retrieved
  907. X *    char **_sfile_;        where previous _file_ is to be retrieved
  908. X *    int *_slevel_;        where previous level was stashed
  909. X *
  910. X *  DESCRIPTION
  911. X *
  912. X *    Called just before user function executes an explicit or implicit
  913. X *    return.  Prints a trace line if trace is enabled, decrements
  914. X *    the current nesting level, and restores the current function and
  915. X *    file names from the defunct function's stack.
  916. X *
  917. X */
  918. X
  919. VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
  920. int _line_;
  921. char **_sfunc_;
  922. char **_sfile_;
  923. int *_slevel_;
  924. {
  925. X    if (!init_done) {
  926. X    _db_push_ ("");
  927. X    }
  928. X    if (stack -> level != *_slevel_ && (TRACING || DEBUGGING || PROFILING)) {
  929. X    (VOID) fprintf (_db_fp_, ERR_MISSING_RETURN, _db_process_, func);
  930. X        (VOID) XDelay (stack -> delay);
  931. X    } else if (DoProfile ()) {
  932. X    (VOID) fprintf (_db_pfp_, "%s\tX\t%ld\n", func, Clock());
  933. X        (VOID) XDelay (stack -> delay);
  934. X    } else if (DoTrace ()) {
  935. X    DoPrefix (_line_);
  936. X    Indent (stack -> level);
  937. X    (VOID) fprintf (_db_fp_, "<%s\n", func);
  938. X        (VOID) XDelay (stack -> delay);
  939. X    }
  940. X    (VOID) fflush (_db_fp_);
  941. X    stack -> level = *_slevel_ - 1;
  942. X    func = *_sfunc_;
  943. X    file = *_sfile_;
  944. }
  945. X
  946. X
  947. /*
  948. X *  FUNCTION
  949. X *
  950. X *    _db_pargs_    log arguments for subsequent use by _db_doprnt_()
  951. X *
  952. X *  SYNOPSIS
  953. X *
  954. X *    VOID _db_pargs_ (_line_, keyword)
  955. X *    int _line_;
  956. X *    char *keyword;
  957. X *
  958. X *  DESCRIPTION
  959. X *
  960. X *    The new universal printing macro DBUG_PRINT, which replaces
  961. X *    all forms of the DBUG_N macros, needs two calls to runtime
  962. X *    support routines.  The first, this function, remembers arguments
  963. X *    that are used by the subsequent call to _db_doprnt_().
  964. *
  965. X */
  966. X
  967. VOID _db_pargs_ (_line_, keyword)
  968. int _line_;
  969. char *keyword;
  970. {
  971. X    u_line = _line_;
  972. X    u_keyword = keyword;
  973. }
  974. X
  975. X
  976. /*
  977. X *  FUNCTION
  978. X *
  979. X *    _db_doprnt_    handle print of debug lines
  980. X *
  981. X *  SYNOPSIS
  982. X *
  983. X *    VOID _db_doprnt_ (format, ARGLIST)
  984. X *    char *format;
  985. X *    long ARGLIST;
  986. X *
  987. X *  DESCRIPTION
  988. X *
  989. X *    When invoked via one of the DBUG macros, tests the current keyword
  990. X *    set by calling _db_pargs_() to see if that macro has been selected
  991. X *    for processing via the debugger control string, and if so, handles
  992. X *    printing of the arguments via the format string.  The line number
  993. X *    of the DBUG macro in the source is found in u_line.
  994. X *
  995. X *    Note that the format string SHOULD NOT include a terminating
  996. X *    newline, this is supplied automatically.
  997. X *
  998. X *  NOTES
  999. X *
  1000. X *    This runtime support routine replaces the older _db_printf_()
  1001. X *    routine which is temporarily kept around for compatibility.
  1002. X *
  1003. X *    The rather ugly argument declaration is to handle some
  1004. X *    magic with respect to the number of arguments passed
  1005. X *    via the DBUG macros.  The current maximum is 3 arguments
  1006. X *    (not including the keyword and format strings).
  1007. X *
  1008. X *    The new <varargs.h> facility is not yet common enough to
  1009. X *    convert to it quite yet...
  1010. X *
  1011. X */
  1012. X
  1013. /*VARARGS1*/
  1014. VOID _db_doprnt_ (format, ARGLIST)
  1015. char *format;
  1016. long ARGLIST;
  1017. {
  1018. X    if (_db_keyword_ (u_keyword)) {
  1019. X    DoPrefix (u_line);
  1020. X    if (TRACING) {
  1021. X        Indent (stack -> level + 1);
  1022. X    } else {
  1023. X        (VOID) fprintf (_db_fp_, "%s: ", func);
  1024. X    }
  1025. X    (VOID) fprintf (_db_fp_, "%s: ", u_keyword);
  1026. X    (VOID) fprintf (_db_fp_, format, ARGLIST);
  1027. X    (VOID) fprintf (_db_fp_, "\n");
  1028. X    (VOID) fflush (_db_fp_);
  1029. X    (VOID) XDelay (stack -> delay);
  1030. X    }
  1031. }
  1032. X
  1033. /*
  1034. X *    The following routine is kept around temporarily for compatibility
  1035. X *    with older objects that were compiled with the DBUG_N macro form
  1036. X *    of the print routine.  It will print a warning message on first
  1037. X *    usage.  It will go away in subsequent releases...
  1038. X */
  1039. X
  1040. /*VARARGS3*/
  1041. VOID _db_printf_ (_line_, keyword, format, ARGLIST)
  1042. int _line_;
  1043. char *keyword,  *format;
  1044. long ARGLIST;
  1045. {
  1046. X    static BOOLEAN firsttime = TRUE;
  1047. X
  1048. X    if (firsttime) {
  1049. X    (VOID) fprintf (stderr, ERR_PRINTF, _db_process_, file);
  1050. X    firsttime = FALSE;
  1051. X    }
  1052. X    _db_pargs_ (_line_, keyword);
  1053. X    _db_doprnt_ (format, ARGLIST);
  1054. }
  1055. X
  1056. X
  1057. /*
  1058. X *  FUNCTION
  1059. X *
  1060. X *    ListParse    parse list of modifiers in debug control string
  1061. X *
  1062. X *  SYNOPSIS
  1063. X *
  1064. X *    LOCAL struct link *ListParse (ctlp)
  1065. X *    char *ctlp;
  1066. X *
  1067. X *  DESCRIPTION
  1068. X *
  1069. X *    Given pointer to a comma separated list of strings in "cltp",
  1070. X *    parses the list, building a list and returning a pointer to it.
  1071. X *    The original comma separated list is destroyed in the process of
  1072. X *    building the linked list, thus it had better be a duplicate
  1073. X *    if it is important.
  1074. X *
  1075. X *    Note that since each link is added at the head of the list,
  1076. X *    the final list will be in "reverse order", which is not
  1077. X *    significant for our usage here.
  1078. X *
  1079. X */
  1080. X
  1081. LOCAL struct link *ListParse (ctlp)
  1082. char *ctlp;
  1083. {
  1084. X    REGISTER char *start;
  1085. X    REGISTER struct link *new;
  1086. X    REGISTER struct link *head;
  1087. X
  1088. X    head = NULL;
  1089. X    while (*ctlp != EOS) {
  1090. X    start = ctlp;
  1091. X    while (*ctlp != EOS && *ctlp != ',') {
  1092. X        ctlp++;
  1093. X    }
  1094. X    if (*ctlp == ',') {
  1095. X        *ctlp++ = EOS;
  1096. X    }
  1097. X    new = (struct link *) DbugMalloc (sizeof (struct link));
  1098. X    new -> string = StrDup (start);
  1099. X    new -> next_link = head;
  1100. X    head = new;
  1101. X    }
  1102. X    return (head);
  1103. }
  1104. X
  1105. X
  1106. /*
  1107. X *  FUNCTION
  1108. X *
  1109. X *    InList    test a given string for member of a given list
  1110. X *
  1111. X *  SYNOPSIS
  1112. X *
  1113. X *    LOCAL BOOLEAN InList (linkp, cp)
  1114. X *    struct link *linkp;
  1115. X *    char *cp;
  1116. X *
  1117. X *  DESCRIPTION
  1118. X *
  1119. X *    Tests the string pointed to by "cp" to determine if it is in
  1120. X *    the list pointed to by "linkp".  Linkp points to the first
  1121. X *    link in the list.  If linkp is NULL then the string is treated
  1122. X *    as if it is in the list (I.E all strings are in the null list).
  1123. X *    This may seem rather strange at first but leads to the desired
  1124. X *    operation if no list is given.  The net effect is that all
  1125. X *    strings will be accepted when there is no list, and when there
  1126. X *    is a list, only those strings in the list will be accepted.
  1127. X *
  1128. X */
  1129. X
  1130. LOCAL BOOLEAN InList (linkp, cp)
  1131. struct link *linkp;
  1132. char *cp;
  1133. {
  1134. X    REGISTER struct link *scan;
  1135. X    REGISTER BOOLEAN accept;
  1136. X
  1137. X    if (linkp == NULL) {
  1138. X    accept = TRUE;
  1139. X    } else {
  1140. X    accept = FALSE;
  1141. X    for (scan = linkp; scan != NULL; scan = scan -> next_link) {
  1142. X        if (STREQ (scan -> string, cp)) {
  1143. X        accept = TRUE;
  1144. X        break;
  1145. X        }
  1146. X    }
  1147. X    }
  1148. X    return (accept);
  1149. }
  1150. X
  1151. X
  1152. /*
  1153. X *  FUNCTION
  1154. X *
  1155. X *    PushState    push current state onto stack and set up new one
  1156. X *
  1157. X *  SYNOPSIS
  1158. X *
  1159. X *    LOCAL VOID PushState ()
  1160. X *
  1161. X *  DESCRIPTION
  1162. X *
  1163. X *    Pushes the current state on the state stack, and initializes
  1164. X *    a new state.  The only parameter inherited from the previous
  1165. X *    state is the function nesting level.  This action can be
  1166. X *    inhibited if desired, via the "r" flag.
  1167. X *
  1168. X *    The state stack is a linked list of states, with the new
  1169. X *    state added at the head.  This allows the stack to grow
  1170. X *    to the limits of memory if necessary.
  1171. X *
  1172. X */
  1173. X
  1174. LOCAL VOID PushState ()
  1175. {
  1176. X    REGISTER struct state *new;
  1177. X
  1178. X    new = (struct state *) DbugMalloc (sizeof (struct state));
  1179. X    new -> flags = 0;
  1180. X    new -> delay = 0;
  1181. X    new -> maxdepth = MAXDEPTH;
  1182. X    if (stack != NULL) {
  1183. X    new -> level = stack -> level;
  1184. X    } else {
  1185. X    new -> level = 0;
  1186. X    }
  1187. X    new -> out_file = stderr;
  1188. X    new -> functions = NULL;
  1189. X    new -> p_functions = NULL;
  1190. X    new -> keywords = NULL;
  1191. X    new -> processes = NULL;
  1192. X    new -> next_state = stack;
  1193. X    stack = new;
  1194. X    init_done = TRUE;
  1195. }
  1196. X
  1197. X
  1198. /*
  1199. X *  FUNCTION
  1200. X *
  1201. X *    DoTrace    check to see if tracing is current enabled
  1202. X *
  1203. X *  SYNOPSIS
  1204. X *
  1205. X *    LOCAL BOOLEAN DoTrace ()
  1206. X *
  1207. X *  DESCRIPTION
  1208. X *
  1209. X *    Checks to see if tracing is enabled based on whether the
  1210. X *    user has specified tracing, the maximum trace depth has
  1211. X *    not yet been reached, the current function is selected,
  1212. X *    and the current process is selected.  Returns TRUE if
  1213. X *    tracing is enabled, FALSE otherwise.
  1214. X *
  1215. X */
  1216. X
  1217. LOCAL BOOLEAN DoTrace ()
  1218. {
  1219. X    REGISTER BOOLEAN trace;
  1220. X
  1221. X    trace = FALSE;
  1222. X    if (TRACING) {
  1223. X    if (stack -> level <= stack -> maxdepth) {
  1224. X        if (InList (stack -> functions, func)) {
  1225. X        if (InList (stack -> processes, _db_process_)) {
  1226. X            trace = TRUE;
  1227. X        }
  1228. X        }
  1229. X    }
  1230. X    }
  1231. X    return (trace);
  1232. }
  1233. X
  1234. X
  1235. /*
  1236. X *  FUNCTION
  1237. X *
  1238. X *    DoProfile    check to see if profiling is current enabled
  1239. X *
  1240. X *  SYNOPSIS
  1241. X *
  1242. X *    LOCAL BOOLEAN DoProfile ()
  1243. X *
  1244. X *  DESCRIPTION
  1245. X *
  1246. X *    Checks to see if profiling is enabled based on whether the
  1247. X *    user has specified profiling, the maximum trace depth has
  1248. X *    not yet been reached, the current function is selected,
  1249. X *    and the current process is selected.  Returns TRUE if
  1250. X *    profiling is enabled, FALSE otherwise.
  1251. X *
  1252. X */
  1253. X
  1254. LOCAL BOOLEAN DoProfile ()
  1255. {
  1256. X    REGISTER BOOLEAN profile;
  1257. X
  1258. X    profile = FALSE;
  1259. X    if (PROFILING) {
  1260. X    if (stack -> level <= stack -> maxdepth) {
  1261. X        if (InList (stack -> p_functions, func)) {
  1262. X        if (InList (stack -> processes, _db_process_)) {
  1263. X            profile = TRUE;
  1264. X        }
  1265. X        }
  1266. X    }
  1267. X    }
  1268. X    return (profile);
  1269. }
  1270. X
  1271. X
  1272. /*
  1273. X *  FUNCTION
  1274. X *
  1275. X *    _db_keyword_    test keyword for member of keyword list
  1276. X *
  1277. X *  SYNOPSIS
  1278. X *
  1279. X *    BOOLEAN _db_keyword_ (keyword)
  1280. X *    char *keyword;
  1281. X *
  1282. X *  DESCRIPTION
  1283. X *
  1284. X *    Test a keyword to determine if it is in the currently active
  1285. X *    keyword list.  As with the function list, a keyword is accepted
  1286. X *    if the list is null, otherwise it must match one of the list
  1287. X *    members.  When debugging is not on, no keywords are accepted.
  1288. X *    After the maximum trace level is exceeded, no keywords are
  1289. X *    accepted (this behavior subject to change).  Additionally,
  1290. X *    the current function and process must be accepted based on
  1291. X *    their respective lists.
  1292. X *
  1293. X *    Returns TRUE if keyword accepted, FALSE otherwise.
  1294. X *
  1295. X */
  1296. X
  1297. BOOLEAN _db_keyword_ (keyword)
  1298. char *keyword;
  1299. {
  1300. X    REGISTER BOOLEAN accept;
  1301. X
  1302. X    if (!init_done) {
  1303. X    _db_push_ ("");
  1304. X    }
  1305. X    accept = FALSE;
  1306. X    if (DEBUGGING) {
  1307. X    if (stack -> level <= stack -> maxdepth) {
  1308. X        if (InList (stack -> functions, func)) {
  1309. X        if (InList (stack -> keywords, keyword)) {
  1310. X            if (InList (stack -> processes, _db_process_)) {
  1311. X            accept = TRUE;
  1312. X            }
  1313. X        }
  1314. X        }
  1315. X    }
  1316. X    }
  1317. X    return (accept);
  1318. }
  1319. X
  1320. X
  1321. /*
  1322. X *  FUNCTION
  1323. X *
  1324. X *    Indent    indent a line to the given indentation level
  1325. X *
  1326. X *  SYNOPSIS
  1327. X *
  1328. X *    LOCAL VOID Indent (indent)
  1329. X *    int indent;
  1330. X *
  1331. X *  DESCRIPTION
  1332. X *
  1333. X *    Indent a line to the given level.  Note that this is
  1334. X *    a simple minded but portable implementation.
  1335. X *    There are better ways.
  1336. X *
  1337. X *    Also, the indent must be scaled by the compile time option
  1338. X *    of character positions per nesting level.
  1339. X *
  1340. X */
  1341. X
  1342. LOCAL VOID Indent (indent)
  1343. int indent;
  1344. {
  1345. X    REGISTER int count;
  1346. X    AUTO char buffer[PRINTBUF];
  1347. X
  1348. X    indent *= INDENT;
  1349. X    for (count = 0; (count < (indent - INDENT)) && (count < (PRINTBUF - 1)); count++) {
  1350. X    if ((count % INDENT) == 0) {
  1351. X        buffer[count] = '|';
  1352. X    } else {
  1353. X        buffer[count] = ' ';
  1354. X    }
  1355. X    }
  1356. X    buffer[count] = EOS;
  1357. X    (VOID) fprintf (_db_fp_, buffer);
  1358. X    (VOID) fflush (_db_fp_);
  1359. }
  1360. X
  1361. X
  1362. /*
  1363. X *  FUNCTION
  1364. X *
  1365. X *    FreeList    free all memory associated with a linked list
  1366. X *
  1367. X *  SYNOPSIS
  1368. X *
  1369. X *    LOCAL VOID FreeList (linkp)
  1370. X *    struct link *linkp;
  1371. X *
  1372. X *  DESCRIPTION
  1373. X *
  1374. X *    Given pointer to the head of a linked list, frees all
  1375. X *    memory held by the list and the members of the list.
  1376. X *
  1377. X */
  1378. X
  1379. LOCAL VOID FreeList (linkp)
  1380. struct link *linkp;
  1381. {
  1382. X    REGISTER struct link *old;
  1383. X
  1384. X    while (linkp != NULL) {
  1385. X    old = linkp;
  1386. X    linkp = linkp -> next_link;
  1387. X    if (old -> string != NULL) {
  1388. X        free (old -> string);
  1389. X    }
  1390. X    free ((char *) old);
  1391. X    }
  1392. }
  1393. X
  1394. X
  1395. /*
  1396. X *  FUNCTION
  1397. X *
  1398. X *    StrDup   make a duplicate of a string in new memory
  1399. X *
  1400. X *  SYNOPSIS
  1401. X *
  1402. X *    LOCAL char *StrDup (string)
  1403. X *    char *string;
  1404. X *
  1405. X *  DESCRIPTION
  1406. X *
  1407. X *    Given pointer to a string, allocates sufficient memory to make
  1408. X *    a duplicate copy, and copies the string to the newly allocated
  1409. X *    memory.  Failure to allocated sufficient memory is immediately
  1410. X *    fatal.
  1411. X *
  1412. X */
  1413. X
  1414. X
  1415. LOCAL char *StrDup (string)
  1416. char *string;
  1417. {
  1418. X    REGISTER char *new;
  1419. X
  1420. X    new = DbugMalloc (strlen (string) + 1);
  1421. X    (VOID) strcpy (new, string);
  1422. X    return (new);
  1423. }
  1424. X
  1425. X
  1426. /*
  1427. X *  FUNCTION
  1428. X *
  1429. X *    DoPrefix    print debugger line prefix prior to indentation
  1430. X *
  1431. X *  SYNOPSIS
  1432. X *
  1433. X *    LOCAL VOID DoPrefix (_line_)
  1434. X *    int _line_;
  1435. X *
  1436. X *  DESCRIPTION
  1437. X *
  1438. X *    Print prefix common to all debugger output lines, prior to
  1439. X *    doing indentation if necessary.  Print such information as
  1440. SHAR_EOF
  1441. true || echo 'restore of dmake/dbug/dbug/dbug.c failed'
  1442. fi
  1443. echo 'End of part 2, continue with part 3'
  1444. echo 3 > _shar_seq_.tmp
  1445. exit 0
  1446.  
  1447. exit 0 # Just in case...
  1448. -- 
  1449. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1450. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1451. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1452. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1453.