Don't convert function pointers to void * and back.
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 2 Jul 2013 03:41:16 +0000 (20:41 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 2 Jul 2013 03:41:16 +0000 (20:41 -0700)
It isn't portable C, and it's easy enough to avoid.
* alloc.c: Verify SAVE_FUNCPOINTER bits, too.
(make_save_value): Add support for SAVE_FUNCPOINTER.
* keymap.c (map_keymap_char_table_item, map_keymap_internal):
* print.c (print_object):
Distinguish function from object pointers.
* lisp.h (SAVE_FUNCPOINTER): New constant.
(SAVE_SLOT_BITS): Adjust to it.
(SAVE_TYPE_FUNCPTR_PTR_OBJ): New constant, replacing
SAVE_TYPE_PTR_PTR_OBJ.  Change the only use.
(voidfuncptr): New typedef.
(struct Lisp_Save_Value): New member data[0].funcpointer.
(XSAVE_FUNCPOINTER): New function.

src/ChangeLog
src/alloc.c
src/keymap.c
src/lisp.h
src/print.c

index 2dc1af6..13a9162 100644 (file)
@@ -1,5 +1,20 @@
 2013-07-02  Paul Eggert  <eggert@cs.ucla.edu>
 
+       Don't convert function pointers to void * and back.
+       It isn't portable C, and it's easy enough to avoid.
+       * alloc.c: Verify SAVE_FUNCPOINTER bits, too.
+       (make_save_value): Add support for SAVE_FUNCPOINTER.
+       * keymap.c (map_keymap_char_table_item, map_keymap_internal):
+       * print.c (print_object):
+       Distinguish function from object pointers.
+       * lisp.h (SAVE_FUNCPOINTER): New constant.
+       (SAVE_SLOT_BITS): Adjust to it.
+       (SAVE_TYPE_FUNCPTR_PTR_OBJ): New constant, replacing
+       SAVE_TYPE_PTR_PTR_OBJ.  Change the only use.
+       (voidfuncptr): New typedef.
+       (struct Lisp_Save_Value): New member data[0].funcpointer.
+       (XSAVE_FUNCPOINTER): New function.
+
        Simplify buildobj processing.
        * Makefile.in (buildobj.h): Make it a sequence of strings each
        followed by comma, rather than a single string.  Put it into a
index eaef0d4..b625e1f 100644 (file)
@@ -3352,7 +3352,9 @@ free_misc (Lisp_Object misc)
    that are assumed here and elsewhere.  */
 
 verify (SAVE_UNUSED == 0);
-verify ((SAVE_INTEGER | SAVE_POINTER | SAVE_OBJECT) >> SAVE_SLOT_BITS == 0);
+verify (((SAVE_INTEGER | SAVE_POINTER | SAVE_FUNCPOINTER | SAVE_OBJECT)
+        >> SAVE_SLOT_BITS)
+       == 0);
 
 /* Return a Lisp_Save_Value object with the data saved according to
    DATA_TYPE.  DATA_TYPE should be one of SAVE_TYPE_INT_INT, etc.  */
@@ -3379,6 +3381,10 @@ make_save_value (enum Lisp_Save_Type save_type, ...)
        p->data[i].pointer = va_arg (ap, void *);
        break;
 
+      case SAVE_FUNCPOINTER:
+       p->data[i].funcpointer = va_arg (ap, voidfuncptr);
+       break;
+
       case SAVE_INTEGER:
        p->data[i].integer = va_arg (ap, ptrdiff_t);
        break;
index 4e3eff3..d29d563 100644 (file)
@@ -572,7 +572,7 @@ map_keymap_char_table_item (Lisp_Object args, Lisp_Object key, Lisp_Object val)
   if (!NILP (val))
     {
       map_keymap_function_t fun
-       = (map_keymap_function_t) XSAVE_POINTER (args, 0);
+       = (map_keymap_function_t) XSAVE_FUNCPOINTER (args, 0);
       /* If the key is a range, make a copy since map_char_table modifies
         it in place.  */
       if (CONSP (key))
@@ -617,8 +617,8 @@ map_keymap_internal (Lisp_Object map,
        }
       else if (CHAR_TABLE_P (binding))
        map_char_table (map_keymap_char_table_item, Qnil, binding,
-                       make_save_value (SAVE_TYPE_PTR_PTR_OBJ,
-                                        fun, data, args));
+                       make_save_value (SAVE_TYPE_FUNCPTR_PTR_OBJ,
+                                        (voidfuncptr) fun, data, args));
     }
   UNGCPRO;
   return tail;
