aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mackenzie2021-11-29 11:19:31 +0000
committerAlan Mackenzie2021-11-29 11:19:31 +0000
commit368570b3fd09d03ac5b9276d1ca85ae813c3f385 (patch)
tree4d81fdc1a866120157147226c35597073592722d /src
parent9721dcf2754ebad28ac60a9d3152fd26e4c652c4 (diff)
downloademacs-368570b3fd09d03ac5b9276d1ca85ae813c3f385.tar.gz
emacs-368570b3fd09d03ac5b9276d1ca85ae813c3f385.zip
First commit of scratch/correct-warning-pos.
This branch is intended to generate correct position information in warning and error messages from the byte compiler, and is intended thereby to fix bugs It introduces a new mechanism, the symbol with position. This is taken over from the previous git branch scratch/accurate-warning-pos which was abandoned for being too slow. The main difference in the current branch is that the symbol `nil' is never given a position, thus speeding up NILP markedly. * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand) (byte-optimize-form-code-walker, byte-optimize-let-form, byte-optimize-while) (byte-optimize-apply): Use byte-compile-warn-x in place of byte-compile-warn. * lisp/emacs-lisp/bytecomp.el (byte-compile--form-stack): New variable. (byte-compile-strip-s-p-1, byte-compile-strip-symbol-positions): New functions. (byte-compile-recurse-toplevel, byte-compile-initial-macro-environment) (byte-compile-preprocess, byte-compile-macroexpand-declare-function): Bind print-symbols-bare to non-nil. (byte-compile--first-symbol, byte-compile--warning-source-offset): New functions. (byte-compile-warning-prefix): Modify to output two sets of position information, the old (incorrect) set and the new set. (byte-compile-warn): Strip positions from symbols before outputting. (byte-compile-warn-x): New function which outputs a correct position supplied in an argument. (byte-compile-warn-obsolete, byte-compile-emit-callargs-warn) (byte-compile-format-warn, byte-compile-nogroup-warn) (byte-compile-arglist-warn, byte-compile-docstring-length-warn) (byte-compile-warn-about-unresolved-functions, byte-compile-file) (byte-compile--check-prefixed-var, byte-compile--declare-var) (byte-compile-file-form-defvar-function, byte-compile-file-form-defmumble) (byte-compile-check-lambda-list, byte-compile--warn-lexical-dynamic) (byte-compile-lambda, byte-compile-form, byte-compile-normal-call) (byte-compile-check-variable, byte-compile-free-vars-warn) (byte-compile-subr-wrong-args, byte-compile-fset, byte-compile-set-default) (byte-compile-condition-case, byte-compile-save-excursion) (byte-compile-defvar, byte-compile-autoload) (byte-compile-make-variable-buffer-local, byte-compile-define-symbol-prop) (byte-compile-define-keymap): Replace byte-compile-warn with byte-compile-warn-x. (byte-compile-file, compile-defun): Bind symbols-with-pos-enabled to non-nil. (compile-defun, byte-compile-from-buffer): Use `read-positioning-symbols' rather than plain `read'. (byte-compile-toplevel-file-form, byte-compile-form): Dynamically bind byte-compile--form-stack. (byte-compile-file-form-autoload, byte-compile-file-form-defvar) (byte-compile-file-form-make-obsolete, byte-compile-lambda) (byte-compile-push-constant, byte-compile-cond-jump-table) (byte-compile-define-keymap, byte-compile-annotate-call-tree): Strip positions from symbols where they are unwanted. (byte-compile-file-form-defvar): Strip positions from symbols using `bare-symbol'. (byte-compile-file-form-defmumble): New variable bare-name, a version of name without its position. (byte-compile-lambda): Similarly, new variable bare-arglist. (byte-compile-free-vars-warn): New argument arg supplying position information to byte-compile-warn-x. (byte-compile-push-constant): Manipulation of symbol positions. (display-call-tree): Strip positions from symbols. * lisp/emacs-lisp/cconv.el (cconv-convert, cconv--analyze-use) (cconv--analyze-function, cconv-analyze-form): Replace use of byte-compile-warn with byte-compile-warn-x. * lisp/emacs-lisp/cl-generic.el (cl-defmethod): New variable org-name which will supply position information to a new macroexp-warn-and-return. * lisp/emacs-lisp/cl-macs.el (cl-macs--strip-s-p-1) (cl-macs--strip-symbol-positions): New functions to strip positions from symbols in an expression. These duplicaate similarly named functions in bytecomp.el. * lisp/emacs-lisp/macroexpand.el (macroexp--warn-wrap): Calls byte-compile-warn-x in place of byte-compile-warn. (macroexp-warn-and-return): Commented out new position parameter _arg. * src/.gdbinit: Add in code to handle symbols with position. * src/alloc.c (XPNTR, set_symbol_name, valid_lisp_object_p, purecopy) (mark_char_table, mark_object, survives_gc_p, symbol_uses_obj): Use BARE_SYMBOL_P and XBARE_SYMBOL in place of the former SYMBOLP and XSYMBOL. (build_symbol_with_pos): New function. (Fgarbage_collect): Bind Qsymbols_with_pos_enabled to nil around the call to garbage_collect. * src/data.c (Ftype_of): Add case for PVEC_SYMBOL_WITH_POS. (Fbare_symbol_p, Fsymbol_with_pos_p, Fbare_symbol, Fsymbol_with_pos_pos) (Fposition_symbol): New functions. (symbols_with_pos_enabled): New boolean variable. * src/fns.c (internal_equal, hash_lookup): Handle symbols with position. * src/keyboard.c (recursive_edit_1): Bind Qsymbols_with_pos_enabled and Qprint_symbols_bare to nil. * src/lisp.h (lisp_h_PSEUDOVECTORP): New macro. (lisp_h_BASE_EQ): New name for the former lisp_h_EQ. (lisp_h_EQ): Extended to handle symbols with position. (lisp_h_NILP): Now uses BASE_EQ rather than EQ. (lisp_h_SYMBOL_WITH_POS_P, lisp_h_BARE_SYMBOL_P): New macros. (lisp_h_SYMBOLP): Redefined to handle symbols with position. (BARE_SYMBOL_P, BASE_EQ): New macros. (SYMBOLP (macro)): Removed. (SYMBOLP (function), XSYMBOL, make_lisp_symbol, builtin_lisp_symbol) (c_symbol_p): Moved to later in file. (struct Lisp_Symbol_With_Pos): New data type. (pvec_type): PVEC_SYMBOL_WITH_POS: New type code. (PSEUDOVECTORP): Redefined to use the lisp_h_PSEUDOVECTORP. (BARE_SYMBOL_P, SYMBOL_WITH_POS_P, SYMBOLP, XSYMBOL_WITH_POS, XBARE_SYMBOL) (XSYMBOL, make_lisp_symbol, builtin_lisp_symbol, c_symbol_p, CHECK_SYMBOL) (BASE_EQ): New functions, or functions moved from earlier in the file. (SYMBOL_WITH_POS_SYM, SYMBOL_WITH_POS_POS): New INLINE functions. * src/lread.c (read0, read1, read_list, read_vector, read_internal_start) (list2): Add a new bool parameter locate_syms. (Fread_positioning_symbols): New function. (Fread_from_string, read_internal_start, read0, read1, read_list): Pass around suitable values for locate_syms. (read1): Build symbols with position when locate_syms is true. * src/print.c (print_vectorlike): Add handling for PVEC_SYMBOL_WITH_POS. (print_object): Replace EQ with BASE_EQ. (print_symbols_bare): New boolean variable.
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit12
-rw-r--r--src/alloc.c40
-rw-r--r--src/data.c81
-rw-r--r--src/fns.c12
-rw-r--r--src/keyboard.c2
-rw-r--r--src/lisp.h216
-rw-r--r--src/lread.c126
-rw-r--r--src/print.c33
8 files changed, 398 insertions, 124 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index f74e295f7ea..9f2a86b779d 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -746,6 +746,15 @@ Print $ as a overlay pointer.
746This command assumes that $ is an Emacs Lisp overlay value. 746This command assumes that $ is an Emacs Lisp overlay value.
747end 747end
748 748
749define xsymwithpos
750 xgetptr $
751 print (struct Lisp_Symbol_With_Pos *) $ptr
752end
753document xsymwithpos
754Print $ as a symbol with position.
755This command assumes that $ is an Emacs Lisp symbol with position value.
756end
757
749define xsymbol 758define xsymbol
750 set $sym = $ 759 set $sym = $
751 xgetsym $sym 760 xgetsym $sym
@@ -1011,6 +1020,9 @@ define xpr
1011 if $vec == PVEC_OVERLAY 1020 if $vec == PVEC_OVERLAY
1012 xoverlay 1021 xoverlay
1013 end 1022 end
1023 if $vec == PVEC_SYMBOL_WITH_POS
1024 xsymwithpos
1025 end
1014 if $vec == PVEC_PROCESS 1026 if $vec == PVEC_PROCESS
1015 xprocess 1027 xprocess
1016 end 1028 end
diff --git a/src/alloc.c b/src/alloc.c
index f8908c91dba..0d69f23048a 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -591,7 +591,7 @@ pointer_align (void *ptr, int alignment)
591static ATTRIBUTE_NO_SANITIZE_UNDEFINED void * 591static ATTRIBUTE_NO_SANITIZE_UNDEFINED void *
592XPNTR (Lisp_Object a) 592XPNTR (Lisp_Object a)
593{ 593{
594 return (SYMBOLP (a) 594 return (BARE_SYMBOL_P (a)
595 ? (char *) lispsym + (XLI (a) - LISP_WORD_TAG (Lisp_Symbol)) 595 ? (char *) lispsym + (XLI (a) - LISP_WORD_TAG (Lisp_Symbol))
596 : (char *) XLP (a) - (XLI (a) & ~VALMASK)); 596 : (char *) XLP (a) - (XLI (a) & ~VALMASK));
597} 597}
@@ -3598,13 +3598,13 @@ static struct Lisp_Symbol *symbol_free_list;
3598static void 3598static void
3599set_symbol_name (Lisp_Object sym, Lisp_Object name) 3599set_symbol_name (Lisp_Object sym, Lisp_Object name)
3600{ 3600{
3601 XSYMBOL (sym)->u.s.name = name; 3601 XBARE_SYMBOL (sym)->u.s.name = name;
3602} 3602}
3603 3603
3604void 3604void
3605init_symbol (Lisp_Object val, Lisp_Object name) 3605init_symbol (Lisp_Object val, Lisp_Object name)
3606{ 3606{
3607 struct Lisp_Symbol *p = XSYMBOL (val); 3607 struct Lisp_Symbol *p = XBARE_SYMBOL (val);
3608 set_symbol_name (val, name); 3608 set_symbol_name (val, name);
3609 set_symbol_plist (val, Qnil); 3609 set_symbol_plist (val, Qnil);
3610 p->u.s.redirect = SYMBOL_PLAINVAL; 3610 p->u.s.redirect = SYMBOL_PLAINVAL;
@@ -3667,6 +3667,21 @@ make_misc_ptr (void *a)
3667 return make_lisp_ptr (p, Lisp_Vectorlike); 3667 return make_lisp_ptr (p, Lisp_Vectorlike);
3668} 3668}
3669 3669
3670/* Return a new symbol with position with the specified SYMBOL and POSITION. */
3671Lisp_Object
3672build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position)
3673{
3674 Lisp_Object val;
3675 struct Lisp_Symbol_With_Pos *p
3676 = (struct Lisp_Symbol_With_Pos *) allocate_vector (2);
3677 XSETVECTOR (val, p);
3678 XSETPVECTYPESIZE (XVECTOR (val), PVEC_SYMBOL_WITH_POS, 2, 0);
3679 p->sym = symbol;
3680 p->pos = position;
3681
3682 return val;
3683}
3684
3670/* Return a new overlay with specified START, END and PLIST. */ 3685/* Return a new overlay with specified START, END and PLIST. */
3671 3686
3672Lisp_Object 3687Lisp_Object
@@ -5210,7 +5225,7 @@ valid_lisp_object_p (Lisp_Object obj)
5210 if (PURE_P (p)) 5225 if (PURE_P (p))
5211 return 1; 5226 return 1;
5212 5227
5213 if (SYMBOLP (obj) && c_symbol_p (p)) 5228 if (BARE_SYMBOL_P (obj) && c_symbol_p (p))
5214 return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0; 5229 return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
5215 5230
5216 if (p == &buffer_defaults || p == &buffer_local_symbols) 5231 if (p == &buffer_defaults || p == &buffer_local_symbols)
@@ -5638,12 +5653,12 @@ purecopy (Lisp_Object obj)
5638 vec->contents[i] = purecopy (vec->contents[i]); 5653 vec->contents[i] = purecopy (vec->contents[i]);
5639 XSETVECTOR (obj, vec); 5654 XSETVECTOR (obj, vec);
5640 } 5655 }
5641 else if (SYMBOLP (obj)) 5656 else if (BARE_SYMBOL_P (obj))
5642 { 5657 {
5643 if (!XSYMBOL (obj)->u.s.pinned && !c_symbol_p (XSYMBOL (obj))) 5658 if (!XBARE_SYMBOL (obj)->u.s.pinned && !c_symbol_p (XBARE_SYMBOL (obj)))
5644 { /* We can't purify them, but they appear in many pure objects. 5659 { /* We can't purify them, but they appear in many pure objects.
5645 Mark them as `pinned' so we know to mark them at every GC cycle. */ 5660 Mark them as `pinned' so we know to mark them at every GC cycle. */
5646 XSYMBOL (obj)->u.s.pinned = true; 5661 XBARE_SYMBOL (obj)->u.s.pinned = true;
5647 symbol_block_pinned = symbol_block; 5662 symbol_block_pinned = symbol_block;
5648 } 5663 }
5649 /* Don't hash-cons it. */ 5664 /* Don't hash-cons it. */
@@ -6268,7 +6283,10 @@ For further details, see Info node `(elisp)Garbage Collection'. */)
6268 if (garbage_collection_inhibited) 6283 if (garbage_collection_inhibited)
6269 return Qnil; 6284 return Qnil;
6270 6285
6286 ptrdiff_t count = SPECPDL_INDEX ();
6287 specbind (Qsymbols_with_pos_enabled, Qnil);
6271 garbage_collect (); 6288 garbage_collect ();
6289 unbind_to (count, Qnil);
6272 struct gcstat gcst = gcstat; 6290 struct gcstat gcst = gcstat;
6273 6291
6274 Lisp_Object total[] = { 6292 Lisp_Object total[] = {
@@ -6407,7 +6425,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6407 Lisp_Object val = ptr->contents[i]; 6425 Lisp_Object val = ptr->contents[i];
6408 6426
6409 if (FIXNUMP (val) || 6427 if (FIXNUMP (val) ||
6410 (SYMBOLP (val) && symbol_marked_p (XSYMBOL (val)))) 6428 (BARE_SYMBOL_P (val) && symbol_marked_p (XBARE_SYMBOL (val))))
6411 continue; 6429 continue;
6412 if (SUB_CHAR_TABLE_P (val)) 6430 if (SUB_CHAR_TABLE_P (val))
6413 { 6431 {
@@ -6809,7 +6827,7 @@ mark_object (Lisp_Object arg)
6809 6827
6810 case Lisp_Symbol: 6828 case Lisp_Symbol:
6811 { 6829 {
6812 struct Lisp_Symbol *ptr = XSYMBOL (obj); 6830 struct Lisp_Symbol *ptr = XBARE_SYMBOL (obj);
6813 nextsym: 6831 nextsym:
6814 if (symbol_marked_p (ptr)) 6832 if (symbol_marked_p (ptr))
6815 break; 6833 break;
@@ -6930,7 +6948,7 @@ survives_gc_p (Lisp_Object obj)
6930 break; 6948 break;
6931 6949
6932 case Lisp_Symbol: 6950 case Lisp_Symbol:
6933 survives_p = symbol_marked_p (XSYMBOL (obj)); 6951 survives_p = symbol_marked_p (XBARE_SYMBOL (obj));
6934 break; 6952 break;
6935 6953
6936 case Lisp_String: 6954 case Lisp_String:
@@ -7347,7 +7365,7 @@ arenas. */)
7347static bool 7365static bool
7348symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj) 7366symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
7349{ 7367{
7350 struct Lisp_Symbol *sym = XSYMBOL (symbol); 7368 struct Lisp_Symbol *sym = XBARE_SYMBOL (symbol);
7351 Lisp_Object val = find_symbol_value (symbol); 7369 Lisp_Object val = find_symbol_value (symbol);
7352 return (EQ (val, obj) 7370 return (EQ (val, obj)
7353 || EQ (sym->u.s.function, obj) 7371 || EQ (sym->u.s.function, obj)
diff --git a/src/data.c b/src/data.c
index 0d3376f0903..b3b157a7f39 100644
--- a/src/data.c
+++ b/src/data.c
@@ -216,6 +216,7 @@ for example, (type-of 1) returns `integer'. */)
216 case PVEC_NORMAL_VECTOR: return Qvector; 216 case PVEC_NORMAL_VECTOR: return Qvector;
217 case PVEC_BIGNUM: return Qinteger; 217 case PVEC_BIGNUM: return Qinteger;
218 case PVEC_MARKER: return Qmarker; 218 case PVEC_MARKER: return Qmarker;
219 case PVEC_SYMBOL_WITH_POS: return Qsymbol_with_pos;
219 case PVEC_OVERLAY: return Qoverlay; 220 case PVEC_OVERLAY: return Qoverlay;
220 case PVEC_FINALIZER: return Qfinalizer; 221 case PVEC_FINALIZER: return Qfinalizer;
221 case PVEC_USER_PTR: return Quser_ptr; 222 case PVEC_USER_PTR: return Quser_ptr;
@@ -316,6 +317,26 @@ DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0,
316 return Qt; 317 return Qt;
317} 318}
318 319
320DEFUN ("bare-symbol-p", Fbare_symbol_p, Sbare_symbol_p, 1, 1, 0,
321 doc: /* Return t if OBJECT is a symbol, but not a symbol together with position. */
322 attributes: const)
323 (Lisp_Object object)
324{
325 if (BARE_SYMBOL_P (object))
326 return Qt;
327 return Qnil;
328}
329
330DEFUN ("symbol-with-pos-p", Fsymbol_with_pos_p, Ssymbol_with_pos_p, 1, 1, 0,
331 doc: /* Return t if OBJECT is a symbol together with position. */
332 attributes: const)
333 (Lisp_Object object)
334{
335 if (SYMBOL_WITH_POS_P (object))
336 return Qt;
337 return Qnil;
338}
339
319DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0, 340DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0,
320 doc: /* Return t if OBJECT is a symbol. */ 341 doc: /* Return t if OBJECT is a symbol. */
321 attributes: const) 342 attributes: const)
@@ -753,6 +774,51 @@ DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0,
753 return name; 774 return name;
754} 775}
755 776
777DEFUN ("bare-symbol", Fbare_symbol, Sbare_symbol, 1, 1, 0,
778 doc: /* Extract, if need be, the bare symbol from SYM, a symbol. */)
779 (register Lisp_Object sym)
780{
781 if (BARE_SYMBOL_P (sym))
782 return sym;
783 /* Type checking is done in the following macro. */
784 return SYMBOL_WITH_POS_SYM (sym);
785}
786
787DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0,
788 doc: /* Extract the position from a symbol with position. */)
789 (register Lisp_Object ls)
790{
791 /* Type checking is done in the following macro. */
792 return SYMBOL_WITH_POS_POS (ls);
793}
794
795DEFUN ("position-symbol", Fposition_symbol, Sposition_symbol, 2, 2, 0,
796 doc: /* Create a new symbol with position.
797SYM is a symbol, with or without position, the symbol to position.
798POS, the position, is either a fixnum or a symbol with position from which
799the position will be taken. */)
800 (register Lisp_Object sym, register Lisp_Object pos)
801{
802 Lisp_Object bare;
803 Lisp_Object position;
804
805 if (BARE_SYMBOL_P (sym))
806 bare = sym;
807 else if (SYMBOL_WITH_POS_P (sym))
808 bare = XSYMBOL_WITH_POS (sym)->sym;
809 else
810 wrong_type_argument (Qsymbolp, sym);
811
812 if (FIXNUMP (pos))
813 position = pos;
814 else if (SYMBOL_WITH_POS_P (pos))
815 position = XSYMBOL_WITH_POS (pos)->pos;
816 else
817 wrong_type_argument (Qfixnum_or_symbol_with_pos_p, pos);
818
819 return build_symbol_with_pos (bare, position);
820}
821
756DEFUN ("fset", Ffset, Sfset, 2, 2, 0, 822DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
757 doc: /* Set SYMBOL's function definition to DEFINITION, and return DEFINITION. */) 823 doc: /* Set SYMBOL's function definition to DEFINITION, and return DEFINITION. */)
758 (register Lisp_Object symbol, Lisp_Object definition) 824 (register Lisp_Object symbol, Lisp_Object definition)
@@ -3929,6 +3995,8 @@ syms_of_data (void)
3929 3995
3930 DEFSYM (Qlistp, "listp"); 3996 DEFSYM (Qlistp, "listp");
3931 DEFSYM (Qconsp, "consp"); 3997 DEFSYM (Qconsp, "consp");
3998 DEFSYM (Qbare_symbol_p, "bare-symbol-p");
3999 DEFSYM (Qsymbol_with_pos_p, "symbol-with-pos-p");
3932 DEFSYM (Qsymbolp, "symbolp"); 4000 DEFSYM (Qsymbolp, "symbolp");
3933 DEFSYM (Qfixnump, "fixnump"); 4001 DEFSYM (Qfixnump, "fixnump");
3934 DEFSYM (Qintegerp, "integerp"); 4002 DEFSYM (Qintegerp, "integerp");
@@ -3954,6 +4022,7 @@ syms_of_data (void)
3954 4022
3955 DEFSYM (Qchar_table_p, "char-table-p"); 4023 DEFSYM (Qchar_table_p, "char-table-p");
3956 DEFSYM (Qvector_or_char_table_p, "vector-or-char-table-p"); 4024 DEFSYM (Qvector_or_char_table_p, "vector-or-char-table-p");
4025 DEFSYM (Qfixnum_or_symbol_with_pos_p, "fixnum-or-symbol-with-pos-p");
3957 4026
3958 DEFSYM (Qsubrp, "subrp"); 4027 DEFSYM (Qsubrp, "subrp");
3959 DEFSYM (Qunevalled, "unevalled"); 4028 DEFSYM (Qunevalled, "unevalled");
@@ -4038,6 +4107,7 @@ syms_of_data (void)
4038 DEFSYM (Qstring, "string"); 4107 DEFSYM (Qstring, "string");
4039 DEFSYM (Qcons, "cons"); 4108 DEFSYM (Qcons, "cons");
4040 DEFSYM (Qmarker, "marker"); 4109 DEFSYM (Qmarker, "marker");
4110 DEFSYM (Qsymbol_with_pos, "symbol-with-pos");
4041 DEFSYM (Qoverlay, "overlay"); 4111 DEFSYM (Qoverlay, "overlay");
4042 DEFSYM (Qfinalizer, "finalizer"); 4112 DEFSYM (Qfinalizer, "finalizer");
4043 DEFSYM (Qmodule_function, "module-function"); 4113 DEFSYM (Qmodule_function, "module-function");
@@ -4089,6 +4159,8 @@ syms_of_data (void)
4089 defsubr (&Snumber_or_marker_p); 4159 defsubr (&Snumber_or_marker_p);
4090 defsubr (&Sfloatp); 4160 defsubr (&Sfloatp);
4091 defsubr (&Snatnump); 4161 defsubr (&Snatnump);
4162 defsubr (&Sbare_symbol_p);
4163 defsubr (&Ssymbol_with_pos_p);
4092 defsubr (&Ssymbolp); 4164 defsubr (&Ssymbolp);
4093 defsubr (&Skeywordp); 4165 defsubr (&Skeywordp);
4094 defsubr (&Sstringp); 4166 defsubr (&Sstringp);
@@ -4119,6 +4191,9 @@ syms_of_data (void)
4119 defsubr (&Sindirect_function); 4191 defsubr (&Sindirect_function);
4120 defsubr (&Ssymbol_plist); 4192 defsubr (&Ssymbol_plist);
4121 defsubr (&Ssymbol_name); 4193 defsubr (&Ssymbol_name);
4194 defsubr (&Sbare_symbol);
4195 defsubr (&Ssymbol_with_pos_pos);
4196 defsubr (&Sposition_symbol);
4122 defsubr (&Smakunbound); 4197 defsubr (&Smakunbound);
4123 defsubr (&Sfmakunbound); 4198 defsubr (&Sfmakunbound);
4124 defsubr (&Sboundp); 4199 defsubr (&Sboundp);
@@ -4201,6 +4276,12 @@ This variable cannot be set; trying to do so will signal an error. */);
4201 Vmost_negative_fixnum = make_fixnum (MOST_NEGATIVE_FIXNUM); 4276 Vmost_negative_fixnum = make_fixnum (MOST_NEGATIVE_FIXNUM);
4202 make_symbol_constant (intern_c_string ("most-negative-fixnum")); 4277 make_symbol_constant (intern_c_string ("most-negative-fixnum"));
4203 4278
4279 DEFSYM (Qsymbols_with_pos_enabled, "symbols-with-pos-enabled");
4280 DEFVAR_BOOL ("symbols-with-pos-enabled", symbols_with_pos_enabled,
4281 doc: /* Non-nil when "symbols with position" can be used as symbols.
4282Bind this to non-nil in applications such as the byte compiler. */);
4283 symbols_with_pos_enabled = false;
4284
4204 DEFSYM (Qwatchers, "watchers"); 4285 DEFSYM (Qwatchers, "watchers");
4205 DEFSYM (Qmakunbound, "makunbound"); 4286 DEFSYM (Qmakunbound, "makunbound");
4206 DEFSYM (Qunlet, "unlet"); 4287 DEFSYM (Qunlet, "unlet");
diff --git a/src/fns.c b/src/fns.c
index 76c76c92ba9..43df40aa9ed 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2569,6 +2569,13 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2569 } 2569 }
2570 } 2570 }
2571 2571
2572 /* A symbol with position compares the contained symbol, and is
2573 `equal' to the corresponding ordinary symbol. */
2574 if (SYMBOL_WITH_POS_P (o1))
2575 o1 = SYMBOL_WITH_POS_SYM (o1);
2576 if (SYMBOL_WITH_POS_P (o2))
2577 o2 = SYMBOL_WITH_POS_SYM (o2);
2578
2572 if (EQ (o1, o2)) 2579 if (EQ (o1, o2))
2573 return true; 2580 return true;
2574 if (XTYPE (o1) != XTYPE (o2)) 2581 if (XTYPE (o1) != XTYPE (o2))
@@ -4479,7 +4486,10 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash)
4479{ 4486{
4480 ptrdiff_t start_of_bucket, i; 4487 ptrdiff_t start_of_bucket, i;
4481 4488
4482 Lisp_Object hash_code = h->test.hashfn (key, h); 4489 Lisp_Object hash_code;
4490 if (SYMBOL_WITH_POS_P (key))
4491 key = SYMBOL_WITH_POS_SYM (key);
4492 hash_code = h->test.hashfn (key, h);
4483 if (hash) 4493 if (hash)
4484 *hash = hash_code; 4494 *hash = hash_code;
4485 4495
diff --git a/src/keyboard.c b/src/keyboard.c
index c98175aea0d..050537b95cf 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -688,6 +688,8 @@ recursive_edit_1 (void)
688 { 688 {
689 specbind (Qstandard_output, Qt); 689 specbind (Qstandard_output, Qt);
690 specbind (Qstandard_input, Qt); 690 specbind (Qstandard_input, Qt);
691 specbind (Qsymbols_with_pos_enabled, Qnil);
692 specbind (Qprint_symbols_bare, Qnil);
691 } 693 }
692 694
693#ifdef HAVE_WINDOW_SYSTEM 695#ifdef HAVE_WINDOW_SYSTEM
diff --git a/src/lisp.h b/src/lisp.h
index 19caba40014..08013e94d16 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -364,18 +364,38 @@ typedef EMACS_INT Lisp_Word;
364# endif 364# endif
365#endif 365#endif
366 366
367#define lisp_h_PSEUDOVECTORP(a,code) \
368 (lisp_h_VECTORLIKEP((a)) && \
369 ((XUNTAG ((a), Lisp_Vectorlike, union vectorlike_header)->size \
370 & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
371 == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))))
372
367#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x) 373#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x)
368#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x) 374#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
369#define lisp_h_CHECK_TYPE(ok, predicate, x) \ 375#define lisp_h_CHECK_TYPE(ok, predicate, x) \
370 ((ok) ? (void) 0 : wrong_type_argument (predicate, x)) 376 ((ok) ? (void) 0 : wrong_type_argument (predicate, x))
371#define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons) 377#define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons)
372#define lisp_h_EQ(x, y) (XLI (x) == XLI (y)) 378#define lisp_h_BASE_EQ(x, y) (XLI (x) == XLI (y))
379/* #define lisp_h_EQ(x, y) (XLI (x) == XLI (y)) */
380
381#define lisp_h_EQ(x, y) ((XLI ((x)) == XLI ((y))) \
382 || (symbols_with_pos_enabled \
383 && (SYMBOL_WITH_POS_P ((x)) \
384 ? BARE_SYMBOL_P ((y)) \
385 ? (XSYMBOL_WITH_POS((x)))->sym == (y) \
386 : SYMBOL_WITH_POS_P((y)) \
387 && ((XSYMBOL_WITH_POS((x)))->sym \
388 == (XSYMBOL_WITH_POS((y)))->sym) \
389 : (SYMBOL_WITH_POS_P ((y)) \
390 && BARE_SYMBOL_P ((x)) \
391 && ((x) == ((XSYMBOL_WITH_POS ((y)))->sym))))))
392
373#define lisp_h_FIXNUMP(x) \ 393#define lisp_h_FIXNUMP(x) \
374 (! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \ 394 (! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \
375 - (unsigned) (Lisp_Int0 >> !USE_LSB_TAG)) \ 395 - (unsigned) (Lisp_Int0 >> !USE_LSB_TAG)) \
376 & ((1 << INTTYPEBITS) - 1))) 396 & ((1 << INTTYPEBITS) - 1)))
377#define lisp_h_FLOATP(x) TAGGEDP (x, Lisp_Float) 397#define lisp_h_FLOATP(x) TAGGEDP (x, Lisp_Float)
378#define lisp_h_NILP(x) EQ (x, Qnil) 398#define lisp_h_NILP(x) /* x == Qnil */ /* ((XLI (x) == XLI (Qnil))) */ /* EQ (x, Qnil) */ BASE_EQ (x, Qnil)
379#define lisp_h_SET_SYMBOL_VAL(sym, v) \ 399#define lisp_h_SET_SYMBOL_VAL(sym, v) \
380 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \ 400 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \
381 (sym)->u.s.val.value = (v)) 401 (sym)->u.s.val.value = (v))
@@ -384,7 +404,10 @@ typedef EMACS_INT Lisp_Word;
384#define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write) 404#define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write)
385#define lisp_h_SYMBOL_VAL(sym) \ 405#define lisp_h_SYMBOL_VAL(sym) \
386 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), (sym)->u.s.val.value) 406 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), (sym)->u.s.val.value)
387#define lisp_h_SYMBOLP(x) TAGGEDP (x, Lisp_Symbol) 407#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP ((x), PVEC_SYMBOL_WITH_POS)
408#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP ((x), Lisp_Symbol)
409#define lisp_h_SYMBOLP(x) ((BARE_SYMBOL_P ((x)) || \
410 (symbols_with_pos_enabled && (SYMBOL_WITH_POS_P ((x))))))
388#define lisp_h_TAGGEDP(a, tag) \ 411#define lisp_h_TAGGEDP(a, tag) \
389 (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \ 412 (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
390 - (unsigned) (tag)) \ 413 - (unsigned) (tag)) \
@@ -429,11 +452,12 @@ typedef EMACS_INT Lisp_Word;
429# define XLI(o) lisp_h_XLI (o) 452# define XLI(o) lisp_h_XLI (o)
430# define XIL(i) lisp_h_XIL (i) 453# define XIL(i) lisp_h_XIL (i)
431# define XLP(o) lisp_h_XLP (o) 454# define XLP(o) lisp_h_XLP (o)
455# define BARE_SYMBOL_P(x) lisp_h_BARE_SYMBOL_P (x)
432# define CHECK_FIXNUM(x) lisp_h_CHECK_FIXNUM (x) 456# define CHECK_FIXNUM(x) lisp_h_CHECK_FIXNUM (x)
433# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x) 457# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x)
434# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) 458# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
435# define CONSP(x) lisp_h_CONSP (x) 459# define CONSP(x) lisp_h_CONSP (x)
436# define EQ(x, y) lisp_h_EQ (x, y) 460# define BASE_EQ(x, y) lisp_h_BASE_EQ (x, y)
437# define FLOATP(x) lisp_h_FLOATP (x) 461# define FLOATP(x) lisp_h_FLOATP (x)
438# define FIXNUMP(x) lisp_h_FIXNUMP (x) 462# define FIXNUMP(x) lisp_h_FIXNUMP (x)
439# define NILP(x) lisp_h_NILP (x) 463# define NILP(x) lisp_h_NILP (x)
@@ -441,7 +465,7 @@ typedef EMACS_INT Lisp_Word;
441# define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym) 465# define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym)
442# define SYMBOL_TRAPPED_WRITE_P(sym) lisp_h_SYMBOL_TRAPPED_WRITE_P (sym) 466# define SYMBOL_TRAPPED_WRITE_P(sym) lisp_h_SYMBOL_TRAPPED_WRITE_P (sym)
443# define SYMBOL_VAL(sym) lisp_h_SYMBOL_VAL (sym) 467# define SYMBOL_VAL(sym) lisp_h_SYMBOL_VAL (sym)
444# define SYMBOLP(x) lisp_h_SYMBOLP (x) 468/* # define SYMBOLP(x) lisp_h_SYMBOLP (x) */ /* X is accessed more than once. */
445# define TAGGEDP(a, tag) lisp_h_TAGGEDP (a, tag) 469# define TAGGEDP(a, tag) lisp_h_TAGGEDP (a, tag)
446# define VECTORLIKEP(x) lisp_h_VECTORLIKEP (x) 470# define VECTORLIKEP(x) lisp_h_VECTORLIKEP (x)
447# define XCAR(c) lisp_h_XCAR (c) 471# define XCAR(c) lisp_h_XCAR (c)
@@ -600,6 +624,7 @@ extern Lisp_Object char_table_ref (Lisp_Object, int) ATTRIBUTE_PURE;
600extern void char_table_set (Lisp_Object, int, Lisp_Object); 624extern void char_table_set (Lisp_Object, int, Lisp_Object);
601 625
602/* Defined in data.c. */ 626/* Defined in data.c. */
627extern bool symbols_with_pos_enabled;
603extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); 628extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object);
604extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); 629extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
605extern Lisp_Object default_value (Lisp_Object symbol); 630extern Lisp_Object default_value (Lisp_Object symbol);
@@ -984,57 +1009,12 @@ union vectorlike_header
984 ptrdiff_t size; 1009 ptrdiff_t size;
985 }; 1010 };
986 1011
987INLINE bool 1012struct Lisp_Symbol_With_Pos
988(SYMBOLP) (Lisp_Object x)
989{
990 return lisp_h_SYMBOLP (x);
991}
992
993INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
994XSYMBOL (Lisp_Object a)
995{
996 eassert (SYMBOLP (a));
997 intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
998 void *p = (char *) lispsym + i;
999 return p;
1000}
1001
1002INLINE Lisp_Object
1003make_lisp_symbol (struct Lisp_Symbol *sym)
1004{
1005 /* GCC 7 x86-64 generates faster code if lispsym is
1006 cast to char * rather than to intptr_t. */
1007 char *symoffset = (char *) ((char *) sym - (char *) lispsym);
1008 Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
1009 eassert (XSYMBOL (a) == sym);
1010 return a;
1011}
1012
1013INLINE Lisp_Object
1014builtin_lisp_symbol (int index)
1015{
1016 return make_lisp_symbol (&lispsym[index]);
1017}
1018
1019INLINE bool
1020c_symbol_p (struct Lisp_Symbol *sym)
1021{ 1013{
1022 char *bp = (char *) lispsym; 1014 union vectorlike_header header;
1023 char *sp = (char *) sym; 1015 Lisp_Object sym; /* A symbol */
1024 if (PTRDIFF_MAX < INTPTR_MAX) 1016 Lisp_Object pos; /* A fixnum */
1025 return bp <= sp && sp < bp + sizeof lispsym; 1017} GCALIGNED_STRUCT;
1026 else
1027 {
1028 ptrdiff_t offset = sp - bp;
1029 return 0 <= offset && offset < sizeof lispsym;
1030 }
1031}
1032
1033INLINE void
1034(CHECK_SYMBOL) (Lisp_Object x)
1035{
1036 lisp_h_CHECK_SYMBOL (x);
1037}
1038 1018
1039/* In the size word of a vector, this bit means the vector has been marked. */ 1019/* In the size word of a vector, this bit means the vector has been marked. */
1040 1020
@@ -1059,6 +1039,7 @@ enum pvec_type
1059 PVEC_MARKER, 1039 PVEC_MARKER,
1060 PVEC_OVERLAY, 1040 PVEC_OVERLAY,
1061 PVEC_FINALIZER, 1041 PVEC_FINALIZER,
1042 PVEC_SYMBOL_WITH_POS,
1062 PVEC_MISC_PTR, 1043 PVEC_MISC_PTR,
1063 PVEC_USER_PTR, 1044 PVEC_USER_PTR,
1064 PVEC_PROCESS, 1045 PVEC_PROCESS,
@@ -1117,6 +1098,92 @@ enum More_Lisp_Bits
1117 values. They are macros for use in #if and static initializers. */ 1098 values. They are macros for use in #if and static initializers. */
1118#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) 1099#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
1119#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) 1100#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
1101
1102INLINE bool
1103PSEUDOVECTORP (Lisp_Object a, int code)
1104{
1105 return lisp_h_PSEUDOVECTORP (a, code);
1106}
1107
1108INLINE bool
1109(BARE_SYMBOL_P) (Lisp_Object x)
1110{
1111 return lisp_h_BARE_SYMBOL_P (x);
1112}
1113
1114INLINE bool
1115(SYMBOL_WITH_POS_P) (Lisp_Object x)
1116{
1117 return lisp_h_SYMBOL_WITH_POS_P (x);
1118}
1119
1120INLINE bool
1121(SYMBOLP) (Lisp_Object x)
1122{
1123 return lisp_h_SYMBOLP (x);
1124}
1125
1126INLINE struct Lisp_Symbol_With_Pos *
1127XSYMBOL_WITH_POS (Lisp_Object a)
1128{
1129 eassert (SYMBOL_WITH_POS_P (a));
1130 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Symbol_With_Pos);
1131}
1132
1133INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
1134(XBARE_SYMBOL) (Lisp_Object a)
1135{
1136 eassert (BARE_SYMBOL_P (a));
1137 intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
1138 void *p = (char *) lispsym + i;
1139 return p;
1140}
1141
1142INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
1143(XSYMBOL) (Lisp_Object a)
1144{
1145 eassert (SYMBOLP ((a)));
1146 if (!symbols_with_pos_enabled || BARE_SYMBOL_P (a))
1147 return XBARE_SYMBOL (a);
1148 return XBARE_SYMBOL (XSYMBOL_WITH_POS (a)->sym);
1149}
1150
1151INLINE Lisp_Object
1152make_lisp_symbol (struct Lisp_Symbol *sym)
1153{
1154 /* GCC 7 x86-64 generates faster code if lispsym is
1155 cast to char * rather than to intptr_t. */
1156 char *symoffset = (char *) ((char *) sym - (char *) lispsym);
1157 Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
1158 eassert (XSYMBOL (a) == sym);
1159 return a;
1160}
1161
1162INLINE Lisp_Object
1163builtin_lisp_symbol (int index)
1164{
1165 return make_lisp_symbol (&lispsym[index]);
1166}
1167
1168INLINE bool
1169c_symbol_p (struct Lisp_Symbol *sym)
1170{
1171 char *bp = (char *) lispsym;
1172 char *sp = (char *) sym;
1173 if (PTRDIFF_MAX < INTPTR_MAX)
1174 return bp <= sp && sp < bp + sizeof lispsym;
1175 else
1176 {
1177 ptrdiff_t offset = sp - bp;
1178 return 0 <= offset && offset < sizeof lispsym;
1179 }
1180}
1181
1182INLINE void
1183(CHECK_SYMBOL) (Lisp_Object x)
1184{
1185 lisp_h_CHECK_SYMBOL (x);
1186}
1120 1187
1121/* True if the possibly-unsigned integer I doesn't fit in a fixnum. */ 1188/* True if the possibly-unsigned integer I doesn't fit in a fixnum. */
1122 1189
@@ -1248,7 +1315,14 @@ make_fixed_natnum (EMACS_INT n)
1248} 1315}
1249 1316
1250/* Return true if X and Y are the same object. */ 1317/* Return true if X and Y are the same object. */
1318INLINE bool
1319(BASE_EQ) (Lisp_Object x, Lisp_Object y)
1320{
1321 return lisp_h_BASE_EQ (x, y);
1322}
1251 1323
1324/* Return true if X and Y are the same object, reckoning a symbol with
1325 position as being the same as the bare symbol. */
1252INLINE bool 1326INLINE bool
1253(EQ) (Lisp_Object x, Lisp_Object y) 1327(EQ) (Lisp_Object x, Lisp_Object y)
1254{ 1328{
@@ -1714,21 +1788,6 @@ PSEUDOVECTOR_TYPEP (const union vectorlike_header *a, enum pvec_type code)
1714 == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS))); 1788 == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS)));
1715} 1789}
1716 1790
1717/* True if A is a pseudovector whose code is CODE. */
1718INLINE bool
1719PSEUDOVECTORP (Lisp_Object a, int code)
1720{
1721 if (! VECTORLIKEP (a))
1722 return false;
1723 else
1724 {
1725 /* Converting to union vectorlike_header * avoids aliasing issues. */
1726 return PSEUDOVECTOR_TYPEP (XUNTAG (a, Lisp_Vectorlike,
1727 union vectorlike_header),
1728 code);
1729 }
1730}
1731
1732/* A boolvector is a kind of vectorlike, with contents like a string. */ 1791/* A boolvector is a kind of vectorlike, with contents like a string. */
1733 1792
1734struct Lisp_Bool_Vector 1793struct Lisp_Bool_Vector
@@ -2627,6 +2686,22 @@ XOVERLAY (Lisp_Object a)
2627 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay); 2686 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay);
2628} 2687}
2629 2688
2689INLINE Lisp_Object
2690SYMBOL_WITH_POS_SYM (Lisp_Object a)
2691{
2692 if (!SYMBOL_WITH_POS_P (a))
2693 wrong_type_argument (Qsymbol_with_pos_p, a);
2694 return XSYMBOL_WITH_POS (a)->sym;
2695}
2696
2697INLINE Lisp_Object
2698SYMBOL_WITH_POS_POS (Lisp_Object a)
2699{
2700 if (!SYMBOL_WITH_POS_P (a))
2701 wrong_type_argument (Qsymbol_with_pos_p, a);
2702 return XSYMBOL_WITH_POS (a)->pos;
2703}
2704
2630INLINE bool 2705INLINE bool
2631USER_PTRP (Lisp_Object x) 2706USER_PTRP (Lisp_Object x)
2632{ 2707{
@@ -4030,6 +4105,7 @@ extern bool gc_in_progress;
4030extern Lisp_Object make_float (double); 4105extern Lisp_Object make_float (double);
4031extern void display_malloc_warning (void); 4106extern void display_malloc_warning (void);
4032extern ptrdiff_t inhibit_garbage_collection (void); 4107extern ptrdiff_t inhibit_garbage_collection (void);
4108extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object);
4033extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); 4109extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
4034extern void free_cons (struct Lisp_Cons *); 4110extern void free_cons (struct Lisp_Cons *);
4035extern void init_alloc_once (void); 4111extern void init_alloc_once (void);
diff --git a/src/lread.c b/src/lread.c
index 2e63ec48912..7775911c1d3 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -647,12 +647,12 @@ struct subst
647}; 647};
648 648
649static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, 649static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
650 Lisp_Object); 650 Lisp_Object, bool);
651static Lisp_Object read0 (Lisp_Object); 651static Lisp_Object read0 (Lisp_Object, bool);
652static Lisp_Object read1 (Lisp_Object, int *, bool); 652static Lisp_Object read1 (Lisp_Object, int *, bool, bool);
653 653
654static Lisp_Object read_list (bool, Lisp_Object); 654static Lisp_Object read_list (bool, Lisp_Object, bool);
655static Lisp_Object read_vector (Lisp_Object, bool); 655static Lisp_Object read_vector (Lisp_Object, bool, bool);
656 656
657static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); 657static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object);
658static void substitute_in_interval (INTERVAL, void *); 658static void substitute_in_interval (INTERVAL, void *);
@@ -2280,7 +2280,7 @@ readevalloop (Lisp_Object readcharfun,
2280 Qnil, false); 2280 Qnil, false);
2281 if (!NILP (Vpurify_flag) && c == '(') 2281 if (!NILP (Vpurify_flag) && c == '(')
2282 { 2282 {
2283 val = read_list (0, readcharfun); 2283 val = read_list (0, readcharfun, false);
2284 } 2284 }
2285 else 2285 else
2286 { 2286 {
@@ -2302,7 +2302,7 @@ readevalloop (Lisp_Object readcharfun,
2302 else if (! NILP (Vload_read_function)) 2302 else if (! NILP (Vload_read_function))
2303 val = call1 (Vload_read_function, readcharfun); 2303 val = call1 (Vload_read_function, readcharfun);
2304 else 2304 else
2305 val = read_internal_start (readcharfun, Qnil, Qnil); 2305 val = read_internal_start (readcharfun, Qnil, Qnil, false);
2306 } 2306 }
2307 /* Empty hashes can be reused; otherwise, reset on next call. */ 2307 /* Empty hashes can be reused; otherwise, reset on next call. */
2308 if (HASH_TABLE_P (read_objects_map) 2308 if (HASH_TABLE_P (read_objects_map)
@@ -2460,7 +2460,35 @@ STREAM or the value of `standard-input' may be:
2460 return call1 (intern ("read-minibuffer"), 2460 return call1 (intern ("read-minibuffer"),
2461 build_string ("Lisp expression: ")); 2461 build_string ("Lisp expression: "));
2462 2462
2463 return read_internal_start (stream, Qnil, Qnil); 2463 return read_internal_start (stream, Qnil, Qnil, false);
2464}
2465
2466DEFUN ("read-positioning-symbols", Fread_positioning_symbols,
2467 Sread_positioning_symbols, 0, 1, 0,
2468 doc: /* Read one Lisp expression as text from STREAM, return as Lisp object.
2469Convert each occurrence of a symbol into a "symbol with pos" object.
2470
2471If STREAM is nil, use the value of `standard-input' (which see).
2472STREAM or the value of `standard-input' may be:
2473 a buffer (read from point and advance it)
2474 a marker (read from where it points and advance it)
2475 a function (call it with no arguments for each character,
2476 call it with a char as argument to push a char back)
2477 a string (takes text from string, starting at the beginning)
2478 t (read text line using minibuffer and use it, or read from
2479 standard input in batch mode). */)
2480 (Lisp_Object stream)
2481{
2482 if (NILP (stream))
2483 stream = Vstandard_input;
2484 if (EQ (stream, Qt))
2485 stream = Qread_char;
2486 if (EQ (stream, Qread_char))
2487 /* FIXME: ?! When is this used !? */
2488 return call1 (intern ("read-minibuffer"),
2489 build_string ("Lisp expression: "));
2490
2491 return read_internal_start (stream, Qnil, Qnil, true);
2464} 2492}
2465 2493
2466DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0, 2494DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0,
@@ -2476,14 +2504,17 @@ the end of STRING. */)
2476 Lisp_Object ret; 2504 Lisp_Object ret;
2477 CHECK_STRING (string); 2505 CHECK_STRING (string);
2478 /* `read_internal_start' sets `read_from_string_index'. */ 2506 /* `read_internal_start' sets `read_from_string_index'. */
2479 ret = read_internal_start (string, start, end); 2507 ret = read_internal_start (string, start, end, false);
2480 return Fcons (ret, make_fixnum (read_from_string_index)); 2508 return Fcons (ret, make_fixnum (read_from_string_index));
2481} 2509}
2482 2510
2483/* Function to set up the global context we need in toplevel read 2511/* Function to set up the global context we need in toplevel read
2484 calls. START and END only used when STREAM is a string. */ 2512 calls. START and END only used when STREAM is a string.
2513 LOCATE_SYMS true means read symbol occurrences as symbols with
2514 position. */
2485static Lisp_Object 2515static Lisp_Object
2486read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end) 2516read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end,
2517 bool locate_syms)
2487{ 2518{
2488 Lisp_Object retval; 2519 Lisp_Object retval;
2489 2520
@@ -2523,7 +2554,7 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
2523 read_from_string_limit = endval; 2554 read_from_string_limit = endval;
2524 } 2555 }
2525 2556
2526 retval = read0 (stream); 2557 retval = read0 (stream, locate_syms);
2527 if (EQ (Vread_with_symbol_positions, Qt) 2558 if (EQ (Vread_with_symbol_positions, Qt)
2528 || EQ (Vread_with_symbol_positions, stream)) 2559 || EQ (Vread_with_symbol_positions, stream))
2529 Vread_symbol_positions_list = Fnreverse (Vread_symbol_positions_list); 2560 Vread_symbol_positions_list = Fnreverse (Vread_symbol_positions_list);
@@ -2542,12 +2573,12 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
2542 are not allowed. */ 2573 are not allowed. */
2543 2574
2544static Lisp_Object 2575static Lisp_Object
2545read0 (Lisp_Object readcharfun) 2576read0 (Lisp_Object readcharfun, bool locate_syms)
2546{ 2577{
2547 register Lisp_Object val; 2578 register Lisp_Object val;
2548 int c; 2579 int c;
2549 2580
2550 val = read1 (readcharfun, &c, 0); 2581 val = read1 (readcharfun, &c, 0, locate_syms);
2551 if (!c) 2582 if (!c)
2552 return val; 2583 return val;
2553 2584
@@ -2971,10 +3002,12 @@ read_integer (Lisp_Object readcharfun, int radix,
2971 in *PCH and the return value is not interesting. Else, we store 3002 in *PCH and the return value is not interesting. Else, we store
2972 zero in *PCH and we read and return one lisp object. 3003 zero in *PCH and we read and return one lisp object.
2973 3004
2974 FIRST_IN_LIST is true if this is the first element of a list. */ 3005 FIRST_IN_LIST is true if this is the first element of a list.
3006 LOCATE_SYMS true means read symbol occurrences as symbols with
3007 position. */
2975 3008
2976static Lisp_Object 3009static Lisp_Object
2977read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) 3010read1 (Lisp_Object readcharfun, int *pch, bool first_in_list, bool locate_syms)
2978{ 3011{
2979 int c; 3012 int c;
2980 bool uninterned_symbol = false; 3013 bool uninterned_symbol = false;
@@ -2994,10 +3027,10 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2994 switch (c) 3027 switch (c)
2995 { 3028 {
2996 case '(': 3029 case '(':
2997 return read_list (0, readcharfun); 3030 return read_list (0, readcharfun, locate_syms);
2998 3031
2999 case '[': 3032 case '[':
3000 return read_vector (readcharfun, 0); 3033 return read_vector (readcharfun, 0, locate_syms);
3001 3034
3002 case ')': 3035 case ')':
3003 case ']': 3036 case ']':
@@ -3016,7 +3049,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3016 /* Accept extended format for hash tables (extensible to 3049 /* Accept extended format for hash tables (extensible to
3017 other types), e.g. 3050 other types), e.g.
3018 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ 3051 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
3019 Lisp_Object tmp = read_list (0, readcharfun); 3052 Lisp_Object tmp = read_list (0, readcharfun, false);
3020 Lisp_Object head = CAR_SAFE (tmp); 3053 Lisp_Object head = CAR_SAFE (tmp);
3021 Lisp_Object data = Qnil; 3054 Lisp_Object data = Qnil;
3022 Lisp_Object val = Qnil; 3055 Lisp_Object val = Qnil;
@@ -3105,7 +3138,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3105 if (c == '[') 3138 if (c == '[')
3106 { 3139 {
3107 Lisp_Object tmp; 3140 Lisp_Object tmp;
3108 tmp = read_vector (readcharfun, 0); 3141 tmp = read_vector (readcharfun, 0, false);
3109 if (ASIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS) 3142 if (ASIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS)
3110 error ("Invalid size char-table"); 3143 error ("Invalid size char-table");
3111 XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE); 3144 XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE);
@@ -3118,7 +3151,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3118 { 3151 {
3119 /* Sub char-table can't be read as a regular 3152 /* Sub char-table can't be read as a regular
3120 vector because of a two C integer fields. */ 3153 vector because of a two C integer fields. */
3121 Lisp_Object tbl, tmp = read_list (1, readcharfun); 3154 Lisp_Object tbl, tmp = read_list (1, readcharfun, false);
3122 ptrdiff_t size = list_length (tmp); 3155 ptrdiff_t size = list_length (tmp);
3123 int i, depth, min_char; 3156 int i, depth, min_char;
3124 struct Lisp_Cons *cell; 3157 struct Lisp_Cons *cell;
@@ -3156,7 +3189,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3156 if (c == '&') 3189 if (c == '&')
3157 { 3190 {
3158 Lisp_Object length; 3191 Lisp_Object length;
3159 length = read1 (readcharfun, pch, first_in_list); 3192 length = read1 (readcharfun, pch, first_in_list, false);
3160 c = READCHAR; 3193 c = READCHAR;
3161 if (c == '"') 3194 if (c == '"')
3162 { 3195 {
@@ -3165,7 +3198,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3165 unsigned char *data; 3198 unsigned char *data;
3166 3199
3167 UNREAD (c); 3200 UNREAD (c);
3168 tmp = read1 (readcharfun, pch, first_in_list); 3201 tmp = read1 (readcharfun, pch, first_in_list, false);
3169 if (STRING_MULTIBYTE (tmp) 3202 if (STRING_MULTIBYTE (tmp)
3170 || (size_in_chars != SCHARS (tmp) 3203 || (size_in_chars != SCHARS (tmp)
3171 /* We used to print 1 char too many 3204 /* We used to print 1 char too many
@@ -3193,7 +3226,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3193 build them using function calls. */ 3226 build them using function calls. */
3194 Lisp_Object tmp; 3227 Lisp_Object tmp;
3195 struct Lisp_Vector *vec; 3228 struct Lisp_Vector *vec;
3196 tmp = read_vector (readcharfun, 1); 3229 tmp = read_vector (readcharfun, 1, locate_syms);
3197 vec = XVECTOR (tmp); 3230 vec = XVECTOR (tmp);
3198 if (! (COMPILED_STACK_DEPTH < ASIZE (tmp) 3231 if (! (COMPILED_STACK_DEPTH < ASIZE (tmp)
3199 && (FIXNUMP (AREF (tmp, COMPILED_ARGLIST)) 3232 && (FIXNUMP (AREF (tmp, COMPILED_ARGLIST))
@@ -3243,7 +3276,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3243 int ch; 3276 int ch;
3244 3277
3245 /* Read the string itself. */ 3278 /* Read the string itself. */
3246 tmp = read1 (readcharfun, &ch, 0); 3279 tmp = read1 (readcharfun, &ch, 0, false);
3247 if (ch != 0 || !STRINGP (tmp)) 3280 if (ch != 0 || !STRINGP (tmp))
3248 invalid_syntax ("#", readcharfun); 3281 invalid_syntax ("#", readcharfun);
3249 /* Read the intervals and their properties. */ 3282 /* Read the intervals and their properties. */
@@ -3251,14 +3284,14 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3251 { 3284 {
3252 Lisp_Object beg, end, plist; 3285 Lisp_Object beg, end, plist;
3253 3286
3254 beg = read1 (readcharfun, &ch, 0); 3287 beg = read1 (readcharfun, &ch, 0, false);
3255 end = plist = Qnil; 3288 end = plist = Qnil;
3256 if (ch == ')') 3289 if (ch == ')')
3257 break; 3290 break;
3258 if (ch == 0) 3291 if (ch == 0)
3259 end = read1 (readcharfun, &ch, 0); 3292 end = read1 (readcharfun, &ch, 0, false);
3260 if (ch == 0) 3293 if (ch == 0)
3261 plist = read1 (readcharfun, &ch, 0); 3294 plist = read1 (readcharfun, &ch, 0, false);
3262 if (ch) 3295 if (ch)
3263 invalid_syntax ("Invalid string property list", readcharfun); 3296 invalid_syntax ("Invalid string property list", readcharfun);
3264 Fset_text_properties (beg, end, plist, tmp); 3297 Fset_text_properties (beg, end, plist, tmp);
@@ -3369,7 +3402,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3369 if (c == '$') 3402 if (c == '$')
3370 return Vload_file_name; 3403 return Vload_file_name;
3371 if (c == '\'') 3404 if (c == '\'')
3372 return list2 (Qfunction, read0 (readcharfun)); 3405 return list2 (Qfunction, read0 (readcharfun, locate_syms));
3373 /* #:foo is the uninterned symbol named foo. */ 3406 /* #:foo is the uninterned symbol named foo. */
3374 if (c == ':') 3407 if (c == ':')
3375 { 3408 {
@@ -3452,7 +3485,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3452 hash_put (h, number, placeholder, hash); 3485 hash_put (h, number, placeholder, hash);
3453 3486
3454 /* Read the object itself. */ 3487 /* Read the object itself. */
3455 Lisp_Object tem = read0 (readcharfun); 3488 Lisp_Object tem = read0 (readcharfun, locate_syms);
3456 3489
3457 /* If it can be recursive, remember it for 3490 /* If it can be recursive, remember it for
3458 future substitutions. */ 3491 future substitutions. */
@@ -3508,6 +3541,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3508 else if (c == 'b' || c == 'B') 3541 else if (c == 'b' || c == 'B')
3509 return read_integer (readcharfun, 2, stackbuf); 3542 return read_integer (readcharfun, 2, stackbuf);
3510 3543
3544 char acm_buf[15]; /* FIXME!!! 2021-11-27. */
3545 sprintf (acm_buf, "#%c", c);
3546 invalid_syntax (acm_buf, readcharfun);
3511 UNREAD (c); 3547 UNREAD (c);
3512 invalid_syntax ("#", readcharfun); 3548 invalid_syntax ("#", readcharfun);
3513 3549
@@ -3516,10 +3552,10 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3516 goto retry; 3552 goto retry;
3517 3553
3518 case '\'': 3554 case '\'':
3519 return list2 (Qquote, read0 (readcharfun)); 3555 return list2 (Qquote, read0 (readcharfun, locate_syms));
3520 3556
3521 case '`': 3557 case '`':
3522 return list2 (Qbackquote, read0 (readcharfun)); 3558 return list2 (Qbackquote, read0 (readcharfun, locate_syms));
3523 3559
3524 case ',': 3560 case ',':
3525 { 3561 {
@@ -3535,7 +3571,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3535 comma_type = Qcomma; 3571 comma_type = Qcomma;
3536 } 3572 }
3537 3573
3538 value = read0 (readcharfun); 3574 value = read0 (readcharfun, locate_syms);
3539 return list2 (comma_type, value); 3575 return list2 (comma_type, value);
3540 } 3576 }
3541 case '?': 3577 case '?':
@@ -3842,6 +3878,11 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3842 result = intern_driver (name, obarray, tem); 3878 result = intern_driver (name, obarray, tem);
3843 } 3879 }
3844 } 3880 }
3881 if (locate_syms
3882 && !NILP (result)
3883 )
3884 result = build_symbol_with_pos (result,
3885 make_fixnum (start_position));
3845 3886
3846 if (EQ (Vread_with_symbol_positions, Qt) 3887 if (EQ (Vread_with_symbol_positions, Qt)
3847 || EQ (Vread_with_symbol_positions, readcharfun)) 3888 || EQ (Vread_with_symbol_positions, readcharfun))
@@ -4100,9 +4141,9 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
4100 4141
4101 4142
4102static Lisp_Object 4143static Lisp_Object
4103read_vector (Lisp_Object readcharfun, bool bytecodeflag) 4144read_vector (Lisp_Object readcharfun, bool bytecodeflag, bool locate_syms)
4104{ 4145{
4105 Lisp_Object tem = read_list (1, readcharfun); 4146 Lisp_Object tem = read_list (1, readcharfun, locate_syms);
4106 ptrdiff_t size = list_length (tem); 4147 ptrdiff_t size = list_length (tem);
4107 Lisp_Object vector = make_nil_vector (size); 4148 Lisp_Object vector = make_nil_vector (size);
4108 4149
@@ -4174,10 +4215,12 @@ read_vector (Lisp_Object readcharfun, bool bytecodeflag)
4174 return vector; 4215 return vector;
4175} 4216}
4176 4217
4177/* FLAG means check for ']' to terminate rather than ')' and '.'. */ 4218/* FLAG means check for ']' to terminate rather than ')' and '.'.
4219 LOCATE_SYMS true means read symbol occurrencess as symbols with
4220 position. */
4178 4221
4179static Lisp_Object 4222static Lisp_Object
4180read_list (bool flag, Lisp_Object readcharfun) 4223read_list (bool flag, Lisp_Object readcharfun, bool locate_syms)
4181{ 4224{
4182 Lisp_Object val, tail; 4225 Lisp_Object val, tail;
4183 Lisp_Object elt, tem; 4226 Lisp_Object elt, tem;
@@ -4195,7 +4238,7 @@ read_list (bool flag, Lisp_Object readcharfun)
4195 while (1) 4238 while (1)
4196 { 4239 {
4197 int ch; 4240 int ch;
4198 elt = read1 (readcharfun, &ch, first_in_list); 4241 elt = read1 (readcharfun, &ch, first_in_list, locate_syms);
4199 4242
4200 first_in_list = 0; 4243 first_in_list = 0;
4201 4244
@@ -4239,10 +4282,10 @@ read_list (bool flag, Lisp_Object readcharfun)
4239 if (ch == '.') 4282 if (ch == '.')
4240 { 4283 {
4241 if (!NILP (tail)) 4284 if (!NILP (tail))
4242 XSETCDR (tail, read0 (readcharfun)); 4285 XSETCDR (tail, read0 (readcharfun, locate_syms));
4243 else 4286 else
4244 val = read0 (readcharfun); 4287 val = read0 (readcharfun, locate_syms);
4245 read1 (readcharfun, &ch, 0); 4288 read1 (readcharfun, &ch, 0, locate_syms);
4246 4289
4247 if (ch == ')') 4290 if (ch == ')')
4248 { 4291 {
@@ -5120,6 +5163,7 @@ void
5120syms_of_lread (void) 5163syms_of_lread (void)
5121{ 5164{
5122 defsubr (&Sread); 5165 defsubr (&Sread);
5166 defsubr (&Sread_positioning_symbols);
5123 defsubr (&Sread_from_string); 5167 defsubr (&Sread_from_string);
5124 defsubr (&Slread__substitute_object_in_subtree); 5168 defsubr (&Slread__substitute_object_in_subtree);
5125 defsubr (&Sintern); 5169 defsubr (&Sintern);
diff --git a/src/print.c b/src/print.c
index adadb289de0..eb0fe591b85 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1416,6 +1416,30 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1416 printchar ('>', printcharfun); 1416 printchar ('>', printcharfun);
1417 break; 1417 break;
1418 1418
1419 case PVEC_SYMBOL_WITH_POS:
1420 {
1421 struct Lisp_Symbol_With_Pos *sp = XSYMBOL_WITH_POS (obj);
1422 if (print_symbols_bare)
1423 print_object (sp->sym, printcharfun, escapeflag);
1424 else
1425 {
1426 print_c_string ("#<symbol ", printcharfun);
1427 if (BARE_SYMBOL_P (sp->sym))
1428 print_object (sp->sym, printcharfun, escapeflag);
1429 else
1430 print_c_string ("NOT A SYMBOL!!", printcharfun);
1431 if (FIXNUMP (sp->pos))
1432 {
1433 print_c_string (" at ", printcharfun);
1434 print_object (sp->pos, printcharfun, escapeflag);
1435 }
1436 else
1437 print_c_string (" NOT A POSITION!!", printcharfun);
1438 printchar ('>', printcharfun);
1439 }
1440 }
1441 break;
1442
1419 case PVEC_OVERLAY: 1443 case PVEC_OVERLAY:
1420 print_c_string ("#<overlay ", printcharfun); 1444 print_c_string ("#<overlay ", printcharfun);
1421 if (! XMARKER (OVERLAY_START (obj))->buffer) 1445 if (! XMARKER (OVERLAY_START (obj))->buffer)
@@ -1921,7 +1945,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1921 error ("Apparently circular structure being printed"); 1945 error ("Apparently circular structure being printed");
1922 1946
1923 for (i = 0; i < print_depth; i++) 1947 for (i = 0; i < print_depth; i++)
1924 if (EQ (obj, being_printed[i])) 1948 if (BASE_EQ (obj, being_printed[i]))
1925 { 1949 {
1926 int len = sprintf (buf, "#%d", i); 1950 int len = sprintf (buf, "#%d", i);
1927 strout (buf, len, len, printcharfun); 1951 strout (buf, len, len, printcharfun);
@@ -2425,6 +2449,13 @@ priorities. Values other than nil or t are also treated as
2425`default'. */); 2449`default'. */);
2426 Vprint_charset_text_property = Qdefault; 2450 Vprint_charset_text_property = Qdefault;
2427 2451
2452 DEFVAR_BOOL ("print-symbols-bare", print_symbols_bare,
2453 doc: /* A flag to control printing of symbols with position.
2454If the value is nil, print these objects complete with position.
2455Otherwise print just the bare symbol. */);
2456 print_symbols_bare = false;
2457 DEFSYM (Qprint_symbols_bare, "print-symbols-bare");
2458
2428 /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */ 2459 /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
2429 staticpro (&Vprin1_to_string_buffer); 2460 staticpro (&Vprin1_to_string_buffer);
2430 2461