contrib/bc: merge version 5.2.1 from vendor branch

Merge commit 'e63540eed295749528548c2e3a90f5a6e57275c8'
This commit is contained in:
Stefan Eßer 2021-11-30 18:40:32 +01:00
commit 10041e99a0
94 changed files with 1244 additions and 364 deletions

View File

@ -29,6 +29,15 @@
# #
.POSIX: .POSIX:
ROOTDIR = %%ROOTDIR%%
INCDIR = $(ROOTDIR)/include
SRCDIR = $(ROOTDIR)/src
TESTSDIR = $(ROOTDIR)/tests
SCRIPTSDIR = $(ROOTDIR)/scripts
GENDIR = $(ROOTDIR)/gen
BUILDDIR = %%BUILDDIR%%
SRC = %%SRC%% SRC = %%SRC%%
OBJ = %%OBJ%% OBJ = %%OBJ%%
GCDA = %%GCDA%% GCDA = %%GCDA%%
@ -39,46 +48,45 @@ BC_ENABLED = %%BC_ENABLED%%
DC_ENABLED_NAME = DC_ENABLED DC_ENABLED_NAME = DC_ENABLED
DC_ENABLED = %%DC_ENABLED%% DC_ENABLED = %%DC_ENABLED%%
HEADERS = include/args.h include/file.h include/lang.h include/lex.h include/num.h include/opt.h include/parse.h include/program.h include/read.h include/status.h include/vector.h include/vm.h HEADERS = $(INCDIR)/args.h $(INCDIR)/file.h $(INCDIR)/lang.h $(INCDIR)/lex.h $(INCDIR)/num.h $(INCDIR)/opt.h $(INCDIR)/parse.h $(INCDIR)/program.h $(INCDIR)/read.h $(INCDIR)/status.h $(INCDIR)/vector.h $(INCDIR)/vm.h
BC_HEADERS = include/bc.h BC_HEADERS = $(INCDIR)/bc.h
DC_HEADERS = include/dc.h DC_HEADERS = $(INCDIR)/dc.h
HISTORY_HEADERS = include/history.h HISTORY_HEADERS = $(INCDIR)/history.h
EXTRA_MATH_HEADERS = include/rand.h EXTRA_MATH_HEADERS = $(INCDIR)/rand.h
LIBRARY_HEADERS = include/bcl.h include/library.h LIBRARY_HEADERS = $(INCDIR)/bcl.h $(INCDIR)/library.h
GEN_DIR = gen GEN_DIR = gen
GEN = %%GEN%% GEN = %%GEN%%
GEN_EXEC = $(GEN_DIR)/$(GEN) GEN_EXEC = $(GEN_DIR)/$(GEN)
GEN_C = $(GEN_DIR)/$(GEN).c GEN_C = $(GENDIR)/$(GEN).c
GEN_EMU = %%GEN_EMU%% GEN_EMU = %%GEN_EMU%%
BC_LIB = $(GEN_DIR)/lib.bc BC_LIB = $(GENDIR)/lib.bc
BC_LIB_C = $(GEN_DIR)/lib.c BC_LIB_C = $(GEN_DIR)/lib.c
BC_LIB_O = %%BC_LIB_O%% BC_LIB_O = %%BC_LIB_O%%
BC_LIB_GCDA = $(GEN_DIR)/lib.gcda BC_LIB_GCDA = $(GEN_DIR)/lib.gcda
BC_LIB_GCNO = $(GEN_DIR)/lib.gcno BC_LIB_GCNO = $(GEN_DIR)/lib.gcno
BC_LIB2 = $(GEN_DIR)/lib2.bc BC_LIB2 = $(GENDIR)/lib2.bc
BC_LIB2_C = $(GEN_DIR)/lib2.c BC_LIB2_C = $(GEN_DIR)/lib2.c
BC_LIB2_O = %%BC_LIB2_O%% BC_LIB2_O = %%BC_LIB2_O%%
BC_LIB2_GCDA = $(GEN_DIR)/lib2.gcda BC_LIB2_GCDA = $(GEN_DIR)/lib2.gcda
BC_LIB2_GCNO = $(GEN_DIR)/lib2.gcno BC_LIB2_GCNO = $(GEN_DIR)/lib2.gcno
BC_HELP = $(GEN_DIR)/bc_help.txt BC_HELP = $(GENDIR)/bc_help.txt
BC_HELP_C = $(GEN_DIR)/bc_help.c BC_HELP_C = $(GEN_DIR)/bc_help.c
BC_HELP_O = %%BC_HELP_O%% BC_HELP_O = %%BC_HELP_O%%
BC_HELP_GCDA = $(GEN_DIR)/bc_help.gcda BC_HELP_GCDA = $(GEN_DIR)/bc_help.gcda
BC_HELP_GCNO = $(GEN_DIR)/bc_help.gcno BC_HELP_GCNO = $(GEN_DIR)/bc_help.gcno
DC_HELP = $(GEN_DIR)/dc_help.txt DC_HELP = $(GENDIR)/dc_help.txt
DC_HELP_C = $(GEN_DIR)/dc_help.c DC_HELP_C = $(GEN_DIR)/dc_help.c
DC_HELP_O = %%DC_HELP_O%% DC_HELP_O = %%DC_HELP_O%%
DC_HELP_GCDA = $(GEN_DIR)/dc_help.gcda DC_HELP_GCDA = $(GEN_DIR)/dc_help.gcda
DC_HELP_GCNO = $(GEN_DIR)/dc_help.gcno DC_HELP_GCNO = $(GEN_DIR)/dc_help.gcno
BIN = bin BIN = bin
LOCALES = locales
EXEC_SUFFIX = %%EXECSUFFIX%% EXEC_SUFFIX = %%EXECSUFFIX%%
EXEC_PREFIX = %%EXECPREFIX%% EXEC_PREFIX = %%EXECPREFIX%%
@ -97,7 +105,7 @@ LIB_NAME = $(LIB).a
LIBBC = $(BIN)/$(LIB_NAME) LIBBC = $(BIN)/$(LIB_NAME)
BCL = bcl BCL = bcl
BCL_TEST = $(BIN)/$(BCL) BCL_TEST = $(BIN)/$(BCL)
BCL_TEST_C = tests/$(BCL).c BCL_TEST_C = $(TESTSDIR)/$(BCL).c
MANUALS = manuals MANUALS = manuals
BC_MANPAGE_NAME = $(EXEC_PREFIX)$(BC)$(EXEC_SUFFIX).1 BC_MANPAGE_NAME = $(EXEC_PREFIX)$(BC)$(EXEC_SUFFIX).1
@ -112,9 +120,13 @@ BCL_MD = $(BCL_MANPAGE).md
MANPAGE_INSTALL_ARGS = -Dm644 MANPAGE_INSTALL_ARGS = -Dm644
BINARY_INSTALL_ARGS = -Dm755 BINARY_INSTALL_ARGS = -Dm755
PC_INSTALL_ARGS = $(MANPAGE_INSTALL_ARGS)
BCL_PC = $(BCL).pc
PC_PATH = %%PC_PATH%%
BCL_HEADER_NAME = bcl.h BCL_HEADER_NAME = bcl.h
BCL_HEADER = include/$(BCL_HEADER_NAME) BCL_HEADER = $(INCDIR)/$(BCL_HEADER_NAME)
%%DESTDIR%% %%DESTDIR%%
BINDIR = %%BINDIR%% BINDIR = %%BINDIR%%
@ -146,6 +158,8 @@ BC_DEFAULT_TTY_MODE = %%BC_DEFAULT_TTY_MODE%%
DC_DEFAULT_TTY_MODE = %%DC_DEFAULT_TTY_MODE%% DC_DEFAULT_TTY_MODE = %%DC_DEFAULT_TTY_MODE%%
BC_DEFAULT_PROMPT = %%BC_DEFAULT_PROMPT%% BC_DEFAULT_PROMPT = %%BC_DEFAULT_PROMPT%%
DC_DEFAULT_PROMPT = %%DC_DEFAULT_PROMPT%% DC_DEFAULT_PROMPT = %%DC_DEFAULT_PROMPT%%
BC_DEFAULT_EXPR_EXIT = %%BC_DEFAULT_EXPR_EXIT%%
DC_DEFAULT_EXPR_EXIT = %%DC_DEFAULT_EXPR_EXIT%%
RM = rm RM = rm
MKDIR = mkdir MKDIR = mkdir
@ -158,13 +172,13 @@ MINISTAT_EXEC = $(SCRIPTS)/$(MINISTAT)
BITFUNCGEN = bitfuncgen BITFUNCGEN = bitfuncgen
BITFUNCGEN_EXEC = $(SCRIPTS)/$(BITFUNCGEN) BITFUNCGEN_EXEC = $(SCRIPTS)/$(BITFUNCGEN)
INSTALL = $(SCRIPTS)/exec-install.sh INSTALL = $(SCRIPTSDIR)/exec-install.sh
SAFE_INSTALL = $(SCRIPTS)/safe-install.sh SAFE_INSTALL = $(SCRIPTSDIR)/safe-install.sh
LINK = $(SCRIPTS)/link.sh LINK = $(SCRIPTSDIR)/link.sh
MANPAGE = $(SCRIPTS)/manpage.sh MANPAGE = $(SCRIPTSDIR)/manpage.sh
KARATSUBA = $(SCRIPTS)/karatsuba.py KARATSUBA = $(SCRIPTSDIR)/karatsuba.py
LOCALE_INSTALL = $(SCRIPTS)/locale_install.sh LOCALE_INSTALL = $(SCRIPTSDIR)/locale_install.sh
LOCALE_UNINSTALL = $(SCRIPTS)/locale_uninstall.sh LOCALE_UNINSTALL = $(SCRIPTSDIR)/locale_uninstall.sh
VALGRIND_ARGS = --error-exitcode=100 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all VALGRIND_ARGS = --error-exitcode=100 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all
@ -176,14 +190,16 @@ BC_DEFS0 = -DBC_DEFAULT_BANNER=$(BC_DEFAULT_BANNER)
BC_DEFS1 = -DBC_DEFAULT_SIGINT_RESET=$(BC_DEFAULT_SIGINT_RESET) BC_DEFS1 = -DBC_DEFAULT_SIGINT_RESET=$(BC_DEFAULT_SIGINT_RESET)
BC_DEFS2 = -DBC_DEFAULT_TTY_MODE=$(BC_DEFAULT_TTY_MODE) BC_DEFS2 = -DBC_DEFAULT_TTY_MODE=$(BC_DEFAULT_TTY_MODE)
BC_DEFS3 = -DBC_DEFAULT_PROMPT=$(BC_DEFAULT_PROMPT) BC_DEFS3 = -DBC_DEFAULT_PROMPT=$(BC_DEFAULT_PROMPT)
BC_DEFS = $(BC_DEFS0) $(BC_DEFS1) $(BC_DEFS2) $(BC_DEFS3) BC_DEFS4 = -DBC_DEFAULT_EXPR_EXIT=$(BC_DEFAULT_EXPR_EXIT)
BC_DEFS = $(BC_DEFS0) $(BC_DEFS1) $(BC_DEFS2) $(BC_DEFS3) $(BC_DEFS4)
DC_DEFS1 = -DDC_DEFAULT_SIGINT_RESET=$(DC_DEFAULT_SIGINT_RESET) DC_DEFS1 = -DDC_DEFAULT_SIGINT_RESET=$(DC_DEFAULT_SIGINT_RESET)
DC_DEFS2 = -DDC_DEFAULT_TTY_MODE=$(DC_DEFAULT_TTY_MODE) DC_DEFS2 = -DDC_DEFAULT_TTY_MODE=$(DC_DEFAULT_TTY_MODE)
DC_DEFS3 = -DDC_DEFAULT_PROMPT=$(DC_DEFAULT_PROMPT) DC_DEFS3 = -DDC_DEFAULT_PROMPT=$(DC_DEFAULT_PROMPT)
DC_DEFS = $(DC_DEFS1) $(DC_DEFS2) $(DC_DEFS3) DC_DEFS4 = -DDC_DEFAULT_EXPR_EXIT=$(DC_DEFAULT_EXPR_EXIT)
DC_DEFS = $(DC_DEFS1) $(DC_DEFS2) $(DC_DEFS3) $(DC_DEFS4)
CPPFLAGS1 = -D$(BC_ENABLED_NAME)=$(BC_ENABLED) -D$(DC_ENABLED_NAME)=$(DC_ENABLED) CPPFLAGS1 = -D$(BC_ENABLED_NAME)=$(BC_ENABLED) -D$(DC_ENABLED_NAME)=$(DC_ENABLED)
CPPFLAGS2 = $(CPPFLAGS1) -I./include/ -DBUILD_TYPE=$(BC_BUILD_TYPE) %%LONG_BIT_DEFINE%% CPPFLAGS2 = $(CPPFLAGS1) -I$(INCDIR)/ -DBUILD_TYPE=$(BC_BUILD_TYPE) %%LONG_BIT_DEFINE%%
CPPFLAGS3 = $(CPPFLAGS2) -DEXECPREFIX=$(EXEC_PREFIX) -DMAINEXEC=$(MAIN_EXEC) CPPFLAGS3 = $(CPPFLAGS2) -DEXECPREFIX=$(EXEC_PREFIX) -DMAINEXEC=$(MAIN_EXEC)
CPPFLAGS4 = $(CPPFLAGS3) -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 %%BSD%% CPPFLAGS4 = $(CPPFLAGS3) -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 %%BSD%%
CPPFLAGS5 = $(CPPFLAGS4) -DBC_NUM_KARATSUBA_LEN=$(BC_NUM_KARATSUBA_LEN) CPPFLAGS5 = $(CPPFLAGS4) -DBC_NUM_KARATSUBA_LEN=$(BC_NUM_KARATSUBA_LEN)
@ -212,7 +228,10 @@ all: %%DEFAULT_TARGET%%
%%SECOND_TARGET%%: %%SECOND_TARGET_PREREQS%% %%SECOND_TARGET%%: %%SECOND_TARGET_PREREQS%%
%%SECOND_TARGET_CMD%% %%SECOND_TARGET_CMD%%
$(GEN_EXEC): $(GEN_DIR):
mkdir -p $(GEN_DIR)
$(GEN_EXEC): $(GEN_DIR)
%%GEN_EXEC_TARGET%% %%GEN_EXEC_TARGET%%
$(BC_LIB_C): $(GEN_EXEC) $(BC_LIB) $(BC_LIB_C): $(GEN_EXEC) $(BC_LIB)
@ -242,13 +261,18 @@ $(DC_HELP_O): $(DC_HELP_C)
$(BIN): $(BIN):
$(MKDIR) -p $(BIN) $(MKDIR) -p $(BIN)
src:
$(MKDIR) -p src
headers: %%HEADERS%% headers: %%HEADERS%%
$(MINISTAT): $(MINISTAT):
$(HOSTCC) $(HOSTCFLAGS) -lm -o $(MINISTAT_EXEC) scripts/ministat.c mkdir -p $(SCRIPTS)
$(HOSTCC) $(HOSTCFLAGS) -lm -o $(MINISTAT_EXEC) $(ROOTDIR)/scripts/ministat.c
$(BITFUNCGEN): $(BITFUNCGEN):
$(HOSTCC) $(HOSTCFLAGS) -lm -o $(BITFUNCGEN_EXEC) scripts/bitfuncgen.c mkdir -p $(SCRIPTS)
$(HOSTCC) $(HOSTCFLAGS) -lm -o $(BITFUNCGEN_EXEC) $(ROOTDIR)/scripts/bitfuncgen.c
help: help:
@printf 'available targets:\n' @printf 'available targets:\n'
@ -314,18 +338,18 @@ test_bc_tests:%%BC_TESTS%%
test_bc_scripts:%%BC_SCRIPT_TESTS%% test_bc_scripts:%%BC_SCRIPT_TESTS%%
test_bc_stdin: test_bc_stdin:
@sh tests/stdin.sh bc %%BC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/stdin.sh bc %%BC_TEST_EXEC%%
test_bc_read: test_bc_read:
@sh tests/read.sh bc %%BC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/read.sh bc %%BC_TEST_EXEC%%
test_bc_errors: test_bc_error_lines%%BC_ERROR_TESTS%% test_bc_errors: test_bc_error_lines%%BC_ERROR_TESTS%%
test_bc_error_lines: test_bc_error_lines:
@sh tests/errors.sh bc %%BC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/errors.sh bc %%BC_TEST_EXEC%%
test_bc_other: test_bc_other:
@sh tests/other.sh bc $(BC_ENABLE_EXTRA_MATH) %%BC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/other.sh bc $(BC_ENABLE_EXTRA_MATH) %%BC_TEST_EXEC%%
test_bc_header: test_bc_header:
@printf '$(TEST_STARS)\n\nRunning bc tests...\n\n' @printf '$(TEST_STARS)\n\nRunning bc tests...\n\n'
@ -338,18 +362,18 @@ test_dc_tests:%%DC_TESTS%%
test_dc_scripts:%%DC_SCRIPT_TESTS%% test_dc_scripts:%%DC_SCRIPT_TESTS%%
test_dc_stdin: test_dc_stdin:
@sh tests/stdin.sh dc %%DC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/stdin.sh dc %%DC_TEST_EXEC%%
test_dc_read: test_dc_read:
@sh tests/read.sh dc %%DC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/read.sh dc %%DC_TEST_EXEC%%
test_dc_errors: test_dc_error_lines%%DC_ERROR_TESTS%% test_dc_errors: test_dc_error_lines%%DC_ERROR_TESTS%%
test_dc_error_lines: test_dc_error_lines:
@sh tests/errors.sh dc %%DC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/errors.sh dc %%DC_TEST_EXEC%%
test_dc_other: test_dc_other:
@sh tests/other.sh dc $(BC_ENABLE_EXTRA_MATH) %%DC_TEST_EXEC%% @export BC_TEST_OUTPUT_DIR="$(BUILDDIR)/tests"; sh $(TESTSDIR)/other.sh dc $(BC_ENABLE_EXTRA_MATH) %%DC_TEST_EXEC%%
test_dc_header: test_dc_header:
@printf '$(TEST_STARS)\n\nRunning dc tests...\n\n' @printf '$(TEST_STARS)\n\nRunning dc tests...\n\n'
@ -368,107 +392,110 @@ test_bc_history_skip:
@printf 'No bc history tests to run\n' @printf 'No bc history tests to run\n'
test_bc_history0: test_bc_history0:
@sh tests/history.sh bc 0 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 0 %%BC_TEST_EXEC%%
test_bc_history1: test_bc_history1:
@sh tests/history.sh bc 1 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 1 %%BC_TEST_EXEC%%
test_bc_history2: test_bc_history2:
@sh tests/history.sh bc 2 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 2 %%BC_TEST_EXEC%%
test_bc_history3: test_bc_history3:
@sh tests/history.sh bc 3 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 3 %%BC_TEST_EXEC%%
test_bc_history4: test_bc_history4:
@sh tests/history.sh bc 4 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 4 %%BC_TEST_EXEC%%
test_bc_history5: test_bc_history5:
@sh tests/history.sh bc 5 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 5 %%BC_TEST_EXEC%%
test_bc_history6: test_bc_history6:
@sh tests/history.sh bc 6 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 6 %%BC_TEST_EXEC%%
test_bc_history7: test_bc_history7:
@sh tests/history.sh bc 7 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 7 %%BC_TEST_EXEC%%
test_bc_history8: test_bc_history8:
@sh tests/history.sh bc 8 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 8 %%BC_TEST_EXEC%%
test_bc_history9: test_bc_history9:
@sh tests/history.sh bc 9 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 9 %%BC_TEST_EXEC%%
test_bc_history10: test_bc_history10:
@sh tests/history.sh bc 10 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 10 %%BC_TEST_EXEC%%
test_bc_history11: test_bc_history11:
@sh tests/history.sh bc 11 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 11 %%BC_TEST_EXEC%%
test_bc_history12: test_bc_history12:
@sh tests/history.sh bc 12 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 12 %%BC_TEST_EXEC%%
test_bc_history13: test_bc_history13:
@sh tests/history.sh bc 13 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 13 %%BC_TEST_EXEC%%
test_bc_history14: test_bc_history14:
@sh tests/history.sh bc 14 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 14 %%BC_TEST_EXEC%%
test_bc_history15: test_bc_history15:
@sh tests/history.sh bc 15 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 15 %%BC_TEST_EXEC%%
test_bc_history16: test_bc_history16:
@sh tests/history.sh bc 16 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 16 %%BC_TEST_EXEC%%
test_bc_history17: test_bc_history17:
@sh tests/history.sh bc 17 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 17 %%BC_TEST_EXEC%%
test_bc_history18: test_bc_history18:
@sh tests/history.sh bc 18 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 18 %%BC_TEST_EXEC%%
test_bc_history19: test_bc_history19:
@sh tests/history.sh bc 19 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 19 %%BC_TEST_EXEC%%
test_bc_history20: test_bc_history20:
@sh tests/history.sh bc 20 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 20 %%BC_TEST_EXEC%%
test_bc_history21: test_bc_history21:
@sh tests/history.sh bc 21 %%BC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh bc 21 %%BC_TEST_EXEC%%
test_dc_history:%%DC_HISTORY_TEST_PREREQS%% test_dc_history:%%DC_HISTORY_TEST_PREREQS%%
test_dc_history_all: test_dc_history0 test_dc_history1 test_dc_history2 test_dc_history3 test_dc_history4 test_dc_history5 test_dc_history6 test_dc_history7 test_dc_history8 test_dc_history9 test_dc_history_all: test_dc_history0 test_dc_history1 test_dc_history2 test_dc_history3 test_dc_history4 test_dc_history5 test_dc_history6 test_dc_history7 test_dc_history8 test_dc_history9 test_dc_history10
test_dc_history_skip: test_dc_history_skip:
@printf 'No dc history tests to run\n' @printf 'No dc history tests to run\n'
test_dc_history0: test_dc_history0:
@sh tests/history.sh dc 0 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 0 %%DC_TEST_EXEC%%
test_dc_history1: test_dc_history1:
@sh tests/history.sh dc 1 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 1 %%DC_TEST_EXEC%%
test_dc_history2: test_dc_history2:
@sh tests/history.sh dc 2 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 2 %%DC_TEST_EXEC%%
test_dc_history3: test_dc_history3:
@sh tests/history.sh dc 3 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 3 %%DC_TEST_EXEC%%
test_dc_history4: test_dc_history4:
@sh tests/history.sh dc 4 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 4 %%DC_TEST_EXEC%%
test_dc_history5: test_dc_history5:
@sh tests/history.sh dc 5 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 5 %%DC_TEST_EXEC%%
test_dc_history6: test_dc_history6:
@sh tests/history.sh dc 6 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 6 %%DC_TEST_EXEC%%
test_dc_history7: test_dc_history7:
@sh tests/history.sh dc 7 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 7 %%DC_TEST_EXEC%%
test_dc_history8: test_dc_history8:
@sh tests/history.sh dc 8 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 8 %%DC_TEST_EXEC%%
test_dc_history9: test_dc_history9:
@sh tests/history.sh dc 9 %%DC_TEST_EXEC%% @sh $(TESTSDIR)/history.sh dc 9 %%DC_TEST_EXEC%%
test_dc_history10:
@sh $(TESTSDIR)/history.sh dc 10 %%DC_TEST_EXEC%%
test_history_header: test_history_header:
@printf '$(TEST_STARS)\n\nRunning history tests...\n\n' @printf '$(TEST_STARS)\n\nRunning history tests...\n\n'
@ -505,18 +532,17 @@ clean:%%CLEAN_PREREQS%%
@$(RM) -f $(BC_EXEC) @$(RM) -f $(BC_EXEC)
@$(RM) -f $(DC_EXEC) @$(RM) -f $(DC_EXEC)
@$(RM) -fr $(BIN) @$(RM) -fr $(BIN)
@$(RM) -f $(LOCALES)/*.cat
@$(RM) -f $(BC_LIB_C) $(BC_LIB_O) @$(RM) -f $(BC_LIB_C) $(BC_LIB_O)
@$(RM) -f $(BC_LIB2_C) $(BC_LIB2_O) @$(RM) -f $(BC_LIB2_C) $(BC_LIB2_O)
@$(RM) -f $(BC_HELP_C) $(BC_HELP_O) @$(RM) -f $(BC_HELP_C) $(BC_HELP_O)
@$(RM) -f $(DC_HELP_C) $(DC_HELP_O) @$(RM) -f $(DC_HELP_C) $(DC_HELP_O)
@$(RM) -fr Debug/ Release/ @$(RM) -fr vs/bin/ vs/lib/
clean_benchmarks: clean_benchmarks:
@printf 'Cleaning benchmarks...\n' @printf 'Cleaning benchmarks...\n'
@$(RM) -f $(MINISTAT_EXEC) @$(RM) -f $(MINISTAT_EXEC)
@$(RM) -f benchmarks/bc/*.txt @$(RM) -f $(ROOTDIR)/benchmarks/bc/*.txt
@$(RM) -f benchmarks/dc/*.txt @$(RM) -f $(ROOTDIR)/benchmarks/dc/*.txt
clean_config: clean clean_benchmarks clean_config: clean clean_benchmarks
@printf 'Cleaning config...\n' @printf 'Cleaning config...\n'
@ -544,19 +570,19 @@ clean_tests: clean clean_config clean_coverage
@printf 'Cleaning test files...\n' @printf 'Cleaning test files...\n'
@$(RM) -fr $(BC_TEST_OUTPUTS) $(DC_TEST_OUTPUTS) @$(RM) -fr $(BC_TEST_OUTPUTS) $(DC_TEST_OUTPUTS)
@$(RM) -fr $(BC_FUZZ_OUTPUTS) $(DC_FUZZ_OUTPUTS) @$(RM) -fr $(BC_FUZZ_OUTPUTS) $(DC_FUZZ_OUTPUTS)
@$(RM) -f tests/bc/parse.txt tests/bc/parse_results.txt @$(RM) -f $(TESTSDIR)/bc/parse.txt $(TESTSDIR)/bc/parse_results.txt
@$(RM) -f tests/bc/print.txt tests/bc/print_results.txt @$(RM) -f $(TESTSDIR)/bc/print.txt $(TESTSDIR)/bc/print_results.txt
@$(RM) -f tests/bc/bessel.txt tests/bc/bessel_results.txt @$(RM) -f $(TESTSDIR)/bc/bessel.txt $(TESTSDIR)/bc/bessel_results.txt
@$(RM) -f tests/bc/strings2.txt tests/bc/strings2_results.txt @$(RM) -f $(TESTSDIR)/bc/strings2.txt $(TESTSDIR)/bc/strings2_results.txt
@$(RM) -f tests/bc/scripts/bessel.txt @$(RM) -f $(TESTSDIR)/bc/scripts/bessel.txt
@$(RM) -f tests/bc/scripts/parse.txt @$(RM) -f $(TESTSDIR)/bc/scripts/parse.txt
@$(RM) -f tests/bc/scripts/print.txt @$(RM) -f $(TESTSDIR)/bc/scripts/print.txt
@$(RM) -f tests/bc/scripts/add.txt @$(RM) -f $(TESTSDIR)/bc/scripts/add.txt
@$(RM) -f tests/bc/scripts/divide.txt @$(RM) -f $(TESTSDIR)/bc/scripts/divide.txt
@$(RM) -f tests/bc/scripts/multiply.txt @$(RM) -f $(TESTSDIR)/bc/scripts/multiply.txt
@$(RM) -f tests/bc/scripts/subtract.txt @$(RM) -f $(TESTSDIR)/bc/scripts/subtract.txt
@$(RM) -f tests/bc/scripts/strings2.txt @$(RM) -f $(TESTSDIR)/bc/scripts/strings2.txt
@$(RM) -f tests/dc/scripts/prime.txt @$(RM) -f $(TESTSDIR)/dc/scripts/prime.txt
@$(RM) -f .log_*.txt @$(RM) -f .log_*.txt
@$(RM) -f .math.txt .results.txt .ops.txt @$(RM) -f .math.txt .results.txt .ops.txt
@$(RM) -f .test.txt @$(RM) -f .test.txt
@ -581,10 +607,11 @@ install_bcl_header:
$(SAFE_INSTALL) $(MANPAGE_INSTALL_ARGS) $(BCL_HEADER) $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME) $(SAFE_INSTALL) $(MANPAGE_INSTALL_ARGS) $(BCL_HEADER) $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME)
install_execs: install_execs:
$(INSTALL) $(DESTDIR)$(BINDIR) "$(EXEC_SUFFIX)" $(INSTALL) $(DESTDIR)$(BINDIR) "$(EXEC_SUFFIX)" "$(BUILDDIR)/bin"
install_library: install_library: install_bcl_header
$(SAFE_INSTALL) $(BINARY_INSTALL_ARGS) $(LIBBC) $(DESTDIR)$(LIBDIR)/$(LIB_NAME) $(SAFE_INSTALL) $(BINARY_INSTALL_ARGS) $(LIBBC) $(DESTDIR)$(LIBDIR)/$(LIB_NAME)
%%PKG_CONFIG_INSTALL%%
install:%%INSTALL_LOCALES_PREREQS%%%%INSTALL_MAN_PREREQS%%%%INSTALL_PREREQS%% install:%%INSTALL_LOCALES_PREREQS%%%%INSTALL_MAN_PREREQS%%%%INSTALL_PREREQS%%
@ -603,8 +630,9 @@ uninstall_dc_manpage:
uninstall_dc: uninstall_dc:
$(RM) -f $(DESTDIR)$(BINDIR)/$(EXEC_PREFIX)$(DC)$(EXEC_SUFFIX) $(RM) -f $(DESTDIR)$(BINDIR)/$(EXEC_PREFIX)$(DC)$(EXEC_SUFFIX)
uninstall_library: uninstall_library: uninstall_bcl_header
$(RM) -f $(DESTDIR)$(LIBDIR)/$(LIB_NAME) $(RM) -f $(DESTDIR)$(LIBDIR)/$(LIB_NAME)
%%PKG_CONFIG_UNINSTALL%%
uninstall_bcl_header: uninstall_bcl_header:
$(RM) -f $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME) $(RM) -f $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME)

View File

@ -1,5 +1,25 @@
# News # News
## 5.2.1
This is a production release that fixes two parse bugs when in POSIX standard
mode. One of these bugs was due to a quirk of the POSIX grammar, and the other
was because `bc` was too strict.
## 5.2.0
This is a production release that adds a new feature, fixes some bugs, and adds
out-of-source builds and a `pkg-config` file for `bcl`.
The new feature is the ability to turn off exiting on expressions. It is also
possible to set the default using `configure.sh`. This behavior used to exist
with the `BC_EXPR_EXIT` environment variable, which is now used again.
Bugs fixed include:
* Some possible race conditions with error handling.
* Install and uninstall targets for `bcl` did not work.
## 5.1.1 ## 5.1.1
This is a production release that completes a bug fix from `5.1.0`. The bug This is a production release that completes a bug fix from `5.1.0`. The bug

View File

@ -58,8 +58,8 @@ system.
This `bc` should build unmodified on any POSIX-compliant system or on Windows This `bc` should build unmodified on any POSIX-compliant system or on Windows
starting with Windows 10 (though earlier versions may work). starting with Windows 10 (though earlier versions may work).
For more complex build requirements than the ones below, see the For more complex build requirements than the ones below, see the [build
[build manual][5]. manual][5].
### Windows ### Windows
@ -76,38 +76,45 @@ support) disabled, with both calculators built.
#### `bc` #### `bc`
To build `bc`, you can open the `bc.sln` file in Visual Studio, select the To build `bc`, you can open the `vs/bc.sln` file in Visual Studio, select the
configuration, and build. configuration, and build.
You can also build using MSBuild with the following from the root directory: You can also build using MSBuild with the following from the root directory:
``` ```
msbuild -property:Configuration=<config> bc.sln msbuild -property:Configuration=<config> vs/bc.sln
``` ```
where `<config>` is either one of `Debug` or `Release`. where `<config>` is either one of `Debug` or `Release`.
On Windows, the calculators are built as `vs/bin/<platform>/<config>/bc.exe` and
`vs/bin/<Platform>/<Config>/dc.exe`, where `<platform>` can be either `Win32` or
`x64`, and `<config>` can be `Debug` or `Release`.
**Note**: On Windows, `dc.exe` is just copied from `bc.exe`; it is not linked.
Patches are welcome for a way to do that.
#### `bcl` (Library) #### `bcl` (Library)
To build the library, you can open the `bcl.sln` file in Visual Studio, select To build the library, you can open the `vs/bcl.sln` file in Visual Studio,
the configuration, and build. select the configuration, and build.
You can also build using MSBuild with the following from the root directory: You can also build using MSBuild with the following from the root directory:
``` ```
msbuild -property:Configuration=<config> bcl.sln msbuild -property:Configuration=<config> vs/bcl.sln
``` ```
where `<config>` is either one of `Debug` or `Release`. where `<config>` is either one of `Debug`, `ReleaseMD`, or `ReleaseMT`.
On Windows, the library is built as `vs/lib/<platform>/<config>/bcl.lib`, where
`<platform>` can be either `Win32` or `x64`, and `<config>` can be `Debug`,
`ReleaseMD`, or `ReleaseMT`.
### POSIX-Compatible Systems ### POSIX-Compatible Systems
On POSIX-compatible systems, `bc` is built as `bin/bc` and `dc` is built as On POSIX-compatible systems, `bc` is built as `bin/bc` and `dc` is built as
`bin/dc` by default. On Windows, they are built as `Release/bc/bc.exe` and `bin/dc` by default.
`Release/bc/dc.exe`.
**Note**: On Windows, `dc.exe` is just copied from `bc.exe`; it is not linked.
Patches are welcome for a way to do that.
#### Default #### Default
@ -177,6 +184,24 @@ The library is built as `bin/libbcl.a` on POSIX-compatible systems or as
#### Package and Distro Maintainers #### Package and Distro Maintainers
This section is for package and distro maintainers.
##### Out-of-Source Builds
Out-of-source builds are supported; just call `configure.sh` from the directory
where the actual build will happen.
For example, if the source is in `bc`, the build should happen in `build`, then
call `configure.sh` and `make` like so:
```
../bc/configure.sh
make
```
***WARNING***: The path to `configure.sh` from the build directory must not have
spaces because `make` does not support target names with spaces.
##### Recommended Compiler ##### Recommended Compiler
When I ran benchmarks with my `bc` compiled under `clang`, it performed much When I ran benchmarks with my `bc` compiled under `clang`, it performed much
@ -373,16 +398,12 @@ Files:
.gitignore The git ignore file (maintainer use only). .gitignore The git ignore file (maintainer use only).
.gitattributes The git attributes file (maintainer use only). .gitattributes The git attributes file (maintainer use only).
bc.sln The Visual Studio solution file for bc. bcl.pc.in A template pkg-config file for bcl.
bc.vcxproj The Visual Studio project file for bc.
bc.vcxproj.filters The Visual Studio filters file for bc.
bcl.sln The Visual Studio solution file for bcl.
bcl.vcxproj The Visual Studio project file for bcl.
bcl.vcxproj.filters The Visual Studio filters file for bcl.
configure A symlink to configure.sh to make packaging easier. configure A symlink to configure.sh to make packaging easier.
configure.sh The configure script. configure.sh The configure script.
LICENSE.md A Markdown form of the BSD 2-clause License. LICENSE.md A Markdown form of the BSD 2-clause License.
Makefile.in The Makefile template. Makefile.in The Makefile template.
NEWS.md The changelog.
NOTICE.md List of contributors and copyright owners. NOTICE.md List of contributors and copyright owners.
RELEASE.md A checklist for making a release (maintainer use only). RELEASE.md A checklist for making a release (maintainer use only).
@ -395,6 +416,7 @@ Folders:
src All source code. src All source code.
scripts A bunch of shell scripts to help with development and building. scripts A bunch of shell scripts to help with development and building.
tests All tests. tests All tests.
vs Files needed for the build on Windows.
[1]: https://www.gnu.org/software/bc/ [1]: https://www.gnu.org/software/bc/
[4]: ./LICENSE.md [4]: ./LICENSE.md

8
contrib/bc/bcl.pc.in Normal file
View File

@ -0,0 +1,8 @@
includedir=%%INCLUDEDIR%%
libdir=%%LIBDIR%%
Name: bcl
Description: Implemention of arbitrary-precision math from the bc calculator.
Version: %%VERSION%%
Cflags: -I${includedir}
Libs: -L${libdir} -lbcl

View File

@ -31,9 +31,9 @@ script="$0"
scriptdir=$(dirname "$script") scriptdir=$(dirname "$script")
script=$(basename "$script") script=$(basename "$script")
. "$scriptdir/scripts/functions.sh" builddir=$(pwd)
cd "$scriptdir" . "$scriptdir/scripts/functions.sh"
# Simply prints the help message and quits based on the argument. # Simply prints the help message and quits based on the argument.
# @param val The value to pass to exit. Must be an integer. # @param val The value to pass to exit. Must be an integer.
@ -52,13 +52,15 @@ usage() {
printf 'usage:\n' printf 'usage:\n'
printf ' %s -h\n' "$script" printf ' %s -h\n' "$script"
printf ' %s --help\n' "$script" printf ' %s --help\n' "$script"
printf ' %s [-a|-bD|-dB|-c] [-CEfgGHlmMNPtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\n' "$script" printf ' %s [-a|-bD|-dB|-c] [-CEfgGHlmMNtTvz] [-O OPT_LEVEL] [-k KARATSUBA_LEN]\\\n' "$script"
printf ' [-s SETTING] [-S SETTING]\n'
printf ' %s \\\n' "$script" printf ' %s \\\n' "$script"
printf ' [--library|--bc-only --disable-dc|--dc-only --disable-bc|--coverage] \\\n' printf ' [--library|--bc-only --disable-dc|--dc-only --disable-bc|--coverage] \\\n'
printf ' [--force --debug --disable-extra-math --disable-generated-tests] \\\n' printf ' [--force --debug --disable-extra-math --disable-generated-tests] \\\n'
printf ' [--disable-history --disable-man-pages --disable-nls --disable-strip] \\\n' printf ' [--disable-history --disable-man-pages --disable-nls --disable-strip] \\\n'
printf ' [--install-all-locales] [--opt=OPT_LEVEL] \\\n' printf ' [--install-all-locales] [--opt=OPT_LEVEL] \\\n'
printf ' [--karatsuba-len=KARATSUBA_LEN] \\\n' printf ' [--karatsuba-len=KARATSUBA_LEN] \\\n'
printf ' [--set-default-on=SETTING] [--set-default-off=SETTING] \\\n'
printf ' [--prefix=PREFIX] [--bindir=BINDIR] [--datarootdir=DATAROOTDIR] \\\n' printf ' [--prefix=PREFIX] [--bindir=BINDIR] [--datarootdir=DATAROOTDIR] \\\n'
printf ' [--datadir=DATADIR] [--mandir=MANDIR] [--man1dir=MAN1DIR] \\\n' printf ' [--datadir=DATADIR] [--mandir=MANDIR] [--man1dir=MAN1DIR] \\\n'
printf '\n' printf '\n'
@ -205,6 +207,9 @@ usage() {
printf ' path (or contain one). This is treated the same as the POSIX\n' printf ' path (or contain one). This is treated the same as the POSIX\n'
printf ' definition of $NLSPATH (see POSIX environment variables for\n' printf ' definition of $NLSPATH (see POSIX environment variables for\n'
printf ' more information). Default is "/usr/share/locale/%%L/%%N".\n' printf ' more information). Default is "/usr/share/locale/%%L/%%N".\n'
printf ' PC_PATH The location to install pkg-config files to. Must be an\n'
printf ' path or contain one. Default is the first path given by the\n'
printf ' output of `pkg-config --variable=pc_path pkg-config`.\n'
printf ' EXECSUFFIX The suffix to append to the executable names, used to not\n' printf ' EXECSUFFIX The suffix to append to the executable names, used to not\n'
printf ' interfere with other installed bc executables. Default is "".\n' printf ' interfere with other installed bc executables. Default is "".\n'
printf ' EXECPREFIX The prefix to append to the executable names, used to not\n' printf ' EXECPREFIX The prefix to append to the executable names, used to not\n'
@ -290,6 +295,18 @@ usage() {
printf '| | for dc should be on | | |\n' printf '| | for dc should be on | | |\n'
printf '| | in tty mode. | | |\n' printf '| | in tty mode. | | |\n'
printf '| --------------- | -------------------- | ------------ | -------------------- |\n' printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
printf '| bc.expr_exit | Whether to exit bc | 1 | BC_EXPR_EXIT |\n'
printf '| | if an expression or | | |\n'
printf '| | expression file is | | |\n'
printf '| | given with the -e or | | |\n'
printf '| | -f options. | | |\n'
printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
printf '| dc.expr_exit | Whether to exit dc | 1 | DC_EXPR_EXIT |\n'
printf '| | if an expression or | | |\n'
printf '| | expression file is | | |\n'
printf '| | given with the -e or | | |\n'
printf '| | -f options. | | |\n'
printf '| --------------- | -------------------- | ------------ | -------------------- |\n'
printf '\n' printf '\n'
printf 'These settings are not meant to be changed on a whim. They are meant to ensure\n' printf 'These settings are not meant to be changed on a whim. They are meant to ensure\n'
printf 'that this bc and dc will conform to the expectations of the user on each\n' printf 'that this bc and dc will conform to the expectations of the user on each\n'
@ -374,19 +391,34 @@ replace() {
# the arguments are all assumed to be source files that should *not* be built. # the arguments are all assumed to be source files that should *not* be built.
find_src_files() { find_src_files() {
_find_src_files_args=""
if [ "$#" -ge 1 ] && [ "$1" != "" ]; then if [ "$#" -ge 1 ] && [ "$1" != "" ]; then
while [ "$#" -ge 1 ]; do while [ "$#" -ge 1 ]; do
_find_src_files_a="${1## }" _find_src_files_a="${1## }"
shift shift
_find_src_files_args="$_find_src_files_args ! -path src/${_find_src_files_a}" _find_src_files_args=$(printf '%s\n%s/src/%s\n' "$_find_src_files_args" "$scriptdir" "${_find_src_files_a}")
done done
else
_find_src_files_args="-print"
fi fi
printf '%s\n' $(find src/ -depth -name "*.c" $_find_src_files_args) _find_src_files_files=$(find "$scriptdir/src/" -depth -name "*.c" -print)
_find_src_files_result=""
for _find_src_files_f in $_find_src_files_files; do
# If this is true, the file is part of args, and therefore, unneeded.
if [ "${_find_src_files_args##*$_find_src_files_f}" != "${_find_src_files_args}" ]; then
continue
fi
_find_src_files_result=$(printf '%s\n%s\n' "$_find_src_files_result" "$_find_src_files_f")
done
printf '%s\n' "$_find_src_files_result"
} }
# This function generates a list of files to go into the Makefile. It generates # This function generates a list of files to go into the Makefile. It generates
@ -403,10 +435,6 @@ gen_file_list() {
_gen_file_list_contents="$1" _gen_file_list_contents="$1"
shift shift
p=$(pwd)
cd "$scriptdir"
if [ "$#" -ge 1 ]; then if [ "$#" -ge 1 ]; then
_gen_file_list_unneeded="$@" _gen_file_list_unneeded="$@"
else else
@ -422,7 +450,14 @@ gen_file_list() {
_gen_file_list_contents=$(replace "$_gen_file_list_contents" \ _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
"$_gen_file_list_needle_src" "$_gen_file_list_replacement") "$_gen_file_list_needle_src" "$_gen_file_list_replacement")
_gen_file_list_replacement=$(replace_exts "$_gen_file_list_replacement" "c" "o") _gen_file_list_cbases=""
for _gen_file_list_f in $_gen_file_list_replacement; do
_gen_file_list_b=$(basename "$_gen_file_list_f")
_gen_file_list_cbases="$_gen_file_list_cbases src/$_gen_file_list_b"
done
_gen_file_list_replacement=$(replace_exts "$_gen_file_list_cbases" "c" "o")
_gen_file_list_contents=$(replace "$_gen_file_list_contents" \ _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
"$_gen_file_list_needle_obj" "$_gen_file_list_replacement") "$_gen_file_list_needle_obj" "$_gen_file_list_replacement")
@ -434,8 +469,6 @@ gen_file_list() {
_gen_file_list_contents=$(replace "$_gen_file_list_contents" \ _gen_file_list_contents=$(replace "$_gen_file_list_contents" \
"$_gen_file_list_needle_gcno" "$_gen_file_list_replacement") "$_gen_file_list_needle_gcno" "$_gen_file_list_replacement")
cd "$p"
printf '%s\n' "$_gen_file_list_contents" printf '%s\n' "$_gen_file_list_contents"
} }
@ -466,16 +499,16 @@ gen_std_tests() {
if [ -z "${_gen_std_tests_extra_required##*$_gen_std_tests_t*}" ]; then if [ -z "${_gen_std_tests_extra_required##*$_gen_std_tests_t*}" ]; then
printf 'test_%s_%s:\n\t@printf "Skipping %s %s\\n"\n\n' \ printf 'test_%s_%s:\n\t@printf "Skipping %s %s\\n"\n\n' \
"$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \ "$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \
"$_gen_std_tests_t" >> "$scriptdir/Makefile" "$_gen_std_tests_t" >> "Makefile"
continue continue
fi fi
fi fi
printf 'test_%s_%s:\n\t@sh tests/test.sh %s %s %s %s %s\n\n' \ printf 'test_%s_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/test.sh %s %s %s %s %s\n\n' \
"$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \ "$_gen_std_tests_name" "$_gen_std_tests_t" "$builddir" "$_gen_std_tests_name" \
"$_gen_std_tests_t" "$generate_tests" "$time_tests" \ "$_gen_std_tests_t" "$generate_tests" "$time_tests" \
"$*" >> "$scriptdir/Makefile" "$*" >> "Makefile"
done done
} }
@ -512,9 +545,9 @@ gen_err_tests() {
for _gen_err_tests_t in $_gen_err_tests_fs; do for _gen_err_tests_t in $_gen_err_tests_fs; do
printf 'test_%s_error_%s:\n\t@sh tests/error.sh %s %s %s\n\n' \ printf 'test_%s_error_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/error.sh %s %s %s\n\n' \
"$_gen_err_tests_name" "$_gen_err_tests_t" "$_gen_err_tests_name" \ "$_gen_err_tests_name" "$_gen_err_tests_t" "$builddir" "$_gen_err_tests_name" \
"$_gen_err_tests_t" "$*" >> "$scriptdir/Makefile" "$_gen_err_tests_t" "$*" >> "Makefile"
done done
@ -566,10 +599,10 @@ gen_script_tests() {
_gen_script_tests_b=$(basename "$_gen_script_tests_f" ".${_gen_script_tests_name}") _gen_script_tests_b=$(basename "$_gen_script_tests_f" ".${_gen_script_tests_name}")
printf 'test_%s_script_%s:\n\t@sh tests/script.sh %s %s %s 1 %s %s %s\n\n' \ printf 'test_%s_script_%s:\n\t@export BC_TEST_OUTPUT_DIR="%s/tests"; sh \$(TESTSDIR)/script.sh %s %s %s 1 %s %s %s\n\n' \
"$_gen_script_tests_name" "$_gen_script_tests_b" "$_gen_script_tests_name" \ "$_gen_script_tests_name" "$_gen_script_tests_b" "$builddir" "$_gen_script_tests_name" \
"$_gen_script_tests_f" "$_gen_script_tests_extra_math" "$_gen_script_tests_generate" \ "$_gen_script_tests_f" "$_gen_script_tests_extra_math" "$_gen_script_tests_generate" \
"$_gen_script_tests_time" "$*" >> "$scriptdir/Makefile" "$_gen_script_tests_time" "$*" >> "Makefile"
done done
} }
@ -594,6 +627,8 @@ set_default() {
dc.tty_mode) dc_default_tty_mode="$_set_default_on" ;; dc.tty_mode) dc_default_tty_mode="$_set_default_on" ;;
bc.prompt) bc_default_prompt="$_set_default_on" ;; bc.prompt) bc_default_prompt="$_set_default_on" ;;
dc.prompt) dc_default_prompt="$_set_default_on" ;; dc.prompt) dc_default_prompt="$_set_default_on" ;;
bc.expr_exit) bc_default_expr_exit="$_set_default_on";;
dc.expr_exit) dc_default_expr_exit="$_set_default_on";;
?) usage "Invalid setting: $_set_default_name" ;; ?) usage "Invalid setting: $_set_default_name" ;;
esac esac
@ -656,6 +691,8 @@ bc_default_tty_mode=1
dc_default_tty_mode=0 dc_default_tty_mode=0
bc_default_prompt="" bc_default_prompt=""
dc_default_prompt="" dc_default_prompt=""
bc_default_expr_exit=1
dc_default_expr_exit=1
# getopts is a POSIX utility, but it cannot handle long options. Thus, the # getopts is a POSIX utility, but it cannot handle long options. Thus, the
# handling of long options is done by hand, and that's the reason that short and # handling of long options is done by hand, and that's the reason that short and
@ -946,12 +983,12 @@ executable="BC_EXEC"
tests="test_bc timeconst test_dc" tests="test_bc timeconst test_dc"
bc_test="@tests/all.sh bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)" bc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
bc_test_np="@tests/all.sh -n bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)" bc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $time_tests \$(BC_EXEC)"
dc_test="@tests/all.sh dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)" dc_test="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
dc_test_np="@tests/all.sh -n dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)" dc_test_np="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n dc $extra_math 1 $generate_tests $time_tests \$(DC_EXEC)"
timeconst="@tests/bc/timeconst.sh tests/bc/scripts/timeconst.bc \$(BC_EXEC)" timeconst="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/bc/timeconst.sh \$(TESTSDIR)/bc/scripts/timeconst.bc \$(BC_EXEC)"
# In order to have cleanup at exit, we need to be in # In order to have cleanup at exit, we need to be in
# debug mode, so don't run valgrind without that. # debug mode, so don't run valgrind without that.
@ -999,6 +1036,11 @@ if [ "$library" -ne 0 ]; then
test_bc_history_prereqs=" test_bc_history_skip" test_bc_history_prereqs=" test_bc_history_skip"
test_dc_history_prereqs=" test_dc_history_skip" test_dc_history_prereqs=" test_dc_history_skip"
install_prereqs=" install_library"
uninstall_prereqs=" uninstall_library"
install_man_prereqs=" install_bcl_manpage"
uninstall_man_prereqs=" uninstall_bcl_manpage"
elif [ "$bc_only" -eq 1 ]; then elif [ "$bc_only" -eq 1 ]; then
bc=1 bc=1
@ -1151,6 +1193,24 @@ if [ -z "${LIBDIR+set}" ]; then
LIBDIR="$PREFIX/lib" LIBDIR="$PREFIX/lib"
fi fi
if [ -z "${PC_PATH+set}" ]; then
set +e
command -v pkg-config > /dev/null
err=$?
set -e
if [ "$err" -eq 0 ]; then
PC_PATH=$(pkg-config --variable=pc_path pkg-config)
PC_PATH="${PC_PATH%%:*}"
else
PC_PATH=""
fi
fi
# Set a default for the DATAROOTDIR. This is done if either manpages will be # Set a default for the DATAROOTDIR. This is done if either manpages will be
# installed, or locales are enabled because that's probably where NLS_PATH # installed, or locales are enabled because that's probably where NLS_PATH
# points. # points.
@ -1195,14 +1255,14 @@ if [ "$nls" -ne 0 ]; then
flags="-DBC_ENABLE_NLS=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc" flags="-DBC_ENABLE_NLS=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
flags="$flags -DBC_ENABLE_HISTORY=$hist -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0" flags="$flags -DBC_ENABLE_HISTORY=$hist -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I./include/" flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
"$CC" $CPPFLAGS $CFLAGS $flags -c "src/vm.c" -o "$scriptdir/vm.o" > /dev/null 2>&1 "$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/vm.c" -o "./vm.o" > /dev/null 2>&1
err="$?" err="$?"
rm -rf "$scriptdir/vm.o" rm -rf "./vm.o"
# If this errors, it is probably because of building on Windows, # If this errors, it is probably because of building on Windows,
# and NLS is not supported on Windows, so disable it. # and NLS is not supported on Windows, so disable it.
@ -1218,11 +1278,11 @@ if [ "$nls" -ne 0 ]; then
printf 'NLS works.\n\n' printf 'NLS works.\n\n'
printf 'Testing gencat...\n' printf 'Testing gencat...\n'
gencat "$scriptdir/en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null 2>&1 gencat "./en_US.cat" "$scriptdir/locales/en_US.msg" > /dev/null 2>&1
err="$?" err="$?"
rm -rf "$scriptdir/en_US.cat" rm -rf "./en_US.cat"
if [ "$err" -ne 0 ]; then if [ "$err" -ne 0 ]; then
printf 'gencat does not work.\n' printf 'gencat does not work.\n'
@ -1279,14 +1339,14 @@ if [ "$hist" -eq 1 ]; then
flags="-DBC_ENABLE_HISTORY=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc" flags="-DBC_ENABLE_HISTORY=1 -DBC_ENABLED=$bc -DDC_ENABLED=$dc"
flags="$flags -DBC_ENABLE_NLS=$nls -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0" flags="$flags -DBC_ENABLE_NLS=$nls -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_AFL=0"
flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I./include/" flags="$flags -DBC_ENABLE_EXTRA_MATH=$extra_math -I$scriptdir/include/"
flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" flags="$flags -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
"$CC" $CPPFLAGS $CFLAGS $flags -c "src/history.c" -o "$scriptdir/history.o" > /dev/null 2>&1 "$CC" $CPPFLAGS $CFLAGS $flags -c "$scriptdir/src/history.c" -o "./history.o" > /dev/null 2>&1
err="$?" err="$?"
rm -rf "$scriptdir/history.o" rm -rf "./history.o"
# If this errors, it is probably because of building on Windows, # If this errors, it is probably because of building on Windows,
# and history is not supported on Windows, so disable it. # and history is not supported on Windows, so disable it.
@ -1312,7 +1372,7 @@ if [ "$hist" -eq 0 ] || [ "$vg" -ne 0 ]; then
test_dc_history_prereqs=" test_dc_history_skip" test_dc_history_prereqs=" test_dc_history_skip"
history_tests="@printf 'Skipping history tests...\\\\n'" history_tests="@printf 'Skipping history tests...\\\\n'"
else else
history_tests="@printf '\$(TEST_STARS)\\\\n\\\\nRunning history tests...\\\\n\\\\n' \&\& tests/history.sh bc -a \&\& tests/history.sh dc -a \&\& printf '\\\\nAll history tests passed.\\\\n\\\\n\$(TEST_STARS)\\\\n'" history_tests="@printf '\$(TEST_STARS)\\\\n\\\\nRunning history tests...\\\\n\\\\n' \&\& \$(TESTSDIR)/history.sh bc -a \&\& \$(TESTSDIR)/history.sh dc -a \&\& printf '\\\\nAll history tests passed.\\\\n\\\\n\$(TEST_STARS)\\\\n'"
fi fi
# Test OpenBSD. This is not in an if statement because regardless of whatever # Test OpenBSD. This is not in an if statement because regardless of whatever
@ -1327,7 +1387,7 @@ set +e
printf 'Testing for OpenBSD...\n' printf 'Testing for OpenBSD...\n'
flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0" flags="-DBC_TEST_OPENBSD -DBC_ENABLE_AFL=0"
"$CC" $CPPFLAGS $CFLAGS $flags -I./include -E "include/status.h" > /dev/null 2>&1 "$CC" $CPPFLAGS $CFLAGS $flags "-I$scriptdir/include" -E "$scriptdir/include/status.h" > /dev/null 2>&1
err="$?" err="$?"
@ -1403,14 +1463,46 @@ else
headers="$headers \$(DC_HEADERS)" headers="$headers \$(DC_HEADERS)"
fi fi
# This convoluted mess does pull the version out. If you change the format of
# include/version.h, you may have to change this line.
version=$(cat "$scriptdir/include/version.h" | grep "VERSION " - | awk '{ print $3 }' -)
if [ "$library" -ne 0 ]; then if [ "$library" -ne 0 ]; then
unneeded="$unneeded args.c opt.c read.c file.c main.c" unneeded="$unneeded args.c opt.c read.c file.c main.c"
unneeded="$unneeded lang.c lex.c parse.c program.c" unneeded="$unneeded lang.c lex.c parse.c program.c"
unneeded="$unneeded bc.c bc_lex.c bc_parse.c" unneeded="$unneeded bc.c bc_lex.c bc_parse.c"
unneeded="$unneeded dc.c dc_lex.c dc_parse.c" unneeded="$unneeded dc.c dc_lex.c dc_parse.c"
headers="$headers \$(LIBRARY_HEADERS)" headers="$headers \$(LIBRARY_HEADERS)"
if [ "$PC_PATH" != "" ]; then
contents=$(cat "$scriptdir/bcl.pc.in")
contents=$(replace "$contents" "INCLUDEDIR" "$INCLUDEDIR")
contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
contents=$(replace "$contents" "VERSION" "$version")
printf '%s\n' "$contents" > "./bcl.pc"
pkg_config_install="\$(SAFE_INSTALL) \$(PC_INSTALL_ARGS) \"\$(BCL_PC)\" \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
pkg_config_uninstall="\$(RM) -f \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
else
pkg_config_install=""
pkg_config_uninstall=""
fi
else else
unneeded="$unneeded library.c" unneeded="$unneeded library.c"
PC_PATH=""
pkg_config_install=""
pkg_config_uninstall=""
fi fi
# library.c is not needed under normal circumstances. # library.c is not needed under normal circumstances.
@ -1444,6 +1536,8 @@ dc_script_tests=$(gen_script_test_targets dc)
dc_err_tests=$(gen_err_test_targets dc) dc_err_tests=$(gen_err_test_targets dc)
# Print out the values; this is for debugging. # Print out the values; this is for debugging.
printf 'Version: %s\n' "$version"
if [ "$bc" -ne 0 ]; then if [ "$bc" -ne 0 ]; then
printf 'Building bc\n' printf 'Building bc\n'
else else
@ -1479,6 +1573,7 @@ printf 'MANDIR=%s\n' "$MANDIR"
printf 'MAN1DIR=%s\n' "$MAN1DIR" printf 'MAN1DIR=%s\n' "$MAN1DIR"
printf 'MAN3DIR=%s\n' "$MAN3DIR" printf 'MAN3DIR=%s\n' "$MAN3DIR"
printf 'NLSPATH=%s\n' "$NLSPATH" printf 'NLSPATH=%s\n' "$NLSPATH"
printf 'PC_PATH=%s\n' "$PC_PATH"
printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX" printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX"
printf 'EXECPREFIX=%s\n' "$EXECPREFIX" printf 'EXECPREFIX=%s\n' "$EXECPREFIX"
printf 'DESTDIR=%s\n' "$DESTDIR" printf 'DESTDIR=%s\n' "$DESTDIR"
@ -1495,6 +1590,8 @@ printf 'bc.tty_mode=%s\n' "$bc_default_tty_mode"
printf 'dc.tty_mode=%s\n' "$dc_default_tty_mode" printf 'dc.tty_mode=%s\n' "$dc_default_tty_mode"
printf 'bc.prompt=%s\n' "$bc_default_prompt" printf 'bc.prompt=%s\n' "$bc_default_prompt"
printf 'dc.prompt=%s\n' "$dc_default_prompt" printf 'dc.prompt=%s\n' "$dc_default_prompt"
printf 'bc.expr_exit=%s\n' "$bc_default_expr_exit"
printf 'dc.expr_exit=%s\n' "$dc_default_expr_exit"
# This is where the real work begins. This is the point at which the Makefile.in # This is where the real work begins. This is the point at which the Makefile.in
# template is edited and output to the Makefile. # template is edited and output to the Makefile.
@ -1518,11 +1615,15 @@ src_files=$(find_src_files $unneeded)
for f in $src_files; do for f in $src_files; do
o=$(replace_ext "$f" "c" "o") o=$(replace_ext "$f" "c" "o")
SRC_TARGETS=$(printf '%s\n\n%s: %s %s\n\t$(CC) $(CFLAGS) -o %s -c %s\n' \ o=$(basename "$o")
SRC_TARGETS=$(printf '%s\n\nsrc/%s: src %s %s\n\t$(CC) $(CFLAGS) -o src/%s -c %s\n' \
"$SRC_TARGETS" "$o" "$headers" "$f" "$o" "$f") "$SRC_TARGETS" "$o" "$headers" "$f" "$o" "$f")
done done
# Replace all the placeholders. # Replace all the placeholders.
contents=$(replace "$contents" "ROOTDIR" "$scriptdir")
contents=$(replace "$contents" "BUILDDIR" "$builddir")
contents=$(replace "$contents" "HEADERS" "$headers") contents=$(replace "$contents" "HEADERS" "$headers")
contents=$(replace "$contents" "BC_ENABLED" "$bc") contents=$(replace "$contents" "BC_ENABLED" "$bc")
@ -1583,6 +1684,10 @@ contents=$(replace "$contents" "UNINSTALL_MAN_PREREQS" "$uninstall_man_prereqs")
contents=$(replace "$contents" "UNINSTALL_PREREQS" "$uninstall_prereqs") contents=$(replace "$contents" "UNINSTALL_PREREQS" "$uninstall_prereqs")
contents=$(replace "$contents" "UNINSTALL_LOCALES_PREREQS" "$uninstall_locales_prereqs") contents=$(replace "$contents" "UNINSTALL_LOCALES_PREREQS" "$uninstall_locales_prereqs")
contents=$(replace "$contents" "PC_PATH" "$PC_PATH")
contents=$(replace "$contents" "PKG_CONFIG_INSTALL" "$pkg_config_install")
contents=$(replace "$contents" "PKG_CONFIG_UNINSTALL" "$pkg_config_uninstall")
contents=$(replace "$contents" "DEFAULT_TARGET" "$default_target") contents=$(replace "$contents" "DEFAULT_TARGET" "$default_target")
contents=$(replace "$contents" "DEFAULT_TARGET_PREREQS" "$default_target_prereqs") contents=$(replace "$contents" "DEFAULT_TARGET_PREREQS" "$default_target_prereqs")
contents=$(replace "$contents" "DEFAULT_TARGET_CMD" "$default_target_cmd") contents=$(replace "$contents" "DEFAULT_TARGET_CMD" "$default_target_cmd")
@ -1630,9 +1735,11 @@ contents=$(replace "$contents" "BC_DEFAULT_TTY_MODE" "$bc_default_tty_mode")
contents=$(replace "$contents" "DC_DEFAULT_TTY_MODE" "$dc_default_tty_mode") contents=$(replace "$contents" "DC_DEFAULT_TTY_MODE" "$dc_default_tty_mode")
contents=$(replace "$contents" "BC_DEFAULT_PROMPT" "$bc_default_prompt") contents=$(replace "$contents" "BC_DEFAULT_PROMPT" "$bc_default_prompt")
contents=$(replace "$contents" "DC_DEFAULT_PROMPT" "$dc_default_prompt") contents=$(replace "$contents" "DC_DEFAULT_PROMPT" "$dc_default_prompt")
contents=$(replace "$contents" "BC_DEFAULT_EXPR_EXIT" "$bc_default_expr_exit")
contents=$(replace "$contents" "DC_DEFAULT_EXPR_EXIT" "$dc_default_expr_exit")
# Do the first print to the Makefile. # Do the first print to the Makefile.
printf '%s\n%s\n\n' "$contents" "$SRC_TARGETS" > "$scriptdir/Makefile" printf '%s\n%s\n\n' "$contents" "$SRC_TARGETS" > "Makefile"
# Generate the individual test targets. # Generate the individual test targets.
if [ "$bc" -ne 0 ]; then if [ "$bc" -ne 0 ]; then
@ -1647,12 +1754,11 @@ if [ "$dc" -ne 0 ]; then
gen_err_tests dc $dc_test_exec gen_err_tests dc $dc_test_exec
fi fi
cd "$scriptdir"
# Copy the correct manuals to the expected places. # Copy the correct manuals to the expected places.
cp -f manuals/bc/$manpage_args.1.md manuals/bc.1.md mkdir -p manuals
cp -f manuals/bc/$manpage_args.1 manuals/bc.1 cp -f "$scriptdir/manuals/bc/$manpage_args.1.md" manuals/bc.1.md
cp -f manuals/dc/$manpage_args.1.md manuals/dc.1.md cp -f "$scriptdir/manuals/bc/$manpage_args.1" manuals/bc.1
cp -f manuals/dc/$manpage_args.1 manuals/dc.1 cp -f "$scriptdir/manuals/dc/$manpage_args.1.md" manuals/dc.1.md
cp -f "$scriptdir/manuals/dc/$manpage_args.1" manuals/dc.1
make clean > /dev/null make clean > /dev/null

View File

@ -183,3 +183,10 @@ Environment variables:
If an integer and non-zero, enable prompt when TTY mode is possible. If an integer and non-zero, enable prompt when TTY mode is possible.
Overrides the default, which is prompt %s. Overrides the default, which is prompt %s.
BC_EXPR_EXIT
If an integer and non-zero, exit when expressions or expression files are
given on the command-line, and does not exit when an integer and zero.
Overrides the default, which is %s.

View File

@ -142,3 +142,10 @@ Environment variables:
If an integer and non-zero, enable prompt when TTY mode is possible. If an integer and non-zero, enable prompt when TTY mode is possible.
Overrides the default, which is prompt %s. Overrides the default, which is prompt %s.
DC_EXPR_EXIT
If an integer and non-zero, exit when expressions or expression files are
given on the command-line, and does not exit when an integer and zero.
Overrides the default, which is %s.

View File

@ -268,6 +268,10 @@
#define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE #define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE
#endif // BC_DEFAULT_PROMPT #endif // BC_DEFAULT_PROMPT
#ifndef BC_DEFAULT_EXPR_EXIT
#define BC_DEFAULT_EXPR_EXIT (1)
#endif // BC_DEFAULT_EXPR_EXIT
// All of these set defaults for settings. // All of these set defaults for settings.
#ifndef DC_DEFAULT_SIGINT_RESET #ifndef DC_DEFAULT_SIGINT_RESET
#define DC_DEFAULT_SIGINT_RESET (1) #define DC_DEFAULT_SIGINT_RESET (1)
@ -285,6 +289,10 @@
#define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE #define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE
#endif // DC_DEFAULT_PROMPT #endif // DC_DEFAULT_PROMPT
#ifndef DC_DEFAULT_EXPR_EXIT
#define DC_DEFAULT_EXPR_EXIT (1)
#endif // DC_DEFAULT_EXPR_EXIT
/// Statuses, which mark either which category of error happened, or some other /// Statuses, which mark either which category of error happened, or some other
/// status that matters. /// status that matters.
typedef enum BcStatus { typedef enum BcStatus {
@ -472,6 +480,10 @@ typedef enum BcErr {
/// Empty statements in POSIX for loop error. /// Empty statements in POSIX for loop error.
BC_ERR_POSIX_FOR, BC_ERR_POSIX_FOR,
/// POSIX's grammar does not allow a function definition right after a
/// semicolon.
BC_ERR_POSIX_FUNC_AFTER_SEMICOLON,
/// Non-POSIX exponential (scientific or engineering) number used error. /// Non-POSIX exponential (scientific or engineering) number used error.
BC_ERR_POSIX_EXP_NUM, BC_ERR_POSIX_EXP_NUM,

View File

@ -37,6 +37,6 @@
#define BC_VERSION_H #define BC_VERSION_H
/// The current version. /// The current version.
#define VERSION 5.1.1 #define VERSION 5.2.1
#endif // BC_VERSION_H #endif // BC_VERSION_H

View File

@ -176,6 +176,9 @@
/// The flag for reset on SIGINT. /// The flag for reset on SIGINT.
#define BC_FLAG_SIGINT (UINTMAX_C(1)<<12) #define BC_FLAG_SIGINT (UINTMAX_C(1)<<12)
/// The flag for exiting with expressions.
#define BC_FLAG_EXPR_EXIT (UINTMAX_C(1)<<13)
/// A convenience macro for getting the TTYIN flag. /// A convenience macro for getting the TTYIN flag.
#define BC_TTYIN (vm.flags & BC_FLAG_TTYIN) #define BC_TTYIN (vm.flags & BC_FLAG_TTYIN)
@ -220,6 +223,9 @@
/// A convenience macro for getting the leading zero flag. /// A convenience macro for getting the leading zero flag.
#define BC_Z (vm.flags & BC_FLAG_Z) #define BC_Z (vm.flags & BC_FLAG_Z)
/// A convenience macro for getting the expression exit flag.
#define BC_EXPR_EXIT (vm.flags & BC_FLAG_EXPR_EXIT)
#if BC_ENABLED #if BC_ENABLED
/// A convenience macro for checking if bc is in POSIX mode. /// A convenience macro for checking if bc is in POSIX mode.

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX erlaubt keine Vergleichsoperatoren außerhalb von if-Anweisungen oder Schleifen" 22 "POSIX erlaubt keine Vergleichsoperatoren außerhalb von if-Anweisungen oder Schleifen"
23 "POSIX benötigt 0 oder 1 Vergleichsoperatoren pro Bedingung" 23 "POSIX benötigt 0 oder 1 Vergleichsoperatoren pro Bedingung"
24 "POSIX erlaubt keinen leeren Ausdruck in einer for-Schleife" 24 "POSIX erlaubt keinen leeren Ausdruck in einer for-Schleife"
25 "POSIX erlaubt keine exponentielle Notation" 25 "POSIX verlangt einen Zeilenumbruch zwischen einem Semikolon und einer Funktionsdefinition"
26 "POSIX erlaubt keine Feld-Referenzen als Funktionsparameter" 26 "POSIX erlaubt keine exponentielle Notation"
27 "POSIX erfordert, dass die linke Klammer auf der gleichen Linie wie der Funktionskopf steht" 27 "POSIX erlaubt keine Feld-Referenzen als Funktionsparameter"
28 "POSIX erlaubt keine Zuweisung von Strings an Variablen oder Arrays" 28 "POSIX erlaubt keine ungültigen Funktionen"
29 "POSIX erfordert, dass die linke Klammer auf der gleichen Linie wie der Funktionskopf steht"
30 "POSIX erlaubt keine Zuweisung von Strings an Variablen oder Arrays"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX erlaubt keine Vergleichsoperatoren außerhalb von if-Anweisungen oder Schleifen" 22 "POSIX erlaubt keine Vergleichsoperatoren außerhalb von if-Anweisungen oder Schleifen"
23 "POSIX benötigt 0 oder 1 Vergleichsoperatoren pro Bedingung" 23 "POSIX benötigt 0 oder 1 Vergleichsoperatoren pro Bedingung"
24 "POSIX erlaubt keinen leeren Ausdruck in einer for-Schleife" 24 "POSIX erlaubt keinen leeren Ausdruck in einer for-Schleife"
25 "POSIX erlaubt keine exponentielle Notation" 25 "POSIX verlangt einen Zeilenumbruch zwischen einem Semikolon und einer Funktionsdefinition"
26 "POSIX erlaubt keine Feld-Referenzen als Funktionsparameter" 26 "POSIX erlaubt keine exponentielle Notation"
27 "POSIX erfordert, dass die linke Klammer auf der gleichen Linie wie der Funktionskopf steht" 27 "POSIX erlaubt keine Feld-Referenzen als Funktionsparameter"
28 "POSIX erlaubt keine Zuweisung von Strings an Variablen oder Arrays" 28 "POSIX erlaubt keine ungültigen Funktionen"
29 "POSIX erfordert, dass die linke Klammer auf der gleichen Linie wie der Funktionskopf steht"
30 "POSIX erlaubt keine Zuweisung von Strings an Variablen oder Arrays"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX does not allow comparison operators outside if statements or loops" 22 "POSIX does not allow comparison operators outside if statements or loops"
23 "POSIX requires 0 or 1 comparison operators per condition" 23 "POSIX requires 0 or 1 comparison operators per condition"
24 "POSIX requires all 3 parts of a for loop to be non-empty" 24 "POSIX requires all 3 parts of a for loop to be non-empty"
25 "POSIX does not allow exponential notation" 25 "POSIX requires a newline between a semicolon and a function definition",
26 "POSIX does not allow array references as function parameters" 26 "POSIX does not allow exponential notation"
27 "POSIX requires the left brace be on the same line as the function header" 27 "POSIX does not allow array references as function parameters"
28 "POSIX does not allow strings to be assigned to variables or arrays" 28 "POSIX does not allow void functions",
29 "POSIX requires the left brace be on the same line as the function header"
30 "POSIX does not allow strings to be assigned to variables or arrays"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX no permite operadores de comparación aparte de \"if\" expresión o bucles" 22 "POSIX no permite operadores de comparación aparte de \"if\" expresión o bucles"
23 "POSIX requiere 0 o 1 operadores de comparisón para cada condición" 23 "POSIX requiere 0 o 1 operadores de comparisón para cada condición"
24 "POSIX requiere todos 3 partes de una bucla que no esta vacío" 24 "POSIX requiere todos 3 partes de una bucla que no esta vacío"
25 "POSIX no permite una notación exponencial" 25 "POSIX requiere una nueva línea entre un punto y coma y una definición de función"
26 "POSIX no permite una referencia a una matriz como un parámetro de función" 26 "POSIX no permite una notación exponencial"
27 "POSIX requiere el llave de la izquierda que sea en la misma línea que los parámetros de la función" 27 "POSIX no permite una referencia a una matriz como un parámetro de función"
28 "POSIX no permite asignar cadenas a variables o matrices" 28 "POSIX no permite funciones void"
29 "POSIX requiere el llave de la izquierda que sea en la misma línea que los parámetros de la función"
30 "POSIX no permite asignar cadenas a variables o matrices"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX no permite operadores de comparación aparte de \"if\" expresión o bucles" 22 "POSIX no permite operadores de comparación aparte de \"if\" expresión o bucles"
23 "POSIX requiere 0 o 1 operadores de comparisón para cada condición" 23 "POSIX requiere 0 o 1 operadores de comparisón para cada condición"
24 "POSIX requiere todos 3 partes de una bucla que no esta vacío" 24 "POSIX requiere todos 3 partes de una bucla que no esta vacío"
25 "POSIX no permite una notación exponencial" 25 "POSIX requiere una nueva línea entre un punto y coma y una definición de función"
26 "POSIX no permite una referencia a una matriz como un parámetro de función" 26 "POSIX no permite una notación exponencial"
27 "POSIX requiere el llave de la izquierda que sea en la misma línea que los parámetros de la función" 27 "POSIX no permite una referencia a una matriz como un parámetro de función"
28 "POSIX no permite asignar cadenas a variables o matrices" 28 "POSIX no permite funciones void"
29 "POSIX requiere el llave de la izquierda que sea en la misma línea que los parámetros de la función"
30 "POSIX no permite asignar cadenas a variables o matrices"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX interdit les opérateurs de comparaison en dehors des expressions 'if' ou des boucles" 22 "POSIX interdit les opérateurs de comparaison en dehors des expressions 'if' ou des boucles"
23 "POSIX impose 0 ou 1 opérateur de comparaison par condition" 23 "POSIX impose 0 ou 1 opérateur de comparaison par condition"
24 "POSIX interdit une expression vide dans une boucle 'for'" 24 "POSIX interdit une expression vide dans une boucle 'for'"
25 "POSIX interdit la notation exponentielle" 25 "POSIX exige une nouvelle ligne entre un point-virgule et une définition de fonction"
26 "POSIX interdit les références à un tableau dans les paramètres d'une fonction" 26 "POSIX interdit la notation exponentielle"
27 "POSIX impose que l'en-tête de la fonction et le '{' soient sur la même ligne" 27 "POSIX interdit les références à un tableau dans les paramètres d'une fonction"
28 "POSIX interdit pas d'assigner des chaînes de caractères à des variables ou à des tableaux" 28 "POSIX n'autorise pas les fonctions void"
29 "POSIX impose que l'en-tête de la fonction et le '{' soient sur la même ligne"
30 "POSIX interdit pas d'assigner des chaînes de caractères à des variables ou à des tableaux"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX interdit les opérateurs de comparaison en dehors des expressions 'if' ou des boucles" 22 "POSIX interdit les opérateurs de comparaison en dehors des expressions 'if' ou des boucles"
23 "POSIX impose 0 ou 1 opérateur de comparaison par condition" 23 "POSIX impose 0 ou 1 opérateur de comparaison par condition"
24 "POSIX interdit une expression vide dans une boucle 'for'" 24 "POSIX interdit une expression vide dans une boucle 'for'"
25 "POSIX interdit la notation exponentielle" 25 "POSIX exige une nouvelle ligne entre un point-virgule et une définition de fonction."
26 "POSIX interdit les références à un tableau dans les paramètres d'une fonction" 26 "POSIX interdit la notation exponentielle"
27 "POSIX impose que l'en-tête de la fonction et le '{' soient sur la même ligne" 27 "POSIX interdit les références à un tableau dans les paramètres d'une fonction"
28 "POSIX interdit pas d'assigner des chaînes de caractères à des variables ou à des tableaux" 28 "POSIX n'autorise pas les fonctions void"
29 "POSIX impose que l'en-tête de la fonction et le '{' soient sur la même ligne"
30 "POSIX interdit pas d'assigner des chaînes de caractères à des variables ou à des tableaux"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX は if 文やループの外の比較演算子を許可しません。" 22 "POSIX は if 文やループの外の比較演算子を許可しません。"
23 "POSIXは条件ごとに0または1の比較演算子を必要とします。" 23 "POSIXは条件ごとに0または1の比較演算子を必要とします。"
24 "POSIXはforループの3つの部分がすべて空でないことを要求します。" 24 "POSIXはforループの3つの部分がすべて空でないことを要求します。"
25 "POSIXは指数表記を許可しません。" 25 "POSIXでは、セミコロンと関数定義の間に改行を入れる必要があります。"
26 "POSIX は関数パラメータとして配列参照を許可しません。" 26 "POSIXは指数表記を許可しません。"
27 "POSIXでは、関数ヘッダと同じ行に左中括弧があることが必要です。" 27 "POSIX は関数パラメータとして配列参照を許可しません。"
28 "POSIXでは、変数や配列に文字列を割り当てることはできません。" 28 "POSIXではvoid関数を認めていません。"
29 "POSIXでは、関数ヘッダと同じ行に左中括弧があることが必要です。"
30 "POSIXでは、変数や配列に文字列を割り当てることはできません。"
$ ランタイムエラー。 $ ランタイムエラー。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX は if 文やループの外の比較演算子を許可しません。" 22 "POSIX は if 文やループの外の比較演算子を許可しません。"
23 "POSIXは条件ごとに0または1の比較演算子を必要とします。" 23 "POSIXは条件ごとに0または1の比較演算子を必要とします。"
24 "POSIXはforループの3つの部分がすべて空でないことを要求します。" 24 "POSIXはforループの3つの部分がすべて空でないことを要求します。"
25 "POSIXは指数表記を許可しません。" 25 "POSIXでは、セミコロンと関数定義の間に改行を入れる必要があります。"
26 "POSIX は関数パラメータとして配列参照を許可しません。" 26 "POSIXは指数表記を許可しません。"
27 "POSIXでは、関数ヘッダと同じ行に左中括弧があることが必要です。" 27 "POSIX は関数パラメータとして配列参照を許可しません。"
28 "POSIXでは、変数や配列に文字列を割り当てることはできません。" 28 "POSIXではvoid関数を認めていません。"
29 "POSIXでは、関数ヘッダと同じ行に左中括弧があることが必要です。"
30 "POSIXでは、変数や配列に文字列を割り当てることはできません。"
$ ランタイムエラー。 $ ランタイムエラー。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX laat geen vergelijking toe tussen operatoren buiten als verklaringen of lussen" 22 "POSIX laat geen vergelijking toe tussen operatoren buiten als verklaringen of lussen"
23 "POSIX vereist 0 of 1 vergelijkingsoperator per conditie" 23 "POSIX vereist 0 of 1 vergelijkingsoperator per conditie"
24 "POSIX vereist dat alle 3 de delen van een lus niet leeg zijn" 24 "POSIX vereist dat alle 3 de delen van een lus niet leeg zijn"
25 "POSIX laat geen exponentiële notatie toe" 25 "POSIX vereist een nieuwe regel tussen een puntkomma en een functiedefinitie"
26 "POSIX staat geen arrayreferenties toe als functieparameters" 26 "POSIX laat geen exponentiële notatie toe"
27 "POSIX vereist dat de linkse beugel op dezelfde regel staat als de functiehoofding" 27 "POSIX staat geen arrayreferenties toe als functieparameters"
28 "POSIX staat niet toe dat strings worden toegewezen aan variabelen of arrays" 28 "POSIX staat geen lege functies toe"
29 "POSIX vereist dat de linkse beugel op dezelfde regel staat als de functiehoofding"
30 "POSIX staat niet toe dat strings worden toegewezen aan variabelen of arrays"
$ Runtime fouten. $ Runtime fouten.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX laat geen vergelijking toe tussen operatoren buiten als verklaringen of lussen" 22 "POSIX laat geen vergelijking toe tussen operatoren buiten als verklaringen of lussen"
23 "POSIX vereist 0 of 1 vergelijkingsoperator per conditie" 23 "POSIX vereist 0 of 1 vergelijkingsoperator per conditie"
24 "POSIX vereist dat alle 3 de delen van een lus niet leeg zijn" 24 "POSIX vereist dat alle 3 de delen van een lus niet leeg zijn"
25 "POSIX laat geen exponentiële notatie toe" 25 "POSIX vereist een nieuwe regel tussen een puntkomma en een functiedefinitie"
26 "POSIX staat geen arrayreferenties toe als functieparameters" 26 "POSIX laat geen exponentiële notatie toe"
27 "POSIX vereist dat de linkse beugel op dezelfde regel staat als de functiehoofding" 27 "POSIX staat geen arrayreferenties toe als functieparameters"
28 "POSIX staat niet toe dat strings worden toegewezen aan variabelen of arrays" 28 "POSIX staat geen lege functies toe"
29 "POSIX vereist dat de linkse beugel op dezelfde regel staat als de functiehoofding"
30 "POSIX staat niet toe dat strings worden toegewezen aan variabelen of arrays"
$ Runtime fouten. $ Runtime fouten.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX nie pozwala na porównywanie operatorów na zewnątrz, jeśli deklaracje lub pętle" 22 "POSIX nie pozwala na porównywanie operatorów na zewnątrz, jeśli deklaracje lub pętle"
23 "POSIX wymaga 0 lub 1 operatora porównawczego na jeden warunek" 23 "POSIX wymaga 0 lub 1 operatora porównawczego na jeden warunek"
24 "POSIX wymaga, aby wszystkie 3 części pętli nie były puste" 24 "POSIX wymaga, aby wszystkie 3 części pętli nie były puste"
25 "POSIX nie pozwala na notację wykładniczą" 25 "POSIX wymaga nowej linii pomiędzy średnikiem a definicją funkcji"
26 "POSIX nie zezwala na odniesienia do tablicy jako parametrów funkcji" 26 "POSIX nie pozwala na notację wykładniczą"
27 "POSIX wymaga, aby lewe usztywnienie znajdowało się na tej samej linii co nagłówek funkcji" 27 "POSIX nie zezwala na odniesienia do tablicy jako parametrów funkcji"
28 "POSIX nie pozwala na przypisywanie ciągów znaków do zmiennych lub tablic" 28 "POSIX nie dopuszcza funkcji void"
29 "POSIX wymaga, aby lewe usztywnienie znajdowało się na tej samej linii co nagłówek funkcji"
30 "POSIX nie pozwala na przypisywanie ciągów znaków do zmiennych lub tablic"
$ Błędy Runtime'u. $ Błędy Runtime'u.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX nie pozwala na porównywanie operatorów na zewnątrz, jeśli deklaracje lub pętle" 22 "POSIX nie pozwala na porównywanie operatorów na zewnątrz, jeśli deklaracje lub pętle"
23 "POSIX wymaga 0 lub 1 operatora porównawczego na jeden warunek" 23 "POSIX wymaga 0 lub 1 operatora porównawczego na jeden warunek"
24 "POSIX wymaga, aby wszystkie 3 części pętli nie były puste" 24 "POSIX wymaga, aby wszystkie 3 części pętli nie były puste"
25 "POSIX nie pozwala na notację wykładniczą" 25 "POSIX wymaga nowej linii pomiędzy średnikiem a definicją funkcji"
26 "POSIX nie zezwala na odniesienia do tablicy jako parametrów funkcji" 26 "POSIX nie pozwala na notację wykładniczą"
27 "POSIX wymaga, aby lewe usztywnienie znajdowało się na tej samej linii co nagłówek funkcji" 27 "POSIX nie zezwala na odniesienia do tablicy jako parametrów funkcji"
28 "POSIX nie pozwala na przypisywanie ciągów znaków do zmiennych lub tablic" 28 "POSIX nie dopuszcza funkcji void"
29 "POSIX wymaga, aby lewe usztywnienie znajdowało się na tej samej linii co nagłówek funkcji"
30 "POSIX nie pozwala na przypisywanie ciągów znaków do zmiennych lub tablic"
$ Błędy Runtime'u. $ Błędy Runtime'u.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX não permite operadores de comparação fora das expressões 'if' ou loops" 22 "POSIX não permite operadores de comparação fora das expressões 'if' ou loops"
23 "POSIX requer operadores 0 ou 1 de comparação por condição" 23 "POSIX requer operadores 0 ou 1 de comparação por condição"
24 "POSIX não permite uma expressão vazia em um loop 'for'" 24 "POSIX não permite uma expressão vazia em um loop 'for'"
25 "POSIX não permite notação exponencial" 25 "POSIX requer uma nova linha entre um ponto-e-vírgula e uma definição de função"
26 "POSIX não permite referências de matriz como parâmetros de função" 26 "POSIX não permite notação exponencial"
27 "POSIX requer que o cabeçalho da função '{' estejam na mesma linha" 27 "POSIX não permite referências de matriz como parâmetros de função"
28 "POSIX não permite a atribuição de cadeias de caracteres a variáveis ou matrizes" 28 "POSIX não permite funções nulas"
29 "POSIX requer que o cabeçalho da função '{' estejam na mesma linha"
30 "POSIX não permite a atribuição de cadeias de caracteres a variáveis ou matrizes"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX não permite operadores de comparação fora das expressões 'if' ou loops" 22 "POSIX não permite operadores de comparação fora das expressões 'if' ou loops"
23 "POSIX requer operadores 0 ou 1 de comparação por condição" 23 "POSIX requer operadores 0 ou 1 de comparação por condição"
24 "POSIX não permite uma expressão vazia em um loop 'for'" 24 "POSIX não permite uma expressão vazia em um loop 'for'"
25 "POSIX não permite notação exponencial" 25 "POSIX requer uma nova linha entre um ponto-e-vírgula e uma definição de função"
26 "POSIX não permite referências de matriz como parâmetros de função" 26 "POSIX não permite notação exponencial"
27 "POSIX requer que o cabeçalho da função '{' estejam na mesma linha" 27 "POSIX não permite referências de matriz como parâmetros de função"
28 "POSIX não permite a atribuição de cadeias de caracteres a variáveis ou matrizes" 28 "POSIX não permite funções nulas"
29 "POSIX requer que o cabeçalho da função '{' estejam na mesma linha"
30 "POSIX não permite a atribuição de cadeias de caracteres a variáveis ou matrizes"
$ Runtime errors. $ Runtime errors.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы" 22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы"
23 "POSIX требует 0 или 1 оператора сравнения на условие" 23 "POSIX требует 0 или 1 оператора сравнения на условие"
24 "POSIX требует, чтобы все 3 части петли были непустыми" 24 "POSIX требует, чтобы все 3 части петли были непустыми"
25 "POSIX не допускает экспоненциальной нотации" 25 "POSIX требует наличия новой строки между точкой с запятой и определением функции"
26 "POSIX не допускает ссылки на массив в качестве параметров функции" 26 "POSIX не допускает экспоненциальной нотации"
27 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции" 27 "POSIX не допускает ссылки на массив в качестве параметров функции"
28 "POSIX не позволяет присваивать строки переменным или массивам" 28 "POSIX не разрешает функции пустоты"
29 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции"
30 "POSIX не позволяет присваивать строки переменным или массивам"
$ Ошибки выполнения. $ Ошибки выполнения.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX ­¥ à §à¥è ¥â ®¯¥à â®à ¬ áà ¢­¥­¨ï ¢ë室¨âì §  ¯à¥¤¥«ë, ¥á«¨ ã⢥ত¥­¨ï ¨«¨ 横«ë" 22 "POSIX ­¥ à §à¥è ¥â ®¯¥à â®à ¬ áà ¢­¥­¨ï ¢ë室¨âì §  ¯à¥¤¥«ë, ¥á«¨ ã⢥ত¥­¨ï ¨«¨ 横«ë"
23 "POSIX âॡã¥â 0 ¨«¨ 1 ®¯¥à â®à  áà ¢­¥­¨ï ­  ãá«®¢¨¥" 23 "POSIX âॡã¥â 0 ¨«¨ 1 ®¯¥à â®à  áà ¢­¥­¨ï ­  ãá«®¢¨¥"
24 "POSIX âॡã¥â, çâ®¡ë ¢á¥ 3 ç á⨠¯¥â«¨ ¡ë«¨ ­¥¯ãáâ묨" 24 "POSIX âॡã¥â, çâ®¡ë ¢á¥ 3 ç á⨠¯¥â«¨ ¡ë«¨ ­¥¯ãáâ묨"
25 "POSIX ­¥ ¤®¯ã᪠¥â íªá¯®­¥­æ¨ «ì­®© ­®â æ¨¨" 25 "POSIX âॡã¥â ­ «¨ç¨ï ­®¢®© áâப¨ ¬¥¦¤ã â®çª®© á § ¯ï⮩ ¨ ®¯à¥¤¥«¥­¨¥¬ ä㭪樨"
26 "POSIX ­¥ ¤®¯ã᪠¥â áá뫪¨ ­  ¬ áᨢ ¢ ª ç¥á⢥ ¯ à ¬¥â஢ ä㭪樨" 26 "POSIX ­¥ ¤®¯ã᪠¥â íªá¯®­¥­æ¨ «ì­®© ­®â æ¨¨"
27 "POSIX âॡã¥â, çâ®¡ë «¥¢ ï ᪮¡ª  ¡ë«  ­  ⮩ ¦¥ «¨­¨¨, çâ® ¨ § £®«®¢®ª ä㭪樨" 27 "POSIX ­¥ ¤®¯ã᪠¥â áá뫪¨ ­  ¬ áᨢ ¢ ª ç¥á⢥ ¯ à ¬¥â஢ ä㭪樨"
28 "POSIX ­¥ ¯®§¢®«ï¥â ¯à¨á¢ ¨¢ âì áâப¨ ¯¥à¥¬¥­­ë¬ ¨«¨ ¬ áᨢ ¬" 28 "POSIX ­¥ à §à¥è ¥â ä㭪樨 ¯ãáâ®âë"
29 "POSIX âॡã¥â, çâ®¡ë «¥¢ ï ᪮¡ª  ¡ë«  ­  ⮩ ¦¥ «¨­¨¨, çâ® ¨ § £®«®¢®ª ä㭪樨"
30 "POSIX ­¥ ¯®§¢®«ï¥â ¯à¨á¢ ¨¢ âì áâப¨ ¯¥à¥¬¥­­ë¬ ¨«¨ ¬ áᨢ ¬"
$ Žè¨¡ª¨ ¢ë¯®«­¥­¨ï. $ Žè¨¡ª¨ ¢ë¯®«­¥­¨ï.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы" 22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы"
23 "POSIX требует 0 или 1 оператора сравнения на условие" 23 "POSIX требует 0 или 1 оператора сравнения на условие"
24 "POSIX требует, чтобы все 3 части петли были непустыми" 24 "POSIX требует, чтобы все 3 части петли были непустыми"
25 "POSIX не допускает экспоненциальной нотации" 25 "POSIX требует наличия новой строки между точкой с запятой и определением функции"
26 "POSIX не допускает ссылки на массив в качестве параметров функции" 26 "POSIX не допускает экспоненциальной нотации"
27 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции" 27 "POSIX не допускает ссылки на массив в качестве параметров функции"
28 "POSIX не позволяет присваивать строки переменным или массивам" 28 "POSIX не разрешает функции пустоты"
29 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции"
30 "POSIX не позволяет присваивать строки переменным или массивам"
$ Ошибки выполнения. $ Ошибки выполнения.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы" 22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы"
23 "POSIX требует 0 или 1 оператора сравнения на условие" 23 "POSIX требует 0 или 1 оператора сравнения на условие"
24 "POSIX требует, чтобы все 3 части петли были непустыми" 24 "POSIX требует, чтобы все 3 части петли были непустыми"
25 "POSIX не допускает экспоненциальной нотации" 25 "POSIX требует наличия новой строки между точкой с запятой и определением функции"
26 "POSIX не допускает ссылки на массив в качестве параметров функции" 26 "POSIX не допускает экспоненциальной нотации"
27 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции" 27 "POSIX не допускает ссылки на массив в качестве параметров функции"
28 "POSIX не позволяет присваивать строки переменным или массивам" 28 "POSIX не разрешает функции пустоты"
29 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции"
30 "POSIX не позволяет присваивать строки переменным или массивам"
$ Ошибки выполнения. $ Ошибки выполнения.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы" 22 "POSIX не разрешает операторам сравнения выходить за пределы, если утверждения или циклы"
23 "POSIX требует 0 или 1 оператора сравнения на условие" 23 "POSIX требует 0 или 1 оператора сравнения на условие"
24 "POSIX требует, чтобы все 3 части петли были непустыми" 24 "POSIX требует, чтобы все 3 части петли были непустыми"
25 "POSIX не допускает экспоненциальной нотации" 25 "POSIX требует наличия новой строки между точкой с запятой и определением функции"
26 "POSIX не допускает ссылки на массив в качестве параметров функции" 26 "POSIX не допускает экспоненциальной нотации"
27 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции" 27 "POSIX не допускает ссылки на массив в качестве параметров функции"
28 "POSIX не позволяет присваивать строки переменным или массивам" 28 "POSIX не разрешает функции пустоты"
29 "POSIX требует, чтобы левая скобка была на той же линии, что и заголовок функции"
30 "POSIX не позволяет присваивать строки переменным или массивам"
$ Ошибки выполнения. $ Ошибки выполнения.
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX不允许在if语句或循环之外的比较运算符" 22 "POSIX不允许在if语句或循环之外的比较运算符"
23 "POSIX要求每个条件的比较运算符为0或1个" 23 "POSIX要求每个条件的比较运算符为0或1个"
24 "POSIX要求for循环的所有3个部分必须是非空的" 24 "POSIX要求for循环的所有3个部分必须是非空的"
25 "POSIX不允许使用指数符号" 25 "POSIX要求在分号和函数定义之间使用换行符"
26 "POSIX不允许数组引用作为函数参数" 26 "POSIX不允许使用指数符号"
27 "POSIX要求左边的括号和函数头在同一行上" 27 "POSIX不允许数组引用作为函数参数"
28 "POSIX不允许将字符串分配给变量或数组" 28 "POSIX不允许无效函数"
29 "POSIX要求左边的括号和函数头在同一行上"
30 "POSIX不允许将字符串分配给变量或数组"
$ 运行时错误。 $ 运行时错误。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX不允许在if语句或循环之外的比较运算符" 22 "POSIX不允许在if语句或循环之外的比较运算符"
23 "POSIX要求每个条件的比较运算符为0或1个" 23 "POSIX要求每个条件的比较运算符为0或1个"
24 "POSIX要求for循环的所有3个部分必须是非空的" 24 "POSIX要求for循环的所有3个部分必须是非空的"
25 "POSIX不允许使用指数符号" 25 "POSIX要求在分号和函数定义之间使用换行符"
26 "POSIX不允许数组引用作为函数参数" 26 "POSIX不允许使用指数符号"
27 "POSIX要求左边的括号和函数头在同一行上" 27 "POSIX不允许数组引用作为函数参数"
28 "POSIX不允许将字符串分配给变量或数组" 28 "POSIX不允许无效函数"
29 "POSIX要求左边的括号和函数头在同一行上"
30 "POSIX不允许将字符串分配给变量或数组"
$ 运行时错误。 $ 运行时错误。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX不允许在if语句或循环之外的比较运算符" 22 "POSIX不允许在if语句或循环之外的比较运算符"
23 "POSIX要求每个条件的比较运算符为0或1个" 23 "POSIX要求每个条件的比较运算符为0或1个"
24 "POSIX要求for循环的所有3个部分必须是非空的" 24 "POSIX要求for循环的所有3个部分必须是非空的"
25 "POSIX不允许使用指数符号" 25 "POSIX要求在分号和函数定义之间使用换行符"
26 "POSIX不允许数组引用作为函数参数" 26 "POSIX不允许使用指数符号"
27 "POSIX要求左边的括号和函数头在同一行上" 27 "POSIX不允许数组引用作为函数参数"
28 "POSIX不允许将字符串分配给变量或数组" 28 "POSIX不允许无效函数"
29 "POSIX要求左边的括号和函数头在同一行上"
30 "POSIX不允许将字符串分配给变量或数组"
$ 运行时错误。 $ 运行时错误。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX不允许在if语句或循环之外的比较运算符" 22 "POSIX不允许在if语句或循环之外的比较运算符"
23 "POSIX要求每个条件的比较运算符为0或1个" 23 "POSIX要求每个条件的比较运算符为0或1个"
24 "POSIX要求for循环的所有3个部分必须是非空的" 24 "POSIX要求for循环的所有3个部分必须是非空的"
25 "POSIX不允许使用指数符号" 25 "POSIX要求在分号和函数定义之间使用换行符"
26 "POSIX不允许数组引用作为函数参数" 26 "POSIX不允许使用指数符号"
27 "POSIX要求左边的括号和函数头在同一行上" 27 "POSIX不允许数组引用作为函数参数"
28 "POSIX不允许将字符串分配给变量或数组" 28 "POSIX不允许无效函数"
29 "POSIX要求左边的括号和函数头在同一行上"
30 "POSIX不允许将字符串分配给变量或数组"
$ 运行时错误。 $ 运行时错误。
$set 5 $set 5

View File

@ -77,10 +77,12 @@ $set 4
22 "POSIX不允许在if语句或循环之外的比较运算符" 22 "POSIX不允许在if语句或循环之外的比较运算符"
23 "POSIX要求每个条件的比较运算符为0或1个" 23 "POSIX要求每个条件的比较运算符为0或1个"
24 "POSIX要求for循环的所有3个部分必须是非空的" 24 "POSIX要求for循环的所有3个部分必须是非空的"
25 "POSIX不允许使用指数符号" 25 "POSIX要求在分号和函数定义之间使用换行符"
26 "POSIX不允许数组引用作为函数参数" 26 "POSIX不允许使用指数符号"
27 "POSIX要求左边的括号和函数头在同一行上" 27 "POSIX不允许数组引用作为函数参数"
28 "POSIX不允许将字符串分配给变量或数组" 28 "POSIX不允许无效函数"
29 "POSIX要求左边的括号和函数头在同一行上"
30 "POSIX不允许将字符串分配给变量或数组"
$ 运行时错误。 $ 运行时错误。
$set 5 $set 5

View File

@ -2552,6 +2552,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1400,6 +1400,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1400,6 +1400,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1400,6 +1400,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1400,6 +1400,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2552,6 +2552,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2552,6 +2552,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2552,6 +2552,19 @@ This environment variable and the \f[B]BC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]BC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes bc(1) exit after executing the
expressions and expression files, and a non-zero value makes bc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**BC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes bc(1) exit
after executing the expressions and expression files, and a non-zero value
makes bc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
bc(1) returns the following exit statuses: bc(1) returns the following exit statuses:

View File

@ -83,6 +83,23 @@ where `<config>` is either one of `Debug`, `ReleaseMD`, or `ReleaseMT`.
Building `bc`, `dc`, and `bcl` (the library) is more complex than on Windows Building `bc`, `dc`, and `bcl` (the library) is more complex than on Windows
because many build options are supported. because many build options are supported.
### Out-of-Source Builds
Out-of-source builds are done by calling `configure.sh` from the directory where
the build will happen. The `Makefile` is generated into that directory, and the
build can happen normally from there.
For example, if the source is in `bc`, the build should happen in `build`, then
call `configure.sh` and `make` like so:
```
../bc/configure.sh
make
```
***WARNING***: The path to `configure.sh` from the build directory must not have
spaces because `make` does not support target names with spaces.
### Cross Compiling ### Cross Compiling
To cross-compile this `bc`, an appropriate compiler must be present and assigned To cross-compile this `bc`, an appropriate compiler must be present and assigned

View File

@ -1340,6 +1340,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1135,6 +1135,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1135,6 +1135,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1135,6 +1135,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1135,6 +1135,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1340,6 +1340,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1340,6 +1340,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1340,6 +1340,19 @@ This environment variable and the \f[B]DC_TTY_MODE\f[R] environment
variable override the default, which can be queried with the variable override the default, which can be queried with the
\f[B]-h\f[R] or \f[B]--help\f[R] options. \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE .RE
.TP
\f[B]DC_EXPR_EXIT\f[R]
If any expressions or expression files are given on the command-line
with \f[B]-e\f[R], \f[B]--expression\f[R], \f[B]-f\f[R], or
\f[B]--file\f[R], then if this environment variable exists and contains
an integer, a non-zero value makes dc(1) exit after executing the
expressions and expression files, and a non-zero value makes dc(1) not
exit.
.RS
.PP
This environment variable overrides the default, which can be queried
with the \f[B]-h\f[R] or \f[B]--help\f[R] options.
.RE
.SH EXIT STATUS .SH EXIT STATUS
.PP .PP
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables:
override the default, which can be queried with the **-h** or **-\-help** override the default, which can be queried with the **-h** or **-\-help**
options. options.
**DC_EXPR_EXIT**
: If any expressions or expression files are given on the command-line with
**-e**, **-\-expression**, **-f**, or **-\-file**, then if this environment
variable exists and contains an integer, a non-zero value makes dc(1) exit
after executing the expressions and expression files, and a non-zero value
makes dc(1) not exit.
This environment variable overrides the default, which can be queried with
the **-h** or **-\-help** options.
# EXIT STATUS # EXIT STATUS
dc(1) returns the following exit statuses: dc(1) returns the following exit statuses:

View File

@ -29,7 +29,7 @@
# Print usage and exit with an error. # Print usage and exit with an error.
usage() { usage() {
printf "usage: %s install_dir exec_suffix\n" "$0" 1>&2 printf "usage: %s install_dir exec_suffix [bindir]\n" "$0" 1>&2
exit 1 exit 1
} }
@ -49,7 +49,12 @@ shift
exec_suffix="$1" exec_suffix="$1"
shift shift
bindir="$scriptdir/../bin" if [ "$#" -gt 0 ]; then
bindir="$1"
shift
else
bindir="$scriptdir/../bin"
fi
# Install or symlink, depending on the type of file. If it's a file, install it. # Install or symlink, depending on the type of file. If it's a file, install it.
# If it's a symlink, create an equivalent in the install directory. # If it's a symlink, create an equivalent in the install directory.

View File

@ -49,9 +49,6 @@ def run(cmd, env=None):
if testdir == "": if testdir == "":
testdir = os.getcwd() testdir = os.getcwd()
# We want to be in the root directory.
os.chdir(testdir + "/..")
print("\nWARNING: This script is for distro and package maintainers.") print("\nWARNING: This script is for distro and package maintainers.")
print("It is for finding the optimal Karatsuba number.") print("It is for finding the optimal Karatsuba number.")
print("Though it only needs to be run once per release/platform,") print("Though it only needs to be run once per release/platform,")
@ -116,7 +113,7 @@ def run(cmd, env=None):
except KeyError: except KeyError:
flags["CFLAGS"] = "-flto" flags["CFLAGS"] = "-flto"
p = run([ "./configure.sh", "-O3" ], flags) p = run([ "{}/../configure.sh".format(testdir), "-O3" ], flags)
if p.returncode != 0: if p.returncode != 0:
print("configure.sh returned an error ({}); exiting...".format(p.returncode)) print("configure.sh returned an error ({}); exiting...".format(p.returncode))
sys.exit(p.returncode) sys.exit(p.returncode)
@ -161,7 +158,7 @@ def run(cmd, env=None):
# Configure and compile. # Configure and compile.
print("\nCompiling...\n") print("\nCompiling...\n")
p = run([ "./configure.sh", "-O3", "-k{}".format(i) ], config_env) p = run([ "{}/../configure.sh".format(testdir), "-O3", "-k{}".format(i) ], config_env)
if p.returncode != 0: if p.returncode != 0:
print("configure.sh returned an error ({}); exiting...".format(p.returncode)) print("configure.sh returned an error ({}); exiting...".format(p.returncode))

View File

@ -91,6 +91,8 @@ static void bc_args_redefine(const char *keyword) {
size_t i; size_t i;
BC_SIG_ASSERT_LOCKED;
for (i = 0; i < bc_lex_kws_len; ++i) { for (i = 0; i < bc_lex_kws_len; ++i) {
const BcLexKeyword *kw = bc_lex_kws + i; const BcLexKeyword *kw = bc_lex_kws + i;

View File

@ -158,6 +158,8 @@ void bc_lex_token(BcLex *l) {
// character of every identifier would be missing. // character of every identifier would be missing.
char c = l->buf[l->i++], c2; char c = l->buf[l->i++], c2;
BC_SIG_ASSERT_LOCKED;
// This is the workhorse of the lexer. // This is the workhorse of the lexer.
switch (c) { switch (c) {

View File

@ -79,6 +79,7 @@ static bool bc_parse_inst_isLeaf(BcInst t) {
* that can legally end a statement. In bc's case, it could be a newline, a * that can legally end a statement. In bc's case, it could be a newline, a
* semicolon, and a brace in certain cases. * semicolon, and a brace in certain cases.
* @param p The parser. * @param p The parser.
* @return True if the token is a legal delimiter.
*/ */
static bool bc_parse_isDelimiter(const BcParse *p) { static bool bc_parse_isDelimiter(const BcParse *p) {
@ -127,6 +128,23 @@ static bool bc_parse_isDelimiter(const BcParse *p) {
return good; return good;
} }
/**
* Returns true if we are in top level of a function body. The POSIX grammar
* is defined such that anything is allowed after a function body, so we must
* use this function to detect that case when ending a function body.
* @param p The parser.
* @return True if we are in the top level of parsing a function body.
*/
static bool bc_parse_TopFunc(const BcParse *p) {
bool good = p->flags.len == 2;
uint16_t val = BC_PARSE_FLAG_BRACE | BC_PARSE_FLAG_FUNC_INNER;
val |= BC_PARSE_FLAG_FUNC;
return good && BC_PARSE_TOP_FLAG(p) == val;
}
/** /**
* Sets a previously defined exit label. What are labels? See the bc Parsing * Sets a previously defined exit label. What are labels? See the bc Parsing
* section of the Development manual (manuals/development.md). * section of the Development manual (manuals/development.md).
@ -329,12 +347,8 @@ static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) {
// not define it, it's a *runtime* error, not a parse error. // not define it, it's a *runtime* error, not a parse error.
if (idx == BC_VEC_INVALID_IDX) { if (idx == BC_VEC_INVALID_IDX) {
BC_SIG_LOCK;
idx = bc_program_insertFunc(p->prog, name); idx = bc_program_insertFunc(p->prog, name);
BC_SIG_UNLOCK;
assert(idx != BC_VEC_INVALID_IDX); assert(idx != BC_VEC_INVALID_IDX);
// Make sure that this pointer was not invalidated. // Make sure that this pointer was not invalidated.
@ -359,15 +373,13 @@ static void bc_parse_name(BcParse *p, BcInst *type,
{ {
char *name; char *name;
BC_SIG_LOCK; BC_SIG_ASSERT_LOCKED;
// We want a copy of the name since the lexer might overwrite its copy. // We want a copy of the name since the lexer might overwrite its copy.
name = bc_vm_strdup(p->l.str.v); name = bc_vm_strdup(p->l.str.v);
BC_SETJMP_LOCKED(err); BC_SETJMP_LOCKED(err);
BC_SIG_UNLOCK;
// We need the next token to see if it's just a variable or something more. // We need the next token to see if it's just a variable or something more.
bc_lex_next(&p->l); bc_lex_next(&p->l);
@ -431,9 +443,9 @@ static void bc_parse_name(BcParse *p, BcInst *type,
err: err:
// Need to make sure to unallocate the name. // Need to make sure to unallocate the name.
BC_SIG_MAYLOCK;
free(name); free(name);
BC_LONGJMP_CONT; BC_LONGJMP_CONT;
BC_SIG_MAYLOCK;
} }
/** /**
@ -887,7 +899,7 @@ static void bc_parse_endBody(BcParse *p, bool brace) {
bc_lex_next(&p->l); bc_lex_next(&p->l);
// If the next token is not a delimiter, that is a problem. // If the next token is not a delimiter, that is a problem.
if (BC_ERR(!bc_parse_isDelimiter(p))) if (BC_ERR(!bc_parse_isDelimiter(p) && !bc_parse_TopFunc(p)))
bc_parse_err(p, BC_ERR_PARSE_TOKEN); bc_parse_err(p, BC_ERR_PARSE_TOKEN);
} }
@ -1315,15 +1327,9 @@ static void bc_parse_func(BcParse *p) {
// Make sure the functions map and vector are synchronized. // Make sure the functions map and vector are synchronized.
assert(p->prog->fns.len == p->prog->fn_map.len); assert(p->prog->fns.len == p->prog->fn_map.len);
// Must lock signals because vectors are changed, and the vector functions
// expect signals to be locked.
BC_SIG_LOCK;
// Insert the function by name into the map and vector. // Insert the function by name into the map and vector.
idx = bc_program_insertFunc(p->prog, p->l.str.v); idx = bc_program_insertFunc(p->prog, p->l.str.v);
BC_SIG_UNLOCK;
// Make sure the insert worked. // Make sure the insert worked.
assert(idx); assert(idx);
@ -1753,13 +1759,21 @@ static void bc_parse_stmt(BcParse *p) {
// Make sure semicolons are eaten. // Make sure semicolons are eaten.
while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l); while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l);
// POSIX's grammar does not allow a function definition after a semicolon
// without a newline, so check specifically for that case and error if
// the POSIX standard flag is set.
if (p->l.last == BC_LEX_SCOLON && p->l.t == BC_LEX_KW_DEFINE && BC_IS_POSIX)
{
bc_parse_err(p, BC_ERR_POSIX_FUNC_AFTER_SEMICOLON);
}
} }
void bc_parse_parse(BcParse *p) { void bc_parse_parse(BcParse *p) {
assert(p); assert(p);
BC_SETJMP(exit); BC_SETJMP_LOCKED(exit);
// We should not let an EOF get here unless some partial parse was not // We should not let an EOF get here unless some partial parse was not
// completed, in which case, it's the user's fault. // completed, in which case, it's the user's fault.
@ -1780,13 +1794,12 @@ void bc_parse_parse(BcParse *p) {
exit: exit:
BC_SIG_MAYLOCK;
// We need to reset on error. // We need to reset on error.
if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig))) if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
bc_parse_reset(p); bc_parse_reset(p);
BC_LONGJMP_CONT; BC_LONGJMP_CONT;
BC_SIG_MAYLOCK;
} }
/** /**

View File

@ -202,7 +202,7 @@ const uchar bc_err_ids[] = {
BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
#endif // BC_ENABLED #endif // BC_ENABLED
}; };
@ -273,6 +273,7 @@ const char* const bc_err_msgs[] = {
"POSIX does not allow comparison operators outside if statements or loops", "POSIX does not allow comparison operators outside if statements or loops",
"POSIX requires 0 or 1 comparison operators per condition", "POSIX requires 0 or 1 comparison operators per condition",
"POSIX requires all 3 parts of a for loop to be non-empty", "POSIX requires all 3 parts of a for loop to be non-empty",
"POSIX requires a newline between a semicolon and a function definition",
#if BC_ENABLE_EXTRA_MATH #if BC_ENABLE_EXTRA_MATH
"POSIX does not allow exponential notation", "POSIX does not allow exponential notation",
#else #else

View File

@ -157,6 +157,8 @@ void dc_lex_token(BcLex *l) {
char c = l->buf[l->i++], c2; char c = l->buf[l->i++], c2;
size_t i; size_t i;
BC_SIG_ASSERT_LOCKED;
// If the last token was a command that needs a register, we need to parse a // If the last token was a command that needs a register, we need to parse a
// register, so do so. // register, so do so.
for (i = 0; i < dc_lex_regs_len; ++i) { for (i = 0; i < dc_lex_regs_len; ++i) {

View File

@ -302,7 +302,7 @@ void dc_parse_parse(BcParse *p) {
assert(p != NULL); assert(p != NULL);
BC_SETJMP(exit); BC_SETJMP_LOCKED(exit);
// If we have EOF, someone called this function one too many times. // If we have EOF, someone called this function one too many times.
// Otherwise, parse. // Otherwise, parse.
@ -311,11 +311,10 @@ void dc_parse_parse(BcParse *p) {
exit: exit:
BC_SIG_MAYLOCK;
// Need to reset if there was an error. // Need to reset if there was an error.
if (BC_SIG_EXC) bc_parse_reset(p); if (BC_SIG_EXC) bc_parse_reset(p);
BC_LONGJMP_CONT; BC_LONGJMP_CONT;
BC_SIG_MAYLOCK;
} }
#endif // DC_ENABLED #endif // DC_ENABLED

View File

@ -94,8 +94,12 @@ static BcStatus bc_file_output(int fd, const char *buf, size_t n) {
ssize_t written = write(fd, buf + bytes, n - bytes); ssize_t written = write(fd, buf + bytes, n - bytes);
// Check for error and return, if any. // Check for error and return, if any.
if (BC_ERR(written == -1)) if (BC_ERR(written == -1)) {
BC_SIG_TRYUNLOCK(lock);
return errno == EPIPE ? BC_STATUS_EOF : BC_STATUS_ERROR_FATAL; return errno == EPIPE ? BC_STATUS_EOF : BC_STATUS_ERROR_FATAL;
}
bytes += (size_t) written; bytes += (size_t) written;
} }
@ -109,6 +113,8 @@ BcStatus bc_file_flushErr(BcFile *restrict f, BcFlushType type)
{ {
BcStatus s; BcStatus s;
BC_SIG_ASSERT_LOCKED;
// If there is stuff to output... // If there is stuff to output...
if (f->len) { if (f->len) {
@ -151,7 +157,12 @@ BcStatus bc_file_flushErr(BcFile *restrict f, BcFlushType type)
void bc_file_flush(BcFile *restrict f, BcFlushType type) { void bc_file_flush(BcFile *restrict f, BcFlushType type) {
BcStatus s = bc_file_flushErr(f, type); BcStatus s;
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
s = bc_file_flushErr(f, type);
// If we have an error... // If we have an error...
if (BC_ERR(s)) { if (BC_ERR(s)) {
@ -159,16 +170,23 @@ void bc_file_flush(BcFile *restrict f, BcFlushType type) {
// For EOF, set it and jump. // For EOF, set it and jump.
if (s == BC_STATUS_EOF) { if (s == BC_STATUS_EOF) {
vm.status = (sig_atomic_t) s; vm.status = (sig_atomic_t) s;
BC_SIG_TRYUNLOCK(lock);
BC_JMP; BC_JMP;
} }
// Blow up on fatal error. Okay, not blow up, just quit. // Blow up on fatal error. Okay, not blow up, just quit.
else bc_vm_fatalError(BC_ERR_FATAL_IO_ERR); else bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
} }
BC_SIG_TRYUNLOCK(lock);
} }
void bc_file_write(BcFile *restrict f, BcFlushType type, void bc_file_write(BcFile *restrict f, BcFlushType type,
const char *buf, size_t n) const char *buf, size_t n)
{ {
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
// If we have enough to flush, do it. // If we have enough to flush, do it.
if (n > f->cap - f->len) { if (n > f->cap - f->len) {
bc_file_flush(f, type); bc_file_flush(f, type);
@ -182,15 +200,22 @@ void bc_file_write(BcFile *restrict f, BcFlushType type,
memcpy(f->buf + f->len, buf, n); memcpy(f->buf + f->len, buf, n);
f->len += n; f->len += n;
} }
BC_SIG_TRYUNLOCK(lock);
} }
void bc_file_printf(BcFile *restrict f, const char *fmt, ...) void bc_file_printf(BcFile *restrict f, const char *fmt, ...)
{ {
va_list args; va_list args;
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
va_start(args, fmt); va_start(args, fmt);
bc_file_vprintf(f, fmt, args); bc_file_vprintf(f, fmt, args);
va_end(args); va_end(args);
BC_SIG_TRYUNLOCK(lock);
} }
void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) { void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
@ -199,6 +224,8 @@ void bc_file_vprintf(BcFile *restrict f, const char *fmt, va_list args) {
const char *ptr = fmt; const char *ptr = fmt;
char buf[BC_FILE_ULL_LENGTH]; char buf[BC_FILE_ULL_LENGTH];
BC_SIG_ASSERT_LOCKED;
// This is a poor man's printf(). While I could look up algorithms to make // This is a poor man's printf(). While I could look up algorithms to make
// it as fast as possible, and should when I write the standard library for // it as fast as possible, and should when I write the standard library for
// a new language, for bc, outputting is not the bottleneck. So we cheese it // a new language, for bc, outputting is not the bottleneck. So we cheese it
@ -287,12 +314,18 @@ void bc_file_puts(BcFile *restrict f, BcFlushType type, const char *str) {
void bc_file_putchar(BcFile *restrict f, BcFlushType type, uchar c) { void bc_file_putchar(BcFile *restrict f, BcFlushType type, uchar c) {
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
if (f->len == f->cap) bc_file_flush(f, type); if (f->len == f->cap) bc_file_flush(f, type);
assert(f->len < f->cap); assert(f->len < f->cap);
f->buf[f->len] = (char) c; f->buf[f->len] = (char) c;
f->len += 1; f->len += 1;
BC_SIG_TRYUNLOCK(lock);
} }
void bc_file_init(BcFile *f, int fd, char *buf, size_t cap) { void bc_file_init(BcFile *f, int fd, char *buf, size_t cap) {

View File

@ -375,7 +375,7 @@ static ssize_t bc_history_read(char *buf, size_t n) {
ssize_t ret; ssize_t ret;
BC_SIG_LOCK; BC_SIG_ASSERT_LOCKED;
#ifndef _WIN32 #ifndef _WIN32
@ -396,8 +396,6 @@ static ssize_t bc_history_read(char *buf, size_t n) {
#endif // _WIN32 #endif // _WIN32
BC_SIG_UNLOCK;
return ret; return ret;
} }
@ -416,8 +414,13 @@ static BcStatus bc_history_readCode(char *buf, size_t buf_len,
assert(buf_len >= 1); assert(buf_len >= 1);
BC_SIG_LOCK;
// Read a byte. // Read a byte.
n = bc_history_read(buf, 1); n = bc_history_read(buf, 1);
BC_SIG_UNLOCK;
if (BC_ERR(n <= 0)) goto err; if (BC_ERR(n <= 0)) goto err;
// Get the byte. // Get the byte.
@ -431,24 +434,36 @@ static BcStatus bc_history_readCode(char *buf, size_t buf_len,
assert(buf_len >= 2); assert(buf_len >= 2);
BC_SIG_LOCK;
n = bc_history_read(buf + 1, 1); n = bc_history_read(buf + 1, 1);
BC_SIG_UNLOCK;
if (BC_ERR(n <= 0)) goto err; if (BC_ERR(n <= 0)) goto err;
} }
else if ((byte & 0xF0) == 0xE0) { else if ((byte & 0xF0) == 0xE0) {
assert(buf_len >= 3); assert(buf_len >= 3);
BC_SIG_LOCK;
n = bc_history_read(buf + 1, 2); n = bc_history_read(buf + 1, 2);
BC_SIG_UNLOCK;
if (BC_ERR(n <= 0)) goto err; if (BC_ERR(n <= 0)) goto err;
} }
else if ((byte & 0xF8) == 0xF0) { else if ((byte & 0xF8) == 0xF0) {
assert(buf_len >= 3); assert(buf_len >= 3);
BC_SIG_LOCK;
n = bc_history_read(buf + 1, 3); n = bc_history_read(buf + 1, 3);
BC_SIG_UNLOCK;
if (BC_ERR(n <= 0)) goto err; if (BC_ERR(n <= 0)) goto err;
} }
else { else {
@ -606,6 +621,8 @@ static size_t bc_history_cursorPos(void) {
char *ptr, *ptr2; char *ptr, *ptr2;
size_t cols, rows, i; size_t cols, rows, i;
BC_SIG_ASSERT_LOCKED;
// Report cursor location. // Report cursor location.
bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4); bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4);
bc_file_flush(&vm.fout, bc_flush_none); bc_file_flush(&vm.fout, bc_flush_none);
@ -648,12 +665,8 @@ static size_t bc_history_columns(void) {
struct winsize ws; struct winsize ws;
int ret; int ret;
BC_SIG_LOCK;
ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws); ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws);
BC_SIG_UNLOCK;
if (BC_ERR(ret == -1 || !ws.ws_col)) { if (BC_ERR(ret == -1 || !ws.ws_col)) {
// Calling ioctl() failed. Try to query the terminal itself. // Calling ioctl() failed. Try to query the terminal itself.
@ -721,6 +734,8 @@ static void bc_history_refresh(BcHistory *h) {
char* buf = h->buf.v; char* buf = h->buf.v;
size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0; size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0;
BC_SIG_ASSERT_LOCKED;
bc_file_flush(&vm.fout, bc_flush_none); bc_file_flush(&vm.fout, bc_flush_none);
// Get to the prompt column position from the left. // Get to the prompt column position from the left.
@ -783,6 +798,8 @@ static void bc_history_refresh(BcHistory *h) {
*/ */
static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen) static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
{ {
BC_SIG_ASSERT_LOCKED;
bc_vec_grow(&h->buf, clen); bc_vec_grow(&h->buf, clen);
// If we are at the end of the line... // If we are at the end of the line...
@ -836,6 +853,8 @@ static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
*/ */
static void bc_history_edit_left(BcHistory *h) { static void bc_history_edit_left(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
// Stop at the left end. // Stop at the left end.
if (h->pos <= 0) return; if (h->pos <= 0) return;
@ -850,6 +869,8 @@ static void bc_history_edit_left(BcHistory *h) {
*/ */
static void bc_history_edit_right(BcHistory *h) { static void bc_history_edit_right(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
// Stop at the right end. // Stop at the right end.
if (h->pos == BC_HIST_BUF_LEN(h)) return; if (h->pos == BC_HIST_BUF_LEN(h)) return;
@ -866,6 +887,8 @@ static void bc_history_edit_wordEnd(BcHistory *h) {
size_t len = BC_HIST_BUF_LEN(h); size_t len = BC_HIST_BUF_LEN(h);
BC_SIG_ASSERT_LOCKED;
// Don't overflow. // Don't overflow.
if (!len || h->pos >= len) return; if (!len || h->pos >= len) return;
@ -884,6 +907,8 @@ static void bc_history_edit_wordStart(BcHistory *h) {
size_t len = BC_HIST_BUF_LEN(h); size_t len = BC_HIST_BUF_LEN(h);
BC_SIG_ASSERT_LOCKED;
// Stop with no data. // Stop with no data.
if (!len) return; if (!len) return;
@ -900,6 +925,8 @@ static void bc_history_edit_wordStart(BcHistory *h) {
*/ */
static void bc_history_edit_home(BcHistory *h) { static void bc_history_edit_home(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
// Stop at the beginning. // Stop at the beginning.
if (!h->pos) return; if (!h->pos) return;
@ -914,6 +941,8 @@ static void bc_history_edit_home(BcHistory *h) {
*/ */
static void bc_history_edit_end(BcHistory *h) { static void bc_history_edit_end(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
// Stop at the end of the line. // Stop at the end of the line.
if (h->pos == BC_HIST_BUF_LEN(h)) return; if (h->pos == BC_HIST_BUF_LEN(h)) return;
@ -932,11 +961,11 @@ static void bc_history_edit_next(BcHistory *h, bool dir) {
const char *dup, *str; const char *dup, *str;
BC_SIG_ASSERT_LOCKED;
// Stop if there is no history. // Stop if there is no history.
if (h->history.len <= 1) return; if (h->history.len <= 1) return;
BC_SIG_LOCK;
// Duplicate the buffer. // Duplicate the buffer.
if (h->buf.v[0]) dup = bc_vm_strdup(h->buf.v); if (h->buf.v[0]) dup = bc_vm_strdup(h->buf.v);
else dup = ""; else dup = "";
@ -944,8 +973,6 @@ static void bc_history_edit_next(BcHistory *h, bool dir) {
// Update the current history entry before overwriting it with the next one. // Update the current history entry before overwriting it with the next one.
bc_vec_replaceAt(&h->history, h->history.len - 1 - h->idx, &dup); bc_vec_replaceAt(&h->history, h->history.len - 1 - h->idx, &dup);
BC_SIG_UNLOCK;
// Show the new entry. // Show the new entry.
h->idx += (dir == BC_HIST_PREV ? 1 : SIZE_MAX); h->idx += (dir == BC_HIST_PREV ? 1 : SIZE_MAX);
@ -980,6 +1007,8 @@ static void bc_history_edit_delete(BcHistory *h) {
size_t chlen, len = BC_HIST_BUF_LEN(h); size_t chlen, len = BC_HIST_BUF_LEN(h);
BC_SIG_ASSERT_LOCKED;
// If there is no character, skip. // If there is no character, skip.
if (!len || h->pos >= len) return; if (!len || h->pos >= len) return;
@ -1005,6 +1034,8 @@ static void bc_history_edit_backspace(BcHistory *h) {
size_t chlen, len = BC_HIST_BUF_LEN(h); size_t chlen, len = BC_HIST_BUF_LEN(h);
BC_SIG_ASSERT_LOCKED;
// If there are no characters, skip. // If there are no characters, skip.
if (!h->pos || !len) return; if (!h->pos || !len) return;
@ -1031,6 +1062,8 @@ static void bc_history_edit_deletePrevWord(BcHistory *h) {
size_t diff, old_pos = h->pos; size_t diff, old_pos = h->pos;
BC_SIG_ASSERT_LOCKED;
// If at the beginning of the line, skip. // If at the beginning of the line, skip.
if (!old_pos) return; if (!old_pos) return;
@ -1059,6 +1092,8 @@ static void bc_history_edit_deleteNextWord(BcHistory *h) {
size_t next_end = h->pos, len = BC_HIST_BUF_LEN(h); size_t next_end = h->pos, len = BC_HIST_BUF_LEN(h);
BC_SIG_ASSERT_LOCKED;
// If at the end of the line, skip. // If at the end of the line, skip.
if (next_end == len) return; if (next_end == len) return;
@ -1084,6 +1119,8 @@ static void bc_history_swap(BcHistory *h) {
size_t pcl, ncl; size_t pcl, ncl;
char auxb[5]; char auxb[5];
BC_SIG_ASSERT_LOCKED;
// Get the length of the previous and next characters. // Get the length of the previous and next characters.
pcl = bc_history_prevLen(h->buf.v, h->pos); pcl = bc_history_prevLen(h->buf.v, h->pos);
ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL); ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL);
@ -1126,6 +1163,8 @@ static void bc_history_escape(BcHistory *h) {
char c, seq[3]; char c, seq[3];
BC_SIG_ASSERT_LOCKED;
// Read a character into seq. // Read a character into seq.
if (BC_ERR(BC_HIST_READ(seq, 1))) return; if (BC_ERR(BC_HIST_READ(seq, 1))) return;
@ -1274,6 +1313,8 @@ static void bc_history_escape(BcHistory *h) {
*/ */
static void bc_history_add(BcHistory *h, char *line) { static void bc_history_add(BcHistory *h, char *line) {
BC_SIG_ASSERT_LOCKED;
// If there is something already there... // If there is something already there...
if (h->history.len) { if (h->history.len) {
@ -1282,13 +1323,7 @@ static void bc_history_add(BcHistory *h, char *line) {
// Check for, and discard, duplicates. // Check for, and discard, duplicates.
if (!strcmp(s, line)) { if (!strcmp(s, line)) {
BC_SIG_LOCK;
free(line); free(line);
BC_SIG_UNLOCK;
return; return;
} }
} }
@ -1303,6 +1338,8 @@ static void bc_history_add(BcHistory *h, char *line) {
*/ */
static void bc_history_add_empty(BcHistory *h) { static void bc_history_add_empty(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
const char *line = ""; const char *line = "";
// If there is something already there... // If there is something already there...
@ -1324,6 +1361,8 @@ static void bc_history_add_empty(BcHistory *h) {
*/ */
static void bc_history_reset(BcHistory *h) { static void bc_history_reset(BcHistory *h) {
BC_SIG_ASSERT_LOCKED;
h->oldcolpos = h->pos = h->idx = 0; h->oldcolpos = h->pos = h->idx = 0;
h->cols = bc_history_columns(); h->cols = bc_history_columns();
@ -1345,6 +1384,8 @@ static void bc_history_printCtrl(BcHistory *h, unsigned int c) {
char str[3] = "^A"; char str[3] = "^A";
const char newline[2] = "\n"; const char newline[2] = "\n";
BC_SIG_ASSERT_LOCKED;
// Set the correct character. // Set the correct character.
str[1] = (char) (c + 'A' - BC_ACTION_CTRL_A); str[1] = (char) (c + 'A' - BC_ACTION_CTRL_A);
@ -1378,6 +1419,8 @@ static void bc_history_printCtrl(BcHistory *h, unsigned int c) {
*/ */
static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
BC_SIG_LOCK;
bc_history_reset(h); bc_history_reset(h);
// Don't write the saved output the first time. This is because it has // Don't write the saved output the first time. This is because it has
@ -1404,10 +1447,14 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
unsigned int c = 0; unsigned int c = 0;
size_t nread = 0; size_t nread = 0;
BC_SIG_UNLOCK;
// Read a code. // Read a code.
s = bc_history_readCode(cbuf, sizeof(cbuf), &c, &nread); s = bc_history_readCode(cbuf, sizeof(cbuf), &c, &nread);
if (BC_ERR(s)) return s; if (BC_ERR(s)) return s;
BC_SIG_LOCK;
switch (c) { switch (c) {
case BC_ACTION_LINE_FEED: case BC_ACTION_LINE_FEED:
@ -1415,6 +1462,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
{ {
// Return the line. // Return the line.
bc_vec_pop(&h->history); bc_vec_pop(&h->history);
BC_SIG_UNLOCK;
return s; return s;
} }
@ -1434,6 +1482,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
// Quit if the user wants it. // Quit if the user wants it.
if (!BC_SIGINT) { if (!BC_SIGINT) {
vm.status = BC_STATUS_QUIT; vm.status = BC_STATUS_QUIT;
BC_SIG_UNLOCK;
BC_JMP; BC_JMP;
} }
@ -1460,6 +1509,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
case BC_ACTION_CTRL_D: case BC_ACTION_CTRL_D:
{ {
bc_history_printCtrl(h, c); bc_history_printCtrl(h, c);
BC_SIG_UNLOCK;
return BC_STATUS_EOF; return BC_STATUS_EOF;
} }
#endif // _WIN32 #endif // _WIN32
@ -1565,6 +1615,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
bc_history_raise(h, SIGQUIT); bc_history_raise(h, SIGQUIT);
#else // _WIN32 #else // _WIN32
vm.status = BC_STATUS_QUIT; vm.status = BC_STATUS_QUIT;
BC_SIG_UNLOCK;
BC_JMP; BC_JMP;
#endif // _WIN32 #endif // _WIN32
} }
@ -1575,6 +1626,8 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
} }
} }
BC_SIG_UNLOCK;
return BC_STATUS_SUCCESS; return BC_STATUS_SUCCESS;
} }
@ -1611,22 +1664,22 @@ BcStatus bc_history_line(BcHistory *h, BcVec *vec, const char *prompt) {
bc_file_write(&vm.fout, bc_flush_none, "\n", 1); bc_file_write(&vm.fout, bc_flush_none, "\n", 1);
bc_file_flush(&vm.fout, bc_flush_none); bc_file_flush(&vm.fout, bc_flush_none);
BC_SIG_LOCK;
// If we actually have data... // If we actually have data...
if (h->buf.v[0]) { if (h->buf.v[0]) {
BC_SIG_LOCK;
// Duplicate it. // Duplicate it.
line = bc_vm_strdup(h->buf.v); line = bc_vm_strdup(h->buf.v);
BC_SIG_UNLOCK;
// Store it. // Store it.
bc_history_add(h, line); bc_history_add(h, line);
} }
// Add an empty string. // Add an empty string.
else bc_history_add_empty(h); else bc_history_add_empty(h);
BC_SIG_UNLOCK;
// Concatenate the line to the return vector. // Concatenate the line to the return vector.
bc_vec_concat(vec, h->buf.v); bc_vec_concat(vec, h->buf.v);
bc_vec_concat(vec, "\n"); bc_vec_concat(vec, "\n");

View File

@ -258,6 +258,8 @@ void bc_lex_file(BcLex *l, const char *file) {
void bc_lex_next(BcLex *l) { void bc_lex_next(BcLex *l) {
BC_SIG_ASSERT_LOCKED;
assert(l != NULL); assert(l != NULL);
l->last = l->t; l->last = l->t;
@ -294,7 +296,15 @@ static void bc_lex_fixText(BcLex *l, const char *text, size_t len) {
bool bc_lex_readLine(BcLex *l) { bool bc_lex_readLine(BcLex *l) {
bool good = bc_vm_readLine(false); bool good;
// These are reversed because they should be already locked, but
// bc_vm_readLine() needs them to be unlocked.
BC_SIG_UNLOCK;
good = bc_vm_readLine(false);
BC_SIG_LOCK;
bc_lex_fixText(l, vm.buffer.v, vm.buffer.len - 1); bc_lex_fixText(l, vm.buffer.v, vm.buffer.len - 1);
@ -302,10 +312,15 @@ bool bc_lex_readLine(BcLex *l) {
} }
void bc_lex_text(BcLex *l, const char *text, bool is_stdin) { void bc_lex_text(BcLex *l, const char *text, bool is_stdin) {
BC_SIG_ASSERT_LOCKED;
assert(l != NULL && text != NULL); assert(l != NULL && text != NULL);
bc_lex_fixText(l, text, strlen(text)); bc_lex_fixText(l, text, strlen(text));
l->i = 0; l->i = 0;
l->t = l->last = BC_LEX_INVALID; l->t = l->last = BC_LEX_INVALID;
l->is_stdin = is_stdin; l->is_stdin = is_stdin;
bc_lex_next(l); bc_lex_next(l);
} }

View File

@ -77,9 +77,14 @@ BclError bcl_init(void) {
BclError e = BCL_ERROR_NONE; BclError e = BCL_ERROR_NONE;
BC_SIG_LOCK;
vm.refs += 1; vm.refs += 1;
if (vm.refs > 1) return e; if (vm.refs > 1) {
BC_SIG_UNLOCK;
return e;
}
// Setting these to NULL ensures that if an error occurs, we only free what // Setting these to NULL ensures that if an error occurs, we only free what
// is necessary. // is necessary.
@ -89,8 +94,6 @@ BclError bcl_init(void) {
vm.abrt = false; vm.abrt = false;
BC_SIG_LOCK;
// The jmp_bufs always has to be initialized first. // The jmp_bufs always has to be initialized first.
bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE); bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
@ -146,11 +149,14 @@ void bcl_free(void) {
size_t i; size_t i;
BC_SIG_LOCK;
vm.refs -= 1; vm.refs -= 1;
if (vm.refs) return; if (vm.refs) {
BC_SIG_UNLOCK;
BC_SIG_LOCK; return;
}
bc_rand_free(&vm.rng); bc_rand_free(&vm.rng);
bc_vec_free(&vm.out); bc_vec_free(&vm.out);

View File

@ -235,7 +235,7 @@ static bool bc_opt_longoptsMatch(const char *name, const char *option) {
// Can never match a NULL name. // Can never match a NULL name.
if (name == NULL) return false; if (name == NULL) return false;
// Loop through // Loop through.
for (; *a && *n && *a != '='; ++a, ++n) { for (; *a && *n && *a != '='; ++a, ++n) {
if (*a != *n) return false; if (*a != *n) return false;
} }

View File

@ -70,15 +70,11 @@ void bc_parse_addString(BcParse *p) {
size_t idx; size_t idx;
BC_SIG_LOCK;
idx = bc_program_addString(p->prog, p->l.str.v, p->fidx); idx = bc_program_addString(p->prog, p->l.str.v, p->fidx);
// Push the string info. // Push the string info.
bc_parse_update(p, BC_INST_STR, p->fidx); bc_parse_update(p, BC_INST_STR, p->fidx);
bc_parse_pushIndex(p, idx); bc_parse_pushIndex(p, idx);
BC_SIG_UNLOCK;
} }
static void bc_parse_addNum(BcParse *p, const char *string) { static void bc_parse_addNum(BcParse *p, const char *string) {
@ -88,6 +84,8 @@ static void bc_parse_addNum(BcParse *p, const char *string) {
BcConst *c; BcConst *c;
BcVec *slabs; BcVec *slabs;
BC_SIG_ASSERT_LOCKED;
// Special case 0. // Special case 0.
if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) { if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) {
bc_parse_push(p, BC_INST_ZERO); bc_parse_push(p, BC_INST_ZERO);
@ -103,8 +101,6 @@ static void bc_parse_addNum(BcParse *p, const char *string) {
// Get the index. // Get the index.
idx = consts->len; idx = consts->len;
BC_SIG_LOCK;
// Get the right slab. // Get the right slab.
slabs = p->fidx == BC_PROG_MAIN || p->fidx == BC_PROG_READ ? slabs = p->fidx == BC_PROG_MAIN || p->fidx == BC_PROG_READ ?
&vm.main_const_slab : &vm.other_slabs; &vm.main_const_slab : &vm.other_slabs;
@ -120,8 +116,6 @@ static void bc_parse_addNum(BcParse *p, const char *string) {
bc_num_clear(&c->num); bc_num_clear(&c->num);
bc_parse_update(p, BC_INST_NUM, idx); bc_parse_update(p, BC_INST_NUM, idx);
BC_SIG_UNLOCK;
} }
void bc_parse_number(BcParse *p) { void bc_parse_number(BcParse *p) {
@ -158,9 +152,13 @@ void bc_parse_number(BcParse *p) {
void bc_parse_text(BcParse *p, const char *text, bool is_stdin) { void bc_parse_text(BcParse *p, const char *text, bool is_stdin) {
BC_SIG_LOCK;
// Make sure the pointer isn't invalidated. // Make sure the pointer isn't invalidated.
p->func = bc_vec_item(&p->prog->fns, p->fidx); p->func = bc_vec_item(&p->prog->fns, p->fidx);
bc_lex_text(&p->l, text, is_stdin); bc_lex_text(&p->l, text, is_stdin);
BC_SIG_UNLOCK;
} }
void bc_parse_reset(BcParse *p) { void bc_parse_reset(BcParse *p) {

View File

@ -55,6 +55,7 @@
* @param f The new function. * @param f The new function.
*/ */
static inline void bc_program_setVecs(BcProgram *p, BcFunc *f) { static inline void bc_program_setVecs(BcProgram *p, BcFunc *f) {
BC_SIG_ASSERT_LOCKED;
p->consts = &f->consts; p->consts = &f->consts;
p->strs = &f->strs; p->strs = &f->strs;
} }
@ -152,6 +153,8 @@ static void bc_program_popGlobals(BcProgram *p, bool reset) {
size_t i; size_t i;
BC_SIG_ASSERT_LOCKED;
for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) { for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) {
BcVec *v = p->globals_v + i; BcVec *v = p->globals_v + i;
bc_vec_npop(v, reset ? v->len - 1 : 1); bc_vec_npop(v, reset ? v->len - 1 : 1);
@ -238,12 +241,12 @@ size_t bc_program_search(BcProgram *p, const char *id, bool var) {
BcVec *v, *map; BcVec *v, *map;
size_t i; size_t i;
BC_SIG_ASSERT_LOCKED;
// Grab the right vector and map. // Grab the right vector and map.
v = var ? &p->vars : &p->arrs; v = var ? &p->vars : &p->arrs;
map = var ? &p->var_map : &p->arr_map; map = var ? &p->var_map : &p->arr_map;
BC_SIG_LOCK;
// We do an insert because the variable might not exist yet. This is because // We do an insert because the variable might not exist yet. This is because
// the parser calls this function. If the insert succeeds, we create a stack // the parser calls this function. If the insert succeeds, we create a stack
// for the variable/array. But regardless, bc_map_insert() gives us the // for the variable/array. But regardless, bc_map_insert() gives us the
@ -253,8 +256,6 @@ size_t bc_program_search(BcProgram *p, const char *id, bool var) {
bc_array_init(temp, var); bc_array_init(temp, var);
} }
BC_SIG_UNLOCK;
return ((BcId*) bc_vec_item(map, i))->idx; return ((BcId*) bc_vec_item(map, i))->idx;
} }
@ -711,7 +712,9 @@ static void bc_program_read(BcProgram *p) {
// Parse *one* expression. // Parse *one* expression.
bc_parse_text(&vm.read_prs, vm.read_buf.v, false); bc_parse_text(&vm.read_prs, vm.read_buf.v, false);
BC_SIG_LOCK;
vm.expr(&vm.read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL); vm.expr(&vm.read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
BC_SIG_UNLOCK;
// We *must* have a valid expression. A semicolon cannot end an expression, // We *must* have a valid expression. A semicolon cannot end an expression,
// although EOF can. // although EOF can.
@ -736,6 +739,9 @@ static void bc_program_read(BcProgram *p) {
// We want a return instruction to simplify things. // We want a return instruction to simplify things.
bc_vec_pushByte(&f->code, vm.read_ret); bc_vec_pushByte(&f->code, vm.read_ret);
// This lock is here to make sure dc's tail calls are the same length.
BC_SIG_LOCK;
bc_vec_push(&p->stack, &ip); bc_vec_push(&p->stack, &ip);
#if DC_ENABLED #if DC_ENABLED
@ -784,6 +790,9 @@ static void bc_program_printChars(const char *str) {
const char *nl; const char *nl;
size_t len = vm.nchars + strlen(str); size_t len = vm.nchars + strlen(str);
sig_atomic_t lock;
BC_SIG_TRYLOCK(lock);
bc_file_puts(&vm.fout, bc_flush_save, str); bc_file_puts(&vm.fout, bc_flush_save, str);
@ -794,6 +803,8 @@ static void bc_program_printChars(const char *str) {
if (nl != NULL) len = strlen(nl + 1); if (nl != NULL) len = strlen(nl + 1);
vm.nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len; vm.nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
BC_SIG_TRYUNLOCK(lock);
} }
/** /**
@ -830,7 +841,11 @@ static void bc_program_printString(const char *restrict str) {
if (ptr != NULL) { if (ptr != NULL) {
// We need to specially handle a newline. // We need to specially handle a newline.
if (c == 'n') vm.nchars = UINT16_MAX; if (c == 'n') {
BC_SIG_LOCK;
vm.nchars = UINT16_MAX;
BC_SIG_UNLOCK;
}
// Grab the actual character. // Grab the actual character.
c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)]; c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)];
@ -1770,6 +1785,8 @@ static void bc_program_return(BcProgram *p, uchar inst) {
bc_vec_pop(v); bc_vec_pop(v);
} }
BC_SIG_LOCK;
// When we retire, pop all of the unused results. // When we retire, pop all of the unused results.
bc_program_retire(p, 1, nresults); bc_program_retire(p, 1, nresults);
@ -1778,6 +1795,8 @@ static void bc_program_return(BcProgram *p, uchar inst) {
// Pop the stack. This is what causes the function to actually "return." // Pop the stack. This is what causes the function to actually "return."
bc_vec_pop(&p->stack); bc_vec_pop(&p->stack);
BC_SIG_UNLOCK;
} }
#endif // BC_ENABLED #endif // BC_ENABLED
@ -2184,8 +2203,10 @@ static void bc_program_nquit(BcProgram *p, uchar inst) {
// because these are for tail calls. That means that any executions that // because these are for tail calls. That means that any executions that
// we would not have quit in that position on the stack would have quit // we would not have quit in that position on the stack would have quit
// anyway. // anyway.
BC_SIG_LOCK;
bc_vec_npop(&p->stack, i); bc_vec_npop(&p->stack, i);
bc_vec_npop(&p->tail_calls, i); bc_vec_npop(&p->tail_calls, i);
BC_SIG_UNLOCK;
} }
} }
@ -2311,9 +2332,9 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
// Parse. // Parse.
bc_parse_text(&vm.read_prs, str, false); bc_parse_text(&vm.read_prs, str, false);
vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
BC_SIG_LOCK; BC_SIG_LOCK;
vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
BC_UNSETJMP; BC_UNSETJMP;
@ -2329,6 +2350,8 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
ip.len = p->results.len; ip.len = p->results.len;
ip.func = fidx; ip.func = fidx;
BC_SIG_LOCK;
// Pop the operand. // Pop the operand.
bc_vec_pop(&p->results); bc_vec_pop(&p->results);
@ -2352,6 +2375,8 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
// Push the new function onto the execution stack and return. // Push the new function onto the execution stack and return.
bc_vec_push(&p->stack, &ip); bc_vec_push(&p->stack, &ip);
BC_SIG_UNLOCK;
return; return;
err: err:
@ -2678,7 +2703,9 @@ void bc_program_exec(BcProgram *p) {
code = func->code.v; code = func->code.v;
// Ensure the pointers are correct. // Ensure the pointers are correct.
BC_SIG_LOCK;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
#if !BC_HAS_COMPUTED_GOTO #if !BC_HAS_COMPUTED_GOTO
@ -2759,10 +2786,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -2792,10 +2821,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -2824,10 +2855,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -2909,10 +2942,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -3086,10 +3121,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -3103,10 +3140,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }
@ -3179,10 +3218,12 @@ void bc_program_exec(BcProgram *p) {
// Because we changed the execution stack and where we are // Because we changed the execution stack and where we are
// executing, we have to update all of this. // executing, we have to update all of this.
BC_SIG_LOCK;
ip = bc_vec_top(&p->stack); ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func); func = bc_vec_item(&p->fns, ip->func);
code = func->code.v; code = func->code.v;
bc_program_setVecs(p, func); bc_program_setVecs(p, func);
BC_SIG_UNLOCK;
BC_PROG_JUMP(inst, code, ip); BC_PROG_JUMP(inst, code, ip);
} }

View File

@ -461,16 +461,21 @@ BcRand bc_rand_int(BcRNG *r) {
// Get the actual PRNG. // Get the actual PRNG.
BcRNGData *rng = bc_vec_top(&r->v); BcRNGData *rng = bc_vec_top(&r->v);
BcRand res;
// Make sure the PRNG is seeded. // Make sure the PRNG is seeded.
if (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_srand(rng); if (BC_ERR(BC_RAND_ZERO(rng))) bc_rand_srand(rng);
// This is the important part of the PRNG. This is the stuff from PCG, BC_SIG_LOCK;
// including the return statement.
// This is the important part of the PRNG. This is the stuff from PCG.
bc_rand_step(rng); bc_rand_step(rng);
bc_rand_propagate(r, rng); bc_rand_propagate(r, rng);
res = bc_rand_output(rng);
return bc_rand_output(rng); BC_SIG_UNLOCK;
return res;
} }
BcRand bc_rand_bounded(BcRNG *r, BcRand bound) { BcRand bc_rand_bounded(BcRNG *r, BcRand bound) {

View File

@ -196,12 +196,16 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
return BC_STATUS_EOF; return BC_STATUS_EOF;
} }
BC_SIG_LOCK;
// Add to the buffer. // Add to the buffer.
vm.buf_len += (size_t) r; vm.buf_len += (size_t) r;
vm.buf[vm.buf_len] = '\0'; vm.buf[vm.buf_len] = '\0';
// Read from the buffer. // Read from the buffer.
done = bc_read_buf(vec, vm.buf, &vm.buf_len); done = bc_read_buf(vec, vm.buf, &vm.buf_len);
BC_SIG_UNLOCK;
} }
// Terminate the string. // Terminate the string.

View File

@ -186,9 +186,11 @@ void bc_vm_info(const char* const help) {
"disabled"; "disabled";
const char* const prompt = BC_DEFAULT_PROMPT ? "enabled" : const char* const prompt = BC_DEFAULT_PROMPT ? "enabled" :
"disabled"; "disabled";
const char* const expr = BC_DEFAULT_EXPR_EXIT ? "to exit" :
"to not exit";
bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION, bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION,
BC_BUILD_TYPE, banner, sigint, tty, prompt); BC_BUILD_TYPE, banner, sigint, tty, prompt, expr);
} }
#endif // BC_ENABLED #endif // BC_ENABLED
@ -201,9 +203,11 @@ void bc_vm_info(const char* const help) {
"disabled"; "disabled";
const char* const prompt = DC_DEFAULT_PROMPT ? "enabled" : const char* const prompt = DC_DEFAULT_PROMPT ? "enabled" :
"disabled"; "disabled";
const char* const expr = DC_DEFAULT_EXPR_EXIT ? "to exit" :
"to not exit";
bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION, bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION,
BC_BUILD_TYPE, sigint, tty, prompt); BC_BUILD_TYPE, sigint, tty, prompt, expr);
} }
#endif // DC_ENABLED #endif // DC_ENABLED
} }
@ -552,6 +556,8 @@ void bc_vm_shutdown(void) {
void bc_vm_addTemp(BcDig *num) { void bc_vm_addTemp(BcDig *num) {
BC_SIG_ASSERT_LOCKED;
// If we don't have room, just free. // If we don't have room, just free.
if (vm.temps_len == BC_VM_MAX_TEMPS) free(num); if (vm.temps_len == BC_VM_MAX_TEMPS) free(num);
else { else {
@ -563,8 +569,13 @@ void bc_vm_addTemp(BcDig *num) {
} }
BcDig* bc_vm_takeTemp(void) { BcDig* bc_vm_takeTemp(void) {
BC_SIG_ASSERT_LOCKED;
if (!vm.temps_len) return NULL; if (!vm.temps_len) return NULL;
vm.temps_len -= 1; vm.temps_len -= 1;
return temps_buf[vm.temps_len]; return temps_buf[vm.temps_len];
} }
@ -660,8 +671,9 @@ char* bc_vm_strdup(const char *str) {
void bc_vm_printf(const char *fmt, ...) { void bc_vm_printf(const char *fmt, ...) {
va_list args; va_list args;
sig_atomic_t lock;
BC_SIG_LOCK; BC_SIG_TRYLOCK(lock);
va_start(args, fmt); va_start(args, fmt);
bc_file_vprintf(&vm.fout, fmt, args); bc_file_vprintf(&vm.fout, fmt, args);
@ -669,7 +681,7 @@ void bc_vm_printf(const char *fmt, ...) {
vm.nchars = 0; vm.nchars = 0;
BC_SIG_UNLOCK; BC_SIG_TRYUNLOCK(lock);
} }
#endif // !BC_ENABLE_LIBRARY #endif // !BC_ENABLE_LIBRARY
@ -745,6 +757,8 @@ static void bc_vm_clean(void) {
BcInstPtr *ip = bc_vec_item(&vm.prog.stack, 0); BcInstPtr *ip = bc_vec_item(&vm.prog.stack, 0);
bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig); bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig);
BC_SIG_ASSERT_LOCKED;
// If all is good, go ahead and reset. // If all is good, go ahead and reset.
if (good) bc_program_reset(&vm.prog); if (good) bc_program_reset(&vm.prog);
@ -816,6 +830,8 @@ static void bc_vm_process(const char *text, bool is_stdin) {
do { do {
BC_SIG_LOCK;
#if BC_ENABLED #if BC_ENABLED
// If the first token is the keyword define, then we need to do this // If the first token is the keyword define, then we need to do this
// specially because bc thinks it may not be able to parse. // specially because bc thinks it may not be able to parse.
@ -825,6 +841,8 @@ static void bc_vm_process(const char *text, bool is_stdin) {
// Parse it all. // Parse it all.
while (BC_PARSE_CAN_PARSE(vm.prs)) vm.parse(&vm.prs); while (BC_PARSE_CAN_PARSE(vm.prs)) vm.parse(&vm.prs);
BC_SIG_UNLOCK;
// Execute if possible. // Execute if possible.
if(BC_IS_DC || !BC_PARSE_NO_EXEC(&vm.prs)) bc_program_exec(&vm.prog); if(BC_IS_DC || !BC_PARSE_NO_EXEC(&vm.prs)) bc_program_exec(&vm.prog);
@ -901,6 +919,8 @@ bool bc_vm_readLine(bool clear) {
BcStatus s; BcStatus s;
bool good; bool good;
BC_SIG_ASSERT_NOT_LOCKED;
// Clear the buffer if desired. // Clear the buffer if desired.
if (clear) bc_vec_empty(&vm.buffer); if (clear) bc_vec_empty(&vm.buffer);
@ -969,7 +989,11 @@ static void bc_vm_stdin(void) {
bc_vm_process(vm.buffer.v, true); bc_vm_process(vm.buffer.v, true);
if (vm.eof) break; if (vm.eof) break;
else bc_vm_clean(); else {
BC_SIG_LOCK;
bc_vm_clean();
BC_SIG_UNLOCK;
}
} }
#if BC_ENABLED #if BC_ENABLED
@ -1022,7 +1046,11 @@ static void bc_vm_load(const char *name, const char *text) {
bc_lex_file(&vm.prs.l, name); bc_lex_file(&vm.prs.l, name);
bc_parse_text(&vm.prs, text, false); bc_parse_text(&vm.prs, text, false);
BC_SIG_LOCK;
while (vm.prs.l.t != BC_LEX_EOF) vm.parse(&vm.prs); while (vm.prs.l.t != BC_LEX_EOF) vm.parse(&vm.prs);
BC_SIG_UNLOCK;
} }
#endif // BC_ENABLED #endif // BC_ENABLED
@ -1172,7 +1200,7 @@ static void bc_vm_exec(void) {
BC_SIG_UNLOCK; BC_SIG_UNLOCK;
// Sometimes, executing expressions means we need to quit. // Sometimes, executing expressions means we need to quit.
if (!vm.no_exprs && vm.exit_exprs) return; if (!vm.no_exprs && vm.exit_exprs && BC_EXPR_EXIT) return;
} }
// Process files. // Process files.
@ -1194,9 +1222,7 @@ static void bc_vm_exec(void) {
// We need to keep tty if history is enabled, and we need to keep rpath for // We need to keep tty if history is enabled, and we need to keep rpath for
// the times when we read from /dev/urandom. // the times when we read from /dev/urandom.
if (BC_TTY && !vm.history.badTerm) { if (BC_TTY && !vm.history.badTerm) bc_pledge(bc_pledge_end_history, NULL);
bc_pledge(bc_pledge_end_history, NULL);
}
else else
#endif // BC_ENABLE_HISTORY #endif // BC_ENABLE_HISTORY
{ {
@ -1233,6 +1259,8 @@ void bc_vm_boot(int argc, char *argv[]) {
bool tty; bool tty;
const char* const env_len = BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH"; const char* const env_len = BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH";
const char* const env_args = BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS"; const char* const env_args = BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS";
const char* const env_exit = BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT";
int env_exit_def = BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT;
// We need to know which of stdin, stdout, and stderr are tty's. // We need to know which of stdin, stdout, and stderr are tty's.
ttyin = isatty(STDIN_FILENO); ttyin = isatty(STDIN_FILENO);
@ -1269,6 +1297,8 @@ void bc_vm_boot(int argc, char *argv[]) {
// Set the line length by environment variable. // Set the line length by environment variable.
vm.line_len = (uint16_t) bc_vm_envLen(env_len); vm.line_len = (uint16_t) bc_vm_envLen(env_len);
bc_vm_setenvFlag(env_exit, env_exit_def, BC_FLAG_EXPR_EXIT);
// Clear the files and expressions vectors, just in case. This marks them as // Clear the files and expressions vectors, just in case. This marks them as
// *not* allocated. // *not* allocated.
bc_vec_clear(&vm.files); bc_vec_clear(&vm.files);
@ -1289,26 +1319,22 @@ void bc_vm_boot(int argc, char *argv[]) {
bc_program_init(&vm.prog); bc_program_init(&vm.prog);
bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN); bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN);
#if BC_ENABLED
// bc checks this environment variable to see if it should run in standard
// mode.
if (BC_IS_BC) {
char* var = bc_vm_getenv("POSIXLY_CORRECT");
vm.flags |= BC_FLAG_S * (var != NULL);
bc_vm_getenvFree(var);
}
#endif // BC_ENABLED
// Set defaults. // Set defaults.
vm.flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0; vm.flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0;
vm.flags |= BC_I ? BC_FLAG_Q : 0; vm.flags |= BC_I ? BC_FLAG_Q : 0;
#if BC_ENABLED #if BC_ENABLED
if (BC_IS_BC && BC_I) { if (BC_IS_BC) {
// bc checks this environment variable to see if it should run in
// standard mode.
char* var = bc_vm_getenv("POSIXLY_CORRECT");
vm.flags |= BC_FLAG_S * (var != NULL);
bc_vm_getenvFree(var);
// Set whether we print the banner or not. // Set whether we print the banner or not.
bc_vm_setenvFlag("BC_BANNER", BC_DEFAULT_BANNER, BC_FLAG_Q); if (BC_I) bc_vm_setenvFlag("BC_BANNER", BC_DEFAULT_BANNER, BC_FLAG_Q);
} }
#endif // BC_ENABLED #endif // BC_ENABLED
@ -1349,9 +1375,7 @@ void bc_vm_boot(int argc, char *argv[]) {
#if BC_ENABLED #if BC_ENABLED
// Disable global stacks in POSIX mode. // Disable global stacks in POSIX mode.
if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G); if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G);
#endif // BC_ENABLED
#if BC_ENABLED
// Print the banner if allowed. We have to be in bc, in interactive mode, // Print the banner if allowed. We have to be in bc, in interactive mode,
// and not be quieted by command-line option or environment variable. // and not be quieted by command-line option or environment variable.
if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q)) { if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q)) {

View File

@ -43,6 +43,7 @@ misc4
misc5 misc5
misc6 misc6
misc7 misc7
misc8
void void
rand rand
recursive_arrays recursive_arrays

View File

@ -0,0 +1,8 @@
define a(){
return 5
}define b(){
return 6
}
24
a()
b()

View File

@ -0,0 +1,3 @@
24
5
6

View File

@ -7,6 +7,7 @@ halt
define x(e) { return 0; } define x(e) { return 0; }
define x(e) { return 4*(e+e); } define x(e) { return 4*(e+e); }
define x(e) { return (e+e)*4; } define x(e) { return (e+e)*4; }
define a() { return (5); };define b() { return (6); }
limits limits
. .
if (q!=0) { x=3; } else { x=4; } if (q!=0) { x=3; } else { x=4; }

View File

@ -50,7 +50,6 @@ else
bc="$testdir/../../bin/bc" bc="$testdir/../../bin/bc"
fi fi
#
out1="$outputdir/bc_outputs/bc_timeconst.txt" out1="$outputdir/bc_outputs/bc_timeconst.txt"
out2="$outputdir/bc_outputs/bc_timeconst_results.txt" out2="$outputdir/bc_outputs/bc_timeconst_results.txt"

View File

@ -253,7 +253,7 @@ def test_sigint_sigquit(exe, args, env):
send(child, "\t") send(child, "\t")
expect(child, " ") expect(child, " ")
send(child, "\x03") send(child, "\x03")
send(child, "\x1c") # send(child, "\x1c")
wait(child) wait(child)
except pexpect.TIMEOUT: except pexpect.TIMEOUT:
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
@ -1044,6 +1044,7 @@ def test_dc3(exe, args, env):
test_dc_utf8_1, test_dc_utf8_1,
test_dc_utf8_2, test_dc_utf8_2,
test_dc_utf8_3, test_dc_utf8_3,
test_dc_utf8_4,
test_sigint_sigquit, test_sigint_sigquit,
test_eof, test_eof,
test_sigint, test_sigint,

View File

@ -92,7 +92,7 @@ for i in $(seq "$st" "$idx"); do
printf 'Running %s history test %d...' "$d" "$i" printf 'Running %s history test %d...' "$d" "$i"
for j in $(seq 1 3); do for j in $(seq 1 5); do
"$py" "$testdir/history.py" "$d" "$i" "$exe" "$@" "$py" "$testdir/history.py" "$d" "$i" "$exe" "$@"
err="$?" err="$?"

View File

@ -102,7 +102,7 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
@ -123,7 +123,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
@ -144,7 +144,7 @@
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
@ -164,7 +164,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>BC_ENABLED=1;DC_ENABLED=1;BC_ENABLE_EXTRA_MATH=1;BC_ENABLE_HISTORY=0;BC_ENABLE_NLS=0;BC_DEBUG_CODE=0;BC_ENABLE_LIBRARY=0;BUILD_TYPE=HN;BC_DEFAULT_BANNER=1;BC_DEFAULT_SIGINT_RESET=0;DC_DEFAULT_SIGINT_RESET=0;BC_DEFAULT_TTY_MODE=1;DC_DEFAULT_TTY_MODE=1;BC_DEFAULT_PROMPT=1;DC_DEFAULT_PROMPT=1;BC_DEFAULT_EXPR_EXIT=1;DC_DEFAULT_EXPR_EXIT=1;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>