BC_STATUS_SUCCESS,
// BC_STATUS_ALLOC_ERR,
- BC_STATUS_INPUT_EOF,
+// BC_STATUS_INPUT_EOF,
BC_STATUS_BIN_FILE,
// BC_STATUS_PATH_IS_DIR,
static const char *const bc_err_msgs[] = {
NULL,
// "memory allocation error",
- "I/O error",
+// "I/O error",
"file is not text:",
// "path is a directory:",
smallint tty;
smallint ttyin;
+ smallint eof;
} FIX_ALIASING;
#define G (*ptr_to_globals)
#define INIT_G() do { \
};
#endif // ENABLE_BC
+static void fflush_and_check(void)
+{
+ fflush_all();
+ if (ferror(stdout) || ferror(stderr))
+ bb_perror_msg_and_die("output error");
+}
+
static void quit(void) NORETURN;
static void quit(void)
{
- fflush_all();
- exit(ferror(stdout) || ferror(stderr));
+ if (ferror(stdin))
+ bb_perror_msg_and_die("input error");
+ fflush_and_check();
+ exit(0);
}
static void bc_vec_grow(BcVec *v, size_t n)
bc_vec_npop(vec, vec->len);
- fflush(stdout);
+ fflush_and_check();
#if ENABLE_FEATURE_BC_SIGNALS
if (bb_got_signal) { // ^C was pressed
intr:
#endif
if (G.ttyin && !G_posix)
fputs(prompt, stderr);
- fflush(stderr);
+ fflush_and_check();
#if ENABLE_FEATURE_BC_SIGNALS
errno = 0;
#endif
do {
- if (ferror(stdout) || ferror(stderr))
- bb_perror_msg_and_die("output error");
-
i = fgetc(stdin);
if (i == EOF) {
}
#endif
if (ferror(stdin))
- bb_perror_msg_and_die("input error");
- return BC_STATUS_INPUT_EOF;
+ quit(); // this emits error message
+ G.eof = 1;
+ // Note: EOF does not append '\n', therefore:
+ // printf 'print 123\n' | bc - works
+ // printf 'print 123' | bc - fails (syntax error)
+ break;
}
c = (signed char) i;
bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
p->parse = parse;
- p->auto_part = (p->nbraces = 0);
+ // p->auto_part = p->nbraces = 0; - already is
bc_parse_updateFunc(p, func);
}
if (!s || s == BC_STATUS_EXEC_SIGNAL) {
if (!G.ttyin)
quit();
- fflush(stdout);
+ fflush_and_check(); // make sure buffered stdout is printed
fputs(bc_program_ready_msg, stderr);
- fflush(stderr);
+ fflush_and_check();
s = BC_STATUS_SUCCESS;
}
if (BC_PARSE_CAN_EXEC(&G.prs)) {
s = bc_program_exec();
- fflush(stdout);
+ fflush_and_check();
if (s)
s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0);
}
// with a backslash to the parser. The reason for that is because the parser
// treats a backslash+newline combo as whitespace, per the bc spec. In that
// case, and for strings and comments, the parser will expect more stuff.
- while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
+ while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
char *string = buf.v;
if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0);
- // INPUT_EOF will always happen when stdin is
- // closed. It's not a problem in that case.
- if (s == BC_STATUS_INPUT_EOF)
- s = BC_STATUS_SUCCESS;
-
if (str)
s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f,
G.prs.l.line);