home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1294
< prev
next >
Wrap
Internet Message Format
|
1990-12-28
|
32KB
From: new@udel.EDU (Darren New)
Newsgroups: alt.sources
Subject: #define DEBUG (Real source in this posting! oohhh!)
Message-ID: <18965@estelle.udel.EDU>
Date: 9 May 90 18:19:54 GMT
Since I don't have any way of making a shar file, I'm just going to
put these all together. Split apart at the lines containing
+=+=+=+=+ filename
Note that these sources are CBM-Amiga specific to the extent that
they do I/O to a separate window. However, changing this is not much
of a problem. They also include their own version of "printf" which may
need to be hacked for your system. I've found this to be incredibly
useful but no substitute for a real symbolic debugger. Have fun. -- Darren
+=+=+=+=+ DBugLib.doc
These files Created 7/86 by Darren New.
Released to the PUBLIC DOMAIN. No rights reserved.
Do anything you want with it.
Simple request: if you make a significant profit from this, or if you have
improvements or suggestions, please contact me at
new@udel.edu
(the request about profit just for my curiosity)
DISCLAIMER: As I am not making money from this, I am not going to be
oblicated to support it, either. Thus, THIS IS SUPPLIED "AS IS". No
warranty of any kind is made or implied. Lattice is a registered trademark
of Lattice, Inc. Thus endeth the A__-covering.
--------------------------------------------------------------------------
This set of functions is for debugging programs.
The function DEBUG_OPEN() opens a new console at the bottom of the screen.
This console is read and written by DEBUGF(). DEBUG_CLOSE() will close
this console, freeing it's memory. Eventually, I hope to write these
things as resources or devices, or something where everyone doing debug
output will write to the same console so that multi-tasking functions
can be debuged more easily. (Probably shortly after I start coding
multi-process programs myself...)
The main advantages of these functions over most of the debugging macros
already out there are these:
They write to a separate window, so even things with no windows or that do
ANSI stuff and so on can be debugged. Another advantage is that they are
interactive -- pure macros must be recompiled and relinked to be disposed;
these functions can be turned on and off at run time. Of course, a simple
compiler switch can remove all trace of these from the object files, just
like most of the debugging packages. The debugging info can be sent to a
file or to the printer for really sticky problems. Also, user's functions
can be called from the keyboard from within the debug functions. Although
this does take a little setup, it can be worthwhile for stepping through a
program until you start getting strange errors, and then popping back to
your program someplace else in order to examine variables, dump files, or
whatever; I imagine it could also be used to clean up and exit from the
debugger. Finally, it uses AmigaDOS calls only; no Lattice library calls or
STDIO calls or anything like that. If you have a "tiny" program, this may
be helpful.
All traces of these function will be removed from the program if the
preprocessor symbol USE_DBUGLIB is zero. They will be compiled in if the
preprocessor symbol USE_DBUGLIB is one. Note that this takes effect only
when the header <DBugLib.h> is included; i.e., you can't turn them on and
off in the same file. If USE_DBUGLIB is undefined when the header file is
included, it's value will be one if DEBUG is defined, and zero if DEBUG
is not defined. Note also that under Lattice, the -d switch (pass 1) will
#define DEBUG for you.
Note that in order for the macros to remove the function calls with variable
arguments (under Lattice, at least), any arguments after the formatting
string must be separated from the preceeding argument not by a comma, but by
the pre-processor symbol "COMMA". This turns all of the variable args into
one argument if "COMMA" is not defined. Credit for this technique is hereby
given to "Dr. Bob", the author of "DEBUGC", found elsewhere.
DEBUG_OPEN(S) ---> void
Opens the console. All other debug functions will be ignored
while the console is closed. If S is NULL, the default console string
is used as the file name for the Open call. If S is not NULL, that string
will be used as the filename. If the console can not be opened,
DisplayBeep() in a pattern indicative of the error. Calling this is not an
error the debugging console is already open. This automatically gets
called whenever DEBUG_ENTER() gets called and the nesting stack is empty;
usually, this means main() is calling it for the first time.
DEBUG_CLOSE() ---> void
Closes the console. It is not an error to call this when the console
is already closed. The console is automatically closed when DEBUG_RETURN is
called from the (seemingly) outermost proceedure.
DEBUGF(I, SF COMMA A1 COMMA A2 COMMA ...) ---> char *
Other arguments just like PRINTF. The output is formatted and sent
to the debug console. One key is accepted from the keyboard, and interpreted
as follows:
P the debug line is sent to the PRT: device, which is opened until
the next DEBUG_CLOSE() if not already open.
Q DEBUG_CLOSE() will be called, causing deugging output to be disabled
until DEBUG_OPEN is called again.
F debugging output will be appended to :T/DEBUGOUT, which will be
opened if not already opened. If 'f' is typed, the file will
remain open until DEBUG_CLOSE() is called. If 'F' is typed, the
file will be closed immediately.
B the debugging window will be closed and reopened full size. (big)
If 'b' is entered, the window will be 200 scan lines high.
If 'B' is entered, the window will be 400 scan lines high.
T DEBUG_TRACEBACK() will be called.
C the previous action (other than T) will be repeated without pause
until DEBUG_OPEN or DEBUG_CLOSE is called again. Good for
CONTINUOUS output to a file or printer. Type a space to the debug
window to regain control.
N Nest: prompts for a digit 0 through 9. Any DEBUG_ENTER
which causes the nesting level to exceed this will still be
remembered, but will not generate any output on the debug console.
Zero turns off all the reports except "main". A space typed in
response to the prompt allows all nestings to display.
D Detail: prompts for a digit 0 through 9. Any DEBUGF specifying an I
larger than this number will not generate any output. A space typed
in response to the prompt allows all details to display. Note that
detail level of zero will always display.
S Skip: debugging output will be discarded until a DEBUG_RETURN is
called which restores the nesting level to the current level or
lower. Essentially, debugging is turned off until the current
function calls DEBUG_RETURN().
0 thru 9
DEBUG_FUNC[0] thru DEBUG_FUNC[9] will be called if not NULL. Note
that this could be ugly if the user does not fill in this global
array with pointers to functions.
RETURN just return
SPACE Same as return
The routine will keep scanning the keyboard until a C or a newline (return)
or S is detected, at which point it return. Thus, several actions can be
taken on a single debug statement.
DEBUG_CONSOLE() ---> long
Returns 0 if the debugging console is not open, otherwise returns
a pointer to the open console, suitable for Read() and Write(). Don't
Close() this yourself, or future calls to DEBUG may crash.
DEBUG_ENTER(S, SF COMMA A1 COMMA A2 COMMA ...) ---> void
Pass in the name of the function being entered. This will be
remembered, even if the console is closed. If SF is not NULL, then the args
after it (if any) are formatted as in PRINTF and displayed. If this is
first called when the console is closed, it is assumed to be being called
from main(), and calls DEBUG_OPEN(NULL) for you.
DEBUG_RETURN(SF COMMA A1 COMMA A2 COMMA ...) ---> void
Indicates that the most recent function to call DEBUG_ENTER is
now returning. Automatically closes the colsole and otherwise makes sure
that all resources have been freed if the nesting stack goes empty;
it is assumed that you are about to exit from main(). This will
eventually be implemented as a macro that actually returns the value of A1,
if I can figure out how to cast the type properly; the problem is one of
side-effects, mainly.
DEBUG_EXIT() ---> void
Frees all resources used by any of the DEBUG functions. Must be
called before a call to Exit(), exit(), _exit(), or whatever; otherwise, you
will be left with a console sitting around that you can't close.
There will probably be much more over time, maybe including a program to
automatically insert debugging calls into the program for you.
In the future, I plan to add floating point support. If I hear requests, I
may do it before I need it myself. If anyone is interrested in adding it
themselves, I have the fuctions to format the numbers; they just have not
been incorporated into the DO_PRNT function.
+=+=+=+=+ DBugLib.h
/*
This is the header file for the DBugLib package.
Include it while debugging.
*/
#ifndef USE_DBUGLIB
#ifdef DEBUG
#define USE_DBUGLIB 1
#else
#define USE_DBUGLIB 0
#endif
#endif
#if USE_DBUGLIB==1
#define COMMA , /* thanks, Dr. Bob! */
#define C ,
extern void (*DEBUG_FUNC[10])(); /* List of debugging functions */
extern void DEBUG_OPEN(char *);
extern void DEBUG_CLOSE(void);
extern void DEBUGF(int, char *, );
extern void DEBUG_ENTER(char *, char *, );
extern long DEBUG_CONSOLE(void);
extern void DEBUG_RETURN(char *, );
extern void DEBUG_EXIT(void);
extern void DEBUG_TRACEBACK(void);
extern void DEBUG_SETDEFS(char *, char *);
#else
#define DEBUG_OPEN(name) /* nothing */
#define DEBUG_CLOSE() /* nothing */
#define DEBUGF(lev, args) /* nothing */
#define DEBUG_ENTER(name, args) /* nothing */
#define DEBUG_CONSOLE() /* nothing -- shouldn't be referenced */
#define DEBUG_RETURN(args) /* nothing */
#define DEBUG_EXIT() /* nothing */
#define DEBUG_TRACEBACK() /* nothing */
#define DEBUG_SETDEFS(con, file) /* nothing */
#endif
+=+=+=+=+ DBugLib.c
/*
THIS IS "DBUGLIB.C"
Written 7/86 Darren New.
PUBLIC DOMAIN -- May be freely distributed.
See DBugLib.Doc for instructions and details.
To avoid loading STDIO under lattice, compile with -v
*/
#include "exec/types.h"
#include "exec/memory.h"
#include "libraries/dos.h"
#include "proto/exec.h"
#include "proto/dos.h"
#include "string.h"
void (*DEBUG_FUNC[10])(); /* List of debugging functions */
/* default default console */
char * def_deb_console = "RAW:0/130/640/70/Debug Console ";
/* default default debug output file */
char * def_deb_file = ":t/DebugOut";
static long console; /* Actually, this should be a file handle */
#define MUL 65000 /* Multiplyer for delays between flashes */
static char last_answer; /* last char typed -- used by 'C' */
static char last_was_c; /* true if 'C'ing, false otherwise */
static char last_was_skip; /* true if 'S'kiping, false otherwise */
static char * nest_list; /* by TRACEBACK */
static int nest_level; /* by TRACEBACK */
static int skip_level; /* for SKIP */
static long skip_con_hold; /* for SKIP */
static int max_nest_level = 9999; /* by ENTER, RETURN */
static int max_detail = 9999; /* by DEBUGF */
static long db_file_handle; /* handle to debug file */
static long db_prt_handle; /* handle to printer */
static char * laststr; /* pointer to last string typed */
static long laststralloc; /* space allocated for laststr */
static char nosave; /* CONWRITE will not append to laststr */
static char cleol; /* just to pass stuff around */
static void addon(s)
register char * s;
{
register char * newstr;
/* add S to the end of laststr */
if (nosave) return;
again:
if (strlen(laststr) + strlen(s) + 1 >= laststralloc) {
newstr = (char *) AllocMem(laststralloc + strlen(s) + 125,
MEMF_CLEAR);
if (newstr == 0) {
if (laststralloc == 0) {
/* out of memory */
return;
}
FreeMem(laststr, laststralloc);
laststralloc = 0; laststr = "";
goto again;
}
strcpy(newstr, laststr);
FreeMem(laststr, laststralloc);
laststralloc += strlen(s) + 125;
laststr = newstr;
}
strcat(laststr, s);
}
static void conwrite(s)
char * s;
{
if (console != 0) {
Write(console, s, strlen(s));
addon(s);
}
}
static void conwriteint(i)
register int i;
{
char s[10];
if (i > 32760) i = 32760;
s[0] = '0' + i / 10000 ;
s[1] = '0' + i / 1000 % 10;
s[2] = '0' + i / 100 % 10;
s[3] = '0' + i / 10 % 10;
s[4] = '0' + i % 10;
s[5] = '\0';
conwrite(s);
}
static void conwritechar(c)
char c;
{
char buf[2];
buf[0] = c; buf[1] = '\0';
conwrite(buf);
}
static void sendto(a)
long a;
{
register int i;
if (console == 0) return;
if (strlen(laststr) != Write(a, laststr, strlen(laststr))) {
nosave = 1;
last_was_c = 0;
i = IoErr();
conwrite("\033[1mError during output: ");
conwriteint(i);
conwrite("\nTry again...\033[0m\n");
nosave = 0;
}
}
static void isyt()
{
if (!last_was_c) {
nosave = 1;
cleol = 1;
conwrite("\033[1m It's still your turn...\033[0m\r");
nosave = 0;
}
}
static void getresp()
{
char buf;
register int i;
register int oncet;
extern void DEBUG_TRACEBACK();
if (console == 0) return;
oncet = 0;
again:
/* This gives him 1/10 seconds for each debug in continuous mode */
if (! last_was_c || WaitForChar(console, 100000)) {
last_was_c = 0;
Read(console, &buf, 1);
}
else if (oncet) {
buf = ' ';
}
else {
oncet = 1;
buf = last_answer;
}
if (cleol) {
nosave = 1; conwrite("\033[0m\033[K"); nosave = 0;
cleol = 0;
}
/* Process buffer here */
switch (buf) {
case 'N':
case 'n':
nosave = 1;
conwrite("\033[1mEnter maximum nest level or ' ' for all:\033[0m ");
Read(console, &buf, 1);
if (buf <= '9' && buf >= '0') {
conwritechar(buf);
max_nest_level = buf - '0';
}
else if (buf == ' ')
max_nest_level = 99999;
else
conwritechar('\007', NULL);
isyt();
goto again;
case 'D':
case 'd':
nosave = 1;
conwrite("\033[1mEnter maximum detail level or ' ' for all:\033[0m ");
Read(console, &buf, 1);
if (buf <= '9' && buf >= '0') {
conwritechar(buf, NULL);
max_detail = buf - '0';
}
else if (buf == ' ')
max_detail = 9999;
else
conwritechar('\007', NULL);
isyt();
goto again;
case 'S':
case 's':
skip_con_hold = console;
last_was_skip = 1;
skip_level = nest_level;
console = 0; /* temp suspend debugging till return reached */
goto outness; /* Do NOT try to attempt any more output */
case 'P':
case 'p':
last_answer = buf;
if (db_prt_handle == 0)
db_prt_handle = Open("PRT:", MODE_OLDFILE);
if (db_prt_handle == 0) {
i = IoErr();
nosave = 1;
last_was_c = 0;
conwrite("\033[1mError opening printer: ");
conwriteint(i);
conwrite("\n\033[0m\007");
nosave = 0;
isyt();
goto again;
}
sendto(db_prt_handle);
isyt();
goto again;
case 'F':
case 'f':
last_answer = buf;
if (db_file_handle == 0)
db_file_handle = Open(def_deb_file, MODE_OLDFILE);
if (db_file_handle != 0)
Seek(db_file_handle, 0, OFFSET_END);
if (db_file_handle == 0) {
i = IoErr();
if (i == ERROR_OBJECT_NOT_FOUND)
db_file_handle = Open(def_deb_file, MODE_NEWFILE);
}
if (db_file_handle == 0) {
last_was_c = 0;
i = IoErr();
nosave = 1;
conwrite("\033[1mError opening file: ");
conwriteint(i);
conwrite("\n\033[0m\007");
nosave = 0;
isyt();
goto again;
}
sendto(db_file_handle);
if (buf == 'F') {
if (db_file_handle != 0)
Close(db_file_handle);
db_file_handle = 0;
}
isyt();
goto again;
case 'C':
case 'c':
last_was_c = 1;
break;
case 'Q':
case 'q':
Close(console);
console = 0; last_answer = 0; last_was_c = 0;
break;
case 'B':
case 'b':
Close(console);
if (buf == 'B')
console = Open("RAW:0/0/640/400/Debug Console ", MODE_NEWFILE);
else
console = Open("RAW:0/0/640/200/Debug Console ", MODE_NEWFILE);
if (console == 0) { /* could not open */
long ioerr, tl1, tl2;
ioerr = IoErr();
/* Flash hundreds */
for (tl1 = 0; tl1 < ioerr / 100; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
/* Flash tens */
for (tl1 = 0; tl1 < ioerr / 10 % 10; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
/* Flash ones */
for (tl1 = 0; tl1 < ioerr % 10; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
}
sendto(console);
isyt();
goto again;
case 'T':
case 't':
DEBUG_TRACEBACK((long) 0xBADD1E);
isyt();
goto again;
case '0': case '5':
case '1': case '6':
case '2': case '7':
case '3': case '8':
case '4': case '9':
if (DEBUG_FUNC[(int) buf - '0'])
(*DEBUG_FUNC[(int) buf - '0'])();
isyt();
break;
case '\0': /* continuous */
case '\r':
case '\n':
case ' ':
if (!last_was_c) last_answer = buf;
break;
default:
nosave = 1;
conwrite("\033[1mI don't understand ");
conwriteint(buf);
conwrite("\033[0m\n\007");
nosave = 0;
isyt();
goto again;
}
outness:
/* if (laststralloc > 0) {
FreeMem(laststr, laststralloc);
laststr = "";
laststralloc = 0;
} */
if (laststralloc > 0) {
laststr[0] = '\0';
}
}
/******* CODE FROM AUSTIN CODE WORKS, MODIFIED BY DHN *******/
#define EOS ('\0')
#define BITS_PER_CHAR 8
/*
* WORKSIZE is the dimension of work[] which must hold enough characters
* to store a long integer (expanded using the %b format) + '-' and EOS
*/
#define WORKSIZE (((sizeof (long)) * BITS_PER_CHAR) + 2)
struct fmtbuf {
char f_type; /* Format type ('d', etc.) */
char f_width; /* Argument width (INT or LONG) */
char f_radix; /* Argument radix (8, 10, etc.) */
};
#define INT 0
#define LONG 1
#define NEG 2 /* Signal for output of '-' */
/*
* formatinfo[] stores information about the "value" formats
*/
static struct fmtbuf formatinfo[] = {
{ 'b', INT, 2 },
{ 'd', INT, 10 },
{ 'o', INT, 8 },
{ 'u', INT, 10 },
{ 'x', INT, 16 },
{ 'p', LONG, 16 },
{ 'B', LONG, 2 },
{ 'D', LONG, 10 },
{ 'O', LONG, 8 },
{ 'U', LONG, 10 },
{ 'X', LONG, 16 },
{ 'P', LONG, 16 },
{ EOS, 0, 0 },
};
void c_doprnt(format, argp, func)
char *format; /* Format string */
register int *argp; /* Argument vector pointer */
int (*func)(); /* Output Function */
{
register int c;
register struct fmtbuf * pfmt;
register char * presult;
char ljust; /* TRUE for left-justification */
char work[WORKSIZE]; /* Number buffer */
char fill; /* '0' or ' ' for fill */
int prec; /* Precision */
int slen; /* Field length */
int width; /* Argument width */
unsigned long value;
int temp; /* Set if '-' needed. */
short radix; /* Conversion radix */
while ((c = *format++) != EOS) {
/*
* Check for conversion specifications.
*/
if (c == '%') {
/*
* Check for various options.
*/
c = *format++;
ljust = 0; /* No left adjustment */
fill = ' '; /* Fill with spaces */
if (c == '-') { /* %- left justify */
ljust++;
c = *format++;
}
if (c == '0') { /* %0d zero fill arg. */
fill = c;
c = *format++;
}
if (c == '?' || c == '*') { /* %* width from arg */
width = *argp++;
c = *format++;
}
else { /* %n field width */
width = 0;
while (isdigit(c)) {
width *= 10;
width += (c - '0');
c = *format++;
}
}
if (c == '.') { /* %n.n precision */
c = *format++; /* %n.* (from arg) */
if (c == '?' || c == '*') {
prec = *argp++;
c = *format++;
}
else {
prec = 0;
while (isdigit(c)) {
prec *= 10;
prec += (c - '0');
c = *format++;
}
}
}
else {
prec = 32767; /* No prec. specified */
}
/*
* Magic code for pointer -- dhn
*/
if (c == 'p' || c == 'P') {
fill = '0'; width = 6 + 2 * isupper(c);
}
/*
* Process conversion chars, understanding longs.
*/
if (c == 'l' || c == 'L') {
switch (c = *format++) {
case 'b':
case 'd':
case 'o':
case 'u':
case 'x':
c = toupper(c); /* Make %lb %B */
case 'B':
case 'D':
case 'O':
case 'U':
case 'X':
break;
default: /* Here on %Lfoo ==> %Ufoo */
c = 'U';
format--;
break;
}
}
/*
* Search the numeric format structure for this conversion.
*/
for (pfmt = formatinfo;
(pfmt->f_type != c && pfmt->f_type != EOS);
pfmt++)
;
if (pfmt->f_type != EOS) {
/*
* A numeric conversion was found.
* Get the value and expand it into the work area.
*/
radix = pfmt->f_radix;
temp = pfmt->f_width;
presult = &work[WORKSIZE];
*--presult = EOS; /* Terminate result */
if (temp == INT) {
if (c == 'd' && *argp < 0) {
value = -*argp++;
temp = NEG; /* Remember signal */
}
else
value = (unsigned) *argp++;
}
else {
value = * (long *) argp;
argp += (sizeof(long) / sizeof(*argp));
}
if (value == 0)
*--presult = '0';
else {
/*
* Convert an unsigned non-zero number.
*/
do {
c = value % radix;
*--presult = c + ((c < 10) ? '0' : ('A' - 10));
} while ((value /= radix) != 0);
if (temp == NEG)
*--presult = '-';
}
}
else {
/*
* String or something
*/
switch (c) {
case 'q': /* Funny int value */
/*
* Convert a word as a pair of octal bytes.
*/
c = 16384;
presult = work;
temp = *argp++;
while (c > 0) {
*presult++ = (temp / c) + '0';
temp %= c;
if (c == 256) {
c = 64;
*presult++ = '.';
}
else
c >>= 3;
}
*presult = EOS;
presult = work;
break;
case 'r': /* Remote format */
argp = (int *) *argp;
format = (char *) *argp++;
continue; /* No print here */
case 's': /* String */
if ((presult = (char *) *argp++) == NULL)
presult = "{NULL}"; /* Bug hack */
break;
case 'c': /* Character */
c = *argp++;
/*
* Fall through
*/
default: /* %% or whatever */
presult = work;
*presult = c;
work[1] = EOS;
break;
}
}
/*
* presult -> first byte of string to output.
* Reuse c as a register temp.
*/
c = strlen(presult); /* True result length */
slen = (c > prec) ? prec : c; /* Field length */
if (!ljust) { /* Right justify? */
while (--width >= slen) {
(*func)(fill);
}
}
/*
* Output the string (up to "prec" bytes)
*/
for (c = prec; *presult != EOS && --c >= 0;) {
(*func)(*presult++);
}
if (ljust) { /* Left justify? */
while (--width >= slen) {
(*func)(' ');
}
}
}
else {
/*
* Not in a % thing, just output the byte.
*/
(*func)(c);
}
}
return;
}
/******** END CODE FROM AUSTIN CODE WORKS *********/
void DEBUG_OPEN(s)
register char * s;
{
register long tl1; /* temp loop var 1 */
register long tl2; /* temp loop var 2 */
register int ioerr;
/* Open debugging console, if not already open. Init stuff */
if (skip_con_hold) {
/* open stops skipping */
console = skip_con_hold;
skip_con_hold = 0; last_was_skip = 0;
skip_level = 0;
}
if (s == NULL) {
s = def_deb_console;
}
last_answer = '\0'; last_was_c = 0;
if (laststralloc > 0) {
FreeMem(laststr, laststralloc);
laststr = "";
laststralloc = 0;
}
laststr = "";
nosave = 0;
if (console != 0) return;
console = Open(s, MODE_NEWFILE);
if (console == 0) { /* could not open */
ioerr = IoErr();
/* Flash hundreds */
for (tl1 = 0; tl1 < ioerr / 100; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
/* Flash tens */
for (tl1 = 0; tl1 < ioerr / 10 % 10; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
/* Flash ones */
for (tl1 = 0; tl1 < ioerr % 10; tl1++) {
Write(Output(), "\007", 1);
for (tl2 = 0; tl2 < MUL; tl2++) ;
}
}
else {
conwrite("\033[1mConsole is open.\033[0m\n");
}
}
void DEBUG_TRACEBACK(i)
long i;
{
char * holdit;
if (nest_level < 1) {
conwrite("DEBUG_TRACEBACK(): Too many returns!\n");
if (i != 0xBADD1E) getresp();
return;
}
if (nest_level <= max_nest_level || i == 0xBADD1E) {
/* Display nesting only if enters and returns showing, or if
called directly from keyboard */
conwrite("Stack traceback: current nest level is ");
conwriteint(nest_level);
holdit = nest_list;
while(holdit != NULL) {
conwrite("\n ");
conwrite(holdit + sizeof(char *));
holdit = * (char * *) holdit;
}
conwrite("\nEnd of stack traceback.\n");
if (i != 0xBADD1E) getresp();
}
}
void DEBUGF(sevlev, fmtstr, args)
int sevlev;
char * fmtstr;
int args;
{
if (console == 0 || sevlev > max_detail) return;
if (fmtstr == NULL) return;
nosave = 1; conwrite("\033[0 p"); nosave = 0; /* turn off cursor */
c_doprnt(fmtstr, &args, conwritechar);
if (fmtstr[strlen(fmtstr)-1] != '\n')
conwrite("\n");
nosave = 1; conwrite("\033[ p"); nosave = 0; /* turn on cursor */
getresp();
}
void DEBUG_ENTER(s, sf, args)
register char * s;
char * sf;
int args;
{
register char * newmem;
register int i;
if (s == NULL) return;
if (nest_level == 0) DEBUG_OPEN(NULL);
if (nest_level <= max_nest_level) {
conwriteint(nest_level);
for (i = 0; i < nest_level; i++)
conwrite("=");
conwrite(">");
conwrite(s);
conwrite("\n");
if (sf != NULL) {
conwrite(" |--> ");
c_doprnt(sf, &args, conwritechar);
conwrite("\n");
}
}
newmem = (char *) AllocMem(sizeof(char *) + strlen(s) + 2, 0);
if (newmem == NULL) return;
(* (char * *) newmem) = nest_list;
strcpy(newmem + sizeof(char *), s);
nest_list = newmem;
nest_level += 1;
if (nest_level - 1 <= max_nest_level) getresp();
}
void DEBUG_CLOSE()
{
last_answer = '\0'; last_was_c = 0;
if (db_file_handle != 0) {
Close(db_file_handle);
conwrite("DB File is closed.\n");
db_file_handle = 0;
}
if (db_prt_handle != 0) {
Close(db_prt_handle);
conwrite("Printer is closed.\n");
db_prt_handle = 0;
}
if (skip_con_hold) {
console = skip_con_hold;
skip_con_hold = last_was_skip = skip_level = 0;
}
if (console != 0) {
conwrite("Console is closed.\n");
Close(console);
console = 0;
}
if (laststralloc > 0) {
FreeMem(laststr, laststralloc);
laststr = "";
laststralloc = 0;
}
}
void DEBUG_RETURN(sf, args)
char * sf;
int args;
{
int i;
char * holdit;
if (nest_level < 1) {
conwrite("DEBUG_RETURN(): Too many returns!\n");
getresp();
return;
}
nest_level -= 1;
if (last_was_skip && nest_level < skip_level) {
console = skip_con_hold;
skip_con_hold = 0; last_was_skip = 0; skip_level = 0;
}
if (nest_level <= max_nest_level) {
conwriteint(nest_level);
for (i = 0; i < nest_level; i++)
conwrite("=");
conwrite("<");
conwrite(nest_list + sizeof(char *));
conwrite("\n");
}
if (sf != NULL && nest_level <= max_nest_level) {
conwrite(" <---| ");
c_doprnt(sf, &args, conwritechar);
conwrite("\n");
}
if (nest_list != NULL) {
holdit = nest_list;
nest_list = * (char * *) nest_list;
FreeMem(holdit, sizeof(char *) + strlen(holdit +
sizeof(char *)) + 2);
}
if (nest_level <= max_nest_level) getresp();
if (nest_level == 0) DEBUG_CLOSE();
}
void DEBUG_EXIT()
{
if (skip_con_hold) console = skip_con_hold;
conwrite("About to DEBUG_EXIT()\n");
getresp();
while (nest_list != NULL) {
char * holdit;
holdit = nest_list;
nest_list = * (char * *) nest_list;
FreeMem(holdit, sizeof(char *) + strlen(holdit + sizeof(char *)) + 2);
}
DEBUG_CLOSE();
}
long DEBUG_CONSOLE()
{
return console;
}
void DEBUG_SETDEFS(con, file)
char * con;
char * file;
{
if (con != NULL)
def_deb_console = con;
if (file != NULL)
def_deb_file = file;
}
+=+=+=+=+ DBTest.c
/* This is the test program for the DBugLib package.
It exercises all features, assuming you actually attempt to
print, file, and so on. (put the include files where you want them)
Note that for ANYTHING to happen, #define DEBUG. This can be done in
Lattice by giving "-d" (alone) on the first pass. This also generates
line numbers in the quad file.
*/
#include <stdio.h>
#include "DBugLib.h"
void main(argc, argv)
int argc; char * argv[];
{
extern void exit(int);
DEBUG_ENTER("Alpha", "Decimal, then Hex: %d, %x" COMMA 123 COMMA 0x456);
DEBUG_ENTER("Beta", NULL);
DEBUGF(2, "If you type an 'F', this will go to a file");
DEBUGF(4, "Making sure long negatives work: %d %X" C -1L C -1L);
DEBUG_TRACEBACK();
DEBUG_RETURN(NULL);
DEBUGF(5, "Here, close the console. then, wait a while...");
DEBUGF(5, "This should not display on a closed console");
DEBUGF(5, "Neither should this");
DEBUG_OPEN(NULL);
DEBUGF(0, "This should always display");
DEBUGF(0, "About to play with Detail levels:");
DEBUGF(1, "ONE");
DEBUGF(2, "TWO");
DEBUGF(3, "THREE");
DEBUGF(4, "FOUR");
DEBUGF(5, "FIVE");
DEBUGF(6, "SIX");
DEBUGF(7, "SEVEN");
DEBUGF(8, "EIGHT");
DEBUGF(9, "NINE");
DEBUGF(10, "TEN");
DEBUGF(11, "ELEVEN");
DEBUGF(10, "Ten");
DEBUGF(9, "Nine");
DEBUGF(8, "Eight");
DEBUGF(7, "Seven");
DEBUGF(6, "Six");
DEBUGF(5, "Five");
DEBUGF(4, "Four");
DEBUGF(3, "Three");
DEBUGF(2, "Two");
DEBUGF(1, "One");
DEBUGF(0, "Zero");
DEBUG_TRACEBACK();
DEBUGF(0, "About to play with function calls:");
/* Level zero is Alpha */
DEBUG_ENTER("One", NULL);
DEBUG_ENTER("Two", NULL);
DEBUG_ENTER("Three", NULL);
DEBUG_ENTER("Four", NULL);
DEBUG_ENTER("Five", NULL);
DEBUG_ENTER("Six", NULL);
DEBUG_ENTER("Seven", NULL);
DEBUG_ENTER("Eight", NULL);
DEBUG_ENTER("Nine", NULL);
DEBUG_ENTER("Ten", NULL);
DEBUG_ENTER("Eleven", NULL);
DEBUGF(0, "This is a debug statement inside %d" COMMA 11);
DEBUG_TRACEBACK();
DEBUG_RETURN("Eleven");
DEBUG_RETURN("Ten");
DEBUG_RETURN("Nine");
DEBUG_RETURN("Eight");
DEBUG_TRACEBACK();
DEBUG_ENTER("Eight", NULL);
DEBUG_ENTER("Nine", NULL);
DEBUG_ENTER("Ten", NULL);
DEBUG_ENTER("Eleven", NULL);
DEBUG_TRACEBACK();
DEBUG_RETURN("Eleven");
DEBUG_RETURN("Ten");
DEBUG_RETURN("Nine");
DEBUG_RETURN("Eight");
DEBUG_TRACEBACK();
DEBUG_RETURN("Seven");
DEBUG_RETURN("Six");
DEBUG_RETURN("Five");
DEBUG_RETURN("Four");
DEBUG_TRACEBACK();
DEBUG_RETURN(NULL);
DEBUG_RETURN(NULL);
DEBUG_RETURN(NULL);
DEBUG_RETURN("Returning a string from alpha: |%s|" COMMA "A string!");
exit(0);
}
+=+=+=+=+ End of file