Browse Source

Fix problems with printing stuff without newlines

The problem was not that stuff was printed without newlines, it was that
history did not recognize it as such. This commit fixes that.

To do that, I had a way for bc_file_* functions to know what kind of
flush they needed to do. I added an enum for it and updated all of the
places. This ensures that there isn't an infinite loop or other such
problem when flushing during history.

This commit does not complete the change. I have to ensure it builds
with history turned off still.
master
Gavin Howard 1 month ago
parent
commit
7378a7abe1
Signed by: gavin GPG Key ID: C08038BDF280D33E
  1. 29
      include/file.h
  2. 3
      include/history.h
  3. 2
      include/vm.h
  4. 4
      src/data.c
  5. 64
      src/file.c
  6. 67
      src/history.c
  7. 8
      src/num.c
  8. 20
      src/program.c
  9. 9
      src/read.c
  10. 56
      src/vm.c

29
include/file.h

@ -51,15 +51,30 @@ typedef struct BcFile {
} BcFile;
typedef enum BcFlushType {
BC_FLUSH_NO_EXTRAS_NO_CLEAR,
BC_FLUSH_SAVE_EXTRAS_NO_CLEAR,
BC_FLUSH_NO_EXTRAS_CLEAR,
BC_FLUSH_SAVE_EXTRAS_CLEAR,
} BcFlushType;
void bc_file_init(BcFile *f, int fd, char *buf, size_t cap);
void bc_file_free(BcFile *f);
void bc_file_putchar(BcFile *restrict f, uchar c);
BcStatus bc_file_flushErr(BcFile *restrict f);
void bc_file_flush(BcFile *restrict f);
void bc_file_write(BcFile *restrict f, const char *buf, size_t n);
void bc_file_printf(BcFile *restrict f, const char *fmt, ...);
void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args);
void bc_file_puts(BcFile *restrict f, const char *str);
void bc_file_putchar(BcFile *restrict f, BcFlushType type, uchar c);
BcStatus bc_file_flushErr(BcFile *restrict f, BcFlushType type);
void bc_file_flush(BcFile *restrict f, BcFlushType type);
void bc_file_write(BcFile *restrict f, BcFlushType type,
const char *buf, size_t n);
void bc_file_printf(BcFile *restrict f, BcFlushType type, const char *fmt, ...);
void bc_file_vprintf(BcFile *restrict f, BcFlushType type,
const char *fmt, va_list args);
void bc_file_puts(BcFile *restrict f, BcFlushType type, const char *str);
extern const BcFlushType bc_flush_none;
extern const BcFlushType bc_flush_err;
extern const BcFlushType bc_flush_save;
#endif // BC_FILE_H

3
include/history.h

