/[gxemul]/upstream/0.3.8/src/main.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.8/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Mon Oct 8 16:19:43 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22228 byte(s)
0.3.8
1 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: main.c,v 1.256 2006/02/04 11:10:58 debug Exp $
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37
38 #include "console.h"
39 #include "cpu.h"
40 #include "device.h"
41 #include "diskimage.h"
42 #include "emul.h"
43 #include "machine.h"
44 #include "misc.h"
45
46
47 extern volatile int single_step;
48 extern int force_debugger_at_exit;
49 extern int show_opcode_statistics;
50
51 extern int optind;
52 extern char *optarg;
53
54 int extra_argc;
55 char **extra_argv;
56 char *progname;
57
58 int fully_deterministic = 0;
59 int dyntrans_backend_enable = 1;
60
61
62 /*****************************************************************************
63 *
64 * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
65 * The global variable quiet_mode can be used to suppress the output
66 * of debug(), but not the output of fatal().
67 *
68 *****************************************************************************/
69
70 int verbose = 0;
71 int quiet_mode = 0;
72
73 static int debug_indent = 0;
74 static int debug_currently_at_start_of_line = 1;
75
76
77 /*
78 * va_debug():
79 *
80 * Used internally by debug() and fatal().
81 */
82 static void va_debug(va_list argp, char *fmt)
83 {
84 char buf[DEBUG_BUFSIZE + 1];
85 char *s;
86 int i;
87
88 buf[0] = buf[DEBUG_BUFSIZE] = 0;
89 vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
90
91 s = buf;
92 while (*s) {
93 if (debug_currently_at_start_of_line) {
94 for (i=0; i<debug_indent; i++)
95 printf(" ");
96 }
97
98 printf("%c", *s);
99
100 debug_currently_at_start_of_line = 0;
101 if (*s == '\n' || *s == '\r')
102 debug_currently_at_start_of_line = 1;
103 s++;
104 }
105 }
106
107
108 /*
109 * debug_indentation():
110 *
111 * Modify the debug indentation.
112 */
113 void debug_indentation(int diff)
114 {
115 debug_indent += diff;
116 if (debug_indent < 0)
117 fprintf(stderr, "WARNING: debug_indent less than 0!\n");
118 }
119
120
121 /*
122 * debug():
123 *
124 * Debug output (ignored if quiet_mode is set).
125 */
126 void debug(char *fmt, ...)
127 {
128 va_list argp;
129
130 if (quiet_mode)
131 return;
132
133 va_start(argp, fmt);
134 va_debug(argp, fmt);
135 va_end(argp);
136 }
137
138
139 /*
140 * fatal():
141 *
142 * Fatal works like debug(), but doesn't care about the quiet_mode
143 * setting.
144 */
145 void fatal(char *fmt, ...)
146 {
147 va_list argp;
148
149 va_start(argp, fmt);
150 va_debug(argp, fmt);
151 va_end(argp);
152 }
153
154
155 /*****************************************************************************/
156
157
158 /*
159 * internal_w():
160 *
161 * For internal use by gxemul itself.
162 */
163 void internal_w(char *arg)
164 {
165 if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
166 fprintf(stderr, "-W is for internal use by gxemul,"
167 " not for manual use.\n");
168 exit(1);
169 }
170
171 arg += 2;
172
173 switch (arg[0]) {
174 case 'S':
175 console_slave(arg + 1);
176 break;
177 default:
178 fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
179 arg);
180 }
181 }
182
183
184 /*****************************************************************************/
185
186
187 /*
188 * usage():
189 *
190 * Prints program usage to stdout.
191 */
192 static void usage(int longusage)
193 {
194 printf("GXemul");
195 #ifdef VERSION
196 printf("-" VERSION);
197 #endif
198 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
199 printf("Read the source code and/or documentation for "
200 "other Copyright messages.\n");
201
202 printf("\nusage: %s [machine, other, and general options] [file "
203 "[...]]\n", progname);
204 printf(" or %s [general options] @configfile\n", progname);
205 printf(" or %s [userland, other, and general options] file "
206 "[args ...]\n", progname);
207
208 if (!longusage) {
209 printf("\nRun %s -h for help on command line options.\n",
210 progname);
211 return;
212 }
213
214 printf("\nMachine selection options:\n");
215 printf(" -E t try to emulate machine type t. (Use -H to get "
216 "a list of types.)\n");
217 printf(" -e st try to emulate machine subtype st. (Use this "
218 "with -E.)\n");
219
220 printf("\nOther options:\n");
221 printf(" -A disable alignment checks in some cases (for higher"
222 " speed)\n");
223 #if defined(BINTRANS) || defined(DYNTRANS_BACKEND)
224 printf(" -B disable native translation backends. (translation"
225 " is turned on\n by default, if it is supposed for "
226 "the particular host)\n");
227 #endif
228 printf(" -C x try to emulate a specific CPU. (Use -H to get a "
229 "list of types.)\n");
230 printf(" -d fname add fname as a disk image. You can add \"xxx:\""
231 " as a prefix\n");
232 printf(" where xxx is one or more of the following:\n");
233 printf(" b specifies that this is the boot"
234 " device\n");
235 printf(" c CD-ROM\n");
236 printf(" d DISK\n");
237 printf(" f FLOPPY\n");
238 printf(" gH;S; set geometry to H heads and S"
239 " sectors-per-track\n");
240 printf(" i IDE\n");
241 printf(" r read-only (don't allow changes to the"
242 " file)\n");
243 printf(" s SCSI\n");
244 printf(" t tape\n");
245 printf(" 0-7 force a specific ID\n");
246 printf(" -I x emulate clock interrupts at x Hz (affects"
247 " rtc devices only, not\n");
248 printf(" actual runtime speed) (this disables automatic"
249 " clock adjustments)\n");
250 printf(" -i display each instruction as it is executed\n");
251 printf(" -J disable some speed tricks\n");
252 printf(" -j name set the name of the kernel, for example:\n");
253 printf(" -j netbsd for NetBSD/pmax\n");
254 printf(" -j bsd for OpenBSD/pmax\n");
255 printf(" -j vmunix for Ultrix/RISC\n");
256 printf(" -M m emulate m MBs of physical RAM\n");
257 printf(" -m nr run at most nr instructions (on any cpu)\n");
258 printf(" -N display nr of instructions/second average, at"
259 " regular intervals\n");
260 printf(" -n nr set nr of CPUs (for SMP experiments)\n");
261 printf(" -O force netboot (tftp instead of disk), even when"
262 " a disk image is\n"
263 " present (for DECstation, SGI, and ARC emulation)\n");
264 printf(" -o arg set the boot argument (for DEC, ARC, or SGI"
265 " emulation).\n");
266 printf(" Default arg for DEC is '-a', for ARC '-aN'.\n");
267 printf(" -p pc add a breakpoint (remember to use the '0x' "
268 "prefix for hex!)\n");
269 printf(" -Q no built-in PROM emulation (use this for "
270 "running ROM images)\n");
271 printf(" -R use random bootstrap cpu, instead of nr 0\n");
272 printf(" -r register dumps before every instruction\n");
273 printf(" -S initialize emulated RAM to random bytes, "
274 "instead of zeroes\n");
275 printf(" -T enter the single-step debugger on "
276 "unimplemented memory accesses\n");
277 printf(" -t show function trace tree\n");
278 printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
279 #ifdef WITH_X11
280 printf(" -X use X11\n");
281 #endif /* WITH_X11 */
282 printf(" -x open up new xterms for emulated serial ports "
283 "(default is on when\n using configuration files or"
284 " when X11 is used, off otherwise)\n");
285 #ifdef WITH_X11
286 printf(" -Y n scale down framebuffer windows by n x n times\n");
287 #endif /* WITH_X11 */
288 printf(" -y x set max_random_cycles_per_chunk to x"
289 " (experimental)\n");
290 printf(" -Z n set nr of graphics cards, for emulating a "
291 "dual-head or tripple-head\n"
292 " environment (only for DECstation emulation)\n");
293 printf(" -z disp add disp as an X11 display to use for "
294 "framebuffers\n");
295
296 printf("\nUserland options:\n");
297 printf(" -u emul userland-only (syscall) emulation (use -H to"
298 " get a list of\n available emulation modes)\n");
299
300 printf("\nGeneral options:\n");
301 printf(" -c cmd add cmd as a command to run before starting "
302 "the simulation\n");
303 printf(" -D guarantee fully deterministic behaviour\n");
304 printf(" -H display a list of possible CPU and "
305 "machine types\n");
306 printf(" -h display this help message\n");
307 printf(" -K force the debugger to be entered at the end "
308 "of a simulation\n");
309 printf(" -q quiet mode (don't print startup messages)\n");
310 printf(" -s show opcode usage statistics after simulation\n");
311 printf(" -V start up in the single-step debugger, paused\n");
312 printf(" -v verbose debug messages\n");
313 printf("\n");
314 printf("If you are selecting a machine type to emulate directly "
315 "on the command line,\nthen you must specify one or more names"
316 " of files that you wish to load into\n"
317 "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
318 "where syms is the text produced by running 'nm' (or 'nm -S') "
319 "on a binary.\n"
320 "To load a raw binary into memory, add \"address:\" in front "
321 "of the filename,\n"
322 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
323 "Examples:\n"
324 " 0xbfc00000:rom.bin for a raw ROM image\n"
325 " 0xbfc00000:0x100:rom.bin for an image with "
326 "0x100 bytes header\n"
327 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
328 "start with pc=0xbfc00884\n");
329 }
330
331
332 /*
333 * get_cmd_args():
334 *
335 * Reads command line arguments.
336 */
337 int get_cmd_args(int argc, char *argv[], struct emul *emul,
338 char ***diskimagesp, int *n_diskimagesp)
339 {
340 int ch, res, using_switch_d = 0, using_switch_Z = 0;
341 char *type = NULL, *subtype = NULL;
342 int n_cpus_set = 0;
343 int msopts = 0; /* Machine-specific options used */
344 struct machine *m = emul_add_machine(emul, "default");
345
346 while ((ch = getopt(argc, argv, "ABC:c:Dd:E:e:HhI:iJj:KM:m:"
347 "Nn:Oo:p:QqRrSsTtUu:VvW:XxY:y:Z:z:")) != -1) {
348 switch (ch) {
349 case 'A':
350 m->dyntrans_alignment_check = 0;
351 msopts = 1;
352 break;
353 case 'B':
354 /* Turns off both bintrans and dyntrans. */
355 m->bintrans_enable = 0;
356 dyntrans_backend_enable = 0;
357 msopts = 1;
358 break;
359 case 'C':
360 m->cpu_name = strdup(optarg);
361 msopts = 1;
362 break;
363 case 'c':
364 emul->n_debugger_cmds ++;
365 emul->debugger_cmds = realloc(emul->debugger_cmds,
366 emul->n_debugger_cmds * sizeof(char *));
367 if (emul->debugger_cmds == NULL) {
368 fatal("out of memory\n");
369 exit(1);
370 }
371 emul->debugger_cmds[emul->n_debugger_cmds-1] =
372 strdup(optarg);
373 break;
374 case 'D':
375 fully_deterministic = 1;
376 break;
377 case 'd':
378 /* diskimage_add() is called further down */
379 (*n_diskimagesp) ++;
380 (*diskimagesp) = realloc(*diskimagesp,
381 sizeof(char *) * (*n_diskimagesp));
382 if (*diskimagesp == NULL) {
383 fprintf(stderr, "out of memory\n");
384 exit(1);
385 }
386 (*diskimagesp)[(*n_diskimagesp) - 1] = strdup(optarg);
387 using_switch_d = 1;
388 msopts = 1;
389 break;
390 case 'E':
391 type = optarg;
392 msopts = 1;
393 break;
394 case 'e':
395 subtype = optarg;
396 msopts = 1;
397 break;
398 case 'H':
399 machine_list_available_types_and_cpus();
400 exit(1);
401 case 'h':
402 usage(1);
403 exit(1);
404 case 'I':
405 m->emulated_hz = atoi(optarg);
406 m->automatic_clock_adjustment = 0;
407 msopts = 1;
408 break;
409 case 'i':
410 m->instruction_trace = 1;
411 msopts = 1;
412 break;
413 case 'J':
414 m->speed_tricks = 0;
415 msopts = 1;
416 break;
417 case 'j':
418 m->boot_kernel_filename = strdup(optarg);
419 if (m->boot_kernel_filename == NULL) {
420 fprintf(stderr, "out of memory\n");
421 exit(1);
422 }
423 msopts = 1;
424 break;
425 case 'K':
426 force_debugger_at_exit = 1;
427 break;
428 case 'M':
429 m->physical_ram_in_mb = atoi(optarg);
430 msopts = 1;
431 break;
432 case 'm':
433 m->max_instructions = atoi(optarg);
434 msopts = 1;
435 break;
436 case 'N':
437 m->show_nr_of_instructions = 1;
438 msopts = 1;
439 break;
440 case 'n':
441 m->ncpus = atoi(optarg);
442 n_cpus_set = 1;
443 msopts = 1;
444 break;
445 case 'O':
446 m->force_netboot = 1;
447 msopts = 1;
448 break;
449 case 'o':
450 m->boot_string_argument = strdup(optarg);
451 if (m->boot_string_argument == NULL) {
452 fprintf(stderr, "out of memory\n");
453 exit(1);
454 }
455 msopts = 1;
456 break;
457 case 'p':
458 if (m->n_breakpoints >= MAX_BREAKPOINTS) {
459 fprintf(stderr, "too many breakpoints\n");
460 exit(1);
461 }
462 m->breakpoint_string[m->n_breakpoints] = strdup(optarg);
463 if (m->breakpoint_string[m->n_breakpoints] == NULL) {
464 fprintf(stderr, "out of memory\n");
465 exit(1);
466 }
467 m->breakpoint_flags[m->n_breakpoints] = 0;
468 m->n_breakpoints ++;
469 msopts = 1;
470 break;
471 case 'Q':
472 m->prom_emulation = 0;
473 msopts = 1;
474 break;
475 case 'q':
476 quiet_mode = 1;
477 break;
478 case 'R':
479 m->use_random_bootstrap_cpu = 1;
480 msopts = 1;
481 break;
482 case 'r':
483 m->register_dump = 1;
484 msopts = 1;
485 break;
486 case 'S':
487 m->random_mem_contents = 1;
488 msopts = 1;
489 break;
490 case 's':
491 show_opcode_statistics = 1;
492 break;
493 case 'T':
494 m->single_step_on_bad_addr = 1;
495 msopts = 1;
496 break;
497 case 't':
498 m->show_trace_tree = 1;
499 msopts = 1;
500 break;
501 case 'U':
502 m->slow_serial_interrupts_hack_for_linux = 1;
503 msopts = 1;
504 break;
505 case 'u':
506 m->userland_emul = strdup(optarg);
507 if (m->userland_emul == NULL) {
508 fprintf(stderr, "out of memory\n");
509 exit(1);
510 }
511 m->machine_type = MACHINE_USERLAND;
512 msopts = 1;
513 break;
514 case 'V':
515 single_step = 1;
516 break;
517 case 'v':
518 verbose ++;
519 break;
520 case 'W':
521 internal_w(optarg);
522 exit(0);
523 case 'X':
524 m->use_x11 = 1;
525 msopts = 1;
526 /* FALL-THROUGH */
527 case 'x':
528 console_allow_slaves(1);
529 break;
530 case 'Y':
531 m->x11_scaledown = atoi(optarg);
532 if (m->x11_scaledown < -1) {
533 m->x11_scaleup = - m->x11_scaledown;
534 m->x11_scaledown = 1;
535 }
536 if (m->x11_scaledown < 1) {
537 fprintf(stderr, "Invalid scaledown value.\n");
538 exit(1);
539 }
540 msopts = 1;
541 break;
542 case 'y':
543 m->max_random_cycles_per_chunk = atoi(optarg);
544 msopts = 1;
545 break;
546 case 'Z':
547 m->n_gfx_cards = atoi(optarg);
548 using_switch_Z = 1;
549 msopts = 1;
550 break;
551 case 'z':
552 m->x11_n_display_names ++;
553 m->x11_display_names = realloc(
554 m->x11_display_names,
555 m->x11_n_display_names * sizeof(char *));
556 if (m->x11_display_names == NULL) {
557 fprintf(stderr, "out of memory\n");
558 exit(1);
559 }
560 m->x11_display_names[m->x11_n_display_names-1] =
561 strdup(optarg);
562 if (m->x11_display_names
563 [m->x11_n_display_names-1] == NULL) {
564 fprintf(stderr, "out of memory\n");
565 exit(1);
566 }
567 msopts = 1;
568 break;
569 default:
570 fprintf(stderr, "Run %s -h for help on command "
571 "line options.\n", progname);
572 exit(1);
573 }
574 }
575
576 if (type != NULL || subtype != NULL) {
577 if (type == NULL)
578 type = "";
579 if (subtype == NULL)
580 subtype = "";
581 res = machine_name_to_type(type, subtype,
582 &m->machine_type, &m->machine_subtype, &m->arch);
583 if (!res)
584 exit(1);
585 }
586
587 argc -= optind;
588 argv += optind;
589
590 extra_argc = argc;
591 extra_argv = argv;
592
593
594 if (m->machine_type == MACHINE_NONE && msopts) {
595 fprintf(stderr, "Machine specific options used directly on "
596 "the command line, but no machine\nemulation specified?\n");
597 exit(1);
598 }
599
600
601 /* -i and -r are pretty verbose: */
602
603 if (m->instruction_trace && !verbose) {
604 fprintf(stderr, "Implicitly %sturning on -v, because"
605 " of -i\n", quiet_mode? "turning off -q and " : "");
606 verbose = 1;
607 quiet_mode = 0;
608 }
609
610 if (m->register_dump && !verbose) {
611 fprintf(stderr, "Implicitly %sturning on -v, because"
612 " of -r\n", quiet_mode? "turning off -q and " : "");
613 verbose = 1;
614 quiet_mode = 0;
615 }
616
617 if ((m->instruction_trace || m->register_dump || m->show_trace_tree)
618 && m->bintrans_enable) {
619 if (m->arch == ARCH_MIPS)
620 fprintf(stderr, "Implicitly turning off bintrans.\n");
621 m->bintrans_enable = 0;
622 }
623
624
625 /*
626 * Usually, an executable filename must be supplied.
627 *
628 * However, it is possible to boot directly from a harddisk image
629 * file. If no kernel is supplied, but a diskimage is being used,
630 * then try to boot from disk.
631 */
632 if (extra_argc == 0) {
633 if (using_switch_d) {
634 /* Booting directly from a disk image... */
635 } else {
636 usage(0);
637 fprintf(stderr, "\nNo filename given. Aborting.\n");
638 exit(1);
639 }
640 } else if (m->boot_kernel_filename[0] == '\0') {
641 /*
642 * Default boot_kernel_filename is "", which can be overriden
643 * by the -j command line option. If it is still "" here,
644 * and we're not booting directly from a disk image, then
645 * try to set it to the last part of the last file name
646 * given on the command line. (Last part = the stuff after
647 * the last slash.)
648 */
649 char *s = extra_argv[extra_argc - 1];
650 char *s2;
651
652 s2 = strrchr(s, '/');
653 if (s2 == NULL)
654 s2 = s;
655 else
656 s2 ++;
657
658 m->boot_kernel_filename = strdup(s2);
659 if (m->boot_kernel_filename == NULL) {
660 fprintf(stderr, "out of memory\n");
661 exit(1);
662 }
663 }
664
665 if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
666 fprintf(stderr, "Bad number of gfx cards (-Z).\n");
667 exit(1);
668 }
669
670 #ifndef EXPERIMENTAL_NEWMIPS
671 if (m->bintrans_enable && m->arch == ARCH_MIPS) {
672 m->speed_tricks = 0;
673 /* TODO: Print a warning about this? */
674 }
675 #endif
676
677 if (m->n_breakpoints > 0 &&
678 m->bintrans_enable && m->arch == ARCH_MIPS) {
679 fprintf(stderr, "Breakpoints and MIPS binary translation "
680 "don't work too well together right now.\n");
681 exit(1);
682 }
683
684 #ifndef BINTRANS
685 if (m->bintrans_enable) {
686 fprintf(stderr, "WARNING: %s was compiled without "
687 "bintrans support. Ignoring -b.\n", progname);
688 m->bintrans_enable = 0;
689 }
690 #endif
691
692 #ifndef WITH_X11
693 if (m->use_x11) {
694 fprintf(stderr, "WARNING: %s was compiled without "
695 "X11 support. Ignoring -X.\n", progname);
696 m->use_x11 = 0;
697 }
698 #endif
699
700 if (!using_switch_Z && !m->use_x11)
701 m->n_gfx_cards = 0;
702
703 m->bintrans_enabled_from_start = m->bintrans_enable;
704
705 return 0;
706 }
707
708
709 /*
710 * main():
711 *
712 * Two kinds of emulations are started from here:
713 *
714 * o) Simple emulations, using command line arguments, compatible with
715 * earlier version of GXemul/mips64emul.
716 *
717 * o) Emulations set up by parsing special config files. (0 or more.)
718 */
719 int main(int argc, char *argv[])
720 {
721 struct emul **emuls;
722 char **diskimages = NULL;
723 int n_diskimages = 0;
724 int n_emuls;
725 int i;
726
727 progname = argv[0];
728
729 console_init();
730 cpu_init();
731 device_init();
732 machine_init();
733 useremul_init();
734
735 emuls = malloc(sizeof(struct emul *));
736 if (emuls == NULL) {
737 fprintf(stderr, "out of memory\n");
738 exit(1);
739 }
740
741 /* Allocate space for a simple emul setup: */
742 n_emuls = 1;
743 emuls[0] = emul_new(NULL);
744 if (emuls[0] == NULL) {
745 fprintf(stderr, "out of memory\n");
746 exit(1);
747 }
748
749 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
750
751 if (!fully_deterministic) {
752 /* TODO: More than just time(). Use gettimeofday(). */
753 srandom(time(NULL) ^ (getpid() << 12));
754 } else {
755 /* Fully deterministic. -I must have been supplied. */
756 if (emuls[0]->machines[0]->automatic_clock_adjustment) {
757 fatal("Cannot have -D without -I.\n");
758 exit(1);
759 }
760 }
761
762 /* Print startup message: */
763 debug("GXemul");
764 #ifdef VERSION
765 debug("-" VERSION);
766 #endif
767 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
768 debug("Read the source code and/or documentation for "
769 "other Copyright messages.\n\n");
770
771 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE)
772 n_emuls --;
773 else {
774 for (i=0; i<n_diskimages; i++)
775 diskimage_add(emuls[0]->machines[0], diskimages[i]);
776 }
777
778 /* Simple initialization, from command line arguments: */
779 if (n_emuls > 0) {
780 /* Make sure that there are no configuration files as well: */
781 for (i=1; i<argc; i++)
782 if (argv[i][0] == '@') {
783 fprintf(stderr, "You can either start one "
784 "emulation with one machine directly from "
785 "the command\nline, or start one or more "
786 "emulations using configuration files."
787 " Not both.\n");
788 exit(1);
789 }
790
791 /* Initialize one emul: */
792 emul_simple_init(emuls[0]);
793 }
794
795 /* Initialize emulations from config files: */
796 for (i=1; i<argc; i++) {
797 if (argv[i][0] == '@') {
798 char *s = argv[i] + 1;
799 if (strlen(s) == 0 && i+1 < argc &&
800 argv[i+1][0] != '@') {
801 i++;
802 s = argv[i];
803 }
804 n_emuls ++;
805 emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
806 if (emuls == NULL) {
807 fprintf(stderr, "out of memory\n");
808 exit(1);
809 }
810
811 /* Always allow slave xterms when using multiple
812 emulations: */
813 console_allow_slaves(1);
814
815 emuls[n_emuls - 1] =
816 emul_create_from_configfile(s);
817 }
818 }
819
820 if (n_emuls == 0) {
821 fprintf(stderr, "No emulations defined. Maybe you forgot to "
822 "use -E xx and/or -e yy, to specify\nthe machine type."
823 " For example:\n\n %s -e 3max -d disk.img\n\n"
824 "to boot an emulated DECstation 5000/200 with a disk "
825 "image.\n", progname);
826 exit(1);
827 }
828
829 device_set_exit_on_error(0);
830 console_warn_if_slaves_are_needed(1);
831
832 /* Run all emulations: */
833 emul_run(emuls, n_emuls);
834
835 return 0;
836 }
837

  ViewVC Help
Powered by ViewVC 1.1.26