* alloc.c, editfns.c, marker.c, lisp.h: Revert.
Lots of crashes reported by Chong Yidong <cyd@gnu.org>.
+2012-07-27 Dmitry Antipov <dmantipov@yandex.ru>
+
+ 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>.
+
2012-07-27 Dmitry Antipov <dmantipov@yandex.ru>
Fix recently-introduced typos in Windows port.
Reported by Martin Rudalics <rudalics@gmx.at>.
* w32.c (init_environment): Replace comma with semicolon.
- * w32fns.c (syms_of_w32fns): Likewise.
+ * w32fns.c (syms_of_w32fns): Add missing parenthesis.
2012-07-27 Paul Eggert <eggert@cs.ucla.edu>
doc: /* Return a newly allocated marker which does not point at any place. */)
(void)
{
- register Lisp_Object marker = allocate_misc (Lisp_Misc_Marker);
+ register Lisp_Object val;
+ register struct Lisp_Marker *p;
- init_marker (XMARKER (marker), NULL, 0, 0, 0);
- return marker;
+ val = allocate_misc (Lisp_Misc_Marker);
+ p = XMARKER (val);
+ p->buffer = 0;
+ p->bytepos = 0;
+ p->charpos = 0;
+ p->next = NULL;
+ p->insertion_type = 0;
+ return val;
}
/* Return a newly allocated marker which points into BUF
Lisp_Object
build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
{
- register Lisp_Object marker = allocate_misc (Lisp_Misc_Marker);
-
- /* Use Fmake_marker to create marker points to nowhere. */
- eassert (buf != NULL);
+ Lisp_Object obj;
+ struct Lisp_Marker *m;
/* No dead buffers here. */
eassert (!NILP (BVAR (buf, name)));
- /* In a single-byte buffer, two positions must be equal.
- Otherwise, every character is at least one byte. */
- if (BUF_Z (buf) == BUF_Z_BYTE (buf))
- eassert (charpos == bytepos);
- else
- eassert (charpos <= bytepos);
-
- init_marker (XMARKER (marker), buf, charpos, bytepos, 0);
- return marker;
+ /* Every character is at least one byte. */
+ eassert (charpos <= bytepos);
+
+ obj = allocate_misc (Lisp_Misc_Marker);
+ m = XMARKER (obj);
+ m->buffer = buf;
+ m->charpos = charpos;
+ m->bytepos = bytepos;
+ m->insertion_type = 0;
+ m->next = BUF_MARKERS (buf);
+ BUF_MARKERS (buf) = m;
+ return obj;
}
/* Put MARKER back on the free list after using it temporarily. */
case PVEC_SUBR:
break;
- case PVEC_EXCURSION:
- {
- struct Lisp_Excursion *e = (struct Lisp_Excursion *) ptr;
- /* No Lisp_Objects but two special pointers to mark here. */
- eassert (e->buffer != NULL);
- eassert (e->window != NULL);
- if (!VECTOR_MARKED_P (e->buffer))
- mark_buffer (e->buffer);
- if (!VECTOR_MARKED_P (e->window))
- mark_vectorlike ((struct Lisp_Vector *) e->window);
- }
- break;
-
case PVEC_FREE:
abort ();
Qnil, Qt, Qnil);
}
-/* Record buffer state before entering Fsave_excursion. */
-
+\f
Lisp_Object
save_excursion_save (void)
{
- Lisp_Object excursion;
- struct buffer *b = current_buffer;
- struct window *w = XWINDOW (selected_window);
- struct Lisp_Excursion *ex = xmalloc (sizeof *ex);
- struct Lisp_Marker *m = XMARKER (BVAR (b, mark));
-
- ex->size = 0;
- ex->buffer = b;
- ex->window = w;
- ex->visible = (XBUFFER (w->buffer) == b);
- ex->active = !NILP (BVAR (b, mark_active));
-
- /* We do not initialize type and gcmarkbit since this marker
- is never referenced via Lisp_Object and invisible for GC. */
- init_marker (&ex->point, b, PT, PT_BYTE, 0);
-
- /* Likewise. Note that charpos and bytepos may be zero. */
- init_marker (&ex->mark, m->buffer, m->charpos,
- m->bytepos, m->insertion_type);
-
- /* Make it a pseudovector and return excursion object. */
- XSETTYPED_PVECTYPE (ex, size, PVEC_EXCURSION);
- XSETEXCURSION (excursion, ex);
- return excursion;
+ int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
+ == current_buffer);
+
+ return Fcons (Fpoint_marker (),
+ Fcons (Fcopy_marker (BVAR (current_buffer, mark), Qnil),
+ Fcons (visible ? Qt : Qnil,
+ Fcons (BVAR (current_buffer, mark_active),
+ selected_window))));
}
-/* Restore buffer state before leaving Fsave_excursion. */
-
Lisp_Object
-save_excursion_restore (Lisp_Object obj)
+save_excursion_restore (Lisp_Object info)
{
- struct Lisp_Excursion *ex = XEXCURSION (obj);
- struct buffer *b = ex->buffer;
-
- eassert (b != NULL);
- eassert (ex->window != NULL);
-
- /* Restore buffer state only if the buffer is live.
- Otherwise, just cancel an excursion state. */
+ Lisp_Object tem, tem1, omark, nmark;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+ int visible_p;
+
+ tem = Fmarker_buffer (XCAR (info));
+ /* If buffer being returned to is now deleted, avoid error */
+ /* Otherwise could get error here while unwinding to top level
+ and crash */
+ /* In that case, Fmarker_buffer returns nil now. */
+ if (NILP (tem))
+ return Qnil;
- if (!NILP (BVAR (b, name)))
+ omark = nmark = Qnil;
+ GCPRO3 (info, omark, nmark);
+
+ Fset_buffer (tem);
+
+ /* Point marker. */
+ tem = XCAR (info);
+ Fgoto_char (tem);
+ unchain_marker (XMARKER (tem));
+
+ /* Mark marker. */
+ info = XCDR (info);
+ tem = XCAR (info);
+ omark = Fmarker_position (BVAR (current_buffer, mark));
+ Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
+ nmark = Fmarker_position (tem);
+ unchain_marker (XMARKER (tem));
+
+ /* visible */
+ info = XCDR (info);
+ visible_p = !NILP (XCAR (info));
+
+#if 0 /* We used to make the current buffer visible in the selected window
+ if that was true previously. That avoids some anomalies.
+ But it creates others, and it wasn't documented, and it is simpler
+ and cleaner never to alter the window/buffer connections. */
+ tem1 = Fcar (tem);
+ if (!NILP (tem1)
+ && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+ Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
+#endif /* 0 */
+
+ /* Mark active */
+ info = XCDR (info);
+ tem = XCAR (info);
+ tem1 = BVAR (current_buffer, mark_active);
+ BVAR (current_buffer, mark_active) = tem;
+
+ /* If mark is active now, and either was not active
+ or was at a different place, run the activate hook. */
+ if (! NILP (tem))
{
- int active;
- struct Lisp_Marker *m;
- ptrdiff_t oldpos, newpos;
-
- /* Restore current buffer. */
- set_buffer_internal (b);
-
- /* Restore buffer position. */
- SET_PT_BOTH (clip_to_bounds (BEGV, ex->point.charpos, ZV),
- clip_to_bounds (BEGV_BYTE, ex->point.bytepos, ZV_BYTE));
- unchain_marker (&ex->point);
-
- /* Restore mark if it was non-zero. */
- m = XMARKER (BVAR (b, mark));
- oldpos = m->charpos;
- if (BEGV <= ex->mark.charpos)
- attach_marker (m, b, ex->mark.charpos, ex->mark.bytepos);
- newpos = ex->mark.charpos;
- unchain_marker (&ex->mark);
-
- /* If mark and region was active, restore them. */
- active = !NILP (BVAR (b, mark_active));
- BVAR (b, mark_active) = ex->active ? Qt : Qnil;
-
- /* If mark is active now, and either was not active
- or was at a different place, run the activate hook. */
- if (ex->active && oldpos != newpos)
- {
- obj = intern ("activate-mark-hook");
- Frun_hooks (1, &obj);
- }
- /* If mark has ceased to be active, run deactivate hook. */
- else if (active)
- {
- obj = intern ("deactivate-mark-hook");
- Frun_hooks (1, &obj);
- }
-
- /* If buffer was visible in a window, and a different window
- was selected, and the old selected window is still showing
- this buffer, restore point in that window. */
- if (ex->visible)
- {
- struct window *w = ex->window;
-
- if (w != XWINDOW (selected_window) && XBUFFER (w->buffer) == b)
- attach_marker (XMARKER (w->pointm), b, PT, PT_BYTE);
- }
+ if (! EQ (omark, nmark))
+ {
+ tem = intern ("activate-mark-hook");
+ Frun_hooks (1, &tem);
+ }
+ }
+ /* If mark has ceased to be active, run deactivate hook. */
+ else if (! NILP (tem1))
+ {
+ tem = intern ("deactivate-mark-hook");
+ Frun_hooks (1, &tem);
}
- xfree (ex);
+ /* If buffer was visible in a window, and a different window was
+ selected, and the old selected window is still showing this
+ buffer, restore point in that window. */
+ tem = XCDR (info);
+ if (visible_p
+ && !EQ (tem, selected_window)
+ && (tem1 = XWINDOW (tem)->buffer,
+ (/* Window is live... */
+ BUFFERP (tem1)
+ /* ...and it shows the current buffer. */
+ && XBUFFER (tem1) == current_buffer)))
+ Fset_window_point (tem, make_number (PT));
+
+ UNGCPRO;
return Qnil;
}
PVEC_TERMINAL,
PVEC_WINDOW_CONFIGURATION,
PVEC_SUBR,
- PVEC_EXCURSION,
PVEC_OTHER,
/* These last 4 are special because we OR them in fns.c:internal_equal,
so they have to use a disjoint bit pattern:
(struct terminal *) XUNTAG (a, Lisp_Vectorlike))
#define XSUBR(a) (eassert (SUBRP (a)), \
(struct Lisp_Subr *) XUNTAG (a, Lisp_Vectorlike))
-#define XEXCURSION(a) (eassert (EXCURSIONP (a)), \
- (struct Lisp_Excursion *) XUNTAG (a, Lisp_Vectorlike))
#define XBUFFER(a) (eassert (BUFFERP (a)), \
(struct buffer *) XUNTAG (a, Lisp_Vectorlike))
#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), \
#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-/* These are special because both Lisp_Subr and Lisp_Excursion lacks
- struct vectorlike_header. */
+/* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header. */
#define XSETSUBR(a, b) \
XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
-#define XSETEXCURSION(a, b) \
- XSETTYPED_PSEUDOVECTOR (a, b, XEXCURSION (a)->size, PVEC_EXCURSION)
#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
#define XFLOAT_INIT(f,n) (XFLOAT (f)->u.data = (n))
#endif
-/* This structure is used to record buffer state for Fsave_excursion.
- It's mostly treated as Lisp_Vector but allocated and freed explicitly
- with xmalloc and xfree, so there is no vectorlike_header here. */
-
-struct Lisp_Excursion
-{
- ptrdiff_t size;
-
- /* Saved value of XWINDOW (selected_window). */
- struct window *window;
-
- /* Buffer where this excursion is in effect. */
- struct buffer *buffer;
-
- /* Non-zero if the window above has displayed the buffer. */
- unsigned visible : 1;
-
- /* Non-zero if this buffer has the mark active. */
- unsigned active : 1;
-
- /* Saved point. */
- struct Lisp_Marker point;
-
- /* Saved mark. May point to nowhere. */
- struct Lisp_Marker mark;
-};
-
/* A character, declared with the following typedef, is a member
of some character set associated with the current buffer. */
#ifndef _UCHAR_T /* Protect against something in ctab.h on AIX. */
#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
-/* These are special because both Lisp_Subr and Lisp_Excursion lacks
- struct vectorlike_header. */
+/* SUBRP is special since Lisp_Subr lacks struct vectorlike_header. */
#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
-#define EXCURSIONP(x) TYPED_PSEUDOVECTORP (x, Lisp_Excursion, PVEC_EXCURSION)
#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
extern ptrdiff_t charpos_to_bytepos (ptrdiff_t);
extern ptrdiff_t buf_charpos_to_bytepos (struct buffer *, ptrdiff_t);
extern ptrdiff_t buf_bytepos_to_charpos (struct buffer *, ptrdiff_t);
-extern void unchain_marker (struct Lisp_Marker *);
+extern void unchain_marker (struct Lisp_Marker *marker);
extern Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object set_marker_both (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t);
extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object,
- ptrdiff_t, ptrdiff_t);
-extern void init_marker (struct Lisp_Marker *, struct buffer *,
- ptrdiff_t, ptrdiff_t, int);
-extern void attach_marker (struct Lisp_Marker *, struct buffer *,
- ptrdiff_t, ptrdiff_t);
+ ptrdiff_t, ptrdiff_t);
extern Lisp_Object build_marker (struct buffer *, ptrdiff_t, ptrdiff_t);
extern void syms_of_marker (void);
return Qnil;
}
-/* Initialize just allocated Lisp_Marker. */
-
-void
-init_marker (struct Lisp_Marker *m, struct buffer *b,
- ptrdiff_t charpos, ptrdiff_t bytepos, int type)
-{
- m->buffer = b;
- m->charpos = charpos;
- m->bytepos = bytepos;
- m->insertion_type = type;
- if (b)
- {
- m->next = BUF_MARKERS (b);
- BUF_MARKERS (b) = m;
- }
- else
- m->next = NULL;
-}
-
/* Change M so it points to B at CHARPOS and BYTEPOS. */
-void
+static inline void
attach_marker (struct Lisp_Marker *m, struct buffer *b,
ptrdiff_t charpos, ptrdiff_t bytepos)
{