|
|
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.