X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=minsk.c;h=419ce0d9c3bbcb0b43800f109bf68b551965db3d;hb=1383ce852dfc0c85de03e8e0ab838090b7fcd679;hp=d9606ef3b424ed857d14cb1b5f448dd47cfd48e1;hpb=9946bcb5ab6feccc486e8ca41d39758e9125f950;p=minsk.git diff --git a/minsk.c b/minsk.c index d9606ef..419ce0d 100644 --- a/minsk.c +++ b/minsk.c @@ -4,11 +4,6 @@ * (c) 2010 Martin Mares */ -/* - * TODO: - * - we probably have to disable NOP - */ - /* * Things that are not implemented: * @@ -20,6 +15,10 @@ */ #define _GNU_SOURCE +#define UNUSED __attribute__((unused)) +#define NORETURN __attribute__((noreturn)) + +#undef ENABLE_DAEMON_MODE #include #include @@ -28,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 @@ -170,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); } @@ -188,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] == '@') { @@ -214,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; } @@ -227,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++) { @@ -236,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; } @@ -252,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"); @@ -374,15 +386,13 @@ static void print_ins(int x, int y) eat = 1; break; case 4: // One Russian symbol - bit = 6; - fmt = "r"; + fmt = "xr"; break; case 5: // Russian text fmt = "xrrrrrr"; break; case 6: // One Latin symbol - bit = 6; - fmt = "l"; + fmt = "xl"; break; default: // Latin text fmt = "xllllll"; @@ -439,7 +449,7 @@ static void print_ins(int x, int y) linebuf[pos] = ch; pos = (pos+1) & 0177; } - assert(!bit); + assert(bit >= 0); } static void run(void) @@ -799,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 @@ -826,17 +849,9 @@ static void run(void) #define TBF_MAX 5 // Max number of tokens in the bucket #define TBF_REFILL_PER_SEC 0.2 // Bucket refill rate (buckets/sec) -#define PID_FILE "/var/run/minsk.pid" -#define UID 65534 -#define GID 65534 - -static void die(char *msg) -{ - fprintf(stderr, "minsk: "); - fprintf(stderr, msg); - fputc('\n', stderr); - exit(1); -} +#define PID_FILE "/var/run/pd-minsk.pid" +#define UID 124 +#define GID 125 static char **spt_argv; static char *spt_start, *spt_end; @@ -898,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)); @@ -1232,20 +1247,113 @@ static void run_as_daemon(int do_fork) } } -int main(int argc, char **argv) +#else + +static void run_as_daemon(int do_fork UNUSED) +{ + die("Daemon mode not supported in this version, need to recompile."); +} + +static void setproctitle_init(int argc UNUSED, char **argv UNUSED) +{ +} + +#endif + +static void init_memory(int set_password) { - if (argc > 1) + 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 - 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