1 /* 2 * ***************************************************************************** 3 * 4 * Copyright (c) 2018-2020 Gavin D. Howard and contributors. 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * Definitions for bc. 33 * 34 */ 35 36 #ifndef BC_BC_H 37 #define BC_BC_H 38 39 #if BC_ENABLED 40 41 #include <limits.h> 42 #include <stdbool.h> 43 44 #include <status.h> 45 #include <lex.h> 46 #include <parse.h> 47 48 void bc_main(int argc, char **argv); 49 50 extern const char bc_help[]; 51 extern const char bc_lib[]; 52 extern const char* bc_lib_name; 53 54 #if BC_ENABLE_EXTRA_MATH 55 extern const char bc_lib2[]; 56 extern const char* bc_lib2_name; 57 #endif // BC_ENABLE_EXTRA_MATH 58 59 typedef struct BcLexKeyword { 60 uchar data; 61 const char name[9]; 62 } BcLexKeyword; 63 64 #define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1)) 65 66 #define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1))) 67 #define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1)))) 68 69 #define BC_LEX_KW_ENTRY(a, b, c) \ 70 { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a } 71 72 extern const BcLexKeyword bc_lex_kws[]; 73 extern const size_t bc_lex_kws_len; 74 75 void bc_lex_token(BcLex *l); 76 77 #define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags)) 78 #define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p))) 79 80 #define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0) 81 #define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE) 82 83 #define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1) 84 #define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER) 85 86 #define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2) 87 #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC) 88 89 #define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3) 90 #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY) 91 92 #define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4) 93 #define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP) 94 95 #define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5) 96 #define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER) 97 98 #define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6) 99 #define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF) 100 101 #define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7) 102 #define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE) 103 104 #define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8) 105 #define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END) 106 107 #define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0) 108 109 #define BC_PARSE_DELIMITER(t) \ 110 ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF) 111 112 #define BC_PARSE_BLOCK_STMT(f) \ 113 ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER)) 114 115 #define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l))) 116 117 #define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)] 118 #define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1)) 119 #define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1))) 120 121 #define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \ 122 ((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \ 123 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \ 124 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0)) 125 126 #define BC_PARSE_EXPR(i) \ 127 (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07)))) 128 129 #define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops))) 130 #define BC_PARSE_LEAF(prev, bin_last, rparen) \ 131 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev))) 132 133 #if BC_ENABLE_EXTRA_MATH 134 #define BC_PARSE_INST_VAR(t) \ 135 ((t) >= BC_INST_VAR && (t) <= BC_INST_SEED && (t) != BC_INST_ARRAY) 136 #else // BC_ENABLE_EXTRA_MATH 137 #define BC_PARSE_INST_VAR(t) \ 138 ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY) 139 #endif // BC_ENABLE_EXTRA_MATH 140 141 #define BC_PARSE_PREV_PREFIX(p) \ 142 ((p) >= BC_INST_NEG && (p) <= BC_INST_BOOL_NOT) 143 #define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG) 144 145 // We can calculate the conversion between tokens and exprs by subtracting the 146 // position of the first operator in the lex enum and adding the position of 147 // the first in the expr enum. Note: This only works for binary operators. 148 #define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG)) 149 150 typedef enum BcParseStatus { 151 152 BC_PARSE_STATUS_SUCCESS, 153 BC_PARSE_STATUS_EMPTY_EXPR, 154 155 } BcParseStatus; 156 157 void bc_parse_expr(BcParse *p, uint8_t flags); 158 159 void bc_parse_parse(BcParse *p); 160 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next); 161 162 // This is necessary to clear up for if statements at the end of files. 163 void bc_parse_noElse(BcParse *p); 164 165 extern const char bc_sig_msg[]; 166 extern const uchar bc_sig_msg_len; 167 168 extern const char* const bc_parse_const1; 169 extern const uint8_t bc_parse_exprs[]; 170 extern const uchar bc_parse_ops[]; 171 extern const BcParseNext bc_parse_next_expr; 172 extern const BcParseNext bc_parse_next_param; 173 extern const BcParseNext bc_parse_next_print; 174 extern const BcParseNext bc_parse_next_rel; 175 extern const BcParseNext bc_parse_next_elem; 176 extern const BcParseNext bc_parse_next_for; 177 extern const BcParseNext bc_parse_next_read; 178 179 #endif // BC_ENABLED 180 181 #endif // BC_BC_H 182