mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-03-09 06:30:32 -07:00
[wip] reader: add a new helper function ecl_parse_fixnum
This funciton parses an integer and returns OBJNULL when it exceeds the size of a fixnum. It is used in format.d - a file that is not compiled currently. It should be also used in cl_name_char. [wip] because: - is it really needed? - I've commented unicode access for digitp
This commit is contained in:
parent
20a7332473
commit
eb6b814a53
4 changed files with 108 additions and 32 deletions
|
|
@ -78,8 +78,8 @@ WRITER_OBJS = print.o printer/float_to_digits.o printer/float_to_string.o
|
|||
printer/write_list.o printer/write_code.o printer/write_sse.o \
|
||||
printer/print_unreadable.o
|
||||
|
||||
READER_OBJS = reader.o read.o reader/rtab_cl.o \
|
||||
reader/parse_token.o reader/parse_integer.o reader/parse_number.o
|
||||
READER_OBJS = reader.o read.o reader/rtab_cl.o reader/parse_token.o \
|
||||
reader/parse_fixnum.o reader/parse_integer.o reader/parse_number.o
|
||||
|
||||
STREAM_OBJS = stream.o file.o streams/strm_os.o streams/strm_clos.o \
|
||||
streams/strm_string.o streams/strm_composite.o streams/strm_common.o \
|
||||
|
|
|
|||
|
|
@ -40,19 +40,6 @@ typedef struct format_stack_struct {
|
|||
int nparam;
|
||||
} *format_stack;
|
||||
|
||||
#if MOST_POSITIVE_FIXNUM_VAL < INT_MAX
|
||||
# define FMT_VALUE_UPPER_LIMIT MOST_POSITIVE_FIXNUM
|
||||
#else
|
||||
# define FMT_VALUE_UPPER_LIMIT INT_MAX
|
||||
#endif
|
||||
|
||||
#if MOST_NEGATIVE_FIXNUM_VAL > INT_MIN
|
||||
# define FMT_VALUE_LOWER_LIMIT MOST_NEGATIVE_FIXNUM
|
||||
#else
|
||||
# define FMT_VALUE_LOWER_LIMIT INT_MIN
|
||||
#endif
|
||||
|
||||
|
||||
/******************* COMMON ***************************/
|
||||
|
||||
#define NONE 0
|
||||
|
|
@ -2000,25 +1987,11 @@ format(format_stack fmt, cl_index start, cl_index end)
|
|||
do {
|
||||
c = ctl_advance(fmt);
|
||||
} while (ecl_digitp(c,10) != -1);
|
||||
x = ecl_parse_integer(fmt->ctl_str, i, fmt->ctl_index, &i, 10);
|
||||
x = ecl_parse_fixnum(fmt->ctl_str, i, fmt->ctl_index, &i, 10);
|
||||
INTEGER:
|
||||
/* FIXME! A hack to solve the problem of bignums in arguments */
|
||||
if (x == OBJNULL || !ecl_numberp(x))
|
||||
fmt_error(fmt, "integer expected");
|
||||
if (ecl_number_compare(x, ecl_make_fixnum(FMT_VALUE_UPPER_LIMIT)) > 0) {
|
||||
fmt->param[n] = ecl_make_fixnum(FMT_VALUE_UPPER_LIMIT);
|
||||
} else if (ecl_number_compare(x, ecl_make_fixnum(FMT_VALUE_LOWER_LIMIT)) < 0) {
|
||||
fmt->param[n] = ecl_make_fixnum(FMT_VALUE_LOWER_LIMIT);
|
||||
} else {
|
||||
fmt->param[n] = x;
|
||||
}
|
||||
if (ECL_FIXNUMP(x)) {
|
||||
fmt->param[n] = x;
|
||||
} else if (ecl_plusp(x)) {
|
||||
fmt->param[n] = ecl_make_fixnum(MOST_POSITIVE_FIXNUM);
|
||||
} else {
|
||||
fmt->param[n] = ecl_make_fixnum(MOST_NEGATIVE_FIXNUM);
|
||||
}
|
||||
fmt_error(fmt, "fixnum expected");
|
||||
fmt->param[n] = x;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
|
|
|
|||
102
src/c/reader/parse_fixnum.d
Normal file
102
src/c/reader/parse_fixnum.d
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1984 Taiichi Yuasa and Masami Hagiya
|
||||
* Copyright (c) 1990 Giuseppe Attardi
|
||||
* Copyright (c) 2001 Juan Jose Garcia Ripoll
|
||||
* Copyright (c) 2026 Daniel Kochmański
|
||||
*
|
||||
* See file 'LICENSE' for the copyright details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ecl/ecl.h>
|
||||
#include <ecl/number.h>
|
||||
#include <ecl/internal.h>
|
||||
|
||||
#define basep(d) (d <= 36)
|
||||
|
||||
static ecl_character
|
||||
_ecl_char(cl_object object, cl_index index)
|
||||
{
|
||||
switch(ecl_t_of(object)) {
|
||||
#ifdef ECL_UNICODE
|
||||
case t_string:
|
||||
return object->string.self[index];
|
||||
#endif
|
||||
case t_base_string:
|
||||
return object->base_string.self[index];
|
||||
default:
|
||||
ecl_internal_error("ecl_parse_fixnum: source is not a string.");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_ecl_digitp(ecl_character i, int r)
|
||||
{
|
||||
if (('0' <= i) && (i <= '9') && (i < '0' + r))
|
||||
return i - '0';
|
||||
if (('A' <= i) && (10 < r) && (i < 'A' + (r - 10)))
|
||||
return i - 'A' + 10;
|
||||
if (('a' <= i) && (10 < r) && (i < 'a' + (r - 10)))
|
||||
return i - 'a' + 10;
|
||||
/* #ifdef ECL_UNICODE */
|
||||
/* if (i > 255) { */
|
||||
/* int number = ucd_decimal_digit(i); */
|
||||
/* if (number < r) */
|
||||
/* return number; */
|
||||
/* } */
|
||||
/* #endif */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This is like ecl_parse_integer (including the API), but returns OBJNULL also
|
||||
when the result does not fit in a fixnum. */
|
||||
cl_object
|
||||
ecl_parse_fixnum(cl_object str, cl_index start, cl_index end,
|
||||
cl_index *ep, unsigned int radix)
|
||||
{
|
||||
int sign, d;
|
||||
cl_fixnum aux, integer_part;
|
||||
cl_object output;
|
||||
cl_index i, c;
|
||||
|
||||
if (start >= end || !basep(radix)) {
|
||||
*ep = start;
|
||||
return OBJNULL;
|
||||
}
|
||||
sign = 1;
|
||||
c = _ecl_char(str, start);
|
||||
if (c == '+') {
|
||||
start++;
|
||||
} else if (c == '-') {
|
||||
sign = -1;
|
||||
start++;
|
||||
}
|
||||
integer_part = 0;
|
||||
for (i = start; i < end; i++) {
|
||||
c = _ecl_char(str, i);
|
||||
d = _ecl_digitp(c, radix);
|
||||
if (d < 0) {
|
||||
break;
|
||||
}
|
||||
aux = integer_part;
|
||||
integer_part *= radix;
|
||||
if (integer_part/radix != aux) {
|
||||
*ep = i-1;
|
||||
return OBJNULL;
|
||||
}
|
||||
integer_part += d;
|
||||
if (integer_part > MOST_POSITIVE_FIXNUM) {
|
||||
*ep = i-1;
|
||||
return OBJNULL;;
|
||||
}
|
||||
}
|
||||
if (sign < 0) {
|
||||
integer_part = -integer_part;
|
||||
}
|
||||
*ep = i;
|
||||
return (i == start)? OBJNULL : ecl_make_fixnum(integer_part);
|
||||
}
|
||||
|
|
@ -1582,6 +1582,7 @@ extern ECL_API cl_object ecl_read_object(cl_object in);
|
|||
extern ECL_API cl_object ecl_read_token(cl_object rtbl, cl_object in, int flags);
|
||||
extern ECL_API cl_object ecl_parse_token(cl_object token, cl_object in, int flags);
|
||||
extern ECL_API cl_object ecl_parse_number(cl_object s, cl_index start, cl_index end, cl_index *ep, unsigned int radix);
|
||||
extern ECL_API cl_object ecl_parse_fixnum(cl_object s, cl_index start, cl_index end, cl_index *ep, unsigned int radix);
|
||||
extern ECL_API cl_object ecl_parse_integer(cl_object s, cl_index start, cl_index end, cl_index *ep, unsigned int radix);
|
||||
extern ECL_API bool ecl_invalid_character_p(int c);
|
||||
extern ECL_API cl_object ecl_copy_readtable(cl_object from, cl_object to);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue