comparison src/print.c @ 5904:ee27ca517e90

Revise print_symbol(), never calling is{float,ratio}_string(). src/ChangeLog addition: 2015-05-08 Aidan Kehoe <kehoea@parhasard.net> * print.c (print_symbol): Revise this. No longer call isfloat_string() and isratio_string() on practically every symbol seen; check explicitly for the known float format in this function, which turns out to be a more limited and cheap job than you would think. Also check for integer and ratio syntax in passing. Use Vdigit_fixnum_map when working out whether a given character is a digit. * lisp.h: Make Vdigit_fixnum_map available generally. tests/ChangeLog addition: 2015-05-08 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-reader-tests.el: Check read and print handling of symbols that look like numbers. In passing, check the read and print handling of the associated numbers.
author Aidan Kehoe <kehoea@parhasard.net>
date Fri, 08 May 2015 14:33:46 +0100
parents acf1c26e3019
children
comparison
equal deleted inserted replaced
5903:5afddd952c46 5904:ee27ca517e90
2561 /* This deals with GC-relocation */ 2561 /* This deals with GC-relocation */
2562 output_string (printcharfun, 0, name, 0, size); 2562 output_string (printcharfun, 0, name, 0, size);
2563 return; 2563 return;
2564 } 2564 }
2565 2565
2566 if (0 == size)
2567 {
2568 /* Compatible with GNU, but not with Common Lisp, where the syntax
2569 for this symbol is ||. */
2570 write_ascstring (printcharfun,
2571 (print_gensym && !IN_OBARRAY (obj)) ? "#:" : "##");
2572 return;
2573 }
2574
2566 GCPRO2 (obj, printcharfun); 2575 GCPRO2 (obj, printcharfun);
2567 2576
2568 if (print_gensym && !IN_OBARRAY (obj)) 2577 if (print_gensym && !IN_OBARRAY (obj))
2569 { 2578 {
2570 write_ascstring (printcharfun, "#:"); 2579 write_ascstring (printcharfun, "#:");
2571 } 2580 }
2572 else if (0 == size) 2581
2573 { 2582 /* Does it look like a rational or a float? */
2574 /* Compatible with GNU, but not with Common Lisp, where the syntax for
2575 this symbol is ||. */
2576 write_ascstring (printcharfun, "##");
2577 }
2578
2579 /* Does it look like an integer or a float? */
2580 { 2583 {
2581 Ibyte *data = XSTRING_DATA (name); 2584 Ibyte *data = XSTRING_DATA (name), *pend = data + XSTRING_LENGTH (name);
2582 Bytecount confusing = 0; 2585 Fixnum nondigits = 0, fixval = -1;
2583 2586 Boolint confusing = 1;
2584 if (size == 0) 2587 Ichar cc = itext_ichar (data);
2585 goto not_yet_confused; /* Really confusing */ 2588 Lisp_Object got = Qnil;
2586 else if (isdigit (data[0])) 2589
2587 confusing = 0; 2590 if (cc == '-' || cc == '+')
2588 else if (size == 1)
2589 goto not_yet_confused;
2590 else if (data[0] == '-' || data[0] == '+')
2591 confusing = 1;
2592 else
2593 goto not_yet_confused;
2594
2595 for (; confusing < size; confusing++)
2596 { 2591 {
2597 if (!isdigit (data[confusing]) && '/' != data[confusing]) 2592 INC_IBYTEPTR (data);
2593 if (data == pend)
2598 { 2594 {
2599 confusing = 0; 2595 confusing = 0;
2596 }
2597 }
2598
2599 /* No need to check for '.' when working out whether the symbol looks like
2600 a number, '.' will get a backslash on printing no matter what,
2601 disqualifying it from being a number when read. */
2602 while (confusing && data < pend)
2603 {
2604 cc = itext_ichar (data);
2605
2606 switch (cc)
2607 {
2608 /* A symbol like 2e10 cound be confused with a float: */
2609 case 'e':
2610 case 'E':
2611 /* As can one like 123/456: */
2612 case '/':
2613 nondigits++;
2614 confusing = nondigits < 2
2615 /* If it starts with an E or a slash, that's fine, it can't be a
2616 float. */
2617 && data != XSTRING_DATA (name)
2618 /* And if it ends with an e or a slash that's fine too. */
2619 && (data + itext_ichar_len (data)) != pend;
2620 break;
2621
2622 /* There can be a sign in the exponent. Such a sign needs to be
2623 directly after an e and to have trailing digits after it to be
2624 valid float syntax. */
2625 case '+':
2626 case '-':
2627 confusing = (1 == nondigits)
2628 && data != XSTRING_DATA (name)
2629 && (data + itext_ichar_len (data));
2630 if (confusing)
2631 {
2632 Ibyte *lastp = data;
2633 Ichar clast;
2634
2635 DEC_IBYTEPTR (lastp);
2636 clast = itext_ichar (lastp);
2637
2638 confusing = clast == 'E' || clast == 'e';
2639 }
2640 break;
2641
2642 /* A symbol that is all decimal digits could be confused with an
2643 integer: */
2644 default:
2645 got = get_char_table (cc, Vdigit_fixnum_map);
2646 fixval = FIXNUMP (got) ? XREALFIXNUM (got) : -1;
2647 if (fixval < 0 || fixval > 9)
2648 {
2649 confusing = 0;
2650 }
2600 break; 2651 break;
2601 } 2652 }
2653
2654 INC_IBYTEPTR (data);
2602 } 2655 }
2603 not_yet_confused: 2656
2604
2605 if (!confusing)
2606 /* #### Ugh, this is needlessly complex and slow for what we
2607 need here. It might be a good idea to copy equivalent code
2608 from FSF. --hniksic */
2609 confusing = isfloat_string ((char *) data)
2610 || isratio_string ((char *) data);
2611 if (confusing) 2657 if (confusing)
2612 write_ascstring (printcharfun, "\\"); 2658 write_ascstring (printcharfun, "\\");
2613 } 2659 }
2614 2660
2615 { 2661 {
2616 Bytecount i; 2662 Bytecount i;
2617 Bytecount last = 0; 2663 Bytecount last = 0;
2618 2664
2619 for (i = 0; i < size; i++) 2665 for (i = 0; i < size; i++)
2620 { 2666 {
2667 /* In the event that we adopt a non-ASCII-compatible internal format,
2668 this will no longer be Mule-safe. As of May 2015, that is very,
2669 very unlikely. */
2621 switch (string_byte (name, i)) 2670 switch (string_byte (name, i))
2622 { 2671 {
2623 case 0: case 1: case 2: case 3: 2672 case 0: case 1: case 2: case 3:
2624 case 4: case 5: case 6: case 7: 2673 case 4: case 5: case 6: case 7:
2625 case 8: case 9: case 10: case 11: 2674 case 8: case 9: case 10: case 11: