trace.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 460 行
C
460 行
/* ctrace - C program debugging tool * * trace code generation routines * */#ifndef lintstatic char *sccsid = "@(#)trace.c 4.1 (ULTRIX) 7/17/90";#endif lint/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * * Modification History: * * */#include "global.h"#include <ctype.h>#define max(X, Y) (((int) X > (int) Y) ? X : Y)/* boolean fields in the marked array */#define VAR_START 1#define VAR_END 2#define EXP_START 4#define EXP_END 8static enum bool too_many_vars = no; /* too many variables to trace */static int marked[STMTMAX];static int vtrace_count = 0;struct text { int start, end;};static struct { struct text var; struct text exp; enum trace_type ttype; /* old C compiler does not allow structure member names to be the same */} vtrace[TRACEMAX];/* output the preprocessor statement */putpp(){ puttext(yyleng); /* add a #line statement surrounded by newlines so the next trace code is put on a new line */ printf("\n#line %d \"%s\"\n", yylineno, filename);}/* output the statement text as is */puttext(end)register int end;{ register int i; char *strcpy(); if (end >= yyleng) { /* a #if in dcl init list can make end > yyleng */ fputs(yytext, stdout); /* cannot use puts because it adds a newline */ yyleng = token_start = 0; } else { for (i = 0; i < end; ++i) putchar(yytext[i]); strcpy(yytext, yytext + end); yyleng = token_start = yyleng - end; } vtrace_count = 0; /* declarations can contain expressions */}/* cleanup after tracing a statement */reset(){ vtrace_count = yyleng = token_start = 0; /* warn of too many variables to trace in this statement */ if (too_many_vars) { warning("some variables are not traced in this statement"); too_many_vars = no; } /* warn of a statement that was too long to fit in the buffer */ if (too_long) { warning("statement too long to trace"); puttext(yyleng); too_long = no; }}/* functions to maintain the variable trace list */add_fcn(sym, exp_start, exp_end, type)struct symbol_struct sym;int exp_start, exp_end;enum trace_type type;{ register int i; /* see if this function is being traced */ if (!trace) return; /* prevent unnecessary "too many vars" messages */ /* see if the variable is already being traced */ for (i = vtrace_count - 1; i >= 0; --i) if (vtrace[i].exp.start == sym.start && vtrace[i].exp.end == sym.end) { break; } /* if not, use the next trace element */ if (i < 0) if (vtrace_count < tracemax) i = vtrace_count++; else { too_many_vars = yes; return; } /* save the trace information */ vtrace[i].var.start = sym.start; vtrace[i].var.end = sym.end; vtrace[i].exp.start = exp_start; vtrace[i].exp.end = exp_end; vtrace[i].ttype = type;}expand_fcn(sym, new_start, new_end)struct symbol_struct sym;int new_start, new_end;{ register int i; for (i = vtrace_count - 1; i >= 0; --i) if (vtrace[i].exp.start == sym.start && vtrace[i].exp.end == sym.end) { /* don't expand ++i to *++i */ if (sym.type != side_effect) { vtrace[i].exp.start = vtrace[i].var.start = new_start; vtrace[i].exp.end = vtrace[i].var.end = new_end; } break; }}rm_trace(sym)struct symbol_struct sym;{ register int i; for (i = vtrace_count - 1; i >= 0; --i) if (vtrace[i].exp.start == sym.start && vtrace[i].exp.end == sym.end) { --vtrace_count; /* eliminate the hole */ for ( ; i < vtrace_count; ++i) vtrace[i] = vtrace[i + 1]; break; }}rm_all_trace(sym)struct symbol_struct sym;{ register int i, j; for (i = vtrace_count - 1; i >= 0; --i) { if (vtrace[i].exp.start >= sym.start && vtrace[i].exp.start <= sym.end) { --vtrace_count; /* eliminate the hole */ for (j = i; j < vtrace_count; ++j) vtrace[j] = vtrace[j + 1]; } }}/* functions to trace the variables in a statement */tr_vars(start, end)int start;register int end; /* register variables are in order of use */{ register int i, j; enum bool simple_trace(); /* don't trace a statement that was too long to fit in the buffer */ if (too_long) { return; } /* mark the significant characters */ for (i = start; i < end; ++i) marked[i] = 0; for (i = 0; i < vtrace_count; ++i) { marked[vtrace[i].exp.start] |= EXP_START; marked[vtrace[i].exp.end] |= EXP_END; marked[vtrace[i].var.end] |= VAR_END; } /* for each character in the statement */ for (i = start; i < end; ++i) { if (marked[i] & EXP_END) /* check for the end of a traced expression */ for (j = 0; j < vtrace_count; ++j) if (vtrace[j].exp.end == i) { if (!simple_trace(j)) { printf(", "); dump_code(j); transvar(vtrace[j].var); } printf("), "); if (vtrace[j].ttype == strres) printf("_ct"); else transvar(vtrace[j].var); /* check for a postfix ++/-- operator */ if (vtrace[j].ttype == postfix) { if (yytext[vtrace[j].exp.end - 1] == '+') putchar('-'); else putchar('+'); putchar('1'); } putchar(')'); } if (marked[i] & EXP_START) /* check for the start of a traced expression */ for (j = 0; j < vtrace_count; ++j) if (vtrace[j].exp.start == i) { putchar('('); if (simple_trace(j)) dump_code(j); else if (vtrace[j].ttype == strres) printf("_ct = "); } /* output this character */ putchar(yytext[i]); }}/* check for a simple variable trace */static enum boolsimple_trace(j)register int j;{ register int k; if (vtrace[j].exp.start == vtrace[j].var.start && vtrace[j].exp.end == vtrace[j].var.end) { for (k = 0; k < vtrace_count; ++k) if (k != j) { /* if var is not this var */ if (vtrace[k].exp.start >= vtrace[j].var.start && vtrace[k].exp.end <= vtrace[j].var.end) break; /* this var has an embedded var */ if (vtrace[k].exp.start == vtrace[j].var.start || vtrace[k].exp.end == vtrace[j].var.end) break; /* this var is part of a larger var */ } if (k == vtrace_count) return(yes); } return(no);}/* dump routine call */staticdump_code(j)register int j;{ register int k; register char c; if (vtrace[j].ttype == string || vtrace[j].ttype == strres) printf("s_ct_(\""); else /* unknown type */ printf("u_ct_(\""); for (k = 0; (c = indentation[k]) != '\0'; ++k) transchar(c); printf("/* "); putvar(vtrace[j].var); printf("\","); /* size of variable code */ if (vtrace[j].ttype != string && vtrace[j].ttype != strres) { printf("sizeof("); transvar(vtrace[j].var); printf("),"); }}/* output the variable's name */staticputvar(var)struct text var;{ register int i; for (i = var.start; i < var.end; ++i) transchar(yytext[i]);}/* translate sub-exps containing '=', '++', and '--' ops into repeatable exps */statictransvar(var)struct text var;{ register int i, j; /* don't check the first character for start of an expression */ putchar(yytext[var.start]); for (i = var.start + 1; i < var.end; ++i) { if (marked[i] & VAR_END) /* check for the end of a traced variable */ for (j = 0; j < vtrace_count; ++j) if (vtrace[j].var.end == i) { /* transform a postfix ++/-- operator into -/+ 1 */ if (vtrace[j].ttype == postfix) { if (yytext[vtrace[j].exp.end - 1] == '+') putchar('-'); else putchar('+'); printf("1)"); /* skip the postfix operator */ i = max(i, vtrace[j].exp.end - 1); goto skip; } /* skip the rest of a assignment expression */ if (vtrace[j].ttype == assign) { i = max(i, vtrace[j].exp.end - 1); goto skip; } } if (marked[i] & EXP_START) /* check for the start of a traced expression */ for (j = 0; j < vtrace_count; ++j) if (vtrace[j].exp.start == i) { /* insert a '(' in front of a postfix ++/-- expression */ if (vtrace[j].ttype == postfix) putchar('('); /* skip a prefix ++/-- operator */ if (vtrace[j].ttype == prefix) { i = max(i, vtrace[j].var.start - 1); goto skip; } } /* output this character */ putchar(yytext[i]);skip: ; }}/* trace the statement text */tr_stmt(lineno, stmt, putsemicolon)int lineno;char *stmt;enum bool putsemicolon;{ register int c, i; /* see if this function is being traced and */ /* don't trace a statement that was too long to fit in the buffer */ if (!trace || too_long) { return; } /* output the trace function call */ printf("t_ct_(\""); /* if the line number field should be blank */ if (lineno == NO_LINENO) { /* print a blank line number */ printf("\\n "); /* copy the leading blanks and tabs in the loop statement */ if (stmt[0] == '\n') /* skip a leading newline */ i = 1; else i = 0; for ( ; isspace(c = stmt[i]); ++i) transchar(c); i = 0; /* there isn't a newline in the statement text */ } /* if the statement starts on a new line */ else if (stmt[0] == '\n') { /* adjust the line number for any embedded new lines */ for (i = 1; (c = stmt[i]) != '\0'; ++i) if (c == '\n') --lineno; /* print the line number */ printf("\\n%3d ", lineno); i = 1; /* skip the newline in the statement text */ } else i = 0; /* convert special characters in the statement text */ for ( ; (c = stmt[i]) != '\0'; ++i) transchar(c); /* terminate the trace function call */ printf("\")"); /* see if this is to be a statement */ if (putsemicolon) printf("; ");}/* translate a character for a string constant */statictranschar(c)register int c;{ switch (c) { case '"': printf("\\\""); break; case '\\': printf("\\\\"); break; case '\t': printf("\\t"); break; case '\n': printf("\\n"); break; default: putchar(c); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?