xref: /aosp_15_r20/external/bc/include/status.h (revision 5a6e848804d15c18a0125914844ee4eb0bda4fcf)
1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker  *
4*5a6e8488SAndroid Build Coastguard Worker  * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker  *
6*5a6e8488SAndroid Build Coastguard Worker  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker  *
8*5a6e8488SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker  *
11*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker  *   list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker  *
14*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker  *
18*5a6e8488SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker  *
30*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker  *
32*5a6e8488SAndroid Build Coastguard Worker  * All bc status codes and cross-platform portability.
33*5a6e8488SAndroid Build Coastguard Worker  *
34*5a6e8488SAndroid Build Coastguard Worker  */
35*5a6e8488SAndroid Build Coastguard Worker 
36*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_STATUS_H
37*5a6e8488SAndroid Build Coastguard Worker #define BC_STATUS_H
38*5a6e8488SAndroid Build Coastguard Worker 
39*5a6e8488SAndroid Build Coastguard Worker #ifdef _WIN32
40*5a6e8488SAndroid Build Coastguard Worker #include <Windows.h>
41*5a6e8488SAndroid Build Coastguard Worker #include <BaseTsd.h>
42*5a6e8488SAndroid Build Coastguard Worker #include <stdio.h>
43*5a6e8488SAndroid Build Coastguard Worker #include <io.h>
44*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
45*5a6e8488SAndroid Build Coastguard Worker 
46*5a6e8488SAndroid Build Coastguard Worker #include <stdint.h>
47*5a6e8488SAndroid Build Coastguard Worker #include <sys/types.h>
48*5a6e8488SAndroid Build Coastguard Worker 
49*5a6e8488SAndroid Build Coastguard Worker // Windows has deprecated isatty() and the rest of these. Or doesn't have them.
50*5a6e8488SAndroid Build Coastguard Worker // So these are just fixes for Windows.
51*5a6e8488SAndroid Build Coastguard Worker #ifdef _WIN32
52*5a6e8488SAndroid Build Coastguard Worker 
53*5a6e8488SAndroid Build Coastguard Worker // This one is special. Windows did not like me defining an
54*5a6e8488SAndroid Build Coastguard Worker // inline function that was not given a definition in a header
55*5a6e8488SAndroid Build Coastguard Worker // file. This suppresses that by making inline functions non-inline.
56*5a6e8488SAndroid Build Coastguard Worker #define inline
57*5a6e8488SAndroid Build Coastguard Worker 
58*5a6e8488SAndroid Build Coastguard Worker #define restrict __restrict
59*5a6e8488SAndroid Build Coastguard Worker #define strdup _strdup
60*5a6e8488SAndroid Build Coastguard Worker #define write(f, b, s) _write((f), (b), (unsigned int) (s))
61*5a6e8488SAndroid Build Coastguard Worker #define read(f, b, s) _read((f), (b), (unsigned int) (s))
62*5a6e8488SAndroid Build Coastguard Worker #define close _close
63*5a6e8488SAndroid Build Coastguard Worker #define open(f, n, m) \
64*5a6e8488SAndroid Build Coastguard Worker 	_sopen_s((f), (n), (m) | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE)
65*5a6e8488SAndroid Build Coastguard Worker #define sigjmp_buf jmp_buf
66*5a6e8488SAndroid Build Coastguard Worker #define sigsetjmp(j, s) setjmp(j)
67*5a6e8488SAndroid Build Coastguard Worker #define siglongjmp longjmp
68*5a6e8488SAndroid Build Coastguard Worker #define isatty _isatty
69*5a6e8488SAndroid Build Coastguard Worker #define STDIN_FILENO _fileno(stdin)
70*5a6e8488SAndroid Build Coastguard Worker #define STDOUT_FILENO _fileno(stdout)
71*5a6e8488SAndroid Build Coastguard Worker #define STDERR_FILENO _fileno(stderr)
72*5a6e8488SAndroid Build Coastguard Worker #define S_ISDIR(m) ((m) & (_S_IFDIR))
73*5a6e8488SAndroid Build Coastguard Worker #define O_RDONLY _O_RDONLY
74*5a6e8488SAndroid Build Coastguard Worker #define stat _stat
75*5a6e8488SAndroid Build Coastguard Worker #define fstat _fstat
76*5a6e8488SAndroid Build Coastguard Worker #define BC_FILE_SEP '\\'
77*5a6e8488SAndroid Build Coastguard Worker 
78*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
79*5a6e8488SAndroid Build Coastguard Worker #define BC_FILE_SEP '/'
80*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
81*5a6e8488SAndroid Build Coastguard Worker 
82*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLED
83*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLED (1)
84*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
85*5a6e8488SAndroid Build Coastguard Worker 
86*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_ENABLED
87*5a6e8488SAndroid Build Coastguard Worker #define DC_ENABLED (1)
88*5a6e8488SAndroid Build Coastguard Worker #endif // DC_ENABLED
89*5a6e8488SAndroid Build Coastguard Worker 
90*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_EXTRA_MATH
91*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_EXTRA_MATH (1)
92*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
93*5a6e8488SAndroid Build Coastguard Worker 
94*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_LIBRARY
95*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_LIBRARY (0)
96*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
97*5a6e8488SAndroid Build Coastguard Worker 
98*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_HISTORY
99*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_HISTORY (1)
100*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_HISTORY
101*5a6e8488SAndroid Build Coastguard Worker 
102*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_EDITLINE
103*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_EDITLINE (0)
104*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EDITLINE
105*5a6e8488SAndroid Build Coastguard Worker 
106*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_READLINE
107*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_READLINE (0)
108*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_READLINE
109*5a6e8488SAndroid Build Coastguard Worker 
110*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_NLS
111*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_NLS (0)
112*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_NLS
113*5a6e8488SAndroid Build Coastguard Worker 
114*5a6e8488SAndroid Build Coastguard Worker #ifdef __OpenBSD__
115*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_READLINE
116*5a6e8488SAndroid Build Coastguard Worker #error Cannot use readline on OpenBSD
117*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_READLINE
118*5a6e8488SAndroid Build Coastguard Worker #endif // __OpenBSD__
119*5a6e8488SAndroid Build Coastguard Worker 
120*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
121*5a6e8488SAndroid Build Coastguard Worker #error Must enable only one of editline or readline, not both.
122*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EDITLINE && BC_ENABLE_READLINE
123*5a6e8488SAndroid Build Coastguard Worker 
124*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
125*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_LINE_LIB (1)
126*5a6e8488SAndroid Build Coastguard Worker #else // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
127*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_LINE_LIB (0)
128*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE
129*5a6e8488SAndroid Build Coastguard Worker 
130*5a6e8488SAndroid Build Coastguard Worker // This is error checking for fuzz builds.
131*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_AFL
132*5a6e8488SAndroid Build Coastguard Worker #ifndef __AFL_HAVE_MANUAL_CONTROL
133*5a6e8488SAndroid Build Coastguard Worker #error Must compile with afl-clang-fast or afl-clang-lto for fuzzing
134*5a6e8488SAndroid Build Coastguard Worker #endif // __AFL_HAVE_MANUAL_CONTROL
135*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_AFL
136*5a6e8488SAndroid Build Coastguard Worker 
137*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_ENABLE_MEMCHECK
138*5a6e8488SAndroid Build Coastguard Worker #define BC_ENABLE_MEMCHECK (0)
139*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
140*5a6e8488SAndroid Build Coastguard Worker 
141*5a6e8488SAndroid Build Coastguard Worker /**
142*5a6e8488SAndroid Build Coastguard Worker  * Mark a variable as unused.
143*5a6e8488SAndroid Build Coastguard Worker  * @param e  The variable to mark as unused.
144*5a6e8488SAndroid Build Coastguard Worker  */
145*5a6e8488SAndroid Build Coastguard Worker #define BC_UNUSED(e) ((void) (e))
146*5a6e8488SAndroid Build Coastguard Worker 
147*5a6e8488SAndroid Build Coastguard Worker // If users want, they can define this to something like __builtin_expect(e, 1).
148*5a6e8488SAndroid Build Coastguard Worker // It might give a performance improvement.
149*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_LIKELY
150*5a6e8488SAndroid Build Coastguard Worker 
151*5a6e8488SAndroid Build Coastguard Worker /**
152*5a6e8488SAndroid Build Coastguard Worker  * Mark a branch expression as likely.
153*5a6e8488SAndroid Build Coastguard Worker  * @param e  The expression to mark as likely.
154*5a6e8488SAndroid Build Coastguard Worker  */
155*5a6e8488SAndroid Build Coastguard Worker #define BC_LIKELY(e) (e)
156*5a6e8488SAndroid Build Coastguard Worker 
157*5a6e8488SAndroid Build Coastguard Worker #endif // BC_LIKELY
158*5a6e8488SAndroid Build Coastguard Worker 
159*5a6e8488SAndroid Build Coastguard Worker // If users want, they can define this to something like __builtin_expect(e, 0).
160*5a6e8488SAndroid Build Coastguard Worker // It might give a performance improvement.
161*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_UNLIKELY
162*5a6e8488SAndroid Build Coastguard Worker 
163*5a6e8488SAndroid Build Coastguard Worker /**
164*5a6e8488SAndroid Build Coastguard Worker  * Mark a branch expression as unlikely.
165*5a6e8488SAndroid Build Coastguard Worker  * @param e  The expression to mark as unlikely.
166*5a6e8488SAndroid Build Coastguard Worker  */
167*5a6e8488SAndroid Build Coastguard Worker #define BC_UNLIKELY(e) (e)
168*5a6e8488SAndroid Build Coastguard Worker 
169*5a6e8488SAndroid Build Coastguard Worker #endif // BC_UNLIKELY
170*5a6e8488SAndroid Build Coastguard Worker 
171*5a6e8488SAndroid Build Coastguard Worker /**
172*5a6e8488SAndroid Build Coastguard Worker  * Mark a branch expression as an error, if true.
173*5a6e8488SAndroid Build Coastguard Worker  * @param e  The expression to mark as an error, if true.
174*5a6e8488SAndroid Build Coastguard Worker  */
175*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR(e) BC_UNLIKELY(e)
176*5a6e8488SAndroid Build Coastguard Worker 
177*5a6e8488SAndroid Build Coastguard Worker /**
178*5a6e8488SAndroid Build Coastguard Worker  * Mark a branch expression as not an error, if true.
179*5a6e8488SAndroid Build Coastguard Worker  * @param e  The expression to mark as not an error, if true.
180*5a6e8488SAndroid Build Coastguard Worker  */
181*5a6e8488SAndroid Build Coastguard Worker #define BC_NO_ERR(s) BC_LIKELY(s)
182*5a6e8488SAndroid Build Coastguard Worker 
183*5a6e8488SAndroid Build Coastguard Worker // Disable extra debug code by default.
184*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEBUG_CODE
185*5a6e8488SAndroid Build Coastguard Worker #define BC_DEBUG_CODE (0)
186*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG_CODE
187*5a6e8488SAndroid Build Coastguard Worker 
188*5a6e8488SAndroid Build Coastguard Worker #if defined(__clang__)
189*5a6e8488SAndroid Build Coastguard Worker #define BC_CLANG (1)
190*5a6e8488SAndroid Build Coastguard Worker #else // defined(__clang__)
191*5a6e8488SAndroid Build Coastguard Worker #define BC_CLANG (0)
192*5a6e8488SAndroid Build Coastguard Worker #endif // defined(__clang__)
193*5a6e8488SAndroid Build Coastguard Worker 
194*5a6e8488SAndroid Build Coastguard Worker #if defined(__GNUC__) && !BC_CLANG
195*5a6e8488SAndroid Build Coastguard Worker #define BC_GCC (1)
196*5a6e8488SAndroid Build Coastguard Worker #else // defined(__GNUC__) && !BC_CLANG
197*5a6e8488SAndroid Build Coastguard Worker #define BC_GCC (0)
198*5a6e8488SAndroid Build Coastguard Worker #endif // defined(__GNUC__) && !BC_CLANG
199*5a6e8488SAndroid Build Coastguard Worker 
200*5a6e8488SAndroid Build Coastguard Worker // We want to be able to use _Noreturn on C11 compilers.
201*5a6e8488SAndroid Build Coastguard Worker #if __STDC_VERSION__ >= 201112L
202*5a6e8488SAndroid Build Coastguard Worker 
203*5a6e8488SAndroid Build Coastguard Worker #include <stdnoreturn.h>
204*5a6e8488SAndroid Build Coastguard Worker #define BC_NORETURN _Noreturn
205*5a6e8488SAndroid Build Coastguard Worker #define BC_C11 (1)
206*5a6e8488SAndroid Build Coastguard Worker 
207*5a6e8488SAndroid Build Coastguard Worker #else // __STDC_VERSION__
208*5a6e8488SAndroid Build Coastguard Worker 
209*5a6e8488SAndroid Build Coastguard Worker #if BC_CLANG
210*5a6e8488SAndroid Build Coastguard Worker #if __has_attribute(noreturn)
211*5a6e8488SAndroid Build Coastguard Worker #define BC_NORETURN __attribute((noreturn))
212*5a6e8488SAndroid Build Coastguard Worker #else // __has_attribute(noreturn)
213*5a6e8488SAndroid Build Coastguard Worker #define BC_NORETURN
214*5a6e8488SAndroid Build Coastguard Worker #endif // __has_attribute(noreturn)
215*5a6e8488SAndroid Build Coastguard Worker 
216*5a6e8488SAndroid Build Coastguard Worker #else // BC_CLANG
217*5a6e8488SAndroid Build Coastguard Worker 
218*5a6e8488SAndroid Build Coastguard Worker #define BC_NORETURN
219*5a6e8488SAndroid Build Coastguard Worker 
220*5a6e8488SAndroid Build Coastguard Worker #endif // BC_CLANG
221*5a6e8488SAndroid Build Coastguard Worker 
222*5a6e8488SAndroid Build Coastguard Worker #define BC_MUST_RETURN
223*5a6e8488SAndroid Build Coastguard Worker #define BC_C11 (0)
224*5a6e8488SAndroid Build Coastguard Worker 
225*5a6e8488SAndroid Build Coastguard Worker #endif // __STDC_VERSION__
226*5a6e8488SAndroid Build Coastguard Worker 
227*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_UNREACHABLE (0)
228*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_COMPUTED_GOTO (0)
229*5a6e8488SAndroid Build Coastguard Worker 
230*5a6e8488SAndroid Build Coastguard Worker // GCC and Clang complain if fallthroughs are not marked with their special
231*5a6e8488SAndroid Build Coastguard Worker // attribute. Jerks. This creates a define for marking the fallthroughs that is
232*5a6e8488SAndroid Build Coastguard Worker // nothing on other compilers.
233*5a6e8488SAndroid Build Coastguard Worker #if BC_CLANG || BC_GCC
234*5a6e8488SAndroid Build Coastguard Worker 
235*5a6e8488SAndroid Build Coastguard Worker #if defined(__has_attribute)
236*5a6e8488SAndroid Build Coastguard Worker 
237*5a6e8488SAndroid Build Coastguard Worker #if __has_attribute(fallthrough)
238*5a6e8488SAndroid Build Coastguard Worker #define BC_FALLTHROUGH __attribute__((fallthrough));
239*5a6e8488SAndroid Build Coastguard Worker #else // __has_attribute(fallthrough)
240*5a6e8488SAndroid Build Coastguard Worker #define BC_FALLTHROUGH
241*5a6e8488SAndroid Build Coastguard Worker #endif // __has_attribute(fallthrough)
242*5a6e8488SAndroid Build Coastguard Worker 
243*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
244*5a6e8488SAndroid Build Coastguard Worker 
245*5a6e8488SAndroid Build Coastguard Worker #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
246*5a6e8488SAndroid Build Coastguard Worker #undef BC_HAS_UNREACHABLE
247*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_UNREACHABLE (1)
248*5a6e8488SAndroid Build Coastguard Worker #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
249*5a6e8488SAndroid Build Coastguard Worker 
250*5a6e8488SAndroid Build Coastguard Worker #else // BC_GCC
251*5a6e8488SAndroid Build Coastguard Worker 
252*5a6e8488SAndroid Build Coastguard Worker #if __clang_major__ >= 4
253*5a6e8488SAndroid Build Coastguard Worker #undef BC_HAS_UNREACHABLE
254*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_UNREACHABLE (1)
255*5a6e8488SAndroid Build Coastguard Worker #endif // __clang_major__ >= 4
256*5a6e8488SAndroid Build Coastguard Worker 
257*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
258*5a6e8488SAndroid Build Coastguard Worker 
259*5a6e8488SAndroid Build Coastguard Worker #else // defined(__has_attribute)
260*5a6e8488SAndroid Build Coastguard Worker #define BC_FALLTHROUGH
261*5a6e8488SAndroid Build Coastguard Worker #endif // defined(__has_attribute)
262*5a6e8488SAndroid Build Coastguard Worker #else // BC_CLANG || BC_GCC
263*5a6e8488SAndroid Build Coastguard Worker #define BC_FALLTHROUGH
264*5a6e8488SAndroid Build Coastguard Worker #endif // BC_CLANG || BC_GCC
265*5a6e8488SAndroid Build Coastguard Worker 
266*5a6e8488SAndroid Build Coastguard Worker #if BC_HAS_UNREACHABLE
267*5a6e8488SAndroid Build Coastguard Worker 
268*5a6e8488SAndroid Build Coastguard Worker #define BC_UNREACHABLE __builtin_unreachable();
269*5a6e8488SAndroid Build Coastguard Worker 
270*5a6e8488SAndroid Build Coastguard Worker #else // BC_HAS_UNREACHABLE
271*5a6e8488SAndroid Build Coastguard Worker 
272*5a6e8488SAndroid Build Coastguard Worker #ifdef _WIN32
273*5a6e8488SAndroid Build Coastguard Worker 
274*5a6e8488SAndroid Build Coastguard Worker #define BC_UNREACHABLE __assume(0);
275*5a6e8488SAndroid Build Coastguard Worker 
276*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
277*5a6e8488SAndroid Build Coastguard Worker 
278*5a6e8488SAndroid Build Coastguard Worker #define BC_UNREACHABLE
279*5a6e8488SAndroid Build Coastguard Worker 
280*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
281*5a6e8488SAndroid Build Coastguard Worker 
282*5a6e8488SAndroid Build Coastguard Worker #endif // BC_HAS_UNREACHABLE
283*5a6e8488SAndroid Build Coastguard Worker 
284*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
285*5a6e8488SAndroid Build Coastguard Worker 
286*5a6e8488SAndroid Build Coastguard Worker #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
287*5a6e8488SAndroid Build Coastguard Worker 
288*5a6e8488SAndroid Build Coastguard Worker #undef BC_HAS_COMPUTED_GOTO
289*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_COMPUTED_GOTO (1)
290*5a6e8488SAndroid Build Coastguard Worker 
291*5a6e8488SAndroid Build Coastguard Worker #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
292*5a6e8488SAndroid Build Coastguard Worker 
293*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
294*5a6e8488SAndroid Build Coastguard Worker 
295*5a6e8488SAndroid Build Coastguard Worker #if BC_CLANG
296*5a6e8488SAndroid Build Coastguard Worker 
297*5a6e8488SAndroid Build Coastguard Worker #if __clang_major__ >= 4
298*5a6e8488SAndroid Build Coastguard Worker 
299*5a6e8488SAndroid Build Coastguard Worker #undef BC_HAS_COMPUTED_GOTO
300*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_COMPUTED_GOTO (1)
301*5a6e8488SAndroid Build Coastguard Worker 
302*5a6e8488SAndroid Build Coastguard Worker #endif // __clang_major__ >= 4
303*5a6e8488SAndroid Build Coastguard Worker 
304*5a6e8488SAndroid Build Coastguard Worker #endif // BC_CLANG
305*5a6e8488SAndroid Build Coastguard Worker 
306*5a6e8488SAndroid Build Coastguard Worker #ifdef BC_NO_COMPUTED_GOTO
307*5a6e8488SAndroid Build Coastguard Worker 
308*5a6e8488SAndroid Build Coastguard Worker #undef BC_HAS_COMPUTED_GOTO
309*5a6e8488SAndroid Build Coastguard Worker #define BC_HAS_COMPUTED_GOTO (0)
310*5a6e8488SAndroid Build Coastguard Worker 
311*5a6e8488SAndroid Build Coastguard Worker #endif // BC_NO_COMPUTED_GOTO
312*5a6e8488SAndroid Build Coastguard Worker 
313*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
314*5a6e8488SAndroid Build Coastguard Worker #ifdef __OpenBSD__
315*5a6e8488SAndroid Build Coastguard Worker // The OpenBSD GCC doesn't like inline.
316*5a6e8488SAndroid Build Coastguard Worker #define inline
317*5a6e8488SAndroid Build Coastguard Worker #endif // __OpenBSD__
318*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
319*5a6e8488SAndroid Build Coastguard Worker 
320*5a6e8488SAndroid Build Coastguard Worker // Workarounds for AIX's POSIX incompatibility.
321*5a6e8488SAndroid Build Coastguard Worker #ifndef SIZE_MAX
322*5a6e8488SAndroid Build Coastguard Worker #define SIZE_MAX __SIZE_MAX__
323*5a6e8488SAndroid Build Coastguard Worker #endif // SIZE_MAX
324*5a6e8488SAndroid Build Coastguard Worker #ifndef UINTMAX_C
325*5a6e8488SAndroid Build Coastguard Worker #define UINTMAX_C __UINTMAX_C
326*5a6e8488SAndroid Build Coastguard Worker #endif // UINTMAX_C
327*5a6e8488SAndroid Build Coastguard Worker #ifndef UINT32_C
328*5a6e8488SAndroid Build Coastguard Worker #define UINT32_C __UINT32_C
329*5a6e8488SAndroid Build Coastguard Worker #endif // UINT32_C
330*5a6e8488SAndroid Build Coastguard Worker #ifndef UINT_FAST32_MAX
331*5a6e8488SAndroid Build Coastguard Worker #define UINT_FAST32_MAX __UINT_FAST32_MAX__
332*5a6e8488SAndroid Build Coastguard Worker #endif // UINT_FAST32_MAX
333*5a6e8488SAndroid Build Coastguard Worker #ifndef UINT16_MAX
334*5a6e8488SAndroid Build Coastguard Worker #define UINT16_MAX __UINT16_MAX__
335*5a6e8488SAndroid Build Coastguard Worker #endif // UINT16_MAX
336*5a6e8488SAndroid Build Coastguard Worker #ifndef SIG_ATOMIC_MAX
337*5a6e8488SAndroid Build Coastguard Worker #define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
338*5a6e8488SAndroid Build Coastguard Worker #endif // SIG_ATOMIC_MAX
339*5a6e8488SAndroid Build Coastguard Worker 
340*5a6e8488SAndroid Build Coastguard Worker // Yes, this has to be here.
341*5a6e8488SAndroid Build Coastguard Worker #include <bcl.h>
342*5a6e8488SAndroid Build Coastguard Worker 
343*5a6e8488SAndroid Build Coastguard Worker // All of these set defaults for settings.
344*5a6e8488SAndroid Build Coastguard Worker 
345*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLED
346*5a6e8488SAndroid Build Coastguard Worker 
347*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_BANNER
348*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_BANNER (0)
349*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_BANNER
350*5a6e8488SAndroid Build Coastguard Worker 
351*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
352*5a6e8488SAndroid Build Coastguard Worker 
353*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_SIGINT_RESET
354*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_SIGINT_RESET (1)
355*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_SIGINT_RESET
356*5a6e8488SAndroid Build Coastguard Worker 
357*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_TTY_MODE
358*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_TTY_MODE (1)
359*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_TTY_MODE
360*5a6e8488SAndroid Build Coastguard Worker 
361*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_PROMPT
362*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_PROMPT BC_DEFAULT_TTY_MODE
363*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_PROMPT
364*5a6e8488SAndroid Build Coastguard Worker 
365*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_EXPR_EXIT
366*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_EXPR_EXIT (1)
367*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_EXPR_EXIT
368*5a6e8488SAndroid Build Coastguard Worker 
369*5a6e8488SAndroid Build Coastguard Worker #ifndef BC_DEFAULT_DIGIT_CLAMP
370*5a6e8488SAndroid Build Coastguard Worker #define BC_DEFAULT_DIGIT_CLAMP (0)
371*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEFAULT_DIGIT_CLAMP
372*5a6e8488SAndroid Build Coastguard Worker 
373*5a6e8488SAndroid Build Coastguard Worker // All of these set defaults for settings.
374*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_SIGINT_RESET
375*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_SIGINT_RESET (1)
376*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_SIGINT_RESET
377*5a6e8488SAndroid Build Coastguard Worker 
378*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_TTY_MODE
379*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_TTY_MODE (0)
380*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_TTY_MODE
381*5a6e8488SAndroid Build Coastguard Worker 
382*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_HISTORY
383*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_HISTORY DC_DEFAULT_TTY_MODE
384*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_HISTORY
385*5a6e8488SAndroid Build Coastguard Worker 
386*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_PROMPT
387*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_PROMPT DC_DEFAULT_TTY_MODE
388*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_PROMPT
389*5a6e8488SAndroid Build Coastguard Worker 
390*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_EXPR_EXIT
391*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_EXPR_EXIT (1)
392*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_EXPR_EXIT
393*5a6e8488SAndroid Build Coastguard Worker 
394*5a6e8488SAndroid Build Coastguard Worker #ifndef DC_DEFAULT_DIGIT_CLAMP
395*5a6e8488SAndroid Build Coastguard Worker #define DC_DEFAULT_DIGIT_CLAMP (0)
396*5a6e8488SAndroid Build Coastguard Worker #endif // DC_DEFAULT_DIGIT_CLAMP
397*5a6e8488SAndroid Build Coastguard Worker 
398*5a6e8488SAndroid Build Coastguard Worker /// Statuses, which mark either which category of error happened, or some other
399*5a6e8488SAndroid Build Coastguard Worker /// status that matters.
400*5a6e8488SAndroid Build Coastguard Worker typedef enum BcStatus
401*5a6e8488SAndroid Build Coastguard Worker {
402*5a6e8488SAndroid Build Coastguard Worker 	/// Normal status.
403*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_SUCCESS = 0,
404*5a6e8488SAndroid Build Coastguard Worker 
405*5a6e8488SAndroid Build Coastguard Worker 	/// Math error.
406*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_ERROR_MATH,
407*5a6e8488SAndroid Build Coastguard Worker 
408*5a6e8488SAndroid Build Coastguard Worker 	/// Parse (and lex) error.
409*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_ERROR_PARSE,
410*5a6e8488SAndroid Build Coastguard Worker 
411*5a6e8488SAndroid Build Coastguard Worker 	/// Runtime error.
412*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_ERROR_EXEC,
413*5a6e8488SAndroid Build Coastguard Worker 
414*5a6e8488SAndroid Build Coastguard Worker 	/// Fatal error.
415*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_ERROR_FATAL,
416*5a6e8488SAndroid Build Coastguard Worker 
417*5a6e8488SAndroid Build Coastguard Worker 	/// EOF status.
418*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_EOF,
419*5a6e8488SAndroid Build Coastguard Worker 
420*5a6e8488SAndroid Build Coastguard Worker 	/// Quit status. This means that bc/dc is in the process of quitting.
421*5a6e8488SAndroid Build Coastguard Worker 	BC_STATUS_QUIT,
422*5a6e8488SAndroid Build Coastguard Worker 
423*5a6e8488SAndroid Build Coastguard Worker } BcStatus;
424*5a6e8488SAndroid Build Coastguard Worker 
425*5a6e8488SAndroid Build Coastguard Worker /// Errors, which are more specific errors.
426*5a6e8488SAndroid Build Coastguard Worker typedef enum BcErr
427*5a6e8488SAndroid Build Coastguard Worker {
428*5a6e8488SAndroid Build Coastguard Worker 	// Math errors.
429*5a6e8488SAndroid Build Coastguard Worker 
430*5a6e8488SAndroid Build Coastguard Worker 	/// Negative number used when not allowed.
431*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_MATH_NEGATIVE,
432*5a6e8488SAndroid Build Coastguard Worker 
433*5a6e8488SAndroid Build Coastguard Worker 	/// Non-integer used when not allowed.
434*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_MATH_NON_INTEGER,
435*5a6e8488SAndroid Build Coastguard Worker 
436*5a6e8488SAndroid Build Coastguard Worker 	/// Conversion to a hardware integer would overflow.
437*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_MATH_OVERFLOW,
438*5a6e8488SAndroid Build Coastguard Worker 
439*5a6e8488SAndroid Build Coastguard Worker 	/// Divide by zero.
440*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_MATH_DIVIDE_BY_ZERO,
441*5a6e8488SAndroid Build Coastguard Worker 
442*5a6e8488SAndroid Build Coastguard Worker 	// Fatal errors.
443*5a6e8488SAndroid Build Coastguard Worker 
444*5a6e8488SAndroid Build Coastguard Worker 	/// An allocation or reallocation failed.
445*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_ALLOC_ERR,
446*5a6e8488SAndroid Build Coastguard Worker 
447*5a6e8488SAndroid Build Coastguard Worker 	/// I/O failure.
448*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_IO_ERR,
449*5a6e8488SAndroid Build Coastguard Worker 
450*5a6e8488SAndroid Build Coastguard Worker 	/// File error, such as permissions or file does not exist.
451*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_FILE_ERR,
452*5a6e8488SAndroid Build Coastguard Worker 
453*5a6e8488SAndroid Build Coastguard Worker 	/// File is binary, not text, error.
454*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_BIN_FILE,
455*5a6e8488SAndroid Build Coastguard Worker 
456*5a6e8488SAndroid Build Coastguard Worker 	/// Attempted to read a directory as a file error.
457*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_PATH_DIR,
458*5a6e8488SAndroid Build Coastguard Worker 
459*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid option error.
460*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_OPTION,
461*5a6e8488SAndroid Build Coastguard Worker 
462*5a6e8488SAndroid Build Coastguard Worker 	/// Option with required argument not given an argument.
463*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_OPTION_NO_ARG,
464*5a6e8488SAndroid Build Coastguard Worker 
465*5a6e8488SAndroid Build Coastguard Worker 	/// Option with no argument given an argument.
466*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_OPTION_ARG,
467*5a6e8488SAndroid Build Coastguard Worker 
468*5a6e8488SAndroid Build Coastguard Worker 	/// Option argument is invalid.
469*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_FATAL_ARG,
470*5a6e8488SAndroid Build Coastguard Worker 
471*5a6e8488SAndroid Build Coastguard Worker 	// Runtime errors.
472*5a6e8488SAndroid Build Coastguard Worker 
473*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid ibase value.
474*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_IBASE,
475*5a6e8488SAndroid Build Coastguard Worker 
476*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid obase value.
477*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_OBASE,
478*5a6e8488SAndroid Build Coastguard Worker 
479*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid scale value.
480*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_SCALE,
481*5a6e8488SAndroid Build Coastguard Worker 
482*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid expression parsed by read().
483*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_READ_EXPR,
484*5a6e8488SAndroid Build Coastguard Worker 
485*5a6e8488SAndroid Build Coastguard Worker 	/// read() used within an expression given to a read() call.
486*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_REC_READ,
487*5a6e8488SAndroid Build Coastguard Worker 
488*5a6e8488SAndroid Build Coastguard Worker 	/// Type error.
489*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_TYPE,
490*5a6e8488SAndroid Build Coastguard Worker 
491*5a6e8488SAndroid Build Coastguard Worker 	/// Stack has too few elements error.
492*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_STACK,
493*5a6e8488SAndroid Build Coastguard Worker 
494*5a6e8488SAndroid Build Coastguard Worker 	/// Register stack has too few elements error.
495*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_STACK_REGISTER,
496*5a6e8488SAndroid Build Coastguard Worker 
497*5a6e8488SAndroid Build Coastguard Worker 	/// Wrong number of arguments error.
498*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_PARAMS,
499*5a6e8488SAndroid Build Coastguard Worker 
500*5a6e8488SAndroid Build Coastguard Worker 	/// Undefined function error.
501*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_UNDEF_FUNC,
502*5a6e8488SAndroid Build Coastguard Worker 
503*5a6e8488SAndroid Build Coastguard Worker 	/// Void value used in an expression error.
504*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_EXEC_VOID_VAL,
505*5a6e8488SAndroid Build Coastguard Worker 
506*5a6e8488SAndroid Build Coastguard Worker 	// Parse (and lex) errors.
507*5a6e8488SAndroid Build Coastguard Worker 
508*5a6e8488SAndroid Build Coastguard Worker 	/// EOF encountered when not expected error.
509*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_EOF,
510*5a6e8488SAndroid Build Coastguard Worker 
511*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid character error.
512*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_CHAR,
513*5a6e8488SAndroid Build Coastguard Worker 
514*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid string (no ending quote) error.
515*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_STRING,
516*5a6e8488SAndroid Build Coastguard Worker 
517*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid comment (no end found) error.
518*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_COMMENT,
519*5a6e8488SAndroid Build Coastguard Worker 
520*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid token encountered error.
521*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_TOKEN,
522*5a6e8488SAndroid Build Coastguard Worker 
523*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLED
524*5a6e8488SAndroid Build Coastguard Worker 
525*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid expression error.
526*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_EXPR,
527*5a6e8488SAndroid Build Coastguard Worker 
528*5a6e8488SAndroid Build Coastguard Worker 	/// Expression is empty error.
529*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_EMPTY_EXPR,
530*5a6e8488SAndroid Build Coastguard Worker 
531*5a6e8488SAndroid Build Coastguard Worker 	/// Print statement is invalid error.
532*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_PRINT,
533*5a6e8488SAndroid Build Coastguard Worker 
534*5a6e8488SAndroid Build Coastguard Worker 	/// Function definition is invalid error.
535*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_FUNC,
536*5a6e8488SAndroid Build Coastguard Worker 
537*5a6e8488SAndroid Build Coastguard Worker 	/// Assignment is invalid error.
538*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_ASSIGN,
539*5a6e8488SAndroid Build Coastguard Worker 
540*5a6e8488SAndroid Build Coastguard Worker 	/// No auto identifiers given for an auto statement error.
541*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_NO_AUTO,
542*5a6e8488SAndroid Build Coastguard Worker 
543*5a6e8488SAndroid Build Coastguard Worker 	/// Duplicate local (parameter or auto) error.
544*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_DUP_LOCAL,
545*5a6e8488SAndroid Build Coastguard Worker 
546*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid block (within braces) error.
547*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_BLOCK,
548*5a6e8488SAndroid Build Coastguard Worker 
549*5a6e8488SAndroid Build Coastguard Worker 	/// Invalid return statement for void functions.
550*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_RET_VOID,
551*5a6e8488SAndroid Build Coastguard Worker 
552*5a6e8488SAndroid Build Coastguard Worker 	/// Reference attached to a variable, not an array, error.
553*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_PARSE_REF_VAR,
554*5a6e8488SAndroid Build Coastguard Worker 
555*5a6e8488SAndroid Build Coastguard Worker 	// POSIX-only errors.
556*5a6e8488SAndroid Build Coastguard Worker 
557*5a6e8488SAndroid Build Coastguard Worker 	/// Name length greater than 1 error.
558*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_NAME_LEN,
559*5a6e8488SAndroid Build Coastguard Worker 
560*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX comment used error.
561*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_COMMENT,
562*5a6e8488SAndroid Build Coastguard Worker 
563*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX keyword error.
564*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_KW,
565*5a6e8488SAndroid Build Coastguard Worker 
566*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX . (last) error.
567*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_DOT,
568*5a6e8488SAndroid Build Coastguard Worker 
569*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX return error.
570*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_RET,
571*5a6e8488SAndroid Build Coastguard Worker 
572*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX boolean operator used error.
573*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_BOOL,
574*5a6e8488SAndroid Build Coastguard Worker 
575*5a6e8488SAndroid Build Coastguard Worker 	/// POSIX relation operator used outside if, while, or for statements error.
576*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_REL_POS,
577*5a6e8488SAndroid Build Coastguard Worker 
578*5a6e8488SAndroid Build Coastguard Worker 	/// Multiple POSIX relation operators used in an if, while, or for statement
579*5a6e8488SAndroid Build Coastguard Worker 	/// error.
580*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_MULTIREL,
581*5a6e8488SAndroid Build Coastguard Worker 
582*5a6e8488SAndroid Build Coastguard Worker 	/// Empty statements in POSIX for loop error.
583*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_FOR,
584*5a6e8488SAndroid Build Coastguard Worker 
585*5a6e8488SAndroid Build Coastguard Worker 	/// POSIX's grammar does not allow a function definition right after a
586*5a6e8488SAndroid Build Coastguard Worker 	/// semicolon.
587*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_FUNC_AFTER_SEMICOLON,
588*5a6e8488SAndroid Build Coastguard Worker 
589*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX exponential (scientific or engineering) number used error.
590*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_EXP_NUM,
591*5a6e8488SAndroid Build Coastguard Worker 
592*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX array reference error.
593*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_REF,
594*5a6e8488SAndroid Build Coastguard Worker 
595*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX void error.
596*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_VOID,
597*5a6e8488SAndroid Build Coastguard Worker 
598*5a6e8488SAndroid Build Coastguard Worker 	/// Non-POSIX brace position used error.
599*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_BRACE,
600*5a6e8488SAndroid Build Coastguard Worker 
601*5a6e8488SAndroid Build Coastguard Worker 	/// String used in expression.
602*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_EXPR_STRING,
603*5a6e8488SAndroid Build Coastguard Worker 
604*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
605*5a6e8488SAndroid Build Coastguard Worker 
606*5a6e8488SAndroid Build Coastguard Worker 	// Number of elements.
607*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_NELEMS,
608*5a6e8488SAndroid Build Coastguard Worker 
609*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLED
610*5a6e8488SAndroid Build Coastguard Worker 
611*5a6e8488SAndroid Build Coastguard Worker 	/// A marker for the start of POSIX errors.
612*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_START = BC_ERR_POSIX_NAME_LEN,
613*5a6e8488SAndroid Build Coastguard Worker 
614*5a6e8488SAndroid Build Coastguard Worker 	/// A marker for the end of POSIX errors.
615*5a6e8488SAndroid Build Coastguard Worker 	BC_ERR_POSIX_END = BC_ERR_POSIX_EXPR_STRING,
616*5a6e8488SAndroid Build Coastguard Worker 
617*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
618*5a6e8488SAndroid Build Coastguard Worker 
619*5a6e8488SAndroid Build Coastguard Worker } BcErr;
620*5a6e8488SAndroid Build Coastguard Worker 
621*5a6e8488SAndroid Build Coastguard Worker // The indices of each category of error in bc_errs[], and used in bc_err_ids[]
622*5a6e8488SAndroid Build Coastguard Worker // to associate actual errors with their categories.
623*5a6e8488SAndroid Build Coastguard Worker 
624*5a6e8488SAndroid Build Coastguard Worker /// Math error category.
625*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_MATH (0)
626*5a6e8488SAndroid Build Coastguard Worker 
627*5a6e8488SAndroid Build Coastguard Worker /// Parse (and lex) error category.
628*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_PARSE (1)
629*5a6e8488SAndroid Build Coastguard Worker 
630*5a6e8488SAndroid Build Coastguard Worker /// Runtime error category.
631*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_EXEC (2)
632*5a6e8488SAndroid Build Coastguard Worker 
633*5a6e8488SAndroid Build Coastguard Worker /// Fatal error category.
634*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_FATAL (3)
635*5a6e8488SAndroid Build Coastguard Worker 
636*5a6e8488SAndroid Build Coastguard Worker /// Number of categories.
637*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_NELEMS (4)
638*5a6e8488SAndroid Build Coastguard Worker 
639*5a6e8488SAndroid Build Coastguard Worker // If bc is enabled, we add an extra category for POSIX warnings.
640*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLED
641*5a6e8488SAndroid Build Coastguard Worker 
642*5a6e8488SAndroid Build Coastguard Worker /// POSIX warning category.
643*5a6e8488SAndroid Build Coastguard Worker #define BC_ERR_IDX_WARN (BC_ERR_IDX_NELEMS)
644*5a6e8488SAndroid Build Coastguard Worker 
645*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
646*5a6e8488SAndroid Build Coastguard Worker 
647*5a6e8488SAndroid Build Coastguard Worker /**
648*5a6e8488SAndroid Build Coastguard Worker  * The mode bc is in. This is basically what input it is processing.
649*5a6e8488SAndroid Build Coastguard Worker  */
650*5a6e8488SAndroid Build Coastguard Worker typedef enum BcMode
651*5a6e8488SAndroid Build Coastguard Worker {
652*5a6e8488SAndroid Build Coastguard Worker 	/// Expressions mode.
653*5a6e8488SAndroid Build Coastguard Worker 	BC_MODE_EXPRS,
654*5a6e8488SAndroid Build Coastguard Worker 
655*5a6e8488SAndroid Build Coastguard Worker 	/// File mode.
656*5a6e8488SAndroid Build Coastguard Worker 	BC_MODE_FILE,
657*5a6e8488SAndroid Build Coastguard Worker 
658*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_OSSFUZZ
659*5a6e8488SAndroid Build Coastguard Worker 
660*5a6e8488SAndroid Build Coastguard Worker 	/// stdin mode.
661*5a6e8488SAndroid Build Coastguard Worker 	BC_MODE_STDIN,
662*5a6e8488SAndroid Build Coastguard Worker 
663*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_OSSFUZZ
664*5a6e8488SAndroid Build Coastguard Worker 
665*5a6e8488SAndroid Build Coastguard Worker } BcMode;
666*5a6e8488SAndroid Build Coastguard Worker 
667*5a6e8488SAndroid Build Coastguard Worker /// Do a longjmp(). This is what to use when activating an "exception", i.e., a
668*5a6e8488SAndroid Build Coastguard Worker /// longjmp(). With debug code, it will print the name of the function it jumped
669*5a6e8488SAndroid Build Coastguard Worker /// from.
670*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG_CODE
671*5a6e8488SAndroid Build Coastguard Worker #define BC_JMP bc_vm_jmp(__func__)
672*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG_CODE
673*5a6e8488SAndroid Build Coastguard Worker #define BC_JMP bc_vm_jmp()
674*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG_CODE
675*5a6e8488SAndroid Build Coastguard Worker 
676*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
677*5a6e8488SAndroid Build Coastguard Worker 
678*5a6e8488SAndroid Build Coastguard Worker /// Returns true if an exception is in flight, false otherwise.
679*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_EXC(vm) \
680*5a6e8488SAndroid Build Coastguard Worker 	BC_UNLIKELY((vm)->status != (sig_atomic_t) BC_STATUS_SUCCESS || (vm)->sig)
681*5a6e8488SAndroid Build Coastguard Worker 
682*5a6e8488SAndroid Build Coastguard Worker /// Returns true if there is *no* exception in flight, false otherwise.
683*5a6e8488SAndroid Build Coastguard Worker #define BC_NO_SIG_EXC(vm) \
684*5a6e8488SAndroid Build Coastguard Worker 	BC_LIKELY((vm)->status == (sig_atomic_t) BC_STATUS_SUCCESS && !(vm)->sig)
685*5a6e8488SAndroid Build Coastguard Worker 
686*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
687*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_INTERRUPT(vm) \
688*5a6e8488SAndroid Build Coastguard Worker 	BC_UNLIKELY((vm)->sig != 0 && (vm)->sig != SIGWINCH)
689*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
690*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_INTERRUPT(vm) BC_UNLIKELY((vm)->sig != 0)
691*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
692*5a6e8488SAndroid Build Coastguard Worker 
693*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
694*5a6e8488SAndroid Build Coastguard Worker 
695*5a6e8488SAndroid Build Coastguard Worker /// Assert that signals are locked. There are non-async-signal-safe functions in
696*5a6e8488SAndroid Build Coastguard Worker /// bc, and they *must* have signals locked. Other functions are expected to
697*5a6e8488SAndroid Build Coastguard Worker /// *not* have signals locked, for reasons. So this is a pre-built assert
698*5a6e8488SAndroid Build Coastguard Worker /// (no-op in non-debug mode) that check that signals are locked.
699*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_ASSERT_LOCKED  \
700*5a6e8488SAndroid Build Coastguard Worker 	do                        \
701*5a6e8488SAndroid Build Coastguard Worker 	{                         \
702*5a6e8488SAndroid Build Coastguard Worker 		assert(vm->sig_lock); \
703*5a6e8488SAndroid Build Coastguard Worker 	}                         \
704*5a6e8488SAndroid Build Coastguard Worker 	while (0)
705*5a6e8488SAndroid Build Coastguard Worker 
706*5a6e8488SAndroid Build Coastguard Worker /// Assert that signals are unlocked. There are non-async-signal-safe functions
707*5a6e8488SAndroid Build Coastguard Worker /// in bc, and they *must* have signals locked. Other functions are expected to
708*5a6e8488SAndroid Build Coastguard Worker /// *not* have signals locked, for reasons. So this is a pre-built assert
709*5a6e8488SAndroid Build Coastguard Worker /// (no-op in non-debug mode) that check that signals are unlocked.
710*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_ASSERT_NOT_LOCKED   \
711*5a6e8488SAndroid Build Coastguard Worker 	do                             \
712*5a6e8488SAndroid Build Coastguard Worker 	{                              \
713*5a6e8488SAndroid Build Coastguard Worker 		assert(vm->sig_lock == 0); \
714*5a6e8488SAndroid Build Coastguard Worker 	}                              \
715*5a6e8488SAndroid Build Coastguard Worker 	while (0)
716*5a6e8488SAndroid Build Coastguard Worker 
717*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG
718*5a6e8488SAndroid Build Coastguard Worker 
719*5a6e8488SAndroid Build Coastguard Worker /// Assert that signals are locked. There are non-async-signal-safe functions in
720*5a6e8488SAndroid Build Coastguard Worker /// bc, and they *must* have signals locked. Other functions are expected to
721*5a6e8488SAndroid Build Coastguard Worker /// *not* have signals locked, for reasons. So this is a pre-built assert
722*5a6e8488SAndroid Build Coastguard Worker /// (no-op in non-debug mode) that check that signals are locked.
723*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_ASSERT_LOCKED
724*5a6e8488SAndroid Build Coastguard Worker 
725*5a6e8488SAndroid Build Coastguard Worker /// Assert that signals are unlocked. There are non-async-signal-safe functions
726*5a6e8488SAndroid Build Coastguard Worker /// in bc, and they *must* have signals locked. Other functions are expected to
727*5a6e8488SAndroid Build Coastguard Worker /// *not* have signals locked, for reasons. So this is a pre-built assert
728*5a6e8488SAndroid Build Coastguard Worker /// (no-op in non-debug mode) that check that signals are unlocked.
729*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_ASSERT_NOT_LOCKED
730*5a6e8488SAndroid Build Coastguard Worker 
731*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
732*5a6e8488SAndroid Build Coastguard Worker 
733*5a6e8488SAndroid Build Coastguard Worker /// Locks signals.
734*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_LOCK               \
735*5a6e8488SAndroid Build Coastguard Worker 	do                            \
736*5a6e8488SAndroid Build Coastguard Worker 	{                             \
737*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_ASSERT_NOT_LOCKED; \
738*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 1;         \
739*5a6e8488SAndroid Build Coastguard Worker 	}                             \
740*5a6e8488SAndroid Build Coastguard Worker 	while (0)
741*5a6e8488SAndroid Build Coastguard Worker 
742*5a6e8488SAndroid Build Coastguard Worker /// Unlocks signals. If a signal happened, then this will cause a jump.
743*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_UNLOCK         \
744*5a6e8488SAndroid Build Coastguard Worker 	do                        \
745*5a6e8488SAndroid Build Coastguard Worker 	{                         \
746*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_ASSERT_LOCKED; \
747*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 0;     \
748*5a6e8488SAndroid Build Coastguard Worker 		if (vm->sig) BC_JMP;  \
749*5a6e8488SAndroid Build Coastguard Worker 	}                         \
750*5a6e8488SAndroid Build Coastguard Worker 	while (0)
751*5a6e8488SAndroid Build Coastguard Worker 
752*5a6e8488SAndroid Build Coastguard Worker /// Locks signals, regardless of if they are already locked. This is really only
753*5a6e8488SAndroid Build Coastguard Worker /// used after labels that longjmp() goes to after the jump because the cleanup
754*5a6e8488SAndroid Build Coastguard Worker /// code must have signals locked, and BC_LONGJMP_CONT will unlock signals if it
755*5a6e8488SAndroid Build Coastguard Worker /// doesn't jump.
756*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_MAYLOCK    \
757*5a6e8488SAndroid Build Coastguard Worker 	do                    \
758*5a6e8488SAndroid Build Coastguard Worker 	{                     \
759*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 1; \
760*5a6e8488SAndroid Build Coastguard Worker 	}                     \
761*5a6e8488SAndroid Build Coastguard Worker 	while (0)
762*5a6e8488SAndroid Build Coastguard Worker 
763*5a6e8488SAndroid Build Coastguard Worker /// Unlocks signals, regardless of if they were already unlocked. If a signal
764*5a6e8488SAndroid Build Coastguard Worker /// happened, then this will cause a jump.
765*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_MAYUNLOCK     \
766*5a6e8488SAndroid Build Coastguard Worker 	do                       \
767*5a6e8488SAndroid Build Coastguard Worker 	{                        \
768*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 0;    \
769*5a6e8488SAndroid Build Coastguard Worker 		if (vm->sig) BC_JMP; \
770*5a6e8488SAndroid Build Coastguard Worker 	}                        \
771*5a6e8488SAndroid Build Coastguard Worker 	while (0)
772*5a6e8488SAndroid Build Coastguard Worker 
773*5a6e8488SAndroid Build Coastguard Worker /**
774*5a6e8488SAndroid Build Coastguard Worker  * Locks signals, but stores the old lock state, to be restored later by
775*5a6e8488SAndroid Build Coastguard Worker  * BC_SIG_TRYUNLOCK.
776*5a6e8488SAndroid Build Coastguard Worker  * @param v  The variable to store the old lock state to.
777*5a6e8488SAndroid Build Coastguard Worker  */
778*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_TRYLOCK(v) \
779*5a6e8488SAndroid Build Coastguard Worker 	do                    \
780*5a6e8488SAndroid Build Coastguard Worker 	{                     \
781*5a6e8488SAndroid Build Coastguard Worker 		v = vm->sig_lock; \
782*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 1; \
783*5a6e8488SAndroid Build Coastguard Worker 	}                     \
784*5a6e8488SAndroid Build Coastguard Worker 	while (0)
785*5a6e8488SAndroid Build Coastguard Worker 
786*5a6e8488SAndroid Build Coastguard Worker /**
787*5a6e8488SAndroid Build Coastguard Worker  * Restores the previous state of a signal lock, and if it is now unlocked,
788*5a6e8488SAndroid Build Coastguard Worker  * initiates an exception/jump.
789*5a6e8488SAndroid Build Coastguard Worker  * @param v  The old lock state.
790*5a6e8488SAndroid Build Coastguard Worker  */
791*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_TRYUNLOCK(v)          \
792*5a6e8488SAndroid Build Coastguard Worker 	do                               \
793*5a6e8488SAndroid Build Coastguard Worker 	{                                \
794*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = (v);          \
795*5a6e8488SAndroid Build Coastguard Worker 		if (!(v) && vm->sig) BC_JMP; \
796*5a6e8488SAndroid Build Coastguard Worker 	}                                \
797*5a6e8488SAndroid Build Coastguard Worker 	while (0)
798*5a6e8488SAndroid Build Coastguard Worker 
799*5a6e8488SAndroid Build Coastguard Worker /// Stops a stack unwinding. Technically, a stack unwinding needs to be done
800*5a6e8488SAndroid Build Coastguard Worker /// manually, but it will always be done unless certain flags are cleared. This
801*5a6e8488SAndroid Build Coastguard Worker /// clears the flags.
802*5a6e8488SAndroid Build Coastguard Worker #define BC_LONGJMP_STOP  \
803*5a6e8488SAndroid Build Coastguard Worker 	do                   \
804*5a6e8488SAndroid Build Coastguard Worker 	{                    \
805*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_pop = 0; \
806*5a6e8488SAndroid Build Coastguard Worker 		vm->sig = 0;     \
807*5a6e8488SAndroid Build Coastguard Worker 	}                    \
808*5a6e8488SAndroid Build Coastguard Worker 	while (0)
809*5a6e8488SAndroid Build Coastguard Worker 
810*5a6e8488SAndroid Build Coastguard Worker /**
811*5a6e8488SAndroid Build Coastguard Worker  * Sets a jump like BC_SETJMP, but unlike BC_SETJMP, it assumes signals are
812*5a6e8488SAndroid Build Coastguard Worker  * locked and will just set the jump. This does *not* have a call to
813*5a6e8488SAndroid Build Coastguard Worker  * bc_vec_grow() because it is assumed that BC_SETJMP_LOCKED(l) is used *after*
814*5a6e8488SAndroid Build Coastguard Worker  * the initializations that need the setjmp().
815*5a6e8488SAndroid Build Coastguard Worker  * param l  The label to jump to on a longjmp().
816*5a6e8488SAndroid Build Coastguard Worker  */
817*5a6e8488SAndroid Build Coastguard Worker #define BC_SETJMP_LOCKED(vm, l)           \
818*5a6e8488SAndroid Build Coastguard Worker 	do                                    \
819*5a6e8488SAndroid Build Coastguard Worker 	{                                     \
820*5a6e8488SAndroid Build Coastguard Worker 		sigjmp_buf sjb;                   \
821*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_ASSERT_LOCKED;             \
822*5a6e8488SAndroid Build Coastguard Worker 		if (sigsetjmp(sjb, 0))            \
823*5a6e8488SAndroid Build Coastguard Worker 		{                                 \
824*5a6e8488SAndroid Build Coastguard Worker 			assert(BC_SIG_EXC(vm));       \
825*5a6e8488SAndroid Build Coastguard Worker 			goto l;                       \
826*5a6e8488SAndroid Build Coastguard Worker 		}                                 \
827*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_push(&vm->jmp_bufs, &sjb); \
828*5a6e8488SAndroid Build Coastguard Worker 	}                                     \
829*5a6e8488SAndroid Build Coastguard Worker 	while (0)
830*5a6e8488SAndroid Build Coastguard Worker 
831*5a6e8488SAndroid Build Coastguard Worker /// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to
832*5a6e8488SAndroid Build Coastguard Worker /// the next place. This is what continues the stack unwinding. This basically
833*5a6e8488SAndroid Build Coastguard Worker /// copies BC_SIG_UNLOCK into itself, but that is because its condition for
834*5a6e8488SAndroid Build Coastguard Worker /// jumping is BC_SIG_EXC, not just that a signal happened.
835*5a6e8488SAndroid Build Coastguard Worker #define BC_LONGJMP_CONT(vm)                          \
836*5a6e8488SAndroid Build Coastguard Worker 	do                                               \
837*5a6e8488SAndroid Build Coastguard Worker 	{                                                \
838*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_ASSERT_LOCKED;                        \
839*5a6e8488SAndroid Build Coastguard Worker 		if (!vm->sig_pop) bc_vec_pop(&vm->jmp_bufs); \
840*5a6e8488SAndroid Build Coastguard Worker 		vm->sig_lock = 0;                            \
841*5a6e8488SAndroid Build Coastguard Worker 		if (BC_SIG_EXC(vm)) BC_JMP;                  \
842*5a6e8488SAndroid Build Coastguard Worker 	}                                                \
843*5a6e8488SAndroid Build Coastguard Worker 	while (0)
844*5a6e8488SAndroid Build Coastguard Worker 
845*5a6e8488SAndroid Build Coastguard Worker #else // !BC_ENABLE_LIBRARY
846*5a6e8488SAndroid Build Coastguard Worker 
847*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_LOCK
848*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_UNLOCK
849*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_MAYLOCK
850*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_TRYLOCK(lock)
851*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_TRYUNLOCK(lock)
852*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_ASSERT_LOCKED
853*5a6e8488SAndroid Build Coastguard Worker 
854*5a6e8488SAndroid Build Coastguard Worker /// Returns true if an exception is in flight, false otherwise.
855*5a6e8488SAndroid Build Coastguard Worker #define BC_SIG_EXC(vm) \
856*5a6e8488SAndroid Build Coastguard Worker 	BC_UNLIKELY(vm->status != (sig_atomic_t) BC_STATUS_SUCCESS)
857*5a6e8488SAndroid Build Coastguard Worker 
858*5a6e8488SAndroid Build Coastguard Worker /// Returns true if there is *no* exception in flight, false otherwise.
859*5a6e8488SAndroid Build Coastguard Worker #define BC_NO_SIG_EXC(vm) \
860*5a6e8488SAndroid Build Coastguard Worker 	BC_LIKELY(vm->status == (sig_atomic_t) BC_STATUS_SUCCESS)
861*5a6e8488SAndroid Build Coastguard Worker 
862*5a6e8488SAndroid Build Coastguard Worker /// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to
863*5a6e8488SAndroid Build Coastguard Worker /// the next place. This is what continues the stack unwinding. This basically
864*5a6e8488SAndroid Build Coastguard Worker /// copies BC_SIG_UNLOCK into itself, but that is because its condition for
865*5a6e8488SAndroid Build Coastguard Worker /// jumping is BC_SIG_EXC, not just that a signal happened.
866*5a6e8488SAndroid Build Coastguard Worker #define BC_LONGJMP_CONT(vm)         \
867*5a6e8488SAndroid Build Coastguard Worker 	do                              \
868*5a6e8488SAndroid Build Coastguard Worker 	{                               \
869*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_pop(&vm->jmp_bufs);  \
870*5a6e8488SAndroid Build Coastguard Worker 		if (BC_SIG_EXC(vm)) BC_JMP; \
871*5a6e8488SAndroid Build Coastguard Worker 	}                               \
872*5a6e8488SAndroid Build Coastguard Worker 	while (0)
873*5a6e8488SAndroid Build Coastguard Worker 
874*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
875*5a6e8488SAndroid Build Coastguard Worker 
876*5a6e8488SAndroid Build Coastguard Worker /**
877*5a6e8488SAndroid Build Coastguard Worker  * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will
878*5a6e8488SAndroid Build Coastguard Worker  * immediately goto a label where some cleanup code is. This one assumes that
879*5a6e8488SAndroid Build Coastguard Worker  * signals are not locked and will lock them, set the jump, and unlock them.
880*5a6e8488SAndroid Build Coastguard Worker  * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack.
881*5a6e8488SAndroid Build Coastguard Worker  * This grows the jmp_bufs vector first to prevent a fatal error from happening
882*5a6e8488SAndroid Build Coastguard Worker  * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used
883*5a6e8488SAndroid Build Coastguard Worker  * *before* the actual initialization calls that need the setjmp().
884*5a6e8488SAndroid Build Coastguard Worker  * param l  The label to jump to on a longjmp().
885*5a6e8488SAndroid Build Coastguard Worker  */
886*5a6e8488SAndroid Build Coastguard Worker #define BC_SETJMP(vm, l)                  \
887*5a6e8488SAndroid Build Coastguard Worker 	do                                    \
888*5a6e8488SAndroid Build Coastguard Worker 	{                                     \
889*5a6e8488SAndroid Build Coastguard Worker 		sigjmp_buf sjb;                   \
890*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_LOCK;                      \
891*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_grow(&vm->jmp_bufs, 1);    \
892*5a6e8488SAndroid Build Coastguard Worker 		if (sigsetjmp(sjb, 0))            \
893*5a6e8488SAndroid Build Coastguard Worker 		{                                 \
894*5a6e8488SAndroid Build Coastguard Worker 			assert(BC_SIG_EXC(vm));       \
895*5a6e8488SAndroid Build Coastguard Worker 			goto l;                       \
896*5a6e8488SAndroid Build Coastguard Worker 		}                                 \
897*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_push(&vm->jmp_bufs, &sjb); \
898*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_UNLOCK;                    \
899*5a6e8488SAndroid Build Coastguard Worker 	}                                     \
900*5a6e8488SAndroid Build Coastguard Worker 	while (0)
901*5a6e8488SAndroid Build Coastguard Worker 
902*5a6e8488SAndroid Build Coastguard Worker /// Unsets a jump. It always assumes signals are locked. This basically just
903*5a6e8488SAndroid Build Coastguard Worker /// pops a jmp_buf off of the stack of jmp_bufs, and since the jump mechanism
904*5a6e8488SAndroid Build Coastguard Worker /// always jumps to the location at the top of the stack, this effectively
905*5a6e8488SAndroid Build Coastguard Worker /// undoes a setjmp().
906*5a6e8488SAndroid Build Coastguard Worker #define BC_UNSETJMP(vm)            \
907*5a6e8488SAndroid Build Coastguard Worker 	do                             \
908*5a6e8488SAndroid Build Coastguard Worker 	{                              \
909*5a6e8488SAndroid Build Coastguard Worker 		BC_SIG_ASSERT_LOCKED;      \
910*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_pop(&vm->jmp_bufs); \
911*5a6e8488SAndroid Build Coastguard Worker 	}                              \
912*5a6e8488SAndroid Build Coastguard Worker 	while (0)
913*5a6e8488SAndroid Build Coastguard Worker 
914*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
915*5a6e8488SAndroid Build Coastguard Worker 
916*5a6e8488SAndroid Build Coastguard Worker #define BC_SETJMP_LOCKED(vm, l) BC_SETJMP(vm, l)
917*5a6e8488SAndroid Build Coastguard Worker 
918*5a6e8488SAndroid Build Coastguard Worker // Various convenience macros for calling the bc's error handling routine.
919*5a6e8488SAndroid Build Coastguard Worker 
920*5a6e8488SAndroid Build Coastguard Worker /**
921*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
922*5a6e8488SAndroid Build Coastguard Worker  * @param e    The error.
923*5a6e8488SAndroid Build Coastguard Worker  * @param l    The line of the script that the error happened.
924*5a6e8488SAndroid Build Coastguard Worker  * @param ...  Extra arguments for error messages as necessary.
925*5a6e8488SAndroid Build Coastguard Worker  */
926*5a6e8488SAndroid Build Coastguard Worker #define bc_error(e, l, ...) (bc_vm_handleError((e)))
927*5a6e8488SAndroid Build Coastguard Worker 
928*5a6e8488SAndroid Build Coastguard Worker /**
929*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
930*5a6e8488SAndroid Build Coastguard Worker  * @param e  The error.
931*5a6e8488SAndroid Build Coastguard Worker  */
932*5a6e8488SAndroid Build Coastguard Worker #define bc_err(e) (bc_vm_handleError((e)))
933*5a6e8488SAndroid Build Coastguard Worker 
934*5a6e8488SAndroid Build Coastguard Worker /**
935*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
936*5a6e8488SAndroid Build Coastguard Worker  * @param e  The error.
937*5a6e8488SAndroid Build Coastguard Worker  */
938*5a6e8488SAndroid Build Coastguard Worker #define bc_verr(e, ...) (bc_vm_handleError((e)))
939*5a6e8488SAndroid Build Coastguard Worker 
940*5a6e8488SAndroid Build Coastguard Worker #else // BC_ENABLE_LIBRARY
941*5a6e8488SAndroid Build Coastguard Worker 
942*5a6e8488SAndroid Build Coastguard Worker // Various convenience macros for calling the bc's error handling routine.
943*5a6e8488SAndroid Build Coastguard Worker 
944*5a6e8488SAndroid Build Coastguard Worker /**
945*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
946*5a6e8488SAndroid Build Coastguard Worker  * @param e    The error.
947*5a6e8488SAndroid Build Coastguard Worker  * @param l    The line of the script that the error happened.
948*5a6e8488SAndroid Build Coastguard Worker  * @param ...  Extra arguments for error messages as necessary.
949*5a6e8488SAndroid Build Coastguard Worker  */
950*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
951*5a6e8488SAndroid Build Coastguard Worker #define bc_error(e, l, ...) \
952*5a6e8488SAndroid Build Coastguard Worker 	(bc_vm_handleError((e), __FILE__, __LINE__, (l), __VA_ARGS__))
953*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG
954*5a6e8488SAndroid Build Coastguard Worker #define bc_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__))
955*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
956*5a6e8488SAndroid Build Coastguard Worker 
957*5a6e8488SAndroid Build Coastguard Worker /**
958*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
959*5a6e8488SAndroid Build Coastguard Worker  * @param e  The error.
960*5a6e8488SAndroid Build Coastguard Worker  */
961*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
962*5a6e8488SAndroid Build Coastguard Worker #define bc_err(e) (bc_vm_handleError((e), __FILE__, __LINE__, 0))
963*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG
964*5a6e8488SAndroid Build Coastguard Worker #define bc_err(e) (bc_vm_handleError((e), 0))
965*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
966*5a6e8488SAndroid Build Coastguard Worker 
967*5a6e8488SAndroid Build Coastguard Worker /**
968*5a6e8488SAndroid Build Coastguard Worker  * Call bc's error handling routine.
969*5a6e8488SAndroid Build Coastguard Worker  * @param e  The error.
970*5a6e8488SAndroid Build Coastguard Worker  */
971*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
972*5a6e8488SAndroid Build Coastguard Worker #define bc_verr(e, ...) \
973*5a6e8488SAndroid Build Coastguard Worker 	(bc_vm_handleError((e), __FILE__, __LINE__, 0, __VA_ARGS__))
974*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG
975*5a6e8488SAndroid Build Coastguard Worker #define bc_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__))
976*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
977*5a6e8488SAndroid Build Coastguard Worker 
978*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
979*5a6e8488SAndroid Build Coastguard Worker 
980*5a6e8488SAndroid Build Coastguard Worker /**
981*5a6e8488SAndroid Build Coastguard Worker  * Returns true if status @a s is an error, false otherwise.
982*5a6e8488SAndroid Build Coastguard Worker  * @param s  The status to test.
983*5a6e8488SAndroid Build Coastguard Worker  * @return   True if @a s is an error, false otherwise.
984*5a6e8488SAndroid Build Coastguard Worker  */
985*5a6e8488SAndroid Build Coastguard Worker #define BC_STATUS_IS_ERROR(s) \
986*5a6e8488SAndroid Build Coastguard Worker 	((s) >= BC_STATUS_ERROR_MATH && (s) <= BC_STATUS_ERROR_FATAL)
987*5a6e8488SAndroid Build Coastguard Worker 
988*5a6e8488SAndroid Build Coastguard Worker // Convenience macros that can be placed at the beginning and exits of functions
989*5a6e8488SAndroid Build Coastguard Worker // for easy marking of where functions are entered and exited.
990*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG_CODE
991*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_ENTER                                               \
992*5a6e8488SAndroid Build Coastguard Worker 	do                                                              \
993*5a6e8488SAndroid Build Coastguard Worker 	{                                                               \
994*5a6e8488SAndroid Build Coastguard Worker 		size_t bc_func_enter_i;                                     \
995*5a6e8488SAndroid Build Coastguard Worker 		for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \
996*5a6e8488SAndroid Build Coastguard Worker 		     ++bc_func_enter_i)                                     \
997*5a6e8488SAndroid Build Coastguard Worker 		{                                                           \
998*5a6e8488SAndroid Build Coastguard Worker 			bc_file_puts(&vm->ferr, bc_flush_none, "  ");           \
999*5a6e8488SAndroid Build Coastguard Worker 		}                                                           \
1000*5a6e8488SAndroid Build Coastguard Worker 		vm->func_depth += 1;                                        \
1001*5a6e8488SAndroid Build Coastguard Worker 		bc_file_printf(&vm->ferr, "Entering %s\n", __func__);       \
1002*5a6e8488SAndroid Build Coastguard Worker 		bc_file_flush(&vm->ferr, bc_flush_none);                    \
1003*5a6e8488SAndroid Build Coastguard Worker 	}                                                               \
1004*5a6e8488SAndroid Build Coastguard Worker 	while (0);
1005*5a6e8488SAndroid Build Coastguard Worker 
1006*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_EXIT                                                \
1007*5a6e8488SAndroid Build Coastguard Worker 	do                                                              \
1008*5a6e8488SAndroid Build Coastguard Worker 	{                                                               \
1009*5a6e8488SAndroid Build Coastguard Worker 		size_t bc_func_enter_i;                                     \
1010*5a6e8488SAndroid Build Coastguard Worker 		vm->func_depth -= 1;                                        \
1011*5a6e8488SAndroid Build Coastguard Worker 		for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \
1012*5a6e8488SAndroid Build Coastguard Worker 		     ++bc_func_enter_i)                                     \
1013*5a6e8488SAndroid Build Coastguard Worker 		{                                                           \
1014*5a6e8488SAndroid Build Coastguard Worker 			bc_file_puts(&vm->ferr, bc_flush_none, "  ");           \
1015*5a6e8488SAndroid Build Coastguard Worker 		}                                                           \
1016*5a6e8488SAndroid Build Coastguard Worker 		bc_file_printf(&vm->ferr, "Leaving %s\n", __func__);        \
1017*5a6e8488SAndroid Build Coastguard Worker 		bc_file_flush(&vm->ferr, bc_flush_none);                    \
1018*5a6e8488SAndroid Build Coastguard Worker 	}                                                               \
1019*5a6e8488SAndroid Build Coastguard Worker 	while (0);
1020*5a6e8488SAndroid Build Coastguard Worker #else // BC_DEBUG_CODE
1021*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_ENTER
1022*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_EXIT
1023*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG_CODE
1024*5a6e8488SAndroid Build Coastguard Worker 
1025*5a6e8488SAndroid Build Coastguard Worker #endif // BC_STATUS_H
1026