diff options
Diffstat (limited to 'contrib/bc/src/read.c')
-rw-r--r-- | contrib/bc/src/read.c | 137 |
1 files changed, 87 insertions, 50 deletions
diff --git a/contrib/bc/src/read.c b/contrib/bc/src/read.c index b9cd4db7bb49..de9e24ed6acf 100644 --- a/contrib/bc/src/read.c +++ b/contrib/bc/src/read.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2023 Gavin D. Howard and contributors. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -54,12 +54,14 @@ #include <vm.h> /** - * A portability file open function. + * A portability file open function. This is copied to gen/strgen.c. Make sure + * to update that if this changes. * @param path The path to the file to open. * @param mode The mode to open in. */ -static int bc_read_open(const char* path, int mode) { - +static int +bc_read_open(const char* path, int mode) +{ int fd; #ifndef _WIN32 @@ -77,20 +79,23 @@ static int bc_read_open(const char* path, int mode) { * @param buf The buffer to test. * @param size The size of the buffer. */ -static bool bc_read_binary(const char *buf, size_t size) { - +static bool +bc_read_binary(const char* buf, size_t size) +{ size_t i; - for (i = 0; i < size; ++i) { + for (i = 0; i < size; ++i) + { if (BC_ERR(BC_READ_BIN_CHAR(buf[i]))) return true; } return false; } -bool bc_read_buf(BcVec *vec, char *buf, size_t *buf_len) { - - char *nl; +bool +bc_read_buf(BcVec* vec, char* buf, size_t* buf_len) +{ + char* nl; // If nothing there, return. if (!*buf_len) return false; @@ -99,8 +104,8 @@ bool bc_read_buf(BcVec *vec, char *buf, size_t *buf_len) { nl = strchr(buf, '\n'); // If a newline exists... - if (nl != NULL) { - + if (nl != NULL) + { // Get the size of the data up to, and including, the newline. size_t nllen = (size_t) ((nl + 1) - buf); @@ -110,6 +115,7 @@ bool bc_read_buf(BcVec *vec, char *buf, size_t *buf_len) { // buffer up. bc_vec_npush(vec, nllen, buf); *buf_len -= nllen; + // NOLINTNEXTLINE memmove(buf, nl + 1, *buf_len + 1); return true; @@ -122,8 +128,9 @@ bool bc_read_buf(BcVec *vec, char *buf, size_t *buf_len) { return false; } -BcStatus bc_read_chars(BcVec *vec, const char *prompt) { - +BcStatus +bc_read_chars(BcVec* vec, const char* prompt) +{ bool done = false; assert(vec != NULL && vec->size == sizeof(char)); @@ -134,48 +141,64 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) { bc_vec_popAll(vec); // Handle the prompt, if desired. - if (BC_PROMPT) { - bc_file_puts(&vm.fout, bc_flush_none, prompt); - bc_file_flush(&vm.fout, bc_flush_none); + if (BC_PROMPT) + { + bc_file_puts(&vm->fout, bc_flush_none, prompt); + bc_file_flush(&vm->fout, bc_flush_none); } // Try reading from the buffer, and if successful, just return. - if (bc_read_buf(vec, vm.buf, &vm.buf_len)) { + if (bc_read_buf(vec, vm->buf, &vm->buf_len)) + { bc_vec_pushByte(vec, '\0'); return BC_STATUS_SUCCESS; } // Loop until we have something. - while (!done) { - + while (!done) + { ssize_t r; BC_SIG_LOCK; // Read data from stdin. - r = read(STDIN_FILENO, vm.buf + vm.buf_len, - BC_VM_STDIN_BUF_SIZE - vm.buf_len); + r = read(STDIN_FILENO, vm->buf + vm->buf_len, + BC_VM_STDIN_BUF_SIZE - vm->buf_len); // If there was an error... - if (BC_UNLIKELY(r < 0)) { - + if (BC_UNLIKELY(r < 0)) + { // If interupted... - if (errno == EINTR) { + if (errno == EINTR) + { + int sig; // Jump out if we are supposed to quit, which certain signals // will require. - if (vm.status == (sig_atomic_t) BC_STATUS_QUIT) BC_JMP; + if (vm->status == (sig_atomic_t) BC_STATUS_QUIT) BC_JMP; - assert(vm.sig); + assert(vm->sig != 0); + + sig = (int) vm->sig; // Clear the signal and status. - vm.sig = 0; - vm.status = (sig_atomic_t) BC_STATUS_SUCCESS; + vm->sig = 0; + vm->status = (sig_atomic_t) BC_STATUS_SUCCESS; - // Print the ready message and prompt again. - bc_file_puts(&vm.fout, bc_flush_none, bc_program_ready_msg); - if (BC_PROMPT) bc_file_puts(&vm.fout, bc_flush_none, prompt); - bc_file_flush(&vm.fout, bc_flush_none); +#ifndef _WIN32 + // We don't want to print anything on a SIGWINCH. + if (sig != SIGWINCH) +#endif // _WIN32 + { + // Print the ready message and prompt again. + bc_file_puts(&vm->fout, bc_flush_none, + bc_program_ready_msg); + if (BC_PROMPT) + { + bc_file_puts(&vm->fout, bc_flush_none, prompt); + } + bc_file_flush(&vm->fout, bc_flush_none); + } BC_SIG_UNLOCK; @@ -191,7 +214,8 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) { BC_SIG_UNLOCK; // If we read nothing, make sure to terminate the string and return EOF. - if (r == 0) { + if (r == 0) + { bc_vec_pushByte(vec, '\0'); return BC_STATUS_EOF; } @@ -199,11 +223,11 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) { BC_SIG_LOCK; // Add to the buffer. - vm.buf_len += (size_t) r; - vm.buf[vm.buf_len] = '\0'; + vm->buf_len += (size_t) r; + vm->buf[vm->buf_len] = '\0'; // Read from the buffer. - done = bc_read_buf(vec, vm.buf, &vm.buf_len); + done = bc_read_buf(vec, vm->buf, &vm->buf_len); BC_SIG_UNLOCK; } @@ -214,27 +238,33 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) { return BC_STATUS_SUCCESS; } -BcStatus bc_read_line(BcVec *vec, const char *prompt) { - +BcStatus +bc_read_line(BcVec* vec, const char* prompt) +{ BcStatus s; #if BC_ENABLE_HISTORY // Get a line from either history or manual reading. - if (BC_TTY && !vm.history.badTerm) - s = bc_history_line(&vm.history, vec, prompt); + if (BC_TTY && !vm->history.badTerm) + { + s = bc_history_line(&vm->history, vec, prompt); + } else s = bc_read_chars(vec, prompt); #else // BC_ENABLE_HISTORY s = bc_read_chars(vec, prompt); #endif // BC_ENABLE_HISTORY if (BC_ERR(bc_read_binary(vec->v, vec->len - 1))) + { bc_verr(BC_ERR_FATAL_BIN_FILE, bc_program_stdin_name); + } return s; } -char* bc_read_file(const char *path) { - +char* +bc_read_file(const char* path) +{ BcErr e = BC_ERR_FATAL_IO_ERR; size_t size, to_read; struct stat pstat; @@ -242,14 +272,18 @@ char* bc_read_file(const char *path) { char* buf; char* buf2; + // This has been copied to gen/strgen.c. Make sure to change that if this + // changes. + BC_SIG_ASSERT_LOCKED; assert(path != NULL); -#ifndef NDEBUG +#if BC_DEBUG // Need this to quiet MSan. + // NOLINTNEXTLINE memset(&pstat, 0, sizeof(struct stat)); -#endif // NDEBUG +#endif // BC_DEBUG fd = bc_read_open(path, O_RDONLY); @@ -261,7 +295,8 @@ char* bc_read_file(const char *path) { if (BC_ERR(fstat(fd, &pstat) == -1)) goto malloc_err; // Make sure it's not a directory. - if (BC_ERR(S_ISDIR(pstat.st_mode))) { + if (BC_ERR(S_ISDIR(pstat.st_mode))) + { e = BC_ERR_FATAL_PATH_DIR; goto malloc_err; } @@ -272,20 +307,22 @@ char* bc_read_file(const char *path) { buf2 = buf; to_read = size; - do { - + do + { // Read the file. We just bail if a signal interrupts. This is so that // users can interrupt the reading of big files if they want. ssize_t r = read(fd, buf2, to_read); if (BC_ERR(r < 0)) goto read_err; to_read -= (size_t) r; buf2 += (size_t) r; - } while (to_read); + } + while (to_read); // Got to have a nul byte. buf[size] = '\0'; - if (BC_ERR(bc_read_binary(buf, size))) { + if (BC_ERR(bc_read_binary(buf, size))) + { e = BC_ERR_FATAL_BIN_FILE; goto read_err; } |