@ -186,6 +186,9 @@ typedef struct BcHistory {
/// The history.
BcVec history;
/// Any material printed without a trailing newline.
BcVec extras;
#if BC_ENABLE_PROMPT
/// Prompt to display.
const char *prompt;

2
include/vm.h

@ -424,7 +424,7 @@ void bc_vm_shutdown(void);
void bc_vm_freeTemps(void);
void bc_vm_printf(const char *fmt, ...);
void bc_vm_putchar(int c);
void bc_vm_putchar(int c, BcFlushType type);
size_t bc_vm_arraySize(size_t n, size_t size);
size_t bc_vm_growSize(size_t a, size_t b);
void* bc_vm_malloc(size_t n);

4
src/data.c

@ -172,6 +172,10 @@ const char* const bc_err_msgs[] = {
};
const BcFlushType bc_flush_none = BC_FLUSH_NO_EXTRAS_NO_CLEAR;
const BcFlushType bc_flush_err = BC_FLUSH_NO_EXTRAS_CLEAR;
const BcFlushType bc_flush_save = BC_FLUSH_SAVE_EXTRAS_CLEAR;
#if BC_ENABLE_HISTORY
const char *bc_history_bad_terms[] = { "dumb", "cons25", "emacs", NULL };

64
src/file.c

@ -82,11 +82,27 @@ static BcStatus bc_file_output(int fd, const char *buf, size_t n) {
return BC_STATUS_SUCCESS;
}
BcStatus bc_file_flushErr(BcFile *restrict f) {
BcStatus bc_file_flushErr(BcFile *restrict f, BcFlushType type)
{
BcStatus s;
if (f->len) {
if (f->buf[f->len - 1] != '\n' &&
(type == BC_FLUSH_SAVE_EXTRAS_CLEAR ||
type == BC_FLUSH_SAVE_EXTRAS_NO_CLEAR))
{
size_t i;
for (i = f->len - 2; i < f->len && f->buf[i] != '\n'; --i);
i += 1;
bc_vec_string(&vm.history.extras, f->len - i, f->buf + i);
}
else if (type >= BC_FLUSH_NO_EXTRAS_CLEAR)
bc_vec_popAll(&vm.history.extras);
s = bc_file_output(f->fd, f->buf, f->len);
f->len = 0;
}
@ -95,9 +111,9 @@ BcStatus bc_file_flushErr(BcFile *restrict f) {
return s;
}
void bc_file_flush(BcFile *restrict f) {
void bc_file_flush(BcFile *restrict f, BcFlushType type) {
BcStatus s = bc_file_flushErr(f);
BcStatus s = bc_file_flushErr(f, type);
if (BC_ERR(s)) {
@ -109,10 +125,11 @@ void bc_file_flush(BcFile *restrict f) {
}
}
void bc_file_write(BcFile *restrict f, const char *buf, size_t n) {
void bc_file_write(BcFile *restrict f, BcFlushType type,
const char *buf, size_t n)
{
if (n > f->cap - f->len) {
bc_file_flush(f);
bc_file_flush(f, type);
assert(!f->len);
}
@ -123,17 +140,18 @@ void bc_file_write(BcFile *restrict f, const char *buf, size_t n) {
}
}
void bc_file_printf(BcFile *restrict f, const char *fmt, ...) {
void bc_file_printf(BcFile *restrict f, BcFlushType type, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
bc_file_vprintf(f, fmt, args);
bc_file_vprintf(f, type, fmt, args);
va_end(args);
}
void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
void bc_file_vprintf(BcFile *restrict f, BcFlushType type,
const char *fmt, va_list args)
{
char *percent;
const char *ptr = fmt;
char buf[BC_FILE_ULL_LENGTH];
@ -144,7 +162,7 @@ void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
if (percent != ptr) {
size_t len = (size_t) (percent - ptr);
bc_file_write(f, ptr, len);
bc_file_write(f, type, ptr, len);
}
c = percent[1];
@ -153,13 +171,13 @@ void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
uchar uc = (uchar) va_arg(args, int);
bc_file_putchar(f, uc);
bc_file_putchar(f, type, uc);
}
else if (c == 's') {
char *s = va_arg(args, char*);
bc_file_puts(f, s);
bc_file_puts(f, type, s);
}
#if BC_DEBUG_CODE
else if (c == 'd') {
@ -187,25 +205,25 @@ void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
if (c == 'z') ull = (unsigned long long) va_arg(args, size_t);
else ull = (unsigned long long) va_arg(args, unsigned long);
if (!ull) bc_file_putchar(f, '0');
if (!ull) bc_file_putchar(f, type, '0');
else {
bc_file_ultoa(ull, buf);
bc_file_puts(f, buf);
bc_file_puts(f, type, buf);
}
}
ptr = percent + 2 + (c == 'l' || c == 'z');
}
if (ptr[0]) bc_file_puts(f, ptr);
if (ptr[0]) bc_file_puts(f, type, ptr);
}
void bc_file_puts(BcFile *restrict f, const char *str) {
bc_file_write(f, str, strlen(str));
void bc_file_puts(BcFile *restrict f, BcFlushType type, const char *str) {
bc_file_write(f, type, str, strlen(str));
}
void bc_file_putchar(BcFile *restrict f, uchar c) {
if (f->len == f->cap) bc_file_flush(f);
void bc_file_putchar(BcFile *restrict f, BcFlushType type, uchar c) {
if (f->len == f->cap) bc_file_flush(f, type);
assert(f->len < f->cap);
f->buf[f->len] = (char) c;
f->len += 1;
@ -221,5 +239,5 @@ void bc_file_init(BcFile *f, int fd, char *buf, size_t cap) {
void bc_file_free(BcFile *f) {
BC_SIG_ASSERT_LOCKED;
bc_file_flush(f);
bc_file_flush(f, bc_flush_none);
}

67
src/history.c

@ -505,8 +505,8 @@ static size_t bc_history_cursorPos(void) {
size_t cols, rows, i;
// Report cursor location.
bc_file_write(&vm.fout, "\x1b[6n", 4);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4);
bc_file_flush(&vm.fout, bc_flush_none);
// Read the response: ESC [ rows ; cols R.
for (i = 0; i < sizeof(buf) - 1; ++i) {
@ -556,15 +556,15 @@ static size_t bc_history_columns(void) {
if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS;
// Go to right margin and get position.
bc_file_write(&vm.fout, "\x1b[999C", 6);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, "\x1b[999C", 6);
bc_file_flush(&vm.fout, bc_flush_none);
cols = bc_history_cursorPos();
if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS;
// Restore position.
if (cols > start) {
bc_file_printf(&vm.fout, "\x1b[%zuD", cols - start);
bc_file_flush(&vm.fout);
bc_file_printf(&vm.fout, bc_flush_none, "\x1b[%zuD", cols - start);
bc_file_flush(&vm.fout, bc_flush_none);
}
return cols;
@ -632,7 +632,7 @@ static void bc_history_refresh(BcHistory *h) {
char* buf = h->buf.v;
size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos;
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_none);
while(h->pcol + bc_history_colPos(buf, len, pos) >= h->cols) {
@ -647,24 +647,32 @@ static void bc_history_refresh(BcHistory *h) {
len -= bc_history_prevLen(buf, len, NULL);
// Cursor to left edge.
bc_file_write(&vm.fout, "\r", 1);
bc_file_write(&vm.fout, bc_flush_none, "\r", 1);
// Take the extra stuff into account.
if (h->extras.len > 1) {
len += h->extras.len - 1;
pos += h->extras.len - 1;
bc_file_write(&vm.fout, bc_flush_none, h->extras.v, h->extras.len - 1);
}
// Write the prompt, if desired.
#if BC_ENABLE_PROMPT
if (BC_USE_PROMPT) bc_file_write(&vm.fout, h->prompt, h->plen);
if (BC_USE_PROMPT)
bc_file_write(&vm.fout, bc_flush_none, h->prompt, h->plen);
#endif // BC_ENABLE_PROMPT
bc_file_write(&vm.fout, buf, BC_HIST_BUF_LEN(h));
bc_file_write(&vm.fout, bc_flush_none, buf, BC_HIST_BUF_LEN(h));
// Erase to right.
bc_file_write(&vm.fout, "\x1b[0K", 4);
bc_file_write(&vm.fout, bc_flush_none, "\x1b[0K", 4);
// Move cursor to original position.
colpos = bc_history_colPos(buf, len, pos) + h->pcol;
if (colpos) bc_file_printf(&vm.fout, "\r\x1b[%zuC", colpos);
if (colpos) bc_file_printf(&vm.fout, bc_flush_none, "\r\x1b[%zuC", colpos);
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_none);
}
/**
@ -684,7 +692,7 @@ static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
h->buf.len += clen - 1;
bc_vec_pushByte(&h->buf, '\0');
len = BC_HIST_BUF_LEN(h);
len = BC_HIST_BUF_LEN(h) + h->extras.len - 1;
#if BC_ENABLE_PROMPT
colpos = bc_history_promptColLen(h->prompt, h->plen);
#endif // BC_ENABLE_PROMPT
@ -693,8 +701,8 @@ static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
if (colpos < h->cols) {
// Avoid a full update of the line in the trivial case.
bc_file_write(&vm.fout, cbuf, clen);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, cbuf, clen);
bc_file_flush(&vm.fout, bc_flush_none);
}
else bc_history_refresh(h);
}
@ -1102,7 +1110,7 @@ static void bc_history_printCtrl(BcHistory *h, unsigned int c) {
bc_vec_pushByte(&h->buf, '\0');
if (c != BC_ACTION_CTRL_C && c != BC_ACTION_CTRL_D) {
bc_file_write(&vm.fout, newline, sizeof(newline) - 1);
bc_file_write(&vm.fout, bc_flush_none, newline, sizeof(newline) - 1);
bc_history_refresh(h);
}
}
@ -1116,6 +1124,11 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
bc_history_reset(h);
// Don't write the saved output the first time. This is because it has
// already been written to output. In other words, don't uncomment the
// line below or add anything like it.
// bc_file_write(&vm.fout, bc_flush_none, h->extras.v, h->extras.len - 1);
#if BC_ENABLE_PROMPT
if (BC_USE_PROMPT) {
@ -1123,8 +1136,8 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
h->plen = strlen(prompt);
h->pcol = bc_history_promptColLen(prompt, h->plen);
bc_file_write(&vm.fout, prompt, h->plen);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, prompt, h->plen);
bc_file_flush(&vm.fout, bc_flush_none);
}
#endif // BC_ENABLE_PROMPT
@ -1158,8 +1171,8 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
case BC_ACTION_CTRL_C:
{
bc_history_printCtrl(h, c);
bc_file_write(&vm.fout, vm.sigmsg, vm.siglen);
bc_file_write(&vm.fout, bc_program_ready_msg,
bc_file_write(&vm.fout, bc_flush_none, vm.sigmsg, vm.siglen);
bc_file_write(&vm.fout, bc_flush_none, bc_program_ready_msg,
bc_program_ready_msg_len);
bc_history_reset(h);
bc_history_refresh(h);
@ -1254,7 +1267,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
// Clear screen.
case BC_ACTION_CTRL_L:
{
bc_file_write(&vm.fout, "\x1b[H\x1b[2J", 7);
bc_file_write(&vm.fout, bc_flush_none, "\x1b[H\x1b[2J", 7);
bc_history_refresh(h);
break;
}
@ -1302,8 +1315,8 @@ static BcStatus bc_history_raw(BcHistory *h, const char *prompt) {
h->stdin_has_data = bc_history_stdinHasData(h);
if (!h->stdin_has_data) bc_history_disableRaw(h);
bc_file_write(&vm.fout, "\n", 1);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, "\n", 1);
bc_file_flush(&vm.fout, bc_flush_none);
return s;
}
@ -1382,6 +1395,7 @@ void bc_history_init(BcHistory *h) {
bc_vec_init(&h->buf, sizeof(char), NULL);
bc_vec_init(&h->history, sizeof(char*), bc_history_string_free);
bc_vec_init(&h->extras, sizeof(char), NULL);
FD_ZERO(&h->rdset);
FD_SET(STDIN_FILENO, &h->rdset);
@ -1401,6 +1415,7 @@ void bc_history_free(BcHistory *h) {
#ifndef NDEBUG
bc_vec_free(&h->buf);
bc_vec_free(&h->history);
bc_vec_free(&h->extras);
#endif // NDEBUG
}
@ -1439,8 +1454,8 @@ void bc_history_printKeyCodes(BcHistory *h) {
isprint(c) ? c : '?', (unsigned long) c);
// Go left edge manually, we are in raw mode.
bc_vm_putchar('\r');
bc_file_flush(&vm.fout);
bc_vm_putchar('\r', bc_flush_none);
bc_file_flush(&vm.fout, bc_flush_none);
}
bc_history_disableRaw(h);

8
src/num.c

@ -1655,15 +1655,15 @@ int_err:
static inline void bc_num_printNewline(void) {
#if !BC_ENABLE_LIBRARY
if (vm.nchars >= vm.line_len - 1) {
bc_vm_putchar('\\');
bc_vm_putchar('\n');
bc_vm_putchar('\\', bc_flush_none);
bc_vm_putchar('\n', bc_flush_err);
}
#endif // !BC_ENABLE_LIBRARY
}
static void bc_num_putchar(int c) {
if (c != '\n') bc_num_printNewline();
bc_vm_putchar(c);
bc_vm_putchar(c, bc_flush_save);
}
#if DC_ENABLED && !BC_ENABLE_LIBRARY
@ -1671,7 +1671,7 @@ static void bc_num_printChar(size_t n, size_t len, bool rdx) {
BC_UNUSED(rdx);
BC_UNUSED(len);
assert(len == 1);
bc_vm_putchar((uchar) n);
bc_vm_putchar((uchar) n, bc_flush_save);
}
#endif // DC_ENABLED && !BC_ENABLE_LIBRARY

20
src/program.c

@ -514,7 +514,7 @@ static void bc_program_printChars(const char *str) {
const char *nl;
size_t len = vm.nchars + strlen(str);
bc_file_puts(&vm.fout, str);
bc_file_puts(&vm.fout, bc_flush_save, str);
nl = strrchr(str, '\n');
if (nl != NULL) len = strlen(nl + 1);
@ -528,7 +528,7 @@ static void bc_program_printString(const char *restrict str) {
#if DC_ENABLED
if (!len && BC_IS_DC) {
bc_vm_putchar('\0');
bc_vm_putchar('\0', bc_flush_save);
return;
}
#endif // DC_ENABLED
@ -551,11 +551,11 @@ static void bc_program_printString(const char *restrict str) {
else {
// Just print the backslash. The following
// character will be printed later.
bc_vm_putchar('\\');
bc_vm_putchar('\\', bc_flush_save);
}
}
bc_vm_putchar(c);
bc_vm_putchar(c, bc_flush_save);
}
}
@ -600,13 +600,14 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
size_t i = (r->t == BC_RESULT_STR) ? r->d.loc.loc : n->scale;
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_save);
str = *((char**) bc_vec_item(p->strs, i));
if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
else {
bc_program_printString(str);
if (inst == BC_INST_PRINT) bc_vm_putchar('\n');
if (inst == BC_INST_PRINT)
bc_vm_putchar('\n', bc_flush_err);
}
}
@ -1809,8 +1810,9 @@ void bc_program_reset(BcProgram *p) {
memset(ip, 0, sizeof(BcInstPtr));
if (vm.sig) {
bc_file_write(&vm.fout, bc_program_ready_msg, bc_program_ready_msg_len);
bc_file_flush(&vm.fout);
bc_file_write(&vm.fout, bc_flush_none, bc_program_ready_msg,
bc_program_ready_msg_len);
bc_file_flush(&vm.fout, bc_flush_err);
vm.sig = 0;
}
}
@ -1932,7 +1934,7 @@ void bc_program_exec(BcProgram *p) {
{
// We want to flush output before
// this in case there is a prompt.
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_save);
bc_program_read(p);

9
src/read.c

@ -100,8 +100,8 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
#if BC_ENABLE_PROMPT
if (BC_USE_PROMPT) {
bc_file_puts(&vm.fout, prompt);
bc_file_flush(&vm.fout);
bc_file_puts(&vm.fout, bc_flush_none, prompt);
bc_file_flush(&vm.fout, bc_flush_none);
}
#endif // BC_ENABLE_PROMPT
@ -132,9 +132,10 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
vm.status = (sig_atomic_t) BC_STATUS_SUCCESS;
#if BC_ENABLE_PROMPT
if (BC_USE_PROMPT) bc_file_puts(&vm.fout, prompt);
if (BC_USE_PROMPT)
bc_file_puts(&vm.fout, bc_flush_none, prompt);
#endif // BC_ENABLE_PROMPT
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_none);
BC_SIG_UNLOCK;

56
src/vm.c

@ -79,7 +79,7 @@ BC_NORETURN void bc_vm_jmp(void) {
bc_file_puts(&vm.ferr, "Longjmp: ");
bc_file_puts(&vm.ferr, f);
bc_file_putchar(&vm.ferr, '\n');
bc_file_flush(&vm.ferr);
bc_file_flush(&vm.ferr, bc_flush_none);
#endif // BC_DEBUG_CODE
#ifndef NDEBUG
@ -123,18 +123,18 @@ void bc_vm_info(const char* const help) {
BC_SIG_ASSERT_LOCKED;
bc_file_puts(&vm.fout, vm.name);
bc_file_putchar(&vm.fout, ' ');
bc_file_puts(&vm.fout, BC_VERSION);
bc_file_putchar(&vm.fout, '\n');
bc_file_puts(&vm.fout, bc_copyright);
bc_file_puts(&vm.fout, bc_flush_none, vm.name);
bc_file_putchar(&vm.fout, bc_flush_none, ' ');
bc_file_puts(&vm.fout, bc_flush_none, BC_VERSION);
bc_file_putchar(&vm.fout, bc_flush_none, '\n');
bc_file_puts(&vm.fout, bc_flush_none, bc_copyright);
if (help) {
bc_file_putchar(&vm.fout, '\n');
bc_file_printf(&vm.fout, help, vm.name, vm.name);
bc_file_putchar(&vm.fout, bc_flush_none, '\n');
bc_file_printf(&vm.fout, bc_flush_none, help, vm.name, vm.name);
}
bc_file_flush(&vm.fout);
bc_file_flush(&vm.fout, bc_flush_err);
}
#endif // !BC_ENABLE_LIBRARY
@ -192,7 +192,7 @@ void bc_vm_handleError(BcErr e, size_t line, ...) {
BC_SIG_TRYLOCK(lock);
// Make sure all of stdout is written first.
s = bc_file_flushErr(&vm.fout);
s = bc_file_flushErr(&vm.fout, bc_flush_err);
if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) {
vm.status = (sig_atomic_t) s;
@ -200,10 +200,10 @@ void bc_vm_handleError(BcErr e, size_t line, ...) {
}
va_start(args, line);
bc_file_putchar(&vm.ferr, '\n');
bc_file_puts(&vm.ferr, err_type);
bc_file_putchar(&vm.ferr, ' ');
bc_file_vprintf(&vm.ferr, vm.err_msgs[e], args);
bc_file_putchar(&vm.ferr, bc_flush_none, '\n');
bc_file_puts(&vm.ferr, bc_flush_none, err_type);
bc_file_putchar(&vm.ferr, bc_flush_none, ' ');
bc_file_vprintf(&vm.ferr, bc_flush_none, vm.err_msgs[e], args);
va_end(args);
if (BC_NO_ERR(vm.file)) {
@ -211,33 +211,33 @@ void bc_vm_handleError(BcErr e, size_t line, ...) {
// This is the condition for parsing vs runtime.
// If line is not 0, it is parsing.
if (line) {
bc_file_puts(&vm.ferr, "\n ");
bc_file_puts(&vm.ferr, vm.file);
bc_file_printf(&vm.ferr, bc_err_line, line);
bc_file_puts(&vm.ferr, bc_flush_none, "\n ");
bc_file_puts(&vm.ferr, bc_flush_none, vm.file);
bc_file_printf(&vm.ferr, bc_flush_none, bc_err_line, line);
}
else {
BcInstPtr *ip = bc_vec_item_rev(&vm.prog.stack, 0);
BcFunc *f = bc_vec_item(&vm.prog.fns, ip->func);
bc_file_puts(&vm.ferr, "\n ");
bc_file_puts(&vm.ferr, vm.func_header);
bc_file_putchar(&vm.ferr, ' ');
bc_file_puts(&vm.ferr, f->name);
bc_file_puts(&vm.ferr, bc_flush_none, "\n ");
bc_file_puts(&vm.ferr, bc_flush_none, vm.func_header);
bc_file_putchar(&vm.ferr, bc_flush_none, ' ');
bc_file_puts(&vm.ferr, bc_flush_none, f->name);
#if BC_ENABLED
if (BC_IS_BC && ip->func != BC_PROG_MAIN &&
ip->func != BC_PROG_READ)
{
bc_file_puts(&vm.ferr, "()");
bc_file_puts(&vm.ferr, bc_flush_none, "()");
}
#endif // BC_ENABLED
}
}
bc_file_puts(&vm.ferr, "\n\n");
bc_file_puts(&vm.ferr, bc_flush_none, "\n\n");
s = bc_file_flushErr(&vm.ferr);
s = bc_file_flushErr(&vm.ferr, bc_flush_err);
#if !BC_ENABLE_MEMCHECK
// Because this function is called by a BC_NORETURN function when fatal
@ -446,7 +446,7 @@ void bc_vm_printf(const char *fmt, ...) {
BC_SIG_LOCK;
va_start(args, fmt);
bc_file_vprintf(&vm.fout, fmt, args);
bc_file_vprintf(&vm.fout, bc_flush_none, fmt, args);
va_end(args);
vm.nchars = 0;
@ -455,11 +455,11 @@ void bc_vm_printf(const char *fmt, ...) {
}
#endif // !BC_ENABLE_LIBRARY
void bc_vm_putchar(int c) {
void bc_vm_putchar(int c, BcFlushType type) {
#if BC_ENABLE_LIBRARY
bc_vec_pushByte(&vm.out, (uchar) c);
#else // BC_ENABLE_LIBRARY
bc_file_putchar(&vm.fout, (uchar) c);
bc_file_putchar(&vm.fout, type, (uchar) c);
vm.nchars = (c == '\n' ? 0 : vm.nchars + 1);
#endif // BC_ENABLE_LIBRARY
}
@ -531,7 +531,7 @@ static void bc_vm_process(const char *text) {
assert(BC_IS_DC || vm.prog.results.len == 0);
if (BC_I) bc_file_flush(&vm.fout);
if (BC_I) bc_file_flush(&vm.fout, bc_flush_save);
} while (vm.prs.l.t != BC_LEX_EOF);
}

Loading…
Cancel
Save