|
|
1.1 root 1: #include "core.pub"
2: #include "symtab.pub"
3: #include "memory.pri"
4: #include "parse.h"
5: #include "expr.pub"
6: #include "frame.pub"
7: #include "process.pub"
8: #include "format.pub"
9: #include "journal.pub"
10: SRCFILE("memory.c")
11:
12: Memory::Memory(Core *c)
13: {
14: core = c;
15: prevpat = 0;
16: }
17:
18: void Memory::userclose()
19: {
20: trace("%d.userclose()", this); VOK;
21: delete pad;
22: pad = 0;
23: invalidate();
24: Cell *cellsetsib;
25: for( ; cellset; cellset = cellsetsib ){
26: cellsetsib = cellset->sib; // new malloc
27: delete cellset;
28: }
29: current = 0;
30: }
31:
32: void Memory::makecell(Cell *model, long addr )
33: {
34: Cell *c;
35:
36: trace( "%d.makecell(%d,%d)", this, model, addr ); VOK;
37: if( !model ){
38: model = new Cell(this);
39: model->fmt = F_HEX;
40: model->size = 1;
41: }
42: for( c = cellset; c; c = c->sib )
43: if( addr == c->addr ) break;
44: if( !c ){
45: c = new Cell(this);
46: c->addr = addr;
47: c->sib = cellset;
48: cellset = c;
49: }
50: c->fmt = model->fmt;
51: c->size = model->size;
52: c->display();
53: current = c;
54: }
55:
56: void Memory::banner()
57: {
58: trace( "%d.banner()", this ); VOK;
59: if( pad ){
60: pad->banner("Memory: %s", core->procpath());
61: pad->name("Mem %s", basename(core->procpath()));
62: }
63: }
64:
65: void Memory::open(long a)
66: {
67: trace( "%d.open(%d)", this, a ); VOK;
68: if( !pad ){
69: pad = new Pad((PadRcv*) this);
70: banner();
71: }
72: pad->makecurrent();
73: if( a ) makecell(current,a);
74: }
75:
76: char *Memory::help()
77: {
78: return ".=<expr> {show memory cell at address}";
79: }
80:
81: char *Memory::kbd(char *s)
82: {
83: Parse y(G_DOTEQ_CONEX,0);
84: Expr *e;
85: Bls error;
86:
87: trace( "%d.kbd(%s)", this, s ); OK(0);
88: if( !(e = (Expr*)y.parse(s)) )
89: return sf("%s: %s", y.error, s);
90: e->evaltext(core->process()->globals, error);
91: if( e->evalerr )
92: return sf("%s: %s", s, error.text);
93: makecell(current,e->val.lng);
94: return 0;
95: }
96:
97: struct FmtSize {
98: long fmt;
99: long size;
100: };
101:
102: FmtSize FS[] = {
103: F_DECIMAL, 7,
104: F_SIGNED, 7,
105: F_OCTAL, 7,
106: F_HEX, 7,
107: F_ASCII, 7,
108: F_SYMBOLIC, 7,
109: F_TIME, 4,
110: F_FLOAT, 4,
111: F_DOUBLE, 8,
112: F_DBLHEX, 8,
113: 0, 0
114: };
115:
116: Index Cell::carte()
117: {
118: Menu m, s, f;
119:
120: OK(ZIndex);
121: m.last( spy ? "unspy" : "spy on", (Action)&Cell::setspy, !spy );
122: s.last("1 byte ", (Action)&Cell::resize, 1);
123: s.last("2 bytes", (Action)&Cell::resize, 2);
124: s.last("4 bytes", (Action)&Cell::resize, 4);
125: s.last("8 bytes", (Action)&Cell::resize, 8);
126: m.last(s.index("size"));
127:
128: for( int i = 0; FS[i].fmt; ++i )
129: if( FS[i].size & size ){
130: long b = FS[i].fmt;
131: if( fmt&b ) b |= F_TURNOFF;
132: f.last(FmtName(b), (Action)&Cell::reformat, b);
133: }
134: m.last(f.index("format"));
135: m.last( ".+1", (Action)&Cell::relative, 1 );
136: m.last( ".+2", (Action)&Cell::relative, 2 );
137: m.last( ".+4", (Action)&Cell::relative, 4 );
138: if( size < 8 )
139: m.last( "* thru .", (Action)&Cell::indirect, 0 );
140: m.last( ".-1", (Action)&Cell::relative, -1 );
141: m.last( ".-2", (Action)&Cell::relative, -2 );
142: m.last( ".-4", (Action)&Cell::relative, -4 );
143:
144: m.last( "asmblr", (Action)&Cell::asmblr, 0 );
145:
146: return m.index();
147: }
148:
149: void Cell::dodisplay(Bls &t)
150: {
151: Cslfd *m;
152: long afmt = fmt&~(F_ASCII|F_DOUBLE|F_FLOAT|F_DBLHEX|F_TIME);
153: long cfmt = fmt&~F_SYMBOLIC;
154: switch( size ){
155: case 8:
156: if( !(cfmt &= F_DOUBLE|F_DBLHEX) )
157: cfmt = F_DOUBLE;
158: break;
159: default:
160: if( !(cfmt &= ~(F_DOUBLE|F_DBLHEX)) )
161: cfmt = F_HEX;
162: }
163: Format a(afmt?afmt:F_HEX, memory->core->symtab());
164: Format c(cfmt);
165: if( spy ) t.af( ">>> " );
166: t.af( "%s/%d: ", a.f(addr), size );
167: switch( size ){
168: case 1: c.format |= F_MASKEXT8; break;
169: case 2: c.format |= F_MASKEXT16; break;
170: }
171: if( m = memory->core->peek(addr,0) ){
172: long val;
173: switch( size ){
174: case 1: c.format |= F_MASKEXT8;
175: val = m->chr;
176: break;
177: case 2: c.format |= F_MASKEXT16;
178: val = m->sht;
179: break;
180: case 4: val = m->lng;
181: }
182: t.af( "%s", c.f(val, m->dbl) );
183: if( spy ) *spy = *m;
184: } else
185: t.af( "cannot read" );
186: }
187:
188: void Cell::display(char *error, int j)
189: {
190: Bls t;
191:
192: trace( "%d.display()", this ); VOK;
193: dodisplay(t);
194: if( error ) t.af( " %s", error );
195: Attrib attrib = ACCEPT_KBD|SELECTLINE;
196: if( spy ) attrib |= DONT_CUT;
197: memory->pad->insert(addr, attrib, (PadRcv*)this, carte(), "%s", t.text);
198: if( j )
199: memory->core->process()->journal()->insert("%s", t.text);
200: }
201:
202: int Cell::changed()
203: {
204: int changed = 0;
205: Cslfd *m;
206:
207: trace( "%d.changed()" ); OK(0);
208: if( !spy ) return 0;
209: m = memory->core->peek(addr);
210: switch( size ){
211: case 1: if( m->chr != spy->chr ) changed = 1; break;
212: case 2: if( m->sht != spy->sht ) changed = 1; break;
213: case 4: if( m->lng != spy->lng ) changed = 1; break;
214: case 8: if( m->dbl != spy->dbl ) changed = 1; break;
215: }
216: if( changed ) display(0,1);
217: return changed;
218: }
219:
220:
221: void Cell::setspy(long s)
222: {
223: trace( "%d.setspy(%d)", this, s ); VOK;
224: if( !s && spy ){
225: delete spy;
226: spy = 0;
227: } else if( s )
228: spy = new Cslfd;
229: display();
230: }
231:
232: void Cell::relative(long a)
233: {
234: trace( "%d.relative(%d)", this, a ); VOK;
235: memory->makecell(this,addr+a*size);
236: }
237:
238: void Cell::indirect()
239: {
240: Cslfd *m;
241:
242: trace( "%d.indirect()", this ); VOK;
243: if( !(m = memory->core->peek(addr,0)) )
244: display(); /* will have same problem */
245: else
246: memory->makecell(this, size==1 ? (unsigned char) m->chr
247: : size==2 ? (unsigned short) m->sht : m->lng);
248: }
249:
250: char *Cell::help()
251: {
252: return "$=<expr> {update cell} | .=<expr> {open cell} | [/?]<string> {search}";
253: }
254:
255: char *Cell::search(int dir, char *pat)
256: {
257: Cell s(memory);
258:
259: trace("%d.search(%d,%s)", this, dir, pat?pat:"0"); OK("Cell::search");
260: if( !pat || !*pat || !strcmp(pat,"?") || !strcmp(pat,"/") )
261: pat = memory->prevpat;
262: memory->prevpat = sf("%s", pat);
263: int patlen = strlen(pat);
264: s = *this;
265: long t0 = time(0);
266: for( s.addr = addr+dir*size; s.addr != addr; s.addr += dir*size ){
267: Cslfd *m = memory->core->peek(s.addr, 0);
268: if( !m ){
269: memory->makecell(this,s.addr);
270: return "memory not contiguously readable for search";
271: }
272: Bls t;
273: s.dodisplay(t);
274: register char *p, pat0 = *pat;
275: for( p = t.text; *p; ++p ){
276: if( *p == pat0 && !strncmp(p, pat, patlen) ){
277: memory->makecell(this,s.addr);
278: return 0;
279: }
280: }
281: const timeout = 10;
282: if( time(0) > t0+timeout ){
283: memory->makecell(this,s.addr);
284: return sf("search timeout (%d secs)", timeout);
285: }
286: }
287: }
288:
289: char *Cell::kbd(char *s) /* should eval against loader symbol frame */
290: {
291: Parse y(G_DOLEQ_CONEX, 0);
292: Expr *e;
293: Bls t;
294:
295: trace( "%d.kbd(%s)", this, s ); OK("kbd");
296: if( !*s ){
297: relative(1);
298: return 0;
299: }
300: if( s[0] == '/' )
301: return search( 1, s+1);
302: if( s[0] == '?' )
303: return search(-1, s+1);
304: if( (e = (Expr*)y.parse(s)) ){
305: e->evaltext(memory->core->process()->globals, t);
306: display(e->evalerr ? t.text
307: : memory->core->poke(addr,e->val.lng,size));
308: return 0;
309: }
310: return memory->kbd(s);
311: }
312:
313: void Cell::reformat(long f)
314: {
315: trace( "%d.reformat(0x%X) 0x%X ", this, f, fmt ); VOK;
316: fmt ^= f;
317: if( f&F_TURNOFF )
318: fmt &= ~f;
319: else
320: fmt |= f;
321: display();
322: }
323:
324: void Cell::resize(int s)
325: {
326: trace( "%d.resize(%d) %d", this, s, size ); VOK;
327: size = s;
328: reformat(0);
329: }
330:
331: void Cell::asmblr()
332: {
333: trace( "%d.asmblr()" ); VOK;
334: memory->core->process()->openasm(addr);
335: }
336:
337: int Memory::changes(long verbose)
338: {
339: Cell *c;
340: long changes = 0, key = 0x40000000, spies = 0; /* !!! */
341: trace( "%d.changes()", this ); OK(0);
342:
343: pad->removeline(key);
344: for( c = cellset; c; c = c->sib )
345: if( c->spy ){
346: ++spies;
347: changes += c->changed();
348: }
349: if( verbose ){
350: if( spies == 0 )
351: pad->insert( key, SELECTLINE, "no spies" );
352: else if( changes==0 )
353: pad->insert( key, SELECTLINE, "no spies changed" );
354: }
355: return changes;
356: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.