BcVecFree dtor;
} BcVec;
-#define bc_vec_pop(v) (bc_vec_npop((v), 1))
-#define bc_vec_top(v) (bc_vec_item_rev((v), 0))
-
typedef signed char BcDig;
typedef struct BcNum {
bool neg;
} BcNum;
-#define BC_NUM_MIN_BASE ((unsigned long) 2)
-#define BC_NUM_MAX_IBASE ((unsigned long) 16)
-#define BC_NUM_DEF_SIZE (16)
-#define BC_NUM_PRINT_WIDTH (69)
+#define BC_NUM_MIN_BASE ((unsigned long) 2)
+#define BC_NUM_MAX_IBASE ((unsigned long) 16)
+// larger value might speed up BIGNUM calculations a bit:
+#define BC_NUM_DEF_SIZE (16)
+#define BC_NUM_PRINT_WIDTH (69)
-#define BC_NUM_KARATSUBA_LEN (32)
+#define BC_NUM_KARATSUBA_LEN (32)
-#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
-#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
-#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
+#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
+#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
+#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
#define BC_NUM_AREQ(a, b) \
(BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
#define BC_NUM_MREQ(a, b, scale) \
struct BcLexKeyword {
char name8[8];
};
-#define BC_LEX_KW_ENTRY(a, b, c) \
- { .name8 = a /*, .len = b, .posix = c*/ }
+#define BC_LEX_KW_ENTRY(a, b) \
+ { .name8 = a /*, .posix = b */ }
static const struct BcLexKeyword bc_lex_kws[20] = {
- BC_LEX_KW_ENTRY("auto" , 4, 1), // 0
- BC_LEX_KW_ENTRY("break" , 5, 1), // 1
- BC_LEX_KW_ENTRY("continue", 8, 0), // 2 note: this one has no terminating NUL
- BC_LEX_KW_ENTRY("define" , 6, 1), // 3
-
- BC_LEX_KW_ENTRY("else" , 4, 0), // 4
- BC_LEX_KW_ENTRY("for" , 3, 1), // 5
- BC_LEX_KW_ENTRY("halt" , 4, 0), // 6
- BC_LEX_KW_ENTRY("ibase" , 5, 1), // 7
-
- BC_LEX_KW_ENTRY("if" , 2, 1), // 8
- BC_LEX_KW_ENTRY("last" , 4, 0), // 9
- BC_LEX_KW_ENTRY("length" , 6, 1), // 10
- BC_LEX_KW_ENTRY("limits" , 6, 0), // 11
-
- BC_LEX_KW_ENTRY("obase" , 5, 1), // 12
- BC_LEX_KW_ENTRY("print" , 5, 0), // 13
- BC_LEX_KW_ENTRY("quit" , 4, 1), // 14
- BC_LEX_KW_ENTRY("read" , 4, 0), // 15
-
- BC_LEX_KW_ENTRY("return" , 6, 1), // 16
- BC_LEX_KW_ENTRY("scale" , 5, 1), // 17
- BC_LEX_KW_ENTRY("sqrt" , 4, 1), // 18
- BC_LEX_KW_ENTRY("while" , 5, 1), // 19
+ BC_LEX_KW_ENTRY("auto" , 1), // 0
+ BC_LEX_KW_ENTRY("break" , 1), // 1
+ BC_LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL
+ BC_LEX_KW_ENTRY("define" , 1), // 3
+
+ BC_LEX_KW_ENTRY("else" , 0), // 4
+ BC_LEX_KW_ENTRY("for" , 1), // 5
+ BC_LEX_KW_ENTRY("halt" , 0), // 6
+ BC_LEX_KW_ENTRY("ibase" , 1), // 7
+
+ BC_LEX_KW_ENTRY("if" , 1), // 8
+ BC_LEX_KW_ENTRY("last" , 0), // 9
+ BC_LEX_KW_ENTRY("length" , 1), // 10
+ BC_LEX_KW_ENTRY("limits" , 0), // 11
+
+ BC_LEX_KW_ENTRY("obase" , 1), // 12
+ BC_LEX_KW_ENTRY("print" , 0), // 13
+ BC_LEX_KW_ENTRY("quit" , 1), // 14
+ BC_LEX_KW_ENTRY("read" , 0), // 15
+
+ BC_LEX_KW_ENTRY("return" , 1), // 16
+ BC_LEX_KW_ENTRY("scale" , 1), // 17
+ BC_LEX_KW_ENTRY("sqrt" , 1), // 18
+ BC_LEX_KW_ENTRY("while" , 1), // 19
};
+#undef BC_LEX_KW_ENTRY
enum {
POSIX_KWORD_MASK = 0
| (1 << 0)
| (1 << 18)
| (1 << 19)
};
+#define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK)
#endif
struct BcLex;
#define BC_PARSE_STREND ((char) UCHAR_MAX)
-#define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i)))
-#define bc_parse_updateFunc(p, f) \
- ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f))))
-
-#define BC_PARSE_REL (1 << 0)
-#define BC_PARSE_PRINT (1 << 1)
+#define BC_PARSE_REL (1 << 0)
+#define BC_PARSE_PRINT (1 << 1)
#define BC_PARSE_NOCALL (1 << 2)
#define BC_PARSE_NOREAD (1 << 3)
-#define BC_PARSE_ARRAY (1 << 4)
+#define BC_PARSE_ARRAY (1 << 4)
#define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags))
#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse)))
BcLexType tokens[4];
} BcParseNext;
-#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ }
-#define BC_PARSE_NEXT(a, ...) \
- { \
- .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \
- }
-
struct BcParse;
struct BcProgram;
#define BC_PROG_MAIN (0)
#define BC_PROG_READ (1)
-
#if ENABLE_DC
#define BC_PROG_REQ_FUNCS (2)
#endif
typedef unsigned long (*BcProgramBuiltIn)(BcNum *);
-static void bc_program_addFunc(char *name, size_t *idx);
-static void bc_program_reset(void);
-
#define BC_FLAG_X (1 << 0)
#define BC_FLAG_W (1 << 1)
#define BC_FLAG_V (1 << 2)
#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10)
// These identify what tokens can come after expressions in certain cases.
+#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ }
+#define BC_PARSE_NEXT(a, ...) \
+ { \
+ .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \
+ }
static const BcParseNext bc_parse_next_expr =
BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF);
static const BcParseNext bc_parse_next_param =
}
}
+static void bc_vec_pop(BcVec *v)
+{
+ v->len--;
+ if (v->dtor)
+ v->dtor(v->v + (v->size * v->len));
+}
+
static void bc_vec_npop(BcVec *v, size_t n)
{
if (!v->dtor)
len = v->len + strlen(str);
if (v->cap < len) bc_vec_grow(v, len - v->len);
- strcat(v->v, str);
+ strcpy(v->v + v->len - 1, str);
v->len = len;
}
return v->v + v->size * (v->len - idx - 1);
}
+static void *bc_vec_top(const BcVec *v)
+{
+ return v->v + v->size * (v->len - 1);
+}
+
static void bc_vec_free(void *vec)
{
BcVec *v = (BcVec *) vec;
size_t size = ((size_t) -1);
size_t i;
- buf = xmalloc_open_read_close(path, &size);
+ // Never returns NULL (dies on errors)
+ buf = xmalloc_xopen_read_close(path, &size);
for (i = 0; i < size; ++i) {
char c = buf[i];
match:
// buf starts with keyword bc_lex_kws[i]
l->t.t = BC_LEX_KEY_1st_keyword + i;
- if (!((1 << i) & POSIX_KWORD_MASK)) {
+ if (!bc_lex_kws_POSIX(i)) {
s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8);
if (s) return s;
}
}
else {
bc_vec_pop_all(&l->t.v);
- bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]);
+ bc_vec_push(&l->t.v, &l->buf[l->i - 1]);
bc_vec_pushZeroByte(&l->t.v);
l->t.t = BC_LEX_NAME;
}
}
#endif // ENABLE_DC
+static void bc_program_addFunc(char *name, size_t *idx);
+
static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
{
bc_program_addFunc(name, idx);
p->func = bc_vec_item(&G.prog.fns, p->fidx);
}
+#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i))
+
static void bc_parse_pushName(BcParse *p, char *name)
{
size_t i = 0, len = strlen(name);
return bc_lex_text(&p->l, text);
}
+// Called when parsing or execution detects a failure,
+// resets execution structures.
+static void bc_program_reset(void)
+{
+ BcFunc *f;
+ BcInstPtr *ip;
+
+ bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1);
+ bc_vec_pop_all(&G.prog.results);
+
+ f = bc_vec_item(&G.prog.fns, 0);
+ ip = bc_vec_top(&G.prog.stack);
+ ip->idx = f->code.len;
+}
+
+#define bc_parse_updateFunc(p, f) \
+ ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f))))
+
// Called when bc/dc_parse_parse() detects a failure,
// resets parsing structures.
static void bc_parse_reset(BcParse *p)
}
}
-// Called when parsing or execution detects a failure,
-// resets execution structures.
-static void bc_program_reset(void)
-{
- BcFunc *f;
- BcInstPtr *ip;
-
- bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1);
- bc_vec_pop_all(&G.prog.results);
-
- f = bc_vec_item(&G.prog.fns, 0);
- ip = bc_vec_top(&G.prog.stack);
- ip->idx = f->code.len;
-
- // If !tty, no need to check for ^C: we don't have ^C handler,
- // we would be killed by a signal and won't reach this place
-}
-
static BcStatus bc_program_exec(void)
{
BcStatus s = BC_STATUS_SUCCESS;