|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 7978 (0x1f2a)
Types: TextFile
Names: »dbg.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec8/uutty/dbg.c«
/* John Chambers' debugging package for C programs. This
** package is intended, among other things, to be added to
** other peoples' software after the fact to aid in getting
** it to run. An attempt has been made to avoid global
** names that others will use, though there are likely
** to be collisions with other debugging packages. The
** most common source of conflicts is due to the fact that
** this package includes <stdio.h> and <sys/types.h>; you
** should hunt down references to either of these and put
** the line:
** #include <dbg.h>
** in place of both of them.
**
** The primary functions defined here are based on conditional
** calls of printf(), with the program's name inserted at the
** start, a newline appended, and fflush() called to send it
** on its way. There is also a hexdump() routine to produce
** a hex dump of a chunk of memory, and an ascdump() routine
** to display things in ASCII form. All these are intended
** to be called via the macros defined in "dbg.h".
**
** The global variable "debug" should be set to a value in [0,9],
** to control the amount of debugging output.
**
** Note that "dbgout" is a FILE*, either stdout or stderr as you
** wish, with stderr the default.
*/
#include "dbg.h"
static char dbgheader[] = "@(#)RELEASE: 1.0 Sep 20 1986 ~jc/dbg";
/*
** If you normally use terminals with a particular line
** length, you might adjust these. Note that there is
** an initial 7-byte fieldin all lines, plus a newline,
** so MAXCOLS should be >= MAXCHS+8.
*/
#define MAXCOLS 80 /* Max length of print line */
#define MAXCHRS 64 /* Max chars in one hexdump chunk */
extern int errno; /* Unix error code */
char *crlf = "\n"; /* Line terminator string, might be "\n\r" */
FILE *dbgout = stderr; /* Can be assigned to switch to stdout */
int dbgsleep = 0; /* Sleep time (secs) after messages */
int debug = 1; /* Set to desired debug level (0-9) */
char *dbgtimep = 0; /* Set to ASCII date/time if desired in output */
static int hex_chrs = MAXCHRS; /* Number of chars to dump in one line */
static int hex_cols = MAXCOLS; /* Length of print line */
static int hex_word = MAXCHRS; /* Number of bytes to group together */
char *progname = "?"; /* Set to argv[0] */
/*
** Debug output routine. The program's name is
** prepended to the message, a terminator is added,
** and an optional sleep is done.
*/
/*VARARGS1*//*ARGSUSED*/
dmsg(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) char *fmt;
{ int n;
n = fprintf(dbgout,"%s: ",progname);
n += fprintf(dbgout,fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
n += fprintf(dbgout,crlf);
fflush(dbgout);
if (dbgsleep) sleep(dbgsleep);
return n;
}
/* Note that emsg() writes to both dbgout and stderr.
*/
/*VARARGS1*//*ARGSUSED*/
emsg(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) char *fmt;
{ int n;
if (dbgout != stderr)
n = dmsg(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
n += fprintf(stderr,"%s: ",progname);
n += fprintf(stderr,fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
n += fprintf(stderr,crlf);
fflush(stderr);
return n;
}
/* Print a message to the debug output, adding only
** a terminator, but don't add program identification.
*/
/*VARARGS1*//*ARGSUSED*/
pmsg(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) char *fmt;
{ int n;
n = fprintf(dbgout,fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
n += fprintf(dbgout,crlf);
fflush(dbgout);
if (dbgsleep) sleep(dbgsleep);
return n;
}
/* Write a message to the debug output, adding nothing.
*/
/*VARARGS1*//*ARGSUSED*/
wmsg(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) char *fmt;
{ int n;
n = fprintf(dbgout,fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
fflush(dbgout);
if (dbgsleep) sleep(dbgsleep);
return n;
}
/*
** Hexdump routine. The params are a starting address,
** a byte count, an address to show on the output (which
** is often the starting address), and an optional message
** for labeling the dump. If the message is present, the
** address is not displayed, since they both would appear
** at the same place in the output.
**
** Note that the actual output is done by pmsg().
*/
static char hex_cc[1+MAXCOLS];
static char hex_hi[1+MAXCOLS];
static char hex_lo[1+MAXCOLS];
static int ascfl = 0; /* True if hex dump not wanted */
/*
** Produce only the ASCII line; omit the two hex lines.
*/
ascdump(a,n,o,m)
char *a; /* Address of first byte to dump */
U32 n; /* Number of bytes */
char *o; /* Offset (address) to report */
char *m; /* Initial message, if o==NUL */
{ int c;
D4("ascdump(a=%06lX,n=%d,o=%06lX,m=%06lX)",a,n,o,m);
if (dbgtimep) fprintf(dbgout,"%s ",dbgtimep);
if (m) sprintf(hex_cc,"%s ",m);
else sprintf(hex_cc,"%7d ",o);
fprintf(dbgout,"%7.7s",hex_cc);
fflush(dbgout);
while (n-- > 0) {
c = *a++ & 0x7F;
switch (c) {
case '\0': fprintf(dbgout,"\\0"); break;
case '^' : fprintf(dbgout,"\\^"); break;
case '\\': fprintf(dbgout,"\\\\"); break;
case '\b': fprintf(dbgout,"\\b"); break;
case '\n': fprintf(dbgout,"\\n"); break;
case '\r': fprintf(dbgout,"\\r"); break;
case '\t': fprintf(dbgout,"\\t"); break;
case 0x7F: fprintf(dbgout,"\\D"); break;
default:
if (c < ' ') {
fprintf(dbgout,"^%c",c|0x40);
break;
}
fprintf(dbgout,"%c",c);
break;
}
}
fprintf(dbgout,crlf);
fflush(dbgout);
}
/*
*/
hexdump(a,n,o,m)
char *a; /* Address of first byte to dump */
U32 n; /* Number of bytes */
U32 o; /* Offset (address) to report */
char *m; /* Initial message, if o==NUL; -1 for ascii only */
{
ascfl = 0;
return hex_dump(a,n,o,m);
}
/*
*/
hex_dump(a,n,o,m)
char *a; /* Address of first byte to dump */
U32 n; /* Number of bytes */
U32 o; /* Offset (address) to report */
char *m; /* Initial message, if o==NUL; -1 for ascii only */
{ int col, i;
char c;
hex_init(m,o);
col = 0;
while (n) {
c = *a++;
i = 7 + col + (col / hex_word);
n--;
hex_lo[i] = hex_dig(c & 0xF);
hex_hi[i] = hex_dig((c >> 4) & 0xF);
hex_cc[i] = dsp(c);
col++;
o++;
if (col >= hex_chrs) {
hex_out();
hex_init(m,o);
col = 0;
}
}
if (col > 0) hex_out();
return 0;
}
/* Generate a printable char for x. If x is an ASCII
** printable char, it is returned. For others, '_' is
** returned.
*/
dsp(x)
{ x &= 0x7F;
return (0x20<=x && x<=0x7E) ? x : '_';
}
/* Given a small integer [0-15], this routine returns
** the corresponding ASCII char for a hex digit.
*/
hex_dig(x)
{ return ( 0<=x && x<= 9) ? '0' + x
: (10<=x && x<=15) ? 'A' + x - 10
: '_';
}
/* Initialize the line images for a given address.
*/
hex_init(m,a)
char *m; /* Initial message (<=8 chars) */
U32 a; /* Address reported on output */
{ int i;
i = hex_chrs + (hex_chrs / hex_word) + 8; /* Length of print line (including final newline) */
if (hex_cols < i) {
hex_cols = i;
D5("hex_init: cols=%d chrs=%d word=%d",hex_cols,hex_chrs,hex_word);
}
for (i=0; i<=hex_cols; i++)
hex_cc[i] = hex_hi[i] = hex_lo[i] = ' ';
if (m && a==0) {
strcpy(hex_cc,m);
} else {
sprintf(hex_cc,"%6ld: ",a);
sprintf(hex_hi,"%6lX: ",a);
}
return 0;
}
/* The three lines of hex dump info are complete;
** do a bit of straightening out, and print them.
*/
hex_out()
{ int i;
for (i=0; i<=hex_cols; i++) { /* sprintf() may produce nulls */
if (hex_cc[i] == 0) hex_cc[i] = ' ';
if (hex_hi[i] == 0) hex_hi[i] = ' ';
if (hex_lo[i] == 0) hex_lo[i] = ' ';
}
for (i=hex_cols; i>0; i--) /* Trim lines */
if (hex_cc[i] == ' ')
hex_cc[i] = 0;
else break;
for (i=hex_cols; i>0; i--)
if (hex_hi[i] == ' ')
hex_hi[i] = 0;
else break;
for (i=hex_cols; i>0; i--)
if (hex_lo[i] == ' ')
hex_lo[i] = 0;
else break;
if (dbgtimep) fprintf(dbgout,"%s ",dbgtimep);
pmsg("%s",hex_cc); /* Symbolic dump */
if (ascfl == 0) {
if (dbgtimep) fprintf(dbgout,"%s ",dbgtimep);
pmsg("%s",hex_hi); /* High-order hex digit */
if (dbgtimep) fprintf(dbgout,"%s ",dbgtimep);
pmsg("%s",hex_lo); /* Low-order hex digit */
}
if (dbgsleep) sleep(dbgsleep);
return 0;
}