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