xref: /plan9-contrib/sys/src/cmd/db/command.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /*
2  *
3  *	debugger
4  *
5  */
6 
7 #include "defs.h"
8 #include "fns.h"
9 
10 char	BADEQ[] = "unexpected `='";
11 
12 BOOL	executing;
13 extern	char	*lp;
14 
15 extern	char	lastc, peekc;
16 char	eqformat[ARB] = "z";
17 char	stformat[ARB] = "zMi";
18 
19 ADDR	ditto;
20 
21 ADDR	dot;
22 WORD	dotinc;
23 WORD	adrval, cntval, loopcnt;
24 int	adrflg, cntflg;
25 
26 /* command decoding */
27 
28 command(char *buf, int defcom)
29 {
30 	char	*reg;
31 	char	savc;
32 	char	*savlp=lp;
33 	char	savlc = lastc;
34 	char	savpc = peekc;
35 	static char lastcom = '=', savecom = '=';
36 
37 	if (defcom == 0)
38 		defcom = lastcom;
39 	if (buf) {
40 		if (*buf==EOR)
41 			return(FALSE);
42 		clrinp();
43 		lp=buf;
44 	}
45 	do {
46 		adrflg=expr(0);		/* first address */
47 		if (adrflg)
48 			dot=ditto=expv;
49 		adrval=dot;
50 
51 		if (rdc()==',' && expr(0)) {	/* count */
52 			cntflg=TRUE;
53 			cntval=expv;
54 		} else {
55 			cntflg=FALSE;
56 			cntval=1;
57 			reread();
58 		}
59 
60 		if (!eol(rdc()))
61 			lastcom=lastc;		/* command */
62 		else {
63 			if (adrflg==0)
64 				dot=inkdot(dotinc);
65 			reread();
66 			lastcom=defcom;
67 		}
68 		switch(lastcom) {
69 		case '/':
70 		case '=':
71 		case '?':
72 			savecom = lastcom;
73 			acommand(lastcom);
74 			break;
75 
76 		case '>':
77 			lastcom = savecom;
78 			savc=rdc();
79 			if (reg=regname(savc))
80 				rput(cormap, reg, dot);
81 			else
82 				error("bad variable");
83 			break;
84 
85 		case '!':
86 			lastcom=savecom;
87 			shell();
88 			break;
89 
90 		case '$':
91 			lastcom=savecom;
92 			printtrace(nextchar());
93 			break;
94 
95 		case ':':
96 			if (!executing) {
97 				executing=TRUE;
98 				subpcs(nextchar());
99 				executing=FALSE;
100 				lastcom=savecom;
101 			}
102 			break;
103 
104 		case 0:
105 			prints(DBNAME);
106 			break;
107 
108 		default:
109 			error("bad command");
110 		}
111 		flushbuf();
112 	} while (rdc()==';');
113 	if (buf == 0)
114 		reread();
115 	else {
116 		clrinp();
117 		lp=savlp;
118 		lastc = savlc;
119 		peekc = savpc;
120 	}
121 
122 	if(adrflg)
123 		return dot;
124 	return 1;
125 }
126 
127 /*
128  * [/?][wml]
129  */
130 
131 void
132 acommand(int pc)
133 {
134 	int eqcom;
135 	Map *map;
136 	char *fmt;
137 	char buf[512];
138 
139 	if (pc == '=') {
140 		eqcom = 1;
141 		fmt = eqformat;
142 		map = dotmap;
143 	} else {
144 		eqcom = 0;
145 		fmt = stformat;
146 		if (pc == '/')
147 			map = cormap;
148 		else
149 			map = symmap;
150 	}
151 	if (!map) {
152 		sprint(buf, "no map for %c", pc);
153 		error(buf);
154 	}
155 
156 	switch (rdc())
157 	{
158 	case 'm':
159 		if (eqcom)
160 			error(BADEQ);
161 		cmdmap(map);
162 		break;
163 
164 	case 'L':
165 	case 'l':
166 		if (eqcom)
167 			error(BADEQ);
168 		cmdsrc(lastc, map);
169 		break;
170 
171 	case 'W':
172 	case 'w':
173 		if (eqcom)
174 			error(BADEQ);
175 		cmdwrite(lastc, map);
176 		break;
177 
178 	default:
179 		reread();
180 		getformat(fmt);
181 		scanform(cntval, !eqcom, fmt, map, eqcom);
182 	}
183 }
184 
185 void
186 cmdsrc(int c, Map *map)
187 {
188 	long w;
189 	long locval, locmsk;
190 	ADDR savdot;
191 	ushort sh;
192 	char buf[512];
193 	int ret;
194 
195 	if (c == 'L')
196 		dotinc = 4;
197 	else
198 		dotinc = 2;
199 	savdot=dot;
200 	expr(1);
201 	locval=expv;
202 	if (expr(0))
203 		locmsk=expv;
204 	else
205 		locmsk = ~0;
206 	if (c == 'L')
207 		while ((ret = get4(map, dot, &w)) > 0 &&  (w&locmsk) != locval)
208 			dot = inkdot(dotinc);
209 	else
210 		while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval)
211 			dot = inkdot(dotinc);
212 	if (ret < 0) {
213 		dot=savdot;
214 		error("%r");
215 	}
216 	symoff(buf, 512, dot, CANY);
217 	dprint(buf);
218 }
219 
220 static char badwrite[] = "can't write process memory or text image";
221 
222 void
223 cmdwrite(int wcom, Map *map)
224 {
225 	ADDR savdot;
226 	char *format;
227 	int pass;
228 
229 	if (wcom == 'w')
230 		format = "x";
231 	else
232 		format = "X";
233 	expr(1);
234 	pass = 0;
235 	do {
236 		pass++;
237 		savdot=dot;
238 		exform(1, 1, format, map, 0, pass);
239 		dot=savdot;
240 		if (wcom == 'W') {
241 			if (put4(map, dot, expv) <= 0)
242 				error(badwrite);
243 		} else {
244 			if (put2(map, dot, expv) <= 0)
245 				error(badwrite);
246 		}
247 		savdot=dot;
248 		dprint("=%8t");
249 		exform(1, 0, format, map, 0, pass);
250 		newline();
251 	} while (expr(0));
252 	dot=savdot;
253 }
254 
255 /*
256  * collect a register name; return register offset
257  * this is not what i'd call a good division of labour
258  */
259 
260 char *
261 regname(int regnam)
262 {
263 	static char buf[64];
264 	char *p;
265 	int c;
266 
267 	p = buf;
268 	*p++ = regnam;
269 	while (isalnum(c = readchar())) {
270 		if (p >= buf+sizeof(buf)-1)
271 			error("register name too long");
272 		*p++ = c;
273 	}
274 	*p = 0;
275 	reread();
276 	return (buf);
277 }
278 
279 /*
280  * shell escape
281  */
282 
283 void
284 shell(void)
285 {
286 	int	rc, unixpid;
287 	char *argp = lp;
288 
289 	while (lastc!=EOR)
290 		rdc();
291 	if ((unixpid=fork())==0) {
292 		*lp=0;
293 		execl("/bin/rc", "rc", "-c", argp, 0);
294 		exits("execl");				/* botch */
295 	} else if (unixpid == -1) {
296 		error("cannot fork");
297 	} else {
298 		mkfault = 0;
299 		while ((rc = wait(0)) != unixpid){
300 			if(rc == -1 && mkfault){
301 				mkfault = 0;
302 				continue;
303 			}
304 			break;
305 		}
306 		prints("!");
307 		reread();
308 	}
309 }
310