home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-10 | 40.2 KB | 1,459 lines |
- Newsgroups: comp.sources.misc
- From: Dennis Vadura <dvadura@watdragon.waterloo.edu>
- Subject: v19i024: dmake - dmake version 3.7, Part03/37
- Message-ID: <1991May9.192621.23446@sparky.IMD.Sterling.COM>
- Date: Thu, 9 May 1991 19:26:21 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
- Posting-number: Volume 19, Issue 24
- Archive-name: dmake/part03
- Supersedes: dmake-3.6: Volume 15, Issue 52-77
-
- ---- Cut Here and feed the following to sh ----
- #!/bin/sh
- # this is dmake.shar.03 (part 3 of a multipart archive)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file dmake/dbug/dbug/dbug.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 3; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test -f _shar_wnt_.tmp; then
- sed 's/^X//' << 'SHAR_EOF' >> 'dmake/dbug/dbug/dbug.c' &&
- X * current process name, current source file name and line number,
- X * and current function nesting depth.
- X *
- X */
- X
- X
- LOCAL VOID DoPrefix (_line_)
- int _line_;
- {
- X lineno++;
- X if (stack -> flags & NUMBER_ON) {
- X (VOID) fprintf (_db_fp_, "%5d: ", lineno);
- X }
- X if (stack -> flags & PROCESS_ON) {
- X (VOID) fprintf (_db_fp_, "%s: ", _db_process_);
- X }
- X if (stack -> flags & FILE_ON) {
- X (VOID) fprintf (_db_fp_, "%14s: ", file);
- X }
- X if (stack -> flags & LINE_ON) {
- X (VOID) fprintf (_db_fp_, "%5d: ", _line_);
- X }
- X if (stack -> flags & DEPTH_ON) {
- X (VOID) fprintf (_db_fp_, "%4d: ", stack -> level);
- X }
- X (VOID) fflush (_db_fp_);
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * OpenFile open new output stream for debugger output
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID OpenFile (name)
- X * char *name;
- X *
- X * DESCRIPTION
- X *
- X * Given name of a new file (or "-" for stdout) opens the file
- X * and sets the output stream to the new file.
- X *
- X */
- X
- LOCAL VOID OpenFile (name)
- char *name;
- {
- X REGISTER FILE *fp;
- X REGISTER BOOLEAN newfile;
- X
- X if (name != NULL) {
- X if (strcmp (name, "-") == 0) {
- X _db_fp_ = stdout;
- X stack -> out_file = _db_fp_;
- X } else {
- X if (!Writable (name)) {
- X (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
- X perror ("");
- X (VOID) fflush (_db_fp_);
- X (VOID) XDelay (stack -> delay);
- X } else {
- X if (EXISTS (name)) {
- X newfile = FALSE;
- X } else {
- X newfile = TRUE;
- X }
- X fp = fopen (name, "a");
- X if (fp == NULL) {
- X (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
- X perror ("");
- X (VOID) fflush (_db_fp_);
- X (VOID) XDelay (stack -> delay);
- X } else {
- X _db_fp_ = fp;
- X stack -> out_file = fp;
- X if (newfile) {
- X ChangeOwner (name);
- X }
- X }
- X }
- X }
- X }
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * OpenProfile open new output stream for profiler output
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID OpenProfile (name)
- X * char *name;
- X *
- X * DESCRIPTION
- X *
- X * Given name of a new file, opens the file
- X * and sets the profiler output stream to the new file.
- X *
- X * It is currently unclear whether the prefered behavior is
- X * to truncate any existing file, or simply append to it.
- X * The latter behavior would be desirable for collecting
- X * accumulated runtime history over a number of separate
- X * runs. It might take some changes to the analyzer program
- X * though, and the notes that Binayak sent with the profiling
- X * diffs indicated that append was the normal mode, but this
- X * does not appear to agree with the actual code. I haven't
- X * investigated at this time [fnf; 24-Jul-87].
- X */
- X
- LOCAL VOID OpenProfile (name)
- char *name;
- {
- X REGISTER FILE *fp;
- X REGISTER BOOLEAN newfile;
- X
- X if (name != NULL) {
- X if (!Writable (name)) {
- X (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
- X perror ("");
- X (VOID) fflush (_db_fp_);
- X (VOID) XDelay (stack -> delay);
- X } else {
- X if (EXISTS (name)) {
- X newfile = FALSE;
- X } else {
- X newfile = TRUE;
- X }
- X fp = fopen (name, "w");
- X if (fp == NULL) {
- X (VOID) fprintf (_db_fp_, ERR_OPEN, _db_process_, name);
- X perror ("");
- X (VOID) fflush (_db_fp_);
- X (VOID) XDelay (stack -> delay);
- X } else {
- X _db_pfp_ = fp;
- X stack -> prof_file = fp;
- X if (newfile) {
- X ChangeOwner (name);
- X }
- X }
- X }
- X }
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * CloseFile close the debug output stream
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID CloseFile (fp)
- X * FILE *fp;
- X *
- X * DESCRIPTION
- X *
- X * Closes the debug output stream unless it is standard output
- X * or standard error.
- X *
- X */
- X
- LOCAL VOID CloseFile (fp)
- FILE *fp;
- {
- X if (fp != stderr && fp != stdout) {
- X if (fclose (fp) == EOF) {
- X (VOID) fprintf (stderr, ERR_CLOSE, _db_process_);
- X perror ("");
- X (VOID) fflush (stderr);
- X (VOID) XDelay (stack -> delay);
- X }
- X }
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * DbugExit print error message and exit
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID DbugExit (why)
- X * char *why;
- X *
- X * DESCRIPTION
- X *
- X * Prints error message using current process name, the reason for
- X * aborting (typically out of memory), and exits with status 1.
- X * This should probably be changed to use a status code
- X * defined in the user's debugger include file.
- X *
- X */
- X
- LOCAL VOID DbugExit (why)
- char *why;
- {
- X (VOID) fprintf (stderr, ERR_ABORT, _db_process_, why);
- X (VOID) fflush (stderr);
- X (VOID) XDelay (stack -> delay);
- X exit (1);
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * DbugMalloc allocate memory for debugger runtime support
- X *
- X * SYNOPSIS
- X *
- X * LOCAL char *DbugMalloc (size)
- X * int size;
- X *
- X * DESCRIPTION
- X *
- X * Allocate more memory for debugger runtime support functions.
- X * Failure to to allocate the requested number of bytes is
- X * immediately fatal to the current process. This may be
- X * rather unfriendly behavior. It might be better to simply
- X * print a warning message, freeze the current debugger state,
- X * and continue execution.
- X *
- X */
- X
- LOCAL char *DbugMalloc (size)
- int size;
- {
- X register char *new;
- X
- X new = malloc ( size );
- X if (new == NULL) {
- X DbugExit ("out of memory");
- X }
- X return (new);
- }
- X
- X
- /*
- X * This function may be eliminated when strtok is available
- X * in the runtime environment (missing from BSD4.1).
- X */
- X
- LOCAL char *strtok (s1, s2)
- char *s1, *s2;
- {
- X static char *end = NULL;
- X REGISTER char *rtnval;
- X
- X rtnval = NULL;
- X if (s2 != NULL) {
- X if (s1 != NULL) {
- X end = s1;
- X rtnval = strtok ((char *) NULL, s2);
- X } else if (end != NULL) {
- X if (*end != EOS) {
- X rtnval = end;
- X while (*end != *s2 && *end != EOS) {end++;}
- X if (*end != EOS) {
- X *end++ = EOS;
- X }
- X }
- X }
- X }
- X return (rtnval);
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * BaseName strip leading pathname components from name
- X *
- X * SYNOPSIS
- X *
- X * LOCAL char *BaseName (pathname)
- X * char *pathname;
- X *
- X * DESCRIPTION
- X *
- X * Given pointer to a complete pathname, locates the base file
- X * name at the end of the pathname and returns a pointer to
- X * it.
- X *
- X */
- X
- LOCAL char *BaseName (pathname)
- char *pathname;
- {
- X register char *base;
- X
- X base = strrchr (pathname, '/');
- X if (base++ == NULL) {
- X base = pathname;
- X }
- X return (base);
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * Writable test to see if a pathname is writable/creatable
- X *
- X * SYNOPSIS
- X *
- X * LOCAL BOOLEAN Writable (pathname)
- X * char *pathname;
- X *
- X * DESCRIPTION
- X *
- X * Because the debugger might be linked in with a program that
- X * runs with the set-uid-bit (suid) set, we have to be careful
- X * about opening a user named file for debug output. This consists
- X * of checking the file for write access with the real user id,
- X * or checking the directory where the file will be created.
- X *
- X * Returns TRUE if the user would normally be allowed write or
- X * create access to the named file. Returns FALSE otherwise.
- X *
- X */
- X
- LOCAL BOOLEAN Writable (pathname)
- char *pathname;
- {
- X REGISTER BOOLEAN granted;
- #ifdef unix
- X REGISTER char *lastslash;
- #endif
- X
- #ifndef unix
- X granted = TRUE;
- #else
- X granted = FALSE;
- X if (EXISTS (pathname)) {
- X if (WRITABLE (pathname)) {
- X granted = TRUE;
- X }
- X } else {
- X lastslash = strrchr (pathname, '/');
- X if (lastslash != NULL) {
- X *lastslash = EOS;
- X } else {
- X pathname = ".";
- X }
- X if (WRITABLE (pathname)) {
- X granted = TRUE;
- X }
- X if (lastslash != NULL) {
- X *lastslash = '/';
- X }
- X }
- #endif
- X return (granted);
- }
- X
- X
- /*
- X * This function may be eliminated when strrchr is available
- X * in the runtime environment (missing from BSD4.1).
- X * Alternately, you can use rindex() on BSD systems.
- X */
- X
- LOCAL char *strrchr (s, c)
- char *s;
- char c;
- {
- X REGISTER char *scan;
- X
- X for (scan = s; *scan != EOS; scan++) {;}
- X while (scan > s && *--scan != c) {;}
- X if (*scan != c) {
- X scan = NULL;
- X }
- X return (scan);
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * ChangeOwner change owner to real user for suid programs
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID ChangeOwner (pathname)
- X *
- X * DESCRIPTION
- X *
- X * For unix systems, change the owner of the newly created debug
- X * file to the real owner. This is strictly for the benefit of
- X * programs that are running with the set-user-id bit set.
- X *
- X * Note that at this point, the fact that pathname represents
- X * a newly created file has already been established. If the
- X * program that the debugger is linked to is not running with
- X * the suid bit set, then this operation is redundant (but
- X * harmless).
- X *
- X */
- X
- LOCAL VOID ChangeOwner (pathname)
- char *pathname;
- {
- #ifdef unix
- X if (chown (pathname, getuid (), getgid ()) == -1) {
- X (VOID) fprintf (stderr, ERR_CHOWN, _db_process_, pathname);
- X perror ("");
- X (VOID) fflush (stderr);
- X (VOID) XDelay (stack -> delay);
- X }
- #endif
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * _db_setjmp_ save debugger environment
- X *
- X * SYNOPSIS
- X *
- X * VOID _db_setjmp_ ()
- X *
- X * DESCRIPTION
- X *
- X * Invoked as part of the user's DBUG_SETJMP macro to save
- X * the debugger environment in parallel with saving the user's
- X * environment.
- X *
- X */
- X
- VOID _db_setjmp_ ()
- {
- X jmplevel = stack -> level;
- X jmpfunc = func;
- X jmpfile = file;
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * _db_longjmp_ restore previously saved debugger environment
- X *
- X * SYNOPSIS
- X *
- X * VOID _db_longjmp_ ()
- X *
- X * DESCRIPTION
- X *
- X * Invoked as part of the user's DBUG_LONGJMP macro to restore
- X * the debugger environment in parallel with restoring the user's
- X * previously saved environment.
- X *
- X */
- X
- VOID _db_longjmp_ ()
- {
- X stack -> level = jmplevel;
- X if (jmpfunc) {
- X func = jmpfunc;
- X }
- X if (jmpfile) {
- X file = jmpfile;
- X }
- }
- X
- X
- /*
- X * FUNCTION
- X *
- X * DelayArg convert D flag argument to appropriate value
- X *
- X * SYNOPSIS
- X *
- X * LOCAL int DelayArg (value)
- X * int value;
- X *
- X * DESCRIPTION
- X *
- X * Converts delay argument, given in tenths of a second, to the
- X * appropriate numerical argument used by the system to delay
- X * that that many tenths of a second. For example, on the
- X * AMIGA, there is a system call "Delay()" which takes an
- X * argument in ticks (50 per second). On unix, the sleep
- X * command takes seconds. Thus a value of "10", for one
- X * second of delay, gets converted to 50 on the amiga, and 1
- X * on unix. Other systems will need to use a timing loop.
- X *
- X */
- X
- LOCAL int DelayArg (value)
- int value;
- {
- X int delayarg = 0;
- X
- #ifdef unix
- X delayarg = value / 10; /* Delay is in seconds for sleep () */
- #endif
- #ifdef AMIGA
- X delayarg = (HZ * value) / 10; /* Delay in ticks for XDelay () */
- #endif
- X return (delayarg);
- }
- X
- X
- /*
- X * A dummy delay stub for systems that do not support delays.
- X * With a little work, this can be turned into a timing loop.
- X */
- X
- #ifndef unix
- #ifndef AMIGA
- XXDelay ()
- {
- }
- #endif
- #endif
- X
- X
- /*
- X * FUNCTION
- X *
- X * perror perror simulation for systems that don't have it
- X *
- X * SYNOPSIS
- X *
- X * LOCAL VOID perror (s)
- X * char *s;
- X *
- X * DESCRIPTION
- X *
- X * Perror produces a message on the standard error stream which
- X * provides more information about the library or system error
- X * just encountered. The argument string s is printed, followed
- X * by a ':', a blank, and then a message and a newline.
- X *
- X * An undocumented feature of the unix perror is that if the string
- X * 's' is a null string (NOT a NULL pointer!), then the ':' and
- X * blank are not printed.
- X *
- X * This version just complains about an "unknown system error".
- X *
- X */
- X
- #if !unix && !(AMIGA || LATTICE || __TURBOC__ )
- LOCAL VOID perror (s)
- #if __STDC__
- const char *s;
- #else
- char *s;
- #endif
- {
- X if (s && *s != EOS) {
- X (VOID) fprintf (stderr, "%s: ", s);
- X }
- X (VOID) fprintf (stderr, "<unknown system error>\n");
- }
- #endif /* !unix && !(AMIGA && LATTICE) */
- X
- /*
- X * Here we need the definitions of the clock routine. Add your
- X * own for whatever system that you have.
- X */
- X
- #if unix
- X
- # include <sys/param.h>
- # if BSD4_3 || sun
- X
- /*
- X * Definition of the Clock() routine for 4.3 BSD.
- X */
- X
- #include <sys/time.h>
- #include <sys/resource.h>
- X
- /*
- X * Returns the user time in milliseconds used by this process so
- X * far.
- X */
- X
- LOCAL unsigned long Clock ()
- {
- X struct rusage ru;
- X
- X (VOID) getrusage (RUSAGE_SELF, &ru);
- X return ((ru.ru_utime.tv_sec * 1000) + (ru.ru_utime.tv_usec / 1000));
- }
- X
- #else
- X
- LOCAL unsigned long Clock ()
- {
- X return (0);
- }
- X
- # endif
- X
- #else
- X
- #if AMIGA
- X
- struct DateStamp { /* Yes, this is a hack, but doing it right */
- X long ds_Days; /* is incredibly ugly without splitting this */
- X long ds_Minute; /* off into a separate file */
- X long ds_Tick;
- };
- X
- static int first_clock = TRUE;
- static struct DateStamp begin;
- static struct DateStamp elapsed;
- X
- LOCAL unsigned long Clock ()
- {
- X register struct DateStamp *now;
- X register unsigned long millisec = 0;
- X extern VOID *AllocMem ();
- X
- X now = (struct DateStamp *) AllocMem ((long) sizeof (struct DateStamp), 0L);
- X if (now != NULL) {
- X if (first_clock == TRUE) {
- X first_clock = FALSE;
- X (VOID) DateStamp (now);
- X begin = *now;
- X }
- X (VOID) DateStamp (now);
- X millisec = 24 * 3600 * (1000 / HZ) * (now -> ds_Days - begin.ds_Days);
- X millisec += 60 * (1000 / HZ) * (now -> ds_Minute - begin.ds_Minute);
- X millisec += (1000 / HZ) * (now -> ds_Tick - begin.ds_Tick);
- X (VOID) FreeMem (now, (long) sizeof (struct DateStamp));
- X }
- X return (millisec);
- }
- X
- #else
- X
- LOCAL unsigned long Clock ()
- {
- X return (0);
- }
- X
- #endif /* AMIGA */
- X
- #endif /* unix */
- X
- #ifdef AMIGA
- XXDelay(x)
- int x;
- {
- X if (x) Delay(x); /* fix Delay bug in AmigaDOS */
- }
- #endif
- X
- SHAR_EOF
- chmod 0640 dmake/dbug/dbug/dbug.c ||
- echo 'restore of dmake/dbug/dbug/dbug.c failed'
- Wc_c="`wc -c < 'dmake/dbug/dbug/dbug.c'`"
- test 44504 -eq "$Wc_c" ||
- echo 'dmake/dbug/dbug/dbug.c: original size 44504, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= dmake/dbug/dbug/dbug.h ==============
- if test -f 'dmake/dbug/dbug/dbug.h' -a X"$1" != X"-c"; then
- echo 'x - skipping dmake/dbug/dbug/dbug.h (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.h' &&
- /******************************************************************************
- X * *
- X * N O T I C E *
- X * *
- X * Copyright Abandoned, 1987, Fred Fish *
- X * *
- X * *
- X * This previously copyrighted work has been placed into the public *
- X * domain by the author and may be freely used for any purpose, *
- X * private or commercial. *
- X * *
- X * Because of the number of inquiries I was receiving about the use *
- X * of this product in commercially developed works I have decided to *
- X * simply make it public domain to further its unrestricted use. I *
- X * specifically would be most happy to see this material become a *
- X * part of the standard Unix distributions by AT&T and the Berkeley *
- X * Computer Science Research Group, and a standard part of the GNU *
- X * system from the Free Software Foundation. *
- X * *
- X * I would appreciate it, as a courtesy, if this notice is left in *
- X * all copies and derivative works. Thank you. *
- X * *
- X * The author makes no warranty of any kind with respect to this *
- X * product and explicitly disclaims any implied warranties of mer- *
- X * chantability or fitness for any particular purpose. *
- X * *
- X ******************************************************************************
- X */
- X
- X
- /*
- X * FILE
- X *
- X * dbug.h user include file for programs using the dbug package
- X *
- X * SYNOPSIS
- X *
- X * #include <local/dbug.h>
- X *
- X * SCCS ID
- X *
- X * @(#)dbug.h 1.11 9/5/87
- X *
- X * DESCRIPTION
- X *
- X * Programs which use the dbug package must include this file.
- X * It contains the appropriate macros to call support routines
- X * in the dbug runtime library.
- X *
- X * To disable compilation of the macro expansions define the
- X * preprocessor symbol "DBUG_OFF". This will result in null
- X * macros expansions so that the resulting code will be smaller
- X * and faster. (The difference may be smaller than you think
- X * so this step is recommended only when absolutely necessary).
- X * In general, tradeoffs between space and efficiency are
- X * decided in favor of efficiency since space is seldom a
- X * problem on the new machines).
- X *
- X * All externally visible symbol names follow the pattern
- X * "_db_xxx..xx_" to minimize the possibility of a dbug package
- X * symbol colliding with a user defined symbol.
- X *
- X * The DBUG_<N> style macros are obsolete and should not be used
- X * in new code. Macros to map them to instances of DBUG_PRINT
- X * are provided for compatibility with older code. They may go
- X * away completely in subsequent releases.
- X *
- X * AUTHOR
- X *
- X * Fred Fish
- X * (Currently employed by Motorola Computer Division, Tempe, Az.)
- X * hao!noao!mcdsun!fnf
- X * (602) 438-3614
- X *
- X */
- X
- X
- /*
- X * Internally used dbug variables which must be global.
- X */
- X
- #ifndef DBUG_OFF
- X extern int _db_on_; /* TRUE if debug currently enabled */
- X extern FILE *_db_fp_; /* Current debug output stream */
- X extern char *_db_process_; /* Name of current process */
- X extern int _db_keyword_ (); /* Accept/reject keyword */
- X extern void _db_push_ (); /* Push state, set up new state */
- X extern void _db_pop_ (); /* Pop previous debug state */
- X extern void _db_enter_ (); /* New user function entered */
- X extern void _db_return_ (); /* User function return */
- X extern void _db_pargs_ (); /* Remember args for line */
- X extern void _db_doprnt_ (); /* Print debug output */
- X extern void _db_setjmp_ (); /* Save debugger environment */
- X extern void _db_longjmp_ (); /* Restore debugger environment */
- # endif
- X
- X
- /*
- X * These macros provide a user interface into functions in the
- X * dbug runtime support library. They isolate users from changes
- X * in the MACROS and/or runtime support.
- X *
- X * The symbols "__LINE__" and "__FILE__" are expanded by the
- X * preprocessor to the current source file line number and file
- X * name respectively.
- X *
- X * WARNING --- Because the DBUG_ENTER macro allocates space on
- X * the user function's stack, it must precede any executable
- X * statements in the user function.
- X *
- X */
- X
- # ifdef DBUG_OFF
- # define DBUG_ENTER(a1)
- # define DBUG_MALLOC(a1)
- # define DBUG_RETURN(a1) return(a1)
- # define DBUG_VOID_RETURN return
- # define DBUG_EXECUTE(keyword,a1)
- # define DBUG_PRINT(keyword,arglist)
- # define DBUG_2(keyword,format) /* Obsolete */
- # define DBUG_3(keyword,format,a1) /* Obsolete */
- # define DBUG_4(keyword,format,a1,a2) /* Obsolete */
- # define DBUG_5(keyword,format,a1,a2,a3) /* Obsolete */
- # define DBUG_PUSH(a1)
- # define DBUG_POP()
- # define DBUG_PROCESS(a1)
- # define DBUG_FILE (stderr)
- # define DBUG_SETJMP setjmp
- # define DBUG_LONGJMP longjmp
- # else
- # define DBUG_ENTER(a) \
- X auto char *_db_func_, *_db_file_; \
- X int _db_level_; \
- X _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
- # define DBUG_MALLOC(a) \
- X auto char *_db_func_, *_db_file_; \
- X int _db_level_; \
- X malloc_init();\
- X _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
- # define DBUG_LEAVE \
- X (_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
- # define DBUG_RETURN(a1) return (DBUG_LEAVE, (a1))
- /* define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);} Alternate form */
- # define DBUG_VOID_RETURN DBUG_LEAVE; return
- # define DBUG_EXECUTE(keyword,a1) \
- X {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
- # define DBUG_PRINT(keyword,arglist) \
- X {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
- # define DBUG_2(keyword,format) \
- X DBUG_PRINT(keyword,(format)) /* Obsolete */
- # define DBUG_3(keyword,format,a1) \
- X DBUG_PRINT(keyword,(format,a1)) /* Obsolete */
- # define DBUG_4(keyword,format,a1,a2) \
- X DBUG_PRINT(keyword,(format,a1,a2)) /* Obsolete */
- # define DBUG_5(keyword,format,a1,a2,a3) \
- X DBUG_PRINT(keyword,(format,a1,a2,a3)) /* Obsolete */
- # define DBUG_PUSH(a1) _db_push_ (a1)
- # define DBUG_POP() _db_pop_ ()
- # define DBUG_PROCESS(a1) (_db_process_ = a1)
- # define DBUG_FILE (_db_fp_)
- # define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
- # define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
- # endif
- X
- SHAR_EOF
- chmod 0640 dmake/dbug/dbug/dbug.h ||
- echo 'restore of dmake/dbug/dbug/dbug.h failed'
- Wc_c="`wc -c < 'dmake/dbug/dbug/dbug.h'`"
- test 6259 -eq "$Wc_c" ||
- echo 'dmake/dbug/dbug/dbug.h: original size 6259, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= dmake/dbug/dbug/dbug.p ==============
- if test -f 'dmake/dbug/dbug/dbug.p' -a X"$1" != X"-c"; then
- echo 'x - skipping dmake/dbug/dbug/dbug.p (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.p' &&
- X
- X
- X
- X D B U G
- X
- X C Program Debugging Package
- X
- X by
- X
- X Fred Fish
- X
- X
- X
- X
- X IIIINNNNTTTTRRRROOOODDDDUUUUCCCCTTTTIIIIOOOONNNN
- X
- X
- X Almost every program development environment worthy of
- X the name provides some sort of debugging facility. Usually
- X this takes the form of a program which is capable of
- X controlling execution of other programs and examining the
- X internal state of other executing programs. These types of
- X programs will be referred to as external debuggers since the
- X debugger is not part of the executing program. Examples of
- X this type of debugger include the aaaaddddbbbb and ssssddddbbbb debuggers
- X provided with the UUUUNNNNIIIIXXXX811119 operating system.
- X
- X
- X One of the problems associated with developing programs
- X in an environment with good external debuggers is that
- X developed programs tend to have little or no internal
- X instrumentation. This is usually not a problem for the
- X developer since he is, or at least should be, intimately
- X familiar with the internal organization, data structures,
- X and control flow of the program being debugged. It is a
- X serious problem for maintenance programmers, who are
- X unlikely to have such familiarity with the program being
- X maintained, modified, or ported to another environment. It
- X is also a problem, even for the developer, when the program
- X is moved to an environment with a primitive or unfamiliar
- X debugger, or even no debugger.
- X
- X
- X On the other hand, _d_b_u_g is an example of an internal
- X debugger. Because it requires internal instrumentation of a
- X program, and its usage does not depend on any special
- X capabilities of the execution environment, it is always
- X available and will execute in any environment that the
- X program itself will execute in. In addition, since it is a
- X complete package with a specific user interface, all
- X programs which use it will be provided with similar
- X debugging capabilities. This is in sharp contrast to other
- X
- X
- X __________
- X
- X 1. UNIX is a trademark of AT&T Bell Laboratories.
- X
- X
- X
- X
- X - 1 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X forms of internal instrumentation where each developer has
- X their own, usually less capable, form of internal debugger.
- X In summary, because _d_b_u_g is an internal debugger it provides
- X consistency across operating environments, and because it is
- X available to all developers it provides consistency across
- X all programs in the same environment.
- X
- X
- X The _d_b_u_g package imposes only a slight speed penalty on
- X executing programs, typically much less than 10 percent, and
- X a modest size penalty, typically 10 to 20 percent. By
- X defining a specific C preprocessor symbol both of these can
- X be reduced to zero with no changes required to the source
- X code.
- X
- X
- X The following list is a quick summary of the
- X capabilities of the _d_b_u_g package. Each capability can be
- X individually enabled or disabled at the time a program is
- X invoked by specifying the appropriate command line
- X arguments.
- X
- X o Execution trace showing function level control
- X flow in a semi-graphically manner using
- X indentation to indicate nesting depth.
- X
- X o Output the values of all, or any subset of, key
- X internal variables.
- X
- X o Limit actions to a specific set of named
- X functions.
- X
- X o Limit function trace to a specified nesting depth.
- X
- X o Label each output line with source file name and
- X line number.
- X
- X o Label each output line with name of current
- X process.
- X
- X o Push or pop internal debugging state to allow
- X execution with built in debugging defaults.
- X
- X o Redirect the debug output stream to standard
- X output (stdout) or a named file. The default
- X output stream is standard error (stderr). The
- X redirection mechanism is completely independent of
- X normal command line redirection to avoid output
- X conflicts.
- X
- X
- X
- X
- X
- X - 2 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X PPPPRRRRIIIIMMMMIIIITTTTIIIIVVVVEEEE DDDDEEEEBBBBUUUUGGGGGGGGIIIINNNNGGGG TTTTEEEECCCCHHHHNNNNIIIIQQQQUUUUEEEESSSS
- X
- X
- X Internal instrumentation is already a familiar concept
- X to most programmers, since it is usually the first debugging
- X technique learned. Typically, "print statements" are
- X inserted in the source code at interesting points, the code
- X is recompiled and executed, and the resulting output is
- X examined in an attempt to determine where the problem is.
- X
- X The procedure is iterative, with each iteration yielding
- X more and more output, and hopefully the source of the
- X problem is discovered before the output becomes too large to
- X deal with or previously inserted statements need to be
- X removed. Figure 1 is an example of this type of primitive
- X debugging technique.
- X
- X
- X
- X #include <stdio.h>
- X
- X main (argc, argv)
- X int argc;
- X char *argv[];
- X {
- X printf ("argv[0] = %d\n", argv[0]);
- X /*
- X * Rest of program
- X */
- X printf ("== done ==\n");
- X }
- X
- X
- X Figure 1
- X Primitive Debugging Technique
- X
- X
- X
- X
- X
- X Eventually, and usually after at least several
- X iterations, the problem will be found and corrected. At
- X this point, the newly inserted print statements must be
- X dealt with. One obvious solution is to simply delete them
- X all. Beginners usually do this a few times until they have
- X to repeat the entire process every time a new bug pops up.
- X The second most obvious solution is to somehow disable the
- X output, either through the source code comment facility,
- X creation of a debug variable to be switched on or off, or by
- X using the C preprocessor. Figure 2 is an example of all
- X three techniques.
- X
- X
- X
- X - 3 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X
- X
- X #include <stdio.h>
- X
- X int debug = 0;
- X
- X main (argc, argv)
- X int argc;
- X char *argv[];
- X {
- X /* printf ("argv = %x\n", argv) */
- X if (debug) printf ("argv[0] = %d\n", argv[0]);
- X /*
- X * Rest of program
- X */
- X #ifdef DEBUG
- X printf ("== done ==\n");
- X #endif
- X }
- X
- X
- X Figure 2
- X Debug Disable Techniques
- X
- X
- X
- X
- X
- X Each technique has its advantages and disadvantages
- X with respect to dynamic vs static activation, source code
- X overhead, recompilation requirements, ease of use, program
- X readability, etc. Overuse of the preprocessor solution
- X quickly leads to problems with source code readability and
- X maintainability when multiple ####iiiiffffddddeeeeffff symbols are to be
- X defined or undefined based on specific types of debug
- X desired. The source code can be made slightly more readable
- X by suitable indentation of the ####iiiiffffddddeeeeffff arguments to match the
- X indentation of the code, but not all C preprocessors allow
- X this. The only requirement for the standard UUUUNNNNIIIIXXXX C
- X preprocessor is for the '#' character to appear in the first
- X column, but even this seems like an arbitrary and
- X unreasonable restriction. Figure 3 is an example of this
- X usage.
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X - 4 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X
- X
- X #include <stdio.h>
- X
- X main (argc, argv)
- X int argc;
- X char *argv[];
- X {
- X # ifdef DEBUG
- X printf ("argv[0] = %d\n", argv[0]);
- X # endif
- X /*
- X * Rest of program
- X */
- X # ifdef DEBUG
- X printf ("== done ==\n");
- X # endif
- X }
- X
- X
- X Figure 3
- X More Readable Preprocessor Usage
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X - 5 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN TTTTRRRRAAAACCCCEEEE EEEEXXXXAAAAMMMMPPPPLLLLEEEE
- X
- X
- X We will start off learning about the capabilities of
- X the _d_b_u_g package by using a simple minded program which
- X computes the factorial of a number. In order to better
- X demonstrate the function trace mechanism, this program is
- X implemented recursively. Figure 4 is the main function for
- X this factorial program.
- X
- X
- X
- X #include <stdio.h>
- X /* User programs should use <local/dbug.h> */
- X #include "dbug.h"
- X
- X main (argc, argv)
- X int argc;
- X char *argv[];
- X {
- X register int result, ix;
- X extern int factorial (), atoi ();
- X
- X DBUG_ENTER ("main");
- X DBUG_PROCESS (argv[0]);
- X for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
- X switch (argv[ix][1]) {
- X case '#':
- X DBUG_PUSH (&(argv[ix][2]));
- X break;
- X }
- X }
- X for (; ix < argc; ix++) {
- X DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
- X result = factorial (atoi (argv[ix]));
- X printf ("%d\n", result);
- X }
- X DBUG_RETURN (0);
- X }
- X
- X
- X Figure 4
- X Factorial Program Mainline
- X
- X
- X
- X
- X
- X The mmmmaaaaiiiinnnn function is responsible for processing any
- X command line option arguments and then computing and
- X printing the factorial of each non-option argument.
- X
- X
- X
- X - 6 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X First of all, notice that all of the debugger functions
- X are implemented via preprocessor macros. This does not
- X detract from the readability of the code and makes disabling
- X all debug compilation trivial (a single preprocessor symbol,
- X DDDDBBBBUUUUGGGG____OOOOFFFFFFFF, forces the macro expansions to be null).
- X
- X Also notice the inclusion of the header file ddddbbbbuuuugggg....hhhh
- X from the local header file directory. (The version included
- X here is the test version in the dbug source distribution
- X directory). This file contains all the definitions for the
- X debugger macros, which all have the form DDDDBBBBUUUUGGGG____XXXXXXXX............XXXXXXXX.
- X
- X
- X The DDDDBBBBUUUUGGGG____EEEENNNNTTTTEEEERRRR macro informs that debugger that we have
- X entered the function named mmmmaaaaiiiinnnn. It must be the very first
- X "executable" line in a function, after all declarations and
- X before any other executable line. The DDDDBBBBUUUUGGGG____PPPPRRRROOOOCCCCEEEESSSSSSSS macro is
- X generally used only once per program to inform the debugger
- X what name the program was invoked with. The DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro
- X modifies the current debugger state by saving the previous
- X state and setting a new state based on the control string
- X passed as its argument. The DDDDBBBBUUUUGGGG____PPPPRRRRIIIINNNNTTTT macro is used to
- X print the values of each argument for which a factorial is
- X to be computed. The DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN macro tells the debugger
- X that the end of the current function has been reached and
- X returns a value to the calling function. All of these
- X macros will be fully explained in subsequent sections.
- X
- X To use the debugger, the factorial program is invoked
- X with a command line of the form:
- X
- X factorial -#d:t 1 2 3
- X
- X The mmmmaaaaiiiinnnn function recognizes the "-#d:t" string as a
- X debugger control string, and passes the debugger arguments
- X ("d:t") to the _d_b_u_g runtime support routines via the
- X DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro. This particular string enables output from
- X the DDDDBBBBUUUUGGGG____PPPPRRRRIIIINNNNTTTT macro with the 'd' flag and enables function
- X tracing with the 't' flag. The factorial function is then
- X called three times, with the arguments "1", "2", and "3".
- X Note that the DBUG_PRINT takes exactly ttttwwwwoooo arguments, with
- X the second argument (a format string and list of printable
- X values) enclosed in parenthesis.
- X
- X Debug control strings consist of a header, the "-#",
- X followed by a colon separated list of debugger arguments.
- X Each debugger argument is a single character flag followed
- X by an optional comma separated list of arguments specific to
- X the given flag. Some examples are:
- X
- X
- X
- X
- X
- X - 7 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X -#d:t:o
- X -#d,in,out:f,main:F:L
- X
- X Note that previously enabled debugger actions can be
- X disabled by the control string "-#".
- X
- X
- X The definition of the factorial function, symbolized as
- X "N!", is given by:
- X
- X N! = N * N-1 * ... 2 * 1
- X
- X Figure 5 is the factorial function which implements this
- X algorithm recursively. Note that this is not necessarily
- X the best way to do factorials and error conditions are
- X ignored completely.
- X
- X
- X
- X #include <stdio.h>
- X /* User programs should use <local/dbug.h> */
- X #include "dbug.h"
- X
- X int factorial (value)
- X register int value;
- X {
- X DBUG_ENTER ("factorial");
- X DBUG_PRINT ("find", ("find %d factorial", value));
- X if (value > 1) {
- X value *= factorial (value - 1);
- X }
- X DBUG_PRINT ("result", ("result is %d", value));
- X DBUG_RETURN (value);
- X }
- X
- X
- X Figure 5
- X Factorial Function
- X
- X
- X
- X
- X
- X One advantage (some may not consider it so) to using
- X the _d_b_u_g package is that it strongly encourages fully
- X structured coding with only one entry and one exit point in
- X each function. Multiple exit points, such as early returns
- X to escape a loop, may be used, but each such point requires
- X the use of an appropriate DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN or DDDDBBBBUUUUGGGG____VVVVOOOOIIIIDDDD____RRRREEEETTTTUUUURRRRNNNN
- X macro.
- X
- X
- X
- X
- X - 8 -
- X
- X
- X
- X
- X
- X
- X
- X DBUG User Manual October 29, 1986
- X
- X
- X
- X To build the factorial program on a UUUUNNNNIIIIXXXX system,
- X compile and link with the command:
- X
- X cc -o factorial main.c factorial.c -ldbug
- X
- X The "-ldbug" argument tells the loader to link in the
- X runtime support modules for the _d_b_u_g package. Executing the
- X factorial program with a command of the form:
- X
- X factorial 1 2 3 4 5
- X
- X generates the output shown in figure 6.
- X
- X
- X
- X 1
- X 2
- X 6
- X 24
- X 120
- X
- X
- X Figure 6
- X factorial 1 2 3 4 5
- SHAR_EOF
- true || echo 'restore of dmake/dbug/dbug/dbug.p failed'
- fi
- echo 'End of part 3, continue with part 4'
- echo 4 > _shar_seq_.tmp
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-