home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
fweb140x.zip
/
demos
/
breakpt.web
< prev
next >
Wrap
Text File
|
1993-10-30
|
4KB
|
146 lines
@z --- breakpt.web ---
THIS CODE SERVES AS AN EXAMPLE OF A C CODE WRITTEN IN WEB.
HOWEVER, ITS CONTENTS IS FOR ADVANCED PROGRAMMERS ONLY! See the
discussion of breakpointing/debugging in the user's manual.
@x-----------------------------------------------------------------------------
@c
\Title{BREAKPT.WEB}
@* DEBUGGING. This sample program shows how to write module breakpointing
functions that work in conjunction with the general |_BP| macro mechanism.
@d NO 0
@d YES 1
@ We begin by defining a structure~|_BP| that contains information about each
breakpoint---a flag |on| to indicate whether that breakpoint is active or
not, and a pointer to the name of the module. We will have an array |bps|
of such structures, one for each possible section.
@a
typedef struct
{
char on; /* Flag to indicate active or not. */
char *name; /* Name of the module. */
} BP;
/* The following illustrates use of the built-in macros |_MODULES|,
|_SECTIONS|, ANd |_eval|. */
BP bps0[_MODULES]; /* This array corresponds to all the independent module
names, with 0~corresponding to the unnamed module. */
BP bps[_EVAL(_SECTIONS+1)]; /* These correspond to the \.{@@\ } or~\.{@@*}
sections,
numbered as in \.{WEAVE}'s output. The zeroth section does
not exist. */
@ We shall add a module number to the breakpoint list by calling~|bp|
\It{from the debugger} with a positive argument; we remove one from the
list by calling with a negative argument.
@a
int bp(int m)
{
/* Check for |m| out-of-bounds. */
if(abs(m) > _SECTIONS)
{
printf("Section number %d too large; must be < %d\n",
m,_SECTIONS);
return NO;
}
if(m > 0)
{
printf("Setting breakpoint at section %d\n",m);
return bps[m].on = YES;
}
else if(m < 0)
{
printf("Removing breakpoint at section %d\n",-m);
return bps[-m].on = NO;
}
else
{
puts("Removing all breakpoints");
for(; m<=_SECTIONS; m++)
bps[m].on = NO;
return NO;
}
}
@ We can initialize all breakpoints by calling the following routine from
the debugger. To make it easier for us in this demo, we do that explicitly
in |main|.
@a
void init_bp(void)
{
int m;
puts("Initializing all breakpoints");
for(m=0; m<=_SECTIONS; m++) bps[m].on = YES;
}
@ The actual breakpoint macro should in general be defined as follows:
\.{-m"\_BP(m,name)=trap(m,name);"}, where |trap|~is a function that is to
be called at the beginning of each module. If the module is in the
breakpoint list, then |trap| will call the null function~|_bp|, on which
one can set a debugger breakpoint. (This might be put into an
initialization file.) Thus, for an active module breakpoint, the |trap|
routine will print the name of the module, then stop in the debugger.
@a
void _bp(void)
{}
void trap(int m,char *name)
{
if(bps[m].on)
{
printf("Entering section %d, module \"%s\"\n",
m,bps[m].name = name);
_bp();
}
}
@ Here is a test program.
@a
main()
{
int k = 50; /* To prevent an infinite loop if you run this without any
breakpoints set. */
init_bp(); /* Initialize all breakpoints. */
while(k-- > 0)
{
@<A@>;
@<B@>;
@<This is a very, very long module whose name seems never to end@>;
}
}
@ A simple named section.
@<A@>=
{
puts("A");
}
@ This section has no braces, so the breakpointing mechanism won't work.
@<B@>=
puts("B");
@ This section starts off with a C~declaration. We must use the
\.{@@\{}~command to prevent the debugging statement from being inserting
before the declaration, and the \.{@@b}~command to say where to actually put
the debugging statement.
@<This...@>=
@{
int i;
@b
puts("Testing");
}