BC_STATUS_SUCCESS,
BC_STATUS_ALLOC_ERR,
- BC_STATUS_IO_ERR,
+ BC_STATUS_INPUT_EOF,
BC_STATUS_BIN_FILE,
BC_STATUS_PATH_IS_DIR,
static BcStatus bc_parse_parse(BcParse *p);
static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next);
-#endif
+#endif // ENABLE_BC
-#ifdef ENABLE_DC
+#if ENABLE_DC
#define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT))
long warn;
long exreg;
- const char *name;
#if ENABLE_FEATURE_BC_SIGNALS
const char *sig_msg;
#endif
const char *help;
- bool bc;
} BcGlobals;
+#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
+
#if ENABLE_BC
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
const char *msg);
#endif
-static void bc_vm_exit(BcStatus s);
-static void bc_vm_printf(FILE *restrict f, const char *fmt, ...);
-static void bc_vm_puts(const char *str, FILE *restrict f);
-static void bc_vm_putchar(int c);
-static void bc_vm_fflush(FILE *restrict f);
-
-static void bc_vm_info(const char *const help);
+static void bc_vm_info(void);
static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe,
const char *env_len);
static BcGlobals bcg;
#if ENABLE_BC
-static const char bc_name[] = "bc";
# if ENABLE_FEATURE_BC_SIGNALS
static const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n";
# endif
#endif
#if ENABLE_DC
-static const char dc_name[] = "dc";
# if ENABLE_FEATURE_BC_SIGNALS
static const char dc_sig_msg[] = "\ninterrupt (type \"q\" to exit)\n";
# endif
#endif
-static const char bc_copyright[] =
- "Copyright (c) 2018 Gavin D. Howard and contributors\n"
- "Report bugs at: https://github.com/gavinhoward/bc\n\n"
- "This is free software with ABSOLUTELY NO WARRANTY.\n";
-
static const char* const bc_args_env_name = "BC_ENV_ARGS";
static const char bc_err_fmt[] = "\n%s error: %s\n";
static BcStatus bc_read_line(BcVec *vec, const char *prompt)
{
int i;
- signed char c = 0;
+ signed char c;
if (bcg.ttyin && !bcg.posix) {
- bc_vm_puts(prompt, stderr);
- bc_vm_fflush(stderr);
+ fputs(prompt, stderr);
+ fflush(stderr);
}
bc_vec_npop(vec, vec->len);
- while (c != '\n') {
+ do {
+ if (ferror(stdout) || ferror(stderr))
+ bb_perror_msg_and_die("output error");
i = fgetc(stdin);
+ if (ferror(stdin))
+ bb_perror_msg_and_die("input error");
if (i == EOF) {
bcg.signe = 0;
if (bcg.ttyin) {
- bc_vm_puts(bc_program_ready_msg, stderr);
- if (!bcg.posix) bc_vm_puts(prompt, stderr);
- bc_vm_fflush(stderr);
+ fputs(bc_program_ready_msg, stderr);
+ if (!bcg.posix) fputs(prompt, stderr);
+ fflush(stderr);
}
continue;
}
#endif
- return BC_STATUS_IO_ERR;
+ return BC_STATUS_INPUT_EOF;
}
c = (signed char) i;
if (i > UCHAR_MAX || BC_READ_BIN_CHAR(c)) return BC_STATUS_BIN_FILE;
bc_vec_push(vec, &c);
- }
+ } while (c != '\n');
bc_vec_pushByte(vec, '\0');
*flags = getopt32(argv, bc_args_opt);
#endif
- if ((*flags) & BC_FLAG_V) bc_vm_info(NULL);
+ if ((*flags) & BC_FLAG_V) bc_vm_info();
if (do_exit) exit((int) s);
if (argv[optind] && !strcmp(argv[optind], "--")) ++optind;
static void bc_num_printNewline(size_t *nchars, size_t line_len)
{
if (*nchars == line_len - 1) {
- bc_vm_putchar('\\');
- bc_vm_putchar('\n');
+ bb_putchar('\\');
+ bb_putchar('\n');
*nchars = 0;
}
}
size_t *nchars, size_t line_len)
{
(void) radix, (void) line_len;
- bc_vm_putchar((char) num);
+ bb_putchar((char) num);
*nchars = *nchars + width;
}
#endif
size_t exp, pow;
bc_num_printNewline(nchars, line_len);
- bc_vm_putchar(radix ? '.' : ' ');
+ bb_putchar(radix ? '.' : ' ');
++(*nchars);
bc_num_printNewline(nchars, line_len);
bc_num_printNewline(nchars, line_len);
dig = num / pow;
num -= dig * pow;
- bc_vm_putchar(((char) dig) + '0');
+ bb_putchar(((char) dig) + '0');
}
}
{
if (radix) {
bc_num_printNewline(nchars, line_len);
- bc_vm_putchar('.');
+ bb_putchar('.');
*nchars += 1;
}
bc_num_printNewline(nchars, line_len);
- bc_vm_putchar(bb_hexdigits_upcase[num]);
+ bb_putchar(bb_hexdigits_upcase[num]);
*nchars = *nchars + width;
}
{
size_t i, rdx = n->rdx - 1;
- if (n->neg) bc_vm_putchar('-');
+ if (n->neg) bb_putchar('-');
(*nchars) += n->neg;
for (i = n->len - 1; i < n->len; --i)
BcNumDigitOp print;
bool neg = n->neg;
- if (neg) bc_vm_putchar('-');
+ if (neg) bb_putchar('-');
(*nchars) += neg;
n->neg = false;
bc_num_printNewline(nchars, line_len);
if (n->len == 0) {
- bc_vm_putchar('0');
+ bb_putchar('0');
++(*nchars);
}
else if (base_t == 10)
s = bc_num_printBase(n, base, base_t, nchars, line_len);
if (newline) {
- bc_vm_putchar('\n');
+ bb_putchar('\n');
*nchars = 0;
}
#if ENABLE_DC
if (len == 0) {
- bc_vm_putchar('\0');
+ bb_putchar('\0');
return;
}
#endif
int c = str[i];
if (c != '\\' || i == len - 1)
- bc_vm_putchar(c);
+ bb_putchar(c);
else {
c = str[++i];
case 'a':
{
- bc_vm_putchar('\a');
+ bb_putchar('\a');
break;
}
case 'b':
{
- bc_vm_putchar('\b');
+ bb_putchar('\b');
break;
}
case '\\':
case 'e':
{
- bc_vm_putchar('\\');
+ bb_putchar('\\');
break;
}
case 'f':
{
- bc_vm_putchar('\f');
+ bb_putchar('\f');
break;
}
case 'n':
{
- bc_vm_putchar('\n');
+ bb_putchar('\n');
*nchars = SIZE_MAX;
break;
}
case 'r':
{
- bc_vm_putchar('\r');
+ bb_putchar('\r');
break;
}
case 'q':
{
- bc_vm_putchar('"');
+ bb_putchar('"');
break;
}
case 't':
{
- bc_vm_putchar('\t');
+ bb_putchar('\t');
break;
}
default:
{
// Just print the backslash and following character.
- bc_vm_putchar('\\');
+ bb_putchar('\\');
++(*nchars);
- bc_vm_putchar(c);
+ bb_putchar(c);
break;
}
}
if (inst == BC_INST_PRINT_STR) {
for (i = 0, len = strlen(str); i < len; ++i) {
char c = str[i];
- bc_vm_putchar(c);
+ bb_putchar(c);
if (c == '\n') p->nchars = SIZE_MAX;
++p->nchars;
}
}
else {
bc_program_printString(str, &p->nchars);
- if (inst == BC_INST_PRINT) bc_vm_putchar('\n');
+ if (inst == BC_INST_PRINT) bb_putchar('\n');
}
}
else {
idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx;
str = *((char **) bc_vec_item(&p->strs, idx));
- bc_vm_printf(stdout, "%s", str);
+ printf("%s", str);
}
return s;
if (!s || s == BC_STATUS_EXEC_SIGNAL) {
if (bcg.ttyin) {
- bc_vm_puts(bc_program_ready_msg, stderr);
- bc_vm_fflush(stderr);
+ fputs(bc_program_ready_msg, stderr);
+ fflush(stderr);
s = BC_STATUS_SUCCESS;
}
else
}
#endif
-static void bc_vm_info(const char *const help)
+static void bc_vm_info(void)
{
- bc_vm_printf(stdout, "%s %s\n", bcg.name, "1.1");
- bc_vm_puts(bc_copyright, stdout);
- if (help) bc_vm_printf(stdout, help, bcg.name);
+ printf("%s "BB_VER"\n"
+ "Copyright (c) 2018 Gavin D. Howard and contributors\n"
+ "Report bugs at: https://github.com/gavinhoward/bc\n\n"
+ "This is free software with ABSOLUTELY NO WARRANTY\n"
+ , applet_name);
}
static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line)
{
if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s;
- bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
- bc_vm_printf(stderr, " %s", file);
- bc_vm_printf(stderr, bc_err_line + 4 * !line, line);
+ fprintf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
+ fprintf(stderr, " %s", file);
+ fprintf(stderr, bc_err_line + 4 * !line, line);
return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name));
}
if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
- bc_vm_printf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
- if (msg) bc_vm_printf(stderr, " %s\n", msg);
- bc_vm_printf(stderr, " %s", file);
- bc_vm_printf(stderr, bc_err_line + 4 * !line, line);
+ fprintf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
+ if (msg) fprintf(stderr, " %s\n", msg);
+ fprintf(stderr, " %s", file);
+ fprintf(stderr, bc_err_line + 4 * !line, line);
return s * (!bcg.ttyin && !!p);
}
return len;
}
-static void bc_vm_exit(BcStatus s)
-{
- bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
- exit((int) s);
-}
-
-static void bc_vm_printf(FILE *restrict f, const char *fmt, ...)
-{
- va_list args;
- bool bad;
-
- va_start(args, fmt);
- bad = vfprintf(f, fmt, args) < 0;
- va_end(args);
-
- if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
-}
-
-static void bc_vm_puts(const char *str, FILE *restrict f)
-{
- if (fputs(str, f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
-}
-
-static void bc_vm_putchar(int c)
-{
- if (putchar(c) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
-}
-
-static void bc_vm_fflush(FILE *restrict f)
-{
- if (fflush(f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
-}
-
static BcStatus bc_vm_process(BcVm *vm, const char *text)
{
BcStatus s = bc_parse_text(&vm->prs, text);
if (s == BC_STATUS_LIMITS) {
- bc_vm_putchar('\n');
- bc_vm_printf(stdout, "BC_BASE_MAX = %lu\n", BC_MAX_OBASE);
- bc_vm_printf(stdout, "BC_DIM_MAX = %lu\n", BC_MAX_DIM);
- bc_vm_printf(stdout, "BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);
- bc_vm_printf(stdout, "BC_STRING_MAX = %lu\n", BC_MAX_STRING);
- bc_vm_printf(stdout, "BC_NAME_MAX = %lu\n", BC_MAX_NAME);
- bc_vm_printf(stdout, "BC_NUM_MAX = %lu\n", BC_MAX_NUM);
- bc_vm_printf(stdout, "Max Exponent = %lu\n", BC_MAX_EXP);
- bc_vm_printf(stdout, "Number of Vars = %lu\n", BC_MAX_VARS);
- bc_vm_putchar('\n');
+ bb_putchar('\n');
+ printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE);
+ printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM);
+ printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);
+ printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);
+ printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);
+ printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);
+ printf("Max Exponent = %lu\n", BC_MAX_EXP);
+ printf("Number of Vars = %lu\n", BC_MAX_VARS);
+ bb_putchar('\n');
s = BC_STATUS_SUCCESS;
}
if (BC_PARSE_CAN_EXEC(&vm->prs)) {
s = bc_program_exec(&vm->prog);
- if (!s && bcg.tty) bc_vm_fflush(stdout);
+ if (!s && bcg.tty) fflush(stdout);
if (s && s != BC_STATUS_QUIT)
s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0);
}
// I/O error will always happen when stdin is
// closed. It's not a problem in that case.
- s = s == BC_STATUS_IO_ERR || s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
+ if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT)
+ s = BC_STATUS_SUCCESS;
if (str)
s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f,
s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i)));
if (s && s != BC_STATUS_QUIT) return s;
- if (bcg.bc || !vm->files.len) s = bc_vm_stdin(vm);
+ if (IS_BC || !vm->files.len) s = bc_vm_stdin(vm);
if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, "");
- return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
+ if (s == BC_STATUS_QUIT)
+ s = BC_STATUS_SUCCESS;
+ return s;
}
static void bc_vm_free(BcVm *vm)
bc_vec_init(&vm->files, sizeof(char *), NULL);
#if ENABLE_BC
- vm->flags |= BC_FLAG_S * bcg.bc * (getenv("POSIXLY_CORRECT") != NULL);
- if (bcg.bc) s = bc_vm_envArgs(vm);
+ vm->flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL);
+ if (IS_BC) s = bc_vm_envArgs(vm);
#endif
bc_program_init(&vm->prog, len, exe.init, exe.exp);
bcg.exreg = vm.flags & BC_FLAG_X;
#endif
- if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL);
+ if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info();
st = bc_vm_exec(&vm);
exit:
{
BcVmExe exec;
- bcg.bc = true;
- bcg.name = bc_name;
# if ENABLE_FEATURE_BC_SIGNALS
bcg.sig_msg = bc_sig_msg;
# endif
{
BcVmExe exec;
- bcg.bc = false;
- bcg.name = dc_name;
# if ENABLE_FEATURE_BC_SIGNALS
bcg.sig_msg = dc_sig_msg;
# endif