diff options
| author | Paul Eggert | 2013-03-21 13:56:22 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-03-21 13:56:22 -0700 |
| commit | 7b1123d824e51d40496c242e7a7f173de8936100 (patch) | |
| tree | 0aaafb8bc660f02c35516227bfde2fef344d318a /src | |
| parent | d6723bf7e58e17c889e354bc429f3f134281953a (diff) | |
| download | emacs-7b1123d824e51d40496c242e7a7f173de8936100.tar.gz emacs-7b1123d824e51d40496c242e7a7f173de8936100.zip | |
Use functions and constants to manipulate Lisp_Save_Value objects.
This replaces code that used macros and strings and token-pasting.
The change makes the C source a bit easier to follow,
and shrinks the Emacs executable a bit.
* alloc.c: Verify some properties of Lisp_Save_Value's representation.
(make_save_value): Change 1st arg from string to enum. All callers
changed.
(INTX): Remove.
(mark_object): Use if, not #if, for GC_MARK_STACK.
* lisp.h (SAVE_VALUEP, XSAVE_VALUE, XSAVE_POINTER, XSAVE_INTEGER)
(XSAVE_OBJECT): Now functions, not macros.
(STRING_BYTES_BOUND): Now just a macro, not a constant too;
the constant was never used.
(SAVE_SLOT_BITS, SAVE_VALUE_SLOTS, SAVE_TYPE_BITS, SAVE_TYPE_INT_INT)
(SAVE_TYPE_INT_INT_INT, SAVE_TYPE_OBJ_OBJ, SAVE_TYPE_OBJ_OBJ_OBJ)
(SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, SAVE_TYPE_PTR_INT, SAVE_TYPE_PTR_OBJ)
(SAVE_TYPE_PTR_PTR, SAVE_TYPE_PTR_PTR_OBJ, SAVE_TYPE_MEMORY):
New constants.
(struct Lisp_Save_Value): Replace members area, type0, type1, type2,
type3 with a single member save_type. All uses changed.
(save_type, set_save_pointer, set_save_integer): New functions.
* print.c (PRINTX): Remove.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 23 | ||||
| -rw-r--r-- | src/alloc.c | 95 | ||||
| -rw-r--r-- | src/editfns.c | 7 | ||||
| -rw-r--r-- | src/fileio.c | 3 | ||||
| -rw-r--r-- | src/ftfont.c | 6 | ||||
| -rw-r--r-- | src/keymap.c | 3 | ||||
| -rw-r--r-- | src/lisp.h | 153 | ||||
| -rw-r--r-- | src/print.c | 69 | ||||
| -rw-r--r-- | src/xmenu.c | 2 |
9 files changed, 220 insertions, 141 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index d6b50412f13..f65e08eb6fd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,28 @@ | |||
| 1 | 2013-03-21 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2013-03-21 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Use functions and constants to manipulate Lisp_Save_Value objects. | ||
| 4 | This replaces code that used macros and strings and token-pasting. | ||
| 5 | The change makes the C source a bit easier to follow, | ||
| 6 | and shrinks the Emacs executable a bit. | ||
| 7 | * alloc.c: Verify some properties of Lisp_Save_Value's representation. | ||
| 8 | (make_save_value): Change 1st arg from string to enum. All callers | ||
| 9 | changed. | ||
| 10 | (INTX): Remove. | ||
| 11 | (mark_object): Use if, not #if, for GC_MARK_STACK. | ||
| 12 | * lisp.h (SAVE_VALUEP, XSAVE_VALUE, XSAVE_POINTER, XSAVE_INTEGER) | ||
| 13 | (XSAVE_OBJECT): Now functions, not macros. | ||
| 14 | (STRING_BYTES_BOUND): Now just a macro, not a constant too; | ||
| 15 | the constant was never used. | ||
| 16 | (SAVE_SLOT_BITS, SAVE_VALUE_SLOTS, SAVE_TYPE_BITS, SAVE_TYPE_INT_INT) | ||
| 17 | (SAVE_TYPE_INT_INT_INT, SAVE_TYPE_OBJ_OBJ, SAVE_TYPE_OBJ_OBJ_OBJ) | ||
| 18 | (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, SAVE_TYPE_PTR_INT, SAVE_TYPE_PTR_OBJ) | ||
| 19 | (SAVE_TYPE_PTR_PTR, SAVE_TYPE_PTR_PTR_OBJ, SAVE_TYPE_MEMORY): | ||
| 20 | New constants. | ||
| 21 | (struct Lisp_Save_Value): Replace members area, type0, type1, type2, | ||
| 22 | type3 with a single member save_type. All uses changed. | ||
| 23 | (save_type, set_save_pointer, set_save_integer): New functions. | ||
| 24 | * print.c (PRINTX): Remove. | ||
| 25 | |||
| 3 | * alloc.c: Remove redundant static declarations. | 26 | * alloc.c: Remove redundant static declarations. |
| 4 | 27 | ||
| 5 | 2013-03-20 Dmitry Antipov <dmantipov@yandex.ru> | 28 | 2013-03-20 Dmitry Antipov <dmantipov@yandex.ru> |
diff --git a/src/alloc.c b/src/alloc.c index 39379bc3bd7..4245b3069fa 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3326,56 +3326,50 @@ free_misc (Lisp_Object misc) | |||
| 3326 | total_free_markers++; | 3326 | total_free_markers++; |
| 3327 | } | 3327 | } |
| 3328 | 3328 | ||
| 3329 | /* Verify properties of Lisp_Save_Value's representation | ||
| 3330 | that are assumed here and elsewhere. */ | ||
| 3331 | |||
| 3332 | verify (SAVE_UNUSED == 0); | ||
| 3333 | verify ((SAVE_INTEGER | SAVE_POINTER | SAVE_OBJECT) >> SAVE_SLOT_BITS == 0); | ||
| 3334 | |||
| 3329 | /* Return a Lisp_Save_Value object with the data saved according to | 3335 | /* Return a Lisp_Save_Value object with the data saved according to |
| 3330 | FMT. Format specifiers are `i' for an integer, `p' for a pointer | 3336 | DATA_TYPE. DATA_TYPE should be one of SAVE_TYPE_INT_INT, etc. */ |
| 3331 | and `o' for Lisp_Object. Up to 4 objects can be specified. */ | ||
| 3332 | 3337 | ||
| 3333 | Lisp_Object | 3338 | Lisp_Object |
| 3334 | make_save_value (const char *fmt, ...) | 3339 | make_save_value (enum Lisp_Save_Type save_type, ...) |
| 3335 | { | 3340 | { |
| 3336 | va_list ap; | 3341 | va_list ap; |
| 3337 | int len = strlen (fmt); | 3342 | int i; |
| 3338 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | 3343 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); |
| 3339 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | 3344 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); |
| 3340 | 3345 | ||
| 3341 | eassert (0 < len && len < 5); | 3346 | eassert (0 < save_type |
| 3342 | va_start (ap, fmt); | 3347 | && (save_type < 1 << (SAVE_TYPE_BITS - 1) |
| 3343 | 3348 | || save_type == SAVE_TYPE_MEMORY)); | |
| 3344 | #define INITX(index) \ | 3349 | p->save_type = save_type; |
| 3345 | do { \ | 3350 | va_start (ap, save_type); |
| 3346 | if (len <= index) \ | 3351 | save_type &= ~ (1 << (SAVE_TYPE_BITS - 1)); |
| 3347 | p->type ## index = SAVE_UNUSED; \ | 3352 | |
| 3348 | else \ | 3353 | for (i = 0; save_type; i++, save_type >>= SAVE_SLOT_BITS) |
| 3349 | { \ | 3354 | switch (save_type & ((1 << SAVE_SLOT_BITS) - 1)) |
| 3350 | if (fmt[index] == 'i') \ | 3355 | { |
| 3351 | { \ | 3356 | case SAVE_POINTER: |
| 3352 | p->type ## index = SAVE_INTEGER; \ | 3357 | p->data[i].pointer = va_arg (ap, void *); |
| 3353 | p->data[index].integer = va_arg (ap, ptrdiff_t); \ | 3358 | break; |
| 3354 | } \ | ||
| 3355 | else if (fmt[index] == 'p') \ | ||
| 3356 | { \ | ||
| 3357 | p->type ## index = SAVE_POINTER; \ | ||
| 3358 | p->data[index].pointer = va_arg (ap, void *); \ | ||
| 3359 | } \ | ||
| 3360 | else if (fmt[index] == 'o') \ | ||
| 3361 | { \ | ||
| 3362 | p->type ## index = SAVE_OBJECT; \ | ||
| 3363 | p->data[index].object = va_arg (ap, Lisp_Object); \ | ||
| 3364 | } \ | ||
| 3365 | else \ | ||
| 3366 | emacs_abort (); \ | ||
| 3367 | } \ | ||
| 3368 | } while (0) | ||
| 3369 | 3359 | ||
| 3370 | INITX (0); | 3360 | case SAVE_INTEGER: |
| 3371 | INITX (1); | 3361 | p->data[i].integer = va_arg (ap, ptrdiff_t); |
| 3372 | INITX (2); | 3362 | break; |
| 3373 | INITX (3); | ||
| 3374 | 3363 | ||
| 3375 | #undef INITX | 3364 | case SAVE_OBJECT: |
| 3365 | p->data[i].object = va_arg (ap, Lisp_Object); | ||
| 3366 | break; | ||
| 3367 | |||
| 3368 | default: | ||
| 3369 | emacs_abort (); | ||
| 3370 | } | ||
| 3376 | 3371 | ||
| 3377 | va_end (ap); | 3372 | va_end (ap); |
| 3378 | p->area = 0; | ||
| 3379 | return val; | 3373 | return val; |
| 3380 | } | 3374 | } |
| 3381 | 3375 | ||
| @@ -3386,11 +3380,8 @@ make_save_pointer (void *pointer) | |||
| 3386 | { | 3380 | { |
| 3387 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | 3381 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); |
| 3388 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | 3382 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); |
| 3389 | 3383 | p->save_type = SAVE_POINTER; | |
| 3390 | p->area = 0; | ||
| 3391 | p->type0 = SAVE_POINTER; | ||
| 3392 | p->data[0].pointer = pointer; | 3384 | p->data[0].pointer = pointer; |
| 3393 | p->type1 = p->type2 = p->type3 = SAVE_UNUSED; | ||
| 3394 | return val; | 3385 | return val; |
| 3395 | } | 3386 | } |
| 3396 | 3387 | ||
| @@ -5958,12 +5949,11 @@ mark_object (Lisp_Object arg) | |||
| 5958 | case Lisp_Misc_Save_Value: | 5949 | case Lisp_Misc_Save_Value: |
| 5959 | XMISCANY (obj)->gcmarkbit = 1; | 5950 | XMISCANY (obj)->gcmarkbit = 1; |
| 5960 | { | 5951 | { |
| 5961 | register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); | 5952 | struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); |
| 5962 | /* If `area' is nonzero, `data[0].pointer' is the address | 5953 | /* If `save_type' is zero, `data[0].pointer' is the address |
| 5963 | of a memory area containing `data[1].integer' potential | 5954 | of a memory area containing `data[1].integer' potential |
| 5964 | Lisp_Objects. */ | 5955 | Lisp_Objects. */ |
| 5965 | #if GC_MARK_STACK | 5956 | if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) |
| 5966 | if (ptr->area) | ||
| 5967 | { | 5957 | { |
| 5968 | Lisp_Object *p = ptr->data[0].pointer; | 5958 | Lisp_Object *p = ptr->data[0].pointer; |
| 5969 | ptrdiff_t nelt; | 5959 | ptrdiff_t nelt; |
| @@ -5971,17 +5961,12 @@ mark_object (Lisp_Object arg) | |||
| 5971 | mark_maybe_object (*p); | 5961 | mark_maybe_object (*p); |
| 5972 | } | 5962 | } |
| 5973 | else | 5963 | else |
| 5974 | #endif /* GC_MARK_STACK */ | ||
| 5975 | { | 5964 | { |
| 5976 | /* Find Lisp_Objects in `data[N]' slots and mark them. */ | 5965 | /* Find Lisp_Objects in `data[N]' slots and mark them. */ |
| 5977 | if (ptr->type0 == SAVE_OBJECT) | 5966 | int i; |
| 5978 | mark_object (ptr->data[0].object); | 5967 | for (i = 0; i < SAVE_VALUE_SLOTS; i++) |
| 5979 | if (ptr->type1 == SAVE_OBJECT) | 5968 | if (save_type (ptr, i) == SAVE_OBJECT) |
| 5980 | mark_object (ptr->data[1].object); | 5969 | mark_object (ptr->data[i].object); |
| 5981 | if (ptr->type2 == SAVE_OBJECT) | ||
| 5982 | mark_object (ptr->data[2].object); | ||
| 5983 | if (ptr->type3 == SAVE_OBJECT) | ||
| 5984 | mark_object (ptr->data[3].object); | ||
| 5985 | } | 5970 | } |
| 5986 | } | 5971 | } |
| 5987 | break; | 5972 | break; |
diff --git a/src/editfns.c b/src/editfns.c index f34c574cae3..6357a28e8ea 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -839,7 +839,7 @@ Lisp_Object | |||
| 839 | save_excursion_save (void) | 839 | save_excursion_save (void) |
| 840 | { | 840 | { |
| 841 | return make_save_value | 841 | return make_save_value |
| 842 | ("oooo", | 842 | (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, |
| 843 | Fpoint_marker (), | 843 | Fpoint_marker (), |
| 844 | /* Do not copy the mark if it points to nowhere. */ | 844 | /* Do not copy the mark if it points to nowhere. */ |
| 845 | (XMARKER (BVAR (current_buffer, mark))->buffer | 845 | (XMARKER (BVAR (current_buffer, mark))->buffer |
| @@ -4241,7 +4241,10 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4241 | memcpy (buf, initial_buffer, used); | 4241 | memcpy (buf, initial_buffer, used); |
| 4242 | } | 4242 | } |
| 4243 | else | 4243 | else |
| 4244 | XSAVE_POINTER (buf_save_value, 0) = buf = xrealloc (buf, bufsize); | 4244 | { |
| 4245 | buf = xrealloc (buf, bufsize); | ||
| 4246 | set_save_pointer (buf_save_value, 0, buf); | ||
| 4247 | } | ||
| 4245 | 4248 | ||
| 4246 | p = buf + used; | 4249 | p = buf + used; |
| 4247 | } | 4250 | } |
diff --git a/src/fileio.c b/src/fileio.c index 724250c8aaa..3d7bd9fe216 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -4218,7 +4218,8 @@ by calling `format-decode', which see. */) | |||
| 4218 | to be signaled after decoding the text we read. */ | 4218 | to be signaled after decoding the text we read. */ |
| 4219 | nbytes = internal_condition_case_1 | 4219 | nbytes = internal_condition_case_1 |
| 4220 | (read_non_regular, | 4220 | (read_non_regular, |
| 4221 | make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry), | 4221 | make_save_value (SAVE_TYPE_INT_INT_INT, (ptrdiff_t) fd, |
| 4222 | inserted, trytry), | ||
| 4222 | Qerror, read_non_regular_quit); | 4223 | Qerror, read_non_regular_quit); |
| 4223 | 4224 | ||
| 4224 | if (NILP (nbytes)) | 4225 | if (NILP (nbytes)) |
diff --git a/src/ftfont.c b/src/ftfont.c index 867e25a7a25..0ad173af98a 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -393,7 +393,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for) | |||
| 393 | cache_data = xmalloc (sizeof *cache_data); | 393 | cache_data = xmalloc (sizeof *cache_data); |
| 394 | cache_data->ft_face = NULL; | 394 | cache_data->ft_face = NULL; |
| 395 | cache_data->fc_charset = NULL; | 395 | cache_data->fc_charset = NULL; |
| 396 | val = make_save_value ("pi", cache_data, 0); | 396 | val = make_save_value (SAVE_TYPE_PTR_INT, cache_data, 0); |
| 397 | cache = Fcons (Qnil, val); | 397 | cache = Fcons (Qnil, val); |
| 398 | Fputhash (key, cache, ft_face_cache); | 398 | Fputhash (key, cache, ft_face_cache); |
| 399 | } | 399 | } |
| @@ -1211,7 +1211,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size) | |||
| 1211 | return Qnil; | 1211 | return Qnil; |
| 1212 | } | 1212 | } |
| 1213 | } | 1213 | } |
| 1214 | XSAVE_INTEGER (val, 1)++; | 1214 | set_save_integer (val, 1, XSAVE_INTEGER (val, 1) + 1); |
| 1215 | size = XINT (AREF (entity, FONT_SIZE_INDEX)); | 1215 | size = XINT (AREF (entity, FONT_SIZE_INDEX)); |
| 1216 | if (size == 0) | 1216 | if (size == 0) |
| 1217 | size = pixel_size; | 1217 | size = pixel_size; |
| @@ -1326,7 +1326,7 @@ ftfont_close (FRAME_PTR f, struct font *font) | |||
| 1326 | cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE); | 1326 | cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE); |
| 1327 | eassert (CONSP (cache)); | 1327 | eassert (CONSP (cache)); |
| 1328 | val = XCDR (cache); | 1328 | val = XCDR (cache); |
| 1329 | XSAVE_INTEGER (val, 1)--; | 1329 | set_save_integer (val, 1, XSAVE_INTEGER (val, 1) - 1); |
| 1330 | if (XSAVE_INTEGER (val, 1) == 0) | 1330 | if (XSAVE_INTEGER (val, 1) == 0) |
| 1331 | { | 1331 | { |
| 1332 | struct ftfont_cache_data *cache_data = XSAVE_POINTER (val, 0); | 1332 | struct ftfont_cache_data *cache_data = XSAVE_POINTER (val, 0); |
diff --git a/src/keymap.c b/src/keymap.c index 00eefb375ef..34406a5fc70 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -611,7 +611,8 @@ map_keymap_internal (Lisp_Object map, | |||
| 611 | } | 611 | } |
| 612 | else if (CHAR_TABLE_P (binding)) | 612 | else if (CHAR_TABLE_P (binding)) |
| 613 | map_char_table (map_keymap_char_table_item, Qnil, binding, | 613 | map_char_table (map_keymap_char_table_item, Qnil, binding, |
| 614 | make_save_value ("ppo", fun, data, args)); | 614 | make_save_value (SAVE_TYPE_PTR_PTR_OBJ, |
| 615 | fun, data, args)); | ||
| 615 | } | 616 | } |
| 616 | UNGCPRO; | 617 | UNGCPRO; |
| 617 | return tail; | 618 | return tail; |
diff --git a/src/lisp.h b/src/lisp.h index f526cd36a6f..6838d4a93cb 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -551,6 +551,12 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 551 | return num < lower ? lower : num <= upper ? num : upper; | 551 | return num < lower ? lower : num <= upper ? num : upper; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | |||
| 555 | /* Forward declarations. */ | ||
| 556 | |||
| 557 | LISP_INLINE bool SAVE_VALUEP (Lisp_Object); | ||
| 558 | LISP_INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object); | ||
| 559 | |||
| 554 | /* Extract a value or address from a Lisp_Object. */ | 560 | /* Extract a value or address from a Lisp_Object. */ |
| 555 | 561 | ||
| 556 | #define XCONS(a) (eassert (CONSP (a)), \ | 562 | #define XCONS(a) (eassert (CONSP (a)), \ |
| @@ -571,7 +577,6 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 571 | #define XMISCTYPE(a) (XMISCANY (a)->type) | 577 | #define XMISCTYPE(a) (XMISCANY (a)->type) |
| 572 | #define XMARKER(a) (eassert (MARKERP (a)), &(XMISC (a)->u_marker)) | 578 | #define XMARKER(a) (eassert (MARKERP (a)), &(XMISC (a)->u_marker)) |
| 573 | #define XOVERLAY(a) (eassert (OVERLAYP (a)), &(XMISC (a)->u_overlay)) | 579 | #define XOVERLAY(a) (eassert (OVERLAYP (a)), &(XMISC (a)->u_overlay)) |
| 574 | #define XSAVE_VALUE(a) (eassert (SAVE_VALUEP (a)), &(XMISC (a)->u_save_value)) | ||
| 575 | 580 | ||
| 576 | /* Forwarding object types. */ | 581 | /* Forwarding object types. */ |
| 577 | 582 | ||
| @@ -781,13 +786,10 @@ extern ptrdiff_t string_bytes (struct Lisp_String *); | |||
| 781 | would expose alloc.c internal details that we'd rather keep | 786 | would expose alloc.c internal details that we'd rather keep |
| 782 | private. | 787 | private. |
| 783 | 788 | ||
| 784 | This is a macro for use in static initializers, and a constant for | 789 | This is a macro for use in static initializers. The cast to |
| 785 | visibility to GDB. The cast to ptrdiff_t ensures that | 790 | ptrdiff_t ensures that the macro is signed. */ |
| 786 | the macro is signed. */ | ||
| 787 | static ptrdiff_t const STRING_BYTES_BOUND = | ||
| 788 | #define STRING_BYTES_BOUND \ | 791 | #define STRING_BYTES_BOUND \ |
| 789 | ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)) | 792 | ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)) |
| 790 | STRING_BYTES_BOUND; | ||
| 791 | 793 | ||
| 792 | /* Mark STR as a unibyte string. */ | 794 | /* Mark STR as a unibyte string. */ |
| 793 | #define STRING_SET_UNIBYTE(STR) \ | 795 | #define STRING_SET_UNIBYTE(STR) \ |
| @@ -1392,6 +1394,35 @@ enum | |||
| 1392 | SAVE_OBJECT | 1394 | SAVE_OBJECT |
| 1393 | }; | 1395 | }; |
| 1394 | 1396 | ||
| 1397 | /* Number of bits needed to store one of the above values. */ | ||
| 1398 | enum { SAVE_SLOT_BITS = 2 }; | ||
| 1399 | |||
| 1400 | /* Number of slots in a save value where save_type is nonzero. */ | ||
| 1401 | enum { SAVE_VALUE_SLOTS = 4 }; | ||
| 1402 | |||
| 1403 | /* Bit-width and values for struct Lisp_Save_Value's save_type member. */ | ||
| 1404 | |||
| 1405 | enum { SAVE_TYPE_BITS = SAVE_VALUE_SLOTS * SAVE_SLOT_BITS + 1 }; | ||
| 1406 | |||
| 1407 | enum Lisp_Save_Type | ||
| 1408 | { | ||
| 1409 | SAVE_TYPE_INT_INT = SAVE_INTEGER + (SAVE_INTEGER << SAVE_SLOT_BITS), | ||
| 1410 | SAVE_TYPE_INT_INT_INT | ||
| 1411 | = (SAVE_INTEGER + (SAVE_TYPE_INT_INT << SAVE_SLOT_BITS)), | ||
| 1412 | SAVE_TYPE_OBJ_OBJ = SAVE_OBJECT + (SAVE_OBJECT << SAVE_SLOT_BITS), | ||
| 1413 | SAVE_TYPE_OBJ_OBJ_OBJ = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ << SAVE_SLOT_BITS), | ||
| 1414 | SAVE_TYPE_OBJ_OBJ_OBJ_OBJ | ||
| 1415 | = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ_OBJ << SAVE_SLOT_BITS), | ||
| 1416 | SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS), | ||
| 1417 | SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS), | ||
| 1418 | SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS), | ||
| 1419 | SAVE_TYPE_PTR_PTR_OBJ | ||
| 1420 | = SAVE_POINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS), | ||
| 1421 | |||
| 1422 | /* This has an extra bit indicating it's raw memory. */ | ||
| 1423 | SAVE_TYPE_MEMORY = SAVE_TYPE_PTR_INT + (1 << (SAVE_TYPE_BITS - 1)) | ||
| 1424 | }; | ||
| 1425 | |||
| 1395 | /* Special object used to hold a different values for later use. | 1426 | /* Special object used to hold a different values for later use. |
| 1396 | 1427 | ||
| 1397 | This is mostly used to package C integers and pointers to call | 1428 | This is mostly used to package C integers and pointers to call |
| @@ -1412,73 +1443,96 @@ enum | |||
| 1412 | 1443 | ||
| 1413 | If yon need to pass more than just one C pointer, you should | 1444 | If yon need to pass more than just one C pointer, you should |
| 1414 | use make_save_value. This function allows you to pack up to | 1445 | use make_save_value. This function allows you to pack up to |
| 1415 | 4 integers, pointers or Lisp_Objects and conveniently get them | 1446 | SAVE_VALUE_SLOTS integers, pointers or Lisp_Objects and |
| 1416 | back with XSAVE_POINTER, XSAVE_INTEGER and XSAVE_OBJECT macros: | 1447 | conveniently get them back with XSAVE_POINTER, XSAVE_INTEGER and |
| 1448 | XSAVE_OBJECT macros: | ||
| 1417 | 1449 | ||
| 1418 | ... | 1450 | ... |
| 1419 | struct my_data *md = get_my_data (); | 1451 | struct my_data *md = get_my_data (); |
| 1420 | ptrdiff_t my_offset = get_my_offset (); | ||
| 1421 | Lisp_Object my_object = get_my_object (); | 1452 | Lisp_Object my_object = get_my_object (); |
| 1422 | record_unwind_protect | 1453 | record_unwind_protect |
| 1423 | (my_unwind, make_save_value ("pio", md, my_offset, my_object)); | 1454 | (my_unwind, make_save_value (SAVE_TYPE_PTR_OBJ, md, my_object)); |
| 1424 | ... | 1455 | ... |
| 1425 | 1456 | ||
| 1426 | Lisp_Object my_unwind (Lisp_Object arg) | 1457 | Lisp_Object my_unwind (Lisp_Object arg) |
| 1427 | { | 1458 | { |
| 1428 | struct my_data *md = XSAVE_POINTER (arg, 0); | 1459 | struct my_data *md = XSAVE_POINTER (arg, 0); |
| 1429 | ptrdiff_t my_offset = XSAVE_INTEGER (arg, 1); | 1460 | Lisp_Object my_object = XSAVE_OBJECT (arg, 1); |
| 1430 | Lisp_Object my_object = XSAVE_OBJECT (arg, 2); | ||
| 1431 | ... | 1461 | ... |
| 1432 | } | 1462 | } |
| 1433 | 1463 | ||
| 1434 | If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the | 1464 | If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the |
| 1435 | saved objects and raise eassert if type of the saved object doesn't match | 1465 | saved objects and raise eassert if type of the saved object doesn't match |
| 1436 | the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2) | 1466 | the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2) |
| 1437 | or XSAVE_OBJECT (arg, 1) are wrong because integer was saved in slot 1 and | 1467 | or XSAVE_OBJECT (arg, 0) are wrong because nothing was saved in slot 2 and |
| 1438 | Lisp_Object was saved in slot 2 of ARG. */ | 1468 | Lisp_Object was saved in slot 1 of ARG. */ |
| 1439 | 1469 | ||
| 1440 | struct Lisp_Save_Value | 1470 | struct Lisp_Save_Value |
| 1441 | { | 1471 | { |
| 1442 | ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */ | 1472 | ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */ |
| 1443 | unsigned gcmarkbit : 1; | 1473 | unsigned gcmarkbit : 1; |
| 1444 | int spacer : 6; | 1474 | int spacer : 32 - (16 + 1 + SAVE_TYPE_BITS); |
| 1445 | /* If `area' is nonzero, `data[0].pointer' is the address of a memory area | 1475 | |
| 1446 | containing `data[1].integer' potential Lisp_Objects. The rest of `data' | 1476 | /* DATA[N] may hold up to SAVE_VALUE_SLOTS entries. The type of |
| 1447 | fields are unused. */ | 1477 | V's Ith entry is given by save_type (V, I). E.g., if save_type |
| 1448 | unsigned area : 1; | 1478 | (V, 3) == SAVE_INTEGER, V->data[3].integer is in use. |
| 1449 | /* If `area' is zero, `data[N]' may hold different objects which type is | 1479 | |
| 1450 | encoded in `typeN' fields as described by the anonymous enum above. | 1480 | If SAVE_TYPE == SAVE_TYPE_MEMORY, DATA[0].pointer is the address of |
| 1451 | E.g. if `type0' is SAVE_INTEGER, `data[0].integer' is in use. */ | 1481 | a memory area containing DATA[1].integer potential Lisp_Objects. */ |
| 1452 | unsigned type0 : 2; | 1482 | ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS; |
| 1453 | unsigned type1 : 2; | ||
| 1454 | unsigned type2 : 2; | ||
| 1455 | unsigned type3 : 2; | ||
| 1456 | union { | 1483 | union { |
| 1457 | void *pointer; | 1484 | void *pointer; |
| 1458 | ptrdiff_t integer; | 1485 | ptrdiff_t integer; |
| 1459 | Lisp_Object object; | 1486 | Lisp_Object object; |
| 1460 | } data[4]; | 1487 | } data[SAVE_VALUE_SLOTS]; |
| 1461 | }; | 1488 | }; |
| 1462 | 1489 | ||
| 1463 | /* Macro to set and extract Nth saved pointer. Type | 1490 | /* Return the type of V's Nth saved value. */ |
| 1464 | checking is ugly because it's used as an lvalue. */ | 1491 | LISP_INLINE int |
| 1492 | save_type (struct Lisp_Save_Value *v, int n) | ||
| 1493 | { | ||
| 1494 | eassert (0 <= n && n < SAVE_VALUE_SLOTS); | ||
| 1495 | return (v->save_type >> (SAVE_SLOT_BITS * n) & ((1 << SAVE_SLOT_BITS) - 1)); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | /* Get and set the Nth saved pointer. */ | ||
| 1465 | 1499 | ||
| 1466 | #define XSAVE_POINTER(obj, n) \ | 1500 | LISP_INLINE void * |
| 1467 | XSAVE_VALUE (obj)->data[(eassert (XSAVE_VALUE (obj)->type \ | 1501 | XSAVE_POINTER (Lisp_Object obj, int n) |
| 1468 | ## n == SAVE_POINTER), n)].pointer | 1502 | { |
| 1503 | eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER); | ||
| 1504 | return XSAVE_VALUE (obj)->data[n].pointer;; | ||
| 1505 | } | ||
| 1506 | LISP_INLINE void | ||
| 1507 | set_save_pointer (Lisp_Object obj, int n, void *val) | ||
| 1508 | { | ||
| 1509 | eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER); | ||
| 1510 | XSAVE_VALUE (obj)->data[n].pointer = val; | ||
| 1511 | } | ||
| 1469 | 1512 | ||
| 1470 | /* Likewise for the saved integer. */ | 1513 | /* Likewise for the saved integer. */ |
| 1471 | 1514 | ||
| 1472 | #define XSAVE_INTEGER(obj, n) \ | 1515 | LISP_INLINE ptrdiff_t |
| 1473 | XSAVE_VALUE (obj)->data[(eassert (XSAVE_VALUE (obj)->type \ | 1516 | XSAVE_INTEGER (Lisp_Object obj, int n) |
| 1474 | ## n == SAVE_INTEGER), n)].integer | 1517 | { |
| 1518 | eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER); | ||
| 1519 | return XSAVE_VALUE (obj)->data[n].integer; | ||
| 1520 | } | ||
| 1521 | LISP_INLINE void | ||
| 1522 | set_save_integer (Lisp_Object obj, int n, ptrdiff_t val) | ||
| 1523 | { | ||
| 1524 | eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER); | ||
| 1525 | XSAVE_VALUE (obj)->data[n].integer = val; | ||
| 1526 | } | ||
| 1475 | 1527 | ||
| 1476 | /* Macro to extract Nth saved object. This is never used as | 1528 | /* Extract Nth saved object. */ |
| 1477 | an lvalue, so we can do more convenient type checking. */ | ||
| 1478 | 1529 | ||
| 1479 | #define XSAVE_OBJECT(obj, n) \ | 1530 | LISP_INLINE Lisp_Object |
| 1480 | (eassert (XSAVE_VALUE (obj)->type ## n == SAVE_OBJECT), \ | 1531 | XSAVE_OBJECT (Lisp_Object obj, int n) |
| 1481 | XSAVE_VALUE (obj)->data[n].object) | 1532 | { |
| 1533 | eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_OBJECT); | ||
| 1534 | return XSAVE_VALUE (obj)->data[n].object; | ||
| 1535 | } | ||
| 1482 | 1536 | ||
| 1483 | /* A miscellaneous object, when it's on the free list. */ | 1537 | /* A miscellaneous object, when it's on the free list. */ |
| 1484 | struct Lisp_Free | 1538 | struct Lisp_Free |
| @@ -1501,6 +1555,13 @@ union Lisp_Misc | |||
| 1501 | struct Lisp_Save_Value u_save_value; | 1555 | struct Lisp_Save_Value u_save_value; |
| 1502 | }; | 1556 | }; |
| 1503 | 1557 | ||
| 1558 | LISP_INLINE struct Lisp_Save_Value * | ||
| 1559 | XSAVE_VALUE (Lisp_Object a) | ||
| 1560 | { | ||
| 1561 | eassert (SAVE_VALUEP (a)); | ||
| 1562 | return & XMISC (a)->u_save_value; | ||
| 1563 | } | ||
| 1564 | |||
| 1504 | /* Forwarding pointer to an int variable. | 1565 | /* Forwarding pointer to an int variable. |
| 1505 | This is allowed only in the value cell of a symbol, | 1566 | This is allowed only in the value cell of a symbol, |
| 1506 | and it means that the symbol's value really lives in the | 1567 | and it means that the symbol's value really lives in the |
| @@ -1786,7 +1847,12 @@ typedef struct { | |||
| 1786 | #define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG)) | 1847 | #define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG)) |
| 1787 | #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay) | 1848 | #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay) |
| 1788 | #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker) | 1849 | #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker) |
| 1789 | #define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value) | 1850 | |
| 1851 | LISP_INLINE bool | ||
| 1852 | SAVE_VALUEP (Lisp_Object x) | ||
| 1853 | { | ||
| 1854 | return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value; | ||
| 1855 | } | ||
| 1790 | 1856 | ||
| 1791 | #define AUTOLOADP(x) (CONSP (x) && EQ (Qautoload, XCAR (x))) | 1857 | #define AUTOLOADP(x) (CONSP (x) && EQ (Qautoload, XCAR (x))) |
| 1792 | 1858 | ||
| @@ -3105,7 +3171,7 @@ extern bool abort_on_gc; | |||
| 3105 | extern Lisp_Object make_float (double); | 3171 | extern Lisp_Object make_float (double); |
| 3106 | extern void display_malloc_warning (void); | 3172 | extern void display_malloc_warning (void); |
| 3107 | extern ptrdiff_t inhibit_garbage_collection (void); | 3173 | extern ptrdiff_t inhibit_garbage_collection (void); |
| 3108 | extern Lisp_Object make_save_value (const char *, ...); | 3174 | extern Lisp_Object make_save_value (enum Lisp_Save_Type, ...); |
| 3109 | extern Lisp_Object make_save_pointer (void *); | 3175 | extern Lisp_Object make_save_pointer (void *); |
| 3110 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); | 3176 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); |
| 3111 | extern void free_marker (Lisp_Object); | 3177 | extern void free_marker (Lisp_Object); |
| @@ -3822,8 +3888,7 @@ extern void *record_xmalloc (size_t); | |||
| 3822 | { \ | 3888 | { \ |
| 3823 | Lisp_Object arg_; \ | 3889 | Lisp_Object arg_; \ |
| 3824 | buf = xmalloc ((nelt) * word_size); \ | 3890 | buf = xmalloc ((nelt) * word_size); \ |
| 3825 | arg_ = make_save_value ("pi", buf, nelt); \ | 3891 | arg_ = make_save_value (SAVE_TYPE_MEMORY, buf, nelt); \ |
| 3826 | XSAVE_VALUE (arg_)->area = 1; \ | ||
| 3827 | sa_must_free = 1; \ | 3892 | sa_must_free = 1; \ |
| 3828 | record_unwind_protect (safe_alloca_unwind, arg_); \ | 3893 | record_unwind_protect (safe_alloca_unwind, arg_); \ |
| 3829 | } \ | 3894 | } \ |
diff --git a/src/print.c b/src/print.c index 53c0d99f836..4ab80fe1605 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -2042,17 +2042,15 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2042 | 2042 | ||
| 2043 | strout ("#<save-value ", -1, -1, printcharfun); | 2043 | strout ("#<save-value ", -1, -1, printcharfun); |
| 2044 | 2044 | ||
| 2045 | if (v->area) | 2045 | if (v->save_type == SAVE_TYPE_MEMORY) |
| 2046 | { | 2046 | { |
| 2047 | ptrdiff_t amount = v->data[1].integer; | 2047 | ptrdiff_t amount = v->data[1].integer; |
| 2048 | 2048 | ||
| 2049 | #if GC_MARK_STACK | 2049 | #if GC_MARK_STACK |
| 2050 | 2050 | ||
| 2051 | /* If GC_MARK_STACK, valid_lisp_object_p is quite reliable, | 2051 | /* valid_lisp_object_p is reliable, so try to print up |
| 2052 | and so we try to print up to 8 objects we have saved. | 2052 | to 8 saved objects. This code is rarely used, so |
| 2053 | Although valid_lisp_object_p is slow, this shouldn't be | 2053 | it's OK that valid_lisp_object_p is slow. */ |
| 2054 | a real bottleneck because we do not use this code under | ||
| 2055 | normal circumstances. */ | ||
| 2056 | 2054 | ||
| 2057 | int limit = min (amount, 8); | 2055 | int limit = min (amount, 8); |
| 2058 | Lisp_Object *area = v->data[0].pointer; | 2056 | Lisp_Object *area = v->data[0].pointer; |
| @@ -2077,9 +2075,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2077 | 2075 | ||
| 2078 | #else /* not GC_MARK_STACK */ | 2076 | #else /* not GC_MARK_STACK */ |
| 2079 | 2077 | ||
| 2080 | /* If !GC_MARK_STACK, we have no reliable way to find | 2078 | /* There is no reliable way to determine whether the objects |
| 2081 | whether Lisp_Object pointers points to an initialized | 2079 | are initialized, so do not try to print them. */ |
| 2082 | objects, and so we do not ever trying to print them. */ | ||
| 2083 | 2080 | ||
| 2084 | i = sprintf (buf, "with %"pD"d objects", amount); | 2081 | i = sprintf (buf, "with %"pD"d objects", amount); |
| 2085 | strout (buf, i, i, printcharfun); | 2082 | strout (buf, i, i, printcharfun); |
| @@ -2088,33 +2085,37 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 2088 | } | 2085 | } |
| 2089 | else | 2086 | else |
| 2090 | { | 2087 | { |
| 2091 | /* Print each `data[N]' slot according to its type. */ | 2088 | /* Print each slot according to its type. */ |
| 2092 | 2089 | int index; | |
| 2093 | #define PRINTX(index) \ | 2090 | for (index = 0; index < SAVE_VALUE_SLOTS; index++) |
| 2094 | do { \ | 2091 | { |
| 2095 | i = 0; \ | 2092 | if (index) |
| 2096 | if (v->type ## index == SAVE_UNUSED) \ | 2093 | PRINTCHAR (' '); |
| 2097 | i = sprintf (buf, "<unused>"); \ | ||
| 2098 | else if (v->type ## index == SAVE_INTEGER) \ | ||
| 2099 | i = sprintf (buf, "<integer %"pD"d>", v->data[index].integer); \ | ||
| 2100 | else if (v->type ## index == SAVE_POINTER) \ | ||
| 2101 | i = sprintf (buf, "<pointer %p>", v->data[index].pointer); \ | ||
| 2102 | else /* SAVE_OBJECT */ \ | ||
| 2103 | print_object (v->data[index].object, printcharfun, escapeflag); \ | ||
| 2104 | if (i) \ | ||
| 2105 | strout (buf, i, i, printcharfun); \ | ||
| 2106 | } while (0) | ||
| 2107 | |||
| 2108 | PRINTX (0); | ||
| 2109 | PRINTCHAR (' '); | ||
| 2110 | PRINTX (1); | ||
| 2111 | PRINTCHAR (' '); | ||
| 2112 | PRINTX (2); | ||
| 2113 | PRINTCHAR (' '); | ||
| 2114 | PRINTX (3); | ||
| 2115 | 2094 | ||
| 2116 | #undef PRINTX | 2095 | switch (save_type (v, index)) |
| 2096 | { | ||
| 2097 | case SAVE_UNUSED: | ||
| 2098 | i = sprintf (buf, "<unused>"); | ||
| 2099 | break; | ||
| 2100 | |||
| 2101 | case SAVE_POINTER: | ||
| 2102 | i = sprintf (buf, "<pointer %p>", | ||
| 2103 | v->data[index].pointer); | ||
| 2104 | break; | ||
| 2105 | |||
| 2106 | case SAVE_INTEGER: | ||
| 2107 | i = sprintf (buf, "<integer %"pD"d>", | ||
| 2108 | v->data[index].integer); | ||
| 2109 | break; | ||
| 2110 | |||
| 2111 | case SAVE_OBJECT: | ||
| 2112 | print_object (v->data[index].object, printcharfun, | ||
| 2113 | escapeflag); | ||
| 2114 | continue; | ||
| 2115 | } | ||
| 2117 | 2116 | ||
| 2117 | strout (buf, i, i, printcharfun); | ||
| 2118 | } | ||
| 2118 | } | 2119 | } |
| 2119 | PRINTCHAR ('>'); | 2120 | PRINTCHAR ('>'); |
| 2120 | } | 2121 | } |
diff --git a/src/xmenu.c b/src/xmenu.c index 958cd220393..57cf27f955d 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -2479,7 +2479,7 @@ xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, | |||
| 2479 | #endif | 2479 | #endif |
| 2480 | 2480 | ||
| 2481 | record_unwind_protect (pop_down_menu, | 2481 | record_unwind_protect (pop_down_menu, |
| 2482 | make_save_value ("pp", f, menu)); | 2482 | make_save_value (SAVE_TYPE_PTR_PTR, f, menu)); |
| 2483 | 2483 | ||
| 2484 | /* Help display under X won't work because XMenuActivate contains | 2484 | /* Help display under X won't work because XMenuActivate contains |
| 2485 | a loop that doesn't give Emacs a chance to process it. */ | 2485 | a loop that doesn't give Emacs a chance to process it. */ |