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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26