X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=minsk.c;h=419ce0d9c3bbcb0b43800f109bf68b551965db3d;hb=1383ce852dfc0c85de03e8e0ab838090b7fcd679;hp=2532dbaca97314b3dd13a0171ee2ab8012bb3c2d;hpb=903635d2b5f9f7d98c71ba1932a156e19b9f005e;p=minsk.git diff --git a/minsk.c b/minsk.c index 2532dba..419ce0d 100644 --- a/minsk.c +++ b/minsk.c @@ -15,6 +15,10 @@ */ #define _GNU_SOURCE +#define UNUSED __attribute__((unused)) +#define NORETURN __attribute__((noreturn)) + +#undef ENABLE_DAEMON_MODE #include #include @@ -23,15 +27,18 @@ #include #include #include +#include static int trace; static int cpu_quota = -1; static int print_quota = -1; +static int english; static void (*error_hook)(char *msg); // Minsk-2 has 37-bit words in sign-magnitude representation (bit 36 = sign) typedef unsigned long long int word; +#define MEM_SIZE 4096 #define WORD_MASK 01777777777777ULL #define SIGN_MASK 01000000000000ULL #define VAL_MASK 00777777777777ULL @@ -165,11 +172,15 @@ static void wr(int addr, word val) static int lino; -static void parse_error(char *msg) +NORETURN static void parse_error(char *russian_msg, char *english_msg) { if (error_hook) error_hook("Parse error"); - printf("Ошибка входа (стр. %d): %s\n", lino, msg); + + if (english) + printf("Parse error (line %d): %s\n", lino, english_msg); + else + printf("Ошибка входа (стр. %d): %s\n", lino, russian_msg); exit(0); } @@ -183,20 +194,17 @@ static void parse_in(void) lino++; char *eol = strchr(line, '\n'); if (!eol) - parse_error("Строка слишком долгая"); + parse_error("Строка слишком долгая", "Line too long"); *eol = 0; + if (eol > line && eol[-1] == '\r') + *--eol = 0; char *c = line; if (!c[0] || c[0] == ';') - { - if (!strncmp(c, ";daji_zor_i_litva=", 18)) - { - trace = atoi(c+18); - if (error_hook) - error_hook("Secret tracing switch flipped"); - } - continue; - } + continue; + + if (c[0] == '.') + return; if (c[0] == '@') { @@ -209,12 +217,12 @@ static void parse_in(void) if (*c >= '0' && *c <= '7') addr = 8*addr + *c++ - '0'; else - parse_error("Плохая цифра"); + parse_error("Плохая цифра", "Invalid number"); } while (*c == ' ') c++; if (*c) - parse_error("Адрес слишком долгий"); + parse_error("Адрес слишком долгий", "Address too long"); continue; } @@ -222,7 +230,7 @@ static void parse_in(void) if (*c == '-') w = 1; else if (*c != '+') - parse_error("Плохой знак"); + parse_error("Плохой знак", "Invalid sign"); c++; for (int i=0; i<12; i++) { @@ -231,12 +239,12 @@ static void parse_in(void) if (*c >= '0' && *c <= '7') w = 8*w + *c++ - '0'; else - parse_error("Плохая цифра"); + parse_error("Плохая цифра", "Invalid number"); } while (*c == ' ') c++; if (*c) - parse_error("Номер слишком долгий"); + parse_error("Номер слишком долгий", "Number too long"); wr(addr++, w); addr &= 07777; } @@ -247,27 +255,36 @@ static word r1, r2, current_ins; static int ip = 00050; // Standard program start location static int prev_ip; -static void stop(char *reason, char *notice) +NORETURN static void stop(char *russian_reason, char *english_reason) { if (error_hook) - error_hook(notice); - printf("Машина остановлена -- %s\n", reason); - printf("СчАК:%04o См:%c%012llo Р1:%c%012llo Р2:%c%012llo\n", prev_ip, WF(acc), WF(r1), WF(r2)); + error_hook(english_reason); + + if (english) + { + printf("System stopped -- %s\n", english_reason); + printf("IP:%04o ACC:%c%012llo R1:%c%012llo R2:%c%012llo\n", prev_ip, WF(acc), WF(r1), WF(r2)); + } + else + { + printf("Машина остановлена -- %s\n", russian_reason); + printf("СчАК:%04o См:%c%012llo Р1:%c%012llo Р2:%c%012llo\n", prev_ip, WF(acc), WF(r1), WF(r2)); + } exit(0); } -static void over(void) +NORETURN static void over(void) { stop("Аварийный останов", "Overflow"); } -static void notimp(void) +NORETURN static void notimp(void) { acc = current_ins; stop("Устройство разбитое", "Not implemented"); } -static void noins(void) +NORETURN static void noins(void) { acc = current_ins; stop("Эту команду не знаю", "Illegal instruction"); @@ -792,8 +809,21 @@ static void run(void) } } +NORETURN static void die(char *msg) +{ + fprintf(stderr, "minsk: %s\n", msg); + exit(1); +} + /*** Daemon interface ***/ +#ifdef ENABLE_DAEMON_MODE + +/* + * The daemon mode was a quick hack for the Po drate contest. + * Most parameters are hard-wired. + */ + #include #include #include @@ -823,14 +853,6 @@ static void run(void) #define UID 124 #define GID 125 -static void die(char *msg) -{ - fprintf(stderr, "minsk: "); - fprintf(stderr, msg); - fputc('\n', stderr); - exit(1); -} - static char **spt_argv; static char *spt_start, *spt_end; @@ -891,11 +913,11 @@ setproctitle(const char *msg, ...) va_end(args); } -static void sigchld_handler(int sig __attribute__((unused))) +static void sigchld_handler(int sig UNUSED) { } -static void sigalrm_handler(int sig __attribute__((unused))) +static void sigalrm_handler(int sig UNUSED) { const char err[] = "--- Timed out. Time machine disconnected. ---\n"; write(1, err, sizeof(err)); @@ -1225,37 +1247,112 @@ static void run_as_daemon(int do_fork) } } -static void init_memory(void) +#else + +static void run_as_daemon(int do_fork UNUSED) { - // For the contest, we fill the whole memory with -00 00 0000 0000 (HALT), - // not +00 00 0000 0000 (NOP). Otherwise, an empty program would reveal - // the location of the password :) - for (int i=0; i<4096; i++) - mem[i] = 01000000000000ULL; - - // Store the password - int pos = 02655; - mem[pos++] = 0574060565373; - mem[pos++] = 0371741405340; - mem[pos++] = 0534051524017; + die("Daemon mode not supported in this version, need to recompile."); } -int main(int argc, char **argv) +static void setproctitle_init(int argc UNUSED, char **argv UNUSED) { - init_memory(); +} - if (argc > 1) +#endif + +static void init_memory(int set_password) +{ + if (set_password) { - setproctitle_init(argc, argv); - if (!strcmp(argv[1], "--daemon")) - run_as_daemon(1); - else if (!strcmp(argv[1], "--net")) - run_as_daemon(0); - else if (!strncmp(argv[1], "--trace=", 8)) - trace = atoi(argv[1] + 8); - else - die("Usage: minsk [--daemon | --net]"); + // For the contest, we fill the whole memory with -00 00 0000 0000 (HALT), + // not +00 00 0000 0000 (NOP). Otherwise, an empty program would reveal + // the location of the password :) + for (int i=0; i