* lisp.h (XSAVE_OBJECT): New macro to extract saved objects.
(allocate_misc): Remove prototype.
(format_save_value): New prototype.
* alloc.c (allocate_misc): Revert back to static.
(format_save_value): New function to build Lisp_Save_Value
object with the specified internal structure.
(make_save_value): Reimplement using format_save_value.
* editfns.c (save_excursion_save): Use format_save_value.
(save_excursion_restore): Use XSAVE_OBJECT.
+2013-01-15 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Some convenient bits to deal with Lisp_Save_Values.
+ * lisp.h (XSAVE_OBJECT): New macro to extract saved objects.
+ (allocate_misc): Remove prototype.
+ (format_save_value): New prototype.
+ * alloc.c (allocate_misc): Revert back to static.
+ (format_save_value): New function to build Lisp_Save_Value
+ object with the specified internal structure.
+ (make_save_value): Reimplement using format_save_value.
+ * editfns.c (save_excursion_save): Use format_save_value.
+ (save_excursion_restore): Use XSAVE_OBJECT.
+
2013-01-14 Paul Eggert <eggert@cs.ucla.edu>
Avoid needless casts with XSAVE_POINTER.
/* Return a newly allocated Lisp_Misc object of specified TYPE. */
-Lisp_Object
+static Lisp_Object
allocate_misc (enum Lisp_Misc_Type type)
{
Lisp_Object val;
total_free_markers++;
}
+/* Return a Lisp_Save_Value object with the data saved according to
+ FMT. Format specifiers are `i' for an integer, `p' for a pointer
+ and `o' for Lisp_Object. Up to 4 objects can be specified. */
+
+Lisp_Object
+format_save_value (const char *fmt, ...)
+{
+ va_list ap;
+ int len = strlen (fmt);
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+
+ eassert (0 < len && len < 5);
+ va_start (ap, fmt);
+
+#define INITX(index) \
+ do { \
+ if (len <= index) \
+ p->type ## index = SAVE_UNUSED; \
+ else \
+ { \
+ if (fmt[index] == 'i') \
+ { \
+ p->type ## index = SAVE_INTEGER; \
+ p->data[index].integer = va_arg (ap, ptrdiff_t); \
+ } \
+ else if (fmt[index] == 'p') \
+ { \
+ p->type ## index = SAVE_POINTER; \
+ p->data[index].pointer = va_arg (ap, void *); \
+ } \
+ else if (fmt[index] == 'o') \
+ { \
+ p->type ## index = SAVE_OBJECT; \
+ p->data[index].object = va_arg (ap, Lisp_Object); \
+ } \
+ else \
+ emacs_abort (); \
+ } \
+ } while (0)
+
+ INITX (0);
+ INITX (1);
+ INITX (2);
+ INITX (3);
+
+#undef INITX
+
+ va_end (ap);
+ p->area = 0;
+ return val;
+}
+
/* Return a Lisp_Save_Value object containing POINTER and INTEGER.
Most code should use this to package C integers and pointers
to call record_unwind_protect. The unwind function can get the
Lisp_Object
make_save_value (void *pointer, ptrdiff_t integer)
{
- register Lisp_Object val;
- register struct Lisp_Save_Value *p;
-
- val = allocate_misc (Lisp_Misc_Save_Value);
- p = XSAVE_VALUE (val);
- p->type0 = SAVE_POINTER;
- p->data[0].pointer = pointer;
- p->type1 = SAVE_INTEGER;
- p->data[1].integer = integer;
- p->type2 = p->type3 = SAVE_UNUSED;
- p->area = 0;
- return val;
+ return format_save_value ("pi", pointer, integer);
}
/* Free a Lisp_Save_Value object. Do not use this function
Lisp_Object
save_excursion_save (void)
{
- Lisp_Object save = allocate_misc (Lisp_Misc_Save_Value);
- register struct Lisp_Save_Value *v = XSAVE_VALUE (save);
-
- /* Do not allocate extra space and pack everything in SAVE. */
- v->area = 0;
-
- v->type0 = SAVE_OBJECT;
- v->data[0].object = Fpoint_marker ();
-
- /* Do not copy the mark if it points to nowhere. */
- v->type1 = SAVE_OBJECT;
- v->data[1].object = (XMARKER (BVAR (current_buffer, mark))->buffer
- ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
- : Qnil);
-
- /* Selected window if current buffer is shown in it, nil otherwise. */
- v->type2 = SAVE_OBJECT;
- v->data[2].object
- = ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
- ? selected_window : Qnil);
-
- v->type3 = SAVE_OBJECT;
- v->data[3].object = BVAR (current_buffer, mark_active);
-
- return save;
+ return format_save_value
+ ("oooo",
+ Fpoint_marker (),
+ /* Do not copy the mark if it points to nowhere. */
+ (XMARKER (BVAR (current_buffer, mark))->buffer
+ ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
+ : Qnil),
+ /* Selected window if current buffer is shown in it, nil otherwise. */
+ ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+ ? selected_window : Qnil),
+ BVAR (current_buffer, mark_active));
}
/* Restore saved buffer before leaving `save-excursion' special form. */
{
Lisp_Object tem, tem1, omark, nmark;
struct gcpro gcpro1, gcpro2, gcpro3;
- register struct Lisp_Save_Value *v = XSAVE_VALUE (info);
-
- /* Paranoid. */
- eassert (v->type0 == SAVE_OBJECT && v->type1 == SAVE_OBJECT
- && v->type2 == SAVE_OBJECT && v->type3 == SAVE_OBJECT);
- tem = Fmarker_buffer (v->data[0].object);
+ tem = Fmarker_buffer (XSAVE_OBJECT (info, 0));
/* If we're unwinding to top level, saved buffer may be deleted. This
means that all of its markers are unchained and so tem is nil. */
if (NILP (tem))
Fset_buffer (tem);
/* Point marker. */
- tem = v->data[0].object;
+ tem = XSAVE_OBJECT (info, 0);
Fgoto_char (tem);
unchain_marker (XMARKER (tem));
/* Mark marker. */
- tem = v->data[1].object;
+ tem = XSAVE_OBJECT (info, 1);
omark = Fmarker_position (BVAR (current_buffer, mark));
if (NILP (tem))
unchain_marker (XMARKER (BVAR (current_buffer, mark)));
}
/* Mark active. */
- tem = v->data[3].object;
+ tem = XSAVE_OBJECT (info, 3);
tem1 = BVAR (current_buffer, mark_active);
bset_mark_active (current_buffer, tem);
/* 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 = v->data[2].object;
+ tem = XSAVE_OBJECT (info, 2);
if (WINDOWP (tem)
&& !EQ (tem, selected_window)
&& (tem1 = XWINDOW (tem)->buffer,
#define XSAVE_INTEGER(obj) XSAVE_VALUE (obj)->data[1].integer
+/* Macro to extract Nth saved object. */
+
+#define XSAVE_OBJECT(obj, n) \
+ (eassert (XSAVE_VALUE (obj)->type ## n == SAVE_OBJECT), \
+ XSAVE_VALUE (obj)->data[n].object)
+
/* A miscellaneous object, when it's on the free list. */
struct Lisp_Free
{
/* Defined in alloc.c. */
extern void check_pure_size (void);
-extern Lisp_Object allocate_misc (enum Lisp_Misc_Type);
extern void free_misc (Lisp_Object);
extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
extern void malloc_warning (const char *);
extern Lisp_Object make_float (double);
extern void display_malloc_warning (void);
extern ptrdiff_t inhibit_garbage_collection (void);
+extern Lisp_Object format_save_value (const char *, ...);
extern Lisp_Object make_save_value (void *, ptrdiff_t);
extern void free_save_value (Lisp_Object);
extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);