diff options
author | Stefan Eßer <se@FreeBSD.org> | 2021-11-30 17:26:22 +0000 |
---|---|---|
committer | Stefan Eßer <se@FreeBSD.org> | 2021-11-30 17:26:22 +0000 |
commit | 23aff1240891b4ba4bb000345824ca0b87b9b3e3 (patch) | |
tree | 31dbbc9a32d24856e9514e788e8b31b7e965a2bf | |
parent | 6f49f5cdde1c62c4e5a743e895f3afe592b5c0e5 (diff) |
vendor/bc: import release 5.2.0vendor/bc/5.2.0
This version is imported only for documentary purposes since it does
not contain any changes that are relevant for the FreeBSD base system.
64 files changed, 1036 insertions, 258 deletions
diff --git a/Makefile.in b/Makefile.in index 3d6780d6ac95..b9136a57aa92 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,6 +29,15 @@ # .POSIX: +ROOTDIR = %%ROOTDIR%% +INCDIR = $(ROOTDIR)/include +SRCDIR = $(ROOTDIR)/src +TESTSDIR = $(ROOTDIR)/tests +SCRIPTSDIR = $(ROOTDIR)/scripts +GENDIR = $(ROOTDIR)/gen + +BUILDDIR = %%BUILDDIR%% + SRC = %%SRC%% OBJ = %%OBJ%% GCDA = %%GCDA%% @@ -39,46 +48,45 @@ BC_ENABLED = %%BC_ENABLED%% DC_ENABLED_NAME = 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 -BC_HEADERS = include/bc.h -DC_HEADERS = include/dc.h -HISTORY_HEADERS = include/history.h -EXTRA_MATH_HEADERS = include/rand.h -LIBRARY_HEADERS = include/bcl.h include/library.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 = $(INCDIR)/bc.h +DC_HEADERS = $(INCDIR)/dc.h +HISTORY_HEADERS = $(INCDIR)/history.h +EXTRA_MATH_HEADERS = $(INCDIR)/rand.h +LIBRARY_HEADERS = $(INCDIR)/bcl.h $(INCDIR)/library.h GEN_DIR = gen GEN = %%GEN%% GEN_EXEC = $(GEN_DIR)/$(GEN) -GEN_C = $(GEN_DIR)/$(GEN).c +GEN_C = $(GENDIR)/$(GEN).c GEN_EMU = %%GEN_EMU%% -BC_LIB = $(GEN_DIR)/lib.bc +BC_LIB = $(GENDIR)/lib.bc BC_LIB_C = $(GEN_DIR)/lib.c BC_LIB_O = %%BC_LIB_O%% BC_LIB_GCDA = $(GEN_DIR)/lib.gcda 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_O = %%BC_LIB2_O%% BC_LIB2_GCDA = $(GEN_DIR)/lib2.gcda 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_O = %%BC_HELP_O%% BC_HELP_GCDA = $(GEN_DIR)/bc_help.gcda 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_O = %%DC_HELP_O%% DC_HELP_GCDA = $(GEN_DIR)/dc_help.gcda DC_HELP_GCNO = $(GEN_DIR)/dc_help.gcno BIN = bin -LOCALES = locales EXEC_SUFFIX = %%EXECSUFFIX%% EXEC_PREFIX = %%EXECPREFIX%% @@ -97,7 +105,7 @@ LIB_NAME = $(LIB).a LIBBC = $(BIN)/$(LIB_NAME) BCL = bcl BCL_TEST = $(BIN)/$(BCL) -BCL_TEST_C = tests/$(BCL).c +BCL_TEST_C = $(TESTSDIR)/$(BCL).c MANUALS = manuals BC_MANPAGE_NAME = $(EXEC_PREFIX)$(BC)$(EXEC_SUFFIX).1 @@ -112,9 +120,13 @@ BCL_MD = $(BCL_MANPAGE).md MANPAGE_INSTALL_ARGS = -Dm644 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 = include/$(BCL_HEADER_NAME) +BCL_HEADER = $(INCDIR)/$(BCL_HEADER_NAME) %%DESTDIR%% BINDIR = %%BINDIR%% @@ -146,6 +158,8 @@ BC_DEFAULT_TTY_MODE = %%BC_DEFAULT_TTY_MODE%% DC_DEFAULT_TTY_MODE = %%DC_DEFAULT_TTY_MODE%% BC_DEFAULT_PROMPT = %%BC_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 MKDIR = mkdir @@ -158,13 +172,13 @@ MINISTAT_EXEC = $(SCRIPTS)/$(MINISTAT) BITFUNCGEN = bitfuncgen BITFUNCGEN_EXEC = $(SCRIPTS)/$(BITFUNCGEN) -INSTALL = $(SCRIPTS)/exec-install.sh -SAFE_INSTALL = $(SCRIPTS)/safe-install.sh -LINK = $(SCRIPTS)/link.sh -MANPAGE = $(SCRIPTS)/manpage.sh -KARATSUBA = $(SCRIPTS)/karatsuba.py -LOCALE_INSTALL = $(SCRIPTS)/locale_install.sh -LOCALE_UNINSTALL = $(SCRIPTS)/locale_uninstall.sh +INSTALL = $(SCRIPTSDIR)/exec-install.sh +SAFE_INSTALL = $(SCRIPTSDIR)/safe-install.sh +LINK = $(SCRIPTSDIR)/link.sh +MANPAGE = $(SCRIPTSDIR)/manpage.sh +KARATSUBA = $(SCRIPTSDIR)/karatsuba.py +LOCALE_INSTALL = $(SCRIPTSDIR)/locale_install.sh +LOCALE_UNINSTALL = $(SCRIPTSDIR)/locale_uninstall.sh 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_DEFS2 = -DBC_DEFAULT_TTY_MODE=$(BC_DEFAULT_TTY_MODE) 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_DEFS2 = -DDC_DEFAULT_TTY_MODE=$(DC_DEFAULT_TTY_MODE) 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) -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) CPPFLAGS4 = $(CPPFLAGS3) -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 %%BSD%% CPPFLAGS5 = $(CPPFLAGS4) -DBC_NUM_KARATSUBA_LEN=$(BC_NUM_KARATSUBA_LEN) @@ -212,7 +228,10 @@ all: %%DEFAULT_TARGET%% %%SECOND_TARGET%%: %%SECOND_TARGET_PREREQS%% %%SECOND_TARGET_CMD%% -$(GEN_EXEC): +$(GEN_DIR): + mkdir -p $(GEN_DIR) + +$(GEN_EXEC): $(GEN_DIR) %%GEN_EXEC_TARGET%% $(BC_LIB_C): $(GEN_EXEC) $(BC_LIB) @@ -242,13 +261,18 @@ $(DC_HELP_O): $(DC_HELP_C) $(BIN): $(MKDIR) -p $(BIN) +src: + $(MKDIR) -p src + headers: %%HEADERS%% $(MINISTAT): - $(HOSTCC) $(HOSTCFLAGS) -lm -o $(MINISTAT_EXEC) scripts/ministat.c + mkdir -p $(SCRIPTS) + $(HOSTCC) $(HOSTCFLAGS) -lm -o $(MINISTAT_EXEC) $(ROOTDIR)/scripts/ministat.c $(BITFUNCGEN): - $(HOSTCC) $(HOSTCFLAGS) -lm -o $(BITFUNCGEN_EXEC) scripts/bitfuncgen.c + mkdir -p $(SCRIPTS) + $(HOSTCC) $(HOSTCFLAGS) -lm -o $(BITFUNCGEN_EXEC) $(ROOTDIR)/scripts/bitfuncgen.c help: @printf 'available targets:\n' @@ -314,18 +338,18 @@ test_bc_tests:%%BC_TESTS%% test_bc_scripts:%%BC_SCRIPT_TESTS%% 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: - @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_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: - @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: @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_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: - @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_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: - @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: @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' test_bc_history0: - @sh tests/history.sh bc 0 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 0 %%BC_TEST_EXEC%% test_bc_history1: - @sh tests/history.sh bc 1 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 1 %%BC_TEST_EXEC%% test_bc_history2: - @sh tests/history.sh bc 2 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 2 %%BC_TEST_EXEC%% test_bc_history3: - @sh tests/history.sh bc 3 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 3 %%BC_TEST_EXEC%% test_bc_history4: - @sh tests/history.sh bc 4 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 4 %%BC_TEST_EXEC%% test_bc_history5: - @sh tests/history.sh bc 5 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 5 %%BC_TEST_EXEC%% test_bc_history6: - @sh tests/history.sh bc 6 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 6 %%BC_TEST_EXEC%% test_bc_history7: - @sh tests/history.sh bc 7 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 7 %%BC_TEST_EXEC%% test_bc_history8: - @sh tests/history.sh bc 8 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 8 %%BC_TEST_EXEC%% test_bc_history9: - @sh tests/history.sh bc 9 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 9 %%BC_TEST_EXEC%% test_bc_history10: - @sh tests/history.sh bc 10 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 10 %%BC_TEST_EXEC%% test_bc_history11: - @sh tests/history.sh bc 11 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 11 %%BC_TEST_EXEC%% test_bc_history12: - @sh tests/history.sh bc 12 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 12 %%BC_TEST_EXEC%% test_bc_history13: - @sh tests/history.sh bc 13 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 13 %%BC_TEST_EXEC%% test_bc_history14: - @sh tests/history.sh bc 14 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 14 %%BC_TEST_EXEC%% test_bc_history15: - @sh tests/history.sh bc 15 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 15 %%BC_TEST_EXEC%% test_bc_history16: - @sh tests/history.sh bc 16 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 16 %%BC_TEST_EXEC%% test_bc_history17: - @sh tests/history.sh bc 17 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 17 %%BC_TEST_EXEC%% test_bc_history18: - @sh tests/history.sh bc 18 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 18 %%BC_TEST_EXEC%% test_bc_history19: - @sh tests/history.sh bc 19 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 19 %%BC_TEST_EXEC%% test_bc_history20: - @sh tests/history.sh bc 20 %%BC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh bc 20 %%BC_TEST_EXEC%% 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_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: @printf 'No dc history tests to run\n' test_dc_history0: - @sh tests/history.sh dc 0 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 0 %%DC_TEST_EXEC%% test_dc_history1: - @sh tests/history.sh dc 1 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 1 %%DC_TEST_EXEC%% test_dc_history2: - @sh tests/history.sh dc 2 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 2 %%DC_TEST_EXEC%% test_dc_history3: - @sh tests/history.sh dc 3 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 3 %%DC_TEST_EXEC%% test_dc_history4: - @sh tests/history.sh dc 4 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 4 %%DC_TEST_EXEC%% test_dc_history5: - @sh tests/history.sh dc 5 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 5 %%DC_TEST_EXEC%% test_dc_history6: - @sh tests/history.sh dc 6 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 6 %%DC_TEST_EXEC%% test_dc_history7: - @sh tests/history.sh dc 7 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 7 %%DC_TEST_EXEC%% test_dc_history8: - @sh tests/history.sh dc 8 %%DC_TEST_EXEC%% + @sh $(TESTSDIR)/history.sh dc 8 %%DC_TEST_EXEC%% 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: @printf '$(TEST_STARS)\n\nRunning history tests...\n\n' @@ -505,18 +532,17 @@ clean:%%CLEAN_PREREQS%% @$(RM) -f $(BC_EXEC) @$(RM) -f $(DC_EXEC) @$(RM) -fr $(BIN) - @$(RM) -f $(LOCALES)/*.cat @$(RM) -f $(BC_LIB_C) $(BC_LIB_O) @$(RM) -f $(BC_LIB2_C) $(BC_LIB2_O) @$(RM) -f $(BC_HELP_C) $(BC_HELP_O) @$(RM) -f $(DC_HELP_C) $(DC_HELP_O) - @$(RM) -fr Debug/ Release/ + @$(RM) -fr vs/bin/ vs/lib/ clean_benchmarks: @printf 'Cleaning benchmarks...\n' @$(RM) -f $(MINISTAT_EXEC) - @$(RM) -f benchmarks/bc/*.txt - @$(RM) -f benchmarks/dc/*.txt + @$(RM) -f $(ROOTDIR)/benchmarks/bc/*.txt + @$(RM) -f $(ROOTDIR)/benchmarks/dc/*.txt clean_config: clean clean_benchmarks @printf 'Cleaning config...\n' @@ -544,19 +570,19 @@ clean_tests: clean clean_config clean_coverage @printf 'Cleaning test files...\n' @$(RM) -fr $(BC_TEST_OUTPUTS) $(DC_TEST_OUTPUTS) @$(RM) -fr $(BC_FUZZ_OUTPUTS) $(DC_FUZZ_OUTPUTS) - @$(RM) -f tests/bc/parse.txt tests/bc/parse_results.txt - @$(RM) -f tests/bc/print.txt tests/bc/print_results.txt - @$(RM) -f tests/bc/bessel.txt tests/bc/bessel_results.txt - @$(RM) -f tests/bc/strings2.txt tests/bc/strings2_results.txt - @$(RM) -f tests/bc/scripts/bessel.txt - @$(RM) -f tests/bc/scripts/parse.txt - @$(RM) -f tests/bc/scripts/print.txt - @$(RM) -f tests/bc/scripts/add.txt - @$(RM) -f tests/bc/scripts/divide.txt - @$(RM) -f tests/bc/scripts/multiply.txt - @$(RM) -f tests/bc/scripts/subtract.txt - @$(RM) -f tests/bc/scripts/strings2.txt - @$(RM) -f tests/dc/scripts/prime.txt + @$(RM) -f $(TESTSDIR)/bc/parse.txt $(TESTSDIR)/bc/parse_results.txt + @$(RM) -f $(TESTSDIR)/bc/print.txt $(TESTSDIR)/bc/print_results.txt + @$(RM) -f $(TESTSDIR)/bc/bessel.txt $(TESTSDIR)/bc/bessel_results.txt + @$(RM) -f $(TESTSDIR)/bc/strings2.txt $(TESTSDIR)/bc/strings2_results.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/bessel.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/parse.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/print.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/add.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/divide.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/multiply.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/subtract.txt + @$(RM) -f $(TESTSDIR)/bc/scripts/strings2.txt + @$(RM) -f $(TESTSDIR)/dc/scripts/prime.txt @$(RM) -f .log_*.txt @$(RM) -f .math.txt .results.txt .ops.txt @$(RM) -f .test.txt @@ -581,10 +607,11 @@ install_bcl_header: $(SAFE_INSTALL) $(MANPAGE_INSTALL_ARGS) $(BCL_HEADER) $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME) 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) + %%PKG_CONFIG_INSTALL%% install:%%INSTALL_LOCALES_PREREQS%%%%INSTALL_MAN_PREREQS%%%%INSTALL_PREREQS%% @@ -603,8 +630,9 @@ uninstall_dc_manpage: uninstall_dc: $(RM) -f $(DESTDIR)$(BINDIR)/$(EXEC_PREFIX)$(DC)$(EXEC_SUFFIX) -uninstall_library: +uninstall_library: uninstall_bcl_header $(RM) -f $(DESTDIR)$(LIBDIR)/$(LIB_NAME) + %%PKG_CONFIG_UNINSTALL%% uninstall_bcl_header: $(RM) -f $(DESTDIR)$(INCLUDEDIR)/$(BCL_HEADER_NAME) @@ -1,5 +1,19 @@ # News +## 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 This is a production release that completes a bug fix from `5.1.0`. The bug diff --git a/README.md b/README.md index c46d66b7e3ea..259ab923bfc4 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ system. This `bc` should build unmodified on any POSIX-compliant system or on Windows starting with Windows 10 (though earlier versions may work). -For more complex build requirements than the ones below, see the -[build manual][5]. +For more complex build requirements than the ones below, see the [build +manual][5]. ### Windows @@ -76,38 +76,45 @@ support) disabled, with both calculators built. #### `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. 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`. +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) -To build the library, you can open the `bcl.sln` file in Visual Studio, select -the configuration, and build. +To build the library, you can open the `vs/bcl.sln` file in Visual Studio, +select the configuration, and build. 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 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 -`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. +`bin/dc` by default. #### Default @@ -177,6 +184,24 @@ The library is built as `bin/libbcl.a` on POSIX-compatible systems or as #### 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 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). .gitattributes The git attributes file (maintainer use only). - bc.sln The Visual Studio solution file for bc. - 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. + bcl.pc.in A template pkg-config file for bcl. configure A symlink to configure.sh to make packaging easier. configure.sh The configure script. LICENSE.md A Markdown form of the BSD 2-clause License. Makefile.in The Makefile template. + NEWS.md The changelog. NOTICE.md List of contributors and copyright owners. RELEASE.md A checklist for making a release (maintainer use only). @@ -395,6 +416,7 @@ Folders: src All source code. scripts A bunch of shell scripts to help with development and building. tests All tests. + vs Files needed for the build on Windows. [1]: https://www.gnu.org/software/bc/ [4]: ./LICENSE.md diff --git a/bcl.pc.in b/bcl.pc.in new file mode 100644 index 000000000000..f440eeca950f --- /dev/null +++ b/bcl.pc.in @@ -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 diff --git a/configure.sh b/configure.sh index de1339780073..8a6a7817fd2a 100755 --- a/configure.sh +++ b/configure.sh @@ -31,9 +31,9 @@ script="$0" scriptdir=$(dirname "$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. # @param val The value to pass to exit. Must be an integer. @@ -205,6 +205,9 @@ usage() { 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 ' 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 ' interfere with other installed bc executables. Default is "".\n' printf ' EXECPREFIX The prefix to append to the executable names, used to not\n' @@ -290,6 +293,18 @@ usage() { printf '| | for dc should be on | | |\n' printf '| | in tty mode. | | |\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 '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' @@ -374,19 +389,34 @@ replace() { # the arguments are all assumed to be source files that should *not* be built. find_src_files() { + _find_src_files_args="" + if [ "$#" -ge 1 ] && [ "$1" != "" ]; then while [ "$#" -ge 1 ]; do _find_src_files_a="${1## }" 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 - else - _find_src_files_args="-print" 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 @@ -403,10 +433,6 @@ gen_file_list() { _gen_file_list_contents="$1" shift - p=$(pwd) - - cd "$scriptdir" - if [ "$#" -ge 1 ]; then _gen_file_list_unneeded="$@" else @@ -422,7 +448,14 @@ gen_file_list() { _gen_file_list_contents=$(replace "$_gen_file_list_contents" \ "$_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_needle_obj" "$_gen_file_list_replacement") @@ -434,8 +467,6 @@ gen_file_list() { _gen_file_list_contents=$(replace "$_gen_file_list_contents" \ "$_gen_file_list_needle_gcno" "$_gen_file_list_replacement") - cd "$p" - printf '%s\n' "$_gen_file_list_contents" } @@ -466,16 +497,16 @@ gen_std_tests() { 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' \ "$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \ - "$_gen_std_tests_t" >> "$scriptdir/Makefile" + "$_gen_std_tests_t" >> "Makefile" continue fi fi - printf 'test_%s_%s:\n\t@sh tests/test.sh %s %s %s %s %s\n\n' \ - "$_gen_std_tests_name" "$_gen_std_tests_t" "$_gen_std_tests_name" \ + 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" "$builddir" "$_gen_std_tests_name" \ "$_gen_std_tests_t" "$generate_tests" "$time_tests" \ - "$*" >> "$scriptdir/Makefile" + "$*" >> "Makefile" done } @@ -512,9 +543,9 @@ gen_err_tests() { 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' \ - "$_gen_err_tests_name" "$_gen_err_tests_t" "$_gen_err_tests_name" \ - "$_gen_err_tests_t" "$*" >> "$scriptdir/Makefile" + 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" "$builddir" "$_gen_err_tests_name" \ + "$_gen_err_tests_t" "$*" >> "Makefile" done @@ -566,10 +597,10 @@ gen_script_tests() { _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' \ - "$_gen_script_tests_name" "$_gen_script_tests_b" "$_gen_script_tests_name" \ + 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" "$builddir" "$_gen_script_tests_name" \ "$_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 } @@ -594,6 +625,8 @@ set_default() { dc.tty_mode) dc_default_tty_mode="$_set_default_on" ;; bc.prompt) bc_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" ;; esac @@ -656,6 +689,8 @@ bc_default_tty_mode=1 dc_default_tty_mode=0 bc_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 # handling of long options is done by hand, and that's the reason that short and @@ -946,12 +981,12 @@ executable="BC_EXEC" tests="test_bc timeconst test_dc" -bc_test="@tests/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)" -dc_test="@tests/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)" +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="@export BC_TEST_OUTPUT_DIR=\"$builddir/tests\"; \$(TESTSDIR)/all.sh -n bc $extra_math 1 $generate_tests $time_tests \$(BC_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="@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 # debug mode, so don't run valgrind without that. @@ -999,6 +1034,11 @@ if [ "$library" -ne 0 ]; then test_bc_history_prereqs=" test_bc_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 bc=1 @@ -1151,6 +1191,24 @@ if [ -z "${LIBDIR+set}" ]; then LIBDIR="$PREFIX/lib" 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 # installed, or locales are enabled because that's probably where NLS_PATH # points. @@ -1195,14 +1253,14 @@ if [ "$nls" -ne 0 ]; then 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_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" - "$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="$?" - rm -rf "$scriptdir/vm.o" + rm -rf "./vm.o" # If this errors, it is probably because of building on Windows, # and NLS is not supported on Windows, so disable it. @@ -1218,11 +1276,11 @@ if [ "$nls" -ne 0 ]; then printf 'NLS works.\n\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="$?" - rm -rf "$scriptdir/en_US.cat" + rm -rf "./en_US.cat" if [ "$err" -ne 0 ]; then printf 'gencat does not work.\n' @@ -1279,14 +1337,14 @@ if [ "$hist" -eq 1 ]; then 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_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" - "$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="$?" - rm -rf "$scriptdir/history.o" + rm -rf "./history.o" # If this errors, it is probably because of building on Windows, # and history is not supported on Windows, so disable it. @@ -1312,7 +1370,7 @@ if [ "$hist" -eq 0 ] || [ "$vg" -ne 0 ]; then test_dc_history_prereqs=" test_dc_history_skip" history_tests="@printf 'Skipping history tests...\\\\n'" 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 # Test OpenBSD. This is not in an if statement because regardless of whatever @@ -1327,7 +1385,7 @@ set +e printf 'Testing for OpenBSD...\n' 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="$?" @@ -1403,14 +1461,46 @@ else headers="$headers \$(DC_HEADERS)" 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 + unneeded="$unneeded args.c opt.c read.c file.c main.c" unneeded="$unneeded lang.c lex.c parse.c program.c" unneeded="$unneeded bc.c bc_lex.c bc_parse.c" unneeded="$unneeded dc.c dc_lex.c dc_parse.c" 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 + unneeded="$unneeded library.c" + + PC_PATH="" + pkg_config_install="" + pkg_config_uninstall="" + fi # library.c is not needed under normal circumstances. @@ -1444,6 +1534,8 @@ dc_script_tests=$(gen_script_test_targets dc) dc_err_tests=$(gen_err_test_targets dc) # Print out the values; this is for debugging. +printf 'Version: %s\n' "$version" + if [ "$bc" -ne 0 ]; then printf 'Building bc\n' else @@ -1479,6 +1571,7 @@ printf 'MANDIR=%s\n' "$MANDIR" printf 'MAN1DIR=%s\n' "$MAN1DIR" printf 'MAN3DIR=%s\n' "$MAN3DIR" printf 'NLSPATH=%s\n' "$NLSPATH" +printf 'PC_PATH=%s\n' "$PC_PATH" printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX" printf 'EXECPREFIX=%s\n' "$EXECPREFIX" printf 'DESTDIR=%s\n' "$DESTDIR" @@ -1495,6 +1588,8 @@ printf 'bc.tty_mode=%s\n' "$bc_default_tty_mode" printf 'dc.tty_mode=%s\n' "$dc_default_tty_mode" printf 'bc.prompt=%s\n' "$bc_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 # template is edited and output to the Makefile. @@ -1518,11 +1613,15 @@ src_files=$(find_src_files $unneeded) for f in $src_files; do 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") done # Replace all the placeholders. +contents=$(replace "$contents" "ROOTDIR" "$scriptdir") +contents=$(replace "$contents" "BUILDDIR" "$builddir") + contents=$(replace "$contents" "HEADERS" "$headers") contents=$(replace "$contents" "BC_ENABLED" "$bc") @@ -1583,6 +1682,10 @@ contents=$(replace "$contents" "UNINSTALL_MAN_PREREQS" "$uninstall_man_prereqs") contents=$(replace "$contents" "UNINSTALL_PREREQS" "$uninstall_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_PREREQS" "$default_target_prereqs") contents=$(replace "$contents" "DEFAULT_TARGET_CMD" "$default_target_cmd") @@ -1630,9 +1733,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" "BC_DEFAULT_PROMPT" "$bc_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. -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. if [ "$bc" -ne 0 ]; then @@ -1647,12 +1752,11 @@ if [ "$dc" -ne 0 ]; then gen_err_tests dc $dc_test_exec fi -cd "$scriptdir" - # Copy the correct manuals to the expected places. -cp -f manuals/bc/$manpage_args.1.md manuals/bc.1.md -cp -f manuals/bc/$manpage_args.1 manuals/bc.1 -cp -f manuals/dc/$manpage_args.1.md manuals/dc.1.md -cp -f manuals/dc/$manpage_args.1 manuals/dc.1 +mkdir -p manuals +cp -f "$scriptdir/manuals/bc/$manpage_args.1.md" manuals/bc.1.md +cp -f "$scriptdir/manuals/bc/$manpage_args.1" manuals/bc.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 diff --git a/gen/bc_help.txt b/gen/bc_help.txt index 9ba34c606481..36329b1d7aaf 100644 --- a/gen/bc_help.txt +++ b/gen/bc_help.txt @@ -183,3 +183,10 @@ Environment variables: If an integer and non-zero, enable prompt when TTY mode is possible. 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. diff --git a/gen/dc_help.txt b/gen/dc_help.txt index 4cf10826cd7f..a0f275b60b64 100644 --- a/gen/dc_help.txt +++ b/gen/dc_help.txt @@ -142,3 +142,10 @@ Environment variables: If an integer and non-zero, enable prompt when TTY mode is possible. 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. diff --git a/include/status.h b/include/status.h index 662f2b89c04d..3a23b09dc873 100644 --- a/include/status.h +++ b/include/status.h @@ -268,6 +268,10 @@ #define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE #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. #ifndef DC_DEFAULT_SIGINT_RESET #define DC_DEFAULT_SIGINT_RESET (1) @@ -285,6 +289,10 @@ #define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE #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 /// status that matters. typedef enum BcStatus { diff --git a/include/version.h b/include/version.h index 72500c8e3f28..296dbc79b547 100644 --- a/include/version.h +++ b/include/version.h @@ -37,6 +37,6 @@ #define BC_VERSION_H /// The current version. -#define VERSION 5.1.1 +#define VERSION 5.2.0 #endif // BC_VERSION_H diff --git a/include/vm.h b/include/vm.h index bbc5e57e2ac8..d6f698fb1e6d 100644 --- a/include/vm.h +++ b/include/vm.h @@ -176,6 +176,9 @@ /// The flag for reset on SIGINT. #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. #define BC_TTYIN (vm.flags & BC_FLAG_TTYIN) @@ -220,6 +223,9 @@ /// A convenience macro for getting the leading zero flag. #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 /// A convenience macro for checking if bc is in POSIX mode. diff --git a/manuals/bc/A.1 b/manuals/bc/A.1 index bf6c9108456b..038932d52ada 100644 --- a/manuals/bc/A.1 +++ b/manuals/bc/A.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/A.1.md b/manuals/bc/A.1.md index e773d967284c..112e98078cf0 100644 --- a/manuals/bc/A.1.md +++ b/manuals/bc/A.1.md @@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/E.1 b/manuals/bc/E.1 index bb563f5c96fc..6ee1e063ebde 100644 --- a/manuals/bc/E.1 +++ b/manuals/bc/E.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/E.1.md b/manuals/bc/E.1.md index 63367e436cc8..ba6e44c248c2 100644 --- a/manuals/bc/E.1.md +++ b/manuals/bc/E.1.md @@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/EH.1 b/manuals/bc/EH.1 index 0bdfaa9fe14b..4509583a0141 100644 --- a/manuals/bc/EH.1 +++ b/manuals/bc/EH.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/EH.1.md b/manuals/bc/EH.1.md index 044330b7fe0a..2178c375cb92 100644 --- a/manuals/bc/EH.1.md +++ b/manuals/bc/EH.1.md @@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/EHN.1 b/manuals/bc/EHN.1 index f0519898ad7e..6b49f3651d5a 100644 --- a/manuals/bc/EHN.1 +++ b/manuals/bc/EHN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/EHN.1.md b/manuals/bc/EHN.1.md index 25543500eea7..3b60d3d0251b 100644 --- a/manuals/bc/EHN.1.md +++ b/manuals/bc/EHN.1.md @@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/EN.1 b/manuals/bc/EN.1 index 192dccfea2fc..c4704807fac6 100644 --- a/manuals/bc/EN.1 +++ b/manuals/bc/EN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/EN.1.md b/manuals/bc/EN.1.md index e77d64cd7a56..13ad5f8b570a 100644 --- a/manuals/bc/EN.1.md +++ b/manuals/bc/EN.1.md @@ -1149,6 +1149,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/H.1 b/manuals/bc/H.1 index 5f290f12ae32..f6d555943367 100644 --- a/manuals/bc/H.1 +++ b/manuals/bc/H.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/H.1.md b/manuals/bc/H.1.md index 99c88db93230..47b17f1188e4 100644 --- a/manuals/bc/H.1.md +++ b/manuals/bc/H.1.md @@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/HN.1 b/manuals/bc/HN.1 index 4773ff77efea..0687cb263b6e 100644 --- a/manuals/bc/HN.1 +++ b/manuals/bc/HN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/HN.1.md b/manuals/bc/HN.1.md index d5b3324514ad..12ed1c9c5e74 100644 --- a/manuals/bc/HN.1.md +++ b/manuals/bc/HN.1.md @@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/bc/N.1 b/manuals/bc/N.1 index 56fca3d02b4d..40dbad9bb2f2 100644 --- a/manuals/bc/N.1 +++ b/manuals/bc/N.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP bc(1) returns the following exit statuses: diff --git a/manuals/bc/N.1.md b/manuals/bc/N.1.md index 51dad376b56d..92c239c0b12b 100644 --- a/manuals/bc/N.1.md +++ b/manuals/bc/N.1.md @@ -2129,6 +2129,17 @@ bc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 bc(1) returns the following exit statuses: diff --git a/manuals/build.md b/manuals/build.md index 1ed2b269f13c..aa0ed78e2d72 100644 --- a/manuals/build.md +++ b/manuals/build.md @@ -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 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 To cross-compile this `bc`, an appropriate compiler must be present and assigned diff --git a/manuals/dc/A.1 b/manuals/dc/A.1 index a7ff2e3a6963..3dff3b16d080 100644 --- a/manuals/dc/A.1 +++ b/manuals/dc/A.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/A.1.md b/manuals/dc/A.1.md index 0007cc76760a..618543d7f397 100644 --- a/manuals/dc/A.1.md +++ b/manuals/dc/A.1.md @@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/E.1 b/manuals/dc/E.1 index 8760477a03ff..a677bcea0c0c 100644 --- a/manuals/dc/E.1 +++ b/manuals/dc/E.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/E.1.md b/manuals/dc/E.1.md index 6a2c465e5642..a138fdb32158 100644 --- a/manuals/dc/E.1.md +++ b/manuals/dc/E.1.md @@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/EH.1 b/manuals/dc/EH.1 index 4506001dfe55..97c05ca44094 100644 --- a/manuals/dc/EH.1 +++ b/manuals/dc/EH.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/EH.1.md b/manuals/dc/EH.1.md index 06ec59d4b3f7..459f8ac12e7e 100644 --- a/manuals/dc/EH.1.md +++ b/manuals/dc/EH.1.md @@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/EHN.1 b/manuals/dc/EHN.1 index 1124d907bdd9..223bd9f08dfa 100644 --- a/manuals/dc/EHN.1 +++ b/manuals/dc/EHN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/EHN.1.md b/manuals/dc/EHN.1.md index 50cb37ef2586..56ac39ed599e 100644 --- a/manuals/dc/EHN.1.md +++ b/manuals/dc/EHN.1.md @@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/EN.1 b/manuals/dc/EN.1 index beae0e46a9b6..8c2d14f57840 100644 --- a/manuals/dc/EN.1 +++ b/manuals/dc/EN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/EN.1.md b/manuals/dc/EN.1.md index db6f27f34576..03836923c00e 100644 --- a/manuals/dc/EN.1.md +++ b/manuals/dc/EN.1.md @@ -1025,6 +1025,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/H.1 b/manuals/dc/H.1 index b4ab9f511080..f27358fb7f12 100644 --- a/manuals/dc/H.1 +++ b/manuals/dc/H.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/H.1.md b/manuals/dc/H.1.md index 647d486adc38..c97cc8b58eef 100644 --- a/manuals/dc/H.1.md +++ b/manuals/dc/H.1.md @@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/HN.1 b/manuals/dc/HN.1 index eb35cb23ff7b..13a39ef26540 100644 --- a/manuals/dc/HN.1 +++ b/manuals/dc/HN.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/HN.1.md b/manuals/dc/HN.1.md index 70c962624833..47c2a0330ae9 100644 --- a/manuals/dc/HN.1.md +++ b/manuals/dc/HN.1.md @@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/manuals/dc/N.1 b/manuals/dc/N.1 index c5cc36ac9b10..16f89b7ee2a1 100644 --- a/manuals/dc/N.1 +++ b/manuals/dc/N.1 @@ -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 \f[B]-h\f[R] or \f[B]--help\f[R] options. .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 .PP dc(1) returns the following exit statuses: diff --git a/manuals/dc/N.1.md b/manuals/dc/N.1.md index fea23028e483..a14c922b4dbc 100644 --- a/manuals/dc/N.1.md +++ b/manuals/dc/N.1.md @@ -1190,6 +1190,17 @@ dc(1) recognizes the following environment variables: override the default, which can be queried with the **-h** or **-\-help** 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 dc(1) returns the following exit statuses: diff --git a/scripts/exec-install.sh b/scripts/exec-install.sh index 25d56c6fc688..f36caa37e6f8 100755 --- a/scripts/exec-install.sh +++ b/scripts/exec-install.sh @@ -29,7 +29,7 @@ # Print usage and exit with an error. 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 } @@ -49,7 +49,12 @@ shift exec_suffix="$1" 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. # If it's a symlink, create an equivalent in the install directory. diff --git a/scripts/karatsuba.py b/scripts/karatsuba.py index b8505186b526..9aa1c2a5457f 100755 --- a/scripts/karatsuba.py +++ b/scripts/karatsuba.py @@ -49,9 +49,6 @@ testdir = os.path.dirname(script) if testdir == "": 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("It is for finding the optimal Karatsuba number.") print("Though it only needs to be run once per release/platform,") @@ -116,7 +113,7 @@ try: except KeyError: flags["CFLAGS"] = "-flto" -p = run([ "./configure.sh", "-O3" ], flags) +p = run([ "{}/../configure.sh".format(testdir), "-O3" ], flags) if p.returncode != 0: print("configure.sh returned an error ({}); exiting...".format(p.returncode)) sys.exit(p.returncode) @@ -161,7 +158,7 @@ try: # Configure and compile. 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: print("configure.sh returned an error ({}); exiting...".format(p.returncode)) diff --git a/src/args.c b/src/args.c index 6601cfb2eeb6..5eee96f5b559 100644 --- a/src/args.c +++ b/src/args.c @@ -91,6 +91,8 @@ static void bc_args_redefine(const char *keyword) { size_t i; + BC_SIG_ASSERT_LOCKED; + for (i = 0; i < bc_lex_kws_len; ++i) { const BcLexKeyword *kw = bc_lex_kws + i; diff --git a/src/bc_lex.c b/src/bc_lex.c index cdbdf24b17ac..bd03d169ee06 100644 --- a/src/bc_lex.c +++ b/src/bc_lex.c @@ -158,6 +158,8 @@ void bc_lex_token(BcLex *l) { // character of every identifier would be missing. char c = l->buf[l->i++], c2; + BC_SIG_ASSERT_LOCKED; + // This is the workhorse of the lexer. switch (c) { diff --git a/src/bc_parse.c b/src/bc_parse.c index c2fc2186a065..91de31ad5389 100644 --- a/src/bc_parse.c +++ b/src/bc_parse.c @@ -329,12 +329,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. if (idx == BC_VEC_INVALID_IDX) { - BC_SIG_LOCK; - idx = bc_program_insertFunc(p->prog, name); - BC_SIG_UNLOCK; - assert(idx != BC_VEC_INVALID_IDX); // Make sure that this pointer was not invalidated. @@ -359,15 +355,13 @@ static void bc_parse_name(BcParse *p, BcInst *type, { char *name; - BC_SIG_LOCK; + BC_SIG_ASSERT_LOCKED; // We want a copy of the name since the lexer might overwrite its copy. name = bc_vm_strdup(p->l.str.v); BC_SETJMP_LOCKED(err); - BC_SIG_UNLOCK; - // We need the next token to see if it's just a variable or something more. bc_lex_next(&p->l); @@ -431,9 +425,9 @@ static void bc_parse_name(BcParse *p, BcInst *type, err: // Need to make sure to unallocate the name. - BC_SIG_MAYLOCK; free(name); BC_LONGJMP_CONT; + BC_SIG_MAYLOCK; } /** @@ -1315,15 +1309,9 @@ static void bc_parse_func(BcParse *p) { // Make sure the functions map and vector are synchronized. 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. idx = bc_program_insertFunc(p->prog, p->l.str.v); - BC_SIG_UNLOCK; - // Make sure the insert worked. assert(idx); @@ -1759,7 +1747,7 @@ void bc_parse_parse(BcParse *p) { assert(p); - BC_SETJMP(exit); + BC_SETJMP_LOCKED(exit); // We should not let an EOF get here unless some partial parse was not // completed, in which case, it's the user's fault. @@ -1780,13 +1768,12 @@ void bc_parse_parse(BcParse *p) { exit: - BC_SIG_MAYLOCK; - // We need to reset on error. if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig))) bc_parse_reset(p); BC_LONGJMP_CONT; + BC_SIG_MAYLOCK; } /** diff --git a/src/dc_lex.c b/src/dc_lex.c index 5c6950ba9698..576d50943f25 100644 --- a/src/dc_lex.c +++ b/src/dc_lex.c @@ -157,6 +157,8 @@ void dc_lex_token(BcLex *l) { char c = l->buf[l->i++], c2; size_t i; + BC_SIG_ASSERT_LOCKED; + // If the last token was a command that needs a register, we need to parse a // register, so do so. for (i = 0; i < dc_lex_regs_len; ++i) { diff --git a/src/dc_parse.c b/src/dc_parse.c index b9b5afb66c44..26aad6796d88 100644 --- a/src/dc_parse.c +++ b/src/dc_parse.c @@ -302,7 +302,7 @@ void dc_parse_parse(BcParse *p) { assert(p != NULL); - BC_SETJMP(exit); + BC_SETJMP_LOCKED(exit); // If we have EOF, someone called this function one too many times. // Otherwise, parse. @@ -311,11 +311,10 @@ void dc_parse_parse(BcParse *p) { exit: - BC_SIG_MAYLOCK; - // Need to reset if there was an error. if (BC_SIG_EXC) bc_parse_reset(p); BC_LONGJMP_CONT; + BC_SIG_MAYLOCK; } #endif // DC_ENABLED diff --git a/src/file.c b/src/file.c index 35a4647dfabf..627664a9c261 100644 --- a/src/file.c +++ b/src/file.c @@ -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); // 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; + } bytes += (size_t) written; } @@ -109,6 +113,8 @@ BcStatus bc_file_flushErr(BcFile *restrict f, BcFlushType type) { BcStatus s; + BC_SIG_ASSERT_LOCKED; + // If there is stuff to output... 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) { - 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 (BC_ERR(s)) { @@ -159,16 +170,23 @@ void bc_file_flush(BcFile *restrict f, BcFlushType type) { // For EOF, set it and jump. if (s == BC_STATUS_EOF) { vm.status = (sig_atomic_t) s; + BC_SIG_TRYUNLOCK(lock); BC_JMP; } // Blow up on fatal error. Okay, not blow up, just quit. else bc_vm_fatalError(BC_ERR_FATAL_IO_ERR); } + + BC_SIG_TRYUNLOCK(lock); } void bc_file_write(BcFile *restrict f, BcFlushType type, const char *buf, size_t n) { + sig_atomic_t lock; + + BC_SIG_TRYLOCK(lock); + // If we have enough to flush, do it. if (n > f->cap - f->len) { 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); f->len += n; } + + BC_SIG_TRYUNLOCK(lock); } void bc_file_printf(BcFile *restrict f, const char *fmt, ...) { va_list args; + sig_atomic_t lock; + + BC_SIG_TRYLOCK(lock); va_start(args, fmt); bc_file_vprintf(f, fmt, args); va_end(args); + + BC_SIG_TRYUNLOCK(lock); } 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; 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 // 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 @@ -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) { + sig_atomic_t lock; + + BC_SIG_TRYLOCK(lock); + if (f->len == f->cap) bc_file_flush(f, type); assert(f->len < f->cap); f->buf[f->len] = (char) c; f->len += 1; + + BC_SIG_TRYUNLOCK(lock); } void bc_file_init(BcFile *f, int fd, char *buf, size_t cap) { diff --git a/src/history.c b/src/history.c index b5ba0758075c..9f158413efc2 100644 --- a/src/history.c +++ b/src/history.c @@ -375,7 +375,7 @@ static ssize_t bc_history_read(char *buf, size_t n) { ssize_t ret; - BC_SIG_LOCK; + BC_SIG_ASSERT_LOCKED; #ifndef _WIN32 @@ -396,8 +396,6 @@ static ssize_t bc_history_read(char *buf, size_t n) { #endif // _WIN32 - BC_SIG_UNLOCK; - return ret; } @@ -416,8 +414,13 @@ static BcStatus bc_history_readCode(char *buf, size_t buf_len, assert(buf_len >= 1); + BC_SIG_LOCK; + // Read a byte. n = bc_history_read(buf, 1); + + BC_SIG_UNLOCK; + if (BC_ERR(n <= 0)) goto err; // Get the byte. @@ -431,24 +434,36 @@ static BcStatus bc_history_readCode(char *buf, size_t buf_len, assert(buf_len >= 2); + BC_SIG_LOCK; + n = bc_history_read(buf + 1, 1); + BC_SIG_UNLOCK; + if (BC_ERR(n <= 0)) goto err; } else if ((byte & 0xF0) == 0xE0) { assert(buf_len >= 3); + BC_SIG_LOCK; + n = bc_history_read(buf + 1, 2); + BC_SIG_UNLOCK; + if (BC_ERR(n <= 0)) goto err; } else if ((byte & 0xF8) == 0xF0) { assert(buf_len >= 3); + BC_SIG_LOCK; + n = bc_history_read(buf + 1, 3); + BC_SIG_UNLOCK; + if (BC_ERR(n <= 0)) goto err; } else { @@ -606,6 +621,8 @@ static size_t bc_history_cursorPos(void) { char *ptr, *ptr2; size_t cols, rows, i; + BC_SIG_ASSERT_LOCKED; + // Report cursor location. bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4); bc_file_flush(&vm.fout, bc_flush_none); @@ -648,12 +665,8 @@ static size_t bc_history_columns(void) { struct winsize ws; int ret; - BC_SIG_LOCK; - ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws); - BC_SIG_UNLOCK; - if (BC_ERR(ret == -1 || !ws.ws_col)) { // 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; 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); // 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) { + BC_SIG_ASSERT_LOCKED; + bc_vec_grow(&h->buf, clen); // 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) { + BC_SIG_ASSERT_LOCKED; + // Stop at the left end. 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) { + BC_SIG_ASSERT_LOCKED; + // Stop at the right end. 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); + BC_SIG_ASSERT_LOCKED; + // Don't overflow. 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); + BC_SIG_ASSERT_LOCKED; + // Stop with no data. if (!len) return; @@ -900,6 +925,8 @@ static void bc_history_edit_wordStart(BcHistory *h) { */ static void bc_history_edit_home(BcHistory *h) { + BC_SIG_ASSERT_LOCKED; + // Stop at the beginning. if (!h->pos) return; @@ -914,6 +941,8 @@ static void bc_history_edit_home(BcHistory *h) { */ static void bc_history_edit_end(BcHistory *h) { + BC_SIG_ASSERT_LOCKED; + // Stop at the end of the line. 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; + BC_SIG_ASSERT_LOCKED; + // Stop if there is no history. if (h->history.len <= 1) return; - BC_SIG_LOCK; - // Duplicate the buffer. if (h->buf.v[0]) dup = bc_vm_strdup(h->buf.v); 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. bc_vec_replaceAt(&h->history, h->history.len - 1 - h->idx, &dup); - BC_SIG_UNLOCK; - // Show the new entry. 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); + BC_SIG_ASSERT_LOCKED; + // If there is no character, skip. 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); + BC_SIG_ASSERT_LOCKED; + // If there are no characters, skip. if (!h->pos || !len) return; @@ -1031,6 +1062,8 @@ static void bc_history_edit_deletePrevWord(BcHistory *h) { size_t diff, old_pos = h->pos; + BC_SIG_ASSERT_LOCKED; + // If at the beginning of the line, skip. 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); + BC_SIG_ASSERT_LOCKED; + // If at the end of the line, skip. if (next_end == len) return; @@ -1084,6 +1119,8 @@ static void bc_history_swap(BcHistory *h) { size_t pcl, ncl; char auxb[5]; + BC_SIG_ASSERT_LOCKED; + // Get the length of the previous and next characters. pcl = bc_history_prevLen(h->buf.v, h->pos); 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]; + BC_SIG_ASSERT_LOCKED; + // Read a character into seq. 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) { + BC_SIG_ASSERT_LOCKED; + // If there is something already there... if (h->history.len) { @@ -1282,13 +1323,7 @@ static void bc_history_add(BcHistory *h, char *line) { // Check for, and discard, duplicates. if (!strcmp(s, line)) { - - BC_SIG_LOCK; - free(line); - - BC_SIG_UNLOCK; - return; } } @@ -1303,6 +1338,8 @@ static void bc_history_add(BcHistory *h, char *line) { */ static void bc_history_add_empty(BcHistory *h) { + BC_SIG_ASSERT_LOCKED; + const char *line = ""; // 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) { + BC_SIG_ASSERT_LOCKED; + h->oldcolpos = h->pos = h->idx = 0; h->cols = bc_history_columns(); @@ -1345,6 +1384,8 @@ static void bc_history_printCtrl(BcHistory *h, unsigned int c) { char str[3] = "^A"; const char newline[2] = "\n"; + BC_SIG_ASSERT_LOCKED; + // Set the correct character. 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) { + BC_SIG_LOCK; + bc_history_reset(h); // 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; size_t nread = 0; + BC_SIG_UNLOCK; + // Read a code. s = bc_history_readCode(cbuf, sizeof(cbuf), &c, &nread); if (BC_ERR(s)) return s; + BC_SIG_LOCK; + switch (c) { case BC_ACTION_LINE_FEED: @@ -1415,6 +1462,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { { // Return the line. bc_vec_pop(&h->history); + BC_SIG_UNLOCK; return s; } @@ -1434,6 +1482,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { // Quit if the user wants it. if (!BC_SIGINT) { vm.status = BC_STATUS_QUIT; + BC_SIG_UNLOCK; BC_JMP; } @@ -1460,6 +1509,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { case BC_ACTION_CTRL_D: { bc_history_printCtrl(h, c); + BC_SIG_UNLOCK; return BC_STATUS_EOF; } #endif // _WIN32 @@ -1565,6 +1615,7 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { bc_history_raise(h, SIGQUIT); #else // _WIN32 vm.status = BC_STATUS_QUIT; + BC_SIG_UNLOCK; BC_JMP; #endif // _WIN32 } @@ -1575,6 +1626,8 @@ static BcStatus bc_history_edit(BcHistory *h, const char *prompt) { } } + BC_SIG_UNLOCK; + 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_flush(&vm.fout, bc_flush_none); + BC_SIG_LOCK; + // If we actually have data... if (h->buf.v[0]) { - BC_SIG_LOCK; - // Duplicate it. line = bc_vm_strdup(h->buf.v); - BC_SIG_UNLOCK; - // Store it. bc_history_add(h, line); } // Add an empty string. else bc_history_add_empty(h); + BC_SIG_UNLOCK; + // Concatenate the line to the return vector. bc_vec_concat(vec, h->buf.v); bc_vec_concat(vec, "\n"); diff --git a/src/lex.c b/src/lex.c index f8b32451aef7..51e9f31bfa11 100644 --- a/src/lex.c +++ b/src/lex.c @@ -258,6 +258,8 @@ void bc_lex_file(BcLex *l, const char *file) { void bc_lex_next(BcLex *l) { + BC_SIG_ASSERT_LOCKED; + assert(l != NULL); 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 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); @@ -302,10 +312,15 @@ bool bc_lex_readLine(BcLex *l) { } void bc_lex_text(BcLex *l, const char *text, bool is_stdin) { + + BC_SIG_ASSERT_LOCKED; + assert(l != NULL && text != NULL); + bc_lex_fixText(l, text, strlen(text)); l->i = 0; l->t = l->last = BC_LEX_INVALID; l->is_stdin = is_stdin; + bc_lex_next(l); } diff --git a/src/library.c b/src/library.c index e0bd3ee98b85..a9246a025206 100644 --- a/src/library.c +++ b/src/library.c @@ -77,9 +77,14 @@ BclError bcl_init(void) { BclError e = BCL_ERROR_NONE; + BC_SIG_LOCK; + 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 // is necessary. @@ -89,8 +94,6 @@ BclError bcl_init(void) { vm.abrt = false; - BC_SIG_LOCK; - // The jmp_bufs always has to be initialized first. bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE); @@ -146,11 +149,14 @@ void bcl_free(void) { size_t i; - vm.refs -= 1; + BC_SIG_LOCK; - if (vm.refs) return; + vm.refs -= 1; - BC_SIG_LOCK; + if (vm.refs) { + BC_SIG_UNLOCK; + return; + } bc_rand_free(&vm.rng); bc_vec_free(&vm.out); diff --git a/src/opt.c b/src/opt.c index ddc78362e7b1..971e7e5f3ca5 100644 --- a/src/opt.c +++ b/src/opt.c @@ -235,7 +235,7 @@ static bool bc_opt_longoptsMatch(const char *name, const char *option) { // Can never match a NULL name. if (name == NULL) return false; - // Loop through + // Loop through. for (; *a && *n && *a != '='; ++a, ++n) { if (*a != *n) return false; } diff --git a/src/parse.c b/src/parse.c index ea4c25e8ba10..7fdfa31df4ac 100644 --- a/src/parse.c +++ b/src/parse.c @@ -70,15 +70,11 @@ void bc_parse_addString(BcParse *p) { size_t idx; - BC_SIG_LOCK; - idx = bc_program_addString(p->prog, p->l.str.v, p->fidx); // Push the string info. bc_parse_update(p, BC_INST_STR, p->fidx); bc_parse_pushIndex(p, idx); - - BC_SIG_UNLOCK; } 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; BcVec *slabs; + BC_SIG_ASSERT_LOCKED; + // Special case 0. if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) { bc_parse_push(p, BC_INST_ZERO); @@ -103,8 +101,6 @@ static void bc_parse_addNum(BcParse *p, const char *string) { // Get the index. idx = consts->len; - BC_SIG_LOCK; - // Get the right slab. slabs = p->fidx == BC_PROG_MAIN || p->fidx == BC_PROG_READ ? &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_parse_update(p, BC_INST_NUM, idx); - - BC_SIG_UNLOCK; } 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) { + BC_SIG_LOCK; + // Make sure the pointer isn't invalidated. p->func = bc_vec_item(&p->prog->fns, p->fidx); bc_lex_text(&p->l, text, is_stdin); + + BC_SIG_UNLOCK; } void bc_parse_reset(BcParse *p) { diff --git a/src/program.c b/src/program.c index 1ff9c24f323b..bc5b88011638 100644 --- a/src/program.c +++ b/src/program.c @@ -55,6 +55,7 @@ * @param f The new function. */ static inline void bc_program_setVecs(BcProgram *p, BcFunc *f) { + BC_SIG_ASSERT_LOCKED; p->consts = &f->consts; p->strs = &f->strs; } @@ -152,6 +153,8 @@ static void bc_program_popGlobals(BcProgram *p, bool reset) { size_t i; + BC_SIG_ASSERT_LOCKED; + for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) { BcVec *v = p->globals_v + i; 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; size_t i; + BC_SIG_ASSERT_LOCKED; + // Grab the right vector and map. v = var ? &p->vars : &p->arrs; 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 // 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 @@ -253,8 +256,6 @@ size_t bc_program_search(BcProgram *p, const char *id, bool var) { bc_array_init(temp, var); } - BC_SIG_UNLOCK; - return ((BcId*) bc_vec_item(map, i))->idx; } @@ -711,7 +712,9 @@ static void bc_program_read(BcProgram *p) { // Parse *one* expression. 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); + BC_SIG_UNLOCK; // We *must* have a valid expression. A semicolon cannot end an expression, // although EOF can. @@ -736,6 +739,9 @@ static void bc_program_read(BcProgram *p) { // We want a return instruction to simplify things. 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); #if DC_ENABLED @@ -784,6 +790,9 @@ static void bc_program_printChars(const char *str) { const char *nl; size_t len = vm.nchars + strlen(str); + sig_atomic_t lock; + + BC_SIG_TRYLOCK(lock); 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); 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) { // 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. 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_SIG_LOCK; + // When we retire, pop all of the unused results. 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." bc_vec_pop(&p->stack); + + BC_SIG_UNLOCK; } #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 // we would not have quit in that position on the stack would have quit // anyway. + BC_SIG_LOCK; bc_vec_npop(&p->stack, 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. bc_parse_text(&vm.read_prs, str, false); - vm.expr(&vm.read_prs, BC_PARSE_NOCALL); BC_SIG_LOCK; + vm.expr(&vm.read_prs, BC_PARSE_NOCALL); BC_UNSETJMP; @@ -2329,6 +2350,8 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code, ip.len = p->results.len; ip.func = fidx; + BC_SIG_LOCK; + // Pop the operand. 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. bc_vec_push(&p->stack, &ip); + BC_SIG_UNLOCK; + return; err: @@ -2678,7 +2703,9 @@ void bc_program_exec(BcProgram *p) { code = func->code.v; // Ensure the pointers are correct. + BC_SIG_LOCK; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; #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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; 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 // executing, we have to update all of this. + BC_SIG_LOCK; ip = bc_vec_top(&p->stack); func = bc_vec_item(&p->fns, ip->func); code = func->code.v; bc_program_setVecs(p, func); + BC_SIG_UNLOCK; BC_PROG_JUMP(inst, code, ip); } diff --git a/src/rand.c b/src/rand.c index bfc79be7cfb9..a3b8942a6042 100644 --- a/src/rand.c +++ b/src/rand.c @@ -461,16 +461,21 @@ BcRand bc_rand_int(BcRNG *r) { // Get the actual PRNG. BcRNGData *rng = bc_vec_top(&r->v); + BcRand res; // Make sure the PRNG is seeded. 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, - // including the return statement. + BC_SIG_LOCK; + + // This is the important part of the PRNG. This is the stuff from PCG. bc_rand_step(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) { diff --git a/src/read.c b/src/read.c index 84621ad3acac..b9cd4db7bb49 100644 --- a/src/read.c +++ b/src/read.c @@ -196,12 +196,16 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) { return BC_STATUS_EOF; } + BC_SIG_LOCK; + // Add to the buffer. vm.buf_len += (size_t) r; vm.buf[vm.buf_len] = '\0'; // Read from the buffer. done = bc_read_buf(vec, vm.buf, &vm.buf_len); + + BC_SIG_UNLOCK; } // Terminate the string. @@ -186,9 +186,11 @@ void bc_vm_info(const char* const help) { "disabled"; const char* const prompt = BC_DEFAULT_PROMPT ? "enabled" : "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_BUILD_TYPE, banner, sigint, tty, prompt); + BC_BUILD_TYPE, banner, sigint, tty, prompt, expr); } #endif // BC_ENABLED @@ -201,9 +203,11 @@ void bc_vm_info(const char* const help) { "disabled"; const char* const prompt = DC_DEFAULT_PROMPT ? "enabled" : "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_BUILD_TYPE, sigint, tty, prompt); + BC_BUILD_TYPE, sigint, tty, prompt, expr); } #endif // DC_ENABLED } @@ -552,6 +556,8 @@ void bc_vm_shutdown(void) { void bc_vm_addTemp(BcDig *num) { + BC_SIG_ASSERT_LOCKED; + // If we don't have room, just free. if (vm.temps_len == BC_VM_MAX_TEMPS) free(num); else { @@ -563,8 +569,13 @@ void bc_vm_addTemp(BcDig *num) { } BcDig* bc_vm_takeTemp(void) { + + BC_SIG_ASSERT_LOCKED; + if (!vm.temps_len) return NULL; + vm.temps_len -= 1; + return temps_buf[vm.temps_len]; } @@ -660,8 +671,9 @@ char* bc_vm_strdup(const char *str) { void bc_vm_printf(const char *fmt, ...) { va_list args; + sig_atomic_t lock; - BC_SIG_LOCK; + BC_SIG_TRYLOCK(lock); va_start(args, fmt); bc_file_vprintf(&vm.fout, fmt, args); @@ -669,7 +681,7 @@ void bc_vm_printf(const char *fmt, ...) { vm.nchars = 0; - BC_SIG_UNLOCK; + BC_SIG_TRYUNLOCK(lock); } #endif // !BC_ENABLE_LIBRARY @@ -745,6 +757,8 @@ static void bc_vm_clean(void) { BcInstPtr *ip = bc_vec_item(&vm.prog.stack, 0); bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig); + BC_SIG_ASSERT_LOCKED; + // If all is good, go ahead and reset. if (good) bc_program_reset(&vm.prog); @@ -816,6 +830,8 @@ static void bc_vm_process(const char *text, bool is_stdin) { do { + BC_SIG_LOCK; + #if BC_ENABLED // 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. @@ -825,6 +841,8 @@ static void bc_vm_process(const char *text, bool is_stdin) { // Parse it all. while (BC_PARSE_CAN_PARSE(vm.prs)) vm.parse(&vm.prs); + BC_SIG_UNLOCK; + // Execute if possible. 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; bool good; + BC_SIG_ASSERT_NOT_LOCKED; + // Clear the buffer if desired. if (clear) bc_vec_empty(&vm.buffer); @@ -969,7 +989,11 @@ restart: bc_vm_process(vm.buffer.v, true); if (vm.eof) break; - else bc_vm_clean(); + else { + BC_SIG_LOCK; + bc_vm_clean(); + BC_SIG_UNLOCK; + } } #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_parse_text(&vm.prs, text, false); + BC_SIG_LOCK; + while (vm.prs.l.t != BC_LEX_EOF) vm.parse(&vm.prs); + + BC_SIG_UNLOCK; } #endif // BC_ENABLED @@ -1172,7 +1200,7 @@ static void bc_vm_exec(void) { BC_SIG_UNLOCK; // 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. @@ -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 // the times when we read from /dev/urandom. - if (BC_TTY && !vm.history.badTerm) { - bc_pledge(bc_pledge_end_history, NULL); - } + if (BC_TTY && !vm.history.badTerm) bc_pledge(bc_pledge_end_history, NULL); else #endif // BC_ENABLE_HISTORY { @@ -1233,6 +1259,8 @@ void bc_vm_boot(int argc, char *argv[]) { bool tty; 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_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. ttyin = isatty(STDIN_FILENO); @@ -1269,6 +1297,8 @@ void bc_vm_boot(int argc, char *argv[]) { // Set the line length by environment variable. 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 // *not* allocated. bc_vec_clear(&vm.files); @@ -1289,26 +1319,22 @@ void bc_vm_boot(int argc, char *argv[]) { bc_program_init(&vm.prog); bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN); + // Set defaults. + vm.flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0; + vm.flags |= BC_I ? BC_FLAG_Q : 0; + #if BC_ENABLED - // bc checks this environment variable to see if it should run in standard - // mode. 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); - } -#endif // BC_ENABLED - - // Set defaults. - vm.flags |= BC_TTY ? BC_FLAG_P | BC_FLAG_R : 0; - vm.flags |= BC_I ? BC_FLAG_Q : 0; -#if BC_ENABLED - if (BC_IS_BC && BC_I) { // 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 @@ -1349,9 +1375,7 @@ void bc_vm_boot(int argc, char *argv[]) { #if BC_ENABLED // Disable global stacks in POSIX mode. 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, // and not be quieted by command-line option or environment variable. if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q)) { diff --git a/tests/bc/timeconst.sh b/tests/bc/timeconst.sh index 45e10c77bdf4..8b6e1ec596fc 100755 --- a/tests/bc/timeconst.sh +++ b/tests/bc/timeconst.sh @@ -50,7 +50,6 @@ else bc="$testdir/../../bin/bc" fi -# out1="$outputdir/bc_outputs/bc_timeconst.txt" out2="$outputdir/bc_outputs/bc_timeconst_results.txt" diff --git a/tests/history.py b/tests/history.py index 17006c93ef2d..84e32f9612c4 100755 --- a/tests/history.py +++ b/tests/history.py @@ -253,7 +253,7 @@ def test_sigint_sigquit(exe, args, env): send(child, "\t") expect(child, " ") send(child, "\x03") - send(child, "\x1c") + # send(child, "\x1c") wait(child) except pexpect.TIMEOUT: traceback.print_tb(sys.exc_info()[2]) @@ -1044,6 +1044,7 @@ dc_tests = [ test_dc_utf8_1, test_dc_utf8_2, test_dc_utf8_3, + test_dc_utf8_4, test_sigint_sigquit, test_eof, test_sigint, diff --git a/tests/history.sh b/tests/history.sh index 92db985a4f86..1898ae5499dc 100755 --- a/tests/history.sh +++ b/tests/history.sh @@ -92,7 +92,7 @@ for i in $(seq "$st" "$idx"); do 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" "$@" err="$?" diff --git a/vs/bc.vcxproj b/vs/bc.vcxproj index 19b53d66a405..6cfd7d489927 100644 --- a/vs/bc.vcxproj +++ b/vs/bc.vcxproj @@ -102,7 +102,7 @@ <ClCompile> <WarningLevel>Level3</WarningLevel> <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> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <ConformanceMode>true</ConformanceMode> @@ -123,7 +123,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <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> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <ConformanceMode>true</ConformanceMode> @@ -144,7 +144,7 @@ <ClCompile> <WarningLevel>Level3</WarningLevel> <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> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <ConformanceMode>true</ConformanceMode> @@ -164,7 +164,7 @@ <WarningLevel>Level3</WarningLevel> <IntrinsicFunctions>true</IntrinsicFunctions> <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> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> |