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 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 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 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 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 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 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 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 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 198 LOCAL void intr() 199 { 200 signal(SIGINT, intr); 201 } 202 203 fixintr() 204 { 205 signal(SIGINT, dbintr); 206 } 207