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