1 |
/* |
/* |
2 |
* Copyright (C) 2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: emul_parse.c,v 1.32 2005/06/24 09:33:34 debug Exp $ |
* $Id: emul_parse.c,v 1.45 2006/12/30 13:30:52 debug Exp $ |
29 |
* |
* |
30 |
* Set up an emulation by parsing a config file. |
* Set up an emulation by parsing a config file. |
31 |
* |
* |
32 |
* TODO: This could be extended to support XML config files as well, but |
* TODO: REWRITE THIS FROM SCRATCH! :-) |
|
* XML is ugly. It is ugly right now as well. The question is: which |
|
|
* solution is the least ugly? |
|
33 |
*/ |
*/ |
34 |
|
|
35 |
#include <stdio.h> |
#include <stdio.h> |
47 |
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || \ |
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || \ |
48 |
ch == '_' || ch == '$' || (ch >= '0' && ch <= '9') ) |
ch == '_' || ch == '$' || (ch >= '0' && ch <= '9') ) |
49 |
|
|
50 |
|
#define MAX_WORD_LEN 200 |
51 |
|
|
52 |
#define EXPECT_WORD 1 |
#define EXPECT_WORD 1 |
53 |
#define EXPECT_LEFT_PARENTHESIS 2 |
#define EXPECT_LEFT_PARENTHESIS 2 |
54 |
#define EXPECT_RIGHT_PARENTHESIS 4 |
#define EXPECT_RIGHT_PARENTHESIS 4 |
55 |
|
|
56 |
|
static int parenthesis_level = 0; |
57 |
|
|
58 |
|
|
59 |
/* |
/* |
60 |
* read_one_word(): |
* read_one_word(): |
174 |
done = 1; |
done = 1; |
175 |
} else { |
} else { |
176 |
if ((expect & EXPECT_LEFT_PARENTHESIS) && ch == '(') { |
if ((expect & EXPECT_LEFT_PARENTHESIS) && ch == '(') { |
177 |
|
parenthesis_level ++; |
178 |
buf[curlen++] = ch; |
buf[curlen++] = ch; |
179 |
break; |
break; |
180 |
} |
} |
181 |
if ((expect & EXPECT_RIGHT_PARENTHESIS) && ch == ')') { |
if ((expect & EXPECT_RIGHT_PARENTHESIS) && ch == ')') { |
182 |
|
parenthesis_level --; |
183 |
buf[curlen++] = ch; |
buf[curlen++] = ch; |
184 |
break; |
break; |
185 |
} |
} |
214 |
static char cur_machine_bootname[150]; |
static char cur_machine_bootname[150]; |
215 |
static char cur_machine_bootarg[250]; |
static char cur_machine_bootarg[250]; |
216 |
static char cur_machine_slowsi[10]; |
static char cur_machine_slowsi[10]; |
|
static char cur_machine_debugger_on_badaddr[10]; |
|
217 |
static char cur_machine_prom_emulation[10]; |
static char cur_machine_prom_emulation[10]; |
218 |
static char cur_machine_use_x11[10]; |
static char cur_machine_use_x11[10]; |
219 |
static char cur_machine_x11_scaledown[10]; |
static char cur_machine_x11_scaledown[10]; |
|
static char cur_machine_bintrans[10]; |
|
|
static char cur_machine_old_bintrans[10]; |
|
|
static char cur_machine_bintrans_size[10]; |
|
220 |
static char cur_machine_byte_order[20]; |
static char cur_machine_byte_order[20]; |
221 |
static char cur_machine_random_mem[10]; |
static char cur_machine_random_mem[10]; |
222 |
static char cur_machine_random_cpu[10]; |
static char cur_machine_random_cpu[10]; |
256 |
} \ |
} \ |
257 |
} |
} |
258 |
|
|
259 |
|
static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line, |
260 |
|
int *parsestate, char *word, size_t maxbuflen); |
261 |
|
|
262 |
|
|
263 |
/* |
/* |
264 |
* parse_on_off(): |
* parse_on_off(): |
276 |
strcasecmp(s, "disable") == 0 || strcasecmp(s, "0") == 0) |
strcasecmp(s, "disable") == 0 || strcasecmp(s, "0") == 0) |
277 |
return 0; |
return 0; |
278 |
|
|
279 |
fatal("parse_on_off(): unknown value '%s'\n", s); |
fprintf(stderr, "parse_on_off(): WARNING: unknown value '%s'\n", s); |
|
exit(1); |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
* parse__none(): |
|
|
* |
|
|
* emul ( [...] ) |
|
|
*/ |
|
|
static void parse__none(struct emul *e, FILE *f, int *in_emul, int *line, |
|
|
int *parsestate, char *word, size_t maxbuflen) |
|
|
{ |
|
|
if (strcmp(word, "emul") == 0) { |
|
|
if (*in_emul) { |
|
|
fatal("line %i: only one emul per config " |
|
|
"file is supported!\n", *line); |
|
|
exit(1); |
|
|
} |
|
|
*parsestate = PARSESTATE_EMUL; |
|
|
*in_emul = 1; |
|
|
read_one_word(f, word, maxbuflen, |
|
|
line, EXPECT_LEFT_PARENTHESIS); |
|
|
return; |
|
|
} |
|
280 |
|
|
281 |
fatal("line %i: expecting 'emul', not '%s'\n", *line, word); |
return 0; |
|
exit(1); |
|
282 |
} |
} |
283 |
|
|
284 |
|
|
321 |
line, EXPECT_LEFT_PARENTHESIS); |
line, EXPECT_LEFT_PARENTHESIS); |
322 |
|
|
323 |
/* Default net: */ |
/* Default net: */ |
324 |
strlcpy(cur_net_ipv4net, "10.0.0.0", sizeof(cur_net_ipv4net)); |
strlcpy(cur_net_ipv4net, NET_DEFAULT_IPV4_MASK, |
325 |
strlcpy(cur_net_ipv4len, "8", sizeof(cur_net_ipv4len)); |
sizeof(cur_net_ipv4net)); |
326 |
|
snprintf(cur_net_ipv4len, sizeof(cur_net_ipv4len), "%i", |
327 |
|
NET_DEFAULT_IPV4_LEN); |
328 |
strlcpy(cur_net_local_port, "", sizeof(cur_net_local_port)); |
strlcpy(cur_net_local_port, "", sizeof(cur_net_local_port)); |
329 |
cur_net_n_remote = 0; |
cur_net_n_remote = 0; |
330 |
return; |
return; |
347 |
cur_machine_n_device = 0; |
cur_machine_n_device = 0; |
348 |
cur_machine_n_x11_disp = 0; |
cur_machine_n_x11_disp = 0; |
349 |
cur_machine_slowsi[0] = '\0'; |
cur_machine_slowsi[0] = '\0'; |
|
cur_machine_debugger_on_badaddr[0] = '\0'; |
|
350 |
cur_machine_prom_emulation[0] = '\0'; |
cur_machine_prom_emulation[0] = '\0'; |
351 |
cur_machine_use_x11[0] = '\0'; |
cur_machine_use_x11[0] = '\0'; |
352 |
cur_machine_x11_scaledown[0] = '\0'; |
cur_machine_x11_scaledown[0] = '\0'; |
|
cur_machine_bintrans[0] = '\0'; |
|
|
cur_machine_old_bintrans[0] = '\0'; |
|
|
cur_machine_bintrans_size[0] = '\0'; |
|
353 |
cur_machine_byte_order[0] = '\0'; |
cur_machine_byte_order[0] = '\0'; |
354 |
cur_machine_random_mem[0] = '\0'; |
cur_machine_random_mem[0] = '\0'; |
355 |
cur_machine_random_cpu[0] = '\0'; |
cur_machine_random_cpu[0] = '\0'; |
399 |
e->net = net_init(e, NET_INIT_FLAG_GATEWAY, |
e->net = net_init(e, NET_INIT_FLAG_GATEWAY, |
400 |
cur_net_ipv4net, atoi(cur_net_ipv4len), |
cur_net_ipv4net, atoi(cur_net_ipv4len), |
401 |
cur_net_remote, cur_net_n_remote, |
cur_net_remote, cur_net_n_remote, |
402 |
atoi(cur_net_local_port)); |
atoi(cur_net_local_port), NULL); |
403 |
|
|
404 |
if (e->net == NULL) { |
if (e->net == NULL) { |
405 |
fatal("line %i: fatal error: could not create" |
fatal("line %i: fatal error: could not create" |
482 |
m->slow_serial_interrupts_hack_for_linux = |
m->slow_serial_interrupts_hack_for_linux = |
483 |
parse_on_off(cur_machine_slowsi); |
parse_on_off(cur_machine_slowsi); |
484 |
|
|
|
if (!cur_machine_debugger_on_badaddr[0]) |
|
|
strlcpy(cur_machine_debugger_on_badaddr, "no", |
|
|
sizeof(cur_machine_debugger_on_badaddr)); |
|
|
m->single_step_on_bad_addr = |
|
|
parse_on_off(cur_machine_debugger_on_badaddr); |
|
|
|
|
485 |
if (!cur_machine_prom_emulation[0]) |
if (!cur_machine_prom_emulation[0]) |
486 |
strlcpy(cur_machine_prom_emulation, "yes", |
strlcpy(cur_machine_prom_emulation, "yes", |
487 |
sizeof(cur_machine_prom_emulation)); |
sizeof(cur_machine_prom_emulation)); |
513 |
} |
} |
514 |
} |
} |
515 |
|
|
|
if (!cur_machine_bintrans[0]) |
|
|
strlcpy(cur_machine_bintrans, "yes", |
|
|
sizeof(cur_machine_bintrans)); |
|
|
m->bintrans_enable = m->bintrans_enabled_from_start = |
|
|
parse_on_off(cur_machine_bintrans); |
|
|
|
|
|
if (!cur_machine_old_bintrans[0]) |
|
|
strlcpy(cur_machine_old_bintrans, "yes", |
|
|
sizeof(cur_machine_old_bintrans)); |
|
|
m->old_bintrans_enable = parse_on_off(cur_machine_old_bintrans); |
|
|
|
|
|
if (!m->bintrans_enable && m->old_bintrans_enable) { |
|
|
fatal("cannot use old bintrans when bintrans is" |
|
|
" disabled.\n"); |
|
|
exit(1); |
|
|
} |
|
|
|
|
|
/* TODO: Hm... */ |
|
|
if (m->bintrans_enable) |
|
|
m->speed_tricks = 0; |
|
|
|
|
|
if (cur_machine_bintrans_size[0]) |
|
|
m->bintrans_size = 1048576 * |
|
|
atoi(cur_machine_bintrans_size); |
|
|
|
|
516 |
if (!cur_machine_force_netboot[0]) |
if (!cur_machine_force_netboot[0]) |
517 |
strlcpy(cur_machine_force_netboot, "no", |
strlcpy(cur_machine_force_netboot, "no", |
518 |
sizeof(cur_machine_force_netboot)); |
sizeof(cur_machine_force_netboot)); |
540 |
if (cur_machine_emulated_hz[0]) { |
if (cur_machine_emulated_hz[0]) { |
541 |
m->emulated_hz = mystrtoull(cur_machine_emulated_hz, |
m->emulated_hz = mystrtoull(cur_machine_emulated_hz, |
542 |
NULL, 0); |
NULL, 0); |
|
m->automatic_clock_adjustment = 0; |
|
543 |
} |
} |
544 |
|
|
545 |
/* NOTE: Default nr of CPUs is 0: */ |
/* NOTE: Default nr of CPUs is 0: */ |
553 |
else { |
else { |
554 |
m->x11_scaledown = atoi(cur_machine_x11_scaledown); |
m->x11_scaledown = atoi(cur_machine_x11_scaledown); |
555 |
if (m->x11_scaledown < 0) { |
if (m->x11_scaledown < 0) { |
556 |
|
m->x11_scaleup = 0 - m->x11_scaledown; |
557 |
|
m->x11_scaledown = 1; |
558 |
|
} |
559 |
|
if (m->x11_scaledown < 1) { |
560 |
fprintf(stderr, "Invalid scaledown value" |
fprintf(stderr, "Invalid scaledown value" |
561 |
" (%i)\n", m->x11_scaledown); |
" (%i)\n", m->x11_scaledown); |
562 |
exit(1); |
exit(1); |
619 |
WORD("bootname", cur_machine_bootname); |
WORD("bootname", cur_machine_bootname); |
620 |
WORD("bootarg", cur_machine_bootarg); |
WORD("bootarg", cur_machine_bootarg); |
621 |
WORD("slow_serial_interrupts_hack_for_linux", cur_machine_slowsi); |
WORD("slow_serial_interrupts_hack_for_linux", cur_machine_slowsi); |
|
WORD("debugger_on_badaddr", cur_machine_debugger_on_badaddr); |
|
622 |
WORD("prom_emulation", cur_machine_prom_emulation); |
WORD("prom_emulation", cur_machine_prom_emulation); |
623 |
WORD("use_x11", cur_machine_use_x11); |
WORD("use_x11", cur_machine_use_x11); |
624 |
WORD("x11_scaledown", cur_machine_x11_scaledown); |
WORD("x11_scaledown", cur_machine_x11_scaledown); |
|
WORD("bintrans", cur_machine_bintrans); |
|
|
WORD("old_bintrans", cur_machine_old_bintrans); |
|
|
WORD("bintrans_size", cur_machine_bintrans_size); |
|
625 |
WORD("byte_order", cur_machine_byte_order); |
WORD("byte_order", cur_machine_byte_order); |
626 |
WORD("random_mem_contents", cur_machine_random_mem); |
WORD("random_mem_contents", cur_machine_random_mem); |
627 |
WORD("use_random_bootstrap_cpu", cur_machine_random_cpu); |
WORD("use_random_bootstrap_cpu", cur_machine_random_cpu); |
726 |
* |
* |
727 |
* Set up an emulation by parsing a config file. |
* Set up an emulation by parsing a config file. |
728 |
*/ |
*/ |
729 |
void emul_parse_config(struct emul *e, FILE *f) |
void emul_parse_config(struct emul *e, char *fname) |
730 |
{ |
{ |
731 |
char word[500]; |
FILE *f = fopen(fname, "r"); |
732 |
|
char word[MAX_WORD_LEN]; |
733 |
int in_emul = 0; |
int in_emul = 0; |
734 |
int line = 1; |
int line = 1; |
735 |
int parsestate = PARSESTATE_NONE; |
int parsestate = PARSESTATE_EMUL; |
736 |
|
|
737 |
/* debug("emul_parse_config()\n"); */ |
/* debug("emul_parse_config()\n"); */ |
738 |
|
if (f == NULL) { |
739 |
|
perror(fname); |
740 |
|
exit(1); |
741 |
|
} |
742 |
|
|
743 |
while (!feof(f)) { |
while (!feof(f)) { |
744 |
read_one_word(f, word, sizeof(word), &line, |
read_one_word(f, word, sizeof(word), &line, |
749 |
/* debug("word = '%s'\n", word); */ |
/* debug("word = '%s'\n", word); */ |
750 |
|
|
751 |
switch (parsestate) { |
switch (parsestate) { |
|
case PARSESTATE_NONE: |
|
|
parse__none(e, f, &in_emul, &line, &parsestate, |
|
|
word, sizeof(word)); |
|
|
break; |
|
752 |
case PARSESTATE_EMUL: |
case PARSESTATE_EMUL: |
753 |
parse__emul(e, f, &in_emul, &line, &parsestate, |
parse__emul(e, f, &in_emul, &line, &parsestate, |
754 |
word, sizeof(word)); |
word, sizeof(word)); |
761 |
parse__machine(e, f, &in_emul, &line, &parsestate, |
parse__machine(e, f, &in_emul, &line, &parsestate, |
762 |
word, sizeof(word)); |
word, sizeof(word)); |
763 |
break; |
break; |
764 |
|
case PARSESTATE_NONE: |
765 |
|
break; |
766 |
default: |
default: |
767 |
fatal("INTERNAL ERROR in emul_parse.c (" |
fatal("INTERNAL ERROR in emul_parse.c (" |
768 |
"parsestate %i is not imlemented yet?)\n", |
"parsestate %i is not imlemented yet?)\n", |
771 |
} |
} |
772 |
} |
} |
773 |
|
|
774 |
if (parsestate != PARSESTATE_NONE) { |
if (parenthesis_level != 0) { |
775 |
fatal("EOF but not enough right parentheses?\n"); |
fatal("EOF but not enough right parentheses?\n"); |
776 |
exit(1); |
exit(1); |
777 |
} |
} |
778 |
|
|
779 |
|
fclose(f); |
780 |
} |
} |
781 |
|
|