bc_vec_pushZeroByte(v);
}
+#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING
static void bc_vec_concat(BcVec *v, const char *str)
{
size_t len, slen;
v->len = len;
}
+#endif
static void *bc_vec_item(const BcVec *v, size_t idx)
{
}
#endif
-static int push_input_byte(BcVec *vec, char c)
+static int bad_input_byte(char c)
{
if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'?
|| c > 0x7e
) {
- // Bad chars on this line, ignore entire line
bc_error_fmt("illegal character 0x%02x", c);
return 1;
}
- bc_vec_pushByte(vec, (char)c);
return 0;
}
+// Note: it _appends_ data from the stdin to vec.
static void bc_read_line(BcVec *vec)
{
- bool bad_chars;
-
- do {
- int c;
-
- bad_chars = 0;
- bc_vec_pop_all(vec);
-
+ again:
fflush_and_check();
#if ENABLE_FEATURE_BC_SIGNALS
// GNU dc says "Interrupt!"
fputs("\ninterrupted execution\n", stderr);
}
+
# if ENABLE_FEATURE_EDITING
if (G_ttyin) {
int n, i;
}
i = 0;
for (;;) {
- c = line_buf[i++];
+ char c = line_buf[i++];
if (!c) break;
- bad_chars |= push_input_byte(vec, c);
+ if (bad_input_byte(c)) goto again;
}
+ bc_vec_concat(vec, line_buf);
# undef line_buf
} else
# endif
#endif
{
+ int c;
+ bool bad_chars = 0;
+ size_t len = vec->len;
+
IF_FEATURE_BC_SIGNALS(errno = 0;)
do {
c = fgetc(stdin);
// printf 'print 123' | bc - fails (syntax error)
break;
}
- bad_chars |= push_input_byte(vec, c);
+ bad_chars |= bad_input_byte(c);
+ bc_vec_pushByte(vec, (char)c);
} while (c != '\n');
+ if (bad_chars) {
+ // Bad chars on this line, ignore entire line
+ vec->len = len;
+ goto again;
+ }
}
- } while (bad_chars);
bc_vec_pushZeroByte(vec);
}
f = bc_program_func(BC_PROG_READ);
bc_vec_pop_all(&f->code);
- bc_char_vec_init(&buf);
sv_file = G.prog.file;
G.prog.file = NULL;
G.in_read = 1;
+ bc_char_vec_init(&buf);
bc_read_line(&buf);
bc_parse_create(&parse, BC_PROG_READ);
static BC_STATUS zbc_vm_stdin(void)
{
BcStatus s;
- BcVec buf, buffer;
+ BcVec buffer;
size_t str;
bool comment;
bc_lex_file(&G.prs.l);
bc_char_vec_init(&buffer);
- bc_char_vec_init(&buf);
- bc_vec_pushZeroByte(&buffer);
// This loop is complex because the vm tries not to send any lines that end
// with a backslash to the parser. The reason for that is because the parser
comment = false;
str = 0;
for (;;) {
+ size_t prevlen = buffer.len;
char *string;
- bc_read_line(&buf);
- if (buf.len <= 1) // "" buf means EOF
+ bc_read_line(&buffer);
+ // No more input means EOF
+ if (buffer.len <= prevlen + 1) // (we expect +1 for NUL byte)
break;
- string = buf.v;
+ string = buffer.v + prevlen;
while (*string) {
char c = *string;
- if (string == buf.v || string[-1] != '\\') {
+ if (string == buffer.v || string[-1] != '\\') {
// checking applet type is cheaper than accessing sbgn/send
if (IS_BC) // bc: sbgn = send = '"'
str ^= (c == '"');
string++;
}
}
- bc_vec_concat(&buffer, buf.v);
- if (str || comment)
+ if (str || comment) {
+ buffer.len--; // backstep over the trailing NUL byte
continue;
+ }
// Check for backslash+newline.
// we do not check that last char is '\n' -
// if it is not, then it's EOF, and looping back
// to bc_read_line() will detect it:
string -= 2;
- if (string >= buf.v && *string == '\\')
+ if (string >= buffer.v && *string == '\\') {
+ buffer.len--;
continue;
+ }
s = zbc_vm_process(buffer.v);
if (s) {
s = bc_error("comment end could not be found");
}
- bc_vec_free(&buf);
bc_vec_free(&buffer);
RETURN_STATUS(s);
}