blob: aaad89a2496775948ae0c2fd28e8ac23af0565b1 [file] [log] [blame]
/*
* *****************************************************************************
*
* Copyright 2018 Gavin D. Howard
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* *****************************************************************************
*
* Code to handle special I/O for bc.
*
*/
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <program.h>
#include <vm.h>
BcStatus bc_io_getline(BcVec *vec, const char* prompt) {
BcStatus s;
signed char c = 0;
if (bcg.ttyin && (fputs(prompt, stderr) == EOF || fflush(stderr) == EOF))
return BC_STATUS_IO_ERR;
assert(vec && vec->size == sizeof(char));
bc_vec_npop(vec, vec->len);
while (c != '\n') {
if ((c = fgetc(stdin)) == EOF) {
if (errno == EINTR) {
bcg.sigc = bcg.sig;
bcg.signe = 0;
if (bcg.ttyin && (fputs(bc_program_ready_msg, stderr) == EOF ||
fputs(prompt, stderr) == EOF ||
fflush(stderr) == EOF))
{
return BC_STATUS_IO_ERR;
}
continue;
}
else return BC_STATUS_IO_ERR;
}
else if ((c < ' ' && !isspace(c)) || c > '~') return BC_STATUS_BIN_FILE;
if ((s = bc_vec_push(vec, &c))) return s;
}
return bc_vec_pushByte(vec, '\0');
}
BcStatus bc_io_fread(const char *path, char **buf) {
BcStatus s;
FILE *f;
size_t size, read;
long res;
assert(path && buf);
if (!(f = fopen(path, "r"))) return BC_STATUS_EXEC_FILE_ERR;
fseek(f, 0, SEEK_END);
if ((res = ftell(f)) < 0) {
s = BC_STATUS_IO_ERR;
goto malloc_err;
}
size = (size_t) res;
fseek(f, 0, SEEK_SET);
if (!(*buf = malloc(size + 1))) {
s = BC_STATUS_ALLOC_ERR;
goto malloc_err;
}
if ((read = fread(*buf, 1, size, f)) != size) {
s = BC_STATUS_IO_ERR;
goto read_err;
}
(*buf)[size] = '\0';
fclose(f);
return BC_STATUS_SUCCESS;
read_err:
free(*buf);
malloc_err:
fclose(f);
return s;
}