• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * *****************************************************************************
3  *
4  * Copyright (c) 2018-2019 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 int 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 #if BC_ENABLE_EXTRA_MATH
54 extern const char bc_lib2[];
55 extern const char* bc_lib2_name;
56 #endif // BC_ENABLE_EXTRA_MATH
57 
58 typedef struct BcLexKeyword {
59 	uchar data;
60 	const char name[9];
61 } BcLexKeyword;
62 
63 #define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
64 
65 #define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
66 #define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
67 
68 #define BC_LEX_KW_ENTRY(a, b, c) \
69 	{ .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a }
70 
71 extern const BcLexKeyword bc_lex_kws[];
72 extern const size_t bc_lex_kws_len;
73 
74 BcStatus bc_lex_token(BcLex *l);
75 
76 #define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
77 #define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
78 
79 #define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
80 #define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
81 
82 #define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
83 #define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
84 
85 #define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
86 #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
87 
88 #define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
89 #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
90 
91 #define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
92 #define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
93 
94 #define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
95 #define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
96 
97 #define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
98 #define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
99 
100 #define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
101 #define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
102 
103 #define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
104 #define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
105 
106 #define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
107 
108 #define BC_PARSE_DELIMITER(t) \
109 	((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
110 
111 #define BC_PARSE_BLOCK_STMT(f) \
112 	((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
113 
114 #define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
115 
116 #define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
117 #define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
118 #define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
119 
120 #define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8)  \
121 	((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \
122 	 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \
123 	 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0))
124 
125 #define BC_PARSE_EXPR(i) \
126 	(bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
127 
128 #define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
129 #define BC_PARSE_LEAF(prev, bin_last, rparen) \
130 	(!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
131 #define BC_PARSE_INST_VAR(t) \
132 	((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
133 
134 #define BC_PARSE_PREV_PREFIX(p) \
135 	((p) >= BC_INST_INC_PRE && (p) <= BC_INST_BOOL_NOT)
136 #define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
137 
138 // We can calculate the conversion between tokens and exprs by subtracting the
139 // position of the first operator in the lex enum and adding the position of
140 // the first in the expr enum. Note: This only works for binary operators.
141 #define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG))
142 
143 BcStatus bc_parse_expr(BcParse *p, uint8_t flags);
144 
145 BcStatus bc_parse_parse(BcParse *p);
146 BcStatus bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
147 
148 // This is necessary to clear up for if statements at the end of files.
149 void bc_parse_noElse(BcParse *p);
150 
151 #if BC_ENABLE_SIGNALS
152 extern const char bc_sig_msg[];
153 #endif // BC_ENABLE_SIGNALS
154 
155 extern const char* const bc_parse_const1;
156 extern const uint8_t bc_parse_exprs[];
157 extern const uchar bc_parse_ops[];
158 extern const BcParseNext bc_parse_next_expr;
159 extern const BcParseNext bc_parse_next_param;
160 extern const BcParseNext bc_parse_next_print;
161 extern const BcParseNext bc_parse_next_rel;
162 extern const BcParseNext bc_parse_next_elem;
163 extern const BcParseNext bc_parse_next_for;
164 extern const BcParseNext bc_parse_next_read;
165 
166 #endif // BC_ENABLED
167 
168 #endif // BC_BC_H
169