diff options
| author | Alan Mackenzie | 2021-11-29 11:19:31 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2021-11-29 11:19:31 +0000 |
| commit | 368570b3fd09d03ac5b9276d1ca85ae813c3f385 (patch) | |
| tree | 4d81fdc1a866120157147226c35597073592722d /src | |
| parent | 9721dcf2754ebad28ac60a9d3152fd26e4c652c4 (diff) | |
| download | emacs-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/.gdbinit | 12 | ||||
| -rw-r--r-- | src/alloc.c | 40 | ||||
| -rw-r--r-- | src/data.c | 81 | ||||
| -rw-r--r-- | src/fns.c | 12 | ||||
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 216 | ||||
| -rw-r--r-- | src/lread.c | 126 | ||||
| -rw-r--r-- | src/print.c | 33 |
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. | |||
| 746 | This command assumes that $ is an Emacs Lisp overlay value. | 746 | This command assumes that $ is an Emacs Lisp overlay value. |
| 747 | end | 747 | end |
| 748 | 748 | ||
| 749 | define xsymwithpos | ||
| 750 | xgetptr $ | ||
| 751 | print (struct Lisp_Symbol_With_Pos *) $ptr | ||
| 752 | end | ||
| 753 | document xsymwithpos | ||
| 754 | Print $ as a symbol with position. | ||
| 755 | This command assumes that $ is an Emacs Lisp symbol with position value. | ||
| 756 | end | ||
| 757 | |||
| 749 | define xsymbol | 758 | define 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) | |||
| 591 | static ATTRIBUTE_NO_SANITIZE_UNDEFINED void * | 591 | static ATTRIBUTE_NO_SANITIZE_UNDEFINED void * |
| 592 | XPNTR (Lisp_Object a) | 592 | XPNTR (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; | |||
| 3598 | static void | 3598 | static void |
| 3599 | set_symbol_name (Lisp_Object sym, Lisp_Object name) | 3599 | set_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 | ||
| 3604 | void | 3604 | void |
| 3605 | init_symbol (Lisp_Object val, Lisp_Object name) | 3605 | init_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. */ | ||
| 3671 | Lisp_Object | ||
| 3672 | build_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 | ||
| 3672 | Lisp_Object | 3687 | Lisp_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. */) | |||
| 7347 | static bool | 7365 | static bool |
| 7348 | symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj) | 7366 | symbol_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 | ||
| 320 | DEFUN ("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 | |||
| 330 | DEFUN ("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 | |||
| 319 | DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0, | 340 | DEFUN ("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 | ||
| 777 | DEFUN ("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 | |||
| 787 | DEFUN ("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 | |||
| 795 | DEFUN ("position-symbol", Fposition_symbol, Sposition_symbol, 2, 2, 0, | ||
| 796 | doc: /* Create a new symbol with position. | ||
| 797 | SYM is a symbol, with or without position, the symbol to position. | ||
| 798 | POS, the position, is either a fixnum or a symbol with position from which | ||
| 799 | the 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 | |||
| 756 | DEFUN ("fset", Ffset, Sfset, 2, 2, 0, | 822 | DEFUN ("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. | ||
| 4282 | Bind 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"); |
| @@ -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; | |||
| 600 | extern void char_table_set (Lisp_Object, int, Lisp_Object); | 624 | extern void char_table_set (Lisp_Object, int, Lisp_Object); |
| 601 | 625 | ||
| 602 | /* Defined in data.c. */ | 626 | /* Defined in data.c. */ |
| 627 | extern bool symbols_with_pos_enabled; | ||
| 603 | extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); | 628 | extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); |
| 604 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); | 629 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); |
| 605 | extern Lisp_Object default_value (Lisp_Object symbol); | 630 | extern 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 | ||
| 987 | INLINE bool | 1012 | struct Lisp_Symbol_With_Pos |
| 988 | (SYMBOLP) (Lisp_Object x) | ||
| 989 | { | ||
| 990 | return lisp_h_SYMBOLP (x); | ||
| 991 | } | ||
| 992 | |||
| 993 | INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED | ||
| 994 | XSYMBOL (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 | |||
| 1002 | INLINE Lisp_Object | ||
| 1003 | make_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 | |||
| 1013 | INLINE Lisp_Object | ||
| 1014 | builtin_lisp_symbol (int index) | ||
| 1015 | { | ||
| 1016 | return make_lisp_symbol (&lispsym[index]); | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | INLINE bool | ||
| 1020 | c_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 | |||
| 1033 | INLINE 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 | |||
| 1102 | INLINE bool | ||
| 1103 | PSEUDOVECTORP (Lisp_Object a, int code) | ||
| 1104 | { | ||
| 1105 | return lisp_h_PSEUDOVECTORP (a, code); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | INLINE bool | ||
| 1109 | (BARE_SYMBOL_P) (Lisp_Object x) | ||
| 1110 | { | ||
| 1111 | return lisp_h_BARE_SYMBOL_P (x); | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | INLINE bool | ||
| 1115 | (SYMBOL_WITH_POS_P) (Lisp_Object x) | ||
| 1116 | { | ||
| 1117 | return lisp_h_SYMBOL_WITH_POS_P (x); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | INLINE bool | ||
| 1121 | (SYMBOLP) (Lisp_Object x) | ||
| 1122 | { | ||
| 1123 | return lisp_h_SYMBOLP (x); | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | INLINE struct Lisp_Symbol_With_Pos * | ||
| 1127 | XSYMBOL_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 | |||
| 1133 | INLINE 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 | |||
| 1142 | INLINE 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 | |||
| 1151 | INLINE Lisp_Object | ||
| 1152 | make_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 | |||
| 1162 | INLINE Lisp_Object | ||
| 1163 | builtin_lisp_symbol (int index) | ||
| 1164 | { | ||
| 1165 | return make_lisp_symbol (&lispsym[index]); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | INLINE bool | ||
| 1169 | c_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 | |||
| 1182 | INLINE 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. */ |
| 1318 | INLINE 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. */ | ||
| 1252 | INLINE bool | 1326 | INLINE 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. */ | ||
| 1718 | INLINE bool | ||
| 1719 | PSEUDOVECTORP (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 | ||
| 1734 | struct Lisp_Bool_Vector | 1793 | struct 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 | ||
| 2689 | INLINE Lisp_Object | ||
| 2690 | SYMBOL_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 | |||
| 2697 | INLINE Lisp_Object | ||
| 2698 | SYMBOL_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 | |||
| 2630 | INLINE bool | 2705 | INLINE bool |
| 2631 | USER_PTRP (Lisp_Object x) | 2706 | USER_PTRP (Lisp_Object x) |
| 2632 | { | 2707 | { |
| @@ -4030,6 +4105,7 @@ extern bool gc_in_progress; | |||
| 4030 | extern Lisp_Object make_float (double); | 4105 | extern Lisp_Object make_float (double); |
| 4031 | extern void display_malloc_warning (void); | 4106 | extern void display_malloc_warning (void); |
| 4032 | extern ptrdiff_t inhibit_garbage_collection (void); | 4107 | extern ptrdiff_t inhibit_garbage_collection (void); |
| 4108 | extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object); | ||
| 4033 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); | 4109 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); |
| 4034 | extern void free_cons (struct Lisp_Cons *); | 4110 | extern void free_cons (struct Lisp_Cons *); |
| 4035 | extern void init_alloc_once (void); | 4111 | extern 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 | ||
| 649 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, | 649 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, |
| 650 | Lisp_Object); | 650 | Lisp_Object, bool); |
| 651 | static Lisp_Object read0 (Lisp_Object); | 651 | static Lisp_Object read0 (Lisp_Object, bool); |
| 652 | static Lisp_Object read1 (Lisp_Object, int *, bool); | 652 | static Lisp_Object read1 (Lisp_Object, int *, bool, bool); |
| 653 | 653 | ||
| 654 | static Lisp_Object read_list (bool, Lisp_Object); | 654 | static Lisp_Object read_list (bool, Lisp_Object, bool); |
| 655 | static Lisp_Object read_vector (Lisp_Object, bool); | 655 | static Lisp_Object read_vector (Lisp_Object, bool, bool); |
| 656 | 656 | ||
| 657 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); | 657 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); |
| 658 | static void substitute_in_interval (INTERVAL, void *); | 658 | static 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 | |||
| 2466 | DEFUN ("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. | ||
| 2469 | Convert each occurrence of a symbol into a "symbol with pos" object. | ||
| 2470 | |||
| 2471 | If STREAM is nil, use the value of `standard-input' (which see). | ||
| 2472 | STREAM 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 | ||
| 2466 | DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0, | 2494 | DEFUN ("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. */ | ||
| 2485 | static Lisp_Object | 2515 | static Lisp_Object |
| 2486 | read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end) | 2516 | read_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 | ||
| 2544 | static Lisp_Object | 2575 | static Lisp_Object |
| 2545 | read0 (Lisp_Object readcharfun) | 2576 | read0 (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 | ||
| 2976 | static Lisp_Object | 3009 | static Lisp_Object |
| 2977 | read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | 3010 | read1 (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 | ||
| 4102 | static Lisp_Object | 4143 | static Lisp_Object |
| 4103 | read_vector (Lisp_Object readcharfun, bool bytecodeflag) | 4144 | read_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 | ||
| 4179 | static Lisp_Object | 4222 | static Lisp_Object |
| 4180 | read_list (bool flag, Lisp_Object readcharfun) | 4223 | read_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 | |||
| 5120 | syms_of_lread (void) | 5163 | syms_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. | ||
| 2454 | If the value is nil, print these objects complete with position. | ||
| 2455 | Otherwise 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 | ||