summaryrefslogtreecommitdiff
path: root/src/args.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/args.c')
-rw-r--r--src/args.c157
1 files changed, 136 insertions, 21 deletions
diff --git a/src/args.c b/src/args.c
index 5eee96f5b559..64fd02c1d7b8 100644
--- a/src/args.c
+++ b/src/args.c
@@ -47,12 +47,15 @@
#include <read.h>
#include <args.h>
#include <opt.h>
+#include <num.h>
/**
* Adds @a str to the list of expressions to execute later.
* @param str The string to add to the list of expressions.
*/
-static void bc_args_exprs(const char *str) {
+static void
+bc_args_exprs(const char* str)
+{
BC_SIG_ASSERT_LOCKED;
if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), BC_DTOR_NONE);
bc_vec_concat(&vm.exprs, str);
@@ -64,9 +67,10 @@ static void bc_args_exprs(const char *str) {
* @param file The name of the file whose contents should be added to the list
* of expressions to execute.
*/
-static void bc_args_file(const char *file) {
-
- char *buf;
+static void
+bc_args_file(const char* file)
+{
+ char* buf;
BC_SIG_ASSERT_LOCKED;
@@ -80,6 +84,31 @@ static void bc_args_file(const char *file) {
free(buf);
}
+static BcBigDig
+bc_args_builtin(const char* arg)
+{
+ bool strvalid;
+ BcNum n;
+ BcBigDig res;
+
+ strvalid = bc_num_strValid(arg);
+
+ if (BC_ERR(!strvalid))
+ {
+ bc_verr(BC_ERR_FATAL_ARG, arg);
+ }
+
+ bc_num_init(&n, 0);
+
+ bc_num_parse(&n, arg, 10);
+
+ res = bc_num_bigdig(&n);
+
+ bc_num_free(&n);
+
+ return res;
+}
+
#if BC_ENABLED
/**
@@ -87,18 +116,19 @@ static void bc_args_file(const char *file) {
* throws a fatal error.
* @param keyword The keyword to redefine.
*/
-static void bc_args_redefine(const char *keyword) {
-
+static void
+bc_args_redefine(const char* keyword)
+{
size_t i;
BC_SIG_ASSERT_LOCKED;
- for (i = 0; i < bc_lex_kws_len; ++i) {
-
- const BcLexKeyword *kw = bc_lex_kws + i;
-
- if (!strcmp(keyword, kw->name)) {
+ for (i = 0; i < bc_lex_kws_len; ++i)
+ {
+ const BcLexKeyword* kw = bc_lex_kws + i;
+ if (!strcmp(keyword, kw->name))
+ {
if (BC_LEX_KW_POSIX(kw)) break;
vm.redefined_kws[i] = true;
@@ -112,12 +142,17 @@ static void bc_args_redefine(const char *keyword) {
#endif // BC_ENABLED
-void bc_args(int argc, char *argv[], bool exit_exprs) {
-
+void
+bc_args(int argc, char* argv[], bool exit_exprs, BcBigDig scale)
+{
int c;
size_t i;
bool do_exit = false, version = false;
BcOpt opts;
+ BcBigDig newscale = scale, ibase = BC_BASE, obase = BC_BASE;
+#if BC_ENABLE_EXTRA_MATH
+ char* seed = NULL;
+#endif // BC_ENABLE_EXTRA_MATH
BC_SIG_ASSERT_LOCKED;
@@ -125,15 +160,17 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
// This loop should look familiar to anyone who has used getopt() or
// getopt_long() in C.
- while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1) {
-
- switch (c) {
-
+ while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1)
+ {
+ switch (c)
+ {
case 'e':
{
// Barf if not allowed.
if (vm.no_exprs)
+ {
bc_verr(BC_ERR_FATAL_OPTION, "-e (--expression)");
+ }
// Add the expressions and set exit.
bc_args_exprs(opts.optarg);
@@ -146,13 +183,15 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
{
// Figure out if exiting on expressions is disabled.
if (!strcmp(opts.optarg, "-")) vm.no_exprs = true;
- else {
-
+ else
+ {
// Barf if not allowed.
if (vm.no_exprs)
+ {
bc_verr(BC_ERR_FATAL_OPTION, "-f (--file)");
+ }
- // Add the expressions and set exit.
+ // Add the expressions and set exit.
bc_args_file(opts.optarg);
vm.exit_exprs = (exit_exprs || vm.exit_exprs);
}
@@ -173,6 +212,12 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
break;
}
+ case 'I':
+ {
+ ibase = bc_args_builtin(opts.optarg);
+ break;
+ }
+
case 'z':
{
vm.flags |= BC_FLAG_Z;
@@ -185,6 +230,12 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
break;
}
+ case 'O':
+ {
+ obase = bc_args_builtin(opts.optarg);
+ break;
+ }
+
case 'P':
{
vm.flags &= ~(BC_FLAG_P);
@@ -197,6 +248,26 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
break;
}
+ case 'S':
+ {
+ newscale = bc_args_builtin(opts.optarg);
+ break;
+ }
+
+#if BC_ENABLE_EXTRA_MATH
+ case 'E':
+ {
+ if (BC_ERR(!bc_num_strValid(opts.optarg)))
+ {
+ bc_verr(BC_ERR_FATAL_ARG, opts.optarg);
+ }
+
+ seed = opts.optarg;
+
+ break;
+ }
+#endif // BC_ENABLE_EXTRA_MATH
+
#if BC_ENABLED
case 'g':
{
@@ -271,7 +342,8 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
}
if (version) bc_vm_info(NULL);
- if (do_exit) {
+ if (do_exit)
+ {
vm.status = (sig_atomic_t) BC_STATUS_QUIT;
BC_JMP;
}
@@ -282,9 +354,52 @@ void bc_args(int argc, char *argv[], bool exit_exprs) {
// We need to make sure the files list is initialized. We don't want to
// initialize it if there are no files because it's just a waste of memory.
if (opts.optind < (size_t) argc && vm.files.v == NULL)
+ {
bc_vec_init(&vm.files, sizeof(char*), BC_DTOR_NONE);
+ }
// Add all the files to the vector.
for (i = opts.optind; i < (size_t) argc; ++i)
+ {
bc_vec_push(&vm.files, argv + i);
+ }
+
+#if BC_ENABLE_EXTRA_MATH
+ if (seed != NULL)
+ {
+ BcNum n;
+
+ bc_num_init(&n, strlen(seed));
+
+ BC_SIG_UNLOCK;
+
+ bc_num_parse(&n, seed, BC_BASE);
+
+ bc_program_assignSeed(&vm.prog, &n);
+
+ BC_SIG_LOCK;
+
+ bc_num_free(&n);
+ }
+#endif // BC_ENABLE_EXTRA_MATH
+
+ BC_SIG_UNLOCK;
+
+ if (newscale != scale)
+ {
+ bc_program_assignBuiltin(&vm.prog, true, false, newscale);
+ }
+
+ if (obase != BC_BASE)
+ {
+ bc_program_assignBuiltin(&vm.prog, false, true, obase);
+ }
+
+ // This is last to avoid it affecting the value of the others.
+ if (ibase != BC_BASE)
+ {
+ bc_program_assignBuiltin(&vm.prog, false, false, ibase);
+ }
+
+ BC_SIG_LOCK;
}