blob: 425ef7570155bba883ab0550c25389466d5f8250 [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 Howard7345cb92019-04-08 14:13:43 -06004 * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
Gavin Howard5715b042018-02-12 16:11:42 -07005 *
Gavin Howard7345cb92019-04-08 14:13:43 -06006 * All rights reserved.
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 Howard707a4e32018-10-03 16:36:41 -060045#include <lex.h>
46#include <parse.h>
Gavin Howard6839e4d2018-03-20 21:24:52 -060047
Gavin Howarda84ad992018-12-03 19:11:06 -070048int bc_main(int argc, char **argv);
49
Gavin Howarda046ce92019-06-14 19:43:13 -060050extern const char bc_help[];
51
Gavin Howard707a4e32018-10-03 16:36:41 -060052typedef struct BcLexKeyword {
Gavin Howardc1902aa2018-12-20 15:54:28 -070053 uchar data;
Gavin Howard707a4e32018-10-03 16:36:41 -060054 const char name[9];
Gavin Howard707a4e32018-10-03 16:36:41 -060055} BcLexKeyword;
56
Gavin Howard4662d6c2018-12-20 16:31:31 -070057#define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
58
Gavin Howardfbd2b4a2018-12-27 12:11:41 -070059#define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
60#define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
Gavin Howard4662d6c2018-12-20 16:31:31 -070061
Gavin Howardc1902aa2018-12-20 15:54:28 -070062#define BC_LEX_KW_ENTRY(a, b, c) \
Gavin Howarded38e942018-12-21 15:09:13 -070063 { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c),.name = a }
Gavin Howard707a4e32018-10-03 16:36:41 -060064
Gavin Howardc70bd502018-12-31 17:28:32 -070065extern const BcLexKeyword bc_lex_kws[];
66extern const size_t bc_lex_kws_len;
Gavin Howard707a4e32018-10-03 16:36:41 -060067
68BcStatus bc_lex_token(BcLex *l);
69
Gavin Howardb15fa032019-01-02 14:42:36 -070070#define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
71#define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
72
Gavin Howardf2d9a652019-05-11 07:38:32 -060073#define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
Gavin Howardb15fa032019-01-02 14:42:36 -070074#define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
75
Gavin Howardf2d9a652019-05-11 07:38:32 -060076#define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
Gavin Howardb15fa032019-01-02 14:42:36 -070077#define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
78
Gavin Howardf2d9a652019-05-11 07:38:32 -060079#define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
Gavin Howardb15fa032019-01-02 14:42:36 -070080#define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
81
Gavin Howardf2d9a652019-05-11 07:38:32 -060082#define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
Gavin Howardb15fa032019-01-02 14:42:36 -070083#define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
84
Gavin Howardf2d9a652019-05-11 07:38:32 -060085#define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
Gavin Howardb15fa032019-01-02 14:42:36 -070086#define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
87
Gavin Howardf2d9a652019-05-11 07:38:32 -060088#define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
Gavin Howardb15fa032019-01-02 14:42:36 -070089#define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
90
Gavin Howardf2d9a652019-05-11 07:38:32 -060091#define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
Gavin Howardb15fa032019-01-02 14:42:36 -070092#define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
93
Gavin Howardf2d9a652019-05-11 07:38:32 -060094#define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
Gavin Howardb15fa032019-01-02 14:42:36 -070095#define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
96
Gavin Howardf2d9a652019-05-11 07:38:32 -060097#define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
Gavin Howardb15fa032019-01-02 14:42:36 -070098#define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
99
100#define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
101
Gavin Howard7ed50c72019-01-14 11:20:12 -0700102#define BC_PARSE_DELIMITER(t) \
103 ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
Gavin Howardb15fa032019-01-02 14:42:36 -0700104
Gavin Howard63fdbfa2019-01-16 09:47:04 -0700105#define BC_PARSE_BLOCK_STMT(f) \
106 ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
107
Gavin Howard2b4fde92018-12-24 16:02:24 -0700108#define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700109
Gavin Howard1c6cfb82019-01-21 11:42:34 -0700110#define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
111#define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
112#define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700113
Gavin Howard675b5cc2018-12-20 16:55:36 -0700114#define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \
Gavin Howardf2d9a652019-05-11 07:38:32 -0600115 ((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \
116 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \
117 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700118
119#define BC_PARSE_EXPR(i) \
Gavin Howard1cbfe242019-01-09 17:13:11 -0700120 (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700121
Gavin Howard890d0c02018-10-30 16:34:50 -0600122#define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
Gavin Howardb6e5a172018-12-28 17:41:15 -0700123#define BC_PARSE_LEAF(prev, bin_last, rparen) \
124 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
Gavin Howardf81f9042018-12-27 14:19:53 -0700125#define BC_PARSE_INST_VAR(t) \
Gavin Howardd975dc72019-01-24 15:13:17 -0700126 ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
Gavin Howard707a4e32018-10-03 16:36:41 -0600127
Gavin Howarde5228882019-01-10 16:08:04 -0700128#define BC_PARSE_PREV_PREFIX(p) \
129 ((p) >= BC_INST_INC_PRE && (p) <= BC_INST_BOOL_NOT)
130#define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
Gavin Howardac7a3c92019-01-10 13:26:29 -0700131
Gavin Howard707a4e32018-10-03 16:36:41 -0600132// We can calculate the conversion between tokens and exprs by subtracting the
Gavin Howard954f9b62018-12-19 15:22:20 -0700133// position of the first operator in the lex enum and adding the position of
134// the first in the expr enum. Note: This only works for binary operators.
135#define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG))
Gavin Howard707a4e32018-10-03 16:36:41 -0600136
Gavin Howard7536dcf2018-12-15 19:27:09 -0700137BcStatus bc_parse_expr(BcParse *p, uint8_t flags);
Gavin Howard707a4e32018-10-03 16:36:41 -0600138
Gavin Howard9d2497d2018-10-29 16:10:21 -0600139BcStatus bc_parse_parse(BcParse *p);
Gavin Howard7536dcf2018-12-15 19:27:09 -0700140BcStatus bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
Gavin Howardff66e292018-03-28 12:47:58 -0600141
Gavin Howardc5295782019-05-12 17:26:29 -0600142// This is necessary to clear up for if statements at the end of files.
143void bc_parse_noElse(BcParse *p);
144
Gavin Howard10667092018-12-20 11:52:55 -0700145#if BC_ENABLE_SIGNALS
146extern const char bc_sig_msg[];
Gavin Howard10667092018-12-20 11:52:55 -0700147#endif // BC_ENABLE_SIGNALS
148
Gavin Howarda73c11b2018-12-17 11:30:39 -0700149extern const char* const bc_parse_const1;
Gavin Howard675b5cc2018-12-20 16:55:36 -0700150extern const uint8_t bc_parse_exprs[];
Gavin Howardc1902aa2018-12-20 15:54:28 -0700151extern const uchar bc_parse_ops[];
Gavin Howardf89006a2018-10-29 13:01:51 -0600152extern const BcParseNext bc_parse_next_expr;
153extern const BcParseNext bc_parse_next_param;
154extern const BcParseNext bc_parse_next_print;
155extern const BcParseNext bc_parse_next_rel;
156extern const BcParseNext bc_parse_next_elem;
157extern const BcParseNext bc_parse_next_for;
158extern const BcParseNext bc_parse_next_read;
159
Gavin Howarddf4fe792018-10-03 16:48:30 -0600160#endif // BC_ENABLED
161
Gavin Howard4ffe5a92018-09-26 20:58:31 -0600162#endif // BC_BC_H