diff options
Diffstat (limited to 'src/args.c')
| -rw-r--r-- | src/args.c | 157 |
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; } |
