]> mj.ucw.cz Git - minsk.git/blobdiff - minsk.c
Add short options
[minsk.git] / minsk.c
diff --git a/minsk.c b/minsk.c
index 4218a9f4214bb93888da4bedce7ac233c8bed16f..419ce0d9c3bbcb0b43800f109bf68b551965db3d 100644 (file)
--- a/minsk.c
+++ b/minsk.c
@@ -16,6 +16,7 @@
 
 #define _GNU_SOURCE
 #define UNUSED __attribute__((unused))
+#define NORETURN __attribute__((noreturn))
 
 #undef ENABLE_DAEMON_MODE
 
 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
@@ -169,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);
 }
 
@@ -187,7 +194,7 @@ 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;
@@ -210,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;
        }
 
@@ -223,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++)
        {
@@ -232,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;
     }
@@ -248,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");
@@ -793,11 +809,9 @@ static void run(void)
     }
 }
 
-static void die(char *msg)
+NORETURN static void die(char *msg)
 {
-  fprintf(stderr, "minsk: ");
-  fprintf(stderr, msg);
-  fputc('\n', stderr);
+  fprintf(stderr, "minsk: %s\n", msg);
   exit(1);
 }
 
@@ -1246,39 +1260,53 @@ static void setproctitle_init(int argc UNUSED, char **argv UNUSED)
 
 #endif
 
-static void init_memory(void)
+static void init_memory(int set_password)
 {
-  // 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;
+  if (set_password)
+    {
+      // 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<MEM_SIZE; i++)
+        mem[i] = 01000000000000ULL;
+
+      // Store the password
+      int pos = 02655;
+      mem[pos++] = 0574060565373;
+      mem[pos++] = 0371741405340;
+      mem[pos++] = 0534051524017;
+    }
+  else
+    for (int i=0; i<MEM_SIZE; i++)
+      mem[i] = 00000000000000ULL;
 }
 
 static const struct option longopts[] = {
-  { "cpu-quota",       1, NULL, 'q' },
-  { "daemon",          0, NULL, 'd' },
-  { "nofork",          0, NULL, 'n' },
-  { "print-quota",     1, NULL, 'p' },
-  { "trace",           1, NULL, 't' },
-  { NULL,              0, NULL, 0   },
+  { "cpu-quota",       required_argument,      NULL, 'q' },
+  { "daemon",          no_argument,            NULL, 'd' },
+  { "nofork",          no_argument,            NULL, 'n' },
+  { "english",         no_argument,            NULL, 'e' },
+  { "set-password",    no_argument,            NULL, 's' },
+  { "print-quota",     required_argument,      NULL, 'p' },
+  { "trace",           required_argument,      NULL, 't' },
+  { NULL,              0,                      NULL, 0   },
 };
 
 static void usage(void)
 {
+  fprintf(stderr, "Options:\n\n");
+  #ifdef ENABLE_DAEMON_MODE
   fprintf(stderr, "\
-Options:\n\n\
---daemon               Run as daemon and listen for network connections\n\
---nofork               When run with --daemon, avoid forking\n\
---trace=<level>                Enable tracing of program execution\n\
---cpu-quota=<n>                Set CPU quota to <n> instructions\n\
---print-quota=<n>      Set printer quota to <n> lines\n\
+-d, --daemon           Run as daemon and listen for network connections\n\
+-n, --nofork           When run with --daemon, avoid forking\n\
+");
+  #endif
+  fprintf(stderr, "\
+-e, --english          Print messages in English\n\
+-s, --set-password     Put hidden password in memory\n\
+-t, --trace=<level>    Enable tracing of program execution\n\
+-q, --cpu-quota=<n>    Set CPU quota to <n> instructions\n\
+-p, --print-quota=<n>  Set printer quota to <n> lines\n\
 ");
   exit(1);
 }
@@ -1288,8 +1316,9 @@ int main(int argc, char **argv)
   int opt;
   int daemon_mode = 0;
   int do_fork = 1;
+  int set_password = 0;
 
-  while ((opt = getopt_long(argc, argv, "", longopts, NULL)) >= 0)
+  while ((opt = getopt_long(argc, argv, "q:desnp:t:", longopts, NULL)) >= 0)
     switch (opt)
       {
       case 'd':
@@ -1298,6 +1327,12 @@ int main(int argc, char **argv)
       case 'n':
        do_fork = 0;
        break;
+      case 'e':
+       english = 1;
+       break;
+      case 's':
+       set_password = 1;
+       break;
       case 'p':
        print_quota = atoi(optarg);
        break;
@@ -1314,7 +1349,7 @@ int main(int argc, char **argv)
     usage();
 
   setproctitle_init(argc, argv);
-  init_memory();
+  init_memory(set_password);
 
   if (daemon_mode)
     run_as_daemon(do_fork);