xref: /freebsd/contrib/bc/include/status.h (revision 44d4804d)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
610328f8bSStefan Eßer  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
3244d4804dSStefan Eßer  * All bc status codes and cross-platform portability.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_STATUS_H
37252884aeSStefan Eßer #define BC_STATUS_H
38252884aeSStefan Eßer 
39252884aeSStefan Eßer #include <stdint.h>
40252884aeSStefan Eßer 
4144d4804dSStefan Eßer // This is used by configure.sh to test for OpenBSD.
4244d4804dSStefan Eßer #ifdef BC_TEST_OPENBSD
4344d4804dSStefan Eßer #ifdef __OpenBSD__
4444d4804dSStefan Eßer #error On OpenBSD without _BSD_SOURCE
4544d4804dSStefan Eßer #endif // __OpenBSD__
4644d4804dSStefan Eßer #endif // BC_TEST_OPENBSD
4744d4804dSStefan Eßer 
48252884aeSStefan Eßer #ifndef BC_ENABLED
49252884aeSStefan Eßer #define BC_ENABLED (1)
50252884aeSStefan Eßer #endif // BC_ENABLED
51252884aeSStefan Eßer 
52252884aeSStefan Eßer #ifndef DC_ENABLED
53252884aeSStefan Eßer #define DC_ENABLED (1)
54252884aeSStefan Eßer #endif // DC_ENABLED
55252884aeSStefan Eßer 
5644d4804dSStefan Eßer // This is error checking for fuzz builds.
5710328f8bSStefan Eßer #if BC_ENABLE_AFL
5810328f8bSStefan Eßer #ifndef __AFL_HAVE_MANUAL_CONTROL
5944d4804dSStefan Eßer #error Must compile with afl-clang-fast or afl-clang-lto for fuzzing
6010328f8bSStefan Eßer #endif // __AFL_HAVE_MANUAL_CONTROL
6110328f8bSStefan Eßer #endif // BC_ENABLE_AFL
6210328f8bSStefan Eßer 
6310328f8bSStefan Eßer #ifndef BC_ENABLE_MEMCHECK
6410328f8bSStefan Eßer #define BC_ENABLE_MEMCHECK (0)
6510328f8bSStefan Eßer #endif // BC_ENABLE_MEMCHECK
6610328f8bSStefan Eßer 
6744d4804dSStefan Eßer /**
6844d4804dSStefan Eßer  * Mark a variable as unused.
6944d4804dSStefan Eßer  * @param e  The variable to mark as unused.
7044d4804dSStefan Eßer  */
7144d4804dSStefan Eßer #define BC_UNUSED(e) ((void) (e))
7244d4804dSStefan Eßer 
7344d4804dSStefan Eßer // If users want, they can define this to something like __builtin_expect(e, 1).
7444d4804dSStefan Eßer // It might give a performance improvement.
7544d4804dSStefan Eßer #ifndef BC_LIKELY
7644d4804dSStefan Eßer 
7744d4804dSStefan Eßer /**
7844d4804dSStefan Eßer  * Mark a branch expression as likely.
7944d4804dSStefan Eßer  * @param e  The expression to mark as likely.
8044d4804dSStefan Eßer  */
8144d4804dSStefan Eßer #define BC_LIKELY(e) (e)
8244d4804dSStefan Eßer 
8344d4804dSStefan Eßer #endif // BC_LIKELY
8444d4804dSStefan Eßer 
8544d4804dSStefan Eßer // If users want, they can define this to something like __builtin_expect(e, 0).
8644d4804dSStefan Eßer // It might give a performance improvement.
8744d4804dSStefan Eßer #ifndef BC_UNLIKELY
8844d4804dSStefan Eßer 
8944d4804dSStefan Eßer /**
9044d4804dSStefan Eßer  * Mark a branch expression as unlikely.
9144d4804dSStefan Eßer  * @param e  The expression to mark as unlikely.
9244d4804dSStefan Eßer  */
9344d4804dSStefan Eßer #define BC_UNLIKELY(e) (e)
9444d4804dSStefan Eßer 
9544d4804dSStefan Eßer #endif // BC_UNLIKELY
9644d4804dSStefan Eßer 
9744d4804dSStefan Eßer /**
9844d4804dSStefan Eßer  * Mark a branch expression as an error, if true.
9944d4804dSStefan Eßer  * @param e  The expression to mark as an error, if true.
10044d4804dSStefan Eßer  */
10144d4804dSStefan Eßer #define BC_ERR(e) BC_UNLIKELY(e)
10244d4804dSStefan Eßer 
10344d4804dSStefan Eßer /**
10444d4804dSStefan Eßer  * Mark a branch expression as not an error, if true.
10544d4804dSStefan Eßer  * @param e  The expression to mark as not an error, if true.
10644d4804dSStefan Eßer  */
10744d4804dSStefan Eßer #define BC_NO_ERR(s) BC_LIKELY(s)
10844d4804dSStefan Eßer 
10944d4804dSStefan Eßer // Disable extra debug code by default.
11044d4804dSStefan Eßer #ifndef BC_DEBUG_CODE
11144d4804dSStefan Eßer #define BC_DEBUG_CODE (0)
11244d4804dSStefan Eßer #endif // BC_DEBUG_CODE
11344d4804dSStefan Eßer 
11444d4804dSStefan Eßer // We want to be able to use _Noreturn on C11 compilers.
11544d4804dSStefan Eßer #if __STDC_VERSION__ >= 201100L
11644d4804dSStefan Eßer 
11744d4804dSStefan Eßer #include <stdnoreturn.h>
11844d4804dSStefan Eßer #define BC_NORETURN _Noreturn
11944d4804dSStefan Eßer #define BC_C11 (1)
12044d4804dSStefan Eßer 
12144d4804dSStefan Eßer #else // __STDC_VERSION__
12244d4804dSStefan Eßer 
12344d4804dSStefan Eßer #define BC_NORETURN
12444d4804dSStefan Eßer #define BC_MUST_RETURN
12544d4804dSStefan Eßer #define BC_C11 (0)
12644d4804dSStefan Eßer 
12744d4804dSStefan Eßer #endif // __STDC_VERSION__
12844d4804dSStefan Eßer 
12944d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (0)
13044d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (0)
13144d4804dSStefan Eßer 
13244d4804dSStefan Eßer // GCC and Clang complain if fallthroughs are not marked with their special
13344d4804dSStefan Eßer // attribute. Jerks. This creates a define for marking the fallthroughs that is
13444d4804dSStefan Eßer // nothing on other compilers.
13544d4804dSStefan Eßer #if defined(__clang__) || defined(__GNUC__)
13644d4804dSStefan Eßer 
13744d4804dSStefan Eßer #if defined(__has_attribute)
13844d4804dSStefan Eßer 
13944d4804dSStefan Eßer #if __has_attribute(fallthrough)
14044d4804dSStefan Eßer #define BC_FALLTHROUGH __attribute__((fallthrough));
14144d4804dSStefan Eßer #else // __has_attribute(fallthrough)
14244d4804dSStefan Eßer #define BC_FALLTHROUGH
14344d4804dSStefan Eßer #endif // __has_attribute(fallthrough)
14444d4804dSStefan Eßer 
14544d4804dSStefan Eßer #ifdef __GNUC__
14644d4804dSStefan Eßer 
14744d4804dSStefan Eßer #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
14844d4804dSStefan Eßer #undef BC_HAS_UNREACHABLE
14944d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (1)
15044d4804dSStefan Eßer #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
15144d4804dSStefan Eßer 
15244d4804dSStefan Eßer #else // __GNUC__
15344d4804dSStefan Eßer 
15444d4804dSStefan Eßer #if __clang_major__ >= 4
15544d4804dSStefan Eßer #undef BC_HAS_UNREACHABLE
15644d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (1)
15744d4804dSStefan Eßer #endif // __clang_major__ >= 4
15844d4804dSStefan Eßer 
15944d4804dSStefan Eßer #endif // __GNUC__
16044d4804dSStefan Eßer 
16144d4804dSStefan Eßer #else // defined(__has_attribute)
16244d4804dSStefan Eßer #define BC_FALLTHROUGH
16344d4804dSStefan Eßer #endif // defined(__has_attribute)
16444d4804dSStefan Eßer #else // defined(__clang__) || defined(__GNUC__)
16544d4804dSStefan Eßer #define BC_FALLTHROUGH
16644d4804dSStefan Eßer #endif // defined(__clang__) || defined(__GNUC__)
16744d4804dSStefan Eßer 
16844d4804dSStefan Eßer #if BC_HAS_UNREACHABLE
16944d4804dSStefan Eßer 
17044d4804dSStefan Eßer #define BC_UNREACHABLE __builtin_unreachable();
17144d4804dSStefan Eßer 
17244d4804dSStefan Eßer #else // BC_HAS_UNREACHABLE
17344d4804dSStefan Eßer 
17444d4804dSStefan Eßer #ifdef _WIN32
17544d4804dSStefan Eßer 
17644d4804dSStefan Eßer #define BC_UNREACHABLE __assume(0);
17744d4804dSStefan Eßer 
17844d4804dSStefan Eßer #else // _WIN32
17944d4804dSStefan Eßer 
18044d4804dSStefan Eßer #define BC_UNREACHABLE
18144d4804dSStefan Eßer 
18244d4804dSStefan Eßer #endif // _WIN32
18344d4804dSStefan Eßer 
18444d4804dSStefan Eßer #endif // BC_HAS_UNREACHABLE
18544d4804dSStefan Eßer 
18644d4804dSStefan Eßer #ifdef __GNUC__
18744d4804dSStefan Eßer 
18844d4804dSStefan Eßer #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
18944d4804dSStefan Eßer 
19044d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO
19144d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (1)
19244d4804dSStefan Eßer 
19344d4804dSStefan Eßer #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
19444d4804dSStefan Eßer 
19544d4804dSStefan Eßer #endif // __GNUC__
19644d4804dSStefan Eßer 
19744d4804dSStefan Eßer #ifdef __clang__
19844d4804dSStefan Eßer 
19944d4804dSStefan Eßer #if __clang_major__ >= 4
20044d4804dSStefan Eßer 
20144d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO
20244d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (1)
20344d4804dSStefan Eßer 
20444d4804dSStefan Eßer #endif // __clang_major__ >= 4
20544d4804dSStefan Eßer 
20644d4804dSStefan Eßer #endif // __GNUC__
20744d4804dSStefan Eßer 
20844d4804dSStefan Eßer #ifdef BC_NO_COMPUTED_GOTO
20944d4804dSStefan Eßer 
21044d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO
21144d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (0)
21244d4804dSStefan Eßer 
21344d4804dSStefan Eßer #endif // BC_NO_COMPUTED_GOTO
21444d4804dSStefan Eßer 
21544d4804dSStefan Eßer #ifdef __GNUC__
21644d4804dSStefan Eßer #ifdef __OpenBSD__
21744d4804dSStefan Eßer // The OpenBSD GCC doesn't like inline.
21844d4804dSStefan Eßer #define inline
21944d4804dSStefan Eßer #endif // __OpenBSD__
22044d4804dSStefan Eßer #endif // __GNUC__
22144d4804dSStefan Eßer 
22244d4804dSStefan Eßer // Workarounds for AIX's POSIX incompatibility.
22344d4804dSStefan Eßer #ifndef SIZE_MAX
22444d4804dSStefan Eßer #define SIZE_MAX __SIZE_MAX__
22544d4804dSStefan Eßer #endif // SIZE_MAX
22644d4804dSStefan Eßer #ifndef UINTMAX_C
22744d4804dSStefan Eßer #define UINTMAX_C __UINTMAX_C
22844d4804dSStefan Eßer #endif // UINTMAX_C
22944d4804dSStefan Eßer #ifndef UINT32_C
23044d4804dSStefan Eßer #define UINT32_C __UINT32_C
23144d4804dSStefan Eßer #endif // UINT32_C
23244d4804dSStefan Eßer #ifndef UINT_FAST32_MAX
23344d4804dSStefan Eßer #define UINT_FAST32_MAX __UINT_FAST32_MAX__
23444d4804dSStefan Eßer #endif // UINT_FAST32_MAX
23544d4804dSStefan Eßer #ifndef UINT16_MAX
23644d4804dSStefan Eßer #define UINT16_MAX __UINT16_MAX__
23744d4804dSStefan Eßer #endif // UINT16_MAX
23844d4804dSStefan Eßer #ifndef SIG_ATOMIC_MAX
23944d4804dSStefan Eßer #define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
24044d4804dSStefan Eßer #endif // SIG_ATOMIC_MAX
24144d4804dSStefan Eßer 
24244d4804dSStefan Eßer // Yes, this has to be here.
24350696a6eSStefan Eßer #include <bcl.h>
24450696a6eSStefan Eßer 
24544d4804dSStefan Eßer // All of these set defaults for settings.
24644d4804dSStefan Eßer 
24744d4804dSStefan Eßer #if BC_ENABLED
24844d4804dSStefan Eßer 
24944d4804dSStefan Eßer #ifndef BC_DEFAULT_BANNER
25044d4804dSStefan Eßer #define BC_DEFAULT_BANNER (0)
25144d4804dSStefan Eßer #endif // BC_DEFAULT_BANNER
25244d4804dSStefan Eßer 
25344d4804dSStefan Eßer #endif // BC_ENABLED
25444d4804dSStefan Eßer 
25544d4804dSStefan Eßer #ifndef BC_DEFAULT_SIGINT_RESET
25644d4804dSStefan Eßer #define BC_DEFAULT_SIGINT_RESET (1)
25744d4804dSStefan Eßer #endif // BC_DEFAULT_SIGINT_RESET
25844d4804dSStefan Eßer 
25944d4804dSStefan Eßer #ifndef BC_DEFAULT_TTY_MODE
26044d4804dSStefan Eßer #define BC_DEFAULT_TTY_MODE (1)
26144d4804dSStefan Eßer #endif // BC_DEFAULT_TTY_MODE
26244d4804dSStefan Eßer 
26344d4804dSStefan Eßer #ifndef BC_DEFAULT_PROMPT
26444d4804dSStefan Eßer #define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE
26544d4804dSStefan Eßer #endif // BC_DEFAULT_PROMPT
26644d4804dSStefan Eßer 
26744d4804dSStefan Eßer // All of these set defaults for settings.
26844d4804dSStefan Eßer #ifndef DC_DEFAULT_SIGINT_RESET
26944d4804dSStefan Eßer #define DC_DEFAULT_SIGINT_RESET (1)
27044d4804dSStefan Eßer #endif // DC_DEFAULT_SIGINT_RESET
27144d4804dSStefan Eßer 
27244d4804dSStefan Eßer #ifndef DC_DEFAULT_TTY_MODE
27344d4804dSStefan Eßer #define DC_DEFAULT_TTY_MODE (0)
27444d4804dSStefan Eßer #endif // DC_DEFAULT_TTY_MODE
27544d4804dSStefan Eßer 
27644d4804dSStefan Eßer #ifndef DC_DEFAULT_HISTORY
27744d4804dSStefan Eßer #define DC_DEFAULT_HISTORY DC_DEFAULT_TTY_MODE
27844d4804dSStefan Eßer #endif // DC_DEFAULT_HISTORY
27944d4804dSStefan Eßer 
28044d4804dSStefan Eßer #ifndef DC_DEFAULT_PROMPT
28144d4804dSStefan Eßer #define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE
28244d4804dSStefan Eßer #endif // DC_DEFAULT_PROMPT
28344d4804dSStefan Eßer 
28444d4804dSStefan Eßer /// Statuses, which mark either which category of error happened, or some other
28544d4804dSStefan Eßer /// status that matters.
286252884aeSStefan Eßer typedef enum BcStatus {
287252884aeSStefan Eßer 
28844d4804dSStefan Eßer 	/// Normal status.
289252884aeSStefan Eßer 	BC_STATUS_SUCCESS = 0,
29044d4804dSStefan Eßer 
29144d4804dSStefan Eßer 	/// Math error.
292252884aeSStefan Eßer 	BC_STATUS_ERROR_MATH,
29344d4804dSStefan Eßer 
29444d4804dSStefan Eßer 	/// Parse (and lex) error.
295252884aeSStefan Eßer 	BC_STATUS_ERROR_PARSE,
29644d4804dSStefan Eßer 
29744d4804dSStefan Eßer 	/// Runtime error.
298252884aeSStefan Eßer 	BC_STATUS_ERROR_EXEC,
29944d4804dSStefan Eßer 
30044d4804dSStefan Eßer 	/// Fatal error.
301252884aeSStefan Eßer 	BC_STATUS_ERROR_FATAL,
30244d4804dSStefan Eßer 
30344d4804dSStefan Eßer 	/// EOF status.
304252884aeSStefan Eßer 	BC_STATUS_EOF,
30544d4804dSStefan Eßer 
30644d4804dSStefan Eßer 	/// Quit status. This means that bc/dc is in the process of quitting.
307252884aeSStefan Eßer 	BC_STATUS_QUIT,
308252884aeSStefan Eßer 
309252884aeSStefan Eßer } BcStatus;
310252884aeSStefan Eßer 
31144d4804dSStefan Eßer /// Errors, which are more specific errors.
31250696a6eSStefan Eßer typedef enum BcErr {
313252884aeSStefan Eßer 
31444d4804dSStefan Eßer 	// Math errors.
31544d4804dSStefan Eßer 
31644d4804dSStefan Eßer 	/// Negative number used when not allowed.
31750696a6eSStefan Eßer 	BC_ERR_MATH_NEGATIVE,
31844d4804dSStefan Eßer 
31944d4804dSStefan Eßer 	/// Non-integer used when not allowed.
32050696a6eSStefan Eßer 	BC_ERR_MATH_NON_INTEGER,
32144d4804dSStefan Eßer 
32244d4804dSStefan Eßer 	/// Conversion to a hardware integer would overflow.
32350696a6eSStefan Eßer 	BC_ERR_MATH_OVERFLOW,
32444d4804dSStefan Eßer 
32544d4804dSStefan Eßer 	/// Divide by zero.
32650696a6eSStefan Eßer 	BC_ERR_MATH_DIVIDE_BY_ZERO,
327252884aeSStefan Eßer 
32844d4804dSStefan Eßer 	// Fatal errors.
32944d4804dSStefan Eßer 
33044d4804dSStefan Eßer 	/// An allocation or reallocation failed.
33150696a6eSStefan Eßer 	BC_ERR_FATAL_ALLOC_ERR,
33244d4804dSStefan Eßer 
33344d4804dSStefan Eßer 	/// I/O failure.
33450696a6eSStefan Eßer 	BC_ERR_FATAL_IO_ERR,
33544d4804dSStefan Eßer 
33644d4804dSStefan Eßer 	/// File error, such as permissions or file does not exist.
33750696a6eSStefan Eßer 	BC_ERR_FATAL_FILE_ERR,
33844d4804dSStefan Eßer 
33944d4804dSStefan Eßer 	/// File is binary, not text, error.
34050696a6eSStefan Eßer 	BC_ERR_FATAL_BIN_FILE,
34144d4804dSStefan Eßer 
34244d4804dSStefan Eßer 	/// Attempted to read a directory as a file error.
34350696a6eSStefan Eßer 	BC_ERR_FATAL_PATH_DIR,
34444d4804dSStefan Eßer 
34544d4804dSStefan Eßer 	/// Invalid option error.
34650696a6eSStefan Eßer 	BC_ERR_FATAL_OPTION,
34744d4804dSStefan Eßer 
34844d4804dSStefan Eßer 	/// Option with required argument not given an argument.
34950696a6eSStefan Eßer 	BC_ERR_FATAL_OPTION_NO_ARG,
35044d4804dSStefan Eßer 
35144d4804dSStefan Eßer 	/// Option with no argument given an argument.
35250696a6eSStefan Eßer 	BC_ERR_FATAL_OPTION_ARG,
353252884aeSStefan Eßer 
35444d4804dSStefan Eßer 	/// Option argument is invalid.
35544d4804dSStefan Eßer 	BC_ERR_FATAL_ARG,
35644d4804dSStefan Eßer 
35744d4804dSStefan Eßer 	// Runtime errors.
35844d4804dSStefan Eßer 
35944d4804dSStefan Eßer 	/// Invalid ibase value.
36050696a6eSStefan Eßer 	BC_ERR_EXEC_IBASE,
36144d4804dSStefan Eßer 
36244d4804dSStefan Eßer 	/// Invalid obase value.
36350696a6eSStefan Eßer 	BC_ERR_EXEC_OBASE,
36444d4804dSStefan Eßer 
36544d4804dSStefan Eßer 	/// Invalid scale value.
36650696a6eSStefan Eßer 	BC_ERR_EXEC_SCALE,
36744d4804dSStefan Eßer 
36844d4804dSStefan Eßer 	/// Invalid expression parsed by read().
36950696a6eSStefan Eßer 	BC_ERR_EXEC_READ_EXPR,
37044d4804dSStefan Eßer 
37144d4804dSStefan Eßer 	/// read() used within an expression given to a read() call.
37250696a6eSStefan Eßer 	BC_ERR_EXEC_REC_READ,
37344d4804dSStefan Eßer 
37444d4804dSStefan Eßer 	/// Type error.
37550696a6eSStefan Eßer 	BC_ERR_EXEC_TYPE,
376252884aeSStefan Eßer 
37744d4804dSStefan Eßer 	/// Stack has too few elements error.
37850696a6eSStefan Eßer 	BC_ERR_EXEC_STACK,
379252884aeSStefan Eßer 
38044d4804dSStefan Eßer 	/// Register stack has too few elements error.
38144d4804dSStefan Eßer 	BC_ERR_EXEC_STACK_REGISTER,
38244d4804dSStefan Eßer 
38344d4804dSStefan Eßer 	/// Wrong number of arguments error.
38450696a6eSStefan Eßer 	BC_ERR_EXEC_PARAMS,
38544d4804dSStefan Eßer 
38644d4804dSStefan Eßer 	/// Undefined function error.
38750696a6eSStefan Eßer 	BC_ERR_EXEC_UNDEF_FUNC,
38844d4804dSStefan Eßer 
38944d4804dSStefan Eßer 	/// Void value used in an expression error.
39050696a6eSStefan Eßer 	BC_ERR_EXEC_VOID_VAL,
391252884aeSStefan Eßer 
39244d4804dSStefan Eßer 	// Parse (and lex errors).
39344d4804dSStefan Eßer 
39444d4804dSStefan Eßer 	/// EOF encountered when not expected error.
39550696a6eSStefan Eßer 	BC_ERR_PARSE_EOF,
39644d4804dSStefan Eßer 
39744d4804dSStefan Eßer 	/// Invalid character error.
39850696a6eSStefan Eßer 	BC_ERR_PARSE_CHAR,
39944d4804dSStefan Eßer 
40044d4804dSStefan Eßer 	/// Invalid string (no ending quote) error.
40150696a6eSStefan Eßer 	BC_ERR_PARSE_STRING,
40244d4804dSStefan Eßer 
40344d4804dSStefan Eßer 	/// Invalid comment (no end found) error.
40450696a6eSStefan Eßer 	BC_ERR_PARSE_COMMENT,
40544d4804dSStefan Eßer 
40644d4804dSStefan Eßer 	/// Invalid token encountered error.
40750696a6eSStefan Eßer 	BC_ERR_PARSE_TOKEN,
40844d4804dSStefan Eßer 
409252884aeSStefan Eßer #if BC_ENABLED
41044d4804dSStefan Eßer 
41144d4804dSStefan Eßer 	/// Invalid expression error.
41250696a6eSStefan Eßer 	BC_ERR_PARSE_EXPR,
41344d4804dSStefan Eßer 
41444d4804dSStefan Eßer 	/// Expression is empty error.
41550696a6eSStefan Eßer 	BC_ERR_PARSE_EMPTY_EXPR,
41644d4804dSStefan Eßer 
41744d4804dSStefan Eßer 	/// Print statement is invalid error.
41850696a6eSStefan Eßer 	BC_ERR_PARSE_PRINT,
41944d4804dSStefan Eßer 
42044d4804dSStefan Eßer 	/// Function definition is invalid error.
42150696a6eSStefan Eßer 	BC_ERR_PARSE_FUNC,
42244d4804dSStefan Eßer 
42344d4804dSStefan Eßer 	/// Assignment is invalid error.
42450696a6eSStefan Eßer 	BC_ERR_PARSE_ASSIGN,
42544d4804dSStefan Eßer 
42644d4804dSStefan Eßer 	/// No auto identifiers given for an auto statement error.
42750696a6eSStefan Eßer 	BC_ERR_PARSE_NO_AUTO,
42844d4804dSStefan Eßer 
42944d4804dSStefan Eßer 	/// Duplicate local (parameter or auto) error.
43050696a6eSStefan Eßer 	BC_ERR_PARSE_DUP_LOCAL,
43144d4804dSStefan Eßer 
43244d4804dSStefan Eßer 	/// Invalid block (within braces) error.
43350696a6eSStefan Eßer 	BC_ERR_PARSE_BLOCK,
43444d4804dSStefan Eßer 
43544d4804dSStefan Eßer 	/// Invalid return statement for void functions.
43650696a6eSStefan Eßer 	BC_ERR_PARSE_RET_VOID,
43744d4804dSStefan Eßer 
43844d4804dSStefan Eßer 	/// Reference attached to a variable, not an array, error.
43950696a6eSStefan Eßer 	BC_ERR_PARSE_REF_VAR,
440252884aeSStefan Eßer 
44144d4804dSStefan Eßer 	// POSIX-only errors.
44244d4804dSStefan Eßer 
44344d4804dSStefan Eßer 	/// Name length greater than 1 error.
44450696a6eSStefan Eßer 	BC_ERR_POSIX_NAME_LEN,
44544d4804dSStefan Eßer 
44644d4804dSStefan Eßer 	/// Non-POSIX comment used error.
44750696a6eSStefan Eßer 	BC_ERR_POSIX_COMMENT,
44844d4804dSStefan Eßer 
44944d4804dSStefan Eßer 	/// Non-POSIX keyword error.
45050696a6eSStefan Eßer 	BC_ERR_POSIX_KW,
45144d4804dSStefan Eßer 
45244d4804dSStefan Eßer 	/// Non-POSIX . (last) error.
45350696a6eSStefan Eßer 	BC_ERR_POSIX_DOT,
45444d4804dSStefan Eßer 
45544d4804dSStefan Eßer 	/// Non-POSIX return error.
45650696a6eSStefan Eßer 	BC_ERR_POSIX_RET,
45744d4804dSStefan Eßer 
45844d4804dSStefan Eßer 	/// Non-POSIX boolean operator used error.
45950696a6eSStefan Eßer 	BC_ERR_POSIX_BOOL,
46044d4804dSStefan Eßer 
46144d4804dSStefan Eßer 	/// POSIX relation operator used outside if, while, or for statements error.
46250696a6eSStefan Eßer 	BC_ERR_POSIX_REL_POS,
46344d4804dSStefan Eßer 
46444d4804dSStefan Eßer 	/// Multiple POSIX relation operators used in an if, while, or for statement
46544d4804dSStefan Eßer 	/// error.
46650696a6eSStefan Eßer 	BC_ERR_POSIX_MULTIREL,
46744d4804dSStefan Eßer 
46844d4804dSStefan Eßer 	/// Empty statements in POSIX for loop error.
46950696a6eSStefan Eßer 	BC_ERR_POSIX_FOR,
47044d4804dSStefan Eßer 
47144d4804dSStefan Eßer 	/// Non-POSIX exponential (scientific or engineering) number used error.
47250696a6eSStefan Eßer 	BC_ERR_POSIX_EXP_NUM,
47344d4804dSStefan Eßer 
47444d4804dSStefan Eßer 	/// Non-POSIX array reference error.
47550696a6eSStefan Eßer 	BC_ERR_POSIX_REF,
47644d4804dSStefan Eßer 
47744d4804dSStefan Eßer 	/// Non-POSIX void error.
47850696a6eSStefan Eßer 	BC_ERR_POSIX_VOID,
47944d4804dSStefan Eßer 
48044d4804dSStefan Eßer 	/// Non-POSIX brace position used error.
48150696a6eSStefan Eßer 	BC_ERR_POSIX_BRACE,
48244d4804dSStefan Eßer 
48344d4804dSStefan Eßer 	/// String used in expression.
48444d4804dSStefan Eßer 	BC_ERR_POSIX_EXPR_STRING,
48544d4804dSStefan Eßer 
486252884aeSStefan Eßer #endif // BC_ENABLED
487252884aeSStefan Eßer 
48844d4804dSStefan Eßer 	// Number of elements.
48950696a6eSStefan Eßer 	BC_ERR_NELEMS,
490252884aeSStefan Eßer 
491252884aeSStefan Eßer #if BC_ENABLED
49244d4804dSStefan Eßer 
49344d4804dSStefan Eßer 	/// A marker for the start of POSIX errors.
49450696a6eSStefan Eßer 	BC_ERR_POSIX_START = BC_ERR_POSIX_NAME_LEN,
49544d4804dSStefan Eßer 
49644d4804dSStefan Eßer 	/// A marker for the end of POSIX errors.
49744d4804dSStefan Eßer 	BC_ERR_POSIX_END = BC_ERR_POSIX_EXPR_STRING,
49844d4804dSStefan Eßer 
499252884aeSStefan Eßer #endif // BC_ENABLED
500252884aeSStefan Eßer 
50150696a6eSStefan Eßer } BcErr;
502252884aeSStefan Eßer 
50344d4804dSStefan Eßer // The indices of each category of error in bc_errs[], and used in bc_err_ids[]
50444d4804dSStefan Eßer // to associate actual errors with their categories.
50544d4804dSStefan Eßer 
50644d4804dSStefan Eßer /// Math error category.
507252884aeSStefan Eßer #define BC_ERR_IDX_MATH (0)
50844d4804dSStefan Eßer 
50944d4804dSStefan Eßer /// Parse (and lex) error category.
510252884aeSStefan Eßer #define BC_ERR_IDX_PARSE (1)
51144d4804dSStefan Eßer 
51244d4804dSStefan Eßer /// Runtime error category.
513252884aeSStefan Eßer #define BC_ERR_IDX_EXEC (2)
51444d4804dSStefan Eßer 
51544d4804dSStefan Eßer /// Fatal error category.
516252884aeSStefan Eßer #define BC_ERR_IDX_FATAL (3)
51744d4804dSStefan Eßer 
51844d4804dSStefan Eßer /// Number of categories.
519252884aeSStefan Eßer #define BC_ERR_IDX_NELEMS (4)
520252884aeSStefan Eßer 
52144d4804dSStefan Eßer // If bc is enabled, we add an extra category for POSIX warnings.
522252884aeSStefan Eßer #if BC_ENABLED
52344d4804dSStefan Eßer 
52444d4804dSStefan Eßer /// POSIX warning category.
525252884aeSStefan Eßer #define BC_ERR_IDX_WARN (BC_ERR_IDX_NELEMS)
52644d4804dSStefan Eßer 
527252884aeSStefan Eßer #endif // BC_ENABLED
528252884aeSStefan Eßer 
52944d4804dSStefan Eßer /// Do a longjmp(). This is what to use when activating an "exception", i.e., a
53044d4804dSStefan Eßer /// longjmp(). With debug code, it will print the name of the function it jumped
53144d4804dSStefan Eßer /// from.
53244d4804dSStefan Eßer #if BC_DEBUG_CODE
53344d4804dSStefan Eßer #define BC_JMP bc_vm_jmp(__func__)
53444d4804dSStefan Eßer #else // BC_DEBUG_CODE
53544d4804dSStefan Eßer #define BC_JMP bc_vm_jmp()
53644d4804dSStefan Eßer #endif // BC_DEBUG_CODE
53744d4804dSStefan Eßer 
53844d4804dSStefan Eßer /// Returns true if an exception is in flight, false otherwise.
53944d4804dSStefan Eßer #define BC_SIG_EXC \
54044d4804dSStefan Eßer 	BC_UNLIKELY(vm.status != (sig_atomic_t) BC_STATUS_SUCCESS || vm.sig)
54144d4804dSStefan Eßer 
54244d4804dSStefan Eßer /// Returns true if there is *no* exception in flight, false otherwise.
54344d4804dSStefan Eßer #define BC_NO_SIG_EXC \
54444d4804dSStefan Eßer 	BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig)
54544d4804dSStefan Eßer 
54644d4804dSStefan Eßer #ifndef NDEBUG
54744d4804dSStefan Eßer 
54844d4804dSStefan Eßer /// Assert that signals are locked. There are non-async-signal-safe functions in
54944d4804dSStefan Eßer /// bc, and they *must* have signals locked. Other functions are expected to
55044d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert
55144d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are locked.
55244d4804dSStefan Eßer #define BC_SIG_ASSERT_LOCKED do { assert(vm.sig_lock); } while (0)
55344d4804dSStefan Eßer 
55444d4804dSStefan Eßer /// Assert that signals are unlocked. There are non-async-signal-safe functions
55544d4804dSStefan Eßer /// in bc, and they *must* have signals locked. Other functions are expected to
55644d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert
55744d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are unlocked.
55844d4804dSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED do { assert(vm.sig_lock == 0); } while (0)
55944d4804dSStefan Eßer 
56044d4804dSStefan Eßer #else // NDEBUG
56144d4804dSStefan Eßer 
56244d4804dSStefan Eßer /// Assert that signals are locked. There are non-async-signal-safe functions in
56344d4804dSStefan Eßer /// bc, and they *must* have signals locked. Other functions are expected to
56444d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert
56544d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are locked.
56644d4804dSStefan Eßer #define BC_SIG_ASSERT_LOCKED
56744d4804dSStefan Eßer 
56844d4804dSStefan Eßer /// Assert that signals are unlocked. There are non-async-signal-safe functions
56944d4804dSStefan Eßer /// in bc, and they *must* have signals locked. Other functions are expected to
57044d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert
57144d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are unlocked.
57244d4804dSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED
57344d4804dSStefan Eßer 
57444d4804dSStefan Eßer #endif // NDEBUG
57544d4804dSStefan Eßer 
57644d4804dSStefan Eßer /// Locks signals.
57744d4804dSStefan Eßer #define BC_SIG_LOCK               \
57844d4804dSStefan Eßer 	do {                          \
57944d4804dSStefan Eßer 		BC_SIG_ASSERT_NOT_LOCKED; \
58044d4804dSStefan Eßer 		vm.sig_lock = 1;          \
58144d4804dSStefan Eßer 	} while (0)
58244d4804dSStefan Eßer 
58344d4804dSStefan Eßer /// Unlocks signals. If a signal happened, then this will cause a jump.
58444d4804dSStefan Eßer #define BC_SIG_UNLOCK         \
58544d4804dSStefan Eßer 	do {                      \
58644d4804dSStefan Eßer 		BC_SIG_ASSERT_LOCKED; \
58744d4804dSStefan Eßer 		vm.sig_lock = 0;      \
58844d4804dSStefan Eßer 		if (vm.sig) BC_JMP;   \
58944d4804dSStefan Eßer 	} while (0)
59044d4804dSStefan Eßer 
59144d4804dSStefan Eßer /// Locks signals, regardless of if they are already locked. This is really only
59244d4804dSStefan Eßer /// used after labels that longjmp() goes to after the jump because the cleanup
59344d4804dSStefan Eßer /// code must have signals locked, and BC_LONGJMP_CONT will unlock signals if it
59444d4804dSStefan Eßer /// doesn't jump.
59544d4804dSStefan Eßer #define BC_SIG_MAYLOCK   \
59644d4804dSStefan Eßer 	do {                 \
59744d4804dSStefan Eßer 		vm.sig_lock = 1; \
59844d4804dSStefan Eßer 	} while (0)
59944d4804dSStefan Eßer 
60044d4804dSStefan Eßer /// Unlocks signals, regardless of if they were already unlocked. If a signal
60144d4804dSStefan Eßer /// happened, then this will cause a jump.
60244d4804dSStefan Eßer #define BC_SIG_MAYUNLOCK    \
60344d4804dSStefan Eßer 	do {                    \
60444d4804dSStefan Eßer 		vm.sig_lock = 0;    \
60544d4804dSStefan Eßer 		if (vm.sig) BC_JMP; \
60644d4804dSStefan Eßer 	} while (0)
60744d4804dSStefan Eßer 
60844d4804dSStefan Eßer /*
60944d4804dSStefan Eßer  * Locks signals, but stores the old lock state, to be restored later by
61044d4804dSStefan Eßer  * BC_SIG_TRYUNLOCK.
61144d4804dSStefan Eßer  * @param v  The variable to store the old lock state to.
61244d4804dSStefan Eßer  */
61344d4804dSStefan Eßer #define BC_SIG_TRYLOCK(v) \
61444d4804dSStefan Eßer 	do {                  \
61544d4804dSStefan Eßer 		v = vm.sig_lock;  \
61644d4804dSStefan Eßer 		vm.sig_lock = 1;  \
61744d4804dSStefan Eßer 	} while (0)
61844d4804dSStefan Eßer 
61944d4804dSStefan Eßer /* Restores the previous state of a signal lock, and if it is now unlocked,
62044d4804dSStefan Eßer  * initiates an exception/jump.
62144d4804dSStefan Eßer  * @param v  The old lock state.
62244d4804dSStefan Eßer  */
62344d4804dSStefan Eßer #define BC_SIG_TRYUNLOCK(v)         \
62444d4804dSStefan Eßer 	do {                            \
62544d4804dSStefan Eßer 		vm.sig_lock = (v);          \
62644d4804dSStefan Eßer 		if (!(v) && vm.sig) BC_JMP; \
62744d4804dSStefan Eßer 	} while (0)
62844d4804dSStefan Eßer 
62944d4804dSStefan Eßer /**
63044d4804dSStefan Eßer  * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will
63144d4804dSStefan Eßer  * immediately goto a label where some cleanup code is. This one assumes that
63244d4804dSStefan Eßer  * signals are not locked and will lock them, set the jump, and unlock them.
63344d4804dSStefan Eßer  * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack.
63444d4804dSStefan Eßer  * This grows the jmp_bufs vector first to prevent a fatal error from happening
63544d4804dSStefan Eßer  * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used
63644d4804dSStefan Eßer  * *before* the actual initialization calls that need the setjmp().
63744d4804dSStefan Eßer  * param l  The label to jump to on a longjmp().
63844d4804dSStefan Eßer  */
63944d4804dSStefan Eßer #define BC_SETJMP(l)                     \
64044d4804dSStefan Eßer 	do {                                 \
64144d4804dSStefan Eßer 		sigjmp_buf sjb;                  \
64244d4804dSStefan Eßer 		BC_SIG_LOCK;                     \
64344d4804dSStefan Eßer 		bc_vec_grow(&vm.jmp_bufs, 1);    \
64444d4804dSStefan Eßer 		if (sigsetjmp(sjb, 0)) {         \
64544d4804dSStefan Eßer 			assert(BC_SIG_EXC);          \
64644d4804dSStefan Eßer 			goto l;                      \
64744d4804dSStefan Eßer 		}                                \
64844d4804dSStefan Eßer 		bc_vec_push(&vm.jmp_bufs, &sjb); \
64944d4804dSStefan Eßer 		BC_SIG_UNLOCK;                   \
65044d4804dSStefan Eßer 	} while (0)
65144d4804dSStefan Eßer 
65244d4804dSStefan Eßer /**
65344d4804dSStefan Eßer  * Sets a jump like BC_SETJMP, but unlike BC_SETJMP, it assumes signals are
65444d4804dSStefan Eßer  * locked and will just set the jump. This does *not* have a call to
65544d4804dSStefan Eßer  * bc_vec_grow() because it is assumed that BC_SETJMP_LOCKED(l) is used *after*
65644d4804dSStefan Eßer  * the initializations that need the setjmp().
65744d4804dSStefan Eßer  * param l  The label to jump to on a longjmp().
65844d4804dSStefan Eßer  */
65944d4804dSStefan Eßer #define BC_SETJMP_LOCKED(l)              \
66044d4804dSStefan Eßer 	do {                                 \
66144d4804dSStefan Eßer 		sigjmp_buf sjb;                  \
66244d4804dSStefan Eßer 		BC_SIG_ASSERT_LOCKED;            \
66344d4804dSStefan Eßer 		if (sigsetjmp(sjb, 0)) {         \
66444d4804dSStefan Eßer 			assert(BC_SIG_EXC);          \
66544d4804dSStefan Eßer 			goto l;                      \
66644d4804dSStefan Eßer 		}                                \
66744d4804dSStefan Eßer 		bc_vec_push(&vm.jmp_bufs, &sjb); \
66844d4804dSStefan Eßer 	} while (0)
66944d4804dSStefan Eßer 
67044d4804dSStefan Eßer /// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to
67144d4804dSStefan Eßer /// the next place. This is what continues the stack unwinding. This basically
67244d4804dSStefan Eßer /// copies BC_SIG_UNLOCK into itself, but that is because its condition for
67344d4804dSStefan Eßer /// jumping is BC_SIG_EXC, not just that a signal happened.
67444d4804dSStefan Eßer #define BC_LONGJMP_CONT                            \
67544d4804dSStefan Eßer 	do {                                           \
67644d4804dSStefan Eßer 		BC_SIG_ASSERT_LOCKED;                      \
67744d4804dSStefan Eßer 		if (!vm.sig_pop) bc_vec_pop(&vm.jmp_bufs); \
67844d4804dSStefan Eßer 		vm.sig_lock = 0;                           \
67944d4804dSStefan Eßer 		if (BC_SIG_EXC) BC_JMP;                    \
68044d4804dSStefan Eßer 	} while (0)
68144d4804dSStefan Eßer 
68244d4804dSStefan Eßer /// Unsets a jump. It always assumes signals are locked. This basically just
68344d4804dSStefan Eßer /// pops a jmp_buf off of the stack of jmp_bufs, and since the jump mechanism
68444d4804dSStefan Eßer /// always jumps to the location at the top of the stack, this effectively
68544d4804dSStefan Eßer /// undoes a setjmp().
68644d4804dSStefan Eßer #define BC_UNSETJMP               \
68744d4804dSStefan Eßer 	do {                          \
68844d4804dSStefan Eßer 		BC_SIG_ASSERT_LOCKED;     \
68944d4804dSStefan Eßer 		bc_vec_pop(&vm.jmp_bufs); \
69044d4804dSStefan Eßer 	} while (0)
69144d4804dSStefan Eßer 
69244d4804dSStefan Eßer /// Stops a stack unwinding. Technically, a stack unwinding needs to be done
69344d4804dSStefan Eßer /// manually, but it will always be done unless certain flags are cleared. This
69444d4804dSStefan Eßer /// clears the flags.
69544d4804dSStefan Eßer #define BC_LONGJMP_STOP \
69644d4804dSStefan Eßer 	do {                \
69744d4804dSStefan Eßer 		vm.sig_pop = 0; \
69844d4804dSStefan Eßer 		vm.sig = 0;     \
69944d4804dSStefan Eßer 	} while (0)
70044d4804dSStefan Eßer 
70144d4804dSStefan Eßer // Various convenience macros for calling the bc's error handling routine.
70244d4804dSStefan Eßer #if BC_ENABLE_LIBRARY
70344d4804dSStefan Eßer 
70444d4804dSStefan Eßer /**
70544d4804dSStefan Eßer  * Call bc's error handling routine.
70644d4804dSStefan Eßer  * @param e    The error.
70744d4804dSStefan Eßer  * @param l    The line of the script that the error happened.
70844d4804dSStefan Eßer  * @param ...  Extra arguments for error messages as necessary.
70944d4804dSStefan Eßer  */
71044d4804dSStefan Eßer #define bc_error(e, l, ...) (bc_vm_handleError((e)))
71144d4804dSStefan Eßer 
71244d4804dSStefan Eßer /**
71344d4804dSStefan Eßer  * Call bc's error handling routine.
71444d4804dSStefan Eßer  * @param e  The error.
71544d4804dSStefan Eßer  */
71644d4804dSStefan Eßer #define bc_err(e) (bc_vm_handleError((e)))
71744d4804dSStefan Eßer 
71844d4804dSStefan Eßer /**
71944d4804dSStefan Eßer  * Call bc's error handling routine.
72044d4804dSStefan Eßer  * @param e  The error.
72144d4804dSStefan Eßer  */
72244d4804dSStefan Eßer #define bc_verr(e, ...) (bc_vm_handleError((e)))
72344d4804dSStefan Eßer 
72444d4804dSStefan Eßer #else // BC_ENABLE_LIBRARY
72544d4804dSStefan Eßer 
72644d4804dSStefan Eßer /**
72744d4804dSStefan Eßer  * Call bc's error handling routine.
72844d4804dSStefan Eßer  * @param e    The error.
72944d4804dSStefan Eßer  * @param l    The line of the script that the error happened.
73044d4804dSStefan Eßer  * @param ...  Extra arguments for error messages as necessary.
73144d4804dSStefan Eßer  */
73244d4804dSStefan Eßer #define bc_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__))
73344d4804dSStefan Eßer 
73444d4804dSStefan Eßer /**
73544d4804dSStefan Eßer  * Call bc's error handling routine.
73644d4804dSStefan Eßer  * @param e  The error.
73744d4804dSStefan Eßer  */
73844d4804dSStefan Eßer #define bc_err(e) (bc_vm_handleError((e), 0))
73944d4804dSStefan Eßer 
74044d4804dSStefan Eßer /**
74144d4804dSStefan Eßer  * Call bc's error handling routine.
74244d4804dSStefan Eßer  * @param e  The error.
74344d4804dSStefan Eßer  */
74444d4804dSStefan Eßer #define bc_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__))
74544d4804dSStefan Eßer 
74644d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY
74744d4804dSStefan Eßer 
74844d4804dSStefan Eßer /**
74944d4804dSStefan Eßer  * Returns true if status @a s is an error, false otherwise.
75044d4804dSStefan Eßer  * @param s  The status to test.
75144d4804dSStefan Eßer  * @return   True if @a s is an error, false otherwise.
75244d4804dSStefan Eßer  */
75344d4804dSStefan Eßer #define BC_STATUS_IS_ERROR(s) \
75444d4804dSStefan Eßer 	((s) >= BC_STATUS_ERROR_MATH && (s) <= BC_STATUS_ERROR_FATAL)
75544d4804dSStefan Eßer 
75644d4804dSStefan Eßer // Convenience macros that can be placed at the beginning and exits of functions
75744d4804dSStefan Eßer // for easy marking of where functions are entered and exited.
75844d4804dSStefan Eßer #if BC_DEBUG_CODE
75944d4804dSStefan Eßer #define BC_FUNC_ENTER                                              \
76044d4804dSStefan Eßer 	do {                                                           \
76144d4804dSStefan Eßer 		size_t bc_func_enter_i;                                    \
76244d4804dSStefan Eßer 		for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \
76344d4804dSStefan Eßer 		     ++bc_func_enter_i)                                    \
76444d4804dSStefan Eßer 		{                                                          \
76544d4804dSStefan Eßer 			bc_file_puts(&vm.ferr, bc_flush_none, "  ");           \
76644d4804dSStefan Eßer 		}                                                          \
76744d4804dSStefan Eßer 		vm.func_depth += 1;                                        \
76844d4804dSStefan Eßer 		bc_file_printf(&vm.ferr, "Entering %s\n", __func__);       \
76944d4804dSStefan Eßer 		bc_file_flush(&vm.ferr, bc_flush_none);                    \
77044d4804dSStefan Eßer 	} while (0);
77144d4804dSStefan Eßer 
77244d4804dSStefan Eßer #define BC_FUNC_EXIT                                               \
77344d4804dSStefan Eßer 	do {                                                           \
77444d4804dSStefan Eßer 		size_t bc_func_enter_i;                                    \
77544d4804dSStefan Eßer 		vm.func_depth -= 1;                                        \
77644d4804dSStefan Eßer 		for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \
77744d4804dSStefan Eßer 		     ++bc_func_enter_i)                                    \
77844d4804dSStefan Eßer 		{                                                          \
77944d4804dSStefan Eßer 			bc_file_puts(&vm.ferr, bc_flush_none, "  ");           \
78044d4804dSStefan Eßer 		}                                                          \
78144d4804dSStefan Eßer 		bc_file_printf(&vm.ferr, "Leaving %s\n", __func__);        \
78244d4804dSStefan Eßer 		bc_file_flush(&vm.ferr, bc_flush_none);                    \
78344d4804dSStefan Eßer 	} while (0);
78444d4804dSStefan Eßer #else // BC_DEBUG_CODE
78544d4804dSStefan Eßer #define BC_FUNC_ENTER
78644d4804dSStefan Eßer #define BC_FUNC_EXIT
78744d4804dSStefan Eßer #endif // BC_DEBUG_CODE
78844d4804dSStefan Eßer 
789252884aeSStefan Eßer #endif // BC_STATUS_H
790