Commit fe7287f8 authored by unknown's avatar unknown

dbug: function/ (a.k.a. SUBDIR) syntax


dbug/dbug.c:
  function/ (a.k.a. SUBDIR) syntax
dbug/tests-t.pl:
  1. add support for test comments
  2. add test comments
  3. move tests around
  4. add SUBDIR tests
dbug/tests.c:
  support code for SUBDIR testing
include/my_dbug.h:
  comments. change in _db_set_ prototype
dbug/user.r:
  negative lists and function/ syntax.
parent 06477018
...@@ -71,6 +71,12 @@ ...@@ -71,6 +71,12 @@
* thread-local settings * thread-local settings
* negative lists (-#-d,info => everything but "info") * negative lists (-#-d,info => everything but "info")
* *
* function/ syntax
* (the logic is - think of a call stack as of a path.
* "function" means only this function, "function/" means the hierarchy.
* in the future, filters like function1/function2 could be supported.
* wildcards are a natural extension too: * and ?)
*
*/ */
/* /*
...@@ -101,21 +107,24 @@ ...@@ -101,21 +107,24 @@
* The following flags are used to determine which * The following flags are used to determine which
* capabilities the user has enabled with the settings * capabilities the user has enabled with the settings
* push macro. * push macro.
*
* TRACE_ON is also used in _db_stack_frame_->level
* (until we add flags to _db_stack_frame_, increasing it by 4 bytes)
*/ */
#define TRACE_ON 000001 /* Trace enabled */ #define DEBUG_ON (1 << 1) /* Debug enabled */
#define DEBUG_ON 000002 /* Debug enabled */ #define FILE_ON (1 << 2) /* File name print enabled */
#define FILE_ON 000004 /* File name print enabled */ #define LINE_ON (1 << 3) /* Line number print enabled */
#define LINE_ON 000010 /* Line number print enabled */ #define DEPTH_ON (1 << 4) /* Function nest level print enabled */
#define DEPTH_ON 000020 /* Function nest level print enabled */ #define PROCESS_ON (1 << 5) /* Process name print enabled */
#define PROCESS_ON 000040 /* Process name print enabled */ #define NUMBER_ON (1 << 6) /* Number each line of output */
#define NUMBER_ON 000100 /* Number each line of output */ #define PROFILE_ON (1 << 7) /* Print out profiling code */
#define PROFILE_ON 000200 /* Print out profiling code */ #define PID_ON (1 << 8) /* Identify each line with process id */
#define PID_ON 000400 /* Identify each line with process id */ #define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */
#define TIMESTAMP_ON 001000 /* timestamp every line of output */ #define SANITY_CHECK_ON (1 << 10) /* Check safemalloc on DBUG_ENTER */
#define SANITY_CHECK_ON 002000 /* Check safemalloc on DBUG_ENTER */ #define FLUSH_ON_WRITE (1 << 11) /* Flush on every write */
#define FLUSH_ON_WRITE 004000 /* Flush on every write */ #define OPEN_APPEND (1 << 12) /* Open for append */
#define OPEN_APPEND 010000 /* Open for append */ #define TRACE_ON (1 << 31) /* Trace enabled. MUST be the highest bit!*/
#define TRACING (cs->stack->flags & TRACE_ON) #define TRACING (cs->stack->flags & TRACE_ON)
#define DEBUGGING (cs->stack->flags & DEBUG_ON) #define DEBUGGING (cs->stack->flags & DEBUG_ON)
...@@ -141,7 +150,7 @@ ...@@ -141,7 +150,7 @@
* (G?) which allowed the user to specify this. * (G?) which allowed the user to specify this.
* *
* If the automatic variables get allocated on the stack in * If the automatic variables get allocated on the stack in
* reverse order from their declarations, then define AUTOS_REVERSE. * reverse order from their declarations, then define AUTOS_REVERSE to 1.
* This is used by the code that keeps track of stack usage. For * This is used by the code that keeps track of stack usage. For
* forward allocation, the difference in the dbug frame pointers * forward allocation, the difference in the dbug frame pointers
* represents stack used by the callee function. For reverse allocation, * represents stack used by the callee function. For reverse allocation,
...@@ -156,6 +165,8 @@ ...@@ -156,6 +165,8 @@
#ifdef M_I386 /* predefined by xenix 386 compiler */ #ifdef M_I386 /* predefined by xenix 386 compiler */
#define AUTOS_REVERSE 1 #define AUTOS_REVERSE 1
#else
#define AUTOS_REVERSE 0
#endif #endif
/* /*
...@@ -180,9 +191,13 @@ struct link { ...@@ -180,9 +191,13 @@ struct link {
char str[1]; /* Pointer to link's contents */ char str[1]; /* Pointer to link's contents */
}; };
/* flags for struct link */ /* flags for struct link and return flags of InList */
#define INCLUDE 1 #define SUBDIR 1 /* this MUST be 1 */
#define EXCLUDE 2 #define INCLUDE 2
#define EXCLUDE 4
/* this is not a struct link flag, but only a return flags of InList */
#define MATCHED 65536
#define NOT_MATCHED 0
/* /*
* Debugging settings can be pushed or popped off of a * Debugging settings can be pushed or popped off of a
...@@ -225,7 +240,7 @@ typedef struct _db_code_state_ { ...@@ -225,7 +240,7 @@ typedef struct _db_code_state_ {
const char *process; /* Pointer to process name; usually argv[0] */ const char *process; /* Pointer to process name; usually argv[0] */
const char *func; /* Name of current user function */ const char *func; /* Name of current user function */
const char *file; /* Name of current user file */ const char *file; /* Name of current user file */
char **framep; /* Pointer to current frame */ struct _db_stack_frame_ *framep; /* Pointer to current frame */
struct settings *stack; /* debugging settings */ struct settings *stack; /* debugging settings */
const char *jmpfunc; /* Remember current function for setjmp */ const char *jmpfunc; /* Remember current function for setjmp */
const char *jmpfile; /* Remember current file for setjmp */ const char *jmpfile; /* Remember current file for setjmp */
...@@ -272,10 +287,18 @@ static void PushState(CODE_STATE *cs); ...@@ -272,10 +287,18 @@ static void PushState(CODE_STATE *cs);
/* Free memory associated with debug state. */ /* Free memory associated with debug state. */
static void FreeState (CODE_STATE *cs, struct settings *state, int free_state); static void FreeState (CODE_STATE *cs, struct settings *state, int free_state);
/* Test for tracing enabled */ /* Test for tracing enabled */
static BOOLEAN DoTrace(CODE_STATE *cs); static int DoTrace(CODE_STATE *cs, int tracing);
/*
return values of DoTrace.
Can also be used as bitmask: ret & DO_TRACE
*/
#define DO_TRACE 1
#define DONT_TRACE 2
#define ENABLE_TRACE 3
#define DISABLE_TRACE 4
/* Test to see if file is writable */ /* Test to see if file is writable */
#if !(!defined(HAVE_ACCESS) || defined(MSDOS)) #if defined(HAVE_ACCESS) && !defined(MSDOS)
static BOOLEAN Writable(const char *pathname); static BOOLEAN Writable(const char *pathname);
/* Change file owner and group */ /* Change file owner and group */
static void ChangeOwner(CODE_STATE *cs, char *pathname); static void ChangeOwner(CODE_STATE *cs, char *pathname);
...@@ -431,12 +454,7 @@ void _db_process_(const char *name) ...@@ -431,12 +454,7 @@ void _db_process_(const char *name)
/* /*
* FUNCTION * FUNCTION
* *
* _db_set_ set current debugger settings * ParseDbug parse control string and set current debugger settings
*
* SYNOPSIS
*
* VOID _db_set_(control)
* char *control;
* *
* DESCRIPTION * DESCRIPTION
* *
...@@ -458,15 +476,17 @@ void _db_process_(const char *name) ...@@ -458,15 +476,17 @@ void _db_process_(const char *name)
* *
* For convenience, any leading "-#" is stripped off. * For convenience, any leading "-#" is stripped off.
* *
* RETURN
* 1 - a list of functions ("f" flag) was possibly changed
* 0 - a list of functions was not changed
*/ */
void _db_set_(CODE_STATE *cs, const char *control) int ParseDbug(CODE_STATE *cs, const char *control)
{ {
const char *end; const char *end;
int rel; int rel, f_used=0;
struct settings *stack; struct settings *stack;
get_code_state_if_not_set_or_return;
stack= cs->stack; stack= cs->stack;
if (control[0] == '-' && control[1] == '#') if (control[0] == '-' && control[1] == '#')
...@@ -517,7 +537,6 @@ void _db_set_(CODE_STATE *cs, const char *control) ...@@ -517,7 +537,6 @@ void _db_set_(CODE_STATE *cs, const char *control)
{ {
int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0; int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0;
if (sign) control++; if (sign) control++;
/* if (!rel) sign=0; */
c= *control++; c= *control++;
if (*control == ',') control++; if (*control == ',') control++;
/* XXX when adding new cases here, don't forget _db_explain_ ! */ /* XXX when adding new cases here, don't forget _db_explain_ ! */
...@@ -546,6 +565,7 @@ void _db_set_(CODE_STATE *cs, const char *control) ...@@ -546,6 +565,7 @@ void _db_set_(CODE_STATE *cs, const char *control)
stack->delay= atoi(control); stack->delay= atoi(control);
break; break;
case 'f': case 'f':
f_used= 1;
if (sign < 0 && control == end) if (sign < 0 && control == end)
{ {
if (!is_shared(stack,functions)) if (!is_shared(stack,functions))
...@@ -684,8 +704,139 @@ void _db_set_(CODE_STATE *cs, const char *control) ...@@ -684,8 +704,139 @@ void _db_set_(CODE_STATE *cs, const char *control)
control=end+1; control=end+1;
end= DbugStrTok(control); end= DbugStrTok(control);
} }
return !rel || f_used;
} }
#define framep_trace_flag(cs, frp) (frp ? \
frp->level & TRACE_ON : \
(ListFlags(cs->stack->functions) & INCLUDE) ? \
0 : (uint)TRACE_ON)
void FixTraceFlags_helper(CODE_STATE *cs, const char *func,
struct _db_stack_frame_ *framep)
{
if (framep->prev)
FixTraceFlags_helper(cs, framep->func, framep->prev);
cs->func= func;
cs->level= framep->level & ~TRACE_ON;
framep->level= cs->level | framep_trace_flag(cs, framep->prev);
/*
we don't set cs->framep correctly, even though DoTrace uses it.
It's ok, because cs->framep may only affect DO_TRACE/DONT_TRACE return
values, but we ignore them here anyway
*/
switch(DoTrace(cs, 1)) {
case ENABLE_TRACE:
framep->level|= TRACE_ON;
break;
case DISABLE_TRACE:
framep->level&= ~TRACE_ON;
break;
}
}
#define fflags(cs) cs->stack->out_file ? ListFlags(cs->stack->functions) : TRACE_ON;
void FixTraceFlags(int old_fflags, CODE_STATE *cs)
{
const char *func;
int new_fflags, traceon, level;
struct _db_stack_frame_ *framep;
/*
first (a.k.a. safety) check:
if we haven't started tracing yet, no call stack at all - we're safe.
*/
framep=cs->framep;
if (framep == 0)
return;
/*
Ok, the tracing has started, call stack isn't empty.
second check: does the new list have a SUBDIR rule ?
*/
new_fflags=fflags(cs);
if (new_fflags & SUBDIR)
goto yuck;
/*
Ok, new list doesn't use SUBDIR.
third check: we do NOT need to re-scan if
neither old nor new lists used SUBDIR flag and if a default behavior
(whether an unlisted function is traced) hasn't changed.
Default behavior depends on whether there're INCLUDE elements in the list.
*/
if (!(old_fflags & SUBDIR) && !((new_fflags^old_fflags) & INCLUDE))
return;
/*
Ok, old list may've used SUBDIR, or defaults could've changed.
fourth check: are we inside a currently active SUBDIR rule ?
go up the call stack, if TRACE_ON flag ever changes its value - we are.
*/
for (traceon=framep->level; framep; framep=framep->prev)
if ((traceon ^ framep->level) & TRACE_ON)
goto yuck;
/*
Ok, TRACE_ON flag doesn't change in the call stack.
fifth check: but is the top-most value equal to a default one ?
*/
if (((traceon & TRACE_ON) != 0) == ((new_fflags & INCLUDE) == 0))
return;
yuck:
/*
Yuck! function list was changed, and one of the currently active rules
was possibly affected. For example, a tracing could've been enabled or
disabled for a function somewhere up the call stack.
To react correctly, we must go up the call stack all the way to
the top and re-match rules to set TRACE_ON bit correctly.
We must traverse the stack forwards, not backwards.
That's what a recursive helper is doing.
It'll destroy two CODE_STATE fields, save them now.
*/
func= cs->func;
level= cs->level;
FixTraceFlags_helper(cs, func, cs->framep);
/* now we only need to restore CODE_STATE fields, and we're done */
cs->func= func;
cs->level= level;
}
/*
* FUNCTION
*
* _db_set_ set current debugger settings
*
* SYNOPSIS
*
* VOID _db_set_(control)
* char *control;
*
* DESCRIPTION
*
* Given pointer to a debug control string in "control",
* parses the control string, and sets
* up a current debug settings.
*
*/
void _db_set_(const char *control)
{
CODE_STATE *cs;
int old_fflags;
get_code_state_or_return;
old_fflags=fflags(cs);
if (ParseDbug(cs, control))
FixTraceFlags(old_fflags, cs);
}
/* /*
* FUNCTION * FUNCTION
...@@ -701,16 +852,19 @@ void _db_set_(CODE_STATE *cs, const char *control) ...@@ -701,16 +852,19 @@ void _db_set_(CODE_STATE *cs, const char *control)
* *
* Given pointer to a debug control string in "control", pushes * Given pointer to a debug control string in "control", pushes
* the current debug settings, parses the control string, and sets * the current debug settings, parses the control string, and sets
* up a new debug settings with _db_set_() * up a new debug settings
* *
*/ */
void _db_push_(const char *control) void _db_push_(const char *control)
{ {
CODE_STATE *cs; CODE_STATE *cs;
int old_fflags;
get_code_state_or_return; get_code_state_or_return;
old_fflags=fflags(cs);
PushState(cs); PushState(cs);
_db_set_(cs, control); if (ParseDbug(cs, control))
FixTraceFlags(old_fflags, cs);
} }
/* /*
...@@ -733,7 +887,7 @@ void _db_set_init_(const char *control) ...@@ -733,7 +887,7 @@ void _db_set_init_(const char *control)
CODE_STATE tmp_cs; CODE_STATE tmp_cs;
bzero((uchar*) &tmp_cs, sizeof(tmp_cs)); bzero((uchar*) &tmp_cs, sizeof(tmp_cs));
tmp_cs.stack= &init_settings; tmp_cs.stack= &init_settings;
_db_set_(&tmp_cs, control); ParseDbug(&tmp_cs, control);
} }
/* /*
...@@ -756,6 +910,7 @@ void _db_set_init_(const char *control) ...@@ -756,6 +910,7 @@ void _db_set_init_(const char *control)
void _db_pop_() void _db_pop_()
{ {
struct settings *discard; struct settings *discard;
int old_fflags;
CODE_STATE *cs; CODE_STATE *cs;
get_code_state_or_return; get_code_state_or_return;
...@@ -763,8 +918,10 @@ void _db_pop_() ...@@ -763,8 +918,10 @@ void _db_pop_()
discard= cs->stack; discard= cs->stack;
if (discard->next != NULL) if (discard->next != NULL)
{ {
old_fflags=fflags(cs);
cs->stack= discard->next; cs->stack= discard->next;
FreeState(cs, discard, 1); FreeState(cs, discard, 1);
FixTraceFlags(old_fflags, cs);
} }
} }
...@@ -794,7 +951,11 @@ void _db_pop_() ...@@ -794,7 +951,11 @@ void _db_pop_()
while (listp) \ while (listp) \
{ \ { \
if (listp->flags & (f)) \ if (listp->flags & (f)) \
{ \
str_to_buf(listp->str); \ str_to_buf(listp->str); \
if (listp->flags & SUBDIR) \
char_to_buf('/'); \
} \
listp=listp->next_link; \ listp=listp->next_link; \
} \ } \
} while (0) } while (0)
...@@ -928,15 +1089,11 @@ int _db_explain_init_(char *buf, size_t len) ...@@ -928,15 +1089,11 @@ int _db_explain_init_(char *buf, size_t len)
* *
* SYNOPSIS * SYNOPSIS
* *
* VOID _db_enter_(_func_, _file_, _line_, * VOID _db_enter_(_func_, _file_, _line_, _stack_frame_)
* _sfunc_, _sfile_, _slevel_, _sframep_)
* char *_func_; points to current function name * char *_func_; points to current function name
* char *_file_; points to current file name * char *_file_; points to current file name
* int _line_; called from source line number * int _line_; called from source line number
* char **_sfunc_; save previous _func_ * struct _db_stack_frame_ allocated on the caller's stack
* char **_sfile_; save previous _file_
* int *_slevel_; save previous nesting level
* char ***_sframep_; save previous frame pointer
* *
* DESCRIPTION * DESCRIPTION
* *
...@@ -960,54 +1117,60 @@ int _db_explain_init_(char *buf, size_t len) ...@@ -960,54 +1117,60 @@ int _db_explain_init_(char *buf, size_t len)
*/ */
void _db_enter_(const char *_func_, const char *_file_, void _db_enter_(const char *_func_, const char *_file_,
uint _line_, const char **_sfunc_, const char **_sfile_, uint _line_, struct _db_stack_frame_ *_stack_frame_)
uint *_slevel_, char ***_sframep_ __attribute__((unused)))
{ {
int save_errno; int save_errno;
CODE_STATE *cs; CODE_STATE *cs;
if (!((cs=code_state()))) if (!((cs=code_state())))
{ {
*_slevel_= 0; /* Set to avoid valgrind warnings if dbug is enabled later */ _stack_frame_->level= 0; /* Set to avoid valgrind warnings if dbug is enabled later */
_stack_frame_->prev= 0;
return; return;
} }
save_errno= errno; save_errno= errno;
*_sfunc_= cs->func; _stack_frame_->func= cs->func;
*_sfile_= cs->file; _stack_frame_->file= cs->file;
cs->func= _func_; cs->func= _func_;
cs->file= _file_; cs->file= _file_;
*_slevel_= ++cs->level; _stack_frame_->prev= cs->framep;
_stack_frame_->level= ++cs->level | framep_trace_flag(cs, cs->framep);
cs->framep= _stack_frame_;
#ifndef THREAD #ifndef THREAD
*_sframep_= cs->framep;
cs->framep= (char **) _sframep_;
if (DoProfile(cs)) if (DoProfile(cs))
{ {
long stackused; long stackused;
if (*cs->framep == NULL) if (cs->framep->prev == NULL)
stackused= 0; stackused= 0;
else else
{ {
stackused= ((long)(*cs->framep)) - ((long)(cs->framep)); stackused= (char*)(cs->framep->prev) - (char*)(cs->framep);
stackused= stackused > 0 ? stackused : -stackused; stackused= stackused > 0 ? stackused : -stackused;
} }
(void) fprintf(cs->stack->prof_file, PROF_EFMT , Clock(), cs->func); (void) fprintf(cs->stack->prof_file, PROF_EFMT , Clock(), cs->func);
#ifdef AUTOS_REVERSE
(void) fprintf(cs->stack->prof_file, PROF_SFMT, cs->framep, stackused, *_sfunc_);
#else
(void) fprintf(cs->stack->prof_file, PROF_SFMT, (ulong) cs->framep, stackused, (void) fprintf(cs->stack->prof_file, PROF_SFMT, (ulong) cs->framep, stackused,
cs->func); AUTOS_REVERSE ? _stack_frame_->func : cs->func);
#endif
(void) fflush(cs->stack->prof_file); (void) fflush(cs->stack->prof_file);
} }
#endif #endif
if (DoTrace(cs)) switch (DoTrace(cs, TRACING)) {
{ case ENABLE_TRACE:
cs->framep->level|= TRACE_ON;
if (!TRACING) break;
/* fall through */
case DO_TRACE:
if (!cs->locked) if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug); pthread_mutex_lock(&THR_LOCK_dbug);
DoPrefix(cs, _line_); DoPrefix(cs, _line_);
Indent(cs, cs->level); Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file, ">%s\n", cs->func); (void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
dbug_flush(cs); /* This does a unlock */ dbug_flush(cs); /* This does a unlock */
break;
case DISABLE_TRACE:
cs->framep->level&= ~TRACE_ON;
/* fall through */
case DONT_TRACE:
break;
} }
#ifdef SAFEMALLOC #ifdef SAFEMALLOC
if (cs->stack->flags & SANITY_CHECK_ON) if (cs->stack->flags & SANITY_CHECK_ON)
...@@ -1024,11 +1187,9 @@ void _db_enter_(const char *_func_, const char *_file_, ...@@ -1024,11 +1187,9 @@ void _db_enter_(const char *_func_, const char *_file_,
* *
* SYNOPSIS * SYNOPSIS
* *
* VOID _db_return_(_line_, _sfunc_, _sfile_, _slevel_) * VOID _db_return_(_line_, _stack_frame_)
* int _line_; current source line number * int _line_; current source line number
* char **_sfunc_; where previous _func_ is to be retrieved * struct _db_stack_frame_ allocated on the caller's stack
* char **_sfile_; where previous _file_ is to be retrieved
* int *_slevel_; where previous level was stashed
* *
* DESCRIPTION * DESCRIPTION
* *
...@@ -1040,14 +1201,14 @@ void _db_enter_(const char *_func_, const char *_file_, ...@@ -1040,14 +1201,14 @@ void _db_enter_(const char *_func_, const char *_file_,
*/ */
/* helper macro */ /* helper macro */
void _db_return_(uint _line_, const char **_sfunc_, void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_)
const char **_sfile_, uint *_slevel_)
{ {
int save_errno=errno; int save_errno=errno;
int _slevel_=_stack_frame_->level & ~TRACE_ON;
CODE_STATE *cs; CODE_STATE *cs;
get_code_state_or_return; get_code_state_or_return;
if (cs->level != (int) *_slevel_) if (cs->level != _slevel_)
{ {
if (!cs->locked) if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug); pthread_mutex_lock(&THR_LOCK_dbug);
...@@ -1060,7 +1221,7 @@ void _db_return_(uint _line_, const char **_sfunc_, ...@@ -1060,7 +1221,7 @@ void _db_return_(uint _line_, const char **_sfunc_,
#ifdef SAFEMALLOC #ifdef SAFEMALLOC
if (cs->stack->flags & SANITY_CHECK_ON) if (cs->stack->flags & SANITY_CHECK_ON)
{ {
if (_sanity(*_sfile_,_line_)) if (_sanity(_stack_frame_->file,_line_))
cs->stack->flags &= ~SANITY_CHECK_ON; cs->stack->flags &= ~SANITY_CHECK_ON;
} }
#endif #endif
...@@ -1068,7 +1229,7 @@ void _db_return_(uint _line_, const char **_sfunc_, ...@@ -1068,7 +1229,7 @@ void _db_return_(uint _line_, const char **_sfunc_,
if (DoProfile(cs)) if (DoProfile(cs))
(void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func); (void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func);
#endif #endif
if (DoTrace(cs)) if (TRACING && DoTrace(cs, 1) & DO_TRACE)
{ {
if (!cs->locked) if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug); pthread_mutex_lock(&THR_LOCK_dbug);
...@@ -1082,13 +1243,11 @@ void _db_return_(uint _line_, const char **_sfunc_, ...@@ -1082,13 +1243,11 @@ void _db_return_(uint _line_, const char **_sfunc_,
Check to not set level < 0. This can happen if DBUG was disabled when Check to not set level < 0. This can happen if DBUG was disabled when
function was entered and enabled in function. function was entered and enabled in function.
*/ */
cs->level= *_slevel_ != 0 ? *_slevel_-1 : 0; cs->level= _slevel_ != 0 ? _slevel_ - 1 : 0;
cs->func= *_sfunc_; cs->func= _stack_frame_->func;
cs->file= *_sfile_; cs->file= _stack_frame_->file;
#ifndef THREAD
if (cs->framep != NULL) if (cs->framep != NULL)
cs->framep= (char **) *cs->framep; cs->framep= cs->framep->prev;
#endif
errno=save_errno; errno=save_errno;
} }
...@@ -1252,13 +1411,13 @@ void _db_dump_(uint _line_, const char *keyword, ...@@ -1252,13 +1411,13 @@ void _db_dump_(uint _line_, const char *keyword,
* *
* The mode of operation is defined by "todo" parameter. * The mode of operation is defined by "todo" parameter.
* *
* If it's INCLUDE, elements (strings from "cltp") are added to the * If it is INCLUDE, elements (strings from "cltp") are added to the
* list, they'll have INCLUDE flag set. If the list already contains * list, they will have INCLUDE flag set. If the list already contains
* the string in question, new element is not added, but a flag of * the string in question, new element is not added, but a flag of
* the existing element is adjusted (INCLUDE bit is set, EXCLUDE bit * the existing element is adjusted (INCLUDE bit is set, EXCLUDE bit
* is removed). * is removed).
* *
* If it's EXCLUDE, elements are added to the list with the EXCLUDE * If it is EXCLUDE, elements are added to the list with the EXCLUDE
* flag set. If the list already contains the string in question, * flag set. If the list already contains the string in question,
* it is removed, new element is not added. * it is removed, new element is not added.
*/ */
...@@ -1268,16 +1427,22 @@ static struct link *ListAddDel(struct link *head, const char *ctlp, ...@@ -1268,16 +1427,22 @@ static struct link *ListAddDel(struct link *head, const char *ctlp,
{ {
const char *start; const char *start;
struct link **cur; struct link **cur;
int len; int len, subdir;
ctlp--; ctlp--;
next: next:
while (++ctlp < end) while (++ctlp < end)
{ {
start= ctlp; start= ctlp;
subdir=0;
while (ctlp < end && *ctlp != ',') while (ctlp < end && *ctlp != ',')
ctlp++; ctlp++;
len=ctlp-start; len=ctlp-start;
if (start[len-1] == '/')
{
len--;
subdir=SUBDIR;
}
if (len == 0) continue; if (len == 0) continue;
for (cur=&head; *cur; cur=&((*cur)->next_link)) for (cur=&head; *cur; cur=&((*cur)->next_link))
{ {
...@@ -1291,8 +1456,8 @@ static struct link *ListAddDel(struct link *head, const char *ctlp, ...@@ -1291,8 +1456,8 @@ static struct link *ListAddDel(struct link *head, const char *ctlp,
} }
else else
{ {
(*cur)->flags&=~EXCLUDE; (*cur)->flags&=~(EXCLUDE & SUBDIR);
(*cur)->flags|=INCLUDE; (*cur)->flags|=INCLUDE | subdir;
} }
goto next; goto next;
} }
...@@ -1300,7 +1465,7 @@ static struct link *ListAddDel(struct link *head, const char *ctlp, ...@@ -1300,7 +1465,7 @@ static struct link *ListAddDel(struct link *head, const char *ctlp,
*cur= (struct link *) DbugMalloc(sizeof(struct link)+len); *cur= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy((*cur)->str, start, len); memcpy((*cur)->str, start, len);
(*cur)->str[len]=0; (*cur)->str[len]=0;
(*cur)->flags=todo; (*cur)->flags=todo | subdir;
(*cur)->next_link=0; (*cur)->next_link=0;
} }
return head; return head;
...@@ -1355,12 +1520,6 @@ static struct link *ListCopy(struct link *orig) ...@@ -1355,12 +1520,6 @@ static struct link *ListCopy(struct link *orig)
* *
* InList test a given string for member of a given list * InList test a given string for member of a given list
* *
* SYNOPSIS
*
* static int InList(linkp, cp)
* struct link *linkp;
* char *cp;
*
* DESCRIPTION * DESCRIPTION
* *
* Tests the string pointed to by "cp" to determine if it is in * Tests the string pointed to by "cp" to determine if it is in
...@@ -1373,9 +1532,7 @@ static struct link *ListCopy(struct link *orig) ...@@ -1373,9 +1532,7 @@ static struct link *ListCopy(struct link *orig)
* is a list, only those strings in the list will be accepted. * is a list, only those strings in the list will be accepted.
* *
* RETURN * RETURN
* 0 - not in the list (or matched an EXCLUDE element) * combination of SUBDIR, INCLUDE, EXCLUDE, MATCHED flags
* 1 - in the list by default (list is empty or only has EXCLUDE elements)
* 2 - in the list explictly (matched an INCLUDE element)
* *
*/ */
...@@ -1383,12 +1540,14 @@ static int InList(struct link *linkp, const char *cp) ...@@ -1383,12 +1540,14 @@ static int InList(struct link *linkp, const char *cp)
{ {
int result; int result;
for (result=1; linkp != NULL; linkp= linkp->next_link) for (result=MATCHED; linkp != NULL; linkp= linkp->next_link)
{ {
if (!strcmp(linkp->str, cp)) if (!strcmp(linkp->str, cp))
return linkp->flags & EXCLUDE ? 0 : 2; return linkp->flags;
if (!(linkp->flags & EXCLUDE)) if (!(linkp->flags & EXCLUDE))
result=0; result=NOT_MATCHED;
if (linkp->flags & SUBDIR)
result|=SUBDIR;
} }
return result; return result;
} }
...@@ -1535,25 +1694,34 @@ void _db_end_() ...@@ -1535,25 +1694,34 @@ void _db_end_()
* *
* DoTrace check to see if tracing is current enabled * DoTrace check to see if tracing is current enabled
* *
* SYNOPSIS * tracing is the value of TRACING to check if the tracing is enabled
* * or 1 to check if the function is enabled (in _db_keyword_)
* static BOOLEAN DoTrace(stack)
* *
* DESCRIPTION * DESCRIPTION
* *
* Checks to see if tracing is enabled based on whether the * Checks to see if tracing is enabled based on whether the
* user has specified tracing, the maximum trace depth has * user has specified tracing, the maximum trace depth has
* not yet been reached, the current function is selected, * not yet been reached, the current function is selected,
* and the current process is selected. Returns TRUE if * and the current process is selected.
* tracing is enabled, FALSE otherwise.
* *
*/ */
static BOOLEAN DoTrace(CODE_STATE *cs) static int DoTrace(CODE_STATE *cs, int tracing)
{ {
return (TRACING && cs->level <= cs->stack->maxdepth && if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
InList(cs->stack->functions, cs->func) && InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE))
InList(cs->stack->processes, cs->process)); switch(InList(cs->stack->functions, cs->func)) {
case INCLUDE|SUBDIR: return ENABLE_TRACE;
case INCLUDE: return tracing ? DO_TRACE : DONT_TRACE;
case MATCHED|SUBDIR:
case NOT_MATCHED|SUBDIR:
case MATCHED: return tracing && framep_trace_flag(cs, cs->framep) ?
DO_TRACE : DONT_TRACE;
case EXCLUDE:
case NOT_MATCHED: return DONT_TRACE;
case EXCLUDE|SUBDIR: return DISABLE_TRACE;
}
return DONT_TRACE;
} }
...@@ -1581,8 +1749,8 @@ static BOOLEAN DoProfile(CODE_STATE *cs) ...@@ -1581,8 +1749,8 @@ static BOOLEAN DoProfile(CODE_STATE *cs)
{ {
return PROFILING && return PROFILING &&
cs->level <= cs->stack->maxdepth && cs->level <= cs->stack->maxdepth &&
InList(cs->stack->p_functions, cs->func) && InList(cs->stack->p_functions, cs->func) & (INCLUDE|MATCHED) &&
InList(cs->stack->processes, cs->process); InList(cs->stack->processes, cs->process) & (INCLUDE|MATCHED);
} }
#endif #endif
...@@ -1616,12 +1784,10 @@ FILE *_db_fp_(void) ...@@ -1616,12 +1784,10 @@ FILE *_db_fp_(void)
BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict) BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
{ {
get_code_state_if_not_set_or_return FALSE; get_code_state_if_not_set_or_return FALSE;
strict=strict ? INCLUDE : INCLUDE|MATCHED;
return (DEBUGGING && return DEBUGGING && DoTrace(cs, 1) & DO_TRACE &&
(!TRACING || cs->level <= cs->stack->maxdepth) && InList(cs->stack->keywords, keyword) & strict;
InList(cs->stack->functions, cs->func) &&
InList(cs->stack->keywords, keyword) > (strict != 0) &&
InList(cs->stack->processes, cs->process));
} }
/* /*
......
...@@ -12,8 +12,10 @@ die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /; ...@@ -12,8 +12,10 @@ die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /;
# load tests # load tests
@tests=(); @tests=();
while (<DATA>) { while (<DATA>) {
if (/^% tests /) { if (/^% \.\/tests /) {
push @tests, [ $' ] push @tests, [ $' ]
} elsif (/^#/) {
next;
} else { } else {
push @{$tests[$#tests]}, $_ push @{$tests[$#tests]}, $_
} }
...@@ -36,24 +38,27 @@ for (@tests) { ...@@ -36,24 +38,27 @@ for (@tests) {
} }
__DATA__ __DATA__
% tests -#d % ./tests -#d
func2: info: s=ok
func2: info: s=ok func2: info: s=ok
=> execute => execute
=> evaluate: ON => evaluate: ON
=> evaluate_if: OFF => evaluate_if: OFF
main: explain: dbug explained: d main: explain: dbug explained: d
% tests -#d,ret3 func2: info: s=ok
% ./tests d,ret3
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
% tests -#d:-d,ret3 #
func2: info: s=ko ## Testing negative lists
#
% ./tests d:-d,ret3
func2: info: s=ko func2: info: s=ko
=> execute => execute
=> evaluate: ON => evaluate: ON
=> evaluate_if: OFF => evaluate_if: OFF
main: explain: dbug explained: d:-d,ret3 main: explain: dbug explained: d:-d,ret3
% tests -#t:-d,ret3 func2: info: s=ko
% ./tests t:-d,ret3
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -61,14 +66,14 @@ main: explain: dbug explained: d:-d,ret3 ...@@ -61,14 +66,14 @@ main: explain: dbug explained: d:-d,ret3
| | | <func3 | | | <func3
| | <func2 | | <func2
| <func1 | <func1
=> evaluate: OFF
=> evaluate_if: OFF
| >func2 | >func2
| | >func3 | | >func3
| | <func3 | | <func3
| <func2 | <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main <main
% tests -#t:d,info:-d,ret3 % ./tests t:d,info:-d,ret3
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -77,159 +82,168 @@ main: explain: dbug explained: d:-d,ret3 ...@@ -77,159 +82,168 @@ main: explain: dbug explained: d:-d,ret3
| | | info: s=ko | | | info: s=ko
| | <func2 | | <func2
| <func1 | <func1
=> evaluate: OFF
=> evaluate_if: OFF
| >func2 | >func2
| | >func3 | | >func3
| | <func3 | | <func3
| | info: s=ko | | info: s=ko
| <func2 | <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main <main
% tests -#t:d,info:-d,ret3:-f,func2 % ./tests t:d,info:-d,ret3:-f,func2
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| | >func3
| | <func3
<main <main
% tests -#t:d,info:-d,ret3:-f,func2 d,evaluate % ./tests t:d,info:-d,ret3:-f,func2 d,evaluate
=> evaluate: ON => evaluate: ON
=> evaluate_if: OFF => evaluate_if: OFF
% tests -#t:d,info:-d,ret3:-f,func2 d,evaluate_if % ./tests t:d,info:-d,ret3:-f,func2 d,evaluate_if
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: ON => evaluate_if: ON
% tests -#t:d:-d,ret3:-f,func2 d,evaluate_if % ./tests t:d:-d,ret3:-f,func2 d,evaluate_if
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: ON => evaluate_if: ON
% tests -#t:d:-d,ret3:-f,func2 +d,evaluate_if % ./tests t:d:-d,ret3:-f,func2
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
| | >func3 | | >func3
| | <func3 | | <func3
=> evaluate: OFF
=> evaluate_if: ON
<main <main
% tests -#t:d:-d,ret3:-f,func2 #
## Adding incremental settings to the brew
#
% ./tests t:d:-d,ret3:-f,func2 +d,evaluate_if
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
=> evaluate: OFF
=> evaluate_if: ON
| | >func3 | | >func3
| | <func3 | | <func3
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
<main <main
% tests -#t:d:-d,ret3:f:-f,func2 -#+d,dump #
## DBUG_DUMP
#
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27) | dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A 64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| | >func3
| | <func3
<main <main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump % ./tests t:d:-d,ret3:f:-f,func2 +d,dump
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27) | dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A 64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| | >func3
| | <func3
<main <main
% tests -#t:d:-d,ret3:f:-f,func2:+d,dump % ./tests t:d:-d,ret3:f:-f,func2:+d,dump
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27) | dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A 64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| | >func3
| | <func3
<main <main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain % ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (35) | dump: Memory: 0x#### Bytes: (35)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 74 66 2C 66 75 6E 63 32 3A 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t
| | >func3
| | <func3
<main <main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain:P % ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P
dbug: >main dbug: >main
dbug-tests: | >func1 dbug-tests: | >func1
dbug-tests: | | | >func3 dbug-tests: | | | >func3
dbug-tests: | | | <func3 dbug-tests: | | | <func3
dbug-tests: | <func1 dbug-tests: | <func1
dbug-tests: | | >func3
dbug-tests: | | <func3
dbug-tests: | dump: Memory: 0x#### Bytes: (37) dbug-tests: | dump: Memory: 0x#### Bytes: (37)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 50 3A 74 66 2C 66 75 6E 63 32 3A 50 3A 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t
dbug-tests: | | >func3
dbug-tests: | | <func3
dbug-tests: <main dbug-tests: <main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F % ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F
dbug: tests.c: >main dbug: tests.c: >main
dbug-tests: tests.c: | >func1 dbug-tests: tests.c: | >func1
dbug-tests: tests.c: | | | >func3 dbug-tests: tests.c: | | | >func3
dbug-tests: tests.c: | | | <func3 dbug-tests: tests.c: | | | <func3
dbug-tests: tests.c: | <func1 dbug-tests: tests.c: | <func1
dbug-tests: tests.c: | | >func3
dbug-tests: tests.c: | | <func3
dbug-tests: tests.c: | dump: Memory: 0x#### Bytes: (39) dbug-tests: tests.c: | dump: Memory: 0x#### Bytes: (39)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74 66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
dbug-tests: tests.c: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:F:P:t dbug-tests: tests.c: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:F:P:t
dbug-tests: tests.c: | | >func3
dbug-tests: tests.c: | | <func3
dbug-tests: tests.c: <main dbug-tests: tests.c: <main
% tests -#t:d:-d,ret3:f:-f,func2 #
## DBUG_EXPLAIN, DBUG_PUSH, DBUG_POP, DBUG_SET
#
% ./tests t:d:-d,ret3:f:-f,func2
>main >main
| >func1 | >func1
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| <func1 | <func1
| | >func3
| | <func3
=> execute => execute
=> evaluate: ON => evaluate: ON
=> evaluate_if: OFF => evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t | explain: dbug explained: d:-d,ret3:f:-f,func2:t
| | >func3
| | <func3
<main <main
% tests -#t:d:-d,ret3 % ./tests t:d:-d,ret3
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -238,58 +252,48 @@ dbug-tests: tests.c: <main ...@@ -238,58 +252,48 @@ dbug-tests: tests.c: <main
| | | info: s=ko | | | info: s=ko
| | <func2 | | <func2
| <func1 | <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> execute => execute
=> evaluate: ON => evaluate: ON
=> evaluate_if: OFF => evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:t | explain: dbug explained: d:-d,ret3:t
<main
% tests -#t:d,info:-d,ret3:d,push
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2 | >func2
| | >func3 | | >func3
| | <func3 | | <func3
| | info: s=ko | | info: s=ko
| <func2 | <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main <main
% tests -#d,info:-d,ret3:d,push % ./tests d,info:-d,ret3:d,push
func2: info: s=ko
func2: info: s=ko func2: info: s=ko
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
<main <main
% tests -#d,info:-d,ret3:d,push,explain % ./tests d,info:-d,ret3:d,push,explain
func2: info: s=ko
func2: info: s=ko func2: info: s=ko
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| explain: dbug explained: d,info,push,explain:-d,ret3:t | explain: dbug explained: d,info,push,explain:-d,ret3:t
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
<main <main
% tests -#d,info:-d,ret3:d,explain % ./tests d,info:-d,ret3:d,explain
func2: info: s=ko
func2: info: s=ko func2: info: s=ko
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
main: explain: dbug explained: d,info,explain:-d,ret3 main: explain: dbug explained: d,info,explain:-d,ret3
% tests -#d,info:-d,ret3:d,explain,pop
func2: info: s=ko func2: info: s=ko
% ./tests d,info:-d,ret3:d,explain,pop
func2: info: s=ko func2: info: s=ko
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
% tests -#d,info:-d,ret3:d,explain,pop t % ./tests d,info:-d,ret3:d,explain t:d,pop
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -297,14 +301,11 @@ func2: info: s=ko ...@@ -297,14 +301,11 @@ func2: info: s=ko
| | | <func3 | | | <func3
| | <func2 | | <func2
| <func1 | <func1
| >func2
| | >func3
| | <func3
| <func2
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
<main main: explain: dbug explained: d,info,explain:-d,ret3
% tests -#d,info:-d,ret3:d,explain,pop +t func2: info: s=ko
% ./tests d,info:-d,ret3:d,explain,pop +t
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -313,21 +314,35 @@ func2: info: s=ko ...@@ -313,21 +314,35 @@ func2: info: s=ko
| | | info: s=ko | | | info: s=ko
| | <func2 | | <func2
| <func1 | <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
main: explain: dbug explained: d,info,explain,pop:-d,ret3 main: explain: dbug explained: d,info,explain,pop:-d,ret3
% tests -#d,info:-d,ret3:d,explain,set
func2: info: s=ko func2: info: s=ko
% ./tests d,info:-d,ret3:d,explain,set
func2: info: s=ko func2: info: s=ko
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
tests.c: main: explain: dbug explained: d,info,explain,set:-d,ret3:F tests.c: main: explain: dbug explained: d,info,explain,set:-d,ret3:F
% tests -#d,info:-d,ret3:d,explain,set:t tests.c: func2: info: s=ko
% ./tests d,info:-d,ret3:d,explain,set:t
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
=> evaluate: OFF
=> evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
tests.c: | >func2
tests.c: | | >func3
tests.c: | | <func3
tests.c: | | info: s=ko
tests.c: | <func2
tests.c: <main
% ./tests t d,info:-d,ret3:d,explain,set:t
>main >main
| >func1 | >func1
| | >func2 | | >func2
...@@ -336,36 +351,133 @@ func2: info: s=ko ...@@ -336,36 +351,133 @@ func2: info: s=ko
| | | info: s=ko | | | info: s=ko
| | <func2 | | <func2
| <func1 | <func1
=> evaluate: OFF
=> evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
tests.c: | >func2
tests.c: | | >func3
tests.c: | | <func3
tests.c: | | info: s=ko
tests.c: | <func2
tests.c: <main
% ./tests t d,info:-d,ret3:d,explain,set,pop
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
| >func2 | >func2
| | >func3 | | >func3
| | <func3 | | <func3
| | info: s=ko
| <func2 | <func2
<main
% ./tests t:f,func2
| | >func2
| | <func2
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t | >func2
tests.c: <main | <func2
% tests t -#d,info:-d,ret3:d,explain,set:t #
## Testing SUBDIR rules
#
% ./tests t:-f,func2/:d
>main >main
| >func1 | >func1
| <func1
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:f:-f,func2/:t
<main
% ./tests t:f,func1/:d
| >func1
| | >func2 | | >func2
| | | >func3 | | | >func3
| | | <func3 | | | <func3
| | | info: s=ko | | | info: s=ok
| | <func2 | | <func2
| <func1 | <func1
=> evaluate: OFF
=> evaluate_if: OFF
% ./tests t:f,main/:d,pop
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | <func2
| <func1
=> evaluate: OFF
=> evaluate_if: OFF
% ./tests f,main/:d,push
=> evaluate: OFF
=> evaluate_if: OFF
| >func2 | >func2
| | >func3 | | >func3
| | <func3 | | <func3
| | info: s=ko
| <func2 | <func2
<main
#
## Testing FixTraceFlags() - when we need to traverse the call stack
# (these tests fail with FixTraceFlags() disabled)
#
# delete the INCLUDE rule up the stack
% ./tests t:f,func1/ --push1=t:f,func3/
| >func1
| | >func2
| | | >func3
| | | <func3
| | <func2
=> push1
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t | | >func3
tests.c: <main | | <func3
% tests t -#d,info:-d,ret3:d,explain,set,pop # delete the EXCLUDE rule up the stack
func2: info: s=ko % ./tests t:-f,func1/ --push1=t
func2: info: s=ko >main
=> push1
| <func1
=> evaluate: OFF
=> evaluate_if: OFF
| >func2
| | >func3
| | <func3
| <func2
<main
# add the INCLUDE rule up the stack
% ./tests t:f,func3 --push1=t:f,main/
| | | >func3
| | | <func3
=> push1
| <func1
=> evaluate: OFF => evaluate: OFF
=> evaluate_if: OFF => evaluate_if: OFF
| >func2
| | >func3
| | <func3
| <func2
<main
# add the EXCLUDE rule up the stack
% ./tests t --push1=t:-f,main/
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | <func2
=> push1
=> evaluate: OFF
=> evaluate_if: OFF
# change the defaults
% ./tests t:f,func3 --push1=t
| | | >func3
| | | <func3
=> push1
| <func1
=> evaluate: OFF
=> evaluate_if: OFF
| >func2
| | >func3
| | <func3
| <func2
<main <main
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#undef DBUG_OFF #undef DBUG_OFF
#endif #endif
char *push1=0;
#include <my_global.h> /* This includes dbug.h */ #include <my_global.h> /* This includes dbug.h */
#include <my_pthread.h> #include <my_pthread.h>
#include <string.h> #include <string.h>
...@@ -29,6 +31,11 @@ int func1() ...@@ -29,6 +31,11 @@ int func1()
{ {
DBUG_ENTER("func1"); DBUG_ENTER("func1");
func2(); func2();
if (push1)
{
DBUG_PUSH(push1);
fprintf(DBUG_FILE, "=> push1\n");
}
DBUG_RETURN(10); DBUG_RETURN(10);
} }
...@@ -43,12 +50,16 @@ int main (int argc, char *argv[]) ...@@ -43,12 +50,16 @@ int main (int argc, char *argv[])
#endif #endif
dup2(1, 2); dup2(1, 2);
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{
if (strncmp(argv[i], "--push1=", 8) == 0)
push1=argv[i]+8;
else
DBUG_PUSH (argv[i]); DBUG_PUSH (argv[i]);
}
{ {
DBUG_ENTER ("main"); DBUG_ENTER ("main");
DBUG_PROCESS ("dbug-tests"); DBUG_PROCESS ("dbug-tests");
func1(); func1();
func2();
DBUG_EXECUTE_IF("dump", DBUG_EXECUTE_IF("dump",
{ {
char s[1000]; char s[1000];
...@@ -68,6 +79,7 @@ int main (int argc, char *argv[]) ...@@ -68,6 +79,7 @@ int main (int argc, char *argv[])
DBUG_EXPLAIN(s, sizeof(s)-1); DBUG_EXPLAIN(s, sizeof(s)-1);
DBUG_PRINT("explain", ("dbug explained: %s", s)); DBUG_PRINT("explain", ("dbug explained: %s", s));
} }
func2();
DBUG_RETURN (0); DBUG_RETURN (0);
} }
} }
...@@ -908,17 +908,17 @@ via the ...@@ -908,17 +908,17 @@ via the
.B DBUG_PUSH .B DBUG_PUSH
or or
.B DBUG_SET .B DBUG_SET
macros. Control string consists of colon separate flags. Colons macros. Control string consists of colon separated flags. Colons
that are part of ':\\', ':/', or '::' are not considered flag that are part of ':\\', ':/', or '::' are not considered flag
separators. A flag may take an argument or a list of arguments. separators. A flag may take an argument or a list of arguments.
If a control string starts from a '+' sign it works If a control string starts from a '+' sign it works
.I incrementally, .I incrementally,
that is, it can modify existing state without overriding it. In such a that is, it can modify existing state without overriding it. Every
string every flag may be preceded by a '+' or '-' to enable or disable flag may be preceded by a '+' or '-' to enable or disable a
a corresponding option in the debugger state. This section summarizes corresponding option in the debugger state or to add or remove
the currently available debugger options and the flag characters which arguments to the list. This section summarizes the currently available
enable or disable them. Argument lists enclosed in '[' and ']' are debugger options and the flag characters which enable or disable them.
optional. Argument lists enclosed in '[' and ']' are optional.
.SP 2 .SP 2
.BL 22 .BL 22
.LI a[,file] .LI a[,file]
...@@ -942,6 +942,15 @@ Default is zero. ...@@ -942,6 +942,15 @@ Default is zero.
.LI f[,functions] .LI f[,functions]
Limit debugger actions to the specified list of functions. Limit debugger actions to the specified list of functions.
An empty list of functions implies that all functions are selected. An empty list of functions implies that all functions are selected.
Every function in the list may optionally be followed by a '/' -
this will implicitly select all the functions down the call stack.
.SP 1
EX: \fCf,func1,func2/:-f,func3,func4/\fR
.SP 1
This would enable debugger in functions 'func1()', 'func2()' and all
functions called from it (directly or indirectly). But not in
functions 'func3()' or 'func4()' and all functions called from
it.
.LI F .LI F
Mark each debugger output line with the name of the source file Mark each debugger output line with the name of the source file
containing the macro causing the output. containing the macro causing the output.
......
...@@ -20,6 +20,14 @@ ...@@ -20,6 +20,14 @@
extern "C" { extern "C" {
#endif #endif
#if !defined(DBUG_OFF) && !defined(_lint) #if !defined(DBUG_OFF) && !defined(_lint)
struct _db_stack_frame_ {
const char *func; /* function name of the previous stack frame */
const char *file; /* filename of the function of previous frame */
uint level; /* this nesting level, highest bit enables tracing */
struct _db_stack_frame_ *prev; /* pointer to the previous frame */
};
struct _db_code_state_; struct _db_code_state_;
extern my_bool _dbug_on_; extern my_bool _dbug_on_;
extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int); extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int);
...@@ -30,13 +38,11 @@ extern void _db_longjmp_(void); ...@@ -30,13 +38,11 @@ extern void _db_longjmp_(void);
extern void _db_process_(const char *name); extern void _db_process_(const char *name);
extern void _db_push_(const char *control); extern void _db_push_(const char *control);
extern void _db_pop_(void); extern void _db_pop_(void);
extern void _db_set_(struct _db_code_state_ *cs, const char *control); extern void _db_set_(const char *control);
extern void _db_set_init_(const char *control); extern void _db_set_init_(const char *control);
extern void _db_enter_(const char *_func_,const char *_file_,uint _line_, extern void _db_enter_(const char *_func_, const char *_file_, uint _line_,
const char **_sfunc_,const char **_sfile_, struct _db_stack_frame_ *_stack_frame_);
uint *_slevel_, char ***); extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_);
extern void _db_return_(uint _line_,const char **_sfunc_,const char **_sfile_,
uint *_slevel_);
extern void _db_pargs_(uint _line_,const char *keyword); extern void _db_pargs_(uint _line_,const char *keyword);
extern void _db_doprnt_ _VARARGS((const char *format,...)) extern void _db_doprnt_ _VARARGS((const char *format,...))
ATTRIBUTE_FORMAT(printf, 1, 2); ATTRIBUTE_FORMAT(printf, 1, 2);
...@@ -48,12 +54,9 @@ extern void _db_unlock_file_(void); ...@@ -48,12 +54,9 @@ extern void _db_unlock_file_(void);
extern FILE *_db_fp_(void); extern FILE *_db_fp_(void);
extern void _db_force_flush(); extern void _db_force_flush();
#define DBUG_ENTER(a) const char *_db_func_, *_db_file_; uint _db_level_; \ #define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
char **_db_framep_; \ _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
_db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_, \ #define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_)
&_db_framep_)
#define DBUG_LEAVE \
_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_)
#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) #define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) #define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
#define DBUG_EXECUTE(keyword,a1) \ #define DBUG_EXECUTE(keyword,a1) \
...@@ -68,7 +71,7 @@ extern void _db_force_flush(); ...@@ -68,7 +71,7 @@ extern void _db_force_flush();
do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0) do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0)
#define DBUG_PUSH(a1) _db_push_ (a1) #define DBUG_PUSH(a1) _db_push_ (a1)
#define DBUG_POP() _db_pop_ () #define DBUG_POP() _db_pop_ ()
#define DBUG_SET(a1) _db_set_ (0, (a1)) #define DBUG_SET(a1) _db_set_ (a1)
#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1) #define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
#define DBUG_PROCESS(a1) _db_process_(a1) #define DBUG_PROCESS(a1) _db_process_(a1)
#define DBUG_FILE _db_fp_() #define DBUG_FILE _db_fp_()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment