1 /* This file is part of the program psim. 2 3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. 17 18 */ 19 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <fcntl.h> 24 25 #include <signal.h> 26 27 #include "psim.h" 28 #include "options.h" 29 #include "device.h" /* FIXME: psim should provide the interface */ 30 #include "events.h" /* FIXME: psim should provide the interface */ 31 32 #include "bfd.h" 33 #include "gdb/callback.h" 34 #include "gdb/remote-sim.h" 35 36 #ifdef HAVE_STDLIB_H 37 #include <stdlib.h> 38 #endif 39 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> 42 #endif 43 44 #ifdef HAVE_STRING_H 45 #include <string.h> 46 #else 47 #ifdef HAVE_STRINGS_H 48 #include <strings.h> 49 #endif 50 #endif 51 52 #include <errno.h> 53 54 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL) 55 #undef WITH_STDIO 56 #define WITH_STDIO DO_USE_STDIO 57 #endif 58 59 60 extern char **environ; 61 62 static psim *simulation = NULL; 63 64 65 void 66 sim_io_poll_quit (void) 67 { 68 /* nothing to do */ 69 } 70 71 void 72 sim_io_printf_filtered(const char *msg, ...) 73 { 74 va_list ap; 75 va_start(ap, msg); 76 vprintf(msg, ap); 77 va_end(ap); 78 } 79 80 void 81 error (const char *msg, ...) 82 { 83 va_list ap; 84 va_start(ap, msg); 85 vprintf(msg, ap); 86 printf("\n"); 87 va_end(ap); 88 89 /* any final clean up */ 90 if (ppc_trace[trace_print_info] && simulation != NULL) 91 psim_print_info (simulation, ppc_trace[trace_print_info]); 92 93 exit (1); 94 } 95 96 int 97 sim_io_write_stdout(const char *buf, 98 int sizeof_buf) 99 { 100 switch (CURRENT_STDIO) { 101 case DO_USE_STDIO: 102 { 103 int i; 104 for (i = 0; i < sizeof_buf; i++) { 105 putchar(buf[i]); 106 } 107 return i; 108 } 109 break; 110 case DONT_USE_STDIO: 111 return write(1, buf, sizeof_buf); 112 break; 113 default: 114 error("sim_io_write_stdout: invalid switch\n"); 115 } 116 return 0; 117 } 118 119 int 120 sim_io_write_stderr(const char *buf, 121 int sizeof_buf) 122 { 123 switch (CURRENT_STDIO) { 124 case DO_USE_STDIO: 125 { 126 int i; 127 for (i = 0; i < sizeof_buf; i++) { 128 fputc(buf[i], stderr); 129 } 130 return i; 131 } 132 break; 133 case DONT_USE_STDIO: 134 return write(2, buf, sizeof_buf); 135 break; 136 default: 137 error("sim_io_write_stdout: invalid switch\n"); 138 } 139 return 0; 140 } 141 142 int 143 sim_io_read_stdin(char *buf, 144 int sizeof_buf) 145 { 146 switch (CURRENT_STDIO) { 147 case DO_USE_STDIO: 148 if (sizeof_buf > 1) { 149 if (fgets(buf, sizeof_buf, stdin) != NULL) 150 return strlen(buf); 151 } 152 else if (sizeof_buf == 1) { 153 char b[2]; 154 if (fgets(b, sizeof(b), stdin) != NULL) { 155 memcpy(buf, b, strlen(b)); 156 return strlen(b); 157 } 158 } 159 else if (sizeof_buf == 0) 160 return 0; 161 return sim_io_eof; 162 break; 163 case DONT_USE_STDIO: 164 #if defined(O_NDELAY) && defined(F_GETFL) && defined(F_SETFL) 165 { 166 /* check for input */ 167 int flags; 168 int status; 169 int nr_read; 170 int result; 171 /* get the old status */ 172 flags = fcntl(0, F_GETFL, 0); 173 if (flags == -1) { 174 perror("sim_io_read_stdin"); 175 return sim_io_eof; 176 } 177 /* temp, disable blocking IO */ 178 status = fcntl(0, F_SETFL, flags | O_NDELAY); 179 if (status == -1) { 180 perror("sim_io_read_stdin"); 181 return sim_io_eof; 182 } 183 /* try for input */ 184 nr_read = read(0, buf, sizeof_buf); 185 if (nr_read > 0 186 || (nr_read == 0 && sizeof_buf == 0)) 187 result = nr_read; 188 else if (nr_read == 0) 189 result = sim_io_eof; 190 else { /* nr_read < 0 */ 191 if (errno == EAGAIN) 192 result = sim_io_not_ready; 193 else 194 result = sim_io_eof; 195 } 196 /* return to regular vewing */ 197 status = fcntl(0, F_SETFL, flags); 198 if (status == -1) { 199 perror("sim_io_read_stdin"); 200 return sim_io_eof; 201 } 202 return result; 203 } 204 break; 205 #endif 206 default: 207 error("sim_io_read_stdin: invalid switch\n"); 208 break; 209 } 210 return 0; 211 } 212 213 void 214 sim_io_flush_stdoutput(void) 215 { 216 switch (CURRENT_STDIO) { 217 case DO_USE_STDIO: 218 fflush (stdout); 219 break; 220 case DONT_USE_STDIO: 221 break; 222 default: 223 error("sim_io_flush_stdoutput: invalid switch\n"); 224 break; 225 } 226 } 227 228 void 229 sim_io_error (SIM_DESC sd, const char *msg, ...) 230 { 231 va_list ap; 232 va_start(ap, msg); 233 vprintf(msg, ap); 234 printf("\n"); 235 va_end(ap); 236 237 /* any final clean up */ 238 if (ppc_trace[trace_print_info] && simulation != NULL) 239 psim_print_info (simulation, ppc_trace[trace_print_info]); 240 241 exit (1); 242 } 243 244 245 void * 246 zalloc(long size) 247 { 248 void *memory = malloc(size); 249 if (memory == NULL) 250 error("zalloc failed\n"); 251 memset(memory, 0, size); 252 return memory; 253 } 254 255 /* When a CNTRL-C occures, queue an event to shut down the simulation */ 256 257 static RETSIGTYPE 258 cntrl_c(int sig) 259 { 260 psim_stop (simulation); 261 } 262 263 264 int 265 main(int argc, char **argv) 266 { 267 const char *name_of_file; 268 char *arg_; 269 psim_status status; 270 device *root = psim_tree(); 271 272 /* parse the arguments */ 273 argv = psim_options (root, argv + 1, SIM_OPEN_STANDALONE); 274 if (argv[0] == NULL) { 275 if (ppc_trace[trace_opts]) { 276 print_options (); 277 return 0; 278 } else { 279 psim_usage (0, 0, SIM_OPEN_STANDALONE); 280 } 281 } 282 name_of_file = argv[0]; 283 284 if (ppc_trace[trace_opts]) 285 print_options (); 286 287 /* create the simulator */ 288 simulation = psim_create(name_of_file, root); 289 290 /* fudge the environment so that _=prog-name */ 291 arg_ = (char*)zalloc(strlen(argv[0]) + strlen("_=") + 1); 292 strcpy(arg_, "_="); 293 strcat(arg_, argv[0]); 294 putenv(arg_); 295 296 /* initialize it */ 297 psim_init(simulation); 298 psim_stack(simulation, argv, environ); 299 300 { 301 RETSIGTYPE (*prev) (); 302 prev = signal(SIGINT, cntrl_c); 303 psim_run(simulation); 304 signal(SIGINT, prev); 305 } 306 307 /* any final clean up */ 308 if (ppc_trace[trace_print_info]) 309 psim_print_info (simulation, ppc_trace[trace_print_info]); 310 311 /* why did we stop */ 312 status = psim_get_status(simulation); 313 switch (status.reason) { 314 case was_continuing: 315 error("psim: continuing while stopped!\n"); 316 return 0; 317 case was_trap: 318 error("psim: no trap insn\n"); 319 return 0; 320 case was_exited: 321 return status.signal; 322 case was_signalled: 323 printf ("%s: Caught signal %d at address 0x%lx\n", 324 name_of_file, (int)status.signal, 325 (long)status.program_counter); 326 return status.signal; 327 default: 328 error("unknown halt condition\n"); 329 return 0; 330 } 331 } 332