From owner-freebsd-current Fri Mar 31 09:37:43 1995 Return-Path: current-owner Received: (from majordom@localhost) by freefall.cdrom.com (8.6.10/8.6.6) id JAA28789 for current-outgoing; Fri, 31 Mar 1995 09:37:43 -0800 Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.34]) by freefall.cdrom.com (8.6.10/8.6.6) with ESMTP id JAA28767; Fri, 31 Mar 1995 09:37:30 -0800 Received: (from bde@localhost) by godzilla.zeta.org.au (8.6.9/8.6.9) id DAA07088; Sat, 1 Apr 1995 03:35:38 +1000 Date: Sat, 1 Apr 1995 03:35:38 +1000 From: Bruce Evans Message-Id: <199503311735.DAA07088@godzilla.zeta.org.au> To: jkh@freefall.cdrom.com, wollman@halloran-eldar.lcs.mit.edu Subject: Re: dlopen() and Garrett's comments on fn pointers! Cc: current@freefall.cdrom.com Sender: current-owner@FreeBSD.org Precedence: bulk >> In case no one has noticed, the dlsym() routine returns a void* for >> both function and data pointers! :-) >Yup. You have to take an intermediate step through a large-enough >integer (like unsigned long) in order to do it without diagnostics. >(The result is still implementation-defined.) Interesting. dlsym() does the following: long addr; /* WRONG large-enough integral type * (subject to unwanted overflow traps * and 1's complement conversions). */ ... addr = np->nz_value; /* nz_value is RIGHT large-enough type * (unsigned long). */ ... /* sometimes adjust `addr' */ return (void *)addr; /* match the losing interface */ The rules for unportable casts are: 1. pointer -> integral: this may be done for some implementation defined integral type. The result is implementation defined. Casting to an integral type smaller than this type is undefined. Where do we define this type? :-) 2. integral -> pointer: this may always be done. The result is implementation defined. [others omitted]. n. object pointer <-> function pointer: never allowed (but rules 1-2 allow pointer -> big integral -> pointer). dlsym() should return the large-enough integral type and let the caller cast it. Rule 2 should not be used to mask errors. The intermediate step actually makes the cast implementation defined instead of undefined. gcc on i*86's apparently prints more diagnostics for the undefined case but you can't depend on this - it can do whatever for the undefined case, including silently making it work, and it should warn for implementation defined cases iff a cast loses information. None of this should apply to the forms library unless you have dynamic forms and want to write pointers to the forms objects and functions to disk. Bruce