index f4356cd..74f52b3 100644 (file)
@@ -1777,12 +1777,13 @@ enum
   {
     SAVE_UNUSED,
     SAVE_INTEGER,
+    SAVE_FUNCPOINTER,
     SAVE_POINTER,
     SAVE_OBJECT
   };
 
 /* Number of bits needed to store one of the above values.  */
-enum { SAVE_SLOT_BITS = 2 };
+enum { SAVE_SLOT_BITS = 3 };
 
 /* Number of slots in a save value where save_type is nonzero.  */
 enum { SAVE_VALUE_SLOTS = 4 };
@@ -1803,8 +1804,8 @@ enum Lisp_Save_Type
     SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS),
     SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS),
     SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS),
-    SAVE_TYPE_PTR_PTR_OBJ
-      = SAVE_POINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS),
+    SAVE_TYPE_FUNCPTR_PTR_OBJ
+      = SAVE_FUNCPOINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS),
 
     /* This has an extra bit indicating it's raw memory.  */
     SAVE_TYPE_MEMORY = SAVE_TYPE_PTR_INT + (1 << (SAVE_TYPE_BITS - 1))
@@ -1813,9 +1814,9 @@ enum Lisp_Save_Type
 /* Special object used to hold a different values for later use.
 
    This is mostly used to package C integers and pointers to call
-   record_unwind_protect.  Typical task is to pass just one C pointer
-   to unwind function.  You should pack pointer with make_save_pointer
-   and then get it back with XSAVE_POINTER, e.g.:
+   record_unwind_protect.  A typical task is to pass just one C object
+   pointer to the unwind function.  You should pack an object pointer with
+   make_save_pointer and then get it back with XSAVE_POINTER, e.g.:
 
    ...
      struct my_data *md = get_my_data ();
@@ -1828,10 +1829,10 @@ enum Lisp_Save_Type
      ...
    }
 
-   If yon need to pass more than just one C pointer, you should
-   use make_save_value.  This function allows you to pack up to
-   SAVE_VALUE_SLOTS integers, pointers or Lisp_Objects and
-   conveniently get them back with XSAVE_POINTER, XSAVE_INTEGER and
+   If you need to pass something else you can use make_save_value,
+   which allows you to pack up to SAVE_VALUE_SLOTS integers, pointers,
+   function pointers or Lisp_Objects and conveniently get them back
+   with XSAVE_INTEGER, XSAVE_POINTER, XSAVE_FUNCPOINTER, and
    XSAVE_OBJECT macros:
 
    ...
@@ -1854,6 +1855,8 @@ enum Lisp_Save_Type
    or XSAVE_OBJECT (arg, 0) are wrong because nothing was saved in slot 2 and
    Lisp_Object was saved in slot 1 of ARG.  */
 
+typedef void (*voidfuncptr) (void);
+
 struct Lisp_Save_Value
   {
     ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Save_Value */
@@ -1869,6 +1872,7 @@ struct Lisp_Save_Value
     ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;
     union {
       void *pointer;
+      voidfuncptr funcpointer;
       ptrdiff_t integer;
       Lisp_Object object;
     } data[SAVE_VALUE_SLOTS];
@@ -1888,7 +1892,7 @@ LISP_INLINE void *
 XSAVE_POINTER (Lisp_Object obj, int n)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
-  return XSAVE_VALUE (obj)->data[n].pointer;;
+  return XSAVE_VALUE (obj)->data[n].pointer;
 }
 LISP_INLINE void
 set_save_pointer (Lisp_Object obj, int n, void *val)
@@ -1896,6 +1900,12 @@ set_save_pointer (Lisp_Object obj, int n, void *val)
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
   XSAVE_VALUE (obj)->data[n].pointer = val;
 }
+LISP_INLINE voidfuncptr
+XSAVE_FUNCPOINTER (Lisp_Object obj, int n)
+{
+  eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_FUNCPOINTER);
+  return XSAVE_VALUE (obj)->data[n].funcpointer;
+}
 
 /* Likewise for the saved integer.  */
 
index 811ab50..b1eec4c 100644 (file)
@@ -2103,6 +2103,12 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
                                     v->data[index].pointer);
                        break;
 
+                     case SAVE_FUNCPOINTER:
+                       i = sprintf (buf, "<funcpointer %p>",
+                                    ((void *) (intptr_t)
+                                     v->data[index].funcpointer));
+                       break;
+
                      case SAVE_INTEGER:
                        i = sprintf (buf, "<integer %"pD"d>",
                                     v->data[index].integer);
@@ -2112,6 +2118,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
                        print_object (v->data[index].object, printcharfun,
                                      escapeflag);
                        continue;
+
+                     default:
+                       emacs_abort ();
                      }
 
                    strout (buf, i, i, printcharfun);