blob: 7f99c5647e3eb35f6ecab9e9ffa24765c4065e73 [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 for processing command-line arguments.
*
*/
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <status.h>
#include <vector.h>
#include <read.h>
#include <vm.h>
#include <args.h>
static const struct option bc_args_lopt[] = {
{ "expression", required_argument, NULL, 'e' },
{ "file", required_argument, NULL, 'f' },
{ "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' },
{ "extended-register", no_argument, NULL, 'x' },
{ 0, 0, 0, 0 },
};
static const char* const bc_args_opt = "e:f:hilqsvVwx";
static void bc_args_exprs(BcVec *exprs, const char *str) {
bc_vec_concat(exprs, str);
bc_vec_concat(exprs, "\n");
}
static void bc_args_file(BcVec *exprs, const char *file) {
char *buf = bc_read_file(file);
bc_args_exprs(exprs, buf);
free(buf);
}
void bc_args(int argc, char *argv[], unsigned int *flags,
BcVec *exprs, BcVec *files)
{
BcStatus s = BC_STATUS_SUCCESS;
int c, i, idx;
bool do_exit = false;
idx = c = optind = 0;
while ((c = getopt_long(argc, argv, bc_args_opt, bc_args_lopt, &idx)) != -1)
{
switch (c) {
case 0:
{
// This is the case when a long option is found.
break;
}
case 'e':
{
bc_args_exprs(exprs, optarg);
break;
}
case 'f':
{
bc_args_file(exprs, optarg);
break;
}
case 'h':
{
bc_vm_info(bcg.help);
do_exit = true;
break;
}
#ifdef BC_ENABLED
case 'i':
{
if (!bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_I;
break;
}
case 'l':
{
if (!bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_L;
break;
}
case 'q':
{
if (!bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_Q;
break;
}
case 's':
{
if (!bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_S;
break;
}
case 'w':
{
if (!bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_W;
break;
}
#endif // BC_ENABLED
case 'V':
case 'v':
{
bc_vm_info(NULL);
do_exit = true;
break;
}
#ifdef DC_ENABLED
case 'x':
{
if (bcg.bc) s = BC_STATUS_INVALID_OPTION;
(*flags) |= BC_FLAG_X;
break;
}
#endif // DC_ENABLED
// Getopt printed an error message, but we should exit.
case '?':
default:
{
exit(BC_STATUS_INVALID_OPTION);
break;
}
}
if (s) bc_vm_exit(s);
}
if (do_exit) exit((int) s);
if (exprs->len > 1 || !bcg.bc) (*flags) |= BC_FLAG_Q;
if (argv[optind] && strcmp(argv[optind], "--") == 0) ++optind;
for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i);
}