/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <stdarg.h>
#include <stdio.h>
+#include <fcntl.h>
+
+#include <signal.h>
#include "psim.h"
-#include "function_unit.h"
#include "options.h"
+#include "device.h" /* FIXME: psim should provide the interface */
+#include "events.h" /* FIXME: psim should provide the interface */
+
+#include "bfd.h"
+#include "gdb/callback.h"
+#include "gdb/remote-sim.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#endif
+#include <errno.h>
+
+#if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
+#undef WITH_STDIO
+#define WITH_STDIO DO_USE_STDIO
+#endif
+
+
extern char **environ;
-extern char *optarg;
-extern int optind;
-extern int optopt;
-extern int opterr;
+
+static psim *simulation = NULL;
+
void
-printf_filtered(const char *msg, ...)
+sim_io_poll_quit (void)
+{
+ /* nothing to do */
+}
+
+void
+sim_io_printf_filtered(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
}
void
-error (char *msg, ...)
+error (const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ vprintf(msg, ap);
+ printf("\n");
+ va_end(ap);
+
+ /* any final clean up */
+ if (ppc_trace[trace_print_info] && simulation != NULL)
+ psim_print_info (simulation, ppc_trace[trace_print_info]);
+
+ exit (1);
+}
+
+int
+sim_io_write_stdout(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ {
+ int i;
+ for (i = 0; i < sizeof_buf; i++) {
+ putchar(buf[i]);
+ }
+ return i;
+ }
+ break;
+ case DONT_USE_STDIO:
+ return write(1, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stdout: invalid switch\n");
+ }
+ return 0;
+}
+
+int
+sim_io_write_stderr(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ {
+ int i;
+ for (i = 0; i < sizeof_buf; i++) {
+ fputc(buf[i], stderr);
+ }
+ return i;
+ }
+ break;
+ case DONT_USE_STDIO:
+ return write(2, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stdout: invalid switch\n");
+ }
+ return 0;
+}
+
+int
+sim_io_read_stdin(char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ if (sizeof_buf > 1) {
+ if (fgets(buf, sizeof_buf, stdin) != NULL)
+ return strlen(buf);
+ }
+ else if (sizeof_buf == 1) {
+ char b[2];
+ if (fgets(b, sizeof(b), stdin) != NULL) {
+ memcpy(buf, b, strlen(b));
+ return strlen(b);
+ }
+ }
+ else if (sizeof_buf == 0)
+ return 0;
+ return sim_io_eof;
+ break;
+ case DONT_USE_STDIO:
+#if defined(O_NDELAY) && defined(F_GETFL) && defined(F_SETFL)
+ {
+ /* check for input */
+ int flags;
+ int status;
+ int nr_read;
+ int result;
+ /* get the old status */
+ flags = fcntl(0, F_GETFL, 0);
+ if (flags == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ /* temp, disable blocking IO */
+ status = fcntl(0, F_SETFL, flags | O_NDELAY);
+ if (status == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ /* try for input */
+ nr_read = read(0, buf, sizeof_buf);
+ if (nr_read > 0
+ || (nr_read == 0 && sizeof_buf == 0))
+ result = nr_read;
+ else if (nr_read == 0)
+ result = sim_io_eof;
+ else { /* nr_read < 0 */
+ if (errno == EAGAIN)
+ result = sim_io_not_ready;
+ else
+ result = sim_io_eof;
+ }
+ /* return to regular vewing */
+ status = fcntl(0, F_SETFL, flags);
+ if (status == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ return result;
+ }
+ break;
+#endif
+ default:
+ error("sim_io_read_stdin: invalid switch\n");
+ break;
+ }
+ return 0;
+}
+
+void
+sim_io_flush_stdoutput(void)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ fflush (stdout);
+ break;
+ case DONT_USE_STDIO:
+ break;
+ default:
+ error("sim_io_flush_stdoutput: invalid switch\n");
+ break;
+ }
+}
+
+void
+sim_io_error (SIM_DESC sd, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
+ printf("\n");
va_end(ap);
+
+ /* any final clean up */
+ if (ppc_trace[trace_print_info] && simulation != NULL)
+ psim_print_info (simulation, ppc_trace[trace_print_info]);
+
exit (1);
}
+
void *
zalloc(long size)
{
void *memory = malloc(size);
if (memory == NULL)
- error("zmalloc failed\n");
+ error("zalloc failed\n");
memset(memory, 0, size);
return memory;
}
free(chunk);
}
-static void
-usage(void)
+/* When a CNTRL-C occures, queue an event to shut down the simulation */
+
+static RETSIGTYPE
+cntrl_c(int sig)
{
- printf_filtered("Usage:\n\tpsim [ -t <trace-option> ] [-m model] [-i] [-I] <image> [ <image-args> ... ]\n");
- trace_usage();
- error("");
+ psim_stop (simulation);
}
+
int
main(int argc, char **argv)
{
- psim *system;
const char *name_of_file;
char *arg_;
psim_status status;
- int letter;
- int print_info = 0;
+ device *root = psim_tree();
- /* check for arguments -- note sim_calls.c also contains argument processing
- code for the simulator linked within gdb. */
- while ((letter = getopt (argc, argv, "Iim:t:")) != EOF)
- {
- switch (letter) {
- case 't':
- trace_option(optarg);
- break;
- case 'm':
- model_set(optarg);
- break;
- case 'i':
- print_info = 1;
- break;
- case 'I':
- print_info = 2;
- break;
- default:
- usage();
- }
+ /* parse the arguments */
+ argv = psim_options(root, argv + 1);
+ if (argv[0] == NULL) {
+ if (ppc_trace[trace_opts]) {
+ print_options ();
+ return 0;
+ } else {
+ psim_usage(0, 0);
}
- if (optind >= argc)
- usage();
- name_of_file = argv[optind];
+ }
+ name_of_file = argv[0];
if (ppc_trace[trace_opts])
print_options ();
/* create the simulator */
- system = psim_create(name_of_file);
+ simulation = psim_create(name_of_file, root);
/* fudge the environment so that _=prog-name */
- arg_ = (char*)zalloc(strlen(argv[optind]) + strlen("_=") + 1);
+ arg_ = (char*)zalloc(strlen(argv[0]) + strlen("_=") + 1);
strcpy(arg_, "_=");
- strcat(arg_, argv[optind]);
+ strcat(arg_, argv[0]);
putenv(arg_);
/* initialize it */
- psim_init(system);
- psim_stack(system, &argv[optind], environ);
+ psim_init(simulation);
+ psim_stack(simulation, argv, environ);
- psim_run(system);
+ {
+ RETSIGTYPE (*prev) ();
+ prev = signal(SIGINT, cntrl_c);
+ psim_run(simulation);
+ signal(SIGINT, prev);
+ }
/* any final clean up */
- if (print_info)
- psim_print_info (system, print_info);
+ if (ppc_trace[trace_print_info])
+ psim_print_info (simulation, ppc_trace[trace_print_info]);
/* why did we stop */
- status = psim_get_status(system);
+ status = psim_get_status(simulation);
switch (status.reason) {
case was_continuing:
error("psim: continuing while stoped!\n");