blob: ca15aabe8b4fc1aa2004ccbc40da8da7487096c7 [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 * 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.
Gavin Howard5715b042018-02-12 16:11:42 -070029 *
Gavin Howardb5904bf2018-02-20 13:28:18 -070030 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -070031 *
Gavin Howard4ffe5a92018-09-26 20:58:31 -060032 * Definitions for bc.
Gavin Howard5715b042018-02-12 16:11:42 -070033 *
34 */
35
Gavin Howard4ffe5a92018-09-26 20:58:31 -060036#ifndef BC_BC_H
37#define BC_BC_H
Gavin Howard8a596d42018-01-15 15:46:01 -070038
Gavin Howard1545ffe2018-12-24 11:26:46 -070039#if BC_ENABLED
40
Gavin Howardc1902aa2018-12-20 15:54:28 -070041#include <limits.h>
Gavin Howard707a4e32018-10-03 16:36:41 -060042#include <stdbool.h>
43
Gavin Howard29493062018-03-20 19:57:37 -060044#include <status.h>
Gavin Howard9f9bef42020-10-22 21:37:46 -060045#include "lex.h"
46#include "parse.h"
Gavin Howard6839e4d2018-03-20 21:24:52 -060047
Gavin Howard5a321892020-05-16 17:27:55 -060048void bc_main(int argc, char **argv);
Gavin Howarda84ad992018-12-03 19:11:06 -070049
Gavin Howarda046ce92019-06-14 19:43:13 -060050extern const char bc_help[];
Gavin Howard1ddff512019-06-14 19:59:57 -060051extern const char bc_lib[];
52extern const char* bc_lib_name;
Gavin Howard98667672020-04-28 17:17:39 -060053
Gavin Howard1ddff512019-06-14 19:59:57 -060054#if BC_ENABLE_EXTRA_MATH
55extern const char bc_lib2[];
56extern const char* bc_lib2_name;
57#endif // BC_ENABLE_EXTRA_MATH
Gavin Howarda046ce92019-06-14 19:43:13 -060058
Gavin Howard707a4e32018-10-03 16:36:41 -060059typedef struct BcLexKeyword {
Gavin Howardc1902aa2018-12-20 15:54:28 -070060 uchar data;
Gavin Howard707a4e32018-10-03 16:36:41 -060061 const char name[9];
Gavin Howard707a4e32018-10-03 16:36:41 -060062} BcLexKeyword;
63
Gavin Howard4662d6c2018-12-20 16:31:31 -070064#define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
65
Gavin Howardfbd2b4a2018-12-27 12:11:41 -070066#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))))
Gavin Howard4662d6c2018-12-20 16:31:31 -070068
Gavin Howardc1902aa2018-12-20 15:54:28 -070069#define BC_LEX_KW_ENTRY(a, b, c) \
Gavin Howard5151c872019-10-04 18:06:25 -060070 { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a }
Gavin Howard707a4e32018-10-03 16:36:41 -060071
Gavin Howardc70bd502018-12-31 17:28:32 -070072extern const BcLexKeyword bc_lex_kws[];
73extern const size_t bc_lex_kws_len;
Gavin Howard707a4e32018-10-03 16:36:41 -060074
Gavin Howard5a321892020-05-16 17:27:55 -060075void bc_lex_token(BcLex *l);
Gavin Howard707a4e32018-10-03 16:36:41 -060076
Gavin Howardb15fa032019-01-02 14:42:36 -070077#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
Gavin Howardf2d9a652019-05-11 07:38:32 -060080#define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
Gavin Howardb15fa032019-01-02 14:42:36 -070081#define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
82
Gavin Howardf2d9a652019-05-11 07:38:32 -060083#define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
Gavin Howardb15fa032019-01-02 14:42:36 -070084#define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
85
Gavin Howardf2d9a652019-05-11 07:38:32 -060086#define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
Gavin Howardb15fa032019-01-02 14:42:36 -070087#define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
88
Gavin Howardf2d9a652019-05-11 07:38:32 -060089#define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
Gavin Howardb15fa032019-01-02 14:42:36 -070090#define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
91
Gavin Howardf2d9a652019-05-11 07:38:32 -060092#define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
Gavin Howardb15fa032019-01-02 14:42:36 -070093#define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
94
Gavin Howardf2d9a652019-05-11 07:38:32 -060095#define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
Gavin Howardb15fa032019-01-02 14:42:36 -070096#define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
97
Gavin Howardf2d9a652019-05-11 07:38:32 -060098#define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
Gavin Howardb15fa032019-01-02 14:42:36 -070099#define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
100
Gavin Howardf2d9a652019-05-11 07:38:32 -0600101#define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
Gavin Howardb15fa032019-01-02 14:42:36 -0700102#define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
103
Gavin Howardf2d9a652019-05-11 07:38:32 -0600104#define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
Gavin Howardb15fa032019-01-02 14:42:36 -0700105#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
Gavin Howard7ed50c72019-01-14 11:20:12 -0700109#define BC_PARSE_DELIMITER(t) \
110 ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
Gavin Howardb15fa032019-01-02 14:42:36 -0700111
Gavin Howard63fdbfa2019-01-16 09:47:04 -0700112#define BC_PARSE_BLOCK_STMT(f) \
113 ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
114
Gavin Howard2b4fde92018-12-24 16:02:24 -0700115#define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700116
Gavin Howard1c6cfb82019-01-21 11:42:34 -0700117#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)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700120
Gavin Howard675b5cc2018-12-20 16:55:36 -0700121#define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \
Gavin Howardf2d9a652019-05-11 07:38:32 -0600122 ((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))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700125
126#define BC_PARSE_EXPR(i) \
Gavin Howard1cbfe242019-01-09 17:13:11 -0700127 (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700128
Gavin Howard890d0c02018-10-30 16:34:50 -0600129#define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
Gavin Howardb6e5a172018-12-28 17:41:15 -0700130#define BC_PARSE_LEAF(prev, bin_last, rparen) \
131 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
Gavin Howard60068bc2020-04-25 21:32:53 -0600132
Gavin Howardcb067732020-07-01 13:30:08 -0600133#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howard47137932019-10-10 21:16:43 -0600134#define BC_PARSE_INST_VAR(t) \
135 ((t) >= BC_INST_VAR && (t) <= BC_INST_SEED && (t) != BC_INST_ARRAY)
Gavin Howardcb067732020-07-01 13:30:08 -0600136#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howardf81f9042018-12-27 14:19:53 -0700137#define BC_PARSE_INST_VAR(t) \
Gavin Howardd975dc72019-01-24 15:13:17 -0700138 ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
Gavin Howardcb067732020-07-01 13:30:08 -0600139#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
Gavin Howard707a4e32018-10-03 16:36:41 -0600140
Gavin Howarde5228882019-01-10 16:08:04 -0700141#define BC_PARSE_PREV_PREFIX(p) \
Gavin Howard4684d712020-06-18 16:37:45 -0600142 ((p) >= BC_INST_NEG && (p) <= BC_INST_BOOL_NOT)
Gavin Howarde5228882019-01-10 16:08:04 -0700143#define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
Gavin Howardac7a3c92019-01-10 13:26:29 -0700144
Gavin Howard707a4e32018-10-03 16:36:41 -0600145// We can calculate the conversion between tokens and exprs by subtracting the
Gavin Howard954f9b62018-12-19 15:22:20 -0700146// 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))
Gavin Howard707a4e32018-10-03 16:36:41 -0600149
Gavin Howard5a321892020-05-16 17:27:55 -0600150typedef enum BcParseStatus {
Gavin Howard707a4e32018-10-03 16:36:41 -0600151
Gavin Howard5a321892020-05-16 17:27:55 -0600152 BC_PARSE_STATUS_SUCCESS,
153 BC_PARSE_STATUS_EMPTY_EXPR,
154
155} BcParseStatus;
156
157void bc_parse_expr(BcParse *p, uint8_t flags);
158
159void bc_parse_parse(BcParse *p);
160void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
Gavin Howardff66e292018-03-28 12:47:58 -0600161
Gavin Howard10667092018-12-20 11:52:55 -0700162extern const char bc_sig_msg[];
Gavin Howard452841b2020-05-15 13:12:55 -0600163extern const uchar bc_sig_msg_len;
Gavin Howard10667092018-12-20 11:52:55 -0700164
Gavin Howarda73c11b2018-12-17 11:30:39 -0700165extern const char* const bc_parse_const1;
Gavin Howard675b5cc2018-12-20 16:55:36 -0700166extern const uint8_t bc_parse_exprs[];
Gavin Howardc1902aa2018-12-20 15:54:28 -0700167extern const uchar bc_parse_ops[];
Gavin Howardf89006a2018-10-29 13:01:51 -0600168extern const BcParseNext bc_parse_next_expr;
169extern const BcParseNext bc_parse_next_param;
170extern const BcParseNext bc_parse_next_print;
171extern const BcParseNext bc_parse_next_rel;
172extern const BcParseNext bc_parse_next_elem;
173extern const BcParseNext bc_parse_next_for;
174extern const BcParseNext bc_parse_next_read;
175
Gavin Howard6a920e82020-09-30 09:23:37 -0600176#else // BC_ENABLED
177
178#define BC_PARSE_NO_EXEC(p) (0)
179
Gavin Howarddf4fe792018-10-03 16:48:30 -0600180#endif // BC_ENABLED
181
Gavin Howard4ffe5a92018-09-26 20:58:31 -0600182#endif // BC_BC_H