Browse Source

Add locale support

This is not tested yet!
signals
Gavin Howard 3 years ago
parent
commit
5008025c53
Signed by untrusted user who does not match committer: gavin
GPG Key ID: C08038BDF280D33E
  1. 1
      .gitignore
  2. 23
      Makefile.in
  3. 41
      configure.sh
  4. 48
      include/status.h
  5. 23
      include/vm.h
  6. 12
      install.sh
  7. 53
      locale.sh
  8. 89
      locale/en.msg
  9. 1
      locale/en_US.msg
  10. 2
      release.sh
  11. 94
      src/data.c
  12. 6
      src/lang.c
  13. 4
      src/main.c
  14. 37
      src/vm.c
  15. 10
      tests/functions.sh

1
.gitignore vendored

@ -39,3 +39,4 @@ perf.data.old
*.gcov
*.html
*.profraw
*.cat

23
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%%

41
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")

48
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,

23
include/vm.h

@ -27,6 +27,7 @@
#include <limits.h>
#include <signal.h>
#include <nl_types.h>
#include <status.h>
#include <parse.h>
@ -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

12
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

53
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

89
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"

1
locale/en_US.msg

@ -0,0 +1 @@
en.msg

2
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)

94
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

6
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;

4
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;

37
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);

10
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"

Loading…
Cancel
Save