blob: 9f93e00b0aadc7651e71960350d2eb88aee7d8c0 [file] [log] [blame]
Brian Callahan1c761962019-04-02 18:37:44 -04001/*
Gavin Howardb5904bf2018-02-20 13:28:18 -07002 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -07003 *
Gavin Howard29e00ba2020-06-30 09:25:21 -06004 * SPDX-License-Identifier: BSD-2-Clause
5 *
Zach van Rijn6d2cf3f2020-01-14 22:05:02 +00006 * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
Gavin Howard5715b042018-02-12 16:11:42 -07007 *
Gavin Howard7345cb92019-04-08 14:13:43 -06008 * All rights reserved.
Gavin Howard5715b042018-02-12 16:11:42 -07009 *
Gavin Howard7345cb92019-04-08 14:13:43 -060010 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * * Redistributions of source code must retain the above copyright notice, this
14 * list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
Gavin Howard5715b042018-02-12 16:11:42 -070031 *
Gavin Howardb5904bf2018-02-20 13:28:18 -070032 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -070033 *
Gavin Howard4ffe5a92018-09-26 20:58:31 -060034 * Definitions for bc.
Gavin Howard5715b042018-02-12 16:11:42 -070035 *
36 */
37
Gavin Howard4ffe5a92018-09-26 20:58:31 -060038#ifndef BC_BC_H
39#define BC_BC_H
Gavin Howard8a596d42018-01-15 15:46:01 -070040
Gavin Howard1545ffe2018-12-24 11:26:46 -070041#if BC_ENABLED
42
Gavin Howardc1902aa2018-12-20 15:54:28 -070043#include <limits.h>
Gavin Howard707a4e32018-10-03 16:36:41 -060044#include <stdbool.h>
45
Gavin Howard29493062018-03-20 19:57:37 -060046#include <status.h>
Gavin Howard707a4e32018-10-03 16:36:41 -060047#include <lex.h>
48#include <parse.h>
Gavin Howard6839e4d2018-03-20 21:24:52 -060049
Gavin Howard5a321892020-05-16 17:27:55 -060050void bc_main(int argc, char **argv);
Gavin Howarda84ad992018-12-03 19:11:06 -070051
Gavin Howarda046ce92019-06-14 19:43:13 -060052extern const char bc_help[];
Gavin Howard1ddff512019-06-14 19:59:57 -060053extern const char bc_lib[];
54extern const char* bc_lib_name;
Gavin Howard98667672020-04-28 17:17:39 -060055
Gavin Howard1ddff512019-06-14 19:59:57 -060056#if BC_ENABLE_EXTRA_MATH
57extern const char bc_lib2[];
58extern const char* bc_lib2_name;
59#endif // BC_ENABLE_EXTRA_MATH
Gavin Howarda046ce92019-06-14 19:43:13 -060060
Gavin Howard707a4e32018-10-03 16:36:41 -060061typedef struct BcLexKeyword {
Gavin Howardc1902aa2018-12-20 15:54:28 -070062 uchar data;
Gavin Howard707a4e32018-10-03 16:36:41 -060063 const char name[9];
Gavin Howard707a4e32018-10-03 16:36:41 -060064} BcLexKeyword;
65
Gavin Howard4662d6c2018-12-20 16:31:31 -070066#define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
67
Gavin Howardfbd2b4a2018-12-27 12:11:41 -070068#define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
69#define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
Gavin Howard4662d6c2018-12-20 16:31:31 -070070
Gavin Howardc1902aa2018-12-20 15:54:28 -070071#define BC_LEX_KW_ENTRY(a, b, c) \
Gavin Howard5151c872019-10-04 18:06:25 -060072 { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a }
Gavin Howard707a4e32018-10-03 16:36:41 -060073
Gavin Howardc70bd502018-12-31 17:28:32 -070074extern const BcLexKeyword bc_lex_kws[];
75extern const size_t bc_lex_kws_len;
Gavin Howard707a4e32018-10-03 16:36:41 -060076
Gavin Howard5a321892020-05-16 17:27:55 -060077void bc_lex_token(BcLex *l);
Gavin Howard707a4e32018-10-03 16:36:41 -060078
Gavin Howardb15fa032019-01-02 14:42:36 -070079#define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
80#define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
81
Gavin Howardf2d9a652019-05-11 07:38:32 -060082#define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
Gavin Howardb15fa032019-01-02 14:42:36 -070083#define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
84
Gavin Howardf2d9a652019-05-11 07:38:32 -060085#define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
Gavin Howardb15fa032019-01-02 14:42:36 -070086#define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
87
Gavin Howardf2d9a652019-05-11 07:38:32 -060088#define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
Gavin Howardb15fa032019-01-02 14:42:36 -070089#define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
90
Gavin Howardf2d9a652019-05-11 07:38:32 -060091#define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
Gavin Howardb15fa032019-01-02 14:42:36 -070092#define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
93
Gavin Howardf2d9a652019-05-11 07:38:32 -060094#define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
Gavin Howardb15fa032019-01-02 14:42:36 -070095#define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
96
Gavin Howardf2d9a652019-05-11 07:38:32 -060097#define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
Gavin Howardb15fa032019-01-02 14:42:36 -070098#define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
99
Gavin Howardf2d9a652019-05-11 07:38:32 -0600100#define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
Gavin Howardb15fa032019-01-02 14:42:36 -0700101#define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
102
Gavin Howardf2d9a652019-05-11 07:38:32 -0600103#define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
Gavin Howardb15fa032019-01-02 14:42:36 -0700104#define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
105
Gavin Howardf2d9a652019-05-11 07:38:32 -0600106#define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
Gavin Howardb15fa032019-01-02 14:42:36 -0700107#define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
108
109#define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
110
Gavin Howard7ed50c72019-01-14 11:20:12 -0700111#define BC_PARSE_DELIMITER(t) \
112 ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
Gavin Howardb15fa032019-01-02 14:42:36 -0700113
Gavin Howard63fdbfa2019-01-16 09:47:04 -0700114#define BC_PARSE_BLOCK_STMT(f) \
115 ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
116
Gavin Howard2b4fde92018-12-24 16:02:24 -0700117#define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700118
Gavin Howard1c6cfb82019-01-21 11:42:34 -0700119#define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
120#define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
121#define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700122
Gavin Howard675b5cc2018-12-20 16:55:36 -0700123#define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \
Gavin Howardf2d9a652019-05-11 07:38:32 -0600124 ((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \
125 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \
126 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700127
128#define BC_PARSE_EXPR(i) \
Gavin Howard1cbfe242019-01-09 17:13:11 -0700129 (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700130
Gavin Howard890d0c02018-10-30 16:34:50 -0600131#define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
Gavin Howardb6e5a172018-12-28 17:41:15 -0700132#define BC_PARSE_LEAF(prev, bin_last, rparen) \
133 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
Gavin Howard60068bc2020-04-25 21:32:53 -0600134
Gavin Howardcb067732020-07-01 13:30:08 -0600135#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howard47137932019-10-10 21:16:43 -0600136#define BC_PARSE_INST_VAR(t) \
137 ((t) >= BC_INST_VAR && (t) <= BC_INST_SEED && (t) != BC_INST_ARRAY)
Gavin Howardcb067732020-07-01 13:30:08 -0600138#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howardf81f9042018-12-27 14:19:53 -0700139#define BC_PARSE_INST_VAR(t) \
Gavin Howardd975dc72019-01-24 15:13:17 -0700140 ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
Gavin Howardcb067732020-07-01 13:30:08 -0600141#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howard707a4e32018-10-03 16:36:41 -0600142
Gavin Howarde5228882019-01-10 16:08:04 -0700143#define BC_PARSE_PREV_PREFIX(p) \
Gavin Howard4684d712020-06-18 16:37:45 -0600144 ((p) >= BC_INST_NEG && (p) <= BC_INST_BOOL_NOT)
Gavin Howarde5228882019-01-10 16:08:04 -0700145#define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
Gavin Howardac7a3c92019-01-10 13:26:29 -0700146
Gavin Howard707a4e32018-10-03 16:36:41 -0600147// We can calculate the conversion between tokens and exprs by subtracting the
Gavin Howard954f9b62018-12-19 15:22:20 -0700148// position of the first operator in the lex enum and adding the position of
149// the first in the expr enum. Note: This only works for binary operators.
150#define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG))
Gavin Howard707a4e32018-10-03 16:36:41 -0600151
Gavin Howard5a321892020-05-16 17:27:55 -0600152typedef enum BcParseStatus {
Gavin Howard707a4e32018-10-03 16:36:41 -0600153
Gavin Howard5a321892020-05-16 17:27:55 -0600154 BC_PARSE_STATUS_SUCCESS,
155 BC_PARSE_STATUS_EMPTY_EXPR,
156
157} BcParseStatus;
158
159void bc_parse_expr(BcParse *p, uint8_t flags);
160
161void bc_parse_parse(BcParse *p);
162void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
Gavin Howardff66e292018-03-28 12:47:58 -0600163
Gavin Howardc5295782019-05-12 17:26:29 -0600164// This is necessary to clear up for if statements at the end of files.
165void bc_parse_noElse(BcParse *p);
166
Gavin Howard10667092018-12-20 11:52:55 -0700167extern const char bc_sig_msg[];
Gavin Howard452841b2020-05-15 13:12:55 -0600168extern const uchar bc_sig_msg_len;
Gavin Howard10667092018-12-20 11:52:55 -0700169
Gavin Howarda73c11b2018-12-17 11:30:39 -0700170extern const char* const bc_parse_const1;
Gavin Howard675b5cc2018-12-20 16:55:36 -0700171extern const uint8_t bc_parse_exprs[];
Gavin Howardc1902aa2018-12-20 15:54:28 -0700172extern const uchar bc_parse_ops[];
Gavin Howardf89006a2018-10-29 13:01:51 -0600173extern const BcParseNext bc_parse_next_expr;
174extern const BcParseNext bc_parse_next_param;
175extern const BcParseNext bc_parse_next_print;
176extern const BcParseNext bc_parse_next_rel;
177extern const BcParseNext bc_parse_next_elem;
178extern const BcParseNext bc_parse_next_for;
179extern const BcParseNext bc_parse_next_read;
180
Gavin Howarddf4fe792018-10-03 16:48:30 -0600181#endif // BC_ENABLED
182
Gavin Howard4ffe5a92018-09-26 20:58:31 -0600183#endif // BC_BC_H