dc: fix "dc does_not_exist" SEGVing
[oweals/busybox.git] / miscutils / bc.c
index 40430d4113ab0da587b30eded78b675442bd4f09..0200afca27d8ccec79176351c1e955756666f796 100644 (file)
@@ -508,34 +508,35 @@ typedef enum BcLexType {
 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)
@@ -563,6 +564,7 @@ enum {
                | (1 << 18)
                | (1 << 19)
 };
+#define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK)
 #endif
 
 struct BcLex;
@@ -716,9 +718,6 @@ typedef struct BcProgram {
 
 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)
@@ -1070,8 +1069,12 @@ static void bc_vec_expand(BcVec *v, size_t req)
        }
 }
 
-#define bc_vec_pop(v) (bc_vec_npop((v), 1))
-#define bc_vec_top(v) (bc_vec_item_rev((v), 0))
+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)
 {
@@ -1095,8 +1098,6 @@ static void bc_vec_push(BcVec *v, const void *data)
        v->len += 1;
 }
 
-#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i))
-
 static void bc_vec_pushByte(BcVec *v, char data)
 {
        bc_vec_push(v, &data);
@@ -1160,6 +1161,11 @@ static void *bc_vec_item_rev(const BcVec *v, size_t idx)
        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;
@@ -1316,7 +1322,8 @@ static char* bc_read_file(const char *path)
        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];
@@ -2985,7 +2992,7 @@ static BcStatus bc_lex_identifier(BcLex *l)
  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;
                }
@@ -3523,12 +3530,16 @@ static BcStatus dc_lex_token(BcLex *l)
 }
 #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);
@@ -3583,6 +3594,21 @@ static BcStatus bc_parse_text(BcParse *p, const char *text)
        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))))
 
@@ -6548,24 +6574,6 @@ static void bc_program_addFunc(char *name, size_t *idx)
        }
 }
 
-// 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;