#include "termhooks.h" /* For FRAME_KBOARD reference in y-or-n-p. */
#include "font.h"
-#ifdef STDC_HEADERS
#include <float.h>
-#endif
-
/* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
#ifndef IEEE_FLOATING_POINT
#if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
Lisp_Object Qwindow;
static Lisp_Object Qfloat, Qwindow_configuration;
static Lisp_Object Qprocess;
-Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector;
+static Lisp_Object Qcompiled_function, Qframe, Qvector;
+Lisp_Object Qbuffer;
static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
static Lisp_Object Qsubrp, Qmany, Qunevalled;
Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
const char *name;
CHECK_SUBR (subr);
name = XSUBR (subr)->symbol_name;
- return make_string (name, strlen (name));
+ return build_string (name);
}
DEFUN ("interactive-form", Finteractive_form, Sinteractive_form, 1, 1, 0,
CHECK_CHARACTER (idx);
CHAR_TABLE_SET (array, idxval, newelt);
}
- else if (STRING_MULTIBYTE (array))
+ else
{
- EMACS_INT idxval_byte, prev_bytes, new_bytes, nbytes;
- unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
+ int c;
if (idxval < 0 || idxval >= SCHARS (array))
args_out_of_range (array, idx);
CHECK_CHARACTER (newelt);
+ c = XFASTINT (newelt);
- nbytes = SBYTES (array);
-
- idxval_byte = string_char_to_byte (array, idxval);
- p1 = SDATA (array) + idxval_byte;
- prev_bytes = BYTES_BY_CHAR_HEAD (*p1);
- new_bytes = CHAR_STRING (XINT (newelt), p0);
- if (prev_bytes != new_bytes)
+ if (STRING_MULTIBYTE (array))
{
- /* We must relocate the string data. */
- EMACS_INT nchars = SCHARS (array);
- unsigned char *str;
- USE_SAFE_ALLOCA;
-
- SAFE_ALLOCA (str, unsigned char *, nbytes);
- memcpy (str, SDATA (array), nbytes);
- allocate_string_data (XSTRING (array), nchars,
- nbytes + new_bytes - prev_bytes);
- memcpy (SDATA (array), str, idxval_byte);
+ EMACS_INT idxval_byte, prev_bytes, new_bytes, nbytes;
+ unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
+
+ nbytes = SBYTES (array);
+ idxval_byte = string_char_to_byte (array, idxval);
p1 = SDATA (array) + idxval_byte;
- memcpy (p1 + new_bytes, str + idxval_byte + prev_bytes,
- nbytes - (idxval_byte + prev_bytes));
- SAFE_FREE ();
- clear_string_char_byte_cache ();
+ prev_bytes = BYTES_BY_CHAR_HEAD (*p1);
+ new_bytes = CHAR_STRING (c, p0);
+ if (prev_bytes != new_bytes)
+ {
+ /* We must relocate the string data. */
+ EMACS_INT nchars = SCHARS (array);
+ unsigned char *str;
+ USE_SAFE_ALLOCA;
+
+ SAFE_ALLOCA (str, unsigned char *, nbytes);
+ memcpy (str, SDATA (array), nbytes);
+ allocate_string_data (XSTRING (array), nchars,
+ nbytes + new_bytes - prev_bytes);
+ memcpy (SDATA (array), str, idxval_byte);
+ p1 = SDATA (array) + idxval_byte;
+ memcpy (p1 + new_bytes, str + idxval_byte + prev_bytes,
+ nbytes - (idxval_byte + prev_bytes));
+ SAFE_FREE ();
+ clear_string_char_byte_cache ();
+ }
+ while (new_bytes--)
+ *p1++ = *p0++;
}
- while (new_bytes--)
- *p1++ = *p0++;
- }
- else
- {
- if (idxval < 0 || idxval >= SCHARS (array))
- args_out_of_range (array, idx);
- CHECK_NUMBER (newelt);
-
- if (XINT (newelt) >= 0 && ! SINGLE_BYTE_CHAR_P (XINT (newelt)))
+ else
{
- int i;
-
- for (i = SBYTES (array) - 1; i >= 0; i--)
- if (SREF (array, i) >= 0x80)
- args_out_of_range (array, newelt);
- /* ARRAY is an ASCII string. Convert it to a multibyte
- string, and try `aset' again. */
- STRING_SET_MULTIBYTE (array);
- return Faset (array, idx, newelt);
+ if (! SINGLE_BYTE_CHAR_P (c))
+ {
+ int i;
+
+ for (i = SBYTES (array) - 1; i >= 0; i--)
+ if (SREF (array, i) >= 0x80)
+ args_out_of_range (array, newelt);
+ /* ARRAY is an ASCII string. Convert it to a multibyte
+ string, and try `aset' again. */
+ STRING_SET_MULTIBYTE (array);
+ return Faset (array, idx, newelt);
+ }
+ SSET (array, idxval, c);
}
- SSET (array, idxval, XINT (newelt));
}
return newelt;
return Qnil;
}
\f
-/* Convert between long values and pairs of Lisp integers.
- Note that long_to_cons returns a single Lisp integer
- when the value fits in one. */
+/* Convert the cons-of-integers, integer, or float value C to an
+ unsigned value with maximum value MAX. Signal an error if C does not
+ have a valid format or is out of range. */
+uintmax_t
+cons_to_unsigned (Lisp_Object c, uintmax_t max)
+{
+ int valid = 0;
+ uintmax_t val IF_LINT (= 0);
+ if (INTEGERP (c))
+ {
+ valid = 0 <= XINT (c);
+ val = XINT (c);
+ }
+ else if (FLOATP (c))
+ {
+ double d = XFLOAT_DATA (c);
+ if (0 <= d
+ && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1))
+ {
+ val = d;
+ valid = 1;
+ }
+ }
+ else if (CONSP (c) && NATNUMP (XCAR (c)))
+ {
+ uintmax_t top = XFASTINT (XCAR (c));
+ Lisp_Object rest = XCDR (c);
+ if (top <= UINTMAX_MAX >> 24 >> 16
+ && CONSP (rest)
+ && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
+ && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
+ {
+ uintmax_t mid = XFASTINT (XCAR (rest));
+ val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
+ valid = 1;
+ }
+ else if (top <= UINTMAX_MAX >> 16)
+ {
+ if (CONSP (rest))
+ rest = XCAR (rest);
+ if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
+ {
+ val = top << 16 | XFASTINT (rest);
+ valid = 1;
+ }
+ }
+ }
-Lisp_Object
-long_to_cons (long unsigned int i)
-{
- unsigned long top = i >> 16;
- unsigned int bot = i & 0xFFFF;
- if (top == 0)
- return make_number (bot);
- if (top == (unsigned long)-1 >> 16)
- return Fcons (make_number (-1), make_number (bot));
- return Fcons (make_number (top), make_number (bot));
+ if (! (valid && val <= max))
+ error ("Not an in-range integer, float, or cons of integers");
+ return val;
}
-unsigned long
-cons_to_long (Lisp_Object c)
+/* Convert the cons-of-integers, integer, or float value C to a signed
+ value with extrema MIN and MAX. Signal an error if C does not have
+ a valid format or is out of range. */
+intmax_t
+cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
{
- Lisp_Object top, bot;
+ int valid = 0;
+ intmax_t val IF_LINT (= 0);
if (INTEGERP (c))
- return XINT (c);
- top = XCAR (c);
- bot = XCDR (c);
- if (CONSP (bot))
- bot = XCAR (bot);
- return ((XINT (top) << 16) | XINT (bot));
+ {
+ val = XINT (c);
+ valid = 1;
+ }
+ else if (FLOATP (c))
+ {
+ double d = XFLOAT_DATA (c);
+ if (min <= d
+ && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1))
+ {
+ val = d;
+ valid = 1;
+ }
+ }
+ else if (CONSP (c) && INTEGERP (XCAR (c)))
+ {
+ intmax_t top = XINT (XCAR (c));
+ Lisp_Object rest = XCDR (c);
+ if (INTMAX_MIN >> 24 >> 16 <= top && top <= INTMAX_MAX >> 24 >> 16
+ && CONSP (rest)
+ && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
+ && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
+ {
+ intmax_t mid = XFASTINT (XCAR (rest));
+ val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
+ valid = 1;
+ }
+ else if (INTMAX_MIN >> 16 <= top && top <= INTMAX_MAX >> 16)
+ {
+ if (CONSP (rest))
+ rest = XCAR (rest);
+ if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
+ {
+ val = top << 16 | XFASTINT (rest);
+ valid = 1;
+ }
+ }
+ }
+
+ if (! (valid && min <= val && val <= max))
+ error ("Not an in-range integer, float, or cons of integers");
+ return val;
}
\f
DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,
Amin
};
-static Lisp_Object float_arith_driver (double, size_t, enum arithop,
- size_t, Lisp_Object *);
+static Lisp_Object float_arith_driver (double, ptrdiff_t, enum arithop,
+ ptrdiff_t, Lisp_Object *);
static Lisp_Object
-arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
+arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
{
register Lisp_Object val;
- register size_t argnum;
+ ptrdiff_t argnum;
register EMACS_INT accum = 0;
register EMACS_INT next;
int overflow = 0;
- size_t ok_args;
+ ptrdiff_t ok_args;
EMACS_INT ok_accum;
switch (SWITCH_ENUM_CAST (code))
#define isnan(x) ((x) != (x))
static Lisp_Object
-float_arith_driver (double accum, register size_t argnum, enum arithop code,
- size_t nargs, register Lisp_Object *args)
+float_arith_driver (double accum, ptrdiff_t argnum, enum arithop code,
+ ptrdiff_t nargs, Lisp_Object *args)
{
register Lisp_Object val;
double next;
DEFUN ("+", Fplus, Splus, 0, MANY, 0,
doc: /* Return sum of any number of arguments, which are numbers or markers.
usage: (+ &rest NUMBERS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Aadd, nargs, args);
}
With one arg, negates it. With more than one arg,
subtracts all but the first from the first.
usage: (- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Asub, nargs, args);
}
DEFUN ("*", Ftimes, Stimes, 0, MANY, 0,
doc: /* Return product of any number of arguments, which are numbers or markers.
usage: (* &rest NUMBERS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Amult, nargs, args);
}
doc: /* Return first argument divided by all the remaining arguments.
The arguments must be numbers or markers.
usage: (/ DIVIDEND DIVISOR &rest DIVISORS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
- size_t argnum;
+ ptrdiff_t argnum;
for (argnum = 2; argnum < nargs; argnum++)
if (FLOATP (args[argnum]))
return float_arith_driver (0, 0, Adiv, nargs, args);
doc: /* Return largest of all the arguments (which must be numbers or markers).
The value is always a number; markers are converted to numbers.
usage: (max NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Amax, nargs, args);
}
doc: /* Return smallest of all the arguments (which must be numbers or markers).
The value is always a number; markers are converted to numbers.
usage: (min NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Amin, nargs, args);
}
doc: /* Return bitwise-and of all the arguments.
Arguments may be integers, or markers converted to integers.
usage: (logand &rest INTS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Alogand, nargs, args);
}
doc: /* Return bitwise-or of all the arguments.
Arguments may be integers, or markers converted to integers.
usage: (logior &rest INTS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Alogior, nargs, args);
}
doc: /* Return bitwise-exclusive-or of all the arguments.
Arguments may be integers, or markers converted to integers.
usage: (logxor &rest INTS-OR-MARKERS) */)
- (size_t nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
return arith_driver (Alogxor, nargs, args);
}