|
|
1.1 ! root 1: #include "symbol.h" ! 2: #include "srctext.pri" ! 3: #include "core.pub" ! 4: #include "symtab.pub" ! 5: #include "process.pub" ! 6: #include "bpts.pub" ! 7: #include "expr.pub" ! 8: #include "format.pub" ! 9: #include "frame.pri" ! 10: #include <CC/sys/types.h> ! 11: #include <CC/sys/stat.h> ! 12: #include <sys/dir.h> ! 13: SRCFILE("srctext.c") ! 14: ! 15: SrcText::SrcText(Source *s, long c) ! 16: { ! 17: trace( "%d.SrcText(%d,%d)", this, s, c ); VOK; ! 18: source = s; ! 19: compiletime = c; ! 20: path = source->_text; ! 21: prevpat = "<no pattern>"; ! 22: } ! 23: ! 24: Core *SrcText::core() { return source->symtab->core(); } ! 25: ! 26: Process *SrcText::process() { return core()->process(); } ! 27: ! 28: void DoNothing(){} ! 29: ! 30: void SrcText::promote() ! 31: { ! 32: Menu m; ! 33: trace( "%d.promote()", this ); VOK; ! 34: if( promoted ){ ! 35: process()->openglobals(); ! 36: return; ! 37: } ! 38: Var *v; ! 39: BlkVars bv(source->blk); ! 40: int limit = 25; ! 41: while( limit-->0 && (v = bv.gen()) ) ! 42: m.sort(sf("%s\240Sta",v->_text), (Action)&Frame::pickvar, (long)v); ! 43: char *t = sf("\276 %s", basename(source->text())); ! 44: m.first( t, (Action)&DoNothing ); ! 45: process()->openglobals(&m); ! 46: promoted = 1; ! 47: } ! 48: ! 49: char *SrcText::read(Menu &m) ! 50: { ! 51: Func *fun; ! 52: register int l; ! 53: struct stat fdstat; ! 54: register char *p; ! 55: Menu sub; ! 56: ! 57: trace("%d.read(%d) path=%s", this, m, path); OK("SrcText::read"); ! 58: if( edge ) return 0; ! 59: if( fstat(fd, &fdstat) ) ! 60: return SysErr("cannot stat"); ! 61: if( fdstat.st_size == 0 ) ! 62: return "null file"; ! 63: if( !compiletime ) compiletime = source->symtab->modtime(); ! 64: if( modified(fd) > compiletime && !warned ){ ! 65: ++warned; ! 66: trace( "%d>%d", modified(fd), compiletime ); ! 67: return sf("modified since compilation at %24s",ctime(&compiletime)); ! 68: } ! 69: warned = 0; ! 70: fun = (Func*)source->child; ! 71: long n = 0; ! 72: while( fun ){ ! 73: Bls toc; ! 74: if( lastline < fun->lines.hi ) lastline = fun->lines.hi; ! 75: if( strlen(fun->text())<=32 && fun->lines.lo>0 ){ ! 76: toc.af( "%s\256%d", fun->text(), fun->lines.lo ); ! 77: sub.sort( toc.text, (Action) &SrcText::select, fun->lines.lo ); ! 78: ++n; ! 79: } ! 80: fun = (Func*)fun->rsib; ! 81: } ! 82: if( lastline <= 0 ) ! 83: return "not referenced by symbol table (cc -g?)"; ! 84: m.last(sub.index(n>4 ? "index by fcn " : 0)); ! 85: edge = new char*[lastline+1]; ! 86: body = new char[fdstat.st_size]; ! 87: if( !ReadOK( fd, body, fdstat.st_size ) ) ! 88: return SysErr( "read error" ); ! 89: l = 1; ! 90: p = body; ! 91: while( l <= lastline && *p ){ /* should check p stays in body */ ! 92: edge[l++] = p; ! 93: while( *p && *p != '\n' ) ++p; ! 94: *p++ = '\0'; ! 95: trace( "%d %s", l-1, edge[l-1] ); ! 96: } ! 97: pad->lines(l-1); ! 98: return 0; ! 99: } ! 100: ! 101: void SrcText::open() ! 102: { ! 103: Menu m; ! 104: char *error = 0; ! 105: struct stat stbuf; ! 106: ! 107: trace( "%d.open() path=%s", this, path ); VOK; ! 108: if( pad && edge ){ ! 109: pad->makecurrent(); ! 110: return; ! 111: } ! 112: if( !pad ) pad = new Pad( (PadRcv*) this ); ! 113: pad->options( TRUNCATE ); ! 114: pad->banner( "Source Text: %s", process()->prefix(path) ); ! 115: pad->name( basename(path) ); ! 116: pad->tabs(4); ! 117: pad->error(0); ! 118: if( !edge ){ ! 119: pad->menu( ZIndex ); ! 120: pad->lines(0); ! 121: if( (fd = ::open(process()->prefix(path),0)) < 0 ) ! 122: error= SysErr( "cannot open:" ); ! 123: if( !error ){ ! 124: if( ::fstat( fd, &stbuf ) ) ! 125: error = "cannot stat"; ! 126: else if( (stbuf.st_mode&S_IFMT) == S_IFDIR ) ! 127: error = "is a directory"; ! 128: } ! 129: if( !error ) error = read(m); ! 130: if( fd >= 0 ) close(fd); ! 131: if( !error ){ ! 132: if( core()->online() ){ ! 133: Action a = (Action)&SrcText::stmtstep; ! 134: Menu sub; ! 135: for( long i = 5; i <= 50; i += 5 ) ! 136: sub.last(sf("step %3d stmts",i), a, i); ! 137: sub.last("step 100 stmts", a, 100); ! 138: sub.last("step 500 stmts", a, 500); ! 139: m.first("step into fcn", (Action)&SrcText::stepinto ); ! 140: m.first(sub.index("step >4 stmts")); ! 141: m.first("step 4 stmts ", a, 4); ! 142: m.first("step 3 stmts ", a, 3); ! 143: m.first("step 2 stmts ", a, 2); ! 144: m.first("step 1 stmt ", a, 1); ! 145: } ! 146: m.first( "current stmt", (Action)&SrcText::currentstmt ); ! 147: if( core()->online() ) ! 148: m.first( "run", (Action)&SrcText::go ); ! 149: } ! 150: } ! 151: m.first( sf( "reopen %s",basename(path)) ,(Action)&SrcText::reopen ); ! 152: pad->menu(m); ! 153: pad->error( error ); ! 154: pad->makecurrent(); ! 155: } ! 156: ! 157: void SrcText::reopen() ! 158: { ! 159: trace( "%d.reopen()", this ); VOK; ! 160: free(); ! 161: open(); ! 162: } ! 163: ! 164: void SrcText::free() ! 165: { ! 166: trace( "%d.free()", this ); VOK; ! 167: if( edge ) { delete edge; edge = 0; } ! 168: if( body ) { delete body; body = 0; } ! 169: } ! 170: ! 171: void SrcText::userclose() ! 172: { ! 173: trace( "%d.userclose()", this ); VOK; ! 174: free(); ! 175: if( pad ){ ! 176: delete pad; ! 177: pad = 0; ! 178: } ! 179: } ! 180: ! 181: #define NONBPT 0 ! 182: #define SETBPT 1 ! 183: #define SETCLR 2 ! 184: #define CLRBPT 3 ! 185: ! 186: void SrcText::linereq(long i, Attrib a) /* profile hot spot ... */ ! 187: { ! 188: Stmt *stmt = 0; ! 189: Bls t; ! 190: static Index *ix; ! 191: int bpty; ! 192: ! 193: trace( "%d.linereq(%d,0x%X)", this, i, a ); VOK; ! 194: if (!ix) { ! 195: ix = new Index[4]; ! 196: for(int i = 0; i < 4; i++) ! 197: ix[i] = Index(0,0); ! 198: } ! 199: if( ix[0].null() ){ /* ... that's better */ ! 200: Menu m[4]; ! 201: for( bpty = NONBPT; bpty <= CLRBPT; ++bpty ){ ! 202: m[bpty].last( "assembler", (Action) &Stmt::asmblr ); ! 203: m[bpty].last( "open frame", (Action) &Stmt::openframe ); ! 204: } ! 205: m[SETBPT].first( "cond bpt", (Action) &Stmt::conditional, (long)Q_BPT); ! 206: m[SETBPT].first( "trace on", (Action) &Stmt::settrace ); ! 207: m[SETBPT].first( "set bpt", (Action) &Stmt::dobpt, 1 ); ! 208: ! 209: m[SETCLR].first( "trace on", (Action) &Stmt::settrace ); ! 210: m[SETCLR].first( "set bpt", (Action) &Stmt::dobpt, 1 ); ! 211: m[SETCLR].first( "clear bpt", (Action) &Stmt::dobpt, 0 ); ! 212: ! 213: m[CLRBPT].first( "clear bpt", (Action) &Stmt::dobpt, 0 ); ! 214: for( bpty = NONBPT; bpty <= CLRBPT; ++bpty ) ! 215: ix[bpty] = m[bpty].index(); ! 216: } ! 217: if( !edge ) open(); ! 218: if( !edge ) return; ! 219: if( i<1 || i>lastline ) return; ! 220: bpty = NONBPT; ! 221: stmt = source->stmtafter(i); ! 222: if( stmt && core()->online() ){ ! 223: if( !process()->bpts()->isbpt(stmt) ){ ! 224: bpty = SETBPT; ! 225: if( stmt->lineno==i && stmt->condition==Q_BPT ){ ! 226: bpty = SETCLR; ! 227: t.af( "if( ? ) >>>" ); ! 228: } ! 229: } else { ! 230: bpty = CLRBPT; ! 231: if( stmt->lineno == i ){ ! 232: if( stmt->condition ) ! 233: t.af("if(%s)", stmt->condtext->text); ! 234: t.af( ">>>" ); ! 235: } ! 236: } ! 237: } ! 238: t.af("%s", edge[i] ? edge[i] : ""); ! 239: pad->insert(i, (Attrib)a|ACCEPT_KBD, (PadRcv*)stmt, ix[bpty], "%s", t.text); ! 240: } ! 241: ! 242: char *SrcText::srcline(long i) ! 243: { ! 244: trace( "%d.srcline(%d)", this, i ); OK("SrcText::srcline"); ! 245: if( !edge || i<1 || i>lastline ) return ""; ! 246: return edge[i]; ! 247: } ! 248: ! 249: void SrcText::select(long i, long svp) ! 250: { ! 251: trace( "%d.select(%d,%d)", this, i, svp ); VOK; ! 252: if( svp!=SVP || edge ) linereq(i, SELECTLINE); ! 253: } ! 254: ! 255: void SrcText::go() ! 256: { ! 257: trace( "%d.go()", this ); VOK; ! 258: process()->go(); ! 259: } ! 260: ! 261: void SrcText::currentstmt() ! 262: { ! 263: trace( "%d.currentstmt()", this ); VOK; ! 264: core()->process()->currentstmt(); ! 265: } ! 266: ! 267: void SrcText::stmtstep(long i) ! 268: { ! 269: trace( "%d.stmtstep()", this ); VOK; ! 270: process()->stmtstep(i); ! 271: } ! 272: ! 273: void SrcText::stepinto() ! 274: { ! 275: trace( "%d.stepinto()", this ); VOK; ! 276: process()->stepinto(); ! 277: } ! 278: ! 279: char *SrcText::kbd(char *s) ! 280: { ! 281: trace( "%d.kbd(%s)", this, s ); OK("kbd"); ! 282: if( edge ){ ! 283: if( *s == '/' ) ! 284: return contextsearch( lastline, s+1, 1 ); ! 285: else if( *s == '?' ) ! 286: return contextsearch( 1, s+1, -1 ); ! 287: else if( alldigits(s) ) ! 288: select( atoi(s) ); ! 289: else ! 290: return help(); ! 291: } else { ! 292: path = sf("%s",s); ! 293: reopen(); ! 294: } ! 295: return 0; ! 296: } ! 297: ! 298: char *SrcText::help() ! 299: { ! 300: trace( "%d.help()", this ); OK("SrcText::help"); ! 301: return edge ? "<line number> {display line} | [/?]<string> {search}" ! 302: : "<path> {change source file name}"; ! 303: } ! 304: ! 305: char *SrcText::contextsearch(int from, char *pat, int dir) ! 306: { ! 307: trace( "%d.contextsearch(%d,%s,%d)", this, from, pat?pat:"", dir ); ! 308: OK("contextsearch"); ! 309: if( !pat || !*pat || !strcmp(pat,"?") || !strcmp(pat,"/") ) ! 310: pat = prevpat; ! 311: prevpat = sf("%s", pat); ! 312: int patlen = strlen(pat); ! 313: register char pat0 = *pat; ! 314: for( int probe = from+dir; probe != from; probe += dir ){ ! 315: if( probe == 0 ) probe = lastline; ! 316: if( probe == lastline+1 ) probe = 1; ! 317: register char *p; ! 318: for( p = edge[probe]; *p; ++p ){ ! 319: if( *p == pat0 && !strncmp(p, pat, patlen) ){ ! 320: linereq(probe, SELECTLINE); ! 321: return 0; ! 322: } ! 323: } ! 324: } ! 325: return sf("%s: not found", pat); ! 326: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.