From 5008025c5395b2940beb54edbb60dd45db7e9c84 Mon Sep 17 00:00:00 2001 From: Gavin Howard Date: Wed, 20 Feb 2019 15:27:43 -0700 Subject: [PATCH] Add locale support This is not tested yet! --- .gitignore | 1 + Makefile.in | 23 +++++++++--- configure.sh | 41 +++++++++++++++++--- include/status.h | 48 +++++++++++------------ include/vm.h | 23 ++++++++++-- install.sh | 12 +----- locale.sh | 53 ++++++++++++++++++++++++++ locale/en.msg | 89 +++++++++++++++++++++++++++++++++++++++++++ locale/en_US.msg | 1 + release.sh | 2 +- src/data.c | 94 +++++++++++++++++++++++----------------------- src/lang.c | 6 ++- src/main.c | 4 +- src/vm.c | 37 +++++++++++++++++- tests/functions.sh | 10 +++++ 15 files changed, 342 insertions(+), 102 deletions(-) create mode 100755 locale.sh create mode 100644 locale/en.msg create mode 120000 locale/en_US.msg diff --git a/.gitignore b/.gitignore index 74024b58..9d3b2364 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ perf.data.old *.gcov *.html *.profraw +*.cat diff --git a/Makefile.in b/Makefile.in index f4f6c604..07f2012f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,6 +75,7 @@ DC_HELP_GCDA = $(GEN_DIR)/dc_help.gcda DC_HELP_GCNO = $(GEN_DIR)/dc_help.gcno BIN = bin +LOCALE = locale BC = bc DC = dc @@ -95,12 +96,16 @@ MANPAGE_INSTALL_ARGS = -Dm644 DESTDIR = %%DESTDIR%% BINDIR = %%BINDIR%% MAN1DIR = %%MAN1DIR%% +MAIN_EXEC = $(%%MAIN_EXEC%%) +EXEC = $(%%EXEC%%) +LOCALEDIR = %%LOCALEDIR%%/$(MAIN_EXEC) BC_ENABLE_SIGNALS = %%SIGNALS%% BC_ENABLE_HISTORY = %%HISTORY%% BC_ENABLE_REFERENCES = %%REFERENCES%% BC_ENABLE_EXTRA_MATH_NAME = BC_ENABLE_EXTRA_MATH BC_ENABLE_EXTRA_MATH = %%EXTRA_MATH%% +BC_ENABLE_NLS = %%NLS%% RM = rm MKDIR = mkdir @@ -109,6 +114,7 @@ INSTALL = ./install.sh SAFE_INSTALL = ./safe-install.sh LINK = ./link.sh KARATSUBA = ./karatsuba.py +LOCALE_INSTALL = ./locale.sh VALGRIND_ARGS = --error-exitcode=100 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all RONN_ARGS = --roff --organization="Gavin D. Howard" --manual="General Commands Manual" @@ -117,10 +123,10 @@ BC_NUM_KARATSUBA_LEN = %%KARATSUBA_LEN%% CPPFLAGS1 = %%CPPFLAGS%% CPPFLAGS2 = $(CPPFLAGS1) -D$(BC_ENABLED_NAME)=$(BC_ENABLED) -D$(DC_ENABLED_NAME)=$(DC_ENABLED) -CPPFLAGS3 = $(CPPFLAGS2) -I./include/ -DVERSION=$(VERSION) +CPPFLAGS3 = $(CPPFLAGS2) -I./include/ -DVERSION=$(VERSION) -DLOCALEDIR=$(LOCALEDIR) CPPFLAGS4 = $(CPPFLAGS3) -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 CPPFLAGS5 = $(CPPFLAGS4) -DBC_NUM_KARATSUBA_LEN=$(BC_NUM_KARATSUBA_LEN) -CPPFLAGS6 = $(CPPFLAGS5) -DBC_ENABLE_REFERENCES=$(BC_ENABLE_REFERENCES) +CPPFLAGS6 = $(CPPFLAGS5) -DBC_ENABLE_NLS=$(BC_ENABLE_NLS) -DBC_ENABLE_REFERENCES=$(BC_ENABLE_REFERENCES) CPPFLAGS7 = $(CPPFLAGS6) -D$(BC_ENABLE_EXTRA_MATH_NAME)=$(BC_ENABLE_EXTRA_MATH) CPPFLAGS = $(CPPFLAGS7) -DBC_ENABLE_SIGNALS=$(BC_ENABLE_SIGNALS) -DBC_ENABLE_HISTORY=$(BC_ENABLE_HISTORY) CFLAGS = $(CPPFLAGS) %%CFLAGS%% @@ -133,7 +139,7 @@ HOSTCC = %%HOSTCC%% all: make_bin $(DC_HELP_O) $(BC_HELP_O) $(BC_LIB_O) $(BC_LIB2_O) $(BC_LIB3_O) $(BC_OBJ) $(DC_OBJ) $(HISTORY_OBJ) $(OBJ) $(CC) $(CPPFLAGS) $(CFLAGS) $(OBJ) $(DC_OBJ) $(BC_OBJ) $(HISTORY_OBJ) $(BC_HELP_O) $(DC_HELP_O) \ - $(BC_LIB_O) $(BC_LIB2_O) $(BC_LIB3_O) $(LDFLAGS) -o $(%%MAIN_EXEC%%) + $(BC_LIB_O) $(BC_LIB2_O) $(BC_LIB3_O) $(LDFLAGS) -o $(EXEC) %%LINK%% $(GEN_EXEC): @@ -239,6 +245,7 @@ clean: @$(RM) -f *.html @$(RM) -f *.gcda *.gcno @$(RM) -f *.profraw + @$(RM) -f $(LOCALE)/*.cat @$(RM) -f $(GEN_EXEC) @$(RM) -f $(BC_LIB_C) $(BC_LIB_O) @$(RM) -f $(BC_LIB_GCDA) $(BC_LIB_GCNO) @@ -262,15 +269,21 @@ clean_tests: clean clean_config @$(RM) -f .math.txt .results.txt .ops.txt @$(RM) -f .test.txt +install_locales: + $(LOCALE_INSTALL) $(LOCALEDIR) + install_bc_manpage: $(SAFE_INSTALL) $(MANPAGE_INSTALL_ARGS) $(BC_MANPAGE) $(DESTDIR)$(MAN1DIR)/$(BC_MANPAGE_NAME) install_dc_manpage: $(SAFE_INSTALL) $(MANPAGE_INSTALL_ARGS) $(DC_MANPAGE) $(DESTDIR)$(MAN1DIR)/$(DC_MANPAGE_NAME) -install:%%INSTALL_PREREQS%% +install:%%INSTALL_LOCALES_PREREQS%%%%INSTALL_PREREQS%% $(INSTALL) $(DESTDIR)$(BINDIR) "$(EXEC_SUFFIX)" +uninstall_locales: + $(RM) -fr $(LOCALEDIR) + uninstall_bc_manpage: $(RM) -f $(DESTDIR)$(MAN1DIR)/$(BC_MANPAGE_NAME) @@ -283,4 +296,4 @@ uninstall_dc_manpage: uninstall_dc: $(RM) -f $(DESTDIR)$(BINDIR)/$(DC)$(EXEC_SUFFIX) -uninstall:%%UNINSTALL_MAN_PREREQS%%%%UNINSTALL_PREREQS%% +uninstall:%%UNINSTALL_LOCALES_PREREQS%%%%UNINSTALL_MAN_PREREQS%%%%UNINSTALL_PREREQS%% diff --git a/configure.sh b/configure.sh index e5f7acd4..d444aae8 100755 --- a/configure.sh +++ b/configure.sh @@ -63,6 +63,8 @@ usage() { printf ' It is an error if "-m" is specified too.\n' printf ' -M\n' printf ' Disable installing manpages.\n' + printf ' -N\n' + printf ' Disable POSIX locale (NLS) support.\n' printf ' -O OPT_LEVEL\n' printf ' Set the optimization level. This can also be included in the CFLAGS,\n' printf ' but it is provided, so maintainers can build optimized debug builds.\n' @@ -229,8 +231,9 @@ extra_math=1 optimization="" generate_tests=1 install_manpages=1 +nls=1 -while getopts "bBcdDEgGhHk:MO:RS" opt; do +while getopts "bBcdDEgGhHk:MNO:RS" opt; do case "$opt" in b) bc_only=1 ;; @@ -245,6 +248,7 @@ while getopts "bBcdDEgGhHk:MO:RS" opt; do H) hist=0 ;; k) karatsuba_len="$OPTARG" ;; M) install_manpages=0 ;; + N) nls=0 ;; O) optimization="$OPTARG" ;; R) refs=0 ;; S) signals=0 ;; @@ -273,7 +277,8 @@ script="$0" scriptdir=$(dirname "$script") link="@printf 'No link necessary\\\\n'" -main_exec="BC_EXEC" +main_exec="BC" +executable="BC_EXEC" bc_test="@tests/all.sh bc $extra_math $refs $generate_tests" dc_test="@tests/all.sh dc $extra_math $refs $generate_tests" @@ -326,7 +331,8 @@ elif [ "$dc_only" -eq 1 ]; then executables="dc" - main_exec="DC_EXEC" + main_exec="DC" + executable="DC_EXEC" bc_test="@printf 'No bc tests to run\\\\n'" vg_bc_test="@printf 'No bc tests to run\\\\n'" @@ -405,11 +411,22 @@ if [ "$BINDIR" = "" ]; then BINDIR="$PREFIX/bin" fi -if [ "$install_manpages" -ne 0 ]; then - +if [ "$install_manpages" -ne 0 -o "$nls" -ne 0 ]; then if [ "$DATAROOTDIR" = "" ]; then DATAROOTDIR="$PREFIX/share" fi +fi + +if [ "$nls" -ne 0 ]; then + LOCALEDIR="$DATAROOTDIR/locale" + install_locales_prereqs=" install_locales" + uninstall_locales_prereqs=" uninstall_locales" +else + install_locales_prereqs="" + uninstall_locales_prereqs="" +fi + +if [ "$install_manpages" -ne 0 ]; then if [ "$DATADIR" = "" ]; then DATADIR="$DATAROOTDIR" @@ -473,6 +490,13 @@ else BC_LIB2_O="" fi +# Print out the values; this is for debugging. +printf '\n' +printf 'BC_ENABLE_SIGNALS=%s\n' "$signals" +printf 'BC_ENABLE_HISTORY=%s\n' "$hist" +printf 'BC_ENABLE_REFERENCES=%s\n' "$refs" +printf 'BC_ENABLE_EXTRA_MATH=%s\n' "$extra_math" +printf 'BC_ENABLE_NLS=%s\n' "$nls" printf '\n' printf 'CC=%s\n' "$CC" printf 'CFLAGS=%s\n' "$CFLAGS" @@ -486,6 +510,7 @@ printf 'DATAROOTDIR=%s\n' "$DATAROOTDIR" printf 'DATADIR=%s\n' "$DATADIR" printf 'MANDIR=%s\n' "$MANDIR" printf 'MAN1DIR=%s\n' "$MAN1DIR" +printf 'LOCALEDIR=%s\n' "$LOCALEDIR" printf 'EXECSUFFIX=%s\n' "$EXECSUFFIX" printf 'DESTDIR=%s\n' "$DESTDIR" printf 'GEN_EMU=%s\n' "$GEN_EMU" @@ -510,12 +535,15 @@ contents=$(replace "$contents" "SIGNALS" "$signals") contents=$(replace "$contents" "HISTORY" "$hist") contents=$(replace "$contents" "REFERENCES" "$refs") contents=$(replace "$contents" "EXTRA_MATH" "$extra_math") +contents=$(replace "$contents" "NLS" "$nls") contents=$(replace "$contents" "BC_LIB_O" "$bc_lib") contents=$(replace "$contents" "BC_HELP_O" "$bc_help") contents=$(replace "$contents" "DC_HELP_O" "$dc_help") contents=$(replace "$contents" "BC_LIB2_O" "$BC_LIB2_O") contents=$(replace "$contents" "KARATSUBA_LEN" "$karatsuba_len") +contents=$(replace "$contents" "LOCALEDIR" "$LOCALEDIR") +contents=$(replace "$contents" "RELLOCALEDIR" "$RELLOCALEDIR") contents=$(replace "$contents" "DESTDIR" "$DESTDIR") contents=$(replace "$contents" "EXECSUFFIX" "$EXECSUFFIX") contents=$(replace "$contents" "BINDIR" "$BINDIR") @@ -529,11 +557,14 @@ contents=$(replace "$contents" "HOSTCC" "$HOSTCC") contents=$(replace "$contents" "COVERAGE" "$COVERAGE") contents=$(replace "$contents" "COVERAGE_PREREQS" "$COVERAGE_PREREQS") contents=$(replace "$contents" "INSTALL_PREREQS" "$install_prereqs") +contents=$(replace "$contents" "INSTALL_LOCALES_PREREQS" "$install_locales_prereqs") 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" "EXECUTABLES" "$executables") contents=$(replace "$contents" "MAIN_EXEC" "$main_exec") +contents=$(replace "$contents" "EXEC" "$executable") contents=$(replace "$contents" "BC_TEST" "$bc_test") contents=$(replace "$contents" "DC_TEST" "$dc_test") diff --git a/include/status.h b/include/status.h index 3d7a00dc..d19755a3 100644 --- a/include/status.h +++ b/include/status.h @@ -44,6 +44,26 @@ typedef enum BcError { BC_ERROR_MATH_OVERFLOW, BC_ERROR_MATH_DIVIDE_BY_ZERO, + BC_ERROR_FATAL_ALLOC_ERR, + BC_ERROR_FATAL_IO_ERR, + BC_ERROR_FATAL_FILE_ERR, + BC_ERROR_FATAL_BIN_FILE, + BC_ERROR_FATAL_PATH_DIR, + BC_ERROR_FATAL_OPTION, + + BC_ERROR_EXEC_IBASE, + BC_ERROR_EXEC_OBASE, + BC_ERROR_EXEC_SCALE, + BC_ERROR_EXEC_READ_EXPR, + BC_ERROR_EXEC_REC_READ, + BC_ERROR_EXEC_TYPE, + + BC_ERROR_EXEC_STACK, + + BC_ERROR_EXEC_PARAMS, + BC_ERROR_EXEC_UNDEF_FUNC, + BC_ERROR_EXEC_VOID_VAL, + BC_ERROR_PARSE_EOF, BC_ERROR_PARSE_CHAR, BC_ERROR_PARSE_STRING, @@ -59,9 +79,7 @@ typedef enum BcError { BC_ERROR_PARSE_DUP_LOCAL, BC_ERROR_PARSE_BLOCK, BC_ERROR_PARSE_RET_VOID, -#if BC_ENABLE_REFERENCES BC_ERROR_PARSE_REF_VAR, -#endif // BC_ENABLE_REFERENCES BC_ERROR_POSIX_NAME_LEN, BC_ERROR_POSIX_COMMENT, @@ -74,36 +92,12 @@ typedef enum BcError { BC_ERROR_POSIX_FOR1, BC_ERROR_POSIX_FOR2, BC_ERROR_POSIX_FOR3, -#if BC_ENABLE_EXTRA_MATH BC_ERROR_POSIX_EXP_NUM, -#endif // BC_ENABLE_EXTRA_MATH -#if BC_ENABLE_REFERENCES BC_ERROR_POSIX_REF, -#endif // BC_ENABLE_REFERENCES BC_ERROR_POSIX_BRACE, #endif // BC_ENABLED - BC_ERROR_EXEC_IBASE, - BC_ERROR_EXEC_OBASE, - BC_ERROR_EXEC_SCALE, - BC_ERROR_EXEC_READ_EXPR, - BC_ERROR_EXEC_REC_READ, - BC_ERROR_EXEC_TYPE, -#if DC_ENABLED - BC_ERROR_EXEC_STACK, -#endif // DC_ENABLED -#if BC_ENABLED - BC_ERROR_EXEC_PARAMS, - BC_ERROR_EXEC_UNDEF_FUNC, - BC_ERROR_EXEC_VOID_VAL, -#endif // BC_ENABLED - - BC_ERROR_FATAL_ALLOC_ERR, - BC_ERROR_FATAL_IO_ERR, - BC_ERROR_FATAL_FILE_ERR, - BC_ERROR_FATAL_BIN_FILE, - BC_ERROR_FATAL_PATH_DIR, - BC_ERROR_FATAL_OPTION, + BC_ERROR_NELEMS, #if BC_ENABLED BC_ERROR_POSIX_START = BC_ERROR_POSIX_NAME_LEN, diff --git a/include/vm.h b/include/vm.h index 62b0f170..3fc876bc 100644 --- a/include/vm.h +++ b/include/vm.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -42,9 +43,11 @@ #error CHAR_BIT must be at least 6. #endif -#define VERSION_STR(V) #V -#define VERSION_STR2(V) VERSION_STR(V) -#define BC_VERSION VERSION_STR2(VERSION) +#define GEN_STR(V) #V +#define GEN_STR2(V) GEN_STR(V) + +#define BC_VERSION GEN_STR2(VERSION) +#define BC_LOCALEDIR GEN_STR2(LOCALEDIR) // Windows has deprecated isatty(). #ifdef _WIN32 @@ -97,6 +100,12 @@ #define BC_SIGNAL (0) #endif // BC_ENABLE_SIGNALS +#if BC_ENABLE_NLS +#ifdef _WIN32 +#error NLS is not supported on Windows. +#endif // _WIN32 +#endif // BC_ENABLE_NLS + #define bc_vm_err(e) (bc_vm_error((e), 0)) #define bc_vm_verr(e, ...) (bc_vm_error((e), 0, __VA_ARGS__)) @@ -140,6 +149,14 @@ typedef struct BcVm { BcParseParse parse; BcParseExpr expr; + const char *err_msgs[BC_ERROR_NELEMS]; + + char *locale; + +#if BC_ENABLE_NLS + nl_catd catalog; +#endif // BC_ENABLE_NLS + } BcVm; #if BC_ENABLED diff --git a/install.sh b/install.sh index e90da0a7..bc1b6f2d 100755 --- a/install.sh +++ b/install.sh @@ -19,19 +19,11 @@ usage() { exit 1 } -readlink() { - - local exe="$1" - shift - - L=$(ls -dl "$exe") - - printf ${L#*-> } -} - script="$0" scriptdir=$(dirname "$script") +. "$scriptdir/tests/functions.sh" + INSTALL="$scriptdir/safe-install.sh" test "$#" -ge 2 || usage diff --git a/locale.sh b/locale.sh new file mode 100755 index 00000000..0eb2e416 --- /dev/null +++ b/locale.sh @@ -0,0 +1,53 @@ +#! /bin/sh +# +# Copyright 2018 Gavin D. Howard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +usage() { + printf "usage: %s install_dir\n" "$0" 1>&2 + exit 1 +} + +script="$0" +scriptdir=$(dirname "$script") + +. "$scriptdir/tests/functions.sh" + +INSTALL="$scriptdir/safe-install.sh" + +test "$#" -ge 1 || usage + +installdir="$1" +shift + +mkdir -p "$installdir" + +localedir="$scriptdir/locale" + +for file in $localedir/*.msg; do + + base=$(basename "$file") + name=$(echo "$base" | cut -f 1 -d '.') + f="$localedir/$name.cat" + + if [ -L "$file" ]; then + link=$(readlink "$file") + link=$(echo "$link" | cut -f 1 -d '.') + "$INSTALL" -Dlm 755 "$link.cat" "$installdir/$name.cat" + else + gencat "$f" "$file" + "$INSTALL" -Dm 755 "$f" "$installdir/$name.cat" + fi + +done diff --git a/locale/en.msg b/locale/en.msg new file mode 100644 index 00000000..5884ef4b --- /dev/null +++ b/locale/en.msg @@ -0,0 +1,89 @@ +$ $ +$ Copyright 2018 Gavin D. Howard +$ $ +$ Permission to use, copy, modify, and/or distribute this software for any +$ purpose with or without fee is hereby granted. +$ $ +$ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +$ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +$ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +$ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +$ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +$ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +$ PERFORMANCE OF THIS SOFTWARE. +$ $ + +$quote " + +$set 1 + +1 "\n%s error: " +2 "\n%s warning: " + +$set 2 + +1 "Math" +2 "Parse" +3 "Runtime" +4 "Fatal" + +$set 3 + +1 "negative number" +2 "non-integer number" +3 "overflow; number does not fit into a hardware type" +4 "divide by 0" + +$set 4 + +1 "memory allocation error" +2 "I/O error" +3 "could not open file: %s" +4 "file is not ASCII: %s" +5 "path is a directory: %s" +6 "invalid command-line option: '%c' (\"%s\")" + +$set 5 + +1 "invalid ibase; must be [%lu, %lu]" +2 "invalid obase; must be [%lu, %lu]" +3 "invalid scale; must be [%lu, %lu]" +4 "invalid read() expression" +5 "recursive read() call" +6 "variable or array element is the wrong type" +7 "stack has too few elements" +8 "wrong number of parameters; need %zu, have %zu" +9 "undefined function: %s()" +10 "cannot use a void value in an expression" + +$set 6 + +1 "end of file" +2 "invalid character (%c)" +3 "string end could not be found" +4 "comment end could not be found" +5 "invalid token" +6 "invalid expression" +7 "empty expression" +8 "invalid print statement" +9 "invalid function definition" +10 "invalid assignment: left side must be scale, ibase, obase, last, var, or array element" +11 "no auto variable found" +12 "function parameter or auto \"%s%s\" already exists" +13 "block end could not be found" +14 "cannot return a value from void function: %s()" +15 "var cannot be reference: %s" +16 "POSIX does not allow names longer than 1 character: %s" +17 "POSIX does not allow '#' script comments" +18 "POSIX does not allow the following keyword: %s" +19 "POSIX does not allow a period ('.') as a shortcut for the last result" +20 "POSIX requires parentheses around return expressions" +21 "POSIX does not allow the following operator: %s" +22 "POSIX does not allow comparison operators outside if statements or loops" +23 "POSIX requires 0 or 1 comparison operators per condition" +24 "POSIX does not allow an empty init expression in a for loop" +25 "POSIX does not allow an empty condition expression in a for loop" +26 "POSIX does not allow an empty update expression in a for loop" +27 "POSIX does not allow exponential notation" +28 "POSIX does not allow array references as function parameters" +29 "POSIX requires the left brace be on the same line as the function header" diff --git a/locale/en_US.msg b/locale/en_US.msg new file mode 120000 index 00000000..2c40330f --- /dev/null +++ b/locale/en_US.msg @@ -0,0 +1 @@ +en.msg \ No newline at end of file diff --git a/release.sh b/release.sh index b2d49724..9888afd7 100755 --- a/release.sh +++ b/release.sh @@ -313,7 +313,7 @@ build "$debug" "clang" "" header "Running math library under --standard" -echo "quit" | bin/bc -ls +printf 'quit\n' | bin/bc -ls version=$(make version) diff --git a/src/data.c b/src/data.c index 88fef71d..1c6cb77c 100644 --- a/src/data.c +++ b/src/data.c @@ -60,41 +60,59 @@ const char bc_err_ids[] = { BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, + BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, + BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, + + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, #if BC_ENABLED BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, - BC_ERR_IDX_PARSE, -#if BC_ENABLE_REFERENCES - BC_ERR_IDX_PARSE, -#endif // BC_ENABLE_REFERENCES + BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, #endif // BC_ENABLED - - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, -#if DC_ENABLED - BC_ERR_IDX_EXEC, -#endif // DC_ENABLED -#if BC_ENABLED - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, -#endif // BC_ENABLED - - BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, - BC_ERR_IDX_FATAL, BC_ERR_IDX_FATAL, }; const char* const bc_err_msgs[] = { "negative number", - "non integer number", + "non-integer number", "overflow; number cannot fit", - "divide by zero", + "divide by 0", + + "memory allocation error", + "I/O error", + "could not open file: %s", + "file is not ASCII: %s", + "path is a directory: %s", + "bad command-line option: '%c' (\"%s\")", + + "bad ibase; must be [%lu, %lu]", + "bad obase; must be [%lu, %lu]", + "bad scale; must be [%lu, %lu]", + "bad read() expression", + "read() call inside of a read() call", + "variable or array element is the wrong type", +#if DC_ENABLED + "stack has too few elements", +#else // DC_ENABLED + NULL, +#endif // DC_ENABLED +#if BC_ENABLED + "wrong number of parameters; need %zu, have %zu", + "undefined function: %s()", + "cannot use a void value in an expression", +#else + NULL, NULL, NULL +#endif // BC_ENABLED "end of file", "bad character (%c)", @@ -109,55 +127,39 @@ const char* const bc_err_msgs[] = { "bad assignment: left side must be scale, ibase, " "obase, last, var, or array element", "no auto variable found", - "function parameter or auto \"%s\" already exists", + "function parameter or auto \"%s%s\" already exists", "block end could not be found", "cannot return a value from void function: %s()", #if BC_ENABLE_REFERENCES "var cannot be reference: %s", +#else + NULL, #endif // BC_ENABLE_REFERENCES - "POSIX does not allow names longer than 1 character, like \"%s\"", + "POSIX does not allow names longer than 1 character: %s", "POSIX does not allow '#' script comments", - "POSIX does not allow \"%s\" as a keyword", + "POSIX does not allow the following keyword: %s", "POSIX does not allow a period ('.') as a shortcut for the last result", "POSIX requires parentheses around return expressions", - "POSIX does not allow the \"%s\" operators", - "POSIX does not allow comparison operators outside if or loops", - "POSIX requires zero or one comparison operator per condition", + "POSIX does not allow the following operator: %s", + "POSIX does not allow comparison operators outside if statements or loops", + "POSIX requires 0 or 1 comparison operators per condition", "POSIX does not allow an empty init expression in a for loop", "POSIX does not allow an empty condition expression in a for loop", "POSIX does not allow an empty update expression in a for loop", #if BC_ENABLE_EXTRA_MATH "POSIX does not allow exponential notation", +#else + NULL, #endif // BC_ENABLE_EXTRA_MATH #if BC_ENABLE_REFERENCES "POSIX does not allow array references as function parameters", +#else + NULL, #endif // BC_ENABLE_REFERENCES "POSIX requires the left brace be on the same line as the function header", #endif // BC_ENABLED - "bad ibase; must be [%lu, %lu]", - "bad obase; must be [%lu, %lu]", - "bad scale; must be [%lu, %lu]", - "bad read() expression", - "read() call inside of a read() call", - "variable is wrong type", -#if DC_ENABLED - "stack has too few elements", -#endif // DC_ENABLED -#if BC_ENABLED - "mismatched parameters; need %zu, have %zu", - "undefined function: %s()", - "cannot use a void value in an expression", -#endif // BC_ENABLED - - "memory allocation error", - "I/O error", - "could not open file: %s", - "file is not ASCII: %s", - "path is a directory: %s", - "Bad command-line option: '%c' (\"%s\")", - }; #if BC_ENABLE_HISTORY diff --git a/src/lang.c b/src/lang.c index 27572c5d..446bd96e 100644 --- a/src/lang.c +++ b/src/lang.c @@ -51,8 +51,10 @@ BcStatus bc_func_insert(BcFunc *f, char *name, BcType type, size_t line) { for (i = 0; i < f->autos.len; ++i) { BcId *id = bc_vec_item(&f->autos, i); - if (!strcmp(name, id->name) && type == (BcType) id->idx) - return bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name); + if (!strcmp(name, id->name) && type == (BcType) id->idx) { + const char *array = type == BC_TYPE_ARRAY ? "[]" : ""; + return bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name, array); + } } a.idx = type; diff --git a/src/main.c b/src/main.c index 88c08635..94283a66 100644 --- a/src/main.c +++ b/src/main.c @@ -38,11 +38,11 @@ int main(int argc, char *argv[]) { int s; char *name; - setlocale(LC_ALL, ""); - vm = calloc(1, sizeof(BcVm)); if (!vm) return (int) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR); + vm->locale = setlocale(LC_ALL, ""); + name = strrchr(argv[0], '/'); vm->name = !name ? argv[0] : name + 1; diff --git a/src/vm.c b/src/vm.c index f6225b93..6bf09e25 100644 --- a/src/vm.c +++ b/src/vm.c @@ -83,7 +83,7 @@ static BcStatus bc_vm_printError(BcError e, const char* const fmt, fflush(stdout); fprintf(stderr, fmt, bc_errs[id]); - vfprintf(stderr, bc_err_msgs[e], args); + vfprintf(stderr, vm->err_msgs[e], args); assert(vm->file); @@ -202,6 +202,9 @@ static size_t bc_vm_envLen(const char *var) { } void bc_vm_shutdown(void) { +#if BC_ENABLE_NLS + catclose(vm->catalog); +#endif // BC_ENABLE_NLS #if BC_ENABLE_HISTORY // This must always run to ensure that the terminal is back to normal. bc_history_free(&vm->history); @@ -512,6 +515,7 @@ static BcStatus bc_vm_exec(void) { BcStatus bc_vm_boot(int argc, char *argv[], const char *env_len) { BcStatus s; + int i; #if BC_ENABLE_SIGNALS #ifndef _WIN32 struct sigaction sa; @@ -527,6 +531,37 @@ BcStatus bc_vm_boot(int argc, char *argv[], const char *env_len) { #endif // _WIN32 #endif // BC_ENABLE_SIGNALS +#if BC_ENABLE_NLS + { + BcVec dir; + char *dot; + + bc_vec_init(&dir, sizeof(char), NULL); + + bc_vec_string(&dir, strlen(BC_LOCALEDIR), BC_LOCALEDIR); + bc_vec_concat(&dir, "/"); + bc_vec_concat(&dir, vm->locale); + + dot = strrchr(dir.v, '.'); + + if (dot) { + uintptr_t idx = ((uintptr_t) dot) - ((uintptr_t) dir.v); + bc_vec_npop(&dir, dir.len - idx); + bc_vec_pushByte(&dir, '\0'); + } + + vm->catalog = catopen(dir.v, NL_CAT_LOCALE); + + for (i = 0; i < BC_ERROR_NELEMS; ++i) + vm->err_msgs[i] = catgets(vm->catalog, NL_SETD, i + 1, bc_err_msgs[i]); + + bc_vec_free(&dir); + } +#else // BC_ENABLE_NLS + for (i = 0; i < BC_ERROR_NELEMS; ++i) + vm->err_msgs[i] = bc_err_msgs[i]; +#endif // BC_ENABLE_NLS + vm->line_len = (uint16_t) bc_vm_envLen(env_len); bc_vec_init(&vm->files, sizeof(char*), NULL); diff --git a/tests/functions.sh b/tests/functions.sh index dc900fba..ce672e80 100644 --- a/tests/functions.sh +++ b/tests/functions.sh @@ -14,6 +14,16 @@ # PERFORMANCE OF THIS SOFTWARE. # +readlink() { + + local exe="$1" + shift + + L=$(ls -dl "$exe") + + printf ${L#*-> } +} + die() { local d="$1"