📄 dbug.c
字号:
_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 'A': case 'O': stack -> flags |= FLUSH_ON_WRITE; case 'a': case 'o': if (*scan++ == ',') { temp = ListParse (scan); DBUGOpenFile(temp -> str, (int) (scan[-2] == 'A' || scan[-2] == 'a')); FreeList (temp); } else { DBUGOpenFile ("-",0); } 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); if (!(stack->flags & DEBUG_ON)) _db_on_=0; } else { _db_on_=0; }}/* * 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_ (const char *_func_,const char *_file_,uint _line_,const char **_sfunc_,const char **_sfile_,uint *_slevel_,char ***_sframep_ __attribute__((unused))){ reg1 CODE_STATE *state; if (!_no_db_) { int save_errno=errno; if (!init_done) _db_push_ (_DBUG_START_CONDITION_); state=code_state(); *_sfunc_ = 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, (ulong) state->framep, stackused, state->func);#endif (void) fflush (_db_pfp_); }#endif if (DoTrace (state)) { if (!state->locked) pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix (_line_); Indent (state -> level); (void) fprintf (_db_fp_, ">%s\n", state->func); dbug_flush (state); /* 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 errno=save_errno; }}/* * 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_ (uint _line_,const char **_sfunc_,const char **_sfile_,uint *_slevel_){ CODE_STATE *state; if (!_no_db_) { int save_errno=errno; if (!init_done) _db_push_ (""); if (!(state=code_state())) return; /* Only happens at end of program */ if (stack->flags & (TRACE_ON | DEBUG_ON | PROFILE_ON)) { if (!state->locked) 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); } state->level = *_slevel_-1; state->func = *_sfunc_; state->file = *_sfile_;#ifndef THREAD if (state->framep != NULL) state->framep = (char **) *state->framep;#endif errno=save_errno; }}/* * 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_ (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)) { int save_errno=errno; if (!state->locked) 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(state); errno=save_errno; } 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_(uint _line_,const char *keyword,const char *memory,uint length){ int pos; char dbuff[90]; CODE_STATE *state; state=code_state(); if (_db_keyword_ ((char*) keyword)) { if (!state->locked) 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 { fprintf(_db_fp_, "%s: ", state->func); } sprintf(dbuff,"%s: Memory: %lx Bytes: (%d)\n", keyword,(ulong) memory, length); (void) fputs(dbuff,_db_fp_); pos=0; while (length-- > 0) { uint tmp= *((unsigned char*) memory++); if ((pos+=3) >= 80) { fputc('\n',_db_fp_); pos=3; } fputc(_dig_vec[((tmp >> 4) & 15)], _db_fp_); fputc(_dig_vec[tmp & 15], _db_fp_); fputc(' ',_db_fp_); } (void) fputc('\n',_db_fp_); dbug_flush(state); }}/* * 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 (char *ctlp){ REGISTER char *start; REGISTER struct link *new_malloc; REGISTER struct link *head; head = NULL; while (*ctlp != EOS) { start = ctlp; while (*ctlp != EOS && *ctlp != ',') { ctlp++; } if (*ctlp == ',') { *ctlp++ = EOS; } new_malloc = (struct link *) DbugMalloc (sizeof (struct link)); new_malloc -> str = StrDup (start); new_malloc -> next_link = head; head = new_malloc; } return (head);}/* * FUNCTION * * InList test a given string for member of a given list * * SYNOPSIS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -