comparison src/lread.c @ 5864:750fab17b299

Make #'parse-integer Lisp-visible, extend it, allowing non-ASCII digits. src/ChangeLog addition: 2015-02-25 Aidan Kehoe <kehoea@parhasard.net> * lread.c (read_atom): Use the new calling convention for parse_integer(). * lisp.h: Change the declaration of parse_integer (). * number.h (bignum_set_emacs_int, make_bignum_emacs_uint): New #defines, used in data.c. * lread.c (read_integer): Ditto. * lread.c (read1): Ditto. * data.c (find_highest_value): New. * data.c (fill_ichar_array): New. * data.c (build_fixnum_to_char_map): New. * data.c (Fset_digit_fixnum_map): New. * data.c (Fdigit_char_p): Moved from cl-extra.el. * data.c (Fdigit_char): Moved from cl-extra.el. * data.c (parse_integer): Moved from lread.c. * data.c (Fparse_integer): Made available to Lisp. * data.c (syms_of_data): Make the new subrs available. * data.c (vars_of_data): Make the new vars available. Expose parse_integer to Lisp, make it follow the Common Lisp API (with some extensions, to allow us to support non ASCII digit characters). lisp/ChangeLog addition: 2015-02-25 Aidan Kehoe <kehoea@parhasard.net> * cl-extra.el (digit-char-p): Moved to data.c. * cl-extra.el (digit-char): Moved to data.c. tests/ChangeLog addition: 2015-02-25 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: parse_integer(), used in #'read, now signals invalid-argument rather than invalid-read-syntax, check for that. * automated/lisp-tests.el: Check #'parse-integer now it's available to Lisp, check #'digit-char, #'digit-char-p and the congruence in behaviour, check the XEmacs-specific RADIX-TABLE argument behaviour.
author Aidan Kehoe <kehoea@parhasard.net>
date Wed, 25 Feb 2015 11:47:12 +0000
parents a216b3c2b09e
children 6174848f3e6c
comparison
equal deleted inserted replaced
5844:83e5c3cd6be6 5864:750fab17b299
1920 Lstream_flush (XLSTREAM (Vread_buffer_stream)); 1920 Lstream_flush (XLSTREAM (Vread_buffer_stream));
1921 1921
1922 return Lstream_byte_count (XLSTREAM (Vread_buffer_stream)) - 1; 1922 return Lstream_byte_count (XLSTREAM (Vread_buffer_stream)) - 1;
1923 } 1923 }
1924 1924
1925 static Lisp_Object parse_integer (const Ibyte *buf, Bytecount len, int base);
1926
1927 static Lisp_Object 1925 static Lisp_Object
1928 read_atom (Lisp_Object readcharfun, 1926 read_atom (Lisp_Object readcharfun,
1929 Ichar firstchar, 1927 Ichar firstchar,
1930 int uninterned_symbol) 1928 int uninterned_symbol)
1931 { 1929 {
1956 /* Integers can have trailing decimal points. */ 1954 /* Integers can have trailing decimal points. */
1957 if (p1 > read_ptr && p1 < p && *p1 == '.') 1955 if (p1 > read_ptr && p1 < p && *p1 == '.')
1958 p1++; 1956 p1++;
1959 if (p1 == p) 1957 if (p1 == p)
1960 { 1958 {
1959 Ibyte *buf_end;
1961 /* It is an integer. */ 1960 /* It is an integer. */
1962 if (p1[-1] == '.') 1961 if (p1[-1] == '.')
1963 p1[-1] = '\0'; 1962 {
1964 #if 0 1963 len -= 1;
1965 { 1964 }
1966 int number = 0; 1965
1967 if (sizeof (int) == sizeof (EMACS_INT)) 1966 return parse_integer ((Ibyte *) read_ptr, &buf_end, len, 10,
1968 number = atoi (read_buffer); 1967 0, Qnil);
1969 else if (sizeof (long) == sizeof (EMACS_INT))
1970 number = atol (read_buffer);
1971 else
1972 ABORT ();
1973 return make_fixnum (number);
1974 }
1975 #else
1976 return parse_integer ((Ibyte *) read_ptr, len, 10);
1977 #endif
1978 } 1968 }
1979 } 1969 }
1980 #ifdef HAVE_RATIO 1970 #ifdef HAVE_RATIO
1981 if (isratio_string (read_ptr)) 1971 if (isratio_string (read_ptr))
1982 { 1972 {
2009 } 1999 }
2010 return sym; 2000 return sym;
2011 } 2001 }
2012 } 2002 }
2013 2003
2014
2015 static Lisp_Object
2016 parse_integer (const Ibyte *buf, Bytecount len, int base)
2017 {
2018 const Ibyte *lim = buf + len;
2019 const Ibyte *p = buf;
2020 EMACS_UINT num = 0;
2021 int negativland = 0;
2022
2023 if (*p == '-')
2024 {
2025 negativland = 1;
2026 p++;
2027 }
2028 else if (*p == '+')
2029 {
2030 p++;
2031 /* GMP deals with a leading plus sign, badly, make sure it doesn't see
2032 it. */
2033 buf++;
2034 }
2035
2036 if (p == lim)
2037 goto loser;
2038
2039 for (; (p < lim) && (*p != '\0'); p++)
2040 {
2041 int c = *p;
2042 EMACS_UINT onum;
2043
2044 if (isdigit (c))
2045 c = c - '0';
2046 else if (isupper (c))
2047 c = c - 'A' + 10;
2048 else if (islower (c))
2049 c = c - 'a' + 10;
2050 else
2051 goto loser;
2052
2053 if (c < 0 || c >= base)
2054 goto loser;
2055
2056 onum = num;
2057 num = num * base + c;
2058 if (num < onum)
2059 goto overflow;
2060 }
2061
2062 {
2063 EMACS_INT int_result = negativland ? - (EMACS_INT) num : (EMACS_INT) num;
2064 Lisp_Object result = make_fixnum (int_result);
2065 if (num && ((XFIXNUM (result) < 0) != negativland))
2066 goto overflow;
2067 if (XFIXNUM (result) != int_result)
2068 goto overflow;
2069 return result;
2070 }
2071 overflow:
2072 #ifdef HAVE_BIGNUM
2073 {
2074 bignum_set_string (scratch_bignum, (const char *) buf, base);
2075 return make_bignum_bg (scratch_bignum);
2076 }
2077 #else
2078 return Fsignal (Qinvalid_read_syntax,
2079 list3 (build_msg_string
2080 ("Integer constant overflow in reader"),
2081 make_string (buf, len),
2082 make_fixnum (base)));
2083 #endif /* HAVE_BIGNUM */
2084 loser:
2085 return Fsignal (Qinvalid_read_syntax,
2086 list3 (build_msg_string
2087 ("Invalid integer constant in reader"),
2088 make_string (buf, len),
2089 make_fixnum (base)));
2090 }
2091
2092
2093 static Lisp_Object 2004 static Lisp_Object
2094 read_integer (Lisp_Object readcharfun, int base) 2005 read_integer (Lisp_Object readcharfun, int base)
2095 { 2006 {
2096 /* This function can GC */ 2007 /* This function can GC */
2097 int saw_a_backslash; 2008 int saw_a_backslash;
2009 Ibyte *buf_end;
2098 Bytecount len = read_atom_0 (readcharfun, -1, &saw_a_backslash); 2010 Bytecount len = read_atom_0 (readcharfun, -1, &saw_a_backslash);
2099 return (parse_integer 2011 return (parse_integer
2100 (resizing_buffer_stream_ptr (XLSTREAM (Vread_buffer_stream)), 2012 (resizing_buffer_stream_ptr (XLSTREAM (Vread_buffer_stream)),
2101 ((saw_a_backslash) 2013 &buf_end, len, base, 0, Qnil));
2102 ? 0 /* make parse_integer signal error */
2103 : len),
2104 base));
2105 } 2014 }
2106 2015
2107 static Lisp_Object 2016 static Lisp_Object
2108 read_bit_vector (Lisp_Object readcharfun) 2017 read_bit_vector (Lisp_Object readcharfun)
2109 { 2018 {
2698 case '0': case '1': case '2': case '3': case '4': 2607 case '0': case '1': case '2': case '3': case '4':
2699 case '5': case '6': case '7': case '8': case '9': 2608 case '5': case '6': case '7': case '8': case '9':
2700 /* Reader forms that can reuse previously read objects. */ 2609 /* Reader forms that can reuse previously read objects. */
2701 { 2610 {
2702 Lisp_Object parsed, found; 2611 Lisp_Object parsed, found;
2612 Ibyte *buf_end;
2703 2613
2704 Lstream_rewind (XLSTREAM (Vread_buffer_stream)); 2614 Lstream_rewind (XLSTREAM (Vread_buffer_stream));
2705 2615
2706 /* Using read_integer() here is impossible, because it 2616 /* Using read_integer() here is impossible, because it
2707 chokes on `='. */ 2617 chokes on `='. */
2716 Lstream_put_ichar (XLSTREAM (Vread_buffer_stream), 0); 2626 Lstream_put_ichar (XLSTREAM (Vread_buffer_stream), 0);
2717 Lstream_flush (XLSTREAM (Vread_buffer_stream)); 2627 Lstream_flush (XLSTREAM (Vread_buffer_stream));
2718 2628
2719 parsed 2629 parsed
2720 = parse_integer (resizing_buffer_stream_ptr 2630 = parse_integer (resizing_buffer_stream_ptr
2721 (XLSTREAM (Vread_buffer_stream)), 2631 (XLSTREAM (Vread_buffer_stream)), &buf_end,
2722 Lstream_byte_count (XLSTREAM 2632 Lstream_byte_count (XLSTREAM
2723 (Vread_buffer_stream)) 2633 (Vread_buffer_stream))
2724 - 1, 10); 2634 - 1, 10, 0, Qnil);
2725 2635
2726 found = assoc_no_quit (parsed, Vread_objects); 2636 found = assoc_no_quit (parsed, Vread_objects);
2727 if (c == '=') 2637 if (c == '=')
2728 { 2638 {
2729 /* #n=object returns object, but associates it with 2639 /* #n=object returns object, but associates it with