82 #include <my_global.h>
89 #define fnmatch(A,B,C) strcmp(A,B)
103 #define PRINTBUF 1024
116 #define DEBUG_ON (1 << 1)
117 #define FILE_ON (1 << 2)
118 #define LINE_ON (1 << 3)
119 #define DEPTH_ON (1 << 4)
120 #define PROCESS_ON (1 << 5)
121 #define NUMBER_ON (1 << 6)
122 #define PROFILE_ON (1 << 7)
123 #define PID_ON (1 << 8)
124 #define TIMESTAMP_ON (1 << 9)
125 #define FLUSH_ON_WRITE (1 << 10)
126 #define OPEN_APPEND (1 << 11)
127 #define TRACE_ON ((uint)1 << 31)
129 #define TRACING (cs->stack->flags & TRACE_ON)
130 #define DEBUGGING (cs->stack->flags & DEBUG_ON)
131 #define PROFILING (cs->stack->flags & PROFILE_ON)
137 #define BOOLEAN my_bool
143 #define IMPORT extern
146 #define REGISTER register
161 #define PROF_FILE "dbugmon.out"
162 #define PROF_EFMT "E\t%ld\t%s\n"
163 #define PROF_SFMT "S\t%lx\t%lx\t%s\n"
164 #define PROF_XFMT "X\t%ld\t%s\n"
167 #define AUTOS_REVERSE 1
169 #define AUTOS_REVERSE 0
177 static void perror();
187 struct link *next_link;
197 #define MATCHED 65536
198 #define NOT_MATCHED 0
217 char name[FN_REFLEN];
218 struct link *functions;
219 struct link *p_functions;
220 struct link *keywords;
221 struct link *processes;
225 #define is_shared(S, V) ((S)->next && (S)->next->V == (S)->V)
232 static BOOLEAN init_done= FALSE;
239 static struct settings init_settings;
240 static const char *db_process= 0;
241 my_bool _dbug_on_= TRUE;
267 const char *u_keyword;
268 uint m_read_lock_count;
275 #define get_code_state_if_not_set_or_return if (!cs && !((cs=code_state()))) return
276 #define get_code_state_or_return if (!((cs=code_state()))) return
279 #define ListAdd(A,B,C) ListAddDel(A,B,C,INCLUDE)
280 #define ListDel(A,B,C) ListAddDel(A,B,C,EXCLUDE)
281 static struct link *ListAddDel(
struct link *,
const char *,
const char *,
int);
282 static struct link *ListCopy(
struct link *);
283 static int InList(
struct link *linkp,
const char *cp);
284 static uint ListFlags(
struct link *linkp);
285 static void FreeList(
struct link *linkp);
288 static void DBUGOpenFile(
CODE_STATE *,
const char *,
const char *,
int);
289 static void DBUGCloseFile(
CODE_STATE *cs, FILE *fp);
302 #define ENABLE_TRACE 3
303 #define DISABLE_TRACE 4
306 #if defined(HAVE_ACCESS)
307 static BOOLEAN Writable(
const char *pathname);
309 static void ChangeOwner(
CODE_STATE *cs,
char *pathname);
313 static void DoPrefix(
CODE_STATE *cs, uint line);
315 static char *DbugMalloc(
size_t size);
316 static const char *BaseName(
const char *pathname);
317 static void Indent(
CODE_STATE *cs,
int indent);
319 static void DbugExit(
const char *why);
320 static const char *DbugStrTok(
const char *s);
321 static void DbugVfprintf(FILE *stream,
const char* format, va_list args);
327 #define ERR_MISSING_RETURN "missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
328 #define ERR_MISSING_UNLOCK "missing DBUG_UNLOCK_FILE macro in function \"%s\"\n"
329 #define ERR_OPEN "%s: can't open debug output stream \"%s\": "
330 #define ERR_CLOSE "%s: can't close debug file: "
331 #define ERR_ABORT "%s: debugger aborting because %s\n"
338 #if !defined(HAVE_ACCESS)
339 #define EXISTS(pathname) (FALSE)
340 #define Writable(name) (TRUE)
342 #define EXISTS(pathname) (access(pathname, F_OK) == 0)
343 #define WRITABLE(pathname) (access(pathname, W_OK) == 0)
351 #include <my_pthread.h>
352 static pthread_mutex_t THR_LOCK_dbug;
359 static pthread_mutex_t THR_LOCK_gcov;
382 pthread_mutex_init(&THR_LOCK_dbug, NULL);
383 pthread_mutex_init(&THR_LOCK_gcov, NULL);
384 my_rwlock_init(&THR_LOCK_init_settings, NULL);
385 memset(&init_settings, 0,
sizeof(init_settings));
386 init_settings.out_file=stderr;
387 init_settings.flags=OPEN_APPEND;
390 if (!(cs_ptr= (
CODE_STATE**) my_thread_var_dbug()))
395 memset(cs, 0,
sizeof(*cs));
396 cs->process= db_process ? db_process :
"dbug";
399 cs->stack=&init_settings;
400 cs->m_read_lock_count= 0;
415 if (cs->stack == &init_settings)
417 if (++(cs->m_read_lock_count) == 1)
418 rw_rdlock(&THR_LOCK_init_settings);
428 if (cs->stack == &init_settings)
430 if (--(cs->m_read_lock_count) == 0)
431 rw_unlock(&THR_LOCK_init_settings);
441 #define Delay(A) sleep(((uint) A)/10)
458 void _db_process_(
const char *
name)
465 get_code_state_or_return;
499 int DbugParse(
CODE_STATE *cs,
const char *control)
512 assert(! cs->locked);
520 assert(cs->m_read_lock_count == 0);
521 if (stack == &init_settings)
522 rw_wrlock(&THR_LOCK_init_settings);
524 if (control[0] ==
'-' && control[1] ==
'#')
527 rel= control[0] ==
'+' || control[0] ==
'-';
528 if ((!rel || (!stack->out_file && !stack->next)))
531 FreeState(cs, stack, 0);
536 stack->out_file= stderr;
537 stack->prof_file= NULL;
538 stack->functions= NULL;
539 stack->p_functions= NULL;
540 stack->keywords= NULL;
541 stack->processes= NULL;
543 else if (!stack->out_file)
545 stack->flags= stack->next->flags;
546 stack->delay= stack->next->delay;
547 stack->maxdepth= stack->next->maxdepth;
548 stack->sub_level= stack->next->sub_level;
549 strcpy(stack->name, stack->next->name);
550 stack->prof_file= stack->next->prof_file;
551 if (stack->next == &init_settings)
553 assert(stack != &init_settings);
554 rw_rdlock(&THR_LOCK_init_settings);
562 stack->out_file= stderr;
563 stack->functions= ListCopy(init_settings.functions);
564 stack->p_functions= ListCopy(init_settings.p_functions);
565 stack->keywords= ListCopy(init_settings.keywords);
566 stack->processes= ListCopy(init_settings.processes);
568 rw_unlock(&THR_LOCK_init_settings);
572 stack->out_file= stack->next->out_file;
573 stack->functions= stack->next->functions;
574 stack->p_functions= stack->next->p_functions;
575 stack->keywords= stack->next->keywords;
576 stack->processes= stack->next->processes;
580 end= DbugStrTok(control);
581 while (control < end)
583 int c, sign= (*control ==
'+') ? 1 : (*control ==
'-') ? -1 : 0;
586 if (*control ==
',') control++;
590 if (sign < 0 && control == end)
592 if (!is_shared(stack, keywords))
593 FreeList(stack->keywords);
594 stack->keywords=NULL;
595 stack->flags&= ~DEBUG_ON;
598 if (rel && is_shared(stack, keywords))
599 stack->keywords= ListCopy(stack->keywords);
604 stack->keywords= ListDel(stack->keywords, control, end);
606 if (stack->keywords == NULL)
607 stack->flags&= ~DEBUG_ON;
613 if (!(DEBUGGING && stack->keywords == NULL))
615 stack->keywords= ListAdd(stack->keywords, control, end);
616 stack->flags|= DEBUG_ON;
620 if (sign == 1 && control == end)
622 FreeList(stack->keywords);
623 stack->keywords= NULL;
628 stack->delay= atoi(control);
632 if (sign < 0 && control == end)
634 if (!is_shared(stack,functions))
635 FreeList(stack->functions);
636 stack->functions=NULL;
639 if (rel && is_shared(stack,functions))
640 stack->functions= ListCopy(stack->functions);
642 stack->functions= ListDel(stack->functions, control, end);
644 stack->functions= ListAdd(stack->functions, control, end);
648 stack->flags &= ~FILE_ON;
650 stack->flags |= FILE_ON;
654 stack->flags &= ~PID_ON;
656 stack->flags |= PID_ON;
660 stack->flags &= ~LINE_ON;
662 stack->flags |= LINE_ON;
666 stack->flags &= ~DEPTH_ON;
668 stack->flags |= DEPTH_ON;
672 stack->flags &= ~NUMBER_ON;
674 stack->flags |= NUMBER_ON;
678 stack->flags |= FLUSH_ON_WRITE;
683 if (!is_shared(stack, out_file))
684 DBUGCloseFile(cs, stack->out_file);
687 stack->flags &= ~FLUSH_ON_WRITE;
688 stack->out_file= stderr;
691 if (c ==
'a' || c ==
'A')
692 stack->flags |= OPEN_APPEND;
694 stack->flags &= ~OPEN_APPEND;
696 DBUGOpenFile(cs, control, end, stack->flags & OPEN_APPEND);
698 DBUGOpenFile(cs,
"-",0,0);
701 if (sign < 0 && control == end)
703 if (!is_shared(stack,processes))
704 FreeList(stack->processes);
705 stack->processes=NULL;
708 if (rel && is_shared(stack, processes))
709 stack->processes= ListCopy(stack->processes);
711 stack->processes= ListDel(stack->processes, control, end);
713 stack->processes= ListAdd(stack->processes, control, end);
717 stack->flags &= ~PROCESS_ON;
719 stack->flags |= PROCESS_ON;
722 stack->sub_level= cs->level;
728 stack->maxdepth-= atoi(control);
735 stack->maxdepth+= atoi(control);
737 stack->maxdepth= MAXDEPTH;
739 if (stack->maxdepth > 0)
740 stack->flags |= TRACE_ON;
742 stack->flags &= ~TRACE_ON;
746 stack->flags &= ~TIMESTAMP_ON;
748 stack->flags |= TIMESTAMP_ON;
754 end= DbugStrTok(control);
757 if (stack->next == &init_settings)
762 assert((stack->functions == NULL) || (stack->functions != init_settings.functions));
763 assert((stack->p_functions == NULL) || (stack->p_functions != init_settings.p_functions));
764 assert((stack->keywords == NULL) || (stack->keywords != init_settings.keywords));
765 assert((stack->processes == NULL) || (stack->processes != init_settings.processes));
768 if (stack == &init_settings)
769 rw_unlock(&THR_LOCK_init_settings);
771 return !rel || f_used;
774 #define framep_trace_flag(cs, frp) (frp ? \
775 frp->level & TRACE_ON : \
776 (ListFlags(cs->stack->functions) & INCLUDE) ? \
779 void FixTraceFlags_helper(
CODE_STATE *cs,
const char *func,
783 FixTraceFlags_helper(cs, framep->func, framep->prev);
786 cs->level= framep->level & ~TRACE_ON;
787 framep->level= cs->level | framep_trace_flag(cs, framep->prev);
793 switch(DoTrace(cs)) {
795 framep->level|= TRACE_ON;
798 framep->level&= ~TRACE_ON;
803 #define fflags(cs) cs->stack->out_file ? ListFlags(cs->stack->functions) : TRACE_ON;
805 void FixTraceFlags(uint old_fflags,
CODE_STATE *cs)
808 uint new_fflags, traceon,
level;
824 new_fflags=fflags(cs);
825 if (new_fflags & SUBDIR)
836 if (!(old_fflags & SUBDIR) && !((new_fflags^old_fflags) & INCLUDE))
845 for (traceon=framep->level; framep; framep=framep->prev)
846 if ((traceon ^ framep->level) & TRACE_ON)
854 if (((traceon & TRACE_ON) != 0) == ((new_fflags & INCLUDE) == 0))
871 FixTraceFlags_helper(cs, func, cs->framep);
896 void _db_set_(
const char *control)
900 get_code_state_or_return;
903 old_fflags=fflags(cs);
906 if (cs->stack == &init_settings)
909 if (DbugParse(cs, control))
912 FixTraceFlags(old_fflags, cs);
935 void _db_push_(
const char *control)
939 get_code_state_or_return;
942 old_fflags=fflags(cs);
947 if (DbugParse(cs, control))
950 FixTraceFlags(old_fflags, cs);
963 get_code_state_or_return FALSE;
964 return (cs->stack != &init_settings);
982 void _db_set_init_(
const char *control)
985 memset(&tmp_cs, 0,
sizeof(tmp_cs));
986 tmp_cs.stack= &init_settings;
987 tmp_cs.process= db_process ? db_process :
"dbug";
988 DbugParse(&tmp_cs, control);
1014 get_code_state_or_return;
1017 if (discard != &init_settings)
1019 read_lock_stack(cs);
1020 old_fflags=fflags(cs);
1023 cs->stack= discard->next;
1024 FreeState(cs, discard, 1);
1026 read_lock_stack(cs);
1027 FixTraceFlags(old_fflags, cs);
1044 #define char_to_buf(C) do { \
1046 if (buf >= end) goto overflow; \
1048 #define str_to_buf(S) do { \
1050 buf=strnmov(buf, (S), end-buf); \
1051 if (buf >= end) goto overflow; \
1053 #define list_to_buf(l, f) do { \
1054 struct link *listp=(l); \
1057 if (listp->flags & (f)) \
1059 str_to_buf(listp->str); \
1060 if (listp->flags & SUBDIR) \
1063 listp=listp->next_link; \
1066 #define int_to_buf(i) do { \
1068 int10_to_str((i), b, 10); \
1071 #define colon_to_buf do { \
1072 if (buf != start) char_to_buf(':'); \
1074 #define op_int_to_buf(C, val, def) do { \
1075 if ((val) != (def)) \
1082 #define op_intf_to_buf(C, val, def, cond) do { \
1087 if ((val) != (def)) int_to_buf(val); \
1090 #define op_str_to_buf(C, val, cond) do { \
1096 if (*s) str_to_buf(s); \
1099 #define op_list_to_buf(C, val, cond) do { \
1102 int f=ListFlags(val); \
1106 list_to_buf(val, INCLUDE); \
1112 list_to_buf(val, EXCLUDE); \
1116 #define op_bool_to_buf(C, cond) do { \
1126 char *start=
buf, *end=buf+len-4;
1128 get_code_state_if_not_set_or_return *buf=0;
1130 read_lock_stack(cs);
1132 op_list_to_buf(
'd', cs->stack->keywords, DEBUGGING);
1133 op_int_to_buf (
'D', cs->stack->delay, 0);
1134 op_list_to_buf(
'f', cs->stack->functions, cs->stack->functions);
1135 op_bool_to_buf(
'F', cs->stack->flags & FILE_ON);
1136 op_bool_to_buf(
'i', cs->stack->flags & PID_ON);
1137 op_list_to_buf(
'g', cs->stack->p_functions, PROFILING);
1138 op_bool_to_buf(
'L', cs->stack->flags & LINE_ON);
1139 op_bool_to_buf(
'n', cs->stack->flags & DEPTH_ON);
1140 op_bool_to_buf(
'N', cs->stack->flags & NUMBER_ON);
1142 ((cs->stack->flags & FLUSH_ON_WRITE ? 0 : 32) |
1143 (cs->stack->flags & OPEN_APPEND ?
'A' :
'O')),
1144 cs->stack->name, cs->stack->out_file != stderr);
1145 op_list_to_buf(
'p', cs->stack->processes, cs->stack->processes);
1146 op_bool_to_buf(
'P', cs->stack->flags & PROCESS_ON);
1147 op_bool_to_buf(
'r', cs->stack->sub_level != 0);
1148 op_intf_to_buf(
't', cs->stack->maxdepth, MAXDEPTH, TRACING);
1149 op_bool_to_buf(
'T', cs->stack->flags & TIMESTAMP_ON);
1171 #undef op_int_to_buf
1172 #undef op_intf_to_buf
1173 #undef op_str_to_buf
1174 #undef op_list_to_buf
1175 #undef op_bool_to_buf
1186 int _db_explain_init_(
char *buf,
size_t len)
1189 memset(&cs, 0,
sizeof(cs));
1190 cs.stack=&init_settings;
1191 return _db_explain_(&cs, buf, len);
1228 void _db_enter_(
const char *_func_,
const char *_file_,
1233 if (!((cs=code_state())))
1235 _stack_frame_->level= 0;
1236 _stack_frame_->prev= 0;
1241 read_lock_stack(cs);
1243 _stack_frame_->func= cs->func;
1244 _stack_frame_->file= cs->file;
1247 _stack_frame_->prev= cs->framep;
1248 _stack_frame_->level= ++cs->level | framep_trace_flag(cs, cs->framep);
1249 cs->framep= _stack_frame_;
1251 switch (DoTrace(cs)) {
1253 cs->framep->level|= TRACE_ON;
1254 if (!TRACING)
break;
1260 pthread_mutex_lock(&THR_LOCK_dbug);
1261 DoPrefix(cs, _line_);
1262 Indent(cs, cs->level);
1263 (void) fprintf(cs->stack->out_file,
">%s\n", cs->func);
1268 cs->framep->level&= ~TRACE_ON;
1300 int save_errno=errno;
1301 uint _slevel_= _stack_frame_->level & ~TRACE_ON;
1303 get_code_state_or_return;
1305 if (cs->framep != _stack_frame_)
1308 my_snprintf(buf,
sizeof(buf), ERR_MISSING_RETURN, cs->func);
1312 read_lock_stack(cs);
1314 if (DoTrace(cs) & DO_TRACE)
1319 pthread_mutex_lock(&THR_LOCK_dbug);
1320 DoPrefix(cs, _line_);
1321 Indent(cs, cs->level);
1322 (void) fprintf(cs->stack->out_file,
"<%s %u\n", cs->func, _line_);
1330 cs->level= _slevel_ != 0 ? _slevel_ - 1 : 0;
1331 cs->func= _stack_frame_->func;
1332 cs->file= _stack_frame_->file;
1333 if (cs->framep != NULL)
1334 cs->framep= cs->framep->prev;
1361 void _db_pargs_(uint _line_,
const char *keyword)
1364 get_code_state_or_return;
1366 cs->u_keyword= keyword;
1391 get_code_state_or_return 0;
1396 if (_db_keyword_(cs, cs->u_keyword, 0))
1426 void _db_doprnt_(
const char *format,...)
1432 get_code_state_or_return;
1438 va_start(args,format);
1439 read_lock_stack(cs);
1443 pthread_mutex_lock(&THR_LOCK_dbug);
1444 DoPrefix(cs, cs->u_line);
1446 Indent(cs, cs->level + 1);
1448 (
void) fprintf(cs->stack->out_file,
"%s: ", cs->func);
1449 (void) fprintf(cs->stack->out_file,
"%s: ", cs->u_keyword);
1450 DbugVfprintf(cs->stack->out_file, format, args);
1463 static void DbugVfprintf(FILE *stream,
const char* format, va_list args)
1466 (void) my_vsnprintf(cvtbuf,
sizeof(cvtbuf), format, args);
1467 (void) fprintf(stream,
"%s\n", cvtbuf);
1489 void _db_dump_(uint _line_,
const char *keyword,
1490 const unsigned char *memory,
size_t length)
1494 get_code_state_or_return;
1500 read_lock_stack(cs);
1502 if (_db_keyword_(cs, keyword, 0))
1505 pthread_mutex_lock(&THR_LOCK_dbug);
1506 DoPrefix(cs, _line_);
1509 Indent(cs, cs->level + 1);
1510 pos= MY_MIN(MY_MAX(cs->level-cs->stack->sub_level,0)*INDENT,80);
1514 fprintf(cs->stack->out_file,
"%s: ", cs->func);
1516 (void) fprintf(cs->stack->out_file,
"%s: Memory: 0x%lx Bytes: (%ld)\n",
1517 keyword, (ulong) memory, (long) length);
1520 while (length-- > 0)
1522 uint tmp= *((
unsigned char*) memory++);
1525 fputc(
'\n',cs->stack->out_file);
1528 fputc(_dig_vec_upper[((tmp >> 4) & 15)], cs->stack->out_file);
1529 fputc(_dig_vec_upper[tmp & 15], cs->stack->out_file);
1530 fputc(
' ',cs->stack->out_file);
1532 (void) fputc(
'\n',cs->stack->out_file);
1564 static struct link *ListAddDel(
struct link *head,
const char *ctlp,
1565 const char *end,
int todo)
1574 while (++ctlp < end)
1578 while (ctlp < end && *ctlp !=
',')
1581 if (start[len-1] ==
'/')
1586 if (len == 0)
continue;
1587 for (cur=&head; *cur; cur=&((*cur)->next_link))
1589 if (!strncmp((*cur)->str, start, len))
1591 if ((*cur)->flags & todo)
1592 (*cur)->flags|= subdir;
1593 else if (todo == EXCLUDE)
1595 struct link *delme=*cur;
1596 *cur=(*cur)->next_link;
1597 free((
void*) delme);
1601 (*cur)->flags&=~(EXCLUDE | SUBDIR);
1602 (*cur)->flags|=INCLUDE | subdir;
1607 *cur= (
struct link *) DbugMalloc(
sizeof(
struct link)+len);
1608 memcpy((*cur)->str, start, len);
1610 (*cur)->flags=todo | subdir;
1611 (*cur)->next_link=0;
1639 static struct link *ListCopy(
struct link *orig)
1641 struct link *new_malloc;
1646 while (orig != NULL)
1648 len= strlen(orig->str);
1649 new_malloc= (
struct link *) DbugMalloc(
sizeof(
struct link)+len);
1650 memcpy(new_malloc->str, orig->str, len);
1651 new_malloc->str[len]= 0;
1652 new_malloc->flags=orig->flags;
1653 new_malloc->next_link= head;
1655 orig= orig->next_link;
1681 static int InList(
struct link *linkp,
const char *cp)
1685 for (result=MATCHED; linkp != NULL; linkp= linkp->next_link)
1687 if (!fnmatch(linkp->str, cp, 0))
1688 return linkp->flags;
1689 if (!(linkp->flags & EXCLUDE))
1691 if (linkp->flags & SUBDIR)
1704 static uint ListFlags(
struct link *linkp)
1707 for (f=0; linkp != NULL; linkp= linkp->next_link)
1737 memset(new_malloc, 0,
sizeof(
struct settings));
1738 new_malloc->next= cs->stack;
1739 cs->stack= new_malloc;
1761 if (!is_shared(state, keywords))
1762 FreeList(state->keywords);
1763 if (!is_shared(state, functions))
1764 FreeList(state->functions);
1765 if (!is_shared(state, processes))
1766 FreeList(state->processes);
1767 if (!is_shared(state, p_functions))
1768 FreeList(state->p_functions);
1770 if (!is_shared(state, out_file))
1771 DBUGCloseFile(cs, state->out_file);
1773 (
void) fflush(state->out_file);
1775 if (!is_shared(state, prof_file))
1776 DBUGCloseFile(cs, state->prof_file);
1778 (
void) fflush(state->prof_file);
1781 free((
void*) state);
1812 get_code_state_or_return;
1820 fprintf(stderr, ERR_MISSING_UNLOCK,
"(unknown)");
1822 pthread_mutex_unlock(&THR_LOCK_dbug);
1825 while ((discard= cs->stack))
1827 if (discard == &init_settings)
1829 cs->stack= discard->next;
1830 FreeState(cs, discard, 1);
1833 rw_wrlock(&THR_LOCK_init_settings);
1835 init_settings.flags= OPEN_APPEND;
1836 init_settings.out_file= stderr;
1837 init_settings.prof_file= stderr;
1838 init_settings.maxdepth= 0;
1839 init_settings.delay= 0;
1840 init_settings.sub_level= 0;
1841 init_settings.functions= 0;
1842 init_settings.p_functions= 0;
1843 init_settings.keywords= 0;
1844 init_settings.processes= 0;
1845 rw_unlock(&THR_LOCK_init_settings);
1846 FreeState(cs, &tmp, 0);
1865 if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
1866 InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE))
1867 switch(InList(cs->stack->functions, cs->func)) {
1868 case INCLUDE|SUBDIR:
return ENABLE_TRACE;
1869 case INCLUDE:
return DO_TRACE;
1870 case MATCHED|SUBDIR:
1871 case NOT_MATCHED|SUBDIR:
1872 case MATCHED:
return framep_trace_flag(cs, cs->framep) ?
1873 DO_TRACE : DONT_TRACE;
1875 case NOT_MATCHED:
return DONT_TRACE;
1876 case EXCLUDE|SUBDIR:
return DISABLE_TRACE;
1884 get_code_state_or_return NULL;
1885 return cs->stack->out_file;
1908 BOOLEAN _db_keyword_(
CODE_STATE *cs,
const char *keyword,
int strict)
1911 get_code_state_if_not_set_or_return FALSE;
1917 read_lock_stack(cs);
1919 strict=strict ? INCLUDE : INCLUDE|MATCHED;
1920 result= DoTrace(cs) & DO_TRACE &&
1921 InList(cs->stack->keywords, keyword) & strict;
1949 static void Indent(
CODE_STATE *cs,
int indent)
1953 indent= MY_MAX(indent-1-cs->stack->sub_level,0)*INDENT;
1954 for (count= 0; count < indent ; count++)
1956 if ((count % INDENT) == 0)
1957 fputc(
'|',cs->stack->out_file);
1959 fputc(
' ',cs->stack->out_file);
1981 static void FreeList(
struct link *linkp)
1983 REGISTER
struct link *old;
1985 while (linkp != NULL)
1988 linkp= linkp->next_link;
2013 static void DoPrefix(
CODE_STATE *cs, uint _line_)
2016 if (cs->stack->flags & PID_ON)
2018 (void) fprintf(cs->stack->out_file,
"%-7s: ", my_thread_name());
2020 if (cs->stack->flags & NUMBER_ON)
2021 (void) fprintf(cs->stack->out_file,
"%5d: ", cs->lineno);
2022 if (cs->stack->flags & TIMESTAMP_ON)
2028 GetLocalTime(&loc_t);
2029 (void) fprintf (cs->stack->out_file,
2031 "%02d:%02d:%02d.%06d ",
2033 loc_t.wHour, loc_t.wMinute, loc_t.wSecond, loc_t.wMilliseconds);
2037 if (gettimeofday(&tv, NULL) != -1)
2039 if ((tm_p= localtime((
const time_t *)&tv.tv_sec)))
2041 (void) fprintf (cs->stack->out_file,
2043 "%02d:%02d:%02d.%06d ",
2045 tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
2046 (
int) (tv.tv_usec));
2051 if (cs->stack->flags & PROCESS_ON)
2052 (void) fprintf(cs->stack->out_file,
"%s: ", cs->process);
2053 if (cs->stack->flags & FILE_ON)
2054 (void) fprintf(cs->stack->out_file,
"%14s: ", BaseName(cs->file));
2055 if (cs->stack->flags & LINE_ON)
2056 (void) fprintf(cs->stack->out_file,
"%5d: ", _line_);
2057 if (cs->stack->flags & DEPTH_ON)
2058 (void) fprintf(cs->stack->out_file,
"%4d: ", cs->level);
2080 const char *name,
const char *end,
int append)
2088 size_t len=end-
name;
2089 memcpy(cs->stack->name, name, len);
2090 cs->stack->name[len]=0;
2093 strmov(cs->stack->name,name);
2094 name=cs->stack->name;
2095 if (strcmp(name,
"-") == 0)
2097 cs->stack->out_file= stdout;
2098 cs->stack->flags |= FLUSH_ON_WRITE;
2099 cs->stack->name[0]=0;
2103 if (!Writable(name))
2105 (void) fprintf(stderr, ERR_OPEN, cs->process, name);
2111 if (!(fp= fopen(name, append ?
"a+" :
"w")))
2113 (void) fprintf(stderr, ERR_OPEN, cs->process, name);
2119 cs->stack->out_file= fp;
2143 static void DBUGCloseFile(
CODE_STATE *cs, FILE *fp)
2145 if (fp != NULL && fp != stderr && fp != stdout && fclose(fp) == EOF)
2147 pthread_mutex_lock(&THR_LOCK_dbug);
2148 (void) fprintf(cs->stack->out_file, ERR_CLOSE, cs->process);
2174 static void DbugExit(
const char *why)
2177 (void) fprintf(stderr, ERR_ABORT, cs ? cs->process :
"(null)", why);
2178 (void) fflush(stderr);
2204 static char *DbugMalloc(
size_t size)
2206 register char *new_malloc;
2208 if (!(new_malloc= (
char*) malloc(size)))
2209 DbugExit(
"out of memory");
2218 static const char *DbugStrTok(
const char *s)
2220 while (s[0] && (s[0] !=
':' ||
2221 (s[1] ==
'\\' || s[1] ==
'/' || (s[1] ==
':' && s++))))
2245 static const char *BaseName(
const char *pathname)
2247 register const char *base;
2249 base= strrchr(pathname, FN_LIBCHAR);
2250 if (base++ == NullS)
2282 static BOOLEAN Writable(
const char *pathname)
2284 REGISTER BOOLEAN granted;
2285 REGISTER
char *lastslash;
2288 if (EXISTS(pathname))
2290 if (WRITABLE(pathname))
2295 lastslash= strrchr(pathname,
'/');
2296 if (lastslash != NULL)
2300 if (WRITABLE(pathname))
2302 if (lastslash != NULL)
2329 EXPORT
void _db_setjmp_()
2332 get_code_state_or_return;
2334 cs->jmplevel= cs->level;
2335 cs->jmpfunc= cs->func;
2336 cs->jmpfile= cs->file;
2356 EXPORT
void _db_longjmp_()
2359 get_code_state_or_return;
2361 cs->level= cs->jmplevel;
2363 cs->func= cs->jmpfunc;
2365 cs->file= cs->jmpfile;
2395 static void perror(s)
2398 if (s && *s !=
'\0')
2399 (void) fprintf(stderr,
"%s: ", s);
2400 (void) fprintf(stderr,
"<unknown system error>\n");
2411 if (cs->stack->flags & FLUSH_ON_WRITE)
2413 (void) fflush(cs->stack->out_file);
2414 if (cs->stack->delay)
2415 (void) Delay(cs->stack->delay);
2418 pthread_mutex_unlock(&THR_LOCK_dbug);
2427 get_code_state_or_return;
2428 (void) fflush(cs->stack->out_file);
2435 extern void __gcov_flush();
2438 void _db_flush_gcov_()
2442 pthread_mutex_lock(&THR_LOCK_gcov);
2444 pthread_mutex_unlock(&THR_LOCK_gcov);
2452 sigfillset(&new_mask);
2455 fprintf(stderr,
"Flushing gcov data\n");
2460 fprintf(stderr,
"SIGKILL myself\n");
2463 retval=
kill(getpid(), SIGKILL);
2464 assert(retval == 0);
2465 retval= sigsuspend(&new_mask);
2466 fprintf(stderr,
"sigsuspend returned %d errno %d \n", retval, errno);
2472 void _db_lock_file_()
2475 get_code_state_or_return;
2476 pthread_mutex_lock(&THR_LOCK_dbug);
2480 void _db_unlock_file_()
2483 get_code_state_or_return;
2485 pthread_mutex_unlock(&THR_LOCK_dbug);
2488 const char* _db_get_func_(
void)
2491 get_code_state_or_return NULL;
2506 int i_am_a_dummy_function() {