[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:
Daniel Kochmański 2026-03-06 10:37:32 +01:00
parent 20a7332473
commit eb6b814a53
4 changed files with 108 additions and 32 deletions

View file

@ -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 \

View file

@ -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
View 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);
}

View file

@ -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);