comparison src/buffer.c @ 107984:bef5d1738c0b

Make variable forwarding explicit rather the using special values. Basically, this makes the structure of buffer-local values and object forwarding explicit in the type of Lisp_Symbols rather than use special Lisp_Objects for that. This tends to lead to slightly more verbose code, but is more C-like, simpler, and makes it easier to make sure we handled all cases, among other things by letting the compiler help us check it. * lisp.h (enum Lisp_Misc_Type, union Lisp_Misc): Removing forwarding objects. (enum Lisp_Fwd_Type, enum symbol_redirect, union Lisp_Fwd): New types. (struct Lisp_Symbol): Make the various forms of variable-forwarding explicit rather than hiding them inside Lisp_Object "values". (XFWDTYPE): New macro. (XINTFWD, XBOOLFWD, XOBJFWD, XKBOARD_OBJFWD): Redefine. (XBUFFER_LOCAL_VALUE): Remove. (SYMBOL_VAL, SYMBOL_ALIAS, SYMBOL_BLV, SYMBOL_FWD, SET_SYMBOL_VAL) (SET_SYMBOL_ALIAS, SET_SYMBOL_BLV, SET_SYMBOL_FWD): New macros. (SYMBOL_VALUE, SET_SYMBOL_VALUE): Remove. (struct Lisp_Intfwd, struct Lisp_Boolfwd, struct Lisp_Objfwd) (struct Lisp_Buffer_Objfwd, struct Lisp_Kboard_Objfwd): Remove the Lisp_Misc_* header. (struct Lisp_Buffer_Local_Value): Redefine. (BLV_FOUND, SET_BLV_FOUND, BLV_VALUE, SET_BLV_VALUE): New macros. (struct Lisp_Misc_Any): Add filler to get the right size. (struct Lisp_Free): Use struct Lisp_Misc_Any rather than struct Lisp_Intfwd. (DEFVAR_LISP, DEFVAR_LISP_NOPRO, DEFVAR_BOOL, DEFVAR_INT) (DEFVAR_KBOARD): Allocate a forwarding object. * data.c (do_blv_forwarding, store_blv_forwarding): New macros. (let_shadows_global_binding_p): New function. (union Lisp_Val_Fwd): New type. (make_blv): New function. (swap_in_symval_forwarding, indirect_variable, do_symval_forwarding) (store_symval_forwarding, swap_in_global_binding, Fboundp) (swap_in_symval_forwarding, find_symbol_value, Fset) (let_shadows_buffer_binding_p, set_internal, default_value) (Fset_default, Fmake_variable_buffer_local, Fmake_local_variable) (Fkill_local_variable, Fmake_variable_frame_local) (Flocal_variable_p, Flocal_variable_if_set_p) (Fvariable_binding_locus): * xdisp.c (select_frame_for_redisplay): * lread.c (Fintern, Funintern, init_obarray, defvar_int) (defvar_bool, defvar_lisp_nopro, defvar_lisp, defvar_kboard): * frame.c (store_frame_param): * eval.c (Fdefvaralias, Fuser_variable_p, specbind, unbind_to): * bytecode.c (Fbyte_code) <varref, varset>: Adapt to the new symbol value structure. * buffer.c (PER_BUFFER_SYMBOL): Move from buffer.h. (clone_per_buffer_values): Only adjust markers into the current buffer. (reset_buffer_local_variables): PER_BUFFER_IDX is never -2. (Fbuffer_local_value, set_buffer_internal_1) (swap_out_buffer_local_variables): Adapt to the new symbol value structure. (DEFVAR_PER_BUFFER): Allocate a Lisp_Buffer_Objfwd object. (defvar_per_buffer): Take a new arg for the fwd object. (buffer_lisp_local_variables): Return a proper alist (different fix for bug#4138). * alloc.c (Fmake_symbol): Use SET_SYMBOL_VAL. (Fgarbage_collect): Don't handle buffer_defaults specially. (mark_object): Handle new symbol value structure rather than the old special Lisp_Misc_* objects. (gc_sweep) <symbols>: Free also the buffer-local-value objects. * term.c (set_tty_color_mode): * bidi.c (bidi_initialize): Don't access the ->value field directly. * buffer.h (PER_BUFFER_VAR_OFFSET): Don't bother with a buffer_local_flags. * print.c (print_object): Get rid of impossible forwarding objects.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 19 Apr 2010 21:50:52 -0400
parents 688679bd79f5
children 4b71850034e6
comparison
equal deleted inserted replaced
107983:781bff25a517 107984:bef5d1738c0b
76 76
77 If a slot in this structure is -1, then even though there may 77 If a slot in this structure is -1, then even though there may
78 be a DEFVAR_PER_BUFFER for the slot, there is no default value for it; 78 be a DEFVAR_PER_BUFFER for the slot, there is no default value for it;
79 and the corresponding slot in buffer_defaults is not used. 79 and the corresponding slot in buffer_defaults is not used.
80 80
81 If a slot is -2, then there is no DEFVAR_PER_BUFFER for it,
82 but there is a default value which is copied into each buffer.
83
84 If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is 81 If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
85 zero, that is a bug */ 82 zero, that is a bug */
86 83
87 struct buffer buffer_local_flags; 84 struct buffer buffer_local_flags;
88 85
91 88
92 DECL_ALIGN (struct buffer, buffer_local_symbols); 89 DECL_ALIGN (struct buffer, buffer_local_symbols);
93 90
94 /* A Lisp_Object pointer to the above, used for staticpro */ 91 /* A Lisp_Object pointer to the above, used for staticpro */
95 static Lisp_Object Vbuffer_local_symbols; 92 static Lisp_Object Vbuffer_local_symbols;
93
94 /* Return the symbol of the per-buffer variable at offset OFFSET in
95 the buffer structure. */
96
97 #define PER_BUFFER_SYMBOL(OFFSET) \
98 (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_symbols))
96 99
97 /* Flags indicating which built-in buffer-local variables 100 /* Flags indicating which built-in buffer-local variables
98 are permanent locals. */ 101 are permanent locals. */
99 static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; 102 static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS];
100 103
505 /* Don't touch the `name' which should be unique for every buffer. */ 508 /* Don't touch the `name' which should be unique for every buffer. */
506 if (offset == PER_BUFFER_VAR_OFFSET (name)) 509 if (offset == PER_BUFFER_VAR_OFFSET (name))
507 continue; 510 continue;
508 511
509 obj = PER_BUFFER_VALUE (from, offset); 512 obj = PER_BUFFER_VALUE (from, offset);
510 if (MARKERP (obj)) 513 if (MARKERP (obj) && XMARKER (obj)->buffer == from)
511 { 514 {
512 struct Lisp_Marker *m = XMARKER (obj); 515 struct Lisp_Marker *m = XMARKER (obj);
513 obj = Fmake_marker (); 516 obj = Fmake_marker ();
514 XMARKER (obj)->insertion_type = m->insertion_type; 517 XMARKER (obj)->insertion_type = m->insertion_type;
515 set_marker_both (obj, to_buffer, m->charpos, m->bytepos); 518 set_marker_both (obj, to_buffer, m->charpos, m->bytepos);
768 b->local_var_alist = Qnil; 771 b->local_var_alist = Qnil;
769 else 772 else
770 { 773 {
771 Lisp_Object tmp, prop, last = Qnil; 774 Lisp_Object tmp, prop, last = Qnil;
772 for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp)) 775 for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp))
773 if (CONSP (XCAR (tmp)) 776 if (!NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
774 && SYMBOLP (XCAR (XCAR (tmp)))
775 && !NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
776 { 777 {
777 /* If permanent-local, keep it. */ 778 /* If permanent-local, keep it. */
778 last = tmp; 779 last = tmp;
779 if (EQ (prop, Qpermanent_local_hook)) 780 if (EQ (prop, Qpermanent_local_hook))
780 { 781 {
820 offset += sizeof (Lisp_Object)) 821 offset += sizeof (Lisp_Object))
821 { 822 {
822 int idx = PER_BUFFER_IDX (offset); 823 int idx = PER_BUFFER_IDX (offset);
823 if ((idx > 0 824 if ((idx > 0
824 && (permanent_too 825 && (permanent_too
825 || buffer_permanent_local_flags[idx] == 0)) 826 || buffer_permanent_local_flags[idx] == 0)))
826 /* Is -2 used anywhere? */
827 || idx == -2)
828 PER_BUFFER_VALUE (b, offset) = PER_BUFFER_DEFAULT (offset); 827 PER_BUFFER_VALUE (b, offset) = PER_BUFFER_DEFAULT (offset);
829 } 828 }
830 } 829 }
831 830
832 /* We split this away from generate-new-buffer, because rename-buffer 831 /* We split this away from generate-new-buffer, because rename-buffer
936 struct Lisp_Symbol *sym; 935 struct Lisp_Symbol *sym;
937 936
938 CHECK_SYMBOL (variable); 937 CHECK_SYMBOL (variable);
939 CHECK_BUFFER (buffer); 938 CHECK_BUFFER (buffer);
940 buf = XBUFFER (buffer); 939 buf = XBUFFER (buffer);
941 940 sym = XSYMBOL (variable);
942 sym = indirect_variable (XSYMBOL (variable)); 941
943 XSETSYMBOL (variable, sym); 942 start:
944 943 switch (sym->redirect)
945 /* Look in local_var_list */ 944 {
946 result = Fassoc (variable, buf->local_var_alist); 945 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
947 if (NILP (result)) 946 case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break;
948 { 947 case SYMBOL_LOCALIZED:
949 int offset, idx; 948 { /* Look in local_var_alist. */
950 int found = 0; 949 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
951 950 XSETSYMBOL (variable, sym); /* Update In case of aliasing. */
952 /* Look in special slots */ 951 result = Fassoc (variable, buf->local_var_alist);
953 /* buffer-local Lisp variables start at `undo_list', 952 if (!NILP (result))
954 tho only the ones from `name' on are GC'd normally. */ 953 {
955 for (offset = PER_BUFFER_VAR_OFFSET (undo_list); 954 if (blv->fwd)
956 offset < sizeof (struct buffer); 955 { /* What binding is loaded right now? */
957 /* sizeof EMACS_INT == sizeof Lisp_Object */ 956 Lisp_Object current_alist_element = blv->valcell;
958 offset += (sizeof (EMACS_INT))) 957
959 { 958 /* The value of the currently loaded binding is not
960 idx = PER_BUFFER_IDX (offset); 959 stored in it, but rather in the realvalue slot.
961 if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx)) 960 Store that value into the binding it belongs to
962 && SYMBOLP (PER_BUFFER_SYMBOL (offset)) 961 in case that is the one we are about to use. */
963 && EQ (PER_BUFFER_SYMBOL (offset), variable)) 962
964 { 963 XSETCDR (current_alist_element,
965 result = PER_BUFFER_VALUE (buf, offset); 964 do_symval_forwarding (blv->fwd));
966 found = 1; 965 }
967 break; 966 /* Now get the (perhaps updated) value out of the binding. */
968 } 967 result = XCDR (result);
969 } 968 }
970 969 else
971 if (!found) 970 result = Fdefault_value (variable);
972 result = Fdefault_value (variable); 971 break;
973 } 972 }
974 else 973 case SYMBOL_FORWARDED:
975 { 974 {
976 Lisp_Object valcontents; 975 union Lisp_Fwd *fwd = SYMBOL_FWD (sym);
977 Lisp_Object current_alist_element; 976 if (BUFFER_OBJFWDP (fwd))
978 977 result = PER_BUFFER_VALUE (buf, XBUFFER_OBJFWD (fwd)->offset);
979 /* What binding is loaded right now? */ 978 else
980 valcontents = sym->value; 979 result = Fdefault_value (variable);
981 current_alist_element 980 break;
982 = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr); 981 }
983 982 default: abort ();
984 /* The value of the currently loaded binding is not
985 stored in it, but rather in the realvalue slot.
986 Store that value into the binding it belongs to
987 in case that is the one we are about to use. */
988
989 Fsetcdr (current_alist_element,
990 do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
991
992 /* Now get the (perhaps updated) value out of the binding. */
993 result = XCDR (result);
994 } 983 }
995 984
996 if (!EQ (result, Qunbound)) 985 if (!EQ (result, Qunbound))
997 return result; 986 return result;
998 987
1023 val = find_symbol_value (XCAR (elt)); 1012 val = find_symbol_value (XCAR (elt));
1024 /* Use the current buffer value only if buf is the current buffer. */ 1013 /* Use the current buffer value only if buf is the current buffer. */
1025 if (buf != current_buffer) 1014 if (buf != current_buffer)
1026 val = XCDR (elt); 1015 val = XCDR (elt);
1027 1016
1028 /* If symbol is unbound, put just the symbol in the list. */ 1017 result = Fcons (Fcons (XCAR (elt), val), result);
1029 if (EQ (val, Qunbound))
1030 result = Fcons (XCAR (elt), result);
1031 /* Otherwise, put (symbol . value) in the list. */
1032 else
1033 result = Fcons (Fcons (XCAR (elt), val), result);
1034 } 1018 }
1035 1019
1036 return result; 1020 return result;
1037 } 1021 }
1038 1022
1860 void 1844 void
1861 set_buffer_internal_1 (b) 1845 set_buffer_internal_1 (b)
1862 register struct buffer *b; 1846 register struct buffer *b;
1863 { 1847 {
1864 register struct buffer *old_buf; 1848 register struct buffer *old_buf;
1865 register Lisp_Object tail, valcontents; 1849 register Lisp_Object tail;
1866 Lisp_Object tem;
1867 1850
1868 #ifdef USE_MMAP_FOR_BUFFERS 1851 #ifdef USE_MMAP_FOR_BUFFERS
1869 if (b->text->beg == NULL) 1852 if (b->text->beg == NULL)
1870 enlarge_buffer_text (b, 0); 1853 enlarge_buffer_text (b, 0);
1871 #endif /* USE_MMAP_FOR_BUFFERS */ 1854 #endif /* USE_MMAP_FOR_BUFFERS */
1933 } 1916 }
1934 1917
1935 /* Look down buffer's list of local Lisp variables 1918 /* Look down buffer's list of local Lisp variables
1936 to find and update any that forward into C variables. */ 1919 to find and update any that forward into C variables. */
1937 1920
1938 for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail)) 1921 do
1939 { 1922 {
1940 if (CONSP (XCAR (tail)) 1923 for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
1941 && SYMBOLP (XCAR (XCAR (tail))) 1924 {
1942 && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))), 1925 Lisp_Object var = XCAR (XCAR (tail));
1943 (BUFFER_LOCAL_VALUEP (valcontents))) 1926 struct Lisp_Symbol *sym = XSYMBOL (var);
1944 && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue, 1927 if (sym->redirect == SYMBOL_LOCALIZED /* Just to be sure. */
1945 (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem)))) 1928 && SYMBOL_BLV (sym)->fwd)
1946 /* Just reference the variable to cause it to become set for 1929 /* Just reference the variable
1947 this buffer. */ 1930 to cause it to become set for this buffer. */
1948 Fsymbol_value (XCAR (XCAR (tail))); 1931 Fsymbol_value (var);
1949 } 1932 }
1950 1933 }
1951 /* Do the same with any others that were local to the previous buffer */ 1934 /* Do the same with any others that were local to the previous buffer */
1952 1935 while (b != old_buf && (b = old_buf, b));
1953 if (old_buf)
1954 for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
1955 {
1956 if (CONSP (tail)
1957 && SYMBOLP (XCAR (XCAR (tail)))
1958 && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))),
1959 (BUFFER_LOCAL_VALUEP (valcontents)))
1960 && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
1961 (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
1962 /* Just reference the variable to cause it to become set for
1963 this buffer. */
1964 Fsymbol_value (XCAR (XCAR (tail)));
1965 }
1966 } 1936 }
1967 1937
1968 /* Switch to buffer B temporarily for redisplay purposes. 1938 /* Switch to buffer B temporarily for redisplay purposes.
1969 This avoids certain things that don't need to be done within redisplay. */ 1939 This avoids certain things that don't need to be done within redisplay. */
1970 1940
2675 2645
2676 static void 2646 static void
2677 swap_out_buffer_local_variables (b) 2647 swap_out_buffer_local_variables (b)
2678 struct buffer *b; 2648 struct buffer *b;
2679 { 2649 {
2680 Lisp_Object oalist, alist, sym, buffer; 2650 Lisp_Object oalist, alist, buffer;
2681 2651
2682 XSETBUFFER (buffer, b); 2652 XSETBUFFER (buffer, b);
2683 oalist = b->local_var_alist; 2653 oalist = b->local_var_alist;
2684 2654
2685 for (alist = oalist; CONSP (alist); alist = XCDR (alist)) 2655 for (alist = oalist; CONSP (alist); alist = XCDR (alist))
2686 { 2656 {
2687 if (CONSP (XCAR (alist)) 2657 Lisp_Object sym = XCAR (XCAR (alist));
2688 && (sym = XCAR (XCAR (alist)), SYMBOLP (sym)) 2658 eassert (XSYMBOL (sym)->redirect == SYMBOL_LOCALIZED);
2689 /* Need not do anything if some other buffer's binding is 2659 /* Need not do anything if some other buffer's binding is
2690 now encached. */ 2660 now encached. */
2691 && EQ (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer, 2661 if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
2692 buffer))
2693 { 2662 {
2694 /* Symbol is set up for this buffer's old local value: 2663 /* Symbol is set up for this buffer's old local value:
2695 swap it out! */ 2664 swap it out! */
2696 swap_in_global_binding (sym); 2665 swap_in_global_binding (XSYMBOL (sym));
2697 } 2666 }
2698 } 2667 }
2699 } 2668 }
2700 2669
2701 /* Find all the overlays in the current buffer that contain position POS. 2670 /* Find all the overlays in the current buffer that contain position POS.
5160 bzero (buffer_permanent_local_flags, sizeof buffer_permanent_local_flags); 5129 bzero (buffer_permanent_local_flags, sizeof buffer_permanent_local_flags);
5161 5130
5162 /* Make sure all markable slots in buffer_defaults 5131 /* Make sure all markable slots in buffer_defaults
5163 are initialized reasonably, so mark_buffer won't choke. */ 5132 are initialized reasonably, so mark_buffer won't choke. */
5164 reset_buffer (&buffer_defaults); 5133 reset_buffer (&buffer_defaults);
5134 eassert (EQ (buffer_defaults.name, make_number (0)));
5165 reset_buffer_local_variables (&buffer_defaults, 1); 5135 reset_buffer_local_variables (&buffer_defaults, 1);
5136 eassert (EQ (buffer_local_symbols.name, make_number (0)));
5166 reset_buffer (&buffer_local_symbols); 5137 reset_buffer (&buffer_local_symbols);
5167 reset_buffer_local_variables (&buffer_local_symbols, 1); 5138 reset_buffer_local_variables (&buffer_local_symbols, 1);
5168 /* Prevent GC from getting confused. */ 5139 /* Prevent GC from getting confused. */
5169 buffer_defaults.text = &buffer_defaults.own_text; 5140 buffer_defaults.text = &buffer_defaults.own_text;
5170 buffer_local_symbols.text = &buffer_local_symbols.own_text; 5141 buffer_local_symbols.text = &buffer_local_symbols.own_text;
5419 /* Similar to defvar_lisp but define a variable whose value is the Lisp 5390 /* Similar to defvar_lisp but define a variable whose value is the Lisp
5420 Object stored in the current buffer. address is the address of the slot 5391 Object stored in the current buffer. address is the address of the slot
5421 in the buffer that is current now. */ 5392 in the buffer that is current now. */
5422 5393
5423 /* TYPE is nil for a general Lisp variable. 5394 /* TYPE is nil for a general Lisp variable.
5424 An integer specifies a type; then only LIsp values 5395 An integer specifies a type; then only Lisp values
5425 with that type code are allowed (except that nil is allowed too). 5396 with that type code are allowed (except that nil is allowed too).
5426 LNAME is the LIsp-level variable name. 5397 LNAME is the Lisp-level variable name.
5427 VNAME is the name of the buffer slot. 5398 VNAME is the name of the buffer slot.
5428 DOC is a dummy where you write the doc string as a comment. */ 5399 DOC is a dummy where you write the doc string as a comment. */
5429 #define DEFVAR_PER_BUFFER(lname, vname, type, doc) \ 5400 #define DEFVAR_PER_BUFFER(lname, vname, type, doc) \
5430 defvar_per_buffer (lname, vname, type, 0) 5401 do { \
5402 static struct Lisp_Buffer_Objfwd bo_fwd; \
5403 defvar_per_buffer (&bo_fwd, lname, vname, type, 0); \
5404 } while (0)
5431 5405
5432 static void 5406 static void
5433 defvar_per_buffer (namestring, address, type, doc) 5407 defvar_per_buffer (bo_fwd, namestring, address, type, doc)
5408 struct Lisp_Buffer_Objfwd *bo_fwd;
5434 char *namestring; 5409 char *namestring;
5435 Lisp_Object *address; 5410 Lisp_Object *address;
5436 Lisp_Object type; 5411 Lisp_Object type;
5437 char *doc; 5412 char *doc;
5438 { 5413 {
5439 Lisp_Object sym, val; 5414 struct Lisp_Symbol *sym;
5440 int offset; 5415 int offset;
5441 5416
5442 sym = intern (namestring); 5417 sym = XSYMBOL (intern (namestring));
5443 val = allocate_misc ();
5444 offset = (char *)address - (char *)current_buffer; 5418 offset = (char *)address - (char *)current_buffer;
5445 5419
5446 XMISCTYPE (val) = Lisp_Misc_Buffer_Objfwd; 5420 bo_fwd->type = Lisp_Fwd_Buffer_Obj;
5447 XBUFFER_OBJFWD (val)->offset = offset; 5421 bo_fwd->offset = offset;
5448 XBUFFER_OBJFWD (val)->slottype = type; 5422 bo_fwd->slottype = type;
5449 SET_SYMBOL_VALUE (sym, val); 5423 sym->redirect = SYMBOL_FORWARDED;
5450 PER_BUFFER_SYMBOL (offset) = sym; 5424 {
5425 /* I tried to do the job without a cast, but it seems impossible.
5426 union Lisp_Fwd *fwd; &(fwd->u_buffer_objfwd) = bo_fwd; */
5427 SET_SYMBOL_FWD (sym, (union Lisp_Fwd *)bo_fwd);
5428 }
5429 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym);
5451 5430
5452 if (PER_BUFFER_IDX (offset) == 0) 5431 if (PER_BUFFER_IDX (offset) == 0)
5453 /* Did a DEFVAR_PER_BUFFER without initializing the corresponding 5432 /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
5454 slot of buffer_local_flags */ 5433 slot of buffer_local_flags */
5455 abort (); 5434 abort ();