aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Antipov2012-07-27 11:51:52 +0400
committerDmitry Antipov2012-07-27 11:51:52 +0400
commiteeaea515623db982d4e7d453711e6f0fad9c08d8 (patch)
tree6c4f5398509d735e85151d480c8ba4756c1e5ec5
parent073c88c22c0064b60ec57b6dadef9d3a4736e6b5 (diff)
downloademacs-eeaea515623db982d4e7d453711e6f0fad9c08d8.tar.gz
emacs-eeaea515623db982d4e7d453711e6f0fad9c08d8.zip
Revert last save_excursion_save and save_excursion_restore changes.
* alloc.c, editfns.c, marker.c, lisp.h: Revert. Lots of crashes reported by Chong Yidong <cyd@gnu.org>.
-rw-r--r--src/ChangeLog8
-rw-r--r--src/alloc.c53
-rw-r--r--src/editfns.c174
-rw-r--r--src/lisp.h47
-rw-r--r--src/marker.c21
5 files changed, 123 insertions, 180 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index adcdfb7c056..93697303cbb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,9 +1,15 @@
12012-07-27 Dmitry Antipov <dmantipov@yandex.ru> 12012-07-27 Dmitry Antipov <dmantipov@yandex.ru>
2 2
3 Revert last save_excursion_save and save_excursion_restore changes.
4 * alloc.c, editfns.c, marker.c, lisp.h: Revert.
5 Lots of crashes reported by Chong Yidong <cyd@gnu.org>.
6
72012-07-27 Dmitry Antipov <dmantipov@yandex.ru>
8
3 Fix recently-introduced typos in Windows port. 9 Fix recently-introduced typos in Windows port.
4 Reported by Martin Rudalics <rudalics@gmx.at>. 10 Reported by Martin Rudalics <rudalics@gmx.at>.
5 * w32.c (init_environment): Replace comma with semicolon. 11 * w32.c (init_environment): Replace comma with semicolon.
6 * w32fns.c (syms_of_w32fns): Likewise. 12 * w32fns.c (syms_of_w32fns): Add missing parenthesis.
7 13
82012-07-27 Paul Eggert <eggert@cs.ucla.edu> 142012-07-27 Paul Eggert <eggert@cs.ucla.edu>
9 15
diff --git a/src/alloc.c b/src/alloc.c
index 948ce7b6f5c..c7936921a09 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3685,10 +3685,17 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
3685 doc: /* Return a newly allocated marker which does not point at any place. */) 3685 doc: /* Return a newly allocated marker which does not point at any place. */)
3686 (void) 3686 (void)
3687{ 3687{
3688 register Lisp_Object marker = allocate_misc (Lisp_Misc_Marker); 3688 register Lisp_Object val;
3689 register struct Lisp_Marker *p;
3689 3690
3690 init_marker (XMARKER (marker), NULL, 0, 0, 0); 3691 val = allocate_misc (Lisp_Misc_Marker);
3691 return marker; 3692 p = XMARKER (val);
3693 p->buffer = 0;
3694 p->bytepos = 0;
3695 p->charpos = 0;
3696 p->next = NULL;
3697 p->insertion_type = 0;
3698 return val;
3692} 3699}
3693 3700
3694/* Return a newly allocated marker which points into BUF 3701/* Return a newly allocated marker which points into BUF
@@ -3697,23 +3704,24 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
3697Lisp_Object 3704Lisp_Object
3698build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) 3705build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
3699{ 3706{
3700 register Lisp_Object marker = allocate_misc (Lisp_Misc_Marker); 3707 Lisp_Object obj;
3701 3708 struct Lisp_Marker *m;
3702 /* Use Fmake_marker to create marker points to nowhere. */
3703 eassert (buf != NULL);
3704 3709
3705 /* No dead buffers here. */ 3710 /* No dead buffers here. */
3706 eassert (!NILP (BVAR (buf, name))); 3711 eassert (!NILP (BVAR (buf, name)));
3707 3712
3708 /* In a single-byte buffer, two positions must be equal. 3713 /* Every character is at least one byte. */
3709 Otherwise, every character is at least one byte. */ 3714 eassert (charpos <= bytepos);
3710 if (BUF_Z (buf) == BUF_Z_BYTE (buf)) 3715
3711 eassert (charpos == bytepos); 3716 obj = allocate_misc (Lisp_Misc_Marker);
3712 else 3717 m = XMARKER (obj);
3713 eassert (charpos <= bytepos); 3718 m->buffer = buf;
3714 3719 m->charpos = charpos;
3715 init_marker (XMARKER (marker), buf, charpos, bytepos, 0); 3720 m->bytepos = bytepos;
3716 return marker; 3721 m->insertion_type = 0;
3722 m->next = BUF_MARKERS (buf);
3723 BUF_MARKERS (buf) = m;
3724 return obj;
3717} 3725}
3718 3726
3719/* Put MARKER back on the free list after using it temporarily. */ 3727/* Put MARKER back on the free list after using it temporarily. */
@@ -6081,19 +6089,6 @@ mark_object (Lisp_Object arg)
6081 case PVEC_SUBR: 6089 case PVEC_SUBR:
6082 break; 6090 break;
6083 6091
6084 case PVEC_EXCURSION:
6085 {
6086 struct Lisp_Excursion *e = (struct Lisp_Excursion *) ptr;
6087 /* No Lisp_Objects but two special pointers to mark here. */
6088 eassert (e->buffer != NULL);
6089 eassert (e->window != NULL);
6090 if (!VECTOR_MARKED_P (e->buffer))
6091 mark_buffer (e->buffer);
6092 if (!VECTOR_MARKED_P (e->window))
6093 mark_vectorlike ((struct Lisp_Vector *) e->window);
6094 }
6095 break;
6096
6097 case PVEC_FREE: 6092 case PVEC_FREE:
6098 abort (); 6093 abort ();
6099 6094
diff --git a/src/editfns.c b/src/editfns.c
index 8b6c29bc934..f174594dd97 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -821,104 +821,104 @@ This function does not move point. */)
821 Qnil, Qt, Qnil); 821 Qnil, Qt, Qnil);
822} 822}
823 823
824/* Record buffer state before entering Fsave_excursion. */ 824
825
826Lisp_Object 825Lisp_Object
827save_excursion_save (void) 826save_excursion_save (void)
828{ 827{
829 Lisp_Object excursion; 828 int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
830 struct buffer *b = current_buffer; 829 == current_buffer);
831 struct window *w = XWINDOW (selected_window); 830
832 struct Lisp_Excursion *ex = xmalloc (sizeof *ex); 831 return Fcons (Fpoint_marker (),
833 struct Lisp_Marker *m = XMARKER (BVAR (b, mark)); 832 Fcons (Fcopy_marker (BVAR (current_buffer, mark), Qnil),
834 833 Fcons (visible ? Qt : Qnil,
835 ex->size = 0; 834 Fcons (BVAR (current_buffer, mark_active),
836 ex->buffer = b; 835 selected_window))));
837 ex->window = w;
838 ex->visible = (XBUFFER (w->buffer) == b);
839 ex->active = !NILP (BVAR (b, mark_active));
840
841 /* We do not initialize type and gcmarkbit since this marker
842 is never referenced via Lisp_Object and invisible for GC. */
843 init_marker (&ex->point, b, PT, PT_BYTE, 0);
844
845 /* Likewise. Note that charpos and bytepos may be zero. */
846 init_marker (&ex->mark, m->buffer, m->charpos,
847 m->bytepos, m->insertion_type);
848
849 /* Make it a pseudovector and return excursion object. */
850 XSETTYPED_PVECTYPE (ex, size, PVEC_EXCURSION);
851 XSETEXCURSION (excursion, ex);
852 return excursion;
853} 836}
854 837
855/* Restore buffer state before leaving Fsave_excursion. */
856
857Lisp_Object 838Lisp_Object
858save_excursion_restore (Lisp_Object obj) 839save_excursion_restore (Lisp_Object info)
859{ 840{
860 struct Lisp_Excursion *ex = XEXCURSION (obj); 841 Lisp_Object tem, tem1, omark, nmark;
861 struct buffer *b = ex->buffer; 842 struct gcpro gcpro1, gcpro2, gcpro3;
862 843 int visible_p;
863 eassert (b != NULL); 844
864 eassert (ex->window != NULL); 845 tem = Fmarker_buffer (XCAR (info));
865 846 /* If buffer being returned to is now deleted, avoid error */
866 /* Restore buffer state only if the buffer is live. 847 /* Otherwise could get error here while unwinding to top level
867 Otherwise, just cancel an excursion state. */ 848 and crash */
849 /* In that case, Fmarker_buffer returns nil now. */
850 if (NILP (tem))
851 return Qnil;
868 852
869 if (!NILP (BVAR (b, name))) 853 omark = nmark = Qnil;
854 GCPRO3 (info, omark, nmark);
855
856 Fset_buffer (tem);
857
858 /* Point marker. */
859 tem = XCAR (info);
860 Fgoto_char (tem);
861 unchain_marker (XMARKER (tem));
862
863 /* Mark marker. */
864 info = XCDR (info);
865 tem = XCAR (info);
866 omark = Fmarker_position (BVAR (current_buffer, mark));
867 Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
868 nmark = Fmarker_position (tem);
869 unchain_marker (XMARKER (tem));
870
871 /* visible */
872 info = XCDR (info);
873 visible_p = !NILP (XCAR (info));
874
875#if 0 /* We used to make the current buffer visible in the selected window
876 if that was true previously. That avoids some anomalies.
877 But it creates others, and it wasn't documented, and it is simpler
878 and cleaner never to alter the window/buffer connections. */
879 tem1 = Fcar (tem);
880 if (!NILP (tem1)
881 && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
882 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
883#endif /* 0 */
884
885 /* Mark active */
886 info = XCDR (info);
887 tem = XCAR (info);
888 tem1 = BVAR (current_buffer, mark_active);
889 BVAR (current_buffer, mark_active) = tem;
890
891 /* If mark is active now, and either was not active
892 or was at a different place, run the activate hook. */
893 if (! NILP (tem))
870 { 894 {
871 int active; 895 if (! EQ (omark, nmark))
872 struct Lisp_Marker *m; 896 {
873 ptrdiff_t oldpos, newpos; 897 tem = intern ("activate-mark-hook");
874 898 Frun_hooks (1, &tem);
875 /* Restore current buffer. */ 899 }
876 set_buffer_internal (b); 900 }
877 901 /* If mark has ceased to be active, run deactivate hook. */
878 /* Restore buffer position. */ 902 else if (! NILP (tem1))
879 SET_PT_BOTH (clip_to_bounds (BEGV, ex->point.charpos, ZV), 903 {
880 clip_to_bounds (BEGV_BYTE, ex->point.bytepos, ZV_BYTE)); 904 tem = intern ("deactivate-mark-hook");
881 unchain_marker (&ex->point); 905 Frun_hooks (1, &tem);
882
883 /* Restore mark if it was non-zero. */
884 m = XMARKER (BVAR (b, mark));
885 oldpos = m->charpos;
886 if (BEGV <= ex->mark.charpos)
887 attach_marker (m, b, ex->mark.charpos, ex->mark.bytepos);
888 newpos = ex->mark.charpos;
889 unchain_marker (&ex->mark);
890
891 /* If mark and region was active, restore them. */
892 active = !NILP (BVAR (b, mark_active));
893 BVAR (b, mark_active) = ex->active ? Qt : Qnil;
894
895 /* If mark is active now, and either was not active
896 or was at a different place, run the activate hook. */
897 if (ex->active && oldpos != newpos)
898 {
899 obj = intern ("activate-mark-hook");
900 Frun_hooks (1, &obj);
901 }
902 /* If mark has ceased to be active, run deactivate hook. */
903 else if (active)
904 {
905 obj = intern ("deactivate-mark-hook");
906 Frun_hooks (1, &obj);
907 }
908
909 /* If buffer was visible in a window, and a different window
910 was selected, and the old selected window is still showing
911 this buffer, restore point in that window. */
912 if (ex->visible)
913 {
914 struct window *w = ex->window;
915
916 if (w != XWINDOW (selected_window) && XBUFFER (w->buffer) == b)
917 attach_marker (XMARKER (w->pointm), b, PT, PT_BYTE);
918 }
919 } 906 }
920 907
921 xfree (ex); 908 /* If buffer was visible in a window, and a different window was
909 selected, and the old selected window is still showing this
910 buffer, restore point in that window. */
911 tem = XCDR (info);
912 if (visible_p
913 && !EQ (tem, selected_window)
914 && (tem1 = XWINDOW (tem)->buffer,
915 (/* Window is live... */
916 BUFFERP (tem1)
917 /* ...and it shows the current buffer. */
918 && XBUFFER (tem1) == current_buffer)))
919 Fset_window_point (tem, make_number (PT));
920
921 UNGCPRO;
922 return Qnil; 922 return Qnil;
923} 923}
924 924
diff --git a/src/lisp.h b/src/lisp.h
index dd03a130c7c..f0129f05efd 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -375,7 +375,6 @@ enum pvec_type
375 PVEC_TERMINAL, 375 PVEC_TERMINAL,
376 PVEC_WINDOW_CONFIGURATION, 376 PVEC_WINDOW_CONFIGURATION,
377 PVEC_SUBR, 377 PVEC_SUBR,
378 PVEC_EXCURSION,
379 PVEC_OTHER, 378 PVEC_OTHER,
380 /* These last 4 are special because we OR them in fns.c:internal_equal, 379 /* These last 4 are special because we OR them in fns.c:internal_equal,
381 so they have to use a disjoint bit pattern: 380 so they have to use a disjoint bit pattern:
@@ -545,8 +544,6 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
545 (struct terminal *) XUNTAG (a, Lisp_Vectorlike)) 544 (struct terminal *) XUNTAG (a, Lisp_Vectorlike))
546#define XSUBR(a) (eassert (SUBRP (a)), \ 545#define XSUBR(a) (eassert (SUBRP (a)), \
547 (struct Lisp_Subr *) XUNTAG (a, Lisp_Vectorlike)) 546 (struct Lisp_Subr *) XUNTAG (a, Lisp_Vectorlike))
548#define XEXCURSION(a) (eassert (EXCURSIONP (a)), \
549 (struct Lisp_Excursion *) XUNTAG (a, Lisp_Vectorlike))
550#define XBUFFER(a) (eassert (BUFFERP (a)), \ 547#define XBUFFER(a) (eassert (BUFFERP (a)), \
551 (struct buffer *) XUNTAG (a, Lisp_Vectorlike)) 548 (struct buffer *) XUNTAG (a, Lisp_Vectorlike))
552#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), \ 549#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), \
@@ -599,12 +596,9 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
599#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS)) 596#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
600#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)) 597#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
601#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)) 598#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
602/* These are special because both Lisp_Subr and Lisp_Excursion lacks 599/* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header. */
603 struct vectorlike_header. */
604#define XSETSUBR(a, b) \ 600#define XSETSUBR(a, b) \
605 XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR) 601 XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
606#define XSETEXCURSION(a, b) \
607 XSETTYPED_PSEUDOVECTOR (a, b, XEXCURSION (a)->size, PVEC_EXCURSION)
608#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED)) 602#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
609#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)) 603#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
610#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)) 604#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
@@ -1521,33 +1515,6 @@ struct Lisp_Float
1521#define XFLOAT_INIT(f,n) (XFLOAT (f)->u.data = (n)) 1515#define XFLOAT_INIT(f,n) (XFLOAT (f)->u.data = (n))
1522#endif 1516#endif
1523 1517
1524/* This structure is used to record buffer state for Fsave_excursion.
1525 It's mostly treated as Lisp_Vector but allocated and freed explicitly
1526 with xmalloc and xfree, so there is no vectorlike_header here. */
1527
1528struct Lisp_Excursion
1529{
1530 ptrdiff_t size;
1531
1532 /* Saved value of XWINDOW (selected_window). */
1533 struct window *window;
1534
1535 /* Buffer where this excursion is in effect. */
1536 struct buffer *buffer;
1537
1538 /* Non-zero if the window above has displayed the buffer. */
1539 unsigned visible : 1;
1540
1541 /* Non-zero if this buffer has the mark active. */
1542 unsigned active : 1;
1543
1544 /* Saved point. */
1545 struct Lisp_Marker point;
1546
1547 /* Saved mark. May point to nowhere. */
1548 struct Lisp_Marker mark;
1549};
1550
1551/* A character, declared with the following typedef, is a member 1518/* A character, declared with the following typedef, is a member
1552 of some character set associated with the current buffer. */ 1519 of some character set associated with the current buffer. */
1553#ifndef _UCHAR_T /* Protect against something in ctab.h on AIX. */ 1520#ifndef _UCHAR_T /* Protect against something in ctab.h on AIX. */
@@ -1730,10 +1697,8 @@ typedef struct {
1730#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS) 1697#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
1731#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW) 1698#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
1732#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL) 1699#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
1733/* These are special because both Lisp_Subr and Lisp_Excursion lacks 1700/* SUBRP is special since Lisp_Subr lacks struct vectorlike_header. */
1734 struct vectorlike_header. */
1735#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR) 1701#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
1736#define EXCURSIONP(x) TYPED_PSEUDOVECTORP (x, Lisp_Excursion, PVEC_EXCURSION)
1737#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED) 1702#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
1738#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER) 1703#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
1739#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE) 1704#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
@@ -2949,15 +2914,11 @@ extern void clear_charpos_cache (struct buffer *);
2949extern ptrdiff_t charpos_to_bytepos (ptrdiff_t); 2914extern ptrdiff_t charpos_to_bytepos (ptrdiff_t);
2950extern ptrdiff_t buf_charpos_to_bytepos (struct buffer *, ptrdiff_t); 2915extern ptrdiff_t buf_charpos_to_bytepos (struct buffer *, ptrdiff_t);
2951extern ptrdiff_t buf_bytepos_to_charpos (struct buffer *, ptrdiff_t); 2916extern ptrdiff_t buf_bytepos_to_charpos (struct buffer *, ptrdiff_t);
2952extern void unchain_marker (struct Lisp_Marker *); 2917extern void unchain_marker (struct Lisp_Marker *marker);
2953extern Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object); 2918extern Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object);
2954extern Lisp_Object set_marker_both (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t); 2919extern Lisp_Object set_marker_both (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t);
2955extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object, 2920extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object,
2956 ptrdiff_t, ptrdiff_t); 2921 ptrdiff_t, ptrdiff_t);
2957extern void init_marker (struct Lisp_Marker *, struct buffer *,
2958 ptrdiff_t, ptrdiff_t, int);
2959extern void attach_marker (struct Lisp_Marker *, struct buffer *,
2960 ptrdiff_t, ptrdiff_t);
2961extern Lisp_Object build_marker (struct buffer *, ptrdiff_t, ptrdiff_t); 2922extern Lisp_Object build_marker (struct buffer *, ptrdiff_t, ptrdiff_t);
2962extern void syms_of_marker (void); 2923extern void syms_of_marker (void);
2963 2924
diff --git a/src/marker.c b/src/marker.c
index d63947d8c31..0a93f4c180f 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -425,28 +425,9 @@ Returns nil if MARKER points nowhere. */)
425 return Qnil; 425 return Qnil;
426} 426}
427 427
428/* Initialize just allocated Lisp_Marker. */
429
430void
431init_marker (struct Lisp_Marker *m, struct buffer *b,
432 ptrdiff_t charpos, ptrdiff_t bytepos, int type)
433{
434 m->buffer = b;
435 m->charpos = charpos;
436 m->bytepos = bytepos;
437 m->insertion_type = type;
438 if (b)
439 {
440 m->next = BUF_MARKERS (b);
441 BUF_MARKERS (b) = m;
442 }
443 else
444 m->next = NULL;
445}
446
447/* Change M so it points to B at CHARPOS and BYTEPOS. */ 428/* Change M so it points to B at CHARPOS and BYTEPOS. */
448 429
449void 430static inline void
450attach_marker (struct Lisp_Marker *m, struct buffer *b, 431attach_marker (struct Lisp_Marker *m, struct buffer *b,
451 ptrdiff_t charpos, ptrdiff_t bytepos) 432 ptrdiff_t charpos, ptrdiff_t bytepos)
452{ 433{