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
sim_io_poll_quit(void)66 sim_io_poll_quit (void)
67 {
68   /* nothing to do */
69 }
70 
71 void
sim_io_printf_filtered(const char * msg,...)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
error(const char * msg,...)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
sim_io_write_stdout(const char * buf,int sizeof_buf)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
sim_io_write_stderr(const char * buf,int sizeof_buf)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
sim_io_read_stdin(char * buf,int sizeof_buf)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
sim_io_flush_stdoutput(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
sim_io_error(SIM_DESC sd,const char * msg,...)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 *
zalloc(long size)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
cntrl_c(int sig)258 cntrl_c(int sig)
259 {
260   psim_stop (simulation);
261 }
262 
263 
264 int
main(int argc,char ** argv)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);
274   if (argv[0] == NULL) {
275     if (ppc_trace[trace_opts]) {
276       print_options ();
277       return 0;
278     } else {
279       psim_usage(0, 0);
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