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