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