blob: 328735737d1811acb69f2782934d046c2329bc06 [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.
*
* *****************************************************************************
*
* The entry point for bc.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <getopt.h>
#include <bc.h>
static const struct option bc_opts[] = {
{ "code", no_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ "interactive", no_argument, NULL, 'i' },
{ "mathlib", no_argument, NULL, 'l' },
{ "quiet", no_argument, NULL, 'q' },
{ "standard", no_argument, NULL, 's' },
{ "version", no_argument, NULL, 'v' },
{ "warn", no_argument, NULL, 'w' },
{ 0, 0, 0, 0 },
};
static const char *bc_short_opts = "chilqsvw";
static const char *bc_help =
"usage: bc [-hilqsvw] [long-options] [file...]\n"
"\n"
"bc is a command-line calculator with a Turing-complete language.\n"
"\n"
" -c --code print bytecode instead of executing it\n"
" -h --help print this usage message and exit\n"
" -i --interactive force interactive mode\n"
" -l --mathlib use predefined math routines:\n\n"
" s(expr) = sine of expr in radians\n"
" c(expr) = cosine of expr in radians\n"
" a(expr) = arctangent of expr, returning radians\n"
" l(expr) = natural log of expr\n"
" e(expr) = raises e to the power of expr\n"
" j(n, x) = Bessel function of integer order n of x\n"
"\n"
" -q --quiet don't print version and copyright\n"
" -s --standard error if any non-POSIX extensions are used\n"
" -w --warn warn if any non-POSIX extensions are used\n"
" -v --version print version information and copyright and exit\n\n";
BcGlobals bcg;
int main(int argc, char *argv[]) {
BcStatus status;
unsigned int flags;
unsigned int filec;
char** filev;
bool do_exit;
setlocale(LC_ALL, "");
memset(&bcg, 0, sizeof(BcGlobals));
do_exit = false;
flags = 0;
status = BC_STATUS_SUCCESS;
// Getopt needs this.
int opt_idx = 0;
int c = getopt_long(argc, argv, bc_short_opts, bc_opts, &opt_idx);
while (c != -1) {
switch (c) {
case 0:
{
// This is the case when a long option is
// found, so we don't need to do anything.
break;
}
case 'c':
{
flags |= BC_FLAG_CODE;
break;
}
case 'h':
{
if (printf("%s", bc_help) < 0) return BC_STATUS_IO_ERR;
do_exit = true;
break;
}
case 'i':
{
flags |= BC_FLAG_INTERACTIVE;
break;
}
case 'l':
{
flags |= BC_FLAG_MATHLIB;
break;
}
case 'q':
{
flags |= BC_FLAG_QUIET;
break;
}
case 's':
{
flags |= BC_FLAG_STANDARD;
break;
}
case 'v':
{
if (printf("%s", bc_header) < 0) return BC_STATUS_IO_ERR;
do_exit = true;
break;
}
case 'w':
{
flags |= BC_FLAG_WARN;
break;
}
// Getopt printed an error message, but we should exit.
case '?':
default:
{
return BC_STATUS_INVALID_OPTION;
break;
}
}
c = getopt_long(argc, argv, bc_short_opts, bc_opts, &opt_idx);
}
if (do_exit) return status;
if (argv[optind] && strcmp(argv[optind], "--") == 0) ++optind;
filec = argc - optind;
filev = argv + optind;
return bc_main(flags, filec, filev);
}