📄 dbug.c
字号:
new_str = StrDup (control); PushState (); state=code_state(); scan = static_strtok (new_str, ':'); for (; scan != NULL; scan = static_strtok ((char *)NULL, ':')) { switch (*scan++) { case 'd': _db_on_ = TRUE; stack -> flags |= DEBUG_ON; if (*scan++ == ',') { stack -> keywords = ListParse (scan); } break; case 'D': stack -> delay = 0; if (*scan++ == ',') { temp = ListParse (scan); stack -> delay = DelayArg (atoi (temp -> str)); FreeList (temp); } break; case 'f': if (*scan++ == ',') { stack -> functions = ListParse (scan); } break; case 'F': stack -> flags |= FILE_ON; break; case 'i': stack -> flags |= PID_ON; break;#ifndef THREAD case 'g': _db_pon_ = TRUE; if (OpenProfile(PROF_FILE)) { stack -> flags |= PROFILE_ON; if (*scan++ == ',') stack -> p_functions = ListParse (scan); } break;#endif case 'L': stack -> flags |= LINE_ON; break; case 'n': stack -> flags |= DEPTH_ON; break; case 'N': stack -> flags |= NUMBER_ON; break; case 'O': stack -> flags |= FLUSH_ON_WRITE; case 'o': if (*scan++ == ',') { temp = ListParse (scan); DBUGOpenFile (temp -> str); FreeList (temp); } else { DBUGOpenFile ("-"); } break; case 'p': if (*scan++ == ',') { stack -> processes = ListParse (scan); } break; case 'P': stack -> flags |= PROCESS_ON; break; case 'r': stack->sub_level= state->level; break; case 't': stack -> flags |= TRACE_ON; if (*scan++ == ',') { temp = ListParse (scan); stack -> maxdepth = atoi (temp -> str); FreeList (temp); } break; case 'S': stack -> flags |= SANITY_CHECK_ON; break; } } free (new_str);}/* * FUNCTION * * _db_pop_ pop the debug stack * * DESCRIPTION * * Pops the debug stack, returning the debug state to its * condition prior to the most recent _db_push_ invocation. * Note that the pop will fail if it would remove the last * valid state from the stack. This prevents user errors * in the push/pop sequence from screwing up the debugger. * Maybe there should be some kind of warning printed if the * user tries to pop too many states. * */void _db_pop_ (){ reg1 struct state *discard; discard = stack; if (discard != NULL && discard -> next_state != NULL) { stack = discard -> next_state; _db_fp_ = stack -> out_file; _db_pfp_ = stack -> prof_file; if (discard -> keywords != NULL) { FreeList (discard -> keywords); } if (discard -> functions != NULL) { FreeList (discard -> functions); } if (discard -> processes != NULL) { FreeList (discard -> processes); } if (discard -> p_functions != NULL) { FreeList (discard -> p_functions); } CloseFile (discard -> out_file); if (discard -> prof_file) CloseFile (discard -> prof_file); free ((char *) discard); }}/* * FUNCTION * * _db_enter_ process entry point to user function * * SYNOPSIS * * VOID _db_enter_ (_func_, _file_, _line_, * _sfunc_, _sfile_, _slevel_, _sframep_) * 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 * * DESCRIPTION * * Called at the beginning of each user function to tell * the debugger that a new function has been entered. * Note that the pointers to the previous user function * name and previous user file name are stored on the * caller's stack (this is why the ENTER macro must be * the first "executable" code in a function, since it * allocates these storage locations). The previous nesting * level is also stored on the callers stack for internal * self consistency checks. * * Also prints a trace line if tracing is enabled and * increments the current function nesting depth. * * Note that this mechanism allows the debugger to know * what the current user function is at all times, without * maintaining an internal stack for the function names. * */void _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_, _sframep_)const char *_func_;const char *_file_;uint _line_;char **_sfunc_;char **_sfile_;uint *_slevel_;char ***_sframep_ __attribute__((unused));{ reg1 CODE_STATE *state; if (!_no_db_) { if (!init_done) _db_push_ (_DBUG_START_CONDITION_); state=code_state(); *_sfunc_ = (char*) state->func; *_sfile_ = state->file; state->func =(char*) _func_; state->file = (char*) _file_; /* BaseName takes time !! */ *_slevel_ = ++state->level;#ifndef THREAD *_sframep_ = state->framep; state->framep = (char **) _sframep_; if (DoProfile ()) { long stackused; if (*state->framep == NULL) { stackused = 0; } else { stackused = ((long)(*state->framep)) - ((long)(state->framep)); stackused = stackused > 0 ? stackused : -stackused; } (void) fprintf (_db_pfp_, PROF_EFMT , Clock (), state->func);#ifdef AUTOS_REVERSE (void) fprintf (_db_pfp_, PROF_SFMT, state->framep, stackused, *_sfunc_);#else (void) fprintf (_db_pfp_, PROF_SFMT, state->framep, stackused, state->func);#endif (void) fflush (_db_pfp_); }#endif if (DoTrace (state)) { pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix (_line_); Indent (state -> level); (void) fprintf (_db_fp_, ">%s\n", state->func); dbug_flush (); /* This does a unlock */ }#ifdef SAFEMALLOC if (stack -> flags & SANITY_CHECK_ON) if (_sanity(_file_,_line_)) /* Check of safemalloc */ stack -> flags &= ~SANITY_CHECK_ON;#endif }}/* * FUNCTION * * _db_return_ process exit from user function * * SYNOPSIS * * VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_) * 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 * * DESCRIPTION * * Called just before user function executes an explicit or implicit * return. Prints a trace line if trace is enabled, decrements * the current nesting level, and restores the current function and * file names from the defunct function's stack. * */void _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)uint _line_;char **_sfunc_;char **_sfile_;uint *_slevel_;{ CODE_STATE *state; if (!_no_db_) { if (!init_done) _db_push_ (""); state=code_state(); if (stack->flags & (TRACE_ON | DEBUG_ON | PROFILE_ON)) { pthread_mutex_lock(&THR_LOCK_dbug); if (state->level != (int) *_slevel_) (void) fprintf (_db_fp_, ERR_MISSING_RETURN, _db_process_, state->func); else {#ifdef SAFEMALLOC if (stack -> flags & SANITY_CHECK_ON) if (_sanity(*_sfile_,_line_)) stack->flags &= ~SANITY_CHECK_ON;#endif#ifndef THREAD if (DoProfile ()) (void) fprintf (_db_pfp_, PROF_XFMT, Clock(), state->func);#endif if (DoTrace (state)) { DoPrefix (_line_); Indent (state->level); (void) fprintf (_db_fp_, "<%s\n", state->func); } } dbug_flush(); } state->level = *_slevel_-1; state->func = *_sfunc_; state->file = *_sfile_;#ifndef THREAD if (state->framep != NULL) state->framep = (char **) *state->framep;#endif }}/* * FUNCTION * * _db_pargs_ log arguments for subsequent use by _db_doprnt_() * * SYNOPSIS * * VOID _db_pargs_ (_line_, keyword) * int _line_; * char *keyword; * * DESCRIPTION * * The new universal printing macro DBUG_PRINT, which replaces * all forms of the DBUG_N macros, needs two calls to runtime * support routines. The first, this function, remembers arguments * that are used by the subsequent call to _db_doprnt_(). * */void _db_pargs_ (_line_, keyword)uint _line_;const char *keyword;{ CODE_STATE *state=code_state(); state->u_line = _line_; state->u_keyword = (char*) keyword;}/* * FUNCTION * * _db_doprnt_ handle print of debug lines * * SYNOPSIS * * VOID _db_doprnt_ (format, va_alist) * char *format; * va_dcl; * * DESCRIPTION * * When invoked via one of the DBUG macros, tests the current keyword * set by calling _db_pargs_() to see if that macro has been selected * for processing via the debugger control string, and if so, handles * printing of the arguments via the format string. The line number * of the DBUG macro in the source is found in u_line. * * Note that the format string SHOULD NOT include a terminating * newline, this is supplied automatically. * */#include <stdarg.h>void _db_doprnt_ (const char *format,...){ va_list args; CODE_STATE *state; state=code_state(); va_start(args,format); if (_db_keyword_ (state->u_keyword)) { pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix (state->u_line); if (TRACING) { Indent (state->level + 1); } else { (void) fprintf (_db_fp_, "%s: ", state->func); } (void) fprintf (_db_fp_, "%s: ", state->u_keyword); (void) vfprintf (_db_fp_, format, args); va_end(args); (void) fputc('\n',_db_fp_); dbug_flush(); } va_end(args);}/* * FUNCTION * * _db_dump_ dump a string until '\0' is found * * SYNOPSIS * * void _db_dump_ (_line_,keyword,memory,length) * int _line_; current source line number * char *keyword; * char *memory; Memory to print * int length; Bytes to print * * DESCRIPTION * Dump N characters in a binary array. * Is used to examine corrputed memory or arrays. */void _db_dump_(_line_,keyword,memory,length)uint _line_,length;const char *keyword;const char *memory;{ int pos; char dbuff[90],*strpos; CODE_STATE *state; state=code_state(); if (_db_keyword_ ((char*) keyword)) { pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix (_line_); if (TRACING) { Indent (state->level + 1); pos= min(max(state->level-stack->sub_level,0)*INDENT,80); } else { pos=fprintf (_db_fp_, "%s: ", state->func); } sprintf(dbuff,"%s: Memory: %lx Bytes: ",keyword,memory); pos+= strlen(dbuff); (void) fputs(dbuff,_db_fp_); while (length-- > 0) { strpos=int2str((long) *((unsigned char*) memory++),dbuff,10); *strpos++=' '; *strpos=0; if ((pos+= (int) (strpos-dbuff)) >= 80) { pos=(int) (strpos-dbuff); fputc('\n',_db_fp_); } (void) fputs(dbuff,_db_fp_); } (void) fputc('\n',_db_fp_); dbug_flush(); }}/* * FUNCTION * * ListParse parse list of modifiers in debug control string * * SYNOPSIS * * static struct link *ListParse (ctlp) * char *ctlp; * * DESCRIPTION * * Given pointer to a comma separated list of strings in "cltp", * parses the list, building a list and returning a pointer to it. * The original comma separated list is destroyed in the process of * building the linked list, thus it had better be a duplicate * if it is important. * * Note that since each link is added at the head of the list, * the final list will be in "reverse order", which is not * significant for our usage here. * */static struct link *ListParse (ctlp)char *ctlp;{ REGISTER char *start; REGISTER struct link *new; REGISTER struct link *head; head = NULL; while (*ctlp != EOS) { start = ctlp; while (*ctlp != EOS && *ctlp != ',') { ctlp++; } if (*ctlp == ',') { *ctlp++ = EOS; } new = (struct link *) DbugMalloc (sizeof (struct link)); new -> str = StrDup (start); new -> next_link = head; head = new; } return (head);}/* * FUNCTION * * InList test a given string for member of a given list * * SYNOPSIS * * static BOOLEAN InList (linkp, cp) * struct link *linkp; * char *cp; * * DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -