comparison src/lisp.h @ 3063:d30cd499e445

[xemacs-hg @ 2005-11-13 10:48:01 by ben] further error-checking, etc. alloc.c, lrecord.h: Move around the handling of setting of lheader->uid so it's in set_lheader_implementation() -- that way, even non-MC-ALLOC builds get useful uid's in their bare lrecords. Redo related code for strings so the non-ascii count that is stored in the uid isn't hosed. events.c: Save and restore the uid around event zeroing/deadbeefing. lisp.h: Set the correct value of MAX_STRING_ASCII_BEGIN under MC_ALLOC. lisp.h: rearrange the basic code handling ints and chars. basic int stuff goes first, followed by basic char stuff, followed in turn by stuff that mixes ints and chars. this is required since some basic defn's have become inline functions. XCHAR and CHARP have additional error-checking in that they check to make sure that the value in question is not just a character but a valid character (i.e. its numeric value is valid). print.c: debug_p4 now has a useful UID in all cases and uses it; but it also prints the raw header address (previously, you just got one of them). text.h: some basic char defn's that belonged in lisp.h have been moved there. valid_ichar_p() is moved too since the inline functions need it.
author ben
date Sun, 13 Nov 2005 10:48:04 +0000
parents 1e7cc382eb16
children d9ca850d40de 3742ea8250b5
comparison
equal deleted inserted replaced
3062:21d92abaac3a 3063:d30cd499e445
2312 Ibyte *data_; 2312 Ibyte *data_;
2313 Lisp_Object plist; 2313 Lisp_Object plist;
2314 }; 2314 };
2315 typedef struct Lisp_String Lisp_String; 2315 typedef struct Lisp_String Lisp_String;
2316 2316
2317 #ifdef MC_ALLOC
2318 #define MAX_STRING_ASCII_BEGIN ((1 << 22) - 1)
2319 #else
2317 #define MAX_STRING_ASCII_BEGIN ((1 << 21) - 1) 2320 #define MAX_STRING_ASCII_BEGIN ((1 << 21) - 1)
2321 #endif
2318 2322
2319 DECLARE_MODULE_API_LRECORD (string, Lisp_String); 2323 DECLARE_MODULE_API_LRECORD (string, Lisp_String);
2320 #define XSTRING(x) XRECORD (x, string, Lisp_String) 2324 #define XSTRING(x) XRECORD (x, string, Lisp_String)
2321 #define wrap_string(p) wrap_record (p, string) 2325 #define wrap_string(p) wrap_record (p, string)
2322 #define STRINGP(x) RECORDP (x, string) 2326 #define STRINGP(x) RECORDP (x, string)
2557 /* if (INTP (XMARKER (x)->lheader.next.v)) ABORT (); */ 2561 /* if (INTP (XMARKER (x)->lheader.next.v)) ABORT (); */
2558 2562
2559 #define marker_next(m) ((m)->next) 2563 #define marker_next(m) ((m)->next)
2560 #define marker_prev(m) ((m)->prev) 2564 #define marker_prev(m) ((m)->prev)
2561 2565
2566 /*-------------------basic int (no connection to char)------------------*/
2567
2568 #define ZEROP(x) EQ (x, Qzero)
2569
2570 #ifdef ERROR_CHECK_TYPES
2571
2572 #define XINT(x) XINT_1 (x, __FILE__, __LINE__)
2573
2574 DECLARE_INLINE_HEADER (
2575 EMACS_INT
2576 XINT_1 (Lisp_Object obj, const Ascbyte *file, int line)
2577 )
2578 {
2579 assert_at_line (INTP (obj), file, line);
2580 return XREALINT (obj);
2581 }
2582
2583 #else /* no error checking */
2584
2585 #define XINT(obj) XREALINT (obj)
2586
2587 #endif /* no error checking */
2588
2589 #define CHECK_INT(x) do { \
2590 if (!INTP (x)) \
2591 dead_wrong_type_argument (Qintegerp, x); \
2592 } while (0)
2593
2594 #define CONCHECK_INT(x) do { \
2595 if (!INTP (x)) \
2596 x = wrong_type_argument (Qintegerp, x); \
2597 } while (0)
2598
2599 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0)
2600
2601 #define CHECK_NATNUM(x) do { \
2602 if (!NATNUMP (x)) \
2603 dead_wrong_type_argument (Qnatnump, x); \
2604 } while (0)
2605
2606 #define CONCHECK_NATNUM(x) do { \
2607 if (!NATNUMP (x)) \
2608 x = wrong_type_argument (Qnatnump, x); \
2609 } while (0)
2610
2562 /*------------------------------- char ---------------------------------*/ 2611 /*------------------------------- char ---------------------------------*/
2563 2612
2564 #define CHARP(x) (XTYPE (x) == Lisp_Type_Char) 2613 /* NOTE: There are basic functions for converting between a character and
2614 the string representation of a character in text.h, as well as lots of
2615 other character-related stuff. There are other functions/macros for
2616 working with Ichars in charset.h, for retrieving the charset of an
2617 Ichar, the length of an Ichar when converted to text, etc.
2618 */
2619
2620 #ifdef MULE
2621
2622 MODULE_API int non_ascii_valid_ichar_p (Ichar ch);
2623
2624 /* Return whether the given Ichar is valid.
2625 */
2626
2627 DECLARE_INLINE_HEADER (
2628 int
2629 valid_ichar_p (Ichar ch)
2630 )
2631 {
2632 return (! (ch & ~0xFF)) || non_ascii_valid_ichar_p (ch);
2633 }
2634
2635 #else /* not MULE */
2636
2637 /* This works when CH is negative, and correctly returns non-zero only when CH
2638 is in the range [0, 255], inclusive. */
2639 #define valid_ichar_p(ch) (! (ch & ~0xFF))
2640
2641 #endif /* not MULE */
2565 2642
2566 #ifdef ERROR_CHECK_TYPES 2643 #ifdef ERROR_CHECK_TYPES
2644
2645 DECLARE_INLINE_HEADER (
2646 int
2647 CHARP_1 (Lisp_Object obj, const Ascbyte *file, int line)
2648 )
2649 {
2650 if (XTYPE (obj) != Lisp_Type_Char)
2651 return 0;
2652 assert_at_line (valid_ichar_p (XCHARVAL (obj)), file, line);
2653 return 1;
2654 }
2655
2656 #define CHARP(x) CHARP_1 (x, __FILE__, __LINE__)
2567 2657
2568 DECLARE_INLINE_HEADER ( 2658 DECLARE_INLINE_HEADER (
2569 Ichar 2659 Ichar
2570 XCHAR_1 (Lisp_Object obj, const Ascbyte *file, int line) 2660 XCHAR_1 (Lisp_Object obj, const Ascbyte *file, int line)
2571 ) 2661 )
2572 { 2662 {
2663 Ichar ch;
2573 assert_at_line (CHARP (obj), file, line); 2664 assert_at_line (CHARP (obj), file, line);
2574 return XCHARVAL (obj); 2665 ch = XCHARVAL (obj);
2666 assert_at_line (valid_ichar_p (ch), file, line);
2667 return ch;
2575 } 2668 }
2576 2669
2577 #define XCHAR(x) XCHAR_1 (x, __FILE__, __LINE__) 2670 #define XCHAR(x) XCHAR_1 (x, __FILE__, __LINE__)
2578 2671
2579 #else /* no error checking */ 2672 #else /* not ERROR_CHECK_TYPES */
2580 2673
2674 #define CHARP(x) (XTYPE (x) == Lisp_Type_Char)
2581 #define XCHAR(x) ((Ichar) XCHARVAL (x)) 2675 #define XCHAR(x) ((Ichar) XCHARVAL (x))
2582 2676
2583 #endif /* no error checking */ 2677 #endif /* (else) not ERROR_CHECK_TYPES */
2584 2678
2585 #define CHECK_CHAR(x) CHECK_NONRECORD (x, Lisp_Type_Char, Qcharacterp) 2679 #define CONCHECK_CHAR(x) do { \
2586 #define CONCHECK_CHAR(x) CONCHECK_NONRECORD (x, Lisp_Type_Char, Qcharacterp) 2680 if (!CHARP (x)) \
2587 2681 x = wrong_type_argument (Qcharacterp, x); \
2588 2682 } while (0)
2589 /*------------------------------ float ---------------------------------*/ 2683
2590 2684 #define CHECK_CHAR(x) do { \
2591 /* Note: the 'unused_next_' field exists only to ensure that the 2685 if (!CHARP (x)) \
2592 `next' pointer fits within the structure, for the purposes of the 2686 dead_wrong_type_argument (Qcharacterp, x); \
2593 free list. This makes a difference in the unlikely case of 2687 } while (0)
2594 sizeof(double) being smaller than sizeof(void *). */ 2688
2595 2689
2596 struct Lisp_Float 2690 DECLARE_INLINE_HEADER (
2597 { 2691 Lisp_Object
2598 struct lrecord_header lheader; 2692 make_char (Ichar val)
2599 union { double d; struct Lisp_Float *unused_next_; } data; 2693 )
2600 }; 2694 {
2601 typedef struct Lisp_Float Lisp_Float; 2695 type_checking_assert (valid_ichar_p (val));
2602 2696 /* This is defined in lisp-union.h or lisp-disunion.h */
2603 DECLARE_LRECORD (float, Lisp_Float); 2697 return make_char_1 (val);
2604 #define XFLOAT(x) XRECORD (x, float, Lisp_Float) 2698 }
2605 #define wrap_float(p) wrap_record (p, float) 2699
2606 #define FLOATP(x) RECORDP (x, float) 2700 /*------------------------- int-char connection ------------------------*/
2607 #define CHECK_FLOAT(x) CHECK_RECORD (x, float)
2608 #define CONCHECK_FLOAT(x) CONCHECK_RECORD (x, float)
2609
2610 #define float_data(f) ((f)->data.d)
2611 #define XFLOAT_DATA(x) float_data (XFLOAT (x))
2612
2613 #define XFLOATINT(n) extract_float (n)
2614
2615 #define CHECK_INT_OR_FLOAT(x) do { \
2616 if (!INT_OR_FLOATP (x)) \
2617 dead_wrong_type_argument (Qnumberp, x); \
2618 } while (0)
2619
2620 #define CONCHECK_INT_OR_FLOAT(x) do { \
2621 if (!INT_OR_FLOATP (x)) \
2622 x = wrong_type_argument (Qnumberp, x); \
2623 } while (0)
2624
2625 # define INT_OR_FLOATP(x) (INTP (x) || FLOATP (x))
2626
2627 /*-------------------------------- int ---------------------------------*/
2628
2629 #define ZEROP(x) EQ (x, Qzero)
2630 2701
2631 #ifdef ERROR_CHECK_TYPES 2702 #ifdef ERROR_CHECK_TYPES
2632 2703
2633 #define XCHAR_OR_INT(x) XCHAR_OR_INT_1 (x, __FILE__, __LINE__) 2704 #define XCHAR_OR_INT(x) XCHAR_OR_INT_1 (x, __FILE__, __LINE__)
2634 #define XINT(x) XINT_1 (x, __FILE__, __LINE__)
2635
2636 DECLARE_INLINE_HEADER (
2637 EMACS_INT
2638 XINT_1 (Lisp_Object obj, const Ascbyte *file, int line)
2639 )
2640 {
2641 assert_at_line (INTP (obj), file, line);
2642 return XREALINT (obj);
2643 }
2644 2705
2645 DECLARE_INLINE_HEADER ( 2706 DECLARE_INLINE_HEADER (
2646 EMACS_INT 2707 EMACS_INT
2647 XCHAR_OR_INT_1 (Lisp_Object obj, const Ascbyte *file, int line) 2708 XCHAR_OR_INT_1 (Lisp_Object obj, const Ascbyte *file, int line)
2648 ) 2709 )
2651 return CHARP (obj) ? XCHAR (obj) : XINT (obj); 2712 return CHARP (obj) ? XCHAR (obj) : XINT (obj);
2652 } 2713 }
2653 2714
2654 #else /* no error checking */ 2715 #else /* no error checking */
2655 2716
2656 #define XINT(obj) XREALINT (obj)
2657 #define XCHAR_OR_INT(obj) (CHARP (obj) ? XCHAR (obj) : XINT (obj)) 2717 #define XCHAR_OR_INT(obj) (CHARP (obj) ? XCHAR (obj) : XINT (obj))
2658 2718
2659 #endif /* no error checking */ 2719 #endif /* no error checking */
2660 2720
2661 #define CHECK_INT(x) do { \ 2721 /* True of X is an integer whose value is the valid integral equivalent of a
2662 if (!INTP (x)) \ 2722 character. */
2663 dead_wrong_type_argument (Qintegerp, x); \ 2723
2664 } while (0) 2724 #define CHAR_INTP(x) (INTP (x) && valid_ichar_p (XINT (x)))
2665 2725
2666 #define CONCHECK_INT(x) do { \ 2726 /* True of X is a character or an integral value that can be converted into a
2667 if (!INTP (x)) \ 2727 character. */
2668 x = wrong_type_argument (Qintegerp, x); \ 2728 #define CHAR_OR_CHAR_INTP(x) (CHARP (x) || CHAR_INTP (x))
2669 } while (0) 2729
2670 2730 DECLARE_INLINE_HEADER (
2671 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0) 2731 Ichar
2672 2732 XCHAR_OR_CHAR_INT (Lisp_Object obj)
2673 #define CHECK_NATNUM(x) do { \ 2733 )
2674 if (!NATNUMP (x)) \ 2734 {
2675 dead_wrong_type_argument (Qnatnump, x); \ 2735 return CHARP (obj) ? XCHAR (obj) : XINT (obj);
2676 } while (0) 2736 }
2677 2737
2678 #define CONCHECK_NATNUM(x) do { \ 2738 /* Signal an error if CH is not a valid character or integer Lisp_Object.
2679 if (!NATNUMP (x)) \ 2739 If CH is an integer Lisp_Object, convert it to a character Lisp_Object,
2680 x = wrong_type_argument (Qnatnump, x); \ 2740 but merely by repackaging, without performing tests for char validity.
2741 */
2742
2743 #define CHECK_CHAR_COERCE_INT(x) do { \
2744 if (CHARP (x)) \
2745 ; \
2746 else if (CHAR_INTP (x)) \
2747 x = make_char (XINT (x)); \
2748 else \
2749 x = wrong_type_argument (Qcharacterp, x); \
2681 } while (0) 2750 } while (0)
2682 2751
2683 /* next three always continuable because they coerce their arguments. */ 2752 /* next three always continuable because they coerce their arguments. */
2684 #define CHECK_INT_COERCE_CHAR(x) do { \ 2753 #define CHECK_INT_COERCE_CHAR(x) do { \
2685 if (INTP (x)) \ 2754 if (INTP (x)) \
2708 x = make_int (marker_position (x)); \ 2777 x = make_int (marker_position (x)); \
2709 else \ 2778 else \
2710 x = wrong_type_argument (Qinteger_char_or_marker_p, x); \ 2779 x = wrong_type_argument (Qinteger_char_or_marker_p, x); \
2711 } while (0) 2780 } while (0)
2712 2781
2782 /*------------------------------ float ---------------------------------*/
2783
2784 /* Note: the 'unused_next_' field exists only to ensure that the
2785 `next' pointer fits within the structure, for the purposes of the
2786 free list. This makes a difference in the unlikely case of
2787 sizeof(double) being smaller than sizeof(void *). */
2788
2789 struct Lisp_Float
2790 {
2791 struct lrecord_header lheader;
2792 union { double d; struct Lisp_Float *unused_next_; } data;
2793 };
2794 typedef struct Lisp_Float Lisp_Float;
2795
2796 DECLARE_LRECORD (float, Lisp_Float);
2797 #define XFLOAT(x) XRECORD (x, float, Lisp_Float)
2798 #define wrap_float(p) wrap_record (p, float)
2799 #define FLOATP(x) RECORDP (x, float)
2800 #define CHECK_FLOAT(x) CHECK_RECORD (x, float)
2801 #define CONCHECK_FLOAT(x) CONCHECK_RECORD (x, float)
2802
2803 #define float_data(f) ((f)->data.d)
2804 #define XFLOAT_DATA(x) float_data (XFLOAT (x))
2805
2806 #define XFLOATINT(n) extract_float (n)
2807
2808 #define CHECK_INT_OR_FLOAT(x) do { \
2809 if (!INT_OR_FLOATP (x)) \
2810 dead_wrong_type_argument (Qnumberp, x); \
2811 } while (0)
2812
2813 #define CONCHECK_INT_OR_FLOAT(x) do { \
2814 if (!INT_OR_FLOATP (x)) \
2815 x = wrong_type_argument (Qnumberp, x); \
2816 } while (0)
2817
2818 # define INT_OR_FLOATP(x) (INTP (x) || FLOATP (x))
2713 2819
2714 /*--------------------------- readonly objects -------------------------*/ 2820 /*--------------------------- readonly objects -------------------------*/
2715 2821
2716 #ifndef MC_ALLOC 2822 #ifndef MC_ALLOC
2717 #define CHECK_C_WRITEABLE(obj) \ 2823 #define CHECK_C_WRITEABLE(obj) \