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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26