diff options
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 1225 |
1 files changed, 697 insertions, 528 deletions
diff --git a/src/data.c b/src/data.c index bdba3a9bb36..a56b112196d 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -91,7 +91,7 @@ Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; | |||
| 91 | 91 | ||
| 92 | Lisp_Object Qinteractive_form; | 92 | Lisp_Object Qinteractive_form; |
| 93 | 93 | ||
| 94 | static Lisp_Object swap_in_symval_forwarding P_ ((Lisp_Object, Lisp_Object)); | 94 | static void swap_in_symval_forwarding (struct Lisp_Symbol *, struct Lisp_Buffer_Local_Value *); |
| 95 | 95 | ||
| 96 | Lisp_Object Vmost_positive_fixnum, Vmost_negative_fixnum; | 96 | Lisp_Object Vmost_positive_fixnum, Vmost_negative_fixnum; |
| 97 | 97 | ||
| @@ -582,12 +582,35 @@ DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0, | |||
| 582 | register Lisp_Object symbol; | 582 | register Lisp_Object symbol; |
| 583 | { | 583 | { |
| 584 | Lisp_Object valcontents; | 584 | Lisp_Object valcontents; |
| 585 | struct Lisp_Symbol *sym; | ||
| 585 | CHECK_SYMBOL (symbol); | 586 | CHECK_SYMBOL (symbol); |
| 587 | sym = XSYMBOL (symbol); | ||
| 586 | 588 | ||
| 587 | valcontents = SYMBOL_VALUE (symbol); | 589 | start: |
| 588 | 590 | switch (sym->redirect) | |
| 589 | if (BUFFER_LOCAL_VALUEP (valcontents)) | 591 | { |
| 590 | valcontents = swap_in_symval_forwarding (symbol, valcontents); | 592 | case SYMBOL_PLAINVAL: valcontents = SYMBOL_VAL (sym); break; |
| 593 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; | ||
| 594 | case SYMBOL_LOCALIZED: | ||
| 595 | { | ||
| 596 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 597 | if (blv->fwd) | ||
| 598 | /* In set_internal, we un-forward vars when their value is | ||
| 599 | set to Qunbound. */ | ||
| 600 | return Qt; | ||
| 601 | else | ||
| 602 | { | ||
| 603 | swap_in_symval_forwarding (sym, blv); | ||
| 604 | valcontents = BLV_VALUE (blv); | ||
| 605 | } | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | case SYMBOL_FORWARDED: | ||
| 609 | /* In set_internal, we un-forward vars when their value is | ||
| 610 | set to Qunbound. */ | ||
| 611 | return Qt; | ||
| 612 | default: abort (); | ||
| 613 | } | ||
| 591 | 614 | ||
| 592 | return (EQ (valcontents, Qunbound) ? Qnil : Qt); | 615 | return (EQ (valcontents, Qunbound) ? Qnil : Qt); |
| 593 | } | 616 | } |
| @@ -824,14 +847,14 @@ indirect_variable (symbol) | |||
| 824 | 847 | ||
| 825 | hare = tortoise = symbol; | 848 | hare = tortoise = symbol; |
| 826 | 849 | ||
| 827 | while (hare->indirect_variable) | 850 | while (hare->redirect == SYMBOL_VARALIAS) |
| 828 | { | 851 | { |
| 829 | hare = XSYMBOL (hare->value); | 852 | hare = SYMBOL_ALIAS (hare); |
| 830 | if (!hare->indirect_variable) | 853 | if (hare->redirect != SYMBOL_VARALIAS) |
| 831 | break; | 854 | break; |
| 832 | 855 | ||
| 833 | hare = XSYMBOL (hare->value); | 856 | hare = SYMBOL_ALIAS (hare); |
| 834 | tortoise = XSYMBOL (tortoise->value); | 857 | tortoise = SYMBOL_ALIAS (tortoise); |
| 835 | 858 | ||
| 836 | if (hare == tortoise) | 859 | if (hare == tortoise) |
| 837 | { | 860 | { |
| @@ -865,44 +888,46 @@ variable chain of symbols. */) | |||
| 865 | This does not handle buffer-local variables; use | 888 | This does not handle buffer-local variables; use |
| 866 | swap_in_symval_forwarding for that. */ | 889 | swap_in_symval_forwarding for that. */ |
| 867 | 890 | ||
| 891 | #define do_blv_forwarding(blv) \ | ||
| 892 | ((blv)->forwarded ? do_symval_forwarding (BLV_FWD (blv)) : BLV_VALUE (blv)) | ||
| 893 | |||
| 868 | Lisp_Object | 894 | Lisp_Object |
| 869 | do_symval_forwarding (valcontents) | 895 | do_symval_forwarding (valcontents) |
| 870 | register Lisp_Object valcontents; | 896 | register union Lisp_Fwd *valcontents; |
| 871 | { | 897 | { |
| 872 | register Lisp_Object val; | 898 | register Lisp_Object val; |
| 873 | if (MISCP (valcontents)) | 899 | switch (XFWDTYPE (valcontents)) |
| 874 | switch (XMISCTYPE (valcontents)) | 900 | { |
| 875 | { | 901 | case Lisp_Fwd_Int: |
| 876 | case Lisp_Misc_Intfwd: | 902 | XSETINT (val, *XINTFWD (valcontents)->intvar); |
| 877 | XSETINT (val, *XINTFWD (valcontents)->intvar); | 903 | return val; |
| 878 | return val; | 904 | |
| 879 | 905 | case Lisp_Fwd_Bool: | |
| 880 | case Lisp_Misc_Boolfwd: | 906 | return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil); |
| 881 | return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil); | 907 | |
| 882 | 908 | case Lisp_Fwd_Obj: | |
| 883 | case Lisp_Misc_Objfwd: | 909 | return *XOBJFWD (valcontents)->objvar; |
| 884 | return *XOBJFWD (valcontents)->objvar; | 910 | |
| 885 | 911 | case Lisp_Fwd_Buffer_Obj: | |
| 886 | case Lisp_Misc_Buffer_Objfwd: | 912 | return PER_BUFFER_VALUE (current_buffer, |
| 887 | return PER_BUFFER_VALUE (current_buffer, | 913 | XBUFFER_OBJFWD (valcontents)->offset); |
| 888 | XBUFFER_OBJFWD (valcontents)->offset); | 914 | |
| 889 | 915 | case Lisp_Fwd_Kboard_Obj: | |
| 890 | case Lisp_Misc_Kboard_Objfwd: | 916 | /* We used to simply use current_kboard here, but from Lisp |
| 891 | /* We used to simply use current_kboard here, but from Lisp | 917 | code, it's value is often unexpected. It seems nicer to |
| 892 | code, it's value is often unexpected. It seems nicer to | 918 | allow constructions like this to work as intuitively expected: |
| 893 | allow constructions like this to work as intuitively expected: | 919 | |
| 894 | 920 | (with-selected-frame frame | |
| 895 | (with-selected-frame frame | 921 | (define-key local-function-map "\eOP" [f1])) |
| 896 | (define-key local-function-map "\eOP" [f1])) | 922 | |
| 897 | 923 | On the other hand, this affects the semantics of | |
| 898 | On the other hand, this affects the semantics of | 924 | last-command and real-last-command, and people may rely on |
| 899 | last-command and real-last-command, and people may rely on | 925 | that. I took a quick look at the Lisp codebase, and I |
| 900 | that. I took a quick look at the Lisp codebase, and I | 926 | don't think anything will break. --lorentey */ |
| 901 | don't think anything will break. --lorentey */ | 927 | return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset |
| 902 | return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset | 928 | + (char *)FRAME_KBOARD (SELECTED_FRAME ())); |
| 903 | + (char *)FRAME_KBOARD (SELECTED_FRAME ())); | 929 | default: abort (); |
| 904 | } | 930 | } |
| 905 | return valcontents; | ||
| 906 | } | 931 | } |
| 907 | 932 | ||
| 908 | /* Store NEWVAL into SYMBOL, where VALCONTENTS is found in the value cell | 933 | /* Store NEWVAL into SYMBOL, where VALCONTENTS is found in the value cell |
| @@ -913,102 +938,93 @@ do_symval_forwarding (valcontents) | |||
| 913 | BUF non-zero means set the value in buffer BUF instead of the | 938 | BUF non-zero means set the value in buffer BUF instead of the |
| 914 | current buffer. This only plays a role for per-buffer variables. */ | 939 | current buffer. This only plays a role for per-buffer variables. */ |
| 915 | 940 | ||
| 916 | void | 941 | #define store_blv_forwarding(blv, newval, buf) \ |
| 917 | store_symval_forwarding (symbol, valcontents, newval, buf) | 942 | do { \ |
| 918 | Lisp_Object symbol; | 943 | if ((blv)->forwarded) \ |
| 919 | register Lisp_Object valcontents, newval; | 944 | store_symval_forwarding (BLV_FWD (blv), (newval), (buf)); \ |
| 945 | else \ | ||
| 946 | SET_BLV_VALUE (blv, newval); \ | ||
| 947 | } while (0) | ||
| 948 | |||
| 949 | static void | ||
| 950 | store_symval_forwarding (/* symbol, */ valcontents, newval, buf) | ||
| 951 | /* struct Lisp_Symbol *symbol; */ | ||
| 952 | union Lisp_Fwd *valcontents; | ||
| 953 | register Lisp_Object newval; | ||
| 920 | struct buffer *buf; | 954 | struct buffer *buf; |
| 921 | { | 955 | { |
| 922 | switch (SWITCH_ENUM_CAST (XTYPE (valcontents))) | 956 | switch (XFWDTYPE (valcontents)) |
| 923 | { | 957 | { |
| 924 | case Lisp_Misc: | 958 | case Lisp_Fwd_Int: |
| 925 | switch (XMISCTYPE (valcontents)) | 959 | CHECK_NUMBER (newval); |
| 960 | *XINTFWD (valcontents)->intvar = XINT (newval); | ||
| 961 | break; | ||
| 962 | |||
| 963 | case Lisp_Fwd_Bool: | ||
| 964 | *XBOOLFWD (valcontents)->boolvar = !NILP (newval); | ||
| 965 | break; | ||
| 966 | |||
| 967 | case Lisp_Fwd_Obj: | ||
| 968 | *XOBJFWD (valcontents)->objvar = newval; | ||
| 969 | |||
| 970 | /* If this variable is a default for something stored | ||
| 971 | in the buffer itself, such as default-fill-column, | ||
| 972 | find the buffers that don't have local values for it | ||
| 973 | and update them. */ | ||
| 974 | if (XOBJFWD (valcontents)->objvar > (Lisp_Object *) &buffer_defaults | ||
| 975 | && XOBJFWD (valcontents)->objvar < (Lisp_Object *) (&buffer_defaults + 1)) | ||
| 926 | { | 976 | { |
| 927 | case Lisp_Misc_Intfwd: | 977 | int offset = ((char *) XOBJFWD (valcontents)->objvar |
| 928 | CHECK_NUMBER (newval); | 978 | - (char *) &buffer_defaults); |
| 929 | *XINTFWD (valcontents)->intvar = XINT (newval); | 979 | int idx = PER_BUFFER_IDX (offset); |
| 930 | /* This can never happen since intvar points to an EMACS_INT | 980 | |
| 931 | which is at least large enough to hold a Lisp_Object. | 981 | Lisp_Object tail; |
| 932 | if (*XINTFWD (valcontents)->intvar != XINT (newval)) | 982 | |
| 933 | error ("Value out of range for variable `%s'", | 983 | if (idx <= 0) |
| 934 | SDATA (SYMBOL_NAME (symbol))); */ | 984 | break; |
| 935 | break; | 985 | |
| 936 | 986 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) | |
| 937 | case Lisp_Misc_Boolfwd: | ||
| 938 | *XBOOLFWD (valcontents)->boolvar = !NILP (newval); | ||
| 939 | break; | ||
| 940 | |||
| 941 | case Lisp_Misc_Objfwd: | ||
| 942 | *XOBJFWD (valcontents)->objvar = newval; | ||
| 943 | |||
| 944 | /* If this variable is a default for something stored | ||
| 945 | in the buffer itself, such as default-fill-column, | ||
| 946 | find the buffers that don't have local values for it | ||
| 947 | and update them. */ | ||
| 948 | if (XOBJFWD (valcontents)->objvar > (Lisp_Object *) &buffer_defaults | ||
| 949 | && XOBJFWD (valcontents)->objvar < (Lisp_Object *) (&buffer_defaults + 1)) | ||
| 950 | { | 987 | { |
| 951 | int offset = ((char *) XOBJFWD (valcontents)->objvar | 988 | Lisp_Object buf; |
| 952 | - (char *) &buffer_defaults); | 989 | struct buffer *b; |
| 953 | int idx = PER_BUFFER_IDX (offset); | ||
| 954 | 990 | ||
| 955 | Lisp_Object tail; | 991 | buf = Fcdr (XCAR (tail)); |
| 992 | if (!BUFFERP (buf)) continue; | ||
| 993 | b = XBUFFER (buf); | ||
| 956 | 994 | ||
| 957 | if (idx <= 0) | 995 | if (! PER_BUFFER_VALUE_P (b, idx)) |
| 958 | break; | 996 | PER_BUFFER_VALUE (b, offset) = newval; |
| 959 | |||
| 960 | for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 961 | { | ||
| 962 | Lisp_Object buf; | ||
| 963 | struct buffer *b; | ||
| 964 | |||
| 965 | buf = Fcdr (XCAR (tail)); | ||
| 966 | if (!BUFFERP (buf)) continue; | ||
| 967 | b = XBUFFER (buf); | ||
| 968 | |||
| 969 | if (! PER_BUFFER_VALUE_P (b, idx)) | ||
| 970 | PER_BUFFER_VALUE (b, offset) = newval; | ||
| 971 | } | ||
| 972 | } | 997 | } |
| 973 | break; | 998 | } |
| 974 | 999 | break; | |
| 975 | case Lisp_Misc_Buffer_Objfwd: | ||
| 976 | { | ||
| 977 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | ||
| 978 | Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype; | ||
| 979 | |||
| 980 | if (!(NILP (type) || NILP (newval) | ||
| 981 | || (XINT (type) == LISP_INT_TAG | ||
| 982 | ? INTEGERP (newval) | ||
| 983 | : XTYPE (newval) == XINT (type)))) | ||
| 984 | buffer_slot_type_mismatch (newval, XINT (type)); | ||
| 985 | |||
| 986 | if (buf == NULL) | ||
| 987 | buf = current_buffer; | ||
| 988 | PER_BUFFER_VALUE (buf, offset) = newval; | ||
| 989 | } | ||
| 990 | break; | ||
| 991 | 1000 | ||
| 992 | case Lisp_Misc_Kboard_Objfwd: | 1001 | case Lisp_Fwd_Buffer_Obj: |
| 993 | { | 1002 | { |
| 994 | char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ()); | 1003 | int offset = XBUFFER_OBJFWD (valcontents)->offset; |
| 995 | char *p = base + XKBOARD_OBJFWD (valcontents)->offset; | 1004 | Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype; |
| 996 | *(Lisp_Object *) p = newval; | 1005 | |
| 997 | } | 1006 | if (!(NILP (type) || NILP (newval) |
| 998 | break; | 1007 | || (XINT (type) == LISP_INT_TAG |
| 1008 | ? INTEGERP (newval) | ||
| 1009 | : XTYPE (newval) == XINT (type)))) | ||
| 1010 | buffer_slot_type_mismatch (newval, XINT (type)); | ||
| 1011 | |||
| 1012 | if (buf == NULL) | ||
| 1013 | buf = current_buffer; | ||
| 1014 | PER_BUFFER_VALUE (buf, offset) = newval; | ||
| 1015 | } | ||
| 1016 | break; | ||
| 999 | 1017 | ||
| 1000 | default: | 1018 | case Lisp_Fwd_Kboard_Obj: |
| 1001 | goto def; | 1019 | { |
| 1002 | } | 1020 | char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ()); |
| 1021 | char *p = base + XKBOARD_OBJFWD (valcontents)->offset; | ||
| 1022 | *(Lisp_Object *) p = newval; | ||
| 1023 | } | ||
| 1003 | break; | 1024 | break; |
| 1004 | 1025 | ||
| 1005 | default: | 1026 | default: |
| 1006 | def: | 1027 | abort (); /* goto def; */ |
| 1007 | valcontents = SYMBOL_VALUE (symbol); | ||
| 1008 | if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1009 | XBUFFER_LOCAL_VALUE (valcontents)->realvalue = newval; | ||
| 1010 | else | ||
| 1011 | SET_SYMBOL_VALUE (symbol, newval); | ||
| 1012 | } | 1028 | } |
| 1013 | } | 1029 | } |
| 1014 | 1030 | ||
| @@ -1017,25 +1033,22 @@ store_symval_forwarding (symbol, valcontents, newval, buf) | |||
| 1017 | 1033 | ||
| 1018 | void | 1034 | void |
| 1019 | swap_in_global_binding (symbol) | 1035 | swap_in_global_binding (symbol) |
| 1020 | Lisp_Object symbol; | 1036 | struct Lisp_Symbol *symbol; |
| 1021 | { | 1037 | { |
| 1022 | Lisp_Object valcontents = SYMBOL_VALUE (symbol); | 1038 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (symbol); |
| 1023 | struct Lisp_Buffer_Local_Value *blv = XBUFFER_LOCAL_VALUE (valcontents); | ||
| 1024 | Lisp_Object cdr = blv->cdr; | ||
| 1025 | 1039 | ||
| 1026 | /* Unload the previously loaded binding. */ | 1040 | /* Unload the previously loaded binding. */ |
| 1027 | Fsetcdr (XCAR (cdr), | 1041 | if (blv->fwd) |
| 1028 | do_symval_forwarding (blv->realvalue)); | 1042 | SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd)); |
| 1029 | 1043 | ||
| 1030 | /* Select the global binding in the symbol. */ | 1044 | /* Select the global binding in the symbol. */ |
| 1031 | XSETCAR (cdr, cdr); | 1045 | blv->valcell = blv->defcell; |
| 1032 | store_symval_forwarding (symbol, blv->realvalue, XCDR (cdr), NULL); | 1046 | if (blv->fwd) |
| 1047 | store_symval_forwarding (blv->fwd, XCDR (blv->defcell), NULL); | ||
| 1033 | 1048 | ||
| 1034 | /* Indicate that the global binding is set up now. */ | 1049 | /* Indicate that the global binding is set up now. */ |
| 1035 | blv->frame = Qnil; | 1050 | blv->where = Qnil; |
| 1036 | blv->buffer = Qnil; | 1051 | SET_BLV_FOUND (blv, 0); |
| 1037 | blv->found_for_frame = 0; | ||
| 1038 | blv->found_for_buffer = 0; | ||
| 1039 | } | 1052 | } |
| 1040 | 1053 | ||
| 1041 | /* Set up the buffer-local symbol SYMBOL for validity in the current buffer. | 1054 | /* Set up the buffer-local symbol SYMBOL for validity in the current buffer. |
| @@ -1045,55 +1058,50 @@ swap_in_global_binding (symbol) | |||
| 1045 | Return the value forwarded one step past the buffer-local stage. | 1058 | Return the value forwarded one step past the buffer-local stage. |
| 1046 | This could be another forwarding pointer. */ | 1059 | This could be another forwarding pointer. */ |
| 1047 | 1060 | ||
| 1048 | static Lisp_Object | 1061 | static void |
| 1049 | swap_in_symval_forwarding (symbol, valcontents) | 1062 | swap_in_symval_forwarding (symbol, blv) |
| 1050 | Lisp_Object symbol, valcontents; | 1063 | struct Lisp_Symbol *symbol; |
| 1064 | struct Lisp_Buffer_Local_Value *blv; | ||
| 1051 | { | 1065 | { |
| 1052 | register Lisp_Object tem1; | 1066 | register Lisp_Object tem1; |
| 1053 | 1067 | ||
| 1054 | tem1 = XBUFFER_LOCAL_VALUE (valcontents)->buffer; | 1068 | eassert (blv == SYMBOL_BLV (symbol)); |
| 1069 | |||
| 1070 | tem1 = blv->where; | ||
| 1055 | 1071 | ||
| 1056 | if (NILP (tem1) | 1072 | if (NILP (tem1) |
| 1057 | || current_buffer != XBUFFER (tem1) | 1073 | || (blv->frame_local |
| 1058 | || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame | 1074 | ? !EQ (selected_frame, tem1) |
| 1059 | && ! EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame))) | 1075 | : current_buffer != XBUFFER (tem1))) |
| 1060 | { | 1076 | { |
| 1061 | struct Lisp_Symbol *sym = XSYMBOL (symbol); | ||
| 1062 | if (sym->indirect_variable) | ||
| 1063 | { | ||
| 1064 | sym = indirect_variable (sym); | ||
| 1065 | XSETSYMBOL (symbol, sym); | ||
| 1066 | } | ||
| 1067 | 1077 | ||
| 1068 | /* Unload the previously loaded binding. */ | 1078 | /* Unload the previously loaded binding. */ |
| 1069 | tem1 = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); | 1079 | tem1 = blv->valcell; |
| 1070 | Fsetcdr (tem1, | 1080 | if (blv->fwd) |
| 1071 | do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue)); | 1081 | SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd)); |
| 1072 | /* Choose the new binding. */ | 1082 | /* Choose the new binding. */ |
| 1073 | tem1 = assq_no_quit (symbol, current_buffer->local_var_alist); | 1083 | { |
| 1074 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0; | 1084 | Lisp_Object var; |
| 1075 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0; | 1085 | XSETSYMBOL (var, symbol); |
| 1076 | if (NILP (tem1)) | 1086 | if (blv->frame_local) |
| 1077 | { | 1087 | { |
| 1078 | if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame) | 1088 | tem1 = assq_no_quit (var, XFRAME (selected_frame)->param_alist); |
| 1079 | tem1 = assq_no_quit (symbol, XFRAME (selected_frame)->param_alist); | 1089 | blv->where = selected_frame; |
| 1080 | if (! NILP (tem1)) | 1090 | } |
| 1081 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 1; | 1091 | else |
| 1082 | else | 1092 | { |
| 1083 | tem1 = XBUFFER_LOCAL_VALUE (valcontents)->cdr; | 1093 | tem1 = assq_no_quit (var, current_buffer->local_var_alist); |
| 1084 | } | 1094 | XSETBUFFER (blv->where, current_buffer); |
| 1085 | else | 1095 | } |
| 1086 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1; | 1096 | } |
| 1097 | if (!(blv->found = !NILP (tem1))) | ||
| 1098 | tem1 = blv->defcell; | ||
| 1087 | 1099 | ||
| 1088 | /* Load the new binding. */ | 1100 | /* Load the new binding. */ |
| 1089 | XSETCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, tem1); | 1101 | blv->valcell = tem1; |
| 1090 | XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, current_buffer); | 1102 | if (blv->fwd) |
| 1091 | XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame; | 1103 | store_symval_forwarding (blv->fwd, BLV_VALUE (blv), NULL); |
| 1092 | store_symval_forwarding (symbol, | ||
| 1093 | XBUFFER_LOCAL_VALUE (valcontents)->realvalue, | ||
| 1094 | Fcdr (tem1), NULL); | ||
| 1095 | } | 1104 | } |
| 1096 | return XBUFFER_LOCAL_VALUE (valcontents)->realvalue; | ||
| 1097 | } | 1105 | } |
| 1098 | 1106 | ||
| 1099 | /* Find the value of a symbol, returning Qunbound if it's not bound. | 1107 | /* Find the value of a symbol, returning Qunbound if it's not bound. |
| @@ -1106,16 +1114,27 @@ Lisp_Object | |||
| 1106 | find_symbol_value (symbol) | 1114 | find_symbol_value (symbol) |
| 1107 | Lisp_Object symbol; | 1115 | Lisp_Object symbol; |
| 1108 | { | 1116 | { |
| 1109 | register Lisp_Object valcontents; | 1117 | struct Lisp_Symbol *sym; |
| 1110 | register Lisp_Object val; | ||
| 1111 | 1118 | ||
| 1112 | CHECK_SYMBOL (symbol); | 1119 | CHECK_SYMBOL (symbol); |
| 1113 | valcontents = SYMBOL_VALUE (symbol); | 1120 | sym = XSYMBOL (symbol); |
| 1114 | |||
| 1115 | if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1116 | valcontents = swap_in_symval_forwarding (symbol, valcontents); | ||
| 1117 | 1121 | ||
| 1118 | return do_symval_forwarding (valcontents); | 1122 | start: |
| 1123 | switch (sym->redirect) | ||
| 1124 | { | ||
| 1125 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; | ||
| 1126 | case SYMBOL_PLAINVAL: return SYMBOL_VAL (sym); | ||
| 1127 | case SYMBOL_LOCALIZED: | ||
| 1128 | { | ||
| 1129 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 1130 | swap_in_symval_forwarding (sym, blv); | ||
| 1131 | return blv->fwd ? do_symval_forwarding (blv->fwd) : BLV_VALUE (blv); | ||
| 1132 | } | ||
| 1133 | /* FALLTHROUGH */ | ||
| 1134 | case SYMBOL_FORWARDED: | ||
| 1135 | return do_symval_forwarding (SYMBOL_FWD (sym)); | ||
| 1136 | default: abort (); | ||
| 1137 | } | ||
| 1119 | } | 1138 | } |
| 1120 | 1139 | ||
| 1121 | DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0, | 1140 | DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0, |
| @@ -1137,26 +1156,25 @@ DEFUN ("set", Fset, Sset, 2, 2, 0, | |||
| 1137 | (symbol, newval) | 1156 | (symbol, newval) |
| 1138 | register Lisp_Object symbol, newval; | 1157 | register Lisp_Object symbol, newval; |
| 1139 | { | 1158 | { |
| 1140 | return set_internal (symbol, newval, current_buffer, 0); | 1159 | set_internal (symbol, newval, current_buffer, 0); |
| 1160 | return newval; | ||
| 1141 | } | 1161 | } |
| 1142 | 1162 | ||
| 1143 | /* Return 1 if SYMBOL currently has a let-binding | 1163 | /* Return 1 if SYMBOL currently has a let-binding |
| 1144 | which was made in the buffer that is now current. */ | 1164 | which was made in the buffer that is now current. */ |
| 1145 | 1165 | ||
| 1146 | static int | 1166 | static int |
| 1147 | let_shadows_buffer_binding_p (symbol) | 1167 | let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol) |
| 1148 | struct Lisp_Symbol *symbol; | ||
| 1149 | { | 1168 | { |
| 1150 | volatile struct specbinding *p; | 1169 | struct specbinding *p; |
| 1151 | 1170 | ||
| 1152 | for (p = specpdl_ptr - 1; p >= specpdl; p--) | 1171 | for (p = specpdl_ptr - 1; p >= specpdl; p--) |
| 1153 | if (p->func == NULL | 1172 | if (p->func == NULL |
| 1154 | && CONSP (p->symbol)) | 1173 | && CONSP (p->symbol)) |
| 1155 | { | 1174 | { |
| 1156 | struct Lisp_Symbol *let_bound_symbol = XSYMBOL (XCAR (p->symbol)); | 1175 | struct Lisp_Symbol *let_bound_symbol = XSYMBOL (XCAR (p->symbol)); |
| 1157 | if ((symbol == let_bound_symbol | 1176 | eassert (let_bound_symbol->redirect != SYMBOL_VARALIAS); |
| 1158 | || (let_bound_symbol->indirect_variable | 1177 | if (symbol == let_bound_symbol |
| 1159 | && symbol == indirect_variable (let_bound_symbol))) | ||
| 1160 | && XBUFFER (XCDR (XCDR (p->symbol))) == current_buffer) | 1178 | && XBUFFER (XCDR (XCDR (p->symbol))) == current_buffer) |
| 1161 | break; | 1179 | break; |
| 1162 | } | 1180 | } |
| @@ -1164,6 +1182,19 @@ let_shadows_buffer_binding_p (symbol) | |||
| 1164 | return p >= specpdl; | 1182 | return p >= specpdl; |
| 1165 | } | 1183 | } |
| 1166 | 1184 | ||
| 1185 | static int | ||
| 1186 | let_shadows_global_binding_p (symbol) | ||
| 1187 | Lisp_Object symbol; | ||
| 1188 | { | ||
| 1189 | struct specbinding *p; | ||
| 1190 | |||
| 1191 | for (p = specpdl_ptr - 1; p >= specpdl; p--) | ||
| 1192 | if (p->func == NULL && EQ (p->symbol, symbol)) | ||
| 1193 | break; | ||
| 1194 | |||
| 1195 | return p >= specpdl; | ||
| 1196 | } | ||
| 1197 | |||
| 1167 | /* Store the value NEWVAL into SYMBOL. | 1198 | /* Store the value NEWVAL into SYMBOL. |
| 1168 | If buffer-locality is an issue, BUF specifies which buffer to use. | 1199 | If buffer-locality is an issue, BUF specifies which buffer to use. |
| 1169 | (0 stands for the current buffer.) | 1200 | (0 stands for the current buffer.) |
| @@ -1172,133 +1203,155 @@ let_shadows_buffer_binding_p (symbol) | |||
| 1172 | local in every buffer where it is set, then we make it local. | 1203 | local in every buffer where it is set, then we make it local. |
| 1173 | If BINDFLAG is nonzero, we don't do that. */ | 1204 | If BINDFLAG is nonzero, we don't do that. */ |
| 1174 | 1205 | ||
| 1175 | Lisp_Object | 1206 | void |
| 1176 | set_internal (symbol, newval, buf, bindflag) | 1207 | set_internal (symbol, newval, buf, bindflag) |
| 1177 | register Lisp_Object symbol, newval; | 1208 | register Lisp_Object symbol, newval; |
| 1178 | struct buffer *buf; | 1209 | struct buffer *buf; |
| 1179 | int bindflag; | 1210 | int bindflag; |
| 1180 | { | 1211 | { |
| 1181 | int voide = EQ (newval, Qunbound); | 1212 | int voide = EQ (newval, Qunbound); |
| 1182 | 1213 | struct Lisp_Symbol *sym; | |
| 1183 | register Lisp_Object valcontents, innercontents, tem1, current_alist_element; | 1214 | Lisp_Object tem1; |
| 1184 | 1215 | ||
| 1185 | if (buf == 0) | 1216 | if (buf == 0) |
| 1186 | buf = current_buffer; | 1217 | buf = current_buffer; |
| 1187 | 1218 | ||
| 1188 | /* If restoring in a dead buffer, do nothing. */ | 1219 | /* If restoring in a dead buffer, do nothing. */ |
| 1189 | if (NILP (buf->name)) | 1220 | if (NILP (buf->name)) |
| 1190 | return newval; | 1221 | return; |
| 1191 | 1222 | ||
| 1192 | CHECK_SYMBOL (symbol); | 1223 | CHECK_SYMBOL (symbol); |
| 1193 | if (SYMBOL_CONSTANT_P (symbol) | 1224 | if (SYMBOL_CONSTANT_P (symbol)) |
| 1194 | && (NILP (Fkeywordp (symbol)) | ||
| 1195 | || !EQ (newval, SYMBOL_VALUE (symbol)))) | ||
| 1196 | xsignal1 (Qsetting_constant, symbol); | ||
| 1197 | |||
| 1198 | innercontents = valcontents = SYMBOL_VALUE (symbol); | ||
| 1199 | |||
| 1200 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1201 | { | 1225 | { |
| 1202 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | 1226 | if (NILP (Fkeywordp (symbol)) |
| 1203 | int idx = PER_BUFFER_IDX (offset); | 1227 | || !EQ (newval, Fsymbol_value (symbol))) |
| 1204 | if (idx > 0 | 1228 | xsignal1 (Qsetting_constant, symbol); |
| 1205 | && !bindflag | 1229 | else |
| 1206 | && !let_shadows_buffer_binding_p (XSYMBOL (symbol))) | 1230 | /* Allow setting keywords to their own value. */ |
| 1207 | SET_PER_BUFFER_VALUE_P (buf, idx, 1); | 1231 | return; |
| 1208 | } | 1232 | } |
| 1209 | else if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1210 | { | ||
| 1211 | /* valcontents is a struct Lisp_Buffer_Local_Value. */ | ||
| 1212 | if (XSYMBOL (symbol)->indirect_variable) | ||
| 1213 | XSETSYMBOL (symbol, indirect_variable (XSYMBOL (symbol))); | ||
| 1214 | |||
| 1215 | /* What binding is loaded right now? */ | ||
| 1216 | current_alist_element | ||
| 1217 | = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); | ||
| 1218 | |||
| 1219 | /* If the current buffer is not the buffer whose binding is | ||
| 1220 | loaded, or if there may be frame-local bindings and the frame | ||
| 1221 | isn't the right one, or if it's a Lisp_Buffer_Local_Value and | ||
| 1222 | the default binding is loaded, the loaded binding may be the | ||
| 1223 | wrong one. */ | ||
| 1224 | if (!BUFFERP (XBUFFER_LOCAL_VALUE (valcontents)->buffer) | ||
| 1225 | || buf != XBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer) | ||
| 1226 | || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame | ||
| 1227 | && !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame)) | ||
| 1228 | /* Also unload a global binding (if the var is local_if_set). */ | ||
| 1229 | || (EQ (XCAR (current_alist_element), | ||
| 1230 | current_alist_element))) | ||
| 1231 | { | ||
| 1232 | /* The currently loaded binding is not necessarily valid. | ||
| 1233 | We need to unload it, and choose a new binding. */ | ||
| 1234 | 1233 | ||
| 1235 | /* Write out `realvalue' to the old loaded binding. */ | 1234 | sym = XSYMBOL (symbol); |
| 1236 | Fsetcdr (current_alist_element, | ||
| 1237 | do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue)); | ||
| 1238 | 1235 | ||
| 1239 | /* Find the new binding. */ | 1236 | start: |
| 1240 | tem1 = Fassq (symbol, buf->local_var_alist); | 1237 | switch (sym->redirect) |
| 1241 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1; | 1238 | { |
| 1242 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0; | 1239 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1240 | case SYMBOL_PLAINVAL: SET_SYMBOL_VAL (sym , newval); return; | ||
| 1241 | case SYMBOL_LOCALIZED: | ||
| 1242 | { | ||
| 1243 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 1244 | Lisp_Object tmp; XSETBUFFER (tmp, buf); | ||
| 1245 | |||
| 1246 | /* If the current buffer is not the buffer whose binding is | ||
| 1247 | loaded, or if there may be frame-local bindings and the frame | ||
| 1248 | isn't the right one, or if it's a Lisp_Buffer_Local_Value and | ||
| 1249 | the default binding is loaded, the loaded binding may be the | ||
| 1250 | wrong one. */ | ||
| 1251 | if (!EQ (blv->where, | ||
| 1252 | blv->frame_local ? selected_frame : tmp) | ||
| 1253 | /* Also unload a global binding (if the var is local_if_set). */ | ||
| 1254 | || (EQ (blv->valcell, blv->defcell))) | ||
| 1255 | { | ||
| 1256 | /* The currently loaded binding is not necessarily valid. | ||
| 1257 | We need to unload it, and choose a new binding. */ | ||
| 1258 | |||
| 1259 | /* Write out `realvalue' to the old loaded binding. */ | ||
| 1260 | if (blv->fwd) | ||
| 1261 | SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd)); | ||
| 1243 | 1262 | ||
| 1244 | if (NILP (tem1)) | 1263 | /* Find the new binding. */ |
| 1245 | { | 1264 | { |
| 1246 | /* This buffer still sees the default value. */ | 1265 | XSETSYMBOL (symbol, sym); /* May have changed via aliasing. */ |
| 1247 | 1266 | if (blv->frame_local) | |
| 1248 | /* If the variable is not local_if_set, | ||
| 1249 | or if this is `let' rather than `set', | ||
| 1250 | make CURRENT-ALIST-ELEMENT point to itself, | ||
| 1251 | indicating that we're seeing the default value. | ||
| 1252 | Likewise if the variable has been let-bound | ||
| 1253 | in the current buffer. */ | ||
| 1254 | if (bindflag || !XBUFFER_LOCAL_VALUE (valcontents)->local_if_set | ||
| 1255 | || let_shadows_buffer_binding_p (XSYMBOL (symbol))) | ||
| 1256 | { | 1267 | { |
| 1257 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0; | 1268 | tem1 = Fassq (symbol, XFRAME (selected_frame)->param_alist); |
| 1258 | 1269 | blv->where = selected_frame; | |
| 1259 | if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame) | ||
| 1260 | tem1 = Fassq (symbol, | ||
| 1261 | XFRAME (selected_frame)->param_alist); | ||
| 1262 | |||
| 1263 | if (! NILP (tem1)) | ||
| 1264 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 1; | ||
| 1265 | else | ||
| 1266 | tem1 = XBUFFER_LOCAL_VALUE (valcontents)->cdr; | ||
| 1267 | } | 1270 | } |
| 1268 | /* If it's a Lisp_Buffer_Local_Value, being set not bound, | ||
| 1269 | and we're not within a let that was made for this buffer, | ||
| 1270 | create a new buffer-local binding for the variable. | ||
| 1271 | That means, give this buffer a new assoc for a local value | ||
| 1272 | and load that binding. */ | ||
| 1273 | else | 1271 | else |
| 1274 | { | 1272 | { |
| 1275 | tem1 = Fcons (symbol, XCDR (current_alist_element)); | 1273 | tem1 = Fassq (symbol, buf->local_var_alist); |
| 1276 | buf->local_var_alist | 1274 | blv->where = tmp; |
| 1277 | = Fcons (tem1, buf->local_var_alist); | ||
| 1278 | } | 1275 | } |
| 1279 | } | 1276 | } |
| 1277 | blv->found = 1; | ||
| 1278 | |||
| 1279 | if (NILP (tem1)) | ||
| 1280 | { | ||
| 1281 | /* This buffer still sees the default value. */ | ||
| 1282 | |||
| 1283 | /* If the variable is a Lisp_Some_Buffer_Local_Value, | ||
| 1284 | or if this is `let' rather than `set', | ||
| 1285 | make CURRENT-ALIST-ELEMENT point to itself, | ||
| 1286 | indicating that we're seeing the default value. | ||
| 1287 | Likewise if the variable has been let-bound | ||
| 1288 | in the current buffer. */ | ||
| 1289 | if (bindflag || !blv->local_if_set | ||
| 1290 | || let_shadows_buffer_binding_p (sym)) | ||
| 1291 | { | ||
| 1292 | blv->found = 0; | ||
| 1293 | tem1 = blv->defcell; | ||
| 1294 | } | ||
| 1295 | /* If it's a local_if_set, being set not bound, | ||
| 1296 | and we're not within a let that was made for this buffer, | ||
| 1297 | create a new buffer-local binding for the variable. | ||
| 1298 | That means, give this buffer a new assoc for a local value | ||
| 1299 | and load that binding. */ | ||
| 1300 | else | ||
| 1301 | { | ||
| 1302 | /* local_if_set is only supported for buffer-local | ||
| 1303 | bindings, not for frame-local bindings. */ | ||
| 1304 | eassert (!blv->frame_local); | ||
| 1305 | tem1 = Fcons (symbol, XCDR (blv->defcell)); | ||
| 1306 | buf->local_var_alist | ||
| 1307 | = Fcons (tem1, buf->local_var_alist); | ||
| 1308 | } | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | /* Record which binding is now loaded. */ | ||
| 1312 | blv->valcell = tem1; | ||
| 1313 | } | ||
| 1280 | 1314 | ||
| 1281 | /* Record which binding is now loaded. */ | 1315 | /* Store the new value in the cons cell. */ |
| 1282 | XSETCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, tem1); | 1316 | SET_BLV_VALUE (blv, newval); |
| 1283 | 1317 | ||
| 1284 | /* Set `buffer' and `frame' slots for the binding now loaded. */ | 1318 | if (blv->fwd) |
| 1285 | XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, buf); | 1319 | { |
| 1286 | XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame; | 1320 | if (voide) |
| 1287 | } | 1321 | /* If storing void (making the symbol void), forward only through |
| 1288 | innercontents = XBUFFER_LOCAL_VALUE (valcontents)->realvalue; | 1322 | buffer-local indicator, not through Lisp_Objfwd, etc. */ |
| 1323 | blv->fwd = NULL; | ||
| 1324 | else | ||
| 1325 | store_symval_forwarding (blv->fwd, newval, buf); | ||
| 1326 | } | ||
| 1327 | break; | ||
| 1328 | } | ||
| 1329 | case SYMBOL_FORWARDED: | ||
| 1330 | { | ||
| 1331 | union Lisp_Fwd *innercontents = SYMBOL_FWD (sym); | ||
| 1332 | if (BUFFER_OBJFWDP (innercontents)) | ||
| 1333 | { | ||
| 1334 | int offset = XBUFFER_OBJFWD (innercontents)->offset; | ||
| 1335 | int idx = PER_BUFFER_IDX (offset); | ||
| 1336 | if (idx > 0 | ||
| 1337 | && !bindflag | ||
| 1338 | && !let_shadows_buffer_binding_p (sym)) | ||
| 1339 | SET_PER_BUFFER_VALUE_P (buf, idx, 1); | ||
| 1340 | } | ||
| 1289 | 1341 | ||
| 1290 | /* Store the new value in the cons-cell. */ | 1342 | if (voide) |
| 1291 | XSETCDR (XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr), newval); | 1343 | { /* If storing void (making the symbol void), forward only through |
| 1344 | buffer-local indicator, not through Lisp_Objfwd, etc. */ | ||
| 1345 | sym->redirect = SYMBOL_PLAINVAL; | ||
| 1346 | SET_SYMBOL_VAL (sym, newval); | ||
| 1347 | } | ||
| 1348 | else | ||
| 1349 | store_symval_forwarding (/* sym, */ innercontents, newval, buf); | ||
| 1350 | break; | ||
| 1351 | } | ||
| 1352 | default: abort (); | ||
| 1292 | } | 1353 | } |
| 1293 | 1354 | return; | |
| 1294 | /* If storing void (making the symbol void), forward only through | ||
| 1295 | buffer-local indicator, not through Lisp_Objfwd, etc. */ | ||
| 1296 | if (voide) | ||
| 1297 | store_symval_forwarding (symbol, Qnil, newval, buf); | ||
| 1298 | else | ||
| 1299 | store_symval_forwarding (symbol, innercontents, newval, buf); | ||
| 1300 | |||
| 1301 | return newval; | ||
| 1302 | } | 1355 | } |
| 1303 | 1356 | ||
| 1304 | /* Access or set a buffer-local symbol's default value. */ | 1357 | /* Access or set a buffer-local symbol's default value. */ |
| @@ -1310,38 +1363,46 @@ Lisp_Object | |||
| 1310 | default_value (symbol) | 1363 | default_value (symbol) |
| 1311 | Lisp_Object symbol; | 1364 | Lisp_Object symbol; |
| 1312 | { | 1365 | { |
| 1313 | register Lisp_Object valcontents; | 1366 | struct Lisp_Symbol *sym; |
| 1314 | 1367 | ||
| 1315 | CHECK_SYMBOL (symbol); | 1368 | CHECK_SYMBOL (symbol); |
| 1316 | valcontents = SYMBOL_VALUE (symbol); | 1369 | sym = XSYMBOL (symbol); |
| 1317 | 1370 | ||
| 1318 | /* For a built-in buffer-local variable, get the default value | 1371 | start: |
| 1319 | rather than letting do_symval_forwarding get the current value. */ | 1372 | switch (sym->redirect) |
| 1320 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1321 | { | 1373 | { |
| 1322 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | 1374 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1323 | if (PER_BUFFER_IDX (offset) != 0) | 1375 | case SYMBOL_PLAINVAL: return SYMBOL_VAL (sym); |
| 1324 | return PER_BUFFER_DEFAULT (offset); | 1376 | case SYMBOL_LOCALIZED: |
| 1325 | } | 1377 | { |
| 1378 | /* If var is set up for a buffer that lacks a local value for it, | ||
| 1379 | the current value is nominally the default value. | ||
| 1380 | But the `realvalue' slot may be more up to date, since | ||
| 1381 | ordinary setq stores just that slot. So use that. */ | ||
| 1382 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 1383 | if (blv->fwd && EQ (blv->valcell, blv->defcell)) | ||
| 1384 | return do_symval_forwarding (blv->fwd); | ||
| 1385 | else | ||
| 1386 | return XCDR (blv->defcell); | ||
| 1387 | } | ||
| 1388 | case SYMBOL_FORWARDED: | ||
| 1389 | { | ||
| 1390 | union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); | ||
| 1326 | 1391 | ||
| 1327 | /* Handle user-created local variables. */ | 1392 | /* For a built-in buffer-local variable, get the default value |
| 1328 | if (BUFFER_LOCAL_VALUEP (valcontents)) | 1393 | rather than letting do_symval_forwarding get the current value. */ |
| 1329 | { | 1394 | if (BUFFER_OBJFWDP (valcontents)) |
| 1330 | /* If var is set up for a buffer that lacks a local value for it, | 1395 | { |
| 1331 | the current value is nominally the default value. | 1396 | int offset = XBUFFER_OBJFWD (valcontents)->offset; |
| 1332 | But the `realvalue' slot may be more up to date, since | 1397 | if (PER_BUFFER_IDX (offset) != 0) |
| 1333 | ordinary setq stores just that slot. So use that. */ | 1398 | return PER_BUFFER_DEFAULT (offset); |
| 1334 | Lisp_Object current_alist_element, alist_element_car; | 1399 | } |
| 1335 | current_alist_element | 1400 | |
| 1336 | = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); | 1401 | /* For other variables, get the current value. */ |
| 1337 | alist_element_car = XCAR (current_alist_element); | 1402 | return do_symval_forwarding (valcontents); |
| 1338 | if (EQ (alist_element_car, current_alist_element)) | 1403 | } |
| 1339 | return do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue); | 1404 | default: abort (); |
| 1340 | else | ||
| 1341 | return XCDR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); | ||
| 1342 | } | 1405 | } |
| 1343 | /* For other variables, get the current value. */ | ||
| 1344 | return do_symval_forwarding (valcontents); | ||
| 1345 | } | 1406 | } |
| 1346 | 1407 | ||
| 1347 | DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0, | 1408 | DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0, |
| @@ -1381,50 +1442,68 @@ for this variable. */) | |||
| 1381 | (symbol, value) | 1442 | (symbol, value) |
| 1382 | Lisp_Object symbol, value; | 1443 | Lisp_Object symbol, value; |
| 1383 | { | 1444 | { |
| 1384 | register Lisp_Object valcontents, current_alist_element, alist_element_buffer; | 1445 | struct Lisp_Symbol *sym; |
| 1385 | 1446 | ||
| 1386 | CHECK_SYMBOL (symbol); | 1447 | CHECK_SYMBOL (symbol); |
| 1387 | valcontents = SYMBOL_VALUE (symbol); | 1448 | if (SYMBOL_CONSTANT_P (symbol)) |
| 1388 | |||
| 1389 | /* Handle variables like case-fold-search that have special slots | ||
| 1390 | in the buffer. Make them work apparently like Lisp_Buffer_Local_Value | ||
| 1391 | variables. */ | ||
| 1392 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1393 | { | 1449 | { |
| 1394 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | 1450 | if (NILP (Fkeywordp (symbol)) |
| 1395 | int idx = PER_BUFFER_IDX (offset); | 1451 | || !EQ (value, Fdefault_value (symbol))) |
| 1452 | xsignal1 (Qsetting_constant, symbol); | ||
| 1453 | else | ||
| 1454 | /* Allow setting keywords to their own value. */ | ||
| 1455 | return value; | ||
| 1456 | } | ||
| 1457 | sym = XSYMBOL (symbol); | ||
| 1396 | 1458 | ||
| 1397 | PER_BUFFER_DEFAULT (offset) = value; | 1459 | start: |
| 1460 | switch (sym->redirect) | ||
| 1461 | { | ||
| 1462 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; | ||
| 1463 | case SYMBOL_PLAINVAL: return Fset (symbol, value); | ||
| 1464 | case SYMBOL_LOCALIZED: | ||
| 1465 | { | ||
| 1466 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 1398 | 1467 | ||
| 1399 | /* If this variable is not always local in all buffers, | 1468 | /* Store new value into the DEFAULT-VALUE slot. */ |
| 1400 | set it in the buffers that don't nominally have a local value. */ | 1469 | XSETCDR (blv->defcell, value); |
| 1401 | if (idx > 0) | ||
| 1402 | { | ||
| 1403 | struct buffer *b; | ||
| 1404 | 1470 | ||
| 1405 | for (b = all_buffers; b; b = b->next) | 1471 | /* If the default binding is now loaded, set the REALVALUE slot too. */ |
| 1406 | if (!PER_BUFFER_VALUE_P (b, idx)) | 1472 | if (blv->fwd && EQ (blv->defcell, blv->valcell)) |
| 1407 | PER_BUFFER_VALUE (b, offset) = value; | 1473 | store_symval_forwarding (blv->fwd, value, NULL); |
| 1408 | } | 1474 | return value; |
| 1409 | return value; | 1475 | } |
| 1410 | } | 1476 | case SYMBOL_FORWARDED: |
| 1477 | { | ||
| 1478 | union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); | ||
| 1411 | 1479 | ||
| 1412 | if (!BUFFER_LOCAL_VALUEP (valcontents)) | 1480 | /* Handle variables like case-fold-search that have special slots |
| 1413 | return Fset (symbol, value); | 1481 | in the buffer. |
| 1482 | Make them work apparently like Lisp_Buffer_Local_Value variables. */ | ||
| 1483 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1484 | { | ||
| 1485 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | ||
| 1486 | int idx = PER_BUFFER_IDX (offset); | ||
| 1414 | 1487 | ||
| 1415 | /* Store new value into the DEFAULT-VALUE slot. */ | 1488 | PER_BUFFER_DEFAULT (offset) = value; |
| 1416 | XSETCDR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, value); | ||
| 1417 | 1489 | ||
| 1418 | /* If the default binding is now loaded, set the REALVALUE slot too. */ | 1490 | /* If this variable is not always local in all buffers, |
| 1419 | current_alist_element | 1491 | set it in the buffers that don't nominally have a local value. */ |
| 1420 | = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); | 1492 | if (idx > 0) |
| 1421 | alist_element_buffer = Fcar (current_alist_element); | 1493 | { |
| 1422 | if (EQ (alist_element_buffer, current_alist_element)) | 1494 | struct buffer *b; |
| 1423 | store_symval_forwarding (symbol, | ||
| 1424 | XBUFFER_LOCAL_VALUE (valcontents)->realvalue, | ||
| 1425 | value, NULL); | ||
| 1426 | 1495 | ||
| 1427 | return value; | 1496 | for (b = all_buffers; b; b = b->next) |
| 1497 | if (!PER_BUFFER_VALUE_P (b, idx)) | ||
| 1498 | PER_BUFFER_VALUE (b, offset) = value; | ||
| 1499 | } | ||
| 1500 | return value; | ||
| 1501 | } | ||
| 1502 | else | ||
| 1503 | return Fset (symbol, value); | ||
| 1504 | } | ||
| 1505 | default: abort (); | ||
| 1506 | } | ||
| 1428 | } | 1507 | } |
| 1429 | 1508 | ||
| 1430 | DEFUN ("setq-default", Fsetq_default, Ssetq_default, 0, UNEVALLED, 0, | 1509 | DEFUN ("setq-default", Fsetq_default, Ssetq_default, 0, UNEVALLED, 0, |
| @@ -1468,6 +1547,35 @@ usage: (setq-default [VAR VALUE]...) */) | |||
| 1468 | 1547 | ||
| 1469 | /* Lisp functions for creating and removing buffer-local variables. */ | 1548 | /* Lisp functions for creating and removing buffer-local variables. */ |
| 1470 | 1549 | ||
| 1550 | union Lisp_Val_Fwd | ||
| 1551 | { | ||
| 1552 | Lisp_Object value; | ||
| 1553 | union Lisp_Fwd *fwd; | ||
| 1554 | }; | ||
| 1555 | |||
| 1556 | static struct Lisp_Buffer_Local_Value * | ||
| 1557 | make_blv (struct Lisp_Symbol *sym, int forwarded, union Lisp_Val_Fwd valcontents) | ||
| 1558 | { | ||
| 1559 | struct Lisp_Buffer_Local_Value *blv | ||
| 1560 | = xmalloc (sizeof (struct Lisp_Buffer_Local_Value)); | ||
| 1561 | Lisp_Object symbol; XSETSYMBOL (symbol, sym); | ||
| 1562 | Lisp_Object tem = Fcons (symbol, (forwarded | ||
| 1563 | ? do_symval_forwarding (valcontents.fwd) | ||
| 1564 | : valcontents.value)); | ||
| 1565 | /* Buffer_Local_Values cannot have as realval a buffer-local | ||
| 1566 | or keyboard-local forwarding. */ | ||
| 1567 | eassert (!(forwarded && BUFFER_OBJFWDP (valcontents.fwd))); | ||
| 1568 | eassert (!(forwarded && KBOARD_OBJFWDP (valcontents.fwd))); | ||
| 1569 | blv->fwd = forwarded ? valcontents.fwd : NULL; | ||
| 1570 | blv->where = Qnil; | ||
| 1571 | blv->frame_local = 0; | ||
| 1572 | blv->local_if_set = 0; | ||
| 1573 | blv->defcell = tem; | ||
| 1574 | blv->valcell = tem; | ||
| 1575 | SET_BLV_FOUND (blv, 0); | ||
| 1576 | return blv; | ||
| 1577 | } | ||
| 1578 | |||
| 1471 | DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local, Smake_variable_buffer_local, | 1579 | DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local, Smake_variable_buffer_local, |
| 1472 | 1, 1, "vMake Variable Buffer Local: ", | 1580 | 1, 1, "vMake Variable Buffer Local: ", |
| 1473 | doc: /* Make VARIABLE become buffer-local whenever it is set. | 1581 | doc: /* Make VARIABLE become buffer-local whenever it is set. |
| @@ -1485,42 +1593,58 @@ The function `default-value' gets the default value and `set-default' sets it. | |||
| 1485 | (variable) | 1593 | (variable) |
| 1486 | register Lisp_Object variable; | 1594 | register Lisp_Object variable; |
| 1487 | { | 1595 | { |
| 1488 | register Lisp_Object tem, valcontents, newval; | ||
| 1489 | struct Lisp_Symbol *sym; | 1596 | struct Lisp_Symbol *sym; |
| 1597 | struct Lisp_Buffer_Local_Value *blv = NULL; | ||
| 1598 | union Lisp_Val_Fwd valcontents; | ||
| 1599 | int forwarded; | ||
| 1490 | 1600 | ||
| 1491 | CHECK_SYMBOL (variable); | 1601 | CHECK_SYMBOL (variable); |
| 1492 | sym = indirect_variable (XSYMBOL (variable)); | 1602 | sym = XSYMBOL (variable); |
| 1493 | |||
| 1494 | valcontents = sym->value; | ||
| 1495 | if (sym->constant || KBOARD_OBJFWDP (valcontents)) | ||
| 1496 | error ("Symbol %s may not be buffer-local", SDATA (sym->xname)); | ||
| 1497 | 1603 | ||
| 1498 | if (BUFFER_OBJFWDP (valcontents)) | 1604 | start: |
| 1499 | return variable; | 1605 | switch (sym->redirect) |
| 1500 | else if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1501 | { | 1606 | { |
| 1502 | if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame) | 1607 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1503 | error ("Symbol %s may not be buffer-local", SDATA (sym->xname)); | 1608 | case SYMBOL_PLAINVAL: |
| 1504 | newval = valcontents; | 1609 | forwarded = 0; valcontents.value = SYMBOL_VAL (sym); |
| 1610 | if (EQ (valcontents.value, Qunbound)) | ||
| 1611 | valcontents.value = Qnil; | ||
| 1612 | break; | ||
| 1613 | case SYMBOL_LOCALIZED: | ||
| 1614 | blv = SYMBOL_BLV (sym); | ||
| 1615 | if (blv->frame_local) | ||
| 1616 | error ("Symbol %s may not be buffer-local", | ||
| 1617 | SDATA (SYMBOL_NAME (variable))); | ||
| 1618 | break; | ||
| 1619 | case SYMBOL_FORWARDED: | ||
| 1620 | forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym); | ||
| 1621 | if (KBOARD_OBJFWDP (valcontents.fwd)) | ||
| 1622 | error ("Symbol %s may not be buffer-local", | ||
| 1623 | SDATA (SYMBOL_NAME (variable))); | ||
| 1624 | else if (BUFFER_OBJFWDP (valcontents.fwd)) | ||
| 1625 | return variable; | ||
| 1626 | break; | ||
| 1627 | default: abort (); | ||
| 1505 | } | 1628 | } |
| 1506 | else | 1629 | |
| 1630 | if (sym->constant) | ||
| 1631 | error ("Symbol %s may not be buffer-local", SDATA (SYMBOL_NAME (variable))); | ||
| 1632 | |||
| 1633 | if (!blv) | ||
| 1507 | { | 1634 | { |
| 1508 | if (EQ (valcontents, Qunbound)) | 1635 | blv = make_blv (sym, forwarded, valcontents); |
| 1509 | sym->value = Qnil; | 1636 | sym->redirect = SYMBOL_LOCALIZED; |
| 1510 | tem = Fcons (Qnil, Fsymbol_value (variable)); | 1637 | SET_SYMBOL_BLV (sym, blv); |
| 1511 | XSETCAR (tem, tem); | 1638 | { |
| 1512 | newval = allocate_misc (); | 1639 | Lisp_Object symbol; |
| 1513 | XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value; | 1640 | XSETSYMBOL (symbol, sym); /* In case `variable' is aliased. */ |
| 1514 | XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value; | 1641 | if (let_shadows_global_binding_p (symbol)) |
| 1515 | XBUFFER_LOCAL_VALUE (newval)->buffer = Fcurrent_buffer (); | 1642 | error ("Making %s buffer-local while let-bound!", |
| 1516 | XBUFFER_LOCAL_VALUE (newval)->frame = Qnil; | 1643 | SDATA (SYMBOL_NAME (variable))); |
| 1517 | XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0; | 1644 | } |
| 1518 | XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0; | ||
| 1519 | XBUFFER_LOCAL_VALUE (newval)->check_frame = 0; | ||
| 1520 | XBUFFER_LOCAL_VALUE (newval)->cdr = tem; | ||
| 1521 | sym->value = newval; | ||
| 1522 | } | 1645 | } |
| 1523 | XBUFFER_LOCAL_VALUE (newval)->local_if_set = 1; | 1646 | |
| 1647 | blv->local_if_set = 1; | ||
| 1524 | return variable; | 1648 | return variable; |
| 1525 | } | 1649 | } |
| 1526 | 1650 | ||
| @@ -1547,82 +1671,95 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */) | |||
| 1547 | (variable) | 1671 | (variable) |
| 1548 | register Lisp_Object variable; | 1672 | register Lisp_Object variable; |
| 1549 | { | 1673 | { |
| 1550 | register Lisp_Object tem, valcontents; | 1674 | register Lisp_Object tem; |
| 1675 | int forwarded; | ||
| 1676 | union Lisp_Val_Fwd valcontents; | ||
| 1551 | struct Lisp_Symbol *sym; | 1677 | struct Lisp_Symbol *sym; |
| 1678 | struct Lisp_Buffer_Local_Value *blv = NULL; | ||
| 1552 | 1679 | ||
| 1553 | CHECK_SYMBOL (variable); | 1680 | CHECK_SYMBOL (variable); |
| 1554 | sym = indirect_variable (XSYMBOL (variable)); | 1681 | sym = XSYMBOL (variable); |
| 1555 | 1682 | ||
| 1556 | valcontents = sym->value; | 1683 | start: |
| 1557 | if (sym->constant || KBOARD_OBJFWDP (valcontents) | 1684 | switch (sym->redirect) |
| 1558 | || (BUFFER_LOCAL_VALUEP (valcontents) | 1685 | { |
| 1559 | && (XBUFFER_LOCAL_VALUE (valcontents)->check_frame))) | 1686 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1560 | error ("Symbol %s may not be buffer-local", SDATA (sym->xname)); | 1687 | case SYMBOL_PLAINVAL: |
| 1688 | forwarded = 0; valcontents.value = SYMBOL_VAL (sym); break; | ||
| 1689 | case SYMBOL_LOCALIZED: | ||
| 1690 | blv = SYMBOL_BLV (sym); | ||
| 1691 | if (blv->frame_local) | ||
| 1692 | error ("Symbol %s may not be buffer-local", | ||
| 1693 | SDATA (SYMBOL_NAME (variable))); | ||
| 1694 | break; | ||
| 1695 | case SYMBOL_FORWARDED: | ||
| 1696 | forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym); | ||
| 1697 | if (KBOARD_OBJFWDP (valcontents.fwd)) | ||
| 1698 | error ("Symbol %s may not be buffer-local", | ||
| 1699 | SDATA (SYMBOL_NAME (variable))); | ||
| 1700 | break; | ||
| 1701 | default: abort (); | ||
| 1702 | } | ||
| 1561 | 1703 | ||
| 1562 | if ((BUFFER_LOCAL_VALUEP (valcontents) | 1704 | if (sym->constant) |
| 1563 | && XBUFFER_LOCAL_VALUE (valcontents)->local_if_set) | 1705 | error ("Symbol %s may not be buffer-local", SDATA (SYMBOL_NAME (variable))); |
| 1564 | || BUFFER_OBJFWDP (valcontents)) | 1706 | |
| 1707 | if (blv ? blv->local_if_set | ||
| 1708 | : (forwarded && BUFFER_OBJFWDP (valcontents.fwd))) | ||
| 1565 | { | 1709 | { |
| 1566 | tem = Fboundp (variable); | 1710 | tem = Fboundp (variable); |
| 1567 | |||
| 1568 | /* Make sure the symbol has a local value in this particular buffer, | 1711 | /* Make sure the symbol has a local value in this particular buffer, |
| 1569 | by setting it to the same value it already has. */ | 1712 | by setting it to the same value it already has. */ |
| 1570 | Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound)); | 1713 | Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound)); |
| 1571 | return variable; | 1714 | return variable; |
| 1572 | } | 1715 | } |
| 1573 | /* Make sure symbol is set up to hold per-buffer values. */ | 1716 | if (!blv) |
| 1574 | if (!BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1575 | { | 1717 | { |
| 1576 | Lisp_Object newval; | 1718 | blv = make_blv (sym, forwarded, valcontents); |
| 1577 | tem = Fcons (Qnil, do_symval_forwarding (valcontents)); | 1719 | sym->redirect = SYMBOL_LOCALIZED; |
| 1578 | XSETCAR (tem, tem); | 1720 | SET_SYMBOL_BLV (sym, blv); |
| 1579 | newval = allocate_misc (); | 1721 | { |
| 1580 | XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value; | 1722 | Lisp_Object symbol; |
| 1581 | XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value; | 1723 | XSETSYMBOL (symbol, sym); /* In case `variable' is aliased. */ |
| 1582 | XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil; | 1724 | if (let_shadows_global_binding_p (symbol)) |
| 1583 | XBUFFER_LOCAL_VALUE (newval)->frame = Qnil; | 1725 | error ("Making %s local to %s while let-bound!", |
| 1584 | XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0; | 1726 | SDATA (SYMBOL_NAME (variable)), SDATA (current_buffer->name)); |
| 1585 | XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0; | 1727 | } |
| 1586 | XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0; | ||
| 1587 | XBUFFER_LOCAL_VALUE (newval)->check_frame = 0; | ||
| 1588 | XBUFFER_LOCAL_VALUE (newval)->cdr = tem; | ||
| 1589 | sym->value = newval; | ||
| 1590 | } | 1728 | } |
| 1729 | |||
| 1591 | /* Make sure this buffer has its own value of symbol. */ | 1730 | /* Make sure this buffer has its own value of symbol. */ |
| 1592 | XSETSYMBOL (variable, sym); /* Propagate variable indirections. */ | 1731 | XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ |
| 1593 | tem = Fassq (variable, current_buffer->local_var_alist); | 1732 | tem = Fassq (variable, current_buffer->local_var_alist); |
| 1594 | if (NILP (tem)) | 1733 | if (NILP (tem)) |
| 1595 | { | 1734 | { |
| 1735 | if (let_shadows_buffer_binding_p (sym)) | ||
| 1736 | message ("Making %s buffer-local while locally let-bound!", | ||
| 1737 | SDATA (SYMBOL_NAME (variable))); | ||
| 1738 | |||
| 1596 | /* Swap out any local binding for some other buffer, and make | 1739 | /* Swap out any local binding for some other buffer, and make |
| 1597 | sure the current value is permanently recorded, if it's the | 1740 | sure the current value is permanently recorded, if it's the |
| 1598 | default value. */ | 1741 | default value. */ |
| 1599 | find_symbol_value (variable); | 1742 | find_symbol_value (variable); |
| 1600 | 1743 | ||
| 1601 | current_buffer->local_var_alist | 1744 | current_buffer->local_var_alist |
| 1602 | = Fcons (Fcons (variable, XCDR (XBUFFER_LOCAL_VALUE (sym->value)->cdr)), | 1745 | = Fcons (Fcons (variable, XCDR (blv->defcell)), |
| 1603 | current_buffer->local_var_alist); | 1746 | current_buffer->local_var_alist); |
| 1604 | 1747 | ||
| 1605 | /* Make sure symbol does not think it is set up for this buffer; | 1748 | /* Make sure symbol does not think it is set up for this buffer; |
| 1606 | force it to look once again for this buffer's value. */ | 1749 | force it to look once again for this buffer's value. */ |
| 1607 | { | 1750 | if (current_buffer == XBUFFER (blv->where)) |
| 1608 | Lisp_Object *pvalbuf; | 1751 | blv->where = Qnil; |
| 1609 | 1752 | /* blv->valcell = blv->defcell; | |
| 1610 | valcontents = sym->value; | 1753 | * SET_BLV_FOUND (blv, 0); */ |
| 1611 | 1754 | blv->found = 0; | |
| 1612 | pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer; | ||
| 1613 | if (current_buffer == XBUFFER (*pvalbuf)) | ||
| 1614 | *pvalbuf = Qnil; | ||
| 1615 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0; | ||
| 1616 | } | ||
| 1617 | } | 1755 | } |
| 1618 | 1756 | ||
| 1619 | /* If the symbol forwards into a C variable, then load the binding | 1757 | /* If the symbol forwards into a C variable, then load the binding |
| 1620 | for this buffer now. If C code modifies the variable before we | 1758 | for this buffer now. If C code modifies the variable before we |
| 1621 | load the binding in, then that new value will clobber the default | 1759 | load the binding in, then that new value will clobber the default |
| 1622 | binding the next time we unload it. */ | 1760 | binding the next time we unload it. */ |
| 1623 | valcontents = XBUFFER_LOCAL_VALUE (sym->value)->realvalue; | 1761 | if (blv->fwd) |
| 1624 | if (INTFWDP (valcontents) || BOOLFWDP (valcontents) || OBJFWDP (valcontents)) | 1762 | swap_in_symval_forwarding (sym, blv); |
| 1625 | swap_in_symval_forwarding (variable, sym->value); | ||
| 1626 | 1763 | ||
| 1627 | return variable; | 1764 | return variable; |
| 1628 | } | 1765 | } |
| @@ -1634,31 +1771,43 @@ From now on the default value will apply in this buffer. Return VARIABLE. */) | |||
| 1634 | (variable) | 1771 | (variable) |
| 1635 | register Lisp_Object variable; | 1772 | register Lisp_Object variable; |
| 1636 | { | 1773 | { |
| 1637 | register Lisp_Object tem, valcontents; | 1774 | register Lisp_Object tem; |
| 1775 | struct Lisp_Buffer_Local_Value *blv; | ||
| 1638 | struct Lisp_Symbol *sym; | 1776 | struct Lisp_Symbol *sym; |
| 1639 | 1777 | ||
| 1640 | CHECK_SYMBOL (variable); | 1778 | CHECK_SYMBOL (variable); |
| 1641 | sym = indirect_variable (XSYMBOL (variable)); | 1779 | sym = XSYMBOL (variable); |
| 1642 | |||
| 1643 | valcontents = sym->value; | ||
| 1644 | 1780 | ||
| 1645 | if (BUFFER_OBJFWDP (valcontents)) | 1781 | start: |
| 1782 | switch (sym->redirect) | ||
| 1646 | { | 1783 | { |
| 1647 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | 1784 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1648 | int idx = PER_BUFFER_IDX (offset); | 1785 | case SYMBOL_PLAINVAL: return variable; |
| 1649 | 1786 | case SYMBOL_FORWARDED: | |
| 1650 | if (idx > 0) | 1787 | { |
| 1651 | { | 1788 | union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); |
| 1652 | SET_PER_BUFFER_VALUE_P (current_buffer, idx, 0); | 1789 | if (BUFFER_OBJFWDP (valcontents)) |
| 1653 | PER_BUFFER_VALUE (current_buffer, offset) | 1790 | { |
| 1654 | = PER_BUFFER_DEFAULT (offset); | 1791 | int offset = XBUFFER_OBJFWD (valcontents)->offset; |
| 1655 | } | 1792 | int idx = PER_BUFFER_IDX (offset); |
| 1656 | return variable; | 1793 | |
| 1794 | if (idx > 0) | ||
| 1795 | { | ||
| 1796 | SET_PER_BUFFER_VALUE_P (current_buffer, idx, 0); | ||
| 1797 | PER_BUFFER_VALUE (current_buffer, offset) | ||
| 1798 | = PER_BUFFER_DEFAULT (offset); | ||
| 1799 | } | ||
| 1800 | } | ||
| 1801 | return variable; | ||
| 1802 | } | ||
| 1803 | case SYMBOL_LOCALIZED: | ||
| 1804 | blv = SYMBOL_BLV (sym); | ||
| 1805 | if (blv->frame_local) | ||
| 1806 | return variable; | ||
| 1807 | break; | ||
| 1808 | default: abort (); | ||
| 1657 | } | 1809 | } |
| 1658 | 1810 | ||
| 1659 | if (!BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1660 | return variable; | ||
| 1661 | |||
| 1662 | /* Get rid of this buffer's alist element, if any. */ | 1811 | /* Get rid of this buffer's alist element, if any. */ |
| 1663 | XSETSYMBOL (variable, sym); /* Propagate variable indirection. */ | 1812 | XSETSYMBOL (variable, sym); /* Propagate variable indirection. */ |
| 1664 | tem = Fassq (variable, current_buffer->local_var_alist); | 1813 | tem = Fassq (variable, current_buffer->local_var_alist); |
| @@ -1670,14 +1819,13 @@ From now on the default value will apply in this buffer. Return VARIABLE. */) | |||
| 1670 | loaded, recompute its value. We have to do it now, or else | 1819 | loaded, recompute its value. We have to do it now, or else |
| 1671 | forwarded objects won't work right. */ | 1820 | forwarded objects won't work right. */ |
| 1672 | { | 1821 | { |
| 1673 | Lisp_Object *pvalbuf, buf; | 1822 | Lisp_Object buf; XSETBUFFER (buf, current_buffer); |
| 1674 | valcontents = sym->value; | 1823 | if (EQ (buf, blv->where)) |
| 1675 | pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer; | ||
| 1676 | XSETBUFFER (buf, current_buffer); | ||
| 1677 | if (EQ (buf, *pvalbuf)) | ||
| 1678 | { | 1824 | { |
| 1679 | *pvalbuf = Qnil; | 1825 | blv->where = Qnil; |
| 1680 | XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0; | 1826 | /* blv->valcell = blv->defcell; |
| 1827 | * SET_BLV_FOUND (blv, 0); */ | ||
| 1828 | blv->found = 0; | ||
| 1681 | find_symbol_value (variable); | 1829 | find_symbol_value (variable); |
| 1682 | } | 1830 | } |
| 1683 | } | 1831 | } |
| @@ -1712,39 +1860,45 @@ frame-local bindings). */) | |||
| 1712 | (variable) | 1860 | (variable) |
| 1713 | register Lisp_Object variable; | 1861 | register Lisp_Object variable; |
| 1714 | { | 1862 | { |
| 1715 | register Lisp_Object tem, valcontents, newval; | 1863 | int forwarded; |
| 1864 | union Lisp_Val_Fwd valcontents; | ||
| 1716 | struct Lisp_Symbol *sym; | 1865 | struct Lisp_Symbol *sym; |
| 1866 | struct Lisp_Buffer_Local_Value *blv = NULL; | ||
| 1717 | 1867 | ||
| 1718 | CHECK_SYMBOL (variable); | 1868 | CHECK_SYMBOL (variable); |
| 1719 | sym = indirect_variable (XSYMBOL (variable)); | 1869 | sym = XSYMBOL (variable); |
| 1720 | |||
| 1721 | valcontents = sym->value; | ||
| 1722 | if (sym->constant || KBOARD_OBJFWDP (valcontents) | ||
| 1723 | || BUFFER_OBJFWDP (valcontents)) | ||
| 1724 | error ("Symbol %s may not be frame-local", SDATA (sym->xname)); | ||
| 1725 | 1870 | ||
| 1726 | if (BUFFER_LOCAL_VALUEP (valcontents)) | 1871 | start: |
| 1872 | switch (sym->redirect) | ||
| 1727 | { | 1873 | { |
| 1728 | if (!XBUFFER_LOCAL_VALUE (valcontents)->check_frame) | 1874 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1729 | error ("Symbol %s may not be frame-local", SDATA (sym->xname)); | 1875 | case SYMBOL_PLAINVAL: |
| 1730 | return variable; | 1876 | forwarded = 0; valcontents.value = SYMBOL_VAL (sym); |
| 1877 | if (EQ (valcontents.value, Qunbound)) | ||
| 1878 | valcontents.value = Qnil; | ||
| 1879 | break; | ||
| 1880 | case SYMBOL_LOCALIZED: | ||
| 1881 | if (SYMBOL_BLV (sym)->frame_local) | ||
| 1882 | return variable; | ||
| 1883 | else | ||
| 1884 | error ("Symbol %s may not be frame-local", | ||
| 1885 | SDATA (SYMBOL_NAME (variable))); | ||
| 1886 | case SYMBOL_FORWARDED: | ||
| 1887 | forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym); | ||
| 1888 | if (KBOARD_OBJFWDP (valcontents.fwd) || BUFFER_OBJFWDP (valcontents.fwd)) | ||
| 1889 | error ("Symbol %s may not be frame-local", | ||
| 1890 | SDATA (SYMBOL_NAME (variable))); | ||
| 1891 | break; | ||
| 1892 | default: abort (); | ||
| 1731 | } | 1893 | } |
| 1732 | 1894 | ||
| 1733 | if (EQ (valcontents, Qunbound)) | 1895 | if (sym->constant) |
| 1734 | sym->value = Qnil; | 1896 | error ("Symbol %s may not be frame-local", SDATA (SYMBOL_NAME (variable))); |
| 1735 | tem = Fcons (Qnil, Fsymbol_value (variable)); | 1897 | |
| 1736 | XSETCAR (tem, tem); | 1898 | blv = make_blv (sym, forwarded, valcontents); |
| 1737 | newval = allocate_misc (); | 1899 | blv->frame_local = 1; |
| 1738 | XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value; | 1900 | sym->redirect = SYMBOL_LOCALIZED; |
| 1739 | XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value; | 1901 | SET_SYMBOL_BLV (sym, blv); |
| 1740 | XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil; | ||
| 1741 | XBUFFER_LOCAL_VALUE (newval)->frame = Qnil; | ||
| 1742 | XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0; | ||
| 1743 | XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0; | ||
| 1744 | XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0; | ||
| 1745 | XBUFFER_LOCAL_VALUE (newval)->check_frame = 1; | ||
| 1746 | XBUFFER_LOCAL_VALUE (newval)->cdr = tem; | ||
| 1747 | sym->value = newval; | ||
| 1748 | return variable; | 1902 | return variable; |
| 1749 | } | 1903 | } |
| 1750 | 1904 | ||
| @@ -1755,7 +1909,6 @@ BUFFER defaults to the current buffer. */) | |||
| 1755 | (variable, buffer) | 1909 | (variable, buffer) |
| 1756 | register Lisp_Object variable, buffer; | 1910 | register Lisp_Object variable, buffer; |
| 1757 | { | 1911 | { |
| 1758 | Lisp_Object valcontents; | ||
| 1759 | register struct buffer *buf; | 1912 | register struct buffer *buf; |
| 1760 | struct Lisp_Symbol *sym; | 1913 | struct Lisp_Symbol *sym; |
| 1761 | 1914 | ||
| @@ -1768,29 +1921,46 @@ BUFFER defaults to the current buffer. */) | |||
| 1768 | } | 1921 | } |
| 1769 | 1922 | ||
| 1770 | CHECK_SYMBOL (variable); | 1923 | CHECK_SYMBOL (variable); |
| 1771 | sym = indirect_variable (XSYMBOL (variable)); | 1924 | sym = XSYMBOL (variable); |
| 1772 | XSETSYMBOL (variable, sym); | ||
| 1773 | |||
| 1774 | valcontents = sym->value; | ||
| 1775 | if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1776 | { | ||
| 1777 | Lisp_Object tail, elt; | ||
| 1778 | 1925 | ||
| 1779 | for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) | 1926 | start: |
| 1780 | { | 1927 | switch (sym->redirect) |
| 1781 | elt = XCAR (tail); | ||
| 1782 | if (EQ (variable, XCAR (elt))) | ||
| 1783 | return Qt; | ||
| 1784 | } | ||
| 1785 | } | ||
| 1786 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1787 | { | 1928 | { |
| 1788 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | 1929 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1789 | int idx = PER_BUFFER_IDX (offset); | 1930 | case SYMBOL_PLAINVAL: return Qnil; |
| 1790 | if (idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) | 1931 | case SYMBOL_LOCALIZED: |
| 1791 | return Qt; | 1932 | { |
| 1933 | Lisp_Object tail, elt, tmp; | ||
| 1934 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | ||
| 1935 | XSETBUFFER (tmp, buf); | ||
| 1936 | |||
| 1937 | for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 1938 | { | ||
| 1939 | elt = XCAR (tail); | ||
| 1940 | if (EQ (variable, XCAR (elt))) | ||
| 1941 | { | ||
| 1942 | eassert (!blv->frame_local); | ||
| 1943 | eassert (BLV_FOUND (blv) || !EQ (blv->where, tmp)); | ||
| 1944 | return Qt; | ||
| 1945 | } | ||
| 1946 | } | ||
| 1947 | eassert (!BLV_FOUND (blv) || !EQ (blv->where, tmp)); | ||
| 1948 | return Qnil; | ||
| 1949 | } | ||
| 1950 | case SYMBOL_FORWARDED: | ||
| 1951 | { | ||
| 1952 | union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); | ||
| 1953 | if (BUFFER_OBJFWDP (valcontents)) | ||
| 1954 | { | ||
| 1955 | int offset = XBUFFER_OBJFWD (valcontents)->offset; | ||
| 1956 | int idx = PER_BUFFER_IDX (offset); | ||
| 1957 | if (idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) | ||
| 1958 | return Qt; | ||
| 1959 | } | ||
| 1960 | return Qnil; | ||
| 1961 | } | ||
| 1962 | default: abort (); | ||
| 1792 | } | 1963 | } |
| 1793 | return Qnil; | ||
| 1794 | } | 1964 | } |
| 1795 | 1965 | ||
| 1796 | DEFUN ("local-variable-if-set-p", Flocal_variable_if_set_p, Slocal_variable_if_set_p, | 1966 | DEFUN ("local-variable-if-set-p", Flocal_variable_if_set_p, Slocal_variable_if_set_p, |
| @@ -1804,40 +1974,29 @@ BUFFER defaults to the current buffer. */) | |||
| 1804 | (variable, buffer) | 1974 | (variable, buffer) |
| 1805 | register Lisp_Object variable, buffer; | 1975 | register Lisp_Object variable, buffer; |
| 1806 | { | 1976 | { |
| 1807 | Lisp_Object valcontents; | ||
| 1808 | register struct buffer *buf; | ||
| 1809 | struct Lisp_Symbol *sym; | 1977 | struct Lisp_Symbol *sym; |
| 1810 | 1978 | ||
| 1811 | if (NILP (buffer)) | ||
| 1812 | buf = current_buffer; | ||
| 1813 | else | ||
| 1814 | { | ||
| 1815 | CHECK_BUFFER (buffer); | ||
| 1816 | buf = XBUFFER (buffer); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | CHECK_SYMBOL (variable); | 1979 | CHECK_SYMBOL (variable); |
| 1820 | sym = indirect_variable (XSYMBOL (variable)); | 1980 | sym = XSYMBOL (variable); |
| 1821 | XSETSYMBOL (variable, sym); | ||
| 1822 | |||
| 1823 | valcontents = sym->value; | ||
| 1824 | 1981 | ||
| 1825 | if (BUFFER_OBJFWDP (valcontents)) | 1982 | start: |
| 1826 | /* All these slots become local if they are set. */ | 1983 | switch (sym->redirect) |
| 1827 | return Qt; | ||
| 1828 | else if (BUFFER_LOCAL_VALUEP (valcontents)) | ||
| 1829 | { | 1984 | { |
| 1830 | Lisp_Object tail, elt; | 1985 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; |
| 1831 | if (XBUFFER_LOCAL_VALUE (valcontents)->local_if_set) | 1986 | case SYMBOL_PLAINVAL: return Qnil; |
| 1832 | return Qt; | 1987 | case SYMBOL_LOCALIZED: |
| 1833 | for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail)) | 1988 | { |
| 1834 | { | 1989 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); |
| 1835 | elt = XCAR (tail); | 1990 | if (blv->local_if_set) |
| 1836 | if (EQ (variable, XCAR (elt))) | 1991 | return Qt; |
| 1837 | return Qt; | 1992 | XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ |
| 1838 | } | 1993 | return Flocal_variable_p (variable, buffer); |
| 1994 | } | ||
| 1995 | case SYMBOL_FORWARDED: | ||
| 1996 | /* All BUFFER_OBJFWD slots become local if they are set. */ | ||
| 1997 | return (BUFFER_OBJFWDP (SYMBOL_FWD (sym)) ? Qt : Qnil); | ||
| 1998 | default: abort (); | ||
| 1839 | } | 1999 | } |
| 1840 | return Qnil; | ||
| 1841 | } | 2000 | } |
| 1842 | 2001 | ||
| 1843 | DEFUN ("variable-binding-locus", Fvariable_binding_locus, Svariable_binding_locus, | 2002 | DEFUN ("variable-binding-locus", Fvariable_binding_locus, Svariable_binding_locus, |
| @@ -1849,30 +2008,40 @@ If the current binding is global (the default), the value is nil. */) | |||
| 1849 | (variable) | 2008 | (variable) |
| 1850 | register Lisp_Object variable; | 2009 | register Lisp_Object variable; |
| 1851 | { | 2010 | { |
| 1852 | Lisp_Object valcontents; | ||
| 1853 | struct Lisp_Symbol *sym; | 2011 | struct Lisp_Symbol *sym; |
| 1854 | 2012 | ||
| 1855 | CHECK_SYMBOL (variable); | 2013 | CHECK_SYMBOL (variable); |
| 1856 | sym = indirect_variable (XSYMBOL (variable)); | 2014 | sym = XSYMBOL (variable); |
| 1857 | 2015 | ||
| 1858 | /* Make sure the current binding is actually swapped in. */ | 2016 | /* Make sure the current binding is actually swapped in. */ |
| 1859 | find_symbol_value (variable); | 2017 | find_symbol_value (variable); |
| 1860 | 2018 | ||
| 1861 | valcontents = sym->value; | 2019 | start: |
| 1862 | 2020 | switch (sym->redirect) | |
| 1863 | if (BUFFER_LOCAL_VALUEP (valcontents) | ||
| 1864 | || BUFFER_OBJFWDP (valcontents)) | ||
| 1865 | { | 2021 | { |
| 2022 | case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; | ||
| 2023 | case SYMBOL_PLAINVAL: return Qnil; | ||
| 2024 | case SYMBOL_FORWARDED: | ||
| 2025 | { | ||
| 2026 | union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); | ||
| 2027 | if (KBOARD_OBJFWDP (valcontents)) | ||
| 2028 | return Fframe_terminal (Fselected_frame ()); | ||
| 2029 | else if (!BUFFER_OBJFWDP (valcontents)) | ||
| 2030 | return Qnil; | ||
| 2031 | } | ||
| 2032 | /* FALLTHROUGH */ | ||
| 2033 | case SYMBOL_LOCALIZED: | ||
| 1866 | /* For a local variable, record both the symbol and which | 2034 | /* For a local variable, record both the symbol and which |
| 1867 | buffer's or frame's value we are saving. */ | 2035 | buffer's or frame's value we are saving. */ |
| 1868 | if (!NILP (Flocal_variable_p (variable, Qnil))) | 2036 | if (!NILP (Flocal_variable_p (variable, Qnil))) |
| 1869 | return Fcurrent_buffer (); | 2037 | return Fcurrent_buffer (); |
| 1870 | else if (BUFFER_LOCAL_VALUEP (valcontents) | 2038 | else if (sym->redirect == SYMBOL_LOCALIZED |
| 1871 | && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame) | 2039 | && BLV_FOUND (SYMBOL_BLV (sym))) |
| 1872 | return XBUFFER_LOCAL_VALUE (valcontents)->frame; | 2040 | return SYMBOL_BLV (sym)->where; |
| 2041 | else | ||
| 2042 | return Qnil; | ||
| 2043 | default: abort (); | ||
| 1873 | } | 2044 | } |
| 1874 | |||
| 1875 | return Qnil; | ||
| 1876 | } | 2045 | } |
| 1877 | 2046 | ||
| 1878 | /* This code is disabled now that we use the selected frame to return | 2047 | /* This code is disabled now that we use the selected frame to return |