1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)runcont.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 /*
13 * Execution management.
14 */
15
16 #include "defs.h"
17 #include <signal.h>
18 #include "process.h"
19 #include "machine.h"
20 #include "object.h"
21 #include "main.h"
22 #include "breakpoint.h"
23 #include "command.h"
24 #include "process.rep"
25
26 #define MAXNARGS 100 /* maximum number of arguments to RUN */
27
28 typedef char *String;
29
30 LOCAL BOOLEAN just_started;
31 LOCAL int argc;
32 LOCAL String argv[MAXNARGS];
33 LOCAL String infile;
34 LOCAL String outfile;
35 LOCAL PROCESS pbuf;
36 PROCESS *process = &pbuf;
37
38 /*
39 * This is a px-related kludge to deal with the possibility
40 * of object code magically coming from a tmp file.
41 */
42
43 LOCAL String mode;
44 LOCAL String realname;
45
setargs(m,r)46 setargs(m, r)
47 char *m, *r;
48 {
49 mode = m;
50 realname = r;
51 }
52
53 /*
54 * Initialize the argument list.
55 */
56
arginit()57 arginit()
58 {
59 infile = NIL;
60 outfile = NIL;
61 argv[0] = mode;
62 argv[1] = objname;
63 if (option('t') && realname == NIL) {
64 argc = 2;
65 } else {
66 argv[2] = realname;
67 argc = 3;
68 }
69 }
70
71 /*
72 * Add an argument to the list for the debuggee.
73 */
74
newarg(arg)75 newarg(arg)
76 String arg;
77 {
78 if (argc >= MAXNARGS) {
79 error("too many arguments to run");
80 }
81 argv[argc++] = arg;
82 }
83
84 /*
85 * Set the standard input for the debuggee.
86 */
87
inarg(filename)88 inarg(filename)
89 String filename;
90 {
91 if (infile != NIL) {
92 error("multiple input redirects");
93 }
94 infile = filename;
95 }
96
97 /*
98 * Set the standard output for the debuggee.
99 * Probably should check to avoid overwriting an existing file.
100 */
101
outarg(filename)102 outarg(filename)
103 String filename;
104 {
105 if (outfile != NIL) {
106 error("multiple output redirect");
107 }
108 outfile = filename;
109 }
110
111 /*
112 * Initial start of the process. The idea is to get it to the point
113 * where the object code has been loaded but execution has not begun.
114 */
115
initstart()116 initstart()
117 {
118 arginit();
119 argv[argc] = NIL;
120 initcache(process);
121 start(argv, infile, outfile);
122 if (process->status != STOPPED) {
123 panic("could not start program");
124 }
125 }
126
127 /*
128 * Run starts debuggee executing.
129 */
130
run()131 run()
132 {
133 fixbps();
134 curline = 0;
135 argv[argc] = NIL;
136 start(argv, infile, outfile);
137 if (process->status == STOPPED) {
138 just_started = TRUE;
139 isstopped = FALSE;
140 cont();
141 } else if (option('r')) {
142 panic("could not start program");
143 }
144 }
145
146 /*
147 * Continue execution wherever we left off.
148 *
149 * Note that this routine never returns. Eventually bpact() will fail
150 * and we'll call printstatus or step will call it.
151 */
152
153 typedef void SIGFUN();
154
155 LOCAL SIGFUN *dbintr;
156 LOCAL void intr();
157
158 #define fails == FALSE
159
cont()160 cont()
161 {
162 dbintr = signal(SIGINT, intr);
163 if (just_started) {
164 just_started = FALSE;
165 } else {
166 if (!isstopped) {
167 error("can't continue execution");
168 }
169 isstopped = FALSE;
170 step();
171 }
172 for (;;) {
173 if (single_stepping) {
174 printnews();
175 } else {
176 setallbps();
177 resume();
178 unsetallbps();
179 if (bpact() fails) {
180 printstatus();
181 }
182 }
183 step();
184 }
185 /* NOTREACHED */
186 }
187
188 /*
189 * This routine is called if we get an interrupt while "running" px
190 * but actually in the debugger. Could happen, for example, while
191 * processing breakpoints.
192 *
193 * We basically just want to keep going; the assumption is
194 * that when the process resumes it will get the interrupt
195 * which will then be handled.
196 */
197
intr()198 LOCAL void intr()
199 {
200 signal(SIGINT, intr);
201 }
202
fixintr()203 fixintr()
204 {
205 signal(SIGINT, dbintr);
206 }
207