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 56662087dfSStefan Eßer #ifndef BC_ENABLE_LIBRARY 57662087dfSStefan Eßer #define BC_ENABLE_LIBRARY (0) 58662087dfSStefan Eßer #endif // BC_ENABLE_LIBRARY 59662087dfSStefan Eßer 6044d4804dSStefan Eßer // This is error checking for fuzz builds. 6110328f8bSStefan Eßer #if BC_ENABLE_AFL 6210328f8bSStefan Eßer #ifndef __AFL_HAVE_MANUAL_CONTROL 6344d4804dSStefan Eßer #error Must compile with afl-clang-fast or afl-clang-lto for fuzzing 6410328f8bSStefan Eßer #endif // __AFL_HAVE_MANUAL_CONTROL 6510328f8bSStefan Eßer #endif // BC_ENABLE_AFL 6610328f8bSStefan Eßer 6710328f8bSStefan Eßer #ifndef BC_ENABLE_MEMCHECK 6810328f8bSStefan Eßer #define BC_ENABLE_MEMCHECK (0) 6910328f8bSStefan Eßer #endif // BC_ENABLE_MEMCHECK 7010328f8bSStefan Eßer 7144d4804dSStefan Eßer /** 7244d4804dSStefan Eßer * Mark a variable as unused. 7344d4804dSStefan Eßer * @param e The variable to mark as unused. 7444d4804dSStefan Eßer */ 7544d4804dSStefan Eßer #define BC_UNUSED(e) ((void) (e)) 7644d4804dSStefan Eßer 7744d4804dSStefan Eßer // If users want, they can define this to something like __builtin_expect(e, 1). 7844d4804dSStefan Eßer // It might give a performance improvement. 7944d4804dSStefan Eßer #ifndef BC_LIKELY 8044d4804dSStefan Eßer 8144d4804dSStefan Eßer /** 8244d4804dSStefan Eßer * Mark a branch expression as likely. 8344d4804dSStefan Eßer * @param e The expression to mark as likely. 8444d4804dSStefan Eßer */ 8544d4804dSStefan Eßer #define BC_LIKELY(e) (e) 8644d4804dSStefan Eßer 8744d4804dSStefan Eßer #endif // BC_LIKELY 8844d4804dSStefan Eßer 8944d4804dSStefan Eßer // If users want, they can define this to something like __builtin_expect(e, 0). 9044d4804dSStefan Eßer // It might give a performance improvement. 9144d4804dSStefan Eßer #ifndef BC_UNLIKELY 9244d4804dSStefan Eßer 9344d4804dSStefan Eßer /** 9444d4804dSStefan Eßer * Mark a branch expression as unlikely. 9544d4804dSStefan Eßer * @param e The expression to mark as unlikely. 9644d4804dSStefan Eßer */ 9744d4804dSStefan Eßer #define BC_UNLIKELY(e) (e) 9844d4804dSStefan Eßer 9944d4804dSStefan Eßer #endif // BC_UNLIKELY 10044d4804dSStefan Eßer 10144d4804dSStefan Eßer /** 10244d4804dSStefan Eßer * Mark a branch expression as an error, if true. 10344d4804dSStefan Eßer * @param e The expression to mark as an error, if true. 10444d4804dSStefan Eßer */ 10544d4804dSStefan Eßer #define BC_ERR(e) BC_UNLIKELY(e) 10644d4804dSStefan Eßer 10744d4804dSStefan Eßer /** 10844d4804dSStefan Eßer * Mark a branch expression as not an error, if true. 10944d4804dSStefan Eßer * @param e The expression to mark as not an error, if true. 11044d4804dSStefan Eßer */ 11144d4804dSStefan Eßer #define BC_NO_ERR(s) BC_LIKELY(s) 11244d4804dSStefan Eßer 11344d4804dSStefan Eßer // Disable extra debug code by default. 11444d4804dSStefan Eßer #ifndef BC_DEBUG_CODE 11544d4804dSStefan Eßer #define BC_DEBUG_CODE (0) 11644d4804dSStefan Eßer #endif // BC_DEBUG_CODE 11744d4804dSStefan Eßer 11844d4804dSStefan Eßer // We want to be able to use _Noreturn on C11 compilers. 11944d4804dSStefan Eßer #if __STDC_VERSION__ >= 201100L 12044d4804dSStefan Eßer 12144d4804dSStefan Eßer #include <stdnoreturn.h> 12244d4804dSStefan Eßer #define BC_NORETURN _Noreturn 12344d4804dSStefan Eßer #define BC_C11 (1) 12444d4804dSStefan Eßer 12544d4804dSStefan Eßer #else // __STDC_VERSION__ 12644d4804dSStefan Eßer 12744d4804dSStefan Eßer #define BC_NORETURN 12844d4804dSStefan Eßer #define BC_MUST_RETURN 12944d4804dSStefan Eßer #define BC_C11 (0) 13044d4804dSStefan Eßer 13144d4804dSStefan Eßer #endif // __STDC_VERSION__ 13244d4804dSStefan Eßer 13344d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (0) 13444d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (0) 13544d4804dSStefan Eßer 13644d4804dSStefan Eßer // GCC and Clang complain if fallthroughs are not marked with their special 13744d4804dSStefan Eßer // attribute. Jerks. This creates a define for marking the fallthroughs that is 13844d4804dSStefan Eßer // nothing on other compilers. 13944d4804dSStefan Eßer #if defined(__clang__) || defined(__GNUC__) 14044d4804dSStefan Eßer 14144d4804dSStefan Eßer #if defined(__has_attribute) 14244d4804dSStefan Eßer 14344d4804dSStefan Eßer #if __has_attribute(fallthrough) 14444d4804dSStefan Eßer #define BC_FALLTHROUGH __attribute__((fallthrough)); 14544d4804dSStefan Eßer #else // __has_attribute(fallthrough) 14644d4804dSStefan Eßer #define BC_FALLTHROUGH 14744d4804dSStefan Eßer #endif // __has_attribute(fallthrough) 14844d4804dSStefan Eßer 14944d4804dSStefan Eßer #ifdef __GNUC__ 15044d4804dSStefan Eßer 15144d4804dSStefan Eßer #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 15244d4804dSStefan Eßer #undef BC_HAS_UNREACHABLE 15344d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (1) 15444d4804dSStefan Eßer #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 15544d4804dSStefan Eßer 15644d4804dSStefan Eßer #else // __GNUC__ 15744d4804dSStefan Eßer 15844d4804dSStefan Eßer #if __clang_major__ >= 4 15944d4804dSStefan Eßer #undef BC_HAS_UNREACHABLE 16044d4804dSStefan Eßer #define BC_HAS_UNREACHABLE (1) 16144d4804dSStefan Eßer #endif // __clang_major__ >= 4 16244d4804dSStefan Eßer 16344d4804dSStefan Eßer #endif // __GNUC__ 16444d4804dSStefan Eßer 16544d4804dSStefan Eßer #else // defined(__has_attribute) 16644d4804dSStefan Eßer #define BC_FALLTHROUGH 16744d4804dSStefan Eßer #endif // defined(__has_attribute) 16844d4804dSStefan Eßer #else // defined(__clang__) || defined(__GNUC__) 16944d4804dSStefan Eßer #define BC_FALLTHROUGH 17044d4804dSStefan Eßer #endif // defined(__clang__) || defined(__GNUC__) 17144d4804dSStefan Eßer 17244d4804dSStefan Eßer #if BC_HAS_UNREACHABLE 17344d4804dSStefan Eßer 17444d4804dSStefan Eßer #define BC_UNREACHABLE __builtin_unreachable(); 17544d4804dSStefan Eßer 17644d4804dSStefan Eßer #else // BC_HAS_UNREACHABLE 17744d4804dSStefan Eßer 17844d4804dSStefan Eßer #ifdef _WIN32 17944d4804dSStefan Eßer 18044d4804dSStefan Eßer #define BC_UNREACHABLE __assume(0); 18144d4804dSStefan Eßer 18244d4804dSStefan Eßer #else // _WIN32 18344d4804dSStefan Eßer 18444d4804dSStefan Eßer #define BC_UNREACHABLE 18544d4804dSStefan Eßer 18644d4804dSStefan Eßer #endif // _WIN32 18744d4804dSStefan Eßer 18844d4804dSStefan Eßer #endif // BC_HAS_UNREACHABLE 18944d4804dSStefan Eßer 19044d4804dSStefan Eßer #ifdef __GNUC__ 19144d4804dSStefan Eßer 19244d4804dSStefan Eßer #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 19344d4804dSStefan Eßer 19444d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO 19544d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (1) 19644d4804dSStefan Eßer 19744d4804dSStefan Eßer #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 19844d4804dSStefan Eßer 19944d4804dSStefan Eßer #endif // __GNUC__ 20044d4804dSStefan Eßer 20144d4804dSStefan Eßer #ifdef __clang__ 20244d4804dSStefan Eßer 20344d4804dSStefan Eßer #if __clang_major__ >= 4 20444d4804dSStefan Eßer 20544d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO 20644d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (1) 20744d4804dSStefan Eßer 20844d4804dSStefan Eßer #endif // __clang_major__ >= 4 20944d4804dSStefan Eßer 21044d4804dSStefan Eßer #endif // __GNUC__ 21144d4804dSStefan Eßer 21244d4804dSStefan Eßer #ifdef BC_NO_COMPUTED_GOTO 21344d4804dSStefan Eßer 21444d4804dSStefan Eßer #undef BC_HAS_COMPUTED_GOTO 21544d4804dSStefan Eßer #define BC_HAS_COMPUTED_GOTO (0) 21644d4804dSStefan Eßer 21744d4804dSStefan Eßer #endif // BC_NO_COMPUTED_GOTO 21844d4804dSStefan Eßer 21944d4804dSStefan Eßer #ifdef __GNUC__ 22044d4804dSStefan Eßer #ifdef __OpenBSD__ 22144d4804dSStefan Eßer // The OpenBSD GCC doesn't like inline. 22244d4804dSStefan Eßer #define inline 22344d4804dSStefan Eßer #endif // __OpenBSD__ 22444d4804dSStefan Eßer #endif // __GNUC__ 22544d4804dSStefan Eßer 22644d4804dSStefan Eßer // Workarounds for AIX's POSIX incompatibility. 22744d4804dSStefan Eßer #ifndef SIZE_MAX 22844d4804dSStefan Eßer #define SIZE_MAX __SIZE_MAX__ 22944d4804dSStefan Eßer #endif // SIZE_MAX 23044d4804dSStefan Eßer #ifndef UINTMAX_C 23144d4804dSStefan Eßer #define UINTMAX_C __UINTMAX_C 23244d4804dSStefan Eßer #endif // UINTMAX_C 23344d4804dSStefan Eßer #ifndef UINT32_C 23444d4804dSStefan Eßer #define UINT32_C __UINT32_C 23544d4804dSStefan Eßer #endif // UINT32_C 23644d4804dSStefan Eßer #ifndef UINT_FAST32_MAX 23744d4804dSStefan Eßer #define UINT_FAST32_MAX __UINT_FAST32_MAX__ 23844d4804dSStefan Eßer #endif // UINT_FAST32_MAX 23944d4804dSStefan Eßer #ifndef UINT16_MAX 24044d4804dSStefan Eßer #define UINT16_MAX __UINT16_MAX__ 24144d4804dSStefan Eßer #endif // UINT16_MAX 24244d4804dSStefan Eßer #ifndef SIG_ATOMIC_MAX 24344d4804dSStefan Eßer #define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ 24444d4804dSStefan Eßer #endif // SIG_ATOMIC_MAX 24544d4804dSStefan Eßer 24644d4804dSStefan Eßer // Yes, this has to be here. 24750696a6eSStefan Eßer #include <bcl.h> 24850696a6eSStefan Eßer 24944d4804dSStefan Eßer // All of these set defaults for settings. 25044d4804dSStefan Eßer 25144d4804dSStefan Eßer #if BC_ENABLED 25244d4804dSStefan Eßer 25344d4804dSStefan Eßer #ifndef BC_DEFAULT_BANNER 25444d4804dSStefan Eßer #define BC_DEFAULT_BANNER (0) 25544d4804dSStefan Eßer #endif // BC_DEFAULT_BANNER 25644d4804dSStefan Eßer 25744d4804dSStefan Eßer #endif // BC_ENABLED 25844d4804dSStefan Eßer 25944d4804dSStefan Eßer #ifndef BC_DEFAULT_SIGINT_RESET 26044d4804dSStefan Eßer #define BC_DEFAULT_SIGINT_RESET (1) 26144d4804dSStefan Eßer #endif // BC_DEFAULT_SIGINT_RESET 26244d4804dSStefan Eßer 26344d4804dSStefan Eßer #ifndef BC_DEFAULT_TTY_MODE 26444d4804dSStefan Eßer #define BC_DEFAULT_TTY_MODE (1) 26544d4804dSStefan Eßer #endif // BC_DEFAULT_TTY_MODE 26644d4804dSStefan Eßer 26744d4804dSStefan Eßer #ifndef BC_DEFAULT_PROMPT 26844d4804dSStefan Eßer #define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE 26944d4804dSStefan Eßer #endif // BC_DEFAULT_PROMPT 27044d4804dSStefan Eßer 27110041e99SStefan Eßer #ifndef BC_DEFAULT_EXPR_EXIT 27210041e99SStefan Eßer #define BC_DEFAULT_EXPR_EXIT (1) 27310041e99SStefan Eßer #endif // BC_DEFAULT_EXPR_EXIT 27410041e99SStefan Eßer 27544d4804dSStefan Eßer // All of these set defaults for settings. 27644d4804dSStefan Eßer #ifndef DC_DEFAULT_SIGINT_RESET 27744d4804dSStefan Eßer #define DC_DEFAULT_SIGINT_RESET (1) 27844d4804dSStefan Eßer #endif // DC_DEFAULT_SIGINT_RESET 27944d4804dSStefan Eßer 28044d4804dSStefan Eßer #ifndef DC_DEFAULT_TTY_MODE 28144d4804dSStefan Eßer #define DC_DEFAULT_TTY_MODE (0) 28244d4804dSStefan Eßer #endif // DC_DEFAULT_TTY_MODE 28344d4804dSStefan Eßer 28444d4804dSStefan Eßer #ifndef DC_DEFAULT_HISTORY 28544d4804dSStefan Eßer #define DC_DEFAULT_HISTORY DC_DEFAULT_TTY_MODE 28644d4804dSStefan Eßer #endif // DC_DEFAULT_HISTORY 28744d4804dSStefan Eßer 28844d4804dSStefan Eßer #ifndef DC_DEFAULT_PROMPT 28944d4804dSStefan Eßer #define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE 29044d4804dSStefan Eßer #endif // DC_DEFAULT_PROMPT 29144d4804dSStefan Eßer 29210041e99SStefan Eßer #ifndef DC_DEFAULT_EXPR_EXIT 29310041e99SStefan Eßer #define DC_DEFAULT_EXPR_EXIT (1) 29410041e99SStefan Eßer #endif // DC_DEFAULT_EXPR_EXIT 29510041e99SStefan Eßer 29644d4804dSStefan Eßer /// Statuses, which mark either which category of error happened, or some other 29744d4804dSStefan Eßer /// status that matters. 298252884aeSStefan Eßer typedef enum BcStatus { 299252884aeSStefan Eßer 30044d4804dSStefan Eßer /// Normal status. 301252884aeSStefan Eßer BC_STATUS_SUCCESS = 0, 30244d4804dSStefan Eßer 30344d4804dSStefan Eßer /// Math error. 304252884aeSStefan Eßer BC_STATUS_ERROR_MATH, 30544d4804dSStefan Eßer 30644d4804dSStefan Eßer /// Parse (and lex) error. 307252884aeSStefan Eßer BC_STATUS_ERROR_PARSE, 30844d4804dSStefan Eßer 30944d4804dSStefan Eßer /// Runtime error. 310252884aeSStefan Eßer BC_STATUS_ERROR_EXEC, 31144d4804dSStefan Eßer 31244d4804dSStefan Eßer /// Fatal error. 313252884aeSStefan Eßer BC_STATUS_ERROR_FATAL, 31444d4804dSStefan Eßer 31544d4804dSStefan Eßer /// EOF status. 316252884aeSStefan Eßer BC_STATUS_EOF, 31744d4804dSStefan Eßer 31844d4804dSStefan Eßer /// Quit status. This means that bc/dc is in the process of quitting. 319252884aeSStefan Eßer BC_STATUS_QUIT, 320252884aeSStefan Eßer 321252884aeSStefan Eßer } BcStatus; 322252884aeSStefan Eßer 32344d4804dSStefan Eßer /// Errors, which are more specific errors. 32450696a6eSStefan Eßer typedef enum BcErr { 325252884aeSStefan Eßer 32644d4804dSStefan Eßer // Math errors. 32744d4804dSStefan Eßer 32844d4804dSStefan Eßer /// Negative number used when not allowed. 32950696a6eSStefan Eßer BC_ERR_MATH_NEGATIVE, 33044d4804dSStefan Eßer 33144d4804dSStefan Eßer /// Non-integer used when not allowed. 33250696a6eSStefan Eßer BC_ERR_MATH_NON_INTEGER, 33344d4804dSStefan Eßer 33444d4804dSStefan Eßer /// Conversion to a hardware integer would overflow. 33550696a6eSStefan Eßer BC_ERR_MATH_OVERFLOW, 33644d4804dSStefan Eßer 33744d4804dSStefan Eßer /// Divide by zero. 33850696a6eSStefan Eßer BC_ERR_MATH_DIVIDE_BY_ZERO, 339252884aeSStefan Eßer 34044d4804dSStefan Eßer // Fatal errors. 34144d4804dSStefan Eßer 34244d4804dSStefan Eßer /// An allocation or reallocation failed. 34350696a6eSStefan Eßer BC_ERR_FATAL_ALLOC_ERR, 34444d4804dSStefan Eßer 34544d4804dSStefan Eßer /// I/O failure. 34650696a6eSStefan Eßer BC_ERR_FATAL_IO_ERR, 34744d4804dSStefan Eßer 34844d4804dSStefan Eßer /// File error, such as permissions or file does not exist. 34950696a6eSStefan Eßer BC_ERR_FATAL_FILE_ERR, 35044d4804dSStefan Eßer 35144d4804dSStefan Eßer /// File is binary, not text, error. 35250696a6eSStefan Eßer BC_ERR_FATAL_BIN_FILE, 35344d4804dSStefan Eßer 35444d4804dSStefan Eßer /// Attempted to read a directory as a file error. 35550696a6eSStefan Eßer BC_ERR_FATAL_PATH_DIR, 35644d4804dSStefan Eßer 35744d4804dSStefan Eßer /// Invalid option error. 35850696a6eSStefan Eßer BC_ERR_FATAL_OPTION, 35944d4804dSStefan Eßer 36044d4804dSStefan Eßer /// Option with required argument not given an argument. 36150696a6eSStefan Eßer BC_ERR_FATAL_OPTION_NO_ARG, 36244d4804dSStefan Eßer 36344d4804dSStefan Eßer /// Option with no argument given an argument. 36450696a6eSStefan Eßer BC_ERR_FATAL_OPTION_ARG, 365252884aeSStefan Eßer 36644d4804dSStefan Eßer /// Option argument is invalid. 36744d4804dSStefan Eßer BC_ERR_FATAL_ARG, 36844d4804dSStefan Eßer 36944d4804dSStefan Eßer // Runtime errors. 37044d4804dSStefan Eßer 37144d4804dSStefan Eßer /// Invalid ibase value. 37250696a6eSStefan Eßer BC_ERR_EXEC_IBASE, 37344d4804dSStefan Eßer 37444d4804dSStefan Eßer /// Invalid obase value. 37550696a6eSStefan Eßer BC_ERR_EXEC_OBASE, 37644d4804dSStefan Eßer 37744d4804dSStefan Eßer /// Invalid scale value. 37850696a6eSStefan Eßer BC_ERR_EXEC_SCALE, 37944d4804dSStefan Eßer 38044d4804dSStefan Eßer /// Invalid expression parsed by read(). 38150696a6eSStefan Eßer BC_ERR_EXEC_READ_EXPR, 38244d4804dSStefan Eßer 38344d4804dSStefan Eßer /// read() used within an expression given to a read() call. 38450696a6eSStefan Eßer BC_ERR_EXEC_REC_READ, 38544d4804dSStefan Eßer 38644d4804dSStefan Eßer /// Type error. 38750696a6eSStefan Eßer BC_ERR_EXEC_TYPE, 388252884aeSStefan Eßer 38944d4804dSStefan Eßer /// Stack has too few elements error. 39050696a6eSStefan Eßer BC_ERR_EXEC_STACK, 391252884aeSStefan Eßer 39244d4804dSStefan Eßer /// Register stack has too few elements error. 39344d4804dSStefan Eßer BC_ERR_EXEC_STACK_REGISTER, 39444d4804dSStefan Eßer 39544d4804dSStefan Eßer /// Wrong number of arguments error. 39650696a6eSStefan Eßer BC_ERR_EXEC_PARAMS, 39744d4804dSStefan Eßer 39844d4804dSStefan Eßer /// Undefined function error. 39950696a6eSStefan Eßer BC_ERR_EXEC_UNDEF_FUNC, 40044d4804dSStefan Eßer 40144d4804dSStefan Eßer /// Void value used in an expression error. 40250696a6eSStefan Eßer BC_ERR_EXEC_VOID_VAL, 403252884aeSStefan Eßer 40444d4804dSStefan Eßer // Parse (and lex errors). 40544d4804dSStefan Eßer 40644d4804dSStefan Eßer /// EOF encountered when not expected error. 40750696a6eSStefan Eßer BC_ERR_PARSE_EOF, 40844d4804dSStefan Eßer 40944d4804dSStefan Eßer /// Invalid character error. 41050696a6eSStefan Eßer BC_ERR_PARSE_CHAR, 41144d4804dSStefan Eßer 41244d4804dSStefan Eßer /// Invalid string (no ending quote) error. 41350696a6eSStefan Eßer BC_ERR_PARSE_STRING, 41444d4804dSStefan Eßer 41544d4804dSStefan Eßer /// Invalid comment (no end found) error. 41650696a6eSStefan Eßer BC_ERR_PARSE_COMMENT, 41744d4804dSStefan Eßer 41844d4804dSStefan Eßer /// Invalid token encountered error. 41950696a6eSStefan Eßer BC_ERR_PARSE_TOKEN, 42044d4804dSStefan Eßer 421252884aeSStefan Eßer #if BC_ENABLED 42244d4804dSStefan Eßer 42344d4804dSStefan Eßer /// Invalid expression error. 42450696a6eSStefan Eßer BC_ERR_PARSE_EXPR, 42544d4804dSStefan Eßer 42644d4804dSStefan Eßer /// Expression is empty error. 42750696a6eSStefan Eßer BC_ERR_PARSE_EMPTY_EXPR, 42844d4804dSStefan Eßer 42944d4804dSStefan Eßer /// Print statement is invalid error. 43050696a6eSStefan Eßer BC_ERR_PARSE_PRINT, 43144d4804dSStefan Eßer 43244d4804dSStefan Eßer /// Function definition is invalid error. 43350696a6eSStefan Eßer BC_ERR_PARSE_FUNC, 43444d4804dSStefan Eßer 43544d4804dSStefan Eßer /// Assignment is invalid error. 43650696a6eSStefan Eßer BC_ERR_PARSE_ASSIGN, 43744d4804dSStefan Eßer 43844d4804dSStefan Eßer /// No auto identifiers given for an auto statement error. 43950696a6eSStefan Eßer BC_ERR_PARSE_NO_AUTO, 44044d4804dSStefan Eßer 44144d4804dSStefan Eßer /// Duplicate local (parameter or auto) error. 44250696a6eSStefan Eßer BC_ERR_PARSE_DUP_LOCAL, 44344d4804dSStefan Eßer 44444d4804dSStefan Eßer /// Invalid block (within braces) error. 44550696a6eSStefan Eßer BC_ERR_PARSE_BLOCK, 44644d4804dSStefan Eßer 44744d4804dSStefan Eßer /// Invalid return statement for void functions. 44850696a6eSStefan Eßer BC_ERR_PARSE_RET_VOID, 44944d4804dSStefan Eßer 45044d4804dSStefan Eßer /// Reference attached to a variable, not an array, error. 45150696a6eSStefan Eßer BC_ERR_PARSE_REF_VAR, 452252884aeSStefan Eßer 45344d4804dSStefan Eßer // POSIX-only errors. 45444d4804dSStefan Eßer 45544d4804dSStefan Eßer /// Name length greater than 1 error. 45650696a6eSStefan Eßer BC_ERR_POSIX_NAME_LEN, 45744d4804dSStefan Eßer 45844d4804dSStefan Eßer /// Non-POSIX comment used error. 45950696a6eSStefan Eßer BC_ERR_POSIX_COMMENT, 46044d4804dSStefan Eßer 46144d4804dSStefan Eßer /// Non-POSIX keyword error. 46250696a6eSStefan Eßer BC_ERR_POSIX_KW, 46344d4804dSStefan Eßer 46444d4804dSStefan Eßer /// Non-POSIX . (last) error. 46550696a6eSStefan Eßer BC_ERR_POSIX_DOT, 46644d4804dSStefan Eßer 46744d4804dSStefan Eßer /// Non-POSIX return error. 46850696a6eSStefan Eßer BC_ERR_POSIX_RET, 46944d4804dSStefan Eßer 47044d4804dSStefan Eßer /// Non-POSIX boolean operator used error. 47150696a6eSStefan Eßer BC_ERR_POSIX_BOOL, 47244d4804dSStefan Eßer 47344d4804dSStefan Eßer /// POSIX relation operator used outside if, while, or for statements error. 47450696a6eSStefan Eßer BC_ERR_POSIX_REL_POS, 47544d4804dSStefan Eßer 47644d4804dSStefan Eßer /// Multiple POSIX relation operators used in an if, while, or for statement 47744d4804dSStefan Eßer /// error. 47850696a6eSStefan Eßer BC_ERR_POSIX_MULTIREL, 47944d4804dSStefan Eßer 48044d4804dSStefan Eßer /// Empty statements in POSIX for loop error. 48150696a6eSStefan Eßer BC_ERR_POSIX_FOR, 48244d4804dSStefan Eßer 48310041e99SStefan Eßer /// POSIX's grammar does not allow a function definition right after a 48410041e99SStefan Eßer /// semicolon. 48510041e99SStefan Eßer BC_ERR_POSIX_FUNC_AFTER_SEMICOLON, 48610041e99SStefan Eßer 48744d4804dSStefan Eßer /// Non-POSIX exponential (scientific or engineering) number used error. 48850696a6eSStefan Eßer BC_ERR_POSIX_EXP_NUM, 48944d4804dSStefan Eßer 49044d4804dSStefan Eßer /// Non-POSIX array reference error. 49150696a6eSStefan Eßer BC_ERR_POSIX_REF, 49244d4804dSStefan Eßer 49344d4804dSStefan Eßer /// Non-POSIX void error. 49450696a6eSStefan Eßer BC_ERR_POSIX_VOID, 49544d4804dSStefan Eßer 49644d4804dSStefan Eßer /// Non-POSIX brace position used error. 49750696a6eSStefan Eßer BC_ERR_POSIX_BRACE, 49844d4804dSStefan Eßer 49944d4804dSStefan Eßer /// String used in expression. 50044d4804dSStefan Eßer BC_ERR_POSIX_EXPR_STRING, 50144d4804dSStefan Eßer 502252884aeSStefan Eßer #endif // BC_ENABLED 503252884aeSStefan Eßer 50444d4804dSStefan Eßer // Number of elements. 50550696a6eSStefan Eßer BC_ERR_NELEMS, 506252884aeSStefan Eßer 507252884aeSStefan Eßer #if BC_ENABLED 50844d4804dSStefan Eßer 50944d4804dSStefan Eßer /// A marker for the start of POSIX errors. 51050696a6eSStefan Eßer BC_ERR_POSIX_START = BC_ERR_POSIX_NAME_LEN, 51144d4804dSStefan Eßer 51244d4804dSStefan Eßer /// A marker for the end of POSIX errors. 51344d4804dSStefan Eßer BC_ERR_POSIX_END = BC_ERR_POSIX_EXPR_STRING, 51444d4804dSStefan Eßer 515252884aeSStefan Eßer #endif // BC_ENABLED 516252884aeSStefan Eßer 51750696a6eSStefan Eßer } BcErr; 518252884aeSStefan Eßer 51944d4804dSStefan Eßer // The indices of each category of error in bc_errs[], and used in bc_err_ids[] 52044d4804dSStefan Eßer // to associate actual errors with their categories. 52144d4804dSStefan Eßer 52244d4804dSStefan Eßer /// Math error category. 523252884aeSStefan Eßer #define BC_ERR_IDX_MATH (0) 52444d4804dSStefan Eßer 52544d4804dSStefan Eßer /// Parse (and lex) error category. 526252884aeSStefan Eßer #define BC_ERR_IDX_PARSE (1) 52744d4804dSStefan Eßer 52844d4804dSStefan Eßer /// Runtime error category. 529252884aeSStefan Eßer #define BC_ERR_IDX_EXEC (2) 53044d4804dSStefan Eßer 53144d4804dSStefan Eßer /// Fatal error category. 532252884aeSStefan Eßer #define BC_ERR_IDX_FATAL (3) 53344d4804dSStefan Eßer 53444d4804dSStefan Eßer /// Number of categories. 535252884aeSStefan Eßer #define BC_ERR_IDX_NELEMS (4) 536252884aeSStefan Eßer 53744d4804dSStefan Eßer // If bc is enabled, we add an extra category for POSIX warnings. 538252884aeSStefan Eßer #if BC_ENABLED 53944d4804dSStefan Eßer 54044d4804dSStefan Eßer /// POSIX warning category. 541252884aeSStefan Eßer #define BC_ERR_IDX_WARN (BC_ERR_IDX_NELEMS) 54244d4804dSStefan Eßer 543252884aeSStefan Eßer #endif // BC_ENABLED 544252884aeSStefan Eßer 54544d4804dSStefan Eßer /// Do a longjmp(). This is what to use when activating an "exception", i.e., a 54644d4804dSStefan Eßer /// longjmp(). With debug code, it will print the name of the function it jumped 54744d4804dSStefan Eßer /// from. 54844d4804dSStefan Eßer #if BC_DEBUG_CODE 54944d4804dSStefan Eßer #define BC_JMP bc_vm_jmp(__func__) 55044d4804dSStefan Eßer #else // BC_DEBUG_CODE 55144d4804dSStefan Eßer #define BC_JMP bc_vm_jmp() 55244d4804dSStefan Eßer #endif // BC_DEBUG_CODE 55344d4804dSStefan Eßer 55444d4804dSStefan Eßer /// Returns true if an exception is in flight, false otherwise. 55544d4804dSStefan Eßer #define BC_SIG_EXC \ 55644d4804dSStefan Eßer BC_UNLIKELY(vm.status != (sig_atomic_t) BC_STATUS_SUCCESS || vm.sig) 55744d4804dSStefan Eßer 55844d4804dSStefan Eßer /// Returns true if there is *no* exception in flight, false otherwise. 55944d4804dSStefan Eßer #define BC_NO_SIG_EXC \ 56044d4804dSStefan Eßer BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig) 56144d4804dSStefan Eßer 56244d4804dSStefan Eßer #ifndef NDEBUG 56344d4804dSStefan Eßer 56444d4804dSStefan Eßer /// Assert that signals are locked. There are non-async-signal-safe functions in 56544d4804dSStefan Eßer /// bc, and they *must* have signals locked. Other functions are expected to 56644d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert 56744d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are locked. 56844d4804dSStefan Eßer #define BC_SIG_ASSERT_LOCKED do { assert(vm.sig_lock); } while (0) 56944d4804dSStefan Eßer 57044d4804dSStefan Eßer /// Assert that signals are unlocked. There are non-async-signal-safe functions 57144d4804dSStefan Eßer /// in bc, and they *must* have signals locked. Other functions are expected to 57244d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert 57344d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are unlocked. 57444d4804dSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED do { assert(vm.sig_lock == 0); } while (0) 57544d4804dSStefan Eßer 57644d4804dSStefan Eßer #else // NDEBUG 57744d4804dSStefan Eßer 57844d4804dSStefan Eßer /// Assert that signals are locked. There are non-async-signal-safe functions in 57944d4804dSStefan Eßer /// bc, and they *must* have signals locked. Other functions are expected to 58044d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert 58144d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are locked. 58244d4804dSStefan Eßer #define BC_SIG_ASSERT_LOCKED 58344d4804dSStefan Eßer 58444d4804dSStefan Eßer /// Assert that signals are unlocked. There are non-async-signal-safe functions 58544d4804dSStefan Eßer /// in bc, and they *must* have signals locked. Other functions are expected to 58644d4804dSStefan Eßer /// *not* have signals locked, for reasons. So this is a pre-built assert 58744d4804dSStefan Eßer /// (no-op in non-debug mode) that check that signals are unlocked. 58844d4804dSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED 58944d4804dSStefan Eßer 59044d4804dSStefan Eßer #endif // NDEBUG 59144d4804dSStefan Eßer 59244d4804dSStefan Eßer /// Locks signals. 59344d4804dSStefan Eßer #define BC_SIG_LOCK \ 59444d4804dSStefan Eßer do { \ 59544d4804dSStefan Eßer BC_SIG_ASSERT_NOT_LOCKED; \ 59644d4804dSStefan Eßer vm.sig_lock = 1; \ 59744d4804dSStefan Eßer } while (0) 59844d4804dSStefan Eßer 59944d4804dSStefan Eßer /// Unlocks signals. If a signal happened, then this will cause a jump. 60044d4804dSStefan Eßer #define BC_SIG_UNLOCK \ 60144d4804dSStefan Eßer do { \ 60244d4804dSStefan Eßer BC_SIG_ASSERT_LOCKED; \ 60344d4804dSStefan Eßer vm.sig_lock = 0; \ 60444d4804dSStefan Eßer if (vm.sig) BC_JMP; \ 60544d4804dSStefan Eßer } while (0) 60644d4804dSStefan Eßer 60744d4804dSStefan Eßer /// Locks signals, regardless of if they are already locked. This is really only 60844d4804dSStefan Eßer /// used after labels that longjmp() goes to after the jump because the cleanup 60944d4804dSStefan Eßer /// code must have signals locked, and BC_LONGJMP_CONT will unlock signals if it 61044d4804dSStefan Eßer /// doesn't jump. 61144d4804dSStefan Eßer #define BC_SIG_MAYLOCK \ 61244d4804dSStefan Eßer do { \ 61344d4804dSStefan Eßer vm.sig_lock = 1; \ 61444d4804dSStefan Eßer } while (0) 61544d4804dSStefan Eßer 61644d4804dSStefan Eßer /// Unlocks signals, regardless of if they were already unlocked. If a signal 61744d4804dSStefan Eßer /// happened, then this will cause a jump. 61844d4804dSStefan Eßer #define BC_SIG_MAYUNLOCK \ 61944d4804dSStefan Eßer do { \ 62044d4804dSStefan Eßer vm.sig_lock = 0; \ 62144d4804dSStefan Eßer if (vm.sig) BC_JMP; \ 62244d4804dSStefan Eßer } while (0) 62344d4804dSStefan Eßer 62444d4804dSStefan Eßer /* 62544d4804dSStefan Eßer * Locks signals, but stores the old lock state, to be restored later by 62644d4804dSStefan Eßer * BC_SIG_TRYUNLOCK. 62744d4804dSStefan Eßer * @param v The variable to store the old lock state to. 62844d4804dSStefan Eßer */ 62944d4804dSStefan Eßer #define BC_SIG_TRYLOCK(v) \ 63044d4804dSStefan Eßer do { \ 63144d4804dSStefan Eßer v = vm.sig_lock; \ 63244d4804dSStefan Eßer vm.sig_lock = 1; \ 63344d4804dSStefan Eßer } while (0) 63444d4804dSStefan Eßer 63544d4804dSStefan Eßer /* Restores the previous state of a signal lock, and if it is now unlocked, 63644d4804dSStefan Eßer * initiates an exception/jump. 63744d4804dSStefan Eßer * @param v The old lock state. 63844d4804dSStefan Eßer */ 63944d4804dSStefan Eßer #define BC_SIG_TRYUNLOCK(v) \ 64044d4804dSStefan Eßer do { \ 64144d4804dSStefan Eßer vm.sig_lock = (v); \ 64244d4804dSStefan Eßer if (!(v) && vm.sig) BC_JMP; \ 64344d4804dSStefan Eßer } while (0) 64444d4804dSStefan Eßer 64544d4804dSStefan Eßer /** 64644d4804dSStefan Eßer * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will 64744d4804dSStefan Eßer * immediately goto a label where some cleanup code is. This one assumes that 64844d4804dSStefan Eßer * signals are not locked and will lock them, set the jump, and unlock them. 64944d4804dSStefan Eßer * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack. 65044d4804dSStefan Eßer * This grows the jmp_bufs vector first to prevent a fatal error from happening 65144d4804dSStefan Eßer * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used 65244d4804dSStefan Eßer * *before* the actual initialization calls that need the setjmp(). 65344d4804dSStefan Eßer * param l The label to jump to on a longjmp(). 65444d4804dSStefan Eßer */ 65544d4804dSStefan Eßer #define BC_SETJMP(l) \ 65644d4804dSStefan Eßer do { \ 65744d4804dSStefan Eßer sigjmp_buf sjb; \ 65844d4804dSStefan Eßer BC_SIG_LOCK; \ 65944d4804dSStefan Eßer bc_vec_grow(&vm.jmp_bufs, 1); \ 66044d4804dSStefan Eßer if (sigsetjmp(sjb, 0)) { \ 66144d4804dSStefan Eßer assert(BC_SIG_EXC); \ 66244d4804dSStefan Eßer goto l; \ 66344d4804dSStefan Eßer } \ 66444d4804dSStefan Eßer bc_vec_push(&vm.jmp_bufs, &sjb); \ 66544d4804dSStefan Eßer BC_SIG_UNLOCK; \ 66644d4804dSStefan Eßer } while (0) 66744d4804dSStefan Eßer 66844d4804dSStefan Eßer /** 66944d4804dSStefan Eßer * Sets a jump like BC_SETJMP, but unlike BC_SETJMP, it assumes signals are 67044d4804dSStefan Eßer * locked and will just set the jump. This does *not* have a call to 67144d4804dSStefan Eßer * bc_vec_grow() because it is assumed that BC_SETJMP_LOCKED(l) is used *after* 67244d4804dSStefan Eßer * the initializations that need the setjmp(). 67344d4804dSStefan Eßer * param l The label to jump to on a longjmp(). 67444d4804dSStefan Eßer */ 67544d4804dSStefan Eßer #define BC_SETJMP_LOCKED(l) \ 67644d4804dSStefan Eßer do { \ 67744d4804dSStefan Eßer sigjmp_buf sjb; \ 67844d4804dSStefan Eßer BC_SIG_ASSERT_LOCKED; \ 67944d4804dSStefan Eßer if (sigsetjmp(sjb, 0)) { \ 68044d4804dSStefan Eßer assert(BC_SIG_EXC); \ 68144d4804dSStefan Eßer goto l; \ 68244d4804dSStefan Eßer } \ 68344d4804dSStefan Eßer bc_vec_push(&vm.jmp_bufs, &sjb); \ 68444d4804dSStefan Eßer } while (0) 68544d4804dSStefan Eßer 68644d4804dSStefan Eßer /// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to 68744d4804dSStefan Eßer /// the next place. This is what continues the stack unwinding. This basically 68844d4804dSStefan Eßer /// copies BC_SIG_UNLOCK into itself, but that is because its condition for 68944d4804dSStefan Eßer /// jumping is BC_SIG_EXC, not just that a signal happened. 69044d4804dSStefan Eßer #define BC_LONGJMP_CONT \ 69144d4804dSStefan Eßer do { \ 69244d4804dSStefan Eßer BC_SIG_ASSERT_LOCKED; \ 69344d4804dSStefan Eßer if (!vm.sig_pop) bc_vec_pop(&vm.jmp_bufs); \ 69444d4804dSStefan Eßer vm.sig_lock = 0; \ 69544d4804dSStefan Eßer if (BC_SIG_EXC) BC_JMP; \ 69644d4804dSStefan Eßer } while (0) 69744d4804dSStefan Eßer 69844d4804dSStefan Eßer /// Unsets a jump. It always assumes signals are locked. This basically just 69944d4804dSStefan Eßer /// pops a jmp_buf off of the stack of jmp_bufs, and since the jump mechanism 70044d4804dSStefan Eßer /// always jumps to the location at the top of the stack, this effectively 70144d4804dSStefan Eßer /// undoes a setjmp(). 70244d4804dSStefan Eßer #define BC_UNSETJMP \ 70344d4804dSStefan Eßer do { \ 70444d4804dSStefan Eßer BC_SIG_ASSERT_LOCKED; \ 70544d4804dSStefan Eßer bc_vec_pop(&vm.jmp_bufs); \ 70644d4804dSStefan Eßer } while (0) 70744d4804dSStefan Eßer 70844d4804dSStefan Eßer /// Stops a stack unwinding. Technically, a stack unwinding needs to be done 70944d4804dSStefan Eßer /// manually, but it will always be done unless certain flags are cleared. This 71044d4804dSStefan Eßer /// clears the flags. 71144d4804dSStefan Eßer #define BC_LONGJMP_STOP \ 71244d4804dSStefan Eßer do { \ 71344d4804dSStefan Eßer vm.sig_pop = 0; \ 71444d4804dSStefan Eßer vm.sig = 0; \ 71544d4804dSStefan Eßer } while (0) 71644d4804dSStefan Eßer 71744d4804dSStefan Eßer // Various convenience macros for calling the bc's error handling routine. 71844d4804dSStefan Eßer #if BC_ENABLE_LIBRARY 71944d4804dSStefan Eßer 72044d4804dSStefan Eßer /** 72144d4804dSStefan Eßer * Call bc's error handling routine. 72244d4804dSStefan Eßer * @param e The error. 72344d4804dSStefan Eßer * @param l The line of the script that the error happened. 72444d4804dSStefan Eßer * @param ... Extra arguments for error messages as necessary. 72544d4804dSStefan Eßer */ 72644d4804dSStefan Eßer #define bc_error(e, l, ...) (bc_vm_handleError((e))) 72744d4804dSStefan Eßer 72844d4804dSStefan Eßer /** 72944d4804dSStefan Eßer * Call bc's error handling routine. 73044d4804dSStefan Eßer * @param e The error. 73144d4804dSStefan Eßer */ 73244d4804dSStefan Eßer #define bc_err(e) (bc_vm_handleError((e))) 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_verr(e, ...) (bc_vm_handleError((e))) 73944d4804dSStefan Eßer 74044d4804dSStefan Eßer #else // BC_ENABLE_LIBRARY 74144d4804dSStefan Eßer 74244d4804dSStefan Eßer /** 74344d4804dSStefan Eßer * Call bc's error handling routine. 74444d4804dSStefan Eßer * @param e The error. 74544d4804dSStefan Eßer * @param l The line of the script that the error happened. 74644d4804dSStefan Eßer * @param ... Extra arguments for error messages as necessary. 74744d4804dSStefan Eßer */ 74844d4804dSStefan Eßer #define bc_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__)) 74944d4804dSStefan Eßer 75044d4804dSStefan Eßer /** 75144d4804dSStefan Eßer * Call bc's error handling routine. 75244d4804dSStefan Eßer * @param e The error. 75344d4804dSStefan Eßer */ 75444d4804dSStefan Eßer #define bc_err(e) (bc_vm_handleError((e), 0)) 75544d4804dSStefan Eßer 75644d4804dSStefan Eßer /** 75744d4804dSStefan Eßer * Call bc's error handling routine. 75844d4804dSStefan Eßer * @param e The error. 75944d4804dSStefan Eßer */ 76044d4804dSStefan Eßer #define bc_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__)) 76144d4804dSStefan Eßer 76244d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY 76344d4804dSStefan Eßer 76444d4804dSStefan Eßer /** 76544d4804dSStefan Eßer * Returns true if status @a s is an error, false otherwise. 76644d4804dSStefan Eßer * @param s The status to test. 76744d4804dSStefan Eßer * @return True if @a s is an error, false otherwise. 76844d4804dSStefan Eßer */ 76944d4804dSStefan Eßer #define BC_STATUS_IS_ERROR(s) \ 77044d4804dSStefan Eßer ((s) >= BC_STATUS_ERROR_MATH && (s) <= BC_STATUS_ERROR_FATAL) 77144d4804dSStefan Eßer 77244d4804dSStefan Eßer // Convenience macros that can be placed at the beginning and exits of functions 77344d4804dSStefan Eßer // for easy marking of where functions are entered and exited. 77444d4804dSStefan Eßer #if BC_DEBUG_CODE 77544d4804dSStefan Eßer #define BC_FUNC_ENTER \ 77644d4804dSStefan Eßer do { \ 77744d4804dSStefan Eßer size_t bc_func_enter_i; \ 77844d4804dSStefan Eßer for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \ 77944d4804dSStefan Eßer ++bc_func_enter_i) \ 78044d4804dSStefan Eßer { \ 78144d4804dSStefan Eßer bc_file_puts(&vm.ferr, bc_flush_none, " "); \ 78244d4804dSStefan Eßer } \ 78344d4804dSStefan Eßer vm.func_depth += 1; \ 78444d4804dSStefan Eßer bc_file_printf(&vm.ferr, "Entering %s\n", __func__); \ 78544d4804dSStefan Eßer bc_file_flush(&vm.ferr, bc_flush_none); \ 78644d4804dSStefan Eßer } while (0); 78744d4804dSStefan Eßer 78844d4804dSStefan Eßer #define BC_FUNC_EXIT \ 78944d4804dSStefan Eßer do { \ 79044d4804dSStefan Eßer size_t bc_func_enter_i; \ 79144d4804dSStefan Eßer vm.func_depth -= 1; \ 79244d4804dSStefan Eßer for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \ 79344d4804dSStefan Eßer ++bc_func_enter_i) \ 79444d4804dSStefan Eßer { \ 79544d4804dSStefan Eßer bc_file_puts(&vm.ferr, bc_flush_none, " "); \ 79644d4804dSStefan Eßer } \ 79744d4804dSStefan Eßer bc_file_printf(&vm.ferr, "Leaving %s\n", __func__); \ 79844d4804dSStefan Eßer bc_file_flush(&vm.ferr, bc_flush_none); \ 79944d4804dSStefan Eßer } while (0); 80044d4804dSStefan Eßer #else // BC_DEBUG_CODE 80144d4804dSStefan Eßer #define BC_FUNC_ENTER 80244d4804dSStefan Eßer #define BC_FUNC_EXIT 80344d4804dSStefan Eßer #endif // BC_DEBUG_CODE 80444d4804dSStefan Eßer 805252884aeSStefan Eßer #endif // BC_STATUS_H 806