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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26