summaryrefslogtreecommitdiff
path: root/dbug
diff options
context:
space:
mode:
authorunknown <serg@janus.mylan>2008-02-03 20:58:47 +0100
committerunknown <serg@janus.mylan>2008-02-03 20:58:47 +0100
commitfe7287f8f769df22bca66c99c9aeb17b82ab2df8 (patch)
tree6c8a2d2245b0d6ce45716db6816284d02320fd82 /dbug
parent06477018e77c44b48120cd254bc198baed2d6df7 (diff)
downloadmariadb-git-fe7287f8f769df22bca66c99c9aeb17b82ab2df8.tar.gz
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.
Diffstat (limited to 'dbug')
-rw-r--r--dbug/dbug.c396
-rwxr-xr-xdbug/tests-t.pl306
-rw-r--r--dbug/tests.c16
-rw-r--r--dbug/user.r23
4 files changed, 520 insertions, 221 deletions
diff --git a/dbug/dbug.c b/dbug/dbug.c
index fb442412d04..2aaee9324bd 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -71,6 +71,12 @@
* thread-local settings
* 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 @@
* The following flags are used to determine which
* capabilities the user has enabled with the settings
* 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 000002 /* Debug enabled */
-#define FILE_ON 000004 /* File name print enabled */
-#define LINE_ON 000010 /* Line number print enabled */
-#define DEPTH_ON 000020 /* Function nest level print enabled */
-#define PROCESS_ON 000040 /* Process name print enabled */
-#define NUMBER_ON 000100 /* Number each line of output */
-#define PROFILE_ON 000200 /* Print out profiling code */
-#define PID_ON 000400 /* Identify each line with process id */
-#define TIMESTAMP_ON 001000 /* timestamp every line of output */
-#define SANITY_CHECK_ON 002000 /* Check safemalloc on DBUG_ENTER */
-#define FLUSH_ON_WRITE 004000 /* Flush on every write */
-#define OPEN_APPEND 010000 /* Open for append */
+#define DEBUG_ON (1 << 1) /* Debug enabled */
+#define FILE_ON (1 << 2) /* File name print enabled */
+#define LINE_ON (1 << 3) /* Line number print enabled */
+#define DEPTH_ON (1 << 4) /* Function nest level print enabled */
+#define PROCESS_ON (1 << 5) /* Process name print enabled */
+#define NUMBER_ON (1 << 6) /* Number each line of output */
+#define PROFILE_ON (1 << 7) /* Print out profiling code */
+#define PID_ON (1 << 8) /* Identify each line with process id */
+#define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */
+#define SANITY_CHECK_ON (1 << 10) /* Check safemalloc on DBUG_ENTER */
+#define FLUSH_ON_WRITE (1 << 11) /* Flush on every write */
+#define OPEN_APPEND (1 << 12) /* Open for append */
+#define TRACE_ON (1 << 31) /* Trace enabled. MUST be the highest bit!*/
#define TRACING (cs->stack->flags & TRACE_ON)
#define DEBUGGING (cs->stack->flags & DEBUG_ON)
@@ -141,7 +150,7 @@
* (G?) which allowed the user to specify this.
*
* 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
* forward allocation, the difference in the dbug frame pointers
* represents stack used by the callee function. For reverse allocation,
@@ -156,6 +165,8 @@
#ifdef M_I386 /* predefined by xenix 386 compiler */
#define AUTOS_REVERSE 1
+#else
+#define AUTOS_REVERSE 0
#endif
/*
@@ -180,9 +191,13 @@ struct link {
char str[1]; /* Pointer to link's contents */
};
-/* flags for struct link */
-#define INCLUDE 1
-#define EXCLUDE 2
+/* flags for struct link and return flags of InList */
+#define SUBDIR 1 /* this MUST be 1 */
+#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
@@ -223,15 +238,15 @@ my_bool _dbug_on_= TRUE; /* FALSE if no debugging at all */
typedef struct _db_code_state_ {
const char *process; /* Pointer to process name; usually argv[0] */
- const char *func; /* Name of current user function */
- const char *file; /* Name of current user file */
- char **framep; /* Pointer to current frame */
- struct settings *stack; /* debugging settings */
- const char *jmpfunc; /* Remember current function for setjmp */
- const char *jmpfile; /* Remember current file for setjmp */
- int lineno; /* Current debugger output line number */
- int level; /* Current function nesting level */
- int jmplevel; /* Remember nesting level at setjmp() */
+ const char *func; /* Name of current user function */
+ const char *file; /* Name of current user file */
+ struct _db_stack_frame_ *framep; /* Pointer to current frame */
+ struct settings *stack; /* debugging settings */
+ const char *jmpfunc; /* Remember current function for setjmp */
+ const char *jmpfile; /* Remember current file for setjmp */
+ int lineno; /* Current debugger output line number */
+ int level; /* Current function nesting level */
+ int jmplevel; /* Remember nesting level at setjmp() */
/*
* The following variables are used to hold the state information
@@ -272,10 +287,18 @@ static void PushState(CODE_STATE *cs);
/* Free memory associated with debug state. */
static void FreeState (CODE_STATE *cs, struct settings *state, int free_state);
/* 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 */
-#if !(!defined(HAVE_ACCESS) || defined(MSDOS))
+#if defined(HAVE_ACCESS) && !defined(MSDOS)
static BOOLEAN Writable(const char *pathname);
/* Change file owner and group */
static void ChangeOwner(CODE_STATE *cs, char *pathname);
@@ -423,7 +446,7 @@ void _db_process_(const char *name)
if (!db_process)
db_process= name;
-
+
get_code_state_or_return;
cs->process= name;
}
@@ -431,12 +454,7 @@ void _db_process_(const char *name)
/*
* FUNCTION
*
- * _db_set_ set current debugger settings
- *
- * SYNOPSIS
- *
- * VOID _db_set_(control)
- * char *control;
+ * ParseDbug parse control string and set current debugger settings
*
* DESCRIPTION
*
@@ -458,15 +476,17 @@ void _db_process_(const char *name)
*
* 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;
- int rel;
+ int rel, f_used=0;
struct settings *stack;
- get_code_state_if_not_set_or_return;
stack= cs->stack;
if (control[0] == '-' && control[1] == '#')
@@ -517,7 +537,6 @@ void _db_set_(CODE_STATE *cs, const char *control)
{
int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0;
if (sign) control++;
- /* if (!rel) sign=0; */
c= *control++;
if (*control == ',') control++;
/* XXX when adding new cases here, don't forget _db_explain_ ! */
@@ -546,6 +565,7 @@ void _db_set_(CODE_STATE *cs, const char *control)
stack->delay= atoi(control);
break;
case 'f':
+ f_used= 1;
if (sign < 0 && control == end)
{
if (!is_shared(stack,functions))
@@ -684,8 +704,139 @@ void _db_set_(CODE_STATE *cs, const char *control)
control=end+1;
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
@@ -701,16 +852,19 @@ void _db_set_(CODE_STATE *cs, const char *control)
*
* Given pointer to a debug control string in "control", pushes
* 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)
{
CODE_STATE *cs;
+ int old_fflags;
get_code_state_or_return;
+ old_fflags=fflags(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)
CODE_STATE tmp_cs;
bzero((uchar*) &tmp_cs, sizeof(tmp_cs));
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)
void _db_pop_()
{
struct settings *discard;
+ int old_fflags;
CODE_STATE *cs;
get_code_state_or_return;
@@ -763,8 +918,10 @@ void _db_pop_()
discard= cs->stack;
if (discard->next != NULL)
{
+ old_fflags=fflags(cs);
cs->stack= discard->next;
FreeState(cs, discard, 1);
+ FixTraceFlags(old_fflags, cs);
}
}
@@ -794,7 +951,11 @@ void _db_pop_()
while (listp) \
{ \
if (listp->flags & (f)) \
+ { \
str_to_buf(listp->str); \
+ if (listp->flags & SUBDIR) \
+ char_to_buf('/'); \
+ } \
listp=listp->next_link; \
} \
} while (0)
@@ -928,15 +1089,11 @@ int _db_explain_init_(char *buf, size_t len)
*
* SYNOPSIS
*
- * VOID _db_enter_(_func_, _file_, _line_,
- * _sfunc_, _sfile_, _slevel_, _sframep_)
+ * VOID _db_enter_(_func_, _file_, _line_, _stack_frame_)
* char *_func_; points to current function name
* char *_file_; points to current file name
* int _line_; called from source line number
- * char **_sfunc_; save previous _func_
- * char **_sfile_; save previous _file_
- * int *_slevel_; save previous nesting level
- * char ***_sframep_; save previous frame pointer
+ * struct _db_stack_frame_ allocated on the caller's stack
*
* DESCRIPTION
*
@@ -960,54 +1117,60 @@ int _db_explain_init_(char *buf, size_t len)
*/
void _db_enter_(const char *_func_, const char *_file_,
- uint _line_, const char **_sfunc_, const char **_sfile_,
- uint *_slevel_, char ***_sframep_ __attribute__((unused)))
+ uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
int save_errno;
CODE_STATE *cs;
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;
}
save_errno= errno;
- *_sfunc_= cs->func;
- *_sfile_= cs->file;
+ _stack_frame_->func= cs->func;
+ _stack_frame_->file= cs->file;
cs->func= _func_;
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
- *_sframep_= cs->framep;
- cs->framep= (char **) _sframep_;
if (DoProfile(cs))
{
long stackused;
- if (*cs->framep == NULL)
+ if (cs->framep->prev == NULL)
stackused= 0;
else
{
- stackused= ((long)(*cs->framep)) - ((long)(cs->framep));
+ stackused= (char*)(cs->framep->prev) - (char*)(cs->framep);
stackused= stackused > 0 ? stackused : -stackused;
}
(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,
- cs->func);
-#endif
+ AUTOS_REVERSE ? _stack_frame_->func : cs->func);
(void) fflush(cs->stack->prof_file);
}
#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)
pthread_mutex_lock(&THR_LOCK_dbug);
DoPrefix(cs, _line_);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
dbug_flush(cs); /* This does a unlock */
+ break;
+ case DISABLE_TRACE:
+ cs->framep->level&= ~TRACE_ON;
+ /* fall through */
+ case DONT_TRACE:
+ break;
}
#ifdef SAFEMALLOC
if (cs->stack->flags & SANITY_CHECK_ON)
@@ -1024,11 +1187,9 @@ void _db_enter_(const char *_func_, const char *_file_,
*
* SYNOPSIS
*
- * VOID _db_return_(_line_, _sfunc_, _sfile_, _slevel_)
+ * VOID _db_return_(_line_, _stack_frame_)
* int _line_; current source line number
- * char **_sfunc_; where previous _func_ is to be retrieved
- * char **_sfile_; where previous _file_ is to be retrieved
- * int *_slevel_; where previous level was stashed
+ * struct _db_stack_frame_ allocated on the caller's stack
*
* DESCRIPTION
*
@@ -1040,14 +1201,14 @@ void _db_enter_(const char *_func_, const char *_file_,
*/
/* helper macro */
-void _db_return_(uint _line_, const char **_sfunc_,
- const char **_sfile_, uint *_slevel_)
+void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
int save_errno=errno;
+ int _slevel_=_stack_frame_->level & ~TRACE_ON;
CODE_STATE *cs;
get_code_state_or_return;
- if (cs->level != (int) *_slevel_)
+ if (cs->level != _slevel_)
{
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
@@ -1060,7 +1221,7 @@ void _db_return_(uint _line_, const char **_sfunc_,
#ifdef SAFEMALLOC
if (cs->stack->flags & SANITY_CHECK_ON)
{
- if (_sanity(*_sfile_,_line_))
+ if (_sanity(_stack_frame_->file,_line_))
cs->stack->flags &= ~SANITY_CHECK_ON;
}
#endif
@@ -1068,7 +1229,7 @@ void _db_return_(uint _line_, const char **_sfunc_,
if (DoProfile(cs))
(void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func);
#endif
- if (DoTrace(cs))
+ if (TRACING && DoTrace(cs, 1) & DO_TRACE)
{
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
@@ -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
function was entered and enabled in function.
*/
- cs->level= *_slevel_ != 0 ? *_slevel_-1 : 0;
- cs->func= *_sfunc_;
- cs->file= *_sfile_;
-#ifndef THREAD
+ cs->level= _slevel_ != 0 ? _slevel_ - 1 : 0;
+ cs->func= _stack_frame_->func;
+ cs->file= _stack_frame_->file;
if (cs->framep != NULL)
- cs->framep= (char **) *cs->framep;
-#endif
+ cs->framep= cs->framep->prev;
errno=save_errno;
}
@@ -1252,13 +1411,13 @@ void _db_dump_(uint _line_, const char *keyword,
*
* The mode of operation is defined by "todo" parameter.
*
- * If it's INCLUDE, elements (strings from "cltp") are added to the
- * list, they'll have INCLUDE flag set. If the list already contains
+ * If it is INCLUDE, elements (strings from "cltp") are added to the
+ * 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 existing element is adjusted (INCLUDE bit is set, EXCLUDE bit
* 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,
* it is removed, new element is not added.
*/
@@ -1268,16 +1427,22 @@ static struct link *ListAddDel(struct link *head, const char *ctlp,
{
const char *start;
struct link **cur;
- int len;
+ int len, subdir;
ctlp--;
next:
while (++ctlp < end)
{
start= ctlp;
+ subdir=0;
while (ctlp < end && *ctlp != ',')
ctlp++;
len=ctlp-start;
+ if (start[len-1] == '/')
+ {
+ len--;
+ subdir=SUBDIR;
+ }
if (len == 0) continue;
for (cur=&head; *cur; cur=&((*cur)->next_link))
{
@@ -1291,8 +1456,8 @@ next:
}
else
{
- (*cur)->flags&=~EXCLUDE;
- (*cur)->flags|=INCLUDE;
+ (*cur)->flags&=~(EXCLUDE & SUBDIR);
+ (*cur)->flags|=INCLUDE | subdir;
}
goto next;
}
@@ -1300,7 +1465,7 @@ next:
*cur= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy((*cur)->str, start, len);
(*cur)->str[len]=0;
- (*cur)->flags=todo;
+ (*cur)->flags=todo | subdir;
(*cur)->next_link=0;
}
return head;
@@ -1355,12 +1520,6 @@ static struct link *ListCopy(struct link *orig)
*
* InList test a given string for member of a given list
*
- * SYNOPSIS
- *
- * static int InList(linkp, cp)
- * struct link *linkp;
- * char *cp;
- *
* DESCRIPTION
*
* Tests the string pointed to by "cp" to determine if it is in
@@ -1373,9 +1532,7 @@ static struct link *ListCopy(struct link *orig)
* is a list, only those strings in the list will be accepted.
*
* RETURN
- * 0 - not in the list (or matched an EXCLUDE element)
- * 1 - in the list by default (list is empty or only has EXCLUDE elements)
- * 2 - in the list explictly (matched an INCLUDE element)
+ * combination of SUBDIR, INCLUDE, EXCLUDE, MATCHED flags
*
*/
@@ -1383,12 +1540,14 @@ static int InList(struct link *linkp, const char *cp)
{
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))
- return linkp->flags & EXCLUDE ? 0 : 2;
+ return linkp->flags;
if (!(linkp->flags & EXCLUDE))
- result=0;
+ result=NOT_MATCHED;
+ if (linkp->flags & SUBDIR)
+ result|=SUBDIR;
}
return result;
}
@@ -1535,25 +1694,34 @@ void _db_end_()
*
* DoTrace check to see if tracing is current enabled
*
- * SYNOPSIS
- *
- * static BOOLEAN DoTrace(stack)
+ * 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_)
*
* DESCRIPTION
*
* Checks to see if tracing is enabled based on whether the
* user has specified tracing, the maximum trace depth has
* not yet been reached, the current function is selected,
- * and the current process is selected. Returns TRUE if
- * tracing is enabled, FALSE otherwise.
+ * and the current process is selected.
*
*/
-static BOOLEAN DoTrace(CODE_STATE *cs)
+static int DoTrace(CODE_STATE *cs, int tracing)
{
- return (TRACING && cs->level <= cs->stack->maxdepth &&
- InList(cs->stack->functions, cs->func) &&
- InList(cs->stack->processes, cs->process));
+ if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
+ InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE))
+ 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)
{
return PROFILING &&
cs->level <= cs->stack->maxdepth &&
- InList(cs->stack->p_functions, cs->func) &&
- InList(cs->stack->processes, cs->process);
+ InList(cs->stack->p_functions, cs->func) & (INCLUDE|MATCHED) &&
+ InList(cs->stack->processes, cs->process) & (INCLUDE|MATCHED);
}
#endif
@@ -1616,12 +1784,10 @@ FILE *_db_fp_(void)
BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
{
get_code_state_if_not_set_or_return FALSE;
+ strict=strict ? INCLUDE : INCLUDE|MATCHED;
- return (DEBUGGING &&
- (!TRACING || cs->level <= cs->stack->maxdepth) &&
- InList(cs->stack->functions, cs->func) &&
- InList(cs->stack->keywords, keyword) > (strict != 0) &&
- InList(cs->stack->processes, cs->process));
+ return DEBUGGING && DoTrace(cs, 1) & DO_TRACE &&
+ InList(cs->stack->keywords, keyword) & strict;
}
/*
diff --git a/dbug/tests-t.pl b/dbug/tests-t.pl
index 1533a49c9bf..4e4503f1ef7 100755
--- a/dbug/tests-t.pl
+++ b/dbug/tests-t.pl
@@ -12,8 +12,10 @@ die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /;
# load tests
@tests=();
while (<DATA>) {
- if (/^% tests /) {
+ if (/^% \.\/tests /) {
push @tests, [ $' ]
+ } elsif (/^#/) {
+ next;
} else {
push @{$tests[$#tests]}, $_
}
@@ -36,24 +38,27 @@ for (@tests) {
}
__DATA__
-% tests -#d
-func2: info: s=ok
+% ./tests -#d
func2: info: s=ok
=> execute
=> evaluate: ON
=> evaluate_if: OFF
main: explain: dbug explained: d
-% tests -#d,ret3
+func2: info: s=ok
+% ./tests d,ret3
=> evaluate: OFF
=> evaluate_if: OFF
-% tests -#d:-d,ret3
-func2: info: s=ko
+#
+## Testing negative lists
+#
+% ./tests d:-d,ret3
func2: info: s=ko
=> execute
=> evaluate: ON
=> evaluate_if: OFF
main: explain: dbug explained: d:-d,ret3
-% tests -#t:-d,ret3
+func2: info: s=ko
+% ./tests t:-d,ret3
>main
| >func1
| | >func2
@@ -61,14 +66,14 @@ main: explain: dbug explained: d:-d,ret3
| | | <func3
| | <func2
| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
| >func2
| | >func3
| | <func3
| <func2
-=> evaluate: OFF
-=> evaluate_if: OFF
<main
-% tests -#t:d,info:-d,ret3
+% ./tests t:d,info:-d,ret3
>main
| >func1
| | >func2
@@ -77,159 +82,168 @@ main: explain: dbug explained: d:-d,ret3
| | | info: s=ko
| | <func2
| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
-=> evaluate: OFF
-=> evaluate_if: OFF
<main
-% tests -#t:d,info:-d,ret3:-f,func2
+% ./tests t:d,info:-d,ret3:-f,func2
>main
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
=> evaluate: OFF
=> evaluate_if: OFF
+| | >func3
+| | <func3
<main
-% tests -#t:d,info:-d,ret3:-f,func2 d,evaluate
+% ./tests t:d,info:-d,ret3:-f,func2 d,evaluate
=> evaluate: ON
=> 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_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_if: ON
-% tests -#t:d:-d,ret3:-f,func2 +d,evaluate_if
+% ./tests t:d:-d,ret3:-f,func2
>main
| >func1
| | | >func3
| | | <func3
| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:-d,ret3:f:-f,func2:t
| | >func3
| | <func3
-=> evaluate: OFF
-=> evaluate_if: ON
<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
| >func1
| | | >func3
| | | <func3
| <func1
+=> evaluate: OFF
+=> evaluate_if: ON
| | >func3
| | <func3
-=> execute
-=> evaluate: ON
-=> evaluate_if: OFF
-| explain: dbug explained: d:-d,ret3:f:-f,func2:t
<main
-% tests -#t:d:-d,ret3:f:-f,func2 -#+d,dump
+#
+## DBUG_DUMP
+#
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
| 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
74
=> evaluate: OFF
=> evaluate_if: OFF
+| | >func3
+| | <func3
<main
-% tests -#t:d:-d,ret3:f:-f,func2 +d,dump
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
| 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
74
=> evaluate: OFF
=> evaluate_if: OFF
+| | >func3
+| | <func3
<main
-% tests -#t:d:-d,ret3:f:-f,func2:+d,dump
+% ./tests t:d:-d,ret3:f:-f,func2:+d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
| 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
74
=> evaluate: OFF
=> evaluate_if: OFF
+| | >func3
+| | <func3
<main
-% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain
>main
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
| 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
66 2C 66 75 6E 63 32 3A 74
=> evaluate: OFF
=> evaluate_if: OFF
| explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t
+| | >func3
+| | <func3
<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-tests: | >func1
dbug-tests: | | | >func3
dbug-tests: | | | <func3
dbug-tests: | <func1
-dbug-tests: | | >func3
-dbug-tests: | | <func3
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
66 2C 66 75 6E 63 32 3A 50 3A 74
=> evaluate: OFF
=> evaluate_if: OFF
dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t
+dbug-tests: | | >func3
+dbug-tests: | | <func3
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: tests.c: | >func1
dbug-tests: tests.c: | | | >func3
dbug-tests: tests.c: | | | <func3
dbug-tests: tests.c: | <func1
-dbug-tests: tests.c: | | >func3
-dbug-tests: tests.c: | | <func3
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
66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74
=> evaluate: 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: | | >func3
+dbug-tests: tests.c: | | <func3
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
| >func1
| | | >func3
| | | <func3
| <func1
-| | >func3
-| | <func3
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
+| | >func3
+| | <func3
<main
-% tests -#t:d:-d,ret3
+% ./tests t:d:-d,ret3
>main
| >func1
| | >func2
@@ -238,58 +252,48 @@ dbug-tests: tests.c: <main
| | | info: s=ko
| | <func2
| <func1
-| >func2
-| | >func3
-| | <func3
-| | info: s=ko
-| <func2
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| 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
| | >func3
| | <func3
| | info: s=ko
| <func2
-=> evaluate: OFF
-=> evaluate_if: OFF
<main
-% tests -#d,info:-d,ret3:d,push
-func2: info: s=ko
+% ./tests d,info:-d,ret3:d,push
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
<main
-% tests -#d,info:-d,ret3:d,push,explain
-func2: info: s=ko
+% ./tests d,info:-d,ret3:d,push,explain
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
| explain: dbug explained: d,info,push,explain:-d,ret3:t
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
<main
-% tests -#d,info:-d,ret3:d,explain
-func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
main: explain: dbug explained: d,info,explain:-d,ret3
-% tests -#d,info:-d,ret3:d,explain,pop
func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,pop
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
-% tests -#d,info:-d,ret3:d,explain,pop t
+% ./tests d,info:-d,ret3:d,explain t:d,pop
>main
| >func1
| | >func2
@@ -297,14 +301,11 @@ func2: info: s=ko
| | | <func3
| | <func2
| <func1
-| >func2
-| | >func3
-| | <func3
-| <func2
=> evaluate: OFF
=> evaluate_if: OFF
-<main
-% tests -#d,info:-d,ret3:d,explain,pop +t
+main: explain: dbug explained: d,info,explain:-d,ret3
+func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,pop +t
>main
| >func1
| | >func2
@@ -313,21 +314,35 @@ func2: info: s=ko
| | | info: s=ko
| | <func2
| <func1
-| >func2
-| | >func3
-| | <func3
-| | info: s=ko
-| <func2
=> evaluate: OFF
=> evaluate_if: OFF
main: explain: dbug explained: d,info,explain,pop:-d,ret3
-% tests -#d,info:-d,ret3:d,explain,set
func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,set
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
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
| >func1
| | >func2
@@ -336,36 +351,133 @@ func2: info: s=ko
| | | 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,pop
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
| >func2
| | >func3
| | <func3
-| | info: s=ko
| <func2
+<main
+% ./tests t:f,func2
+| | >func2
+| | <func2
=> evaluate: OFF
=> evaluate_if: OFF
- tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
- tests.c: <main
-% tests t -#d,info:-d,ret3:d,explain,set:t
+| >func2
+| <func2
+#
+## Testing SUBDIR rules
+#
+% ./tests t:-f,func2/:d
>main
| >func1
+| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:f:-f,func2/:t
+<main
+% ./tests t:f,func1/:d
+| >func1
| | >func2
| | | >func3
| | | <func3
-| | | info: s=ko
+| | | info: s=ok
| | <func2
| <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
| | >func3
| | <func3
-| | info: s=ko
| <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_if: OFF
- tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
- tests.c: <main
-% tests t -#d,info:-d,ret3:d,explain,set,pop
-func2: info: s=ko
-func2: info: s=ko
+| | >func3
+| | <func3
+# delete the EXCLUDE rule up the stack
+% ./tests t:-f,func1/ --push1=t
+>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_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
diff --git a/dbug/tests.c b/dbug/tests.c
index 42482635eee..edb999c0c60 100644
--- a/dbug/tests.c
+++ b/dbug/tests.c
@@ -6,6 +6,8 @@
#undef DBUG_OFF
#endif
+char *push1=0;
+
#include <my_global.h> /* This includes dbug.h */
#include <my_pthread.h>
#include <string.h>
@@ -29,6 +31,11 @@ int func1()
{
DBUG_ENTER("func1");
func2();
+ if (push1)
+ {
+ DBUG_PUSH(push1);
+ fprintf(DBUG_FILE, "=> push1\n");
+ }
DBUG_RETURN(10);
}
@@ -43,12 +50,16 @@ int main (int argc, char *argv[])
#endif
dup2(1, 2);
for (i = 1; i < argc; i++)
- DBUG_PUSH (argv[i]);
+ {
+ if (strncmp(argv[i], "--push1=", 8) == 0)
+ push1=argv[i]+8;
+ else
+ DBUG_PUSH (argv[i]);
+ }
{
DBUG_ENTER ("main");
DBUG_PROCESS ("dbug-tests");
func1();
- func2();
DBUG_EXECUTE_IF("dump",
{
char s[1000];
@@ -68,6 +79,7 @@ int main (int argc, char *argv[])
DBUG_EXPLAIN(s, sizeof(s)-1);
DBUG_PRINT("explain", ("dbug explained: %s", s));
}
+ func2();
DBUG_RETURN (0);
}
}
diff --git a/dbug/user.r b/dbug/user.r
index e41367de321..6cb1c05b25f 100644
--- a/dbug/user.r
+++ b/dbug/user.r
@@ -908,17 +908,17 @@ via the
.B DBUG_PUSH
or
.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
separators. A flag may take an argument or a list of arguments.
If a control string starts from a '+' sign it works
.I incrementally,
-that is, it can modify existing state without overriding it. In such a
-string every flag may be preceded by a '+' or '-' to enable or disable
-a corresponding option in the debugger state. This section summarizes
-the currently available debugger options and the flag characters which
-enable or disable them. Argument lists enclosed in '[' and ']' are
-optional.
+that is, it can modify existing state without overriding it. Every
+flag may be preceded by a '+' or '-' to enable or disable a
+corresponding option in the debugger state or to add or remove
+arguments to the list. This section summarizes the currently available
+debugger options and the flag characters which enable or disable them.
+Argument lists enclosed in '[' and ']' are optional.
.SP 2
.BL 22
.LI a[,file]
@@ -942,6 +942,15 @@ Default is zero.
.LI f[,functions]
Limit debugger actions to the specified list of functions.
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
Mark each debugger output line with the name of the source file
containing the macro causing the output.