Make interrupts work better

Now they can interrupt some ongoing calculations. It is not entirely
practical to test for it everywhere, but this is a good start.
diff --git a/src/bc.c b/src/bc.c
index dccf641..ca39ba2 100644
--- a/src/bc.c
+++ b/src/bc.c
@@ -39,7 +39,7 @@
 void bc_sig(int sig) {
   if (sig == SIGINT) {
     if (write(2, bc_sig_msg, sizeof(bc_sig_msg) - 1) >= 0)
-      bcg.sig_int += bcg.sig_int == bcg.sig_int_catches;
+      bcg.sig += (bcg.signe = bcg.sig == bcg.sigc);
   }
   else bcg.sig_other = 1;
 }
@@ -200,7 +200,14 @@
   // a backslash newline combo as whitespace, per the bc spec.
   // Thus, the parser will expect more stuff. That is also
   // the case with strings and comments.
-  while ((!s || s != BC_STATUS_QUIT) && !(s = bc_io_getline(&buf, &bufn))) {
+  while ((!s || s != BC_STATUS_QUIT) &&
+         !((s = bc_io_getline(&buf, &bufn)) && s != BC_STATUS_BINARY_FILE))
+  {
+    if (s == BC_STATUS_BINARY_FILE) {
+      putchar('\a');
+      s = BC_STATUS_SUCCESS;
+      continue;
+    }
 
     len = strlen(buf);
     slen = strlen(buffer);
diff --git a/src/data.c b/src/data.c
index 66cf69d..8ff3206 100644
--- a/src/data.c
+++ b/src/data.c
@@ -110,7 +110,7 @@
   "POSIX requires the left brace be on the same line as the function header",
 };
 
-const char bc_sig_msg[36] = "\n\ninterrupt (type \"quit\" to exit)\n\n";
+const char bc_sig_msg[36] = "\ninterrupt (type \"quit\" to exit)\n";
 
 const char bc_lang_func_main[7] = "(main)";
 const char bc_lang_func_read[7] = "(read)";
diff --git a/src/io.c b/src/io.c
index 6485a0c..cfb21de 100644
--- a/src/io.c
+++ b/src/io.c
@@ -51,7 +51,8 @@
     if ((c = fgetc(stdin)) == EOF) {
 
       if (errno == EINTR) {
-        bcg.sig_int_catches = bcg.sig_int;
+        bcg.sigc = bcg.sig;
+        bcg.signe = 0;
         --i;
         continue;
       }
diff --git a/src/main.c b/src/main.c
index addce86..71c3477 100644
--- a/src/main.c
+++ b/src/main.c
@@ -171,6 +171,7 @@
   memset(&bcg, 0, sizeof(BcGlobals));
 
   flags = 0;
+  buffer = NULL;
 
   if ((status = bc_vec_init(&files, sizeof(char*), NULL))) return status;
 
diff --git a/src/num.c b/src/num.c
index c546bdd..62a721e 100644
--- a/src/num.c
+++ b/src/num.c
@@ -305,14 +305,16 @@
   memset(c->num, 0, sizeof(BcDigit) * c->cap);
   c->len = carry = len = 0;
 
-  for (i = 0; i < b->len; ++i) {
+  for (i = 0; !bcg.signe && i < b->len; ++i) {
 
-    for (j = 0; j < a->len; ++j) {
+    for (j = 0; !bcg.signe && j < a->len; ++j) {
       c->num[i + j] += a->num[j] * b->num[i] + carry;
       carry = c->num[i + j] / 10;
       c->num[i + j] %= 10;
     }
 
+    if (bcg.signe) return BC_STATUS_EXEC_SIGNAL;
+
     if (carry) {
       c->num[i + j] += carry;
       carry = 0;
@@ -321,6 +323,8 @@
     else len = BC_MAX(len, i + j);
   }
 
+  if (bcg.signe) return BC_STATUS_EXEC_SIGNAL;
+
   c->len = BC_MAX(len, c->rdx);
   c->neg = !a->neg != !b->neg;
 
@@ -391,7 +395,7 @@
   c->len = copy.len;
   bptr = b->num;
 
-  for (i = end - 1; i < end; --i) {
+  for (i = end - 1; !bcg.signe && i < end; --i) {
 
     ptr = copy.num + i;
 
@@ -401,6 +405,11 @@
     c->num[i] = q;
   }
 
+  if (bcg.signe) {
+    status = BC_STATUS_EXEC_SIGNAL;
+    goto err;
+  }
+
   c->neg = !a->neg != !b->neg;
   while (c->len > c->rdx && !c->num[c->len - 1]) --c->len;
   if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
@@ -480,16 +489,20 @@
 
   b->neg = neg;
 
-  for (powrdx = a->rdx; !(pow & 1); pow >>= 1) {
+  for (powrdx = a->rdx; !bcg.signe && !(pow & 1); pow >>= 1) {
     powrdx <<= 1;
     if ((status = bc_num_mul(&copy, &copy, &copy, powrdx))) goto err;
   }
 
   if ((status = bc_num_copy(c, &copy))) goto err;
+  if (bcg.signe) {
+    status = BC_STATUS_EXEC_SIGNAL;
+    goto err;
+  }
 
   resrdx = powrdx;
 
-  for (pow >>= 1; pow != 0; pow >>= 1) {
+  for (pow >>= 1; !bcg.signe && pow != 0; pow >>= 1) {
 
     powrdx <<= 1;
 
@@ -502,6 +515,10 @@
   }
 
   if (neg && (status = bc_num_inv(c, c, scale))) goto err;
+  if (bcg.signe) {
+    status = BC_STATUS_EXEC_SIGNAL;
+    goto err;
+  }
 
   if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
 
@@ -1086,7 +1103,7 @@
   resrdx = scale + 1;
   len = (x0->len - x0->rdx) + resrdx;
 
-  while (cmp && digits <= len) {
+  while (!bcg.signe && cmp && digits <= len) {
 
     if ((status = bc_num_mul(x0, x0, &f, resrdx))) goto err;
     if ((status = bc_num_sub(&f, a, &f, resrdx))) goto err;
@@ -1102,11 +1119,14 @@
     x1 = temp;
   }
 
+  if (bcg.signe) {
+    status = BC_STATUS_EXEC_SIGNAL;
+    goto err;
+  }
+
   if ((status = bc_num_copy(result, x0))) goto err;
 
-  --scale;
-
-  if (result->rdx > scale) bc_num_truncate(result, result->rdx - scale);
+  if (result->rdx > --scale) bc_num_truncate(result, result->rdx - scale);
   else if (result->rdx < scale)
     status = bc_num_extend(result, scale - result->rdx);
 
diff --git a/src/parse.c b/src/parse.c
index 890827d..cf0f50e 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1179,7 +1179,6 @@
 BcStatus bc_parse_parse(BcParse *p) {
 
   BcStatus status;
-  bool sig;
 
   assert(p);
 
@@ -1193,9 +1192,7 @@
     status = bc_parse_stmt(p, &func->code);
   }
 
-  sig = bcg.sig_int != bcg.sig_int_catches;
-
-  if (status || sig) {
+  if (status || bcg.signe) {
 
     if (p->func) {
 
@@ -1219,7 +1216,7 @@
     bc_vec_npop(&p->conds, p->conds.len);
     bc_vec_npop(&p->ops, p->ops.len);
 
-    status = bc_program_reset(p->prog, status, sig);
+    status = bc_program_reset(p->prog, status);
   }
 
   return status;
@@ -1259,9 +1256,8 @@
 
   type = p->lex.token.type;
 
-  while (bcg.sig_int == bcg.sig_int_catches && !status &&
-         !done && bc_parse_token_exprs[type])
-  {
+  while (!bcg.signe && !status && !done && bc_parse_token_exprs[type]) {
+
     switch (type) {
 
       case BC_LEX_OP_INC:
@@ -1440,7 +1436,11 @@
     type = p->lex.token.type;
   }
 
-  if (status || bcg.sig_int != bcg.sig_int_catches) goto err;
+  if (status) goto err;
+  if (bcg.signe) {
+    status = BC_STATUS_EXEC_SIGNAL;
+    goto err;
+  }
 
   status = BC_STATUS_SUCCESS;
 
diff --git a/src/program.c b/src/program.c
index 8d259c6..afcf629 100644
--- a/src/program.c
+++ b/src/program.c
@@ -1038,7 +1038,7 @@
   return status;
 }
 
-BcStatus bc_program_reset(BcProgram *p, BcStatus status, bool sig) {
+BcStatus bc_program_reset(BcProgram *p, BcStatus status) {
 
   BcFunc *func;
   BcInstPtr *ip;
@@ -1050,11 +1050,13 @@
   ip = bc_vec_top(&p->stack);
   ip->idx = func->code.len;
 
-  bcg.sig_int_catches += sig;
+  if (!status && bcg.signe && !bcg.interactive) return BC_STATUS_QUIT;
 
-  if (!status && sig && !bcg.interactive) return BC_STATUS_QUIT;
+  bcg.sigc += bcg.signe;
+  bcg.signe = bcg.sig != bcg.sigc;
 
-  if (!status && bcg.interactive) {
+  if ((!status || status == BC_STATUS_EXEC_SIGNAL) && bcg.interactive) {
+    status = BC_STATUS_SUCCESS;
     fprintf(stderr, "%s", bc_program_ready_prompt);
     fflush(stderr);
   }
@@ -1070,7 +1072,7 @@
   BcResult result;
   BcFunc *func;
   BcInstPtr *ip;
-  bool cond, sig;
+  bool cond;
   const char **string, *s;
 
   status = BC_STATUS_SUCCESS;
@@ -1318,10 +1320,8 @@
       }
     }
 
-    sig = bcg.sig_int != bcg.sig_int_catches;
-
-    if ((status && status != BC_STATUS_QUIT) || sig)
-      status = bc_program_reset(p, status, sig);
+    if ((status && status != BC_STATUS_QUIT) || bcg.signe)
+      status = bc_program_reset(p, status);
 
     // We keep getting these because if the size of the
     // stack changes, pointers may end up being invalid.
@@ -1436,8 +1436,8 @@
 
     if (putchar('\n') == EOF) status = BC_STATUS_IO_ERR;
 
-    sig = bcg.sig_int != bcg.sig_int_catches;
-    if (status || sig) status = bc_program_reset(p, status, sig);
+    sig = bcg.sig != bcg.sigc;
+    if (status || sig) status = bc_program_reset(p, status);
   }
 
   return status;