xref: /freebsd/contrib/bc/include/bc.h (revision d213476d1cb7a0266812395a6b7a143c912f5aa3)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
63aa99676SStefan Eßer  * Copyright (c) 2018-2020 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  *
32252884aeSStefan Eßer  * Definitions for bc.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_BC_H
37252884aeSStefan Eßer #define BC_BC_H
38252884aeSStefan Eßer 
39252884aeSStefan Eßer #if BC_ENABLED
40252884aeSStefan Eßer 
41252884aeSStefan Eßer #include <limits.h>
42252884aeSStefan Eßer #include <stdbool.h>
43252884aeSStefan Eßer 
44252884aeSStefan Eßer #include <status.h>
45252884aeSStefan Eßer #include <lex.h>
46252884aeSStefan Eßer #include <parse.h>
47252884aeSStefan Eßer 
48252884aeSStefan Eßer void bc_main(int argc, char **argv);
49252884aeSStefan Eßer 
50252884aeSStefan Eßer extern const char bc_help[];
51252884aeSStefan Eßer extern const char bc_lib[];
52252884aeSStefan Eßer extern const char* bc_lib_name;
53252884aeSStefan Eßer 
54252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
55252884aeSStefan Eßer extern const char bc_lib2[];
56252884aeSStefan Eßer extern const char* bc_lib2_name;
57252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
58252884aeSStefan Eßer 
59252884aeSStefan Eßer typedef struct BcLexKeyword {
60252884aeSStefan Eßer 	uchar data;
61252884aeSStefan Eßer 	const char name[9];
62252884aeSStefan Eßer } BcLexKeyword;
63252884aeSStefan Eßer 
64252884aeSStefan Eßer #define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
65252884aeSStefan Eßer 
66252884aeSStefan Eßer #define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
67252884aeSStefan Eßer #define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
68252884aeSStefan Eßer 
69252884aeSStefan Eßer #define BC_LEX_KW_ENTRY(a, b, c) \
70252884aeSStefan Eßer 	{ .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a }
71252884aeSStefan Eßer 
72252884aeSStefan Eßer extern const BcLexKeyword bc_lex_kws[];
73252884aeSStefan Eßer extern const size_t bc_lex_kws_len;
74252884aeSStefan Eßer 
75252884aeSStefan Eßer void bc_lex_token(BcLex *l);
76252884aeSStefan Eßer 
77252884aeSStefan Eßer #define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
78252884aeSStefan Eßer #define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
79252884aeSStefan Eßer 
80252884aeSStefan Eßer #define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
81252884aeSStefan Eßer #define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
82252884aeSStefan Eßer 
83252884aeSStefan Eßer #define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
84252884aeSStefan Eßer #define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
85252884aeSStefan Eßer 
86252884aeSStefan Eßer #define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
87252884aeSStefan Eßer #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
88252884aeSStefan Eßer 
89252884aeSStefan Eßer #define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
90252884aeSStefan Eßer #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
91252884aeSStefan Eßer 
92252884aeSStefan Eßer #define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
93252884aeSStefan Eßer #define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
94252884aeSStefan Eßer 
95252884aeSStefan Eßer #define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
96252884aeSStefan Eßer #define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
97252884aeSStefan Eßer 
98252884aeSStefan Eßer #define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
99252884aeSStefan Eßer #define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
100252884aeSStefan Eßer 
101252884aeSStefan Eßer #define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
102252884aeSStefan Eßer #define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
103252884aeSStefan Eßer 
104252884aeSStefan Eßer #define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
105252884aeSStefan Eßer #define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
106252884aeSStefan Eßer 
107252884aeSStefan Eßer #define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
108252884aeSStefan Eßer 
109252884aeSStefan Eßer #define BC_PARSE_DELIMITER(t) \
110252884aeSStefan Eßer 	((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
111252884aeSStefan Eßer 
112252884aeSStefan Eßer #define BC_PARSE_BLOCK_STMT(f) \
113252884aeSStefan Eßer 	((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
114252884aeSStefan Eßer 
115252884aeSStefan Eßer #define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
116252884aeSStefan Eßer 
117252884aeSStefan Eßer #define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
118252884aeSStefan Eßer #define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
119252884aeSStefan Eßer #define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
120252884aeSStefan Eßer 
121252884aeSStefan Eßer #define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8)  \
122252884aeSStefan Eßer 	((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \
123252884aeSStefan Eßer 	 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \
124252884aeSStefan Eßer 	 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0))
125252884aeSStefan Eßer 
126252884aeSStefan Eßer #define BC_PARSE_EXPR(i) \
127252884aeSStefan Eßer 	(bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
128252884aeSStefan Eßer 
129252884aeSStefan Eßer #define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
130252884aeSStefan Eßer #define BC_PARSE_LEAF(prev, bin_last, rparen) \
131252884aeSStefan Eßer 	(!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
132252884aeSStefan Eßer 
1333aa99676SStefan Eßer #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
134252884aeSStefan Eßer #define BC_PARSE_INST_VAR(t) \
135252884aeSStefan Eßer 	((t) >= BC_INST_VAR && (t) <= BC_INST_SEED && (t) != BC_INST_ARRAY)
1363aa99676SStefan Eßer #else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
137252884aeSStefan Eßer #define BC_PARSE_INST_VAR(t) \
138252884aeSStefan Eßer 	((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
1393aa99676SStefan Eßer #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
140252884aeSStefan Eßer 
141252884aeSStefan Eßer #define BC_PARSE_PREV_PREFIX(p) \
142252884aeSStefan Eßer 	((p) >= BC_INST_NEG && (p) <= BC_INST_BOOL_NOT)
143252884aeSStefan Eßer #define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
144252884aeSStefan Eßer 
145252884aeSStefan Eßer // We can calculate the conversion between tokens and exprs by subtracting the
146252884aeSStefan Eßer // position of the first operator in the lex enum and adding the position of
147252884aeSStefan Eßer // the first in the expr enum. Note: This only works for binary operators.
148252884aeSStefan Eßer #define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG))
149252884aeSStefan Eßer 
150252884aeSStefan Eßer typedef enum BcParseStatus {
151252884aeSStefan Eßer 
152252884aeSStefan Eßer 	BC_PARSE_STATUS_SUCCESS,
153252884aeSStefan Eßer 	BC_PARSE_STATUS_EMPTY_EXPR,
154252884aeSStefan Eßer 
155252884aeSStefan Eßer } BcParseStatus;
156252884aeSStefan Eßer 
157252884aeSStefan Eßer void bc_parse_expr(BcParse *p, uint8_t flags);
158252884aeSStefan Eßer 
159252884aeSStefan Eßer void bc_parse_parse(BcParse *p);
160252884aeSStefan Eßer void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
161252884aeSStefan Eßer 
162252884aeSStefan Eßer extern const char bc_sig_msg[];
163252884aeSStefan Eßer extern const uchar bc_sig_msg_len;
164252884aeSStefan Eßer 
165252884aeSStefan Eßer extern const char* const bc_parse_const1;
166252884aeSStefan Eßer extern const uint8_t bc_parse_exprs[];
167252884aeSStefan Eßer extern const uchar bc_parse_ops[];
168252884aeSStefan Eßer extern const BcParseNext bc_parse_next_expr;
169252884aeSStefan Eßer extern const BcParseNext bc_parse_next_param;
170252884aeSStefan Eßer extern const BcParseNext bc_parse_next_print;
171252884aeSStefan Eßer extern const BcParseNext bc_parse_next_rel;
172252884aeSStefan Eßer extern const BcParseNext bc_parse_next_elem;
173252884aeSStefan Eßer extern const BcParseNext bc_parse_next_for;
174252884aeSStefan Eßer extern const BcParseNext bc_parse_next_read;
175252884aeSStefan Eßer 
176*d213476dSStefan Eßer #else // BC_ENABLED
177*d213476dSStefan Eßer 
178*d213476dSStefan Eßer #define BC_PARSE_NO_EXEC(p) (0)
179*d213476dSStefan Eßer 
180252884aeSStefan Eßer #endif // BC_ENABLED
181252884aeSStefan Eßer 
182252884aeSStefan Eßer #endif // BC_BC_H
183