/[gxemul]/upstream/0.4.0/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.4.0/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26