📄 dbug.c
字号:
* * Tests the string pointed to by "cp" to determine if it is in * the list pointed to by "linkp". Linkp points to the first * link in the list. If linkp is NULL then the string is treated * as if it is in the list (I.E all strings are in the null list). * This may seem rather strange at first but leads to the desired * operation if no list is given. The net effect is that all * strings will be accepted when there is no list, and when there * is a list, only those strings in the list will be accepted. * */static BOOLEAN InList (linkp, cp)struct link *linkp;char *cp;{ REGISTER struct link *scan; REGISTER BOOLEAN accept; if (linkp == NULL) { accept = TRUE; } else { accept = FALSE; for (scan = linkp; scan != NULL; scan = scan -> next_link) { if (STREQ (scan -> str, cp)) { accept = TRUE; break; } } } return (accept);}/* * FUNCTION * * PushState push current state onto stack and set up new one * * SYNOPSIS * * static VOID PushState () * * DESCRIPTION * * Pushes the current state on the state stack, and initializes * a new state. The only parameter inherited from the previous * state is the function nesting level. This action can be * inhibited if desired, via the "r" flag. * * The state stack is a linked list of states, with the new * state added at the head. This allows the stack to grow * to the limits of memory if necessary. * */static void PushState (){ REGISTER struct state *new; REGISTER CODE_STATE *state; if (!init_done) { init_dbug_state(); init_done=TRUE; } state=code_state(); new = (struct state *) DbugMalloc (sizeof (struct state)); new -> flags = 0; new -> delay = 0; new -> maxdepth = MAXDEPTH; new -> sub_level=0; new -> out_file = stderr; new -> prof_file = (FILE*) 0; new -> functions = NULL; new -> p_functions = NULL; new -> keywords = NULL; new -> processes = NULL; new -> next_state = stack; stack=new;}/* * FUNCTION * * DoTrace check to see if tracing is current enabled * * SYNOPSIS * * static BOOLEAN DoTrace (stack) * * 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. * */static BOOLEAN DoTrace (CODE_STATE *state){ reg2 BOOLEAN trace=FALSE; if (TRACING && state->level <= stack -> maxdepth && InList (stack -> functions, state->func) && InList (stack -> processes, _db_process_)) trace = TRUE; return (trace);}/* * FUNCTION * * DoProfile check to see if profiling is current enabled * * SYNOPSIS * * static BOOLEAN DoProfile () * * DESCRIPTION * * Checks to see if profiling is enabled based on whether the * user has specified profiling, the maximum trace depth has * not yet been reached, the current function is selected, * and the current process is selected. Returns TRUE if * profiling is enabled, FALSE otherwise. * */#ifndef THREADstatic BOOLEAN DoProfile (){ REGISTER BOOLEAN profile; CODE_STATE *state; state=code_state(); profile = FALSE; if (PROFILING && state->level <= stack -> maxdepth && InList (stack -> p_functions, state->func) && InList (stack -> processes, _db_process_)) profile = TRUE; return (profile);}#endif/* * FUNCTION * * _db_keyword_ test keyword for member of keyword list * * SYNOPSIS * * BOOLEAN _db_keyword_ (keyword) * char *keyword; * * DESCRIPTION * * Test a keyword to determine if it is in the currently active * keyword list. As with the function list, a keyword is accepted * if the list is null, otherwise it must match one of the list * members. When debugging is not on, no keywords are accepted. * After the maximum trace level is exceeded, no keywords are * accepted (this behavior subject to change). Additionally, * the current function and process must be accepted based on * their respective lists. * * Returns TRUE if keyword accepted, FALSE otherwise. * */BOOLEAN _db_keyword_ (keyword)char *keyword;{ REGISTER BOOLEAN accept; CODE_STATE *state; if (!init_done) _db_push_ (""); state=code_state(); accept = FALSE; if (DEBUGGING && state->level <= stack -> maxdepth && InList (stack -> functions, state->func) && InList (stack -> keywords, keyword) && InList (stack -> processes, _db_process_)) accept = TRUE; return (accept);}/* * FUNCTION * * Indent indent a line to the given indentation level * * SYNOPSIS * * static VOID Indent (indent) * int indent; * * DESCRIPTION * * Indent a line to the given level. Note that this is * a simple minded but portable implementation. * There are better ways. * * Also, the indent must be scaled by the compile time option * of character positions per nesting level. * */static void Indent (indent)int indent;{ REGISTER int count; indent= max(indent-1-stack->sub_level,0)*INDENT; for (count = 0; count < indent ; count++) { if ((count % INDENT) == 0) fputc('|',_db_fp_); else fputc(' ',_db_fp_); }}/* * FUNCTION * * FreeList free all memory associated with a linked list * * SYNOPSIS * * static VOID FreeList (linkp) * struct link *linkp; * * DESCRIPTION * * Given pointer to the head of a linked list, frees all * memory held by the list and the members of the list. * */static void FreeList (linkp)struct link *linkp;{ REGISTER struct link *old; while (linkp != NULL) { old = linkp; linkp = linkp -> next_link; if (old -> str != NULL) { free (old -> str); } free ((char *) old); }}/* * FUNCTION * * StrDup make a duplicate of a string in new memory * * SYNOPSIS * * static char *StrDup (my_string) * char *string; * * DESCRIPTION * * Given pointer to a string, allocates sufficient memory to make * a duplicate copy, and copies the string to the newly allocated * memory. Failure to allocated sufficient memory is immediately * fatal. * */static char *StrDup (str)const char *str;{ reg1 char *new; new = DbugMalloc ((int) strlen (str) + 1); (void) strcpy (new, str); return (new);}/* * FUNCTION * * DoPrefix print debugger line prefix prior to indentation * * SYNOPSIS * * static VOID DoPrefix (_line_) * int _line_; * * DESCRIPTION * * Print prefix common to all debugger output lines, prior to * doing indentation if necessary. Print such information as * current process name, current source file name and line number, * and current function nesting depth. * */static void DoPrefix (_line_)uint _line_;{ CODE_STATE *state; state=code_state(); state->lineno++; if (stack -> flags & PID_ON) {#ifdef THREAD (void) fprintf (_db_fp_, "%5lx: ", pthread_self_ptr());#else (void) fprintf (_db_fp_, "%5d: ", getpid ());#endif } if (stack -> flags & NUMBER_ON) { (void) fprintf (_db_fp_, "%5d: ", state->lineno); } if (stack -> flags & PROCESS_ON) { (void) fprintf (_db_fp_, "%s: ", _db_process_); } if (stack -> flags & FILE_ON) { (void) fprintf (_db_fp_, "%14s: ", BaseName(state->file)); } if (stack -> flags & LINE_ON) { (void) fprintf (_db_fp_, "%5d: ", _line_); } if (stack -> flags & DEPTH_ON) { (void) fprintf (_db_fp_, "%4d: ", state->level); }}/* * FUNCTION * * DBUGOpenFile open new output stream for debugger output * * SYNOPSIS * * static VOID DBUGOpenFile (name) * char *name; * * DESCRIPTION * * Given name of a new file (or "-" for stdout) opens the file * and sets the output stream to the new file. * */static void DBUGOpenFile (name)char *name;{ REGISTER FILE *fp; REGISTER BOOLEAN newfile; if (name != NULL) { strmov(stack->name,name); if (strcmp (name, "-") == 0) { _db_fp_ = stdout; stack -> out_file = _db_fp_; stack -> flags |= FLUSH_ON_WRITE; } else { if (!Writable(name)) { (void) fprintf (stderr, ERR_OPEN, _db_process_, name); perror (""); fflush(stderr); } else { newfile= !EXISTS (name); if (!(fp = fopen (name, "w"))) { (void) fprintf (stderr, ERR_OPEN, _db_process_, name); perror (""); fflush(stderr); } else { _db_fp_ = fp; stack -> out_file = fp; if (newfile) { ChangeOwner (name); } } } } }}/* * FUNCTION * * OpenProfile open new output stream for profiler output * * SYNOPSIS * * static FILE *OpenProfile (name) * char *name; * * DESCRIPTION * * Given name of a new file, opens the file * and sets the profiler output stream to the new file. * * It is currently unclear whether the prefered behavior is * to truncate any existing file, or simply append to it. * The latter behavior would be desirable for collecting * accumulated runtime history over a number of separate * runs. It might take some changes to the analyzer program * though, and the notes that Binayak sent with the profiling * diffs indicated that append was the normal mode, but this * does not appear to agree with the actual code. I haven't * investigated at this time [fnf; 24-Jul-87]. */#ifndef THREADstatic FILE *OpenProfile (name)char *name;{ REGISTER FILE *fp; REGISTER BOOLEAN newfile; fp=0; if (!Writable (name)) { (void) fprintf (_db_fp_, ERR_OPEN, _db_process_, name); perror (""); dbug_flush(); (void) Delay (stack -> delay); } else { newfile= !EXISTS (name); if (!(fp = fopen (name, "w"))) { (void) fprintf (_db_fp_, ERR_OPEN, _db_process_, name); perror (""); dbug_flush(); } else { _db_pfp_ = fp; stack -> prof_file = fp; if (newfile) { ChangeOwner (name); } } } return fp;}#endif/* * FUNCTION * * CloseFile close the debug output stream * * SYNOPSIS * * static VOID CloseFile (fp) * FILE *fp; * * DESCRIPTION * * Closes the debug output stream unless it is standard output * or standard error. * */static void CloseFile (fp)FILE *fp;{ if (fp != stderr && fp != stdout) { if (fclose (fp) == EOF) { pthread_mutex_lock(&THR_LOCK_dbug); (void) fprintf (_db_fp_, ERR_CLOSE, _db_process_); perror (""); dbug_flush(); } }}/* * FUNCTION * * DbugExit print error message and exit * * SYNOPSIS *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -