コード例 #1
0
static void
bdivmod(void)
{
	struct number *a, *b, *rdiv, *rmod;
	BN_CTX *ctx;
	u_int scale;

	a = pop_number();
	if (a == NULL) {
		return;
	}
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}

	rdiv = new_number();
	rmod = new_number();
	rdiv->scale = bmachine.scale;
	rmod->scale = max(b->scale, a->scale + bmachine.scale);
	scale = max(a->scale, b->scale);

	if (BN_is_zero(a->number))
		warnx("divide by zero");
	else {
		normalize(a, scale);
		normalize(b, scale + bmachine.scale);

		ctx = BN_CTX_new();
		bn_checkp(ctx);
		bn_check(BN_div(rdiv->number, rmod->number,
		    b->number, a->number, ctx));
		BN_CTX_free(ctx);
	}
	push_number(rdiv);
	push_number(rmod);
	free_number(a);
	free_number(b);
}
コード例 #2
0
ファイル: inout.c プロジェクト: StarchLinux/coreutils
struct number *
readnumber(struct source *src, u_int base)
{
	struct number	*n;
	int		ch;
	bool		sign = false;
	bool		dot = false;
	BN_ULONG	v;
	u_int		i;

	n = new_number();
	bn_check(BN_zero(n->number));

	while ((ch = (*src->vtable->readchar)(src)) != EOF) {

		if ('0' <= ch && ch <= '9')
			v = ch - '0';
		else if ('A' <= ch && ch <= 'F')
			v = ch - 'A' + 10;
		else if (ch == '_') {
			sign = true;
			continue;
		} else if (ch == '.') {
			if (dot)
				break;
			dot = true;
			continue;
		} else {
			(*src->vtable->unreadchar)(src);
			break;
		}
		if (dot)
			n->scale++;

		bn_check(BN_mul_word(n->number, base));

#if 0
		/* work around a bug in BN_add_word: 0 += 0 is buggy.... */
		if (v > 0)
#endif
			bn_check(BN_add_word(n->number, v));
	}
	if (base != 10) {
		scale_number(n->number, n->scale);
		for (i = 0; i < n->scale; i++)
			(void)BN_div_word(n->number, base);
	}
	if (sign)
		negate(n);
	return n;
}
コード例 #3
0
ファイル: bcode.c プロジェクト: FreeBSDFoundation/freebsd
static u_int
count_digits(const struct number *n)
{
	struct number *int_part, *fract_part;
	u_int i;

	if (BN_is_zero(n->number))
		return n->scale ? n->scale : 1;

	int_part = new_number();
	fract_part = new_number();
	fract_part->scale = n->scale;
	split_number(n, int_part->number, fract_part->number);

	i = 0;
	while (!BN_is_zero(int_part->number)) {
		BN_div_word(int_part->number, 10);
		i++;
	}
	free_number(int_part);
	free_number(fract_part);
	return (i + n->scale);
}
コード例 #4
0
ファイル: bcode.c プロジェクト: darksoul42/bitrig
static void
bsqrt(void)
{
	struct number	*n;
	struct number	*r;
	BIGNUM		*x, *y;
	u_int		scale, onecount;
	BN_CTX		*ctx;

	onecount = 0;
	n = pop_number();
	if (n == NULL) {
		return;
	}
	if (BN_is_zero(n->number)) {
		r = new_number();
		push_number(r);
	} else if (BN_is_negative(n->number))
		warnx("square root of negative number");
	else {
		scale = max(bmachine.scale, n->scale);
		normalize(n, 2*scale);
		x = BN_dup(n->number);
		bn_checkp(x);
		bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
		y = BN_new();
		bn_checkp(y);
		ctx = BN_CTX_new();
		bn_checkp(ctx);
		for (;;) {
			bn_checkp(BN_copy(y, x));
			bn_check(BN_div(x, NULL, n->number, x, ctx));
			bn_check(BN_add(x, x, y));
			bn_check(BN_rshift1(x, x));
			if (bsqrt_stop(x, y, &onecount))
				break;
		}
		r = bmalloc(sizeof(*r));
		r->scale = scale;
		r->number = y;
		BN_free(x);
		BN_CTX_free(ctx);
		push_number(r);
	}

	free_number(n);
}
コード例 #5
0
ファイル: bcode.c プロジェクト: darksoul42/bitrig
static void
load(void)
{
	int		idx;
	struct value	*v, copy;
	struct number	*n;

	idx = readreg();
	if (idx >= 0) {
		v = stack_tos(&bmachine.reg[idx]);
		if (v == NULL) {
			n = new_number();
			bn_check(BN_zero(n->number));
			push_number(n);
		} else
			push(stack_dup_value(v, &copy));
	}
}
コード例 #6
0
ファイル: bcode.c プロジェクト: FreeBSDFoundation/freebsd
static void
lesseq_numbers(void)
{
	struct number *a, *b, *r;

	a = pop_number();
	if (a == NULL)
		return;
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}
	r = new_number();
	bn_check(BN_set_word(r->number,
	    compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
	push_number(r);
}
コード例 #7
0
ファイル: bcode.c プロジェクト: darksoul42/bitrig
static void
equal_numbers(void)
{
	struct number *a, *b, *r;

	a = pop_number();
	if (a == NULL) {
		return;
	}
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}
	r = new_number();
	bn_check(BN_set_word(r->number,
	    compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
	push_number(r);
}
コード例 #8
0
ファイル: interp.c プロジェクト: chubbymaggie/cb-multios
static int cgc_assign_result(interp_t *interp, expr_t *expr)
{
    char tmp[20];
    if (expr->op == OP_FIELD || expr->op == OP_FIELD_VAR)
    {
        int num;
        if (expr->op == OP_FIELD)
            num = expr->e_cint.value;
        else
        {
            if (!get_number(interp, expr->e_var.name, &num))
                return 0;
        }

        if (interp->result.type == VAR_NUMBER)
        {
            to_string_buf(interp->result.v_number.value, tmp);
            return cgc_set_field(interp, num, tmp);
        }
        else if (interp->result.type == VAR_STRING)
        {
            return cgc_set_field(interp, num, interp->result.v_string.value);
        }
        return 0;
    }
    else if (expr->op == OP_VAR)
    {
        var_t *var = NULL;
        if (interp->result.type == VAR_STRING)
            var = new_string(cgc_strdup(interp->result.v_string.value));
        else
            var = new_number(interp->result.v_number.value);
        if (var == NULL)
            return 0;
        return cgc_dict_add(&interp->vars, expr->e_var.name, var);
    }
    else
    {
        return 0;
    }
}
コード例 #9
0
ファイル: bcode.c プロジェクト: FreeBSDFoundation/freebsd
static void
bmul(void)
{
	struct number *a, *b, *r;

	a = pop_number();
	if (a == NULL)
		return;
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}

	r = new_number();
	bmul_number(r, a, b, bmachine.scale);

	push_number(r);
	free_number(a);
	free_number(b);
}
コード例 #10
0
ファイル: 103mtq_02.c プロジェクト: easontse/CLab
int main()
{
	srand(time(NULL));

	int num;
	char oper;

	do {
		do {
			num = rand() % 10000;
		} while ((num < 1000 || num > 9999) || (isPrime(num) == 'N'));

		printf("原始數字:%d\n", num);
		//printf("new_number: %d\n", new_number(num));
		printf("密碼:%d\n", password(new_number(num)));

		printf("是否繼續產生密碼(輸入0程式結束):");
		scanf(" %c", &oper);
	} while (oper != '0');

	return 0;
}
コード例 #11
0
ファイル: bcode.c プロジェクト: repos-holder/openbsd-patches
static void
bmul(void)
{
	struct number	*a, *b;
	struct number	*r;

	a = pop_number();
	if (a == NULL) {
		return;
	}
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}

	r = new_number();
	bmul_number(r, a, b);

	push_number(r);
	free_number(a);
	free_number(b);
}
コード例 #12
0
ファイル: bcode.c プロジェクト: darksoul42/bitrig
static void
bmod(void)
{
	struct number	*a, *b;
	struct number	*r;
	u_int		scale;
	BN_CTX		*ctx;

	a = pop_number();
	if (a == NULL) {
		return;
	}
	b = pop_number();
	if (b == NULL) {
		push_number(a);
		return;
	}

	r = new_number();
	scale = max(a->scale, b->scale);
	r->scale = max(b->scale, a->scale + bmachine.scale);

	if (BN_is_zero(a->number))
		warnx("remainder by zero");
	else {
		normalize(a, scale);
		normalize(b, scale + bmachine.scale);

		ctx = BN_CTX_new();
		bn_checkp(ctx);
		bn_check(BN_mod(r->number, b->number, a->number, ctx));
		BN_CTX_free(ctx);
	}
	push_number(r);
	free_number(a);
	free_number(b);
}
コード例 #13
0
ファイル: bcode.c プロジェクト: FreeBSDFoundation/freebsd
static void
push_scale(void)
{
	struct number *n;
	struct value *value;
	u_int scale = 0;

	value = pop();
	if (value != NULL) {
		switch (value->type) {
		case BCODE_NONE:
			return;
		case BCODE_NUMBER:
			scale = value->u.num->scale;
			break;
		case BCODE_STRING:
			break;
		}
		stack_free_value(value);
		n = new_number();
		bn_check(BN_set_word(n->number, scale));
		push_number(n);
	}
}
コード例 #14
0
ファイル: inout.c プロジェクト: AhmadTux/DragonFlyBSD
void
printnumber(FILE *f, const struct number *b, u_int base)
{
	struct number	*int_part, *fract_part;
	int		digits;
	char		buf[11];
	size_t		sz;
	int		i;
	struct stack	stack;
	char		*p;

	charcount = 0;
	lastchar = -1;
	if (BN_is_zero(b->number))
		putcharwrap(f, '0');

	int_part = new_number();
	fract_part = new_number();
	fract_part->scale = b->scale;

	if (base <= 16)
		digits = 1;
	else {
		digits = snprintf(buf, sizeof(buf), "%u", base-1);
	}
	split_number(b, int_part->number, fract_part->number);

	i = 0;
	stack_init(&stack);
	while (!BN_is_zero(int_part->number)) {
		BN_ULONG rem = BN_div_word(int_part->number, base);
		stack_pushstring(&stack, get_digit(rem, digits, base));
		i++;
	}
	sz = i;
	if (BN_cmp(b->number, &zero) < 0)
		putcharwrap(f, '-');
	for (i = 0; i < sz; i++) {
		p = stack_popstring(&stack);
		if (base > 16)
			putcharwrap(f, ' ');
		printwrap(f, p);
		free(p);
	}
	stack_clear(&stack);
	if (b->scale > 0) {
		struct number	*num_base;
		BIGNUM		mult, stop;

		putcharwrap(f, '.');
		num_base = new_number();
		BN_set_word(num_base->number, base);
		BN_init(&mult);
		BN_one(&mult);
		BN_init(&stop);
		BN_one(&stop);
		scale_number(&stop, b->scale);

		i = 0;
		while (BN_cmp(&mult, &stop) < 0) {
			u_long	rem;

			if (i && base > 16)
				putcharwrap(f, ' ');
			i = 1;

			bmul_number(fract_part, fract_part, num_base);
			split_number(fract_part, int_part->number, NULL);
			rem = BN_get_word(int_part->number);
			p = get_digit(rem, digits, base);
			int_part->scale = 0;
			normalize(int_part, fract_part->scale);
			BN_sub(fract_part->number, fract_part->number,
			    int_part->number);
			printwrap(f, p);
			free(p);
			BN_mul_word(&mult, base);
		}
		free_number(num_base);
		BN_free(&mult);
		BN_free(&stop);
	}
	flushwrap(f);
	free_number(int_part);
	free_number(fract_part);
}
コード例 #15
0
ファイル: machine.c プロジェクト: EarlGray/SECD
static cell_t *chain_index(secd_t *secd, const cell_t *cell, cell_t *prev) {
    return new_cons(secd, new_number(secd, cell_index(secd, cell)), prev);
}
コード例 #16
0
ファイル: machine.c プロジェクト: EarlGray/SECD
cell_t *serialize_cell(secd_t *secd, cell_t *cell) {
    cell_t *opt = SECD_NIL;
    switch (cell_type(cell)) {
    case CELL_CONS: {
        cell_t *cdrc = chain_index(secd, get_cdr(cell), SECD_NIL);
        opt = chain_index(secd, get_car(cell), cdrc);
    }
    break;
    case CELL_PORT:
        opt = secd_pserialize(secd, cell);
        break;
    case CELL_SYM:
        opt = new_cons(secd, cell, SECD_NIL);
        break;
    case CELL_INT:
    case CELL_CHAR:
        opt = new_cons(secd, cell, SECD_NIL);
        break;
    case CELL_OP: {
        cell_t *namec = new_symbol(secd, opcode_table[ cell->as.op ].name);
        opt = new_cons(secd, namec, SECD_NIL);
    }
    break;
    case CELL_FUNC:
        opt = new_cons(secd, new_number(secd, (long)cell->as.ptr), SECD_NIL);
        break;
    case CELL_ARRMETA: {
        cell_t *typec = chain_sym(secd,
                                  (cell->as.mcons.cells ? "cell" : "byte"),
                                  SECD_NIL);
        cell_t *nextc = chain_index(secd, mcons_next(cell), typec);
        opt = chain_index(secd, mcons_prev(cell), nextc);
    }
    break;
    case CELL_FRAME: {
        cell_t *ioc = chain_index(secd, cell->as.frame.io, SECD_NIL);
        cell_t *nextc = chain_index(secd, cell->as.frame.cons.cdr, ioc);
        opt = chain_index(secd, cell->as.frame.cons.car, nextc);
    }
    break;
    case CELL_KONT: {
        cell_t *kctrl = chain_index(secd, cell->as.kont.ctrl, SECD_NIL);
        cell_t *kenv  = chain_index(secd, cell->as.kont.env,  kctrl);
        opt = chain_index(secd, cell->as.kont.stack, kenv);
    }
    break;
    case CELL_FREE: {
        cell_t *nextc = chain_index(secd, get_cdr(cell), SECD_NIL);
        opt = chain_index(secd, get_car(cell), nextc);
    }
    break;
    case CELL_REF:
        opt = chain_index(secd, cell->as.ref, SECD_NIL);
        break;
    case CELL_ERROR:
        opt = chain_string(secd, errmsg(cell), SECD_NIL);
        break;
    case CELL_UNDEF:
        opt = SECD_NIL;
        break;
    case CELL_ARRAY:
        opt = chain_index(secd, arr_val(cell, -1), SECD_NIL);
        break;
    case CELL_STR:
    case CELL_BYTES:
        opt = chain_index(secd, arr_meta((cell_t *)strmem(cell)), SECD_NIL);
        break;
    }
    opt = new_cons(secd, secd_type_sym(secd, cell), opt);
    cell_t *refc = new_cons(secd, new_number(secd, cell->nref), opt);
    return new_cons(secd, new_number(secd, cell - secd->begin), refc);
}
コード例 #17
0
static cell_t *read_token(secd_t *secd, secd_parser_t *p) {
    int tok;
    cell_t *inp = NULL;
    switch (tok = p->token) {
      case '(':
        ++p->nested;
        inp = read_list(secd, p);
        if (p->token != ')')
            goto error_exit;
        return inp;
      case TOK_NUM:
        return new_number(secd, p->numtok);
      case TOK_CHAR:
        return new_char(secd, p->numtok);
      case TOK_SYM:
        return new_symbol(secd, p->symtok);
      case TOK_STR:
        inp = new_string(secd, strmem(p->strtok));
        drop_cell(secd, p->strtok);
        return inp;
      case TOK_EOF:
        return new_symbol(secd, EOF_OBJ);

      case TOK_QUOTE: case TOK_QQ:
      case TOK_UQ: case TOK_UQSPL: {
        const char *formname = special_form_for(tok);
        assert(formname, "No  special form for token=%d\n", tok);
        inp = sexp_read(secd, p);
        assert_cell(inp, "sexp_read: reading subexpression failed");
        return new_cons(secd, new_symbol(secd, formname),
                              new_cons(secd, inp, SECD_NIL));
      }

      case '#':
        switch (tok = lexnext(p)) {
          case '(': {
              cell_t *tmplist = read_list(secd, p);
              if (p->token != ')') {
                  free_cell(secd, tmplist);
                  goto error_exit;
              }
              inp = list_to_vector(secd, tmplist);
              free_cell(secd, tmplist);
              return inp;
            }
          case TOK_SYM: {
              if (p->symtok[0] == '.') {
                int op = secdop_by_name(p->symtok + 1);
                if (op < 0)
                    goto error_exit;

                return new_op(secd, op);
              }
              if (str_eq(p->symtok, "u8")) {
                  lexnext(p);
                  inp = read_bytevector(p);
                  if (p->token != ')')
                      goto error_exit;
                  return inp;
              }
          }
        }
        errorf("Unknown suffix for #\n");
    }

error_exit:
    if (inp) free_cell(secd, inp);
    errorf("read_token: failed\n");
    return new_error(secd, SECD_NIL,
            "read_token: failed on token %1$d '%1$c'", p->token);
}
コード例 #18
0
ファイル: bcode.c プロジェクト: FreeBSDFoundation/freebsd
static void
bexp(void)
{
	struct number	*a, *p;
	struct number	*r;
	bool		neg;
	u_int		rscale;

	p = pop_number();
	if (p == NULL)
		return;
	a = pop_number();
	if (a == NULL) {
		push_number(p);
		return;
	}

	if (p->scale != 0) {
		BIGNUM *i, *f;
		i = BN_new();
		bn_checkp(i);
		f = BN_new();
		bn_checkp(f);
		split_number(p, i, f);
		if (!BN_is_zero(f))
			warnx("Runtime warning: non-zero fractional part in exponent");
		BN_free(i);
		BN_free(f);
	}

	normalize(p, 0);

	neg = false;
	if (BN_is_negative(p->number)) {
		neg = true;
		negate(p);
		rscale = bmachine.scale;
	} else {
		/* Posix bc says min(a.scale * b, max(a.scale, scale) */
		u_long b;
		u_int m;

		b = BN_get_word(p->number);
		m = max(a->scale, bmachine.scale);
		rscale = a->scale * (u_int)b;
		if (rscale > m || (a->scale > 0 && (b == ULONG_MAX ||
		    b > UINT_MAX)))
			rscale = m;
	}

	if (BN_is_zero(p->number)) {
		r = new_number();
		bn_check(BN_one(r->number));
		normalize(r, rscale);
	} else {
		u_int ascale, mscale;

		ascale = a->scale;
		while (!BN_is_bit_set(p->number, 0)) {
			ascale *= 2;
			bmul_number(a, a, a, ascale);
			bn_check(BN_rshift1(p->number, p->number));
		}

		r = dup_number(a);
		bn_check(BN_rshift1(p->number, p->number));

		mscale = ascale;
		while (!BN_is_zero(p->number)) {
			ascale *= 2;
			bmul_number(a, a, a, ascale);
			if (BN_is_bit_set(p->number, 0)) {
				mscale += ascale;
				bmul_number(r, r, a, mscale);
			}
			bn_check(BN_rshift1(p->number, p->number));
		}

		if (neg) {
			BN_CTX *ctx;
			BIGNUM *one;

			one = BN_new();
			bn_checkp(one);
			bn_check(BN_one(one));
			ctx = BN_CTX_new();
			bn_checkp(ctx);
			scale_number(one, r->scale + rscale);

			if (BN_is_zero(r->number))
				warnx("divide by zero");
			else
				bn_check(BN_div(r->number, NULL, one,
				    r->number, ctx));
			BN_free(one);
			BN_CTX_free(ctx);
			r->scale = rscale;
		} else
			normalize(r, rscale);
	}
	push_number(r);
	free_number(a);
	free_number(p);
}
コード例 #19
0
ファイル: bcode.c プロジェクト: repos-holder/openbsd-patches
static void
bexp(void)
{
	struct number	*a, *p;
	struct number	*r;
	bool		neg;
	u_int		scale;

	p = pop_number();
	if (p == NULL) {
		return;
	}
	a = pop_number();
	if (a == NULL) {
		push_number(p);
		return;
	}

	if (p->scale != 0)
		warnx("Runtime warning: non-zero scale in exponent");
	normalize(p, 0);

	neg = false;
	if (BN_cmp(p->number, &zero) < 0) {
		neg = true;
		negate(p);
		scale = bmachine.scale;
	} else {
		/* Posix bc says min(a.scale * b, max(a.scale, scale) */
		u_long	b;
		u_int	m;

		b = BN_get_word(p->number);
		m = max(a->scale, bmachine.scale);
		scale = a->scale * (u_int)b;
		if (scale > m || (a->scale > 0 && (b == BN_MASK2 ||
		    b > UINT_MAX)))
			scale = m;
	}

	if (BN_is_zero(p->number)) {
		r = new_number();
		bn_check(BN_one(r->number));
		normalize(r, scale);
	} else {
		while (!BN_is_bit_set(p->number, 0)) {
			bmul_number(a, a, a);
			bn_check(BN_rshift1(p->number, p->number));
		}

		r = dup_number(a);
		normalize(r, scale);
		bn_check(BN_rshift1(p->number, p->number));

		while (!BN_is_zero(p->number)) {
			bmul_number(a, a, a);
			if (BN_is_bit_set(p->number, 0))
				bmul_number(r, r, a);
			bn_check(BN_rshift1(p->number, p->number));
		}

		if (neg) {
			BN_CTX	*ctx;
			BIGNUM	*one;

			one = BN_new();
			bn_checkp(one);
			bn_check(BN_one(one));
			ctx = BN_CTX_new();
			bn_checkp(ctx);
			scale_number(one, r->scale + scale);
			normalize(r, scale);
			bn_check(BN_div(r->number, NULL, one, r->number, ctx));
			BN_free(one);
			BN_CTX_free(ctx);
		} else
			normalize(r, scale);
	}
	push_number(r);
	free_number(a);
	free_number(p);
}
コード例 #20
0
ファイル: parse.c プロジェクト: mk12/eva
// Parses any expression.
struct ParseResult parse(const char *text) {
	struct ParseResult result;
	result.err_type = PARSE_SUCCESS;
	const char *s = text;
	s += skip_whitespace(s);

	size_t len;
	switch (*s) {
	case '\0':
		result.err_type = ERR_UNEXPECTED_EOI;
		break;
	case '(':
		s++;
		result = parse_pair(s);
		s += result.chars_read;
		break;
	case ')':
		result.err_type = ERR_UNEXPECTED_RPAREN;
		break;
	case '.':
		result.err_type = ERR_INVALID_DOT;
		break;
	case '#':
		len = skip_symbol(s + 1);
		if (len == 1 && s[1] == 't') {
			s += 2;
			result.expr = new_boolean(true);
		} else if (len == 1 && s[1] == 'f') {
			s += 2;
			result.expr = new_boolean(false);
		} else if (len > 2 && s[1] == '\\') {
			char c = parse_char_name(s + 2, len - 1);
			if (c == '\0') {
				s += 2;
				result.err_type = ERR_UNKNOWN_CHARACTER;
			} else {
				s += 1 + len;
				result.expr = new_character(c);
			}
		} else if (s[1] == '\\' && s[2] && !isspace(s[2])) {
			result.expr = new_character(s[2]);
			s += 3;
		} else {
			result.err_type = ERR_INVALID_LITERAL;
		}
		break;
	case '\'':
		s++;
		result = parse(s);
		s += result.chars_read;
		if (result.err_type == PARSE_SUCCESS) {
			result.expr = new_pair(
					new_stdmacro(F_QUOTE),
					new_pair(result.expr, new_null()));
		}
		break;
	case '`':
		s++;
		result = parse(s);
		s += result.chars_read;
		if (result.err_type == PARSE_SUCCESS) {
			result.expr = new_pair(
					new_stdmacro(F_QUASIQUOTE),
					new_pair(result.expr, new_null()));
		}
		break;
	case ',':
		s++;
		enum StandardMacro stdmacro = F_UNQUOTE;
		if (*s == '@') {
			s++;
			stdmacro = F_UNQUOTE_SPLICING;
		}
		result = parse(s);
		s += result.chars_read;
		if (result.err_type == PARSE_SUCCESS) {
			result.expr = new_pair(
					new_stdmacro(stdmacro),
					new_pair(result.expr, new_null()));
		}
		break;
	case '"':
		s++;
		len = skip_string(s);
		if (!(s[len-1] == '\\' && (len < 2 || s[len-2] == '\\'))
				&& s[len] == '"') {
			result.expr = parse_string(s, len);
		} else {
			result.err_type = ERR_UNEXPECTED_EOI;
		}
		s += len;
		s++;
		break;
	default:;
		len = skip_symbol(s);
		assert(len > 0);
		Number number;
		if (parse_number(s, len, &number)) {
			result.expr = new_number(number);
		} else {
			InternId symbol_id = intern_string_n(s, len);
			result.expr = new_symbol(symbol_id);
		}
		s += len;
		break;
	}

	if (result.err_type == PARSE_SUCCESS) {
		s += skip_whitespace(s);
		assert(s > text);
	}
	result.chars_read = (size_t)(s - text);
	return result;
}