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(©, ©, ©, powrdx))) goto err;
}
if ((status = bc_num_copy(c, ©))) 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;