diff --git a/ChangeLog b/ChangeLog index 265beb9b2..b8d7fbbbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2000-12-08 Adam Fedor + + * Set up DO and NSInvocation to use foreign-function interface + library. + * configure.in: Add check for --enable-ffcall + * Documentation/gnustep-base.texi: Update + * Documentation/install.texi: Likewise. + * Documentation/readme.texi: Likewise. + * Documentation/gsdoc/NSTimeZone.gsdoc: Update. + + * Headers/gnustep/base/NSConnection.h: New forward method. + * Headers/gnustep/base/NSInvocation.h: New frame ivar. + * Source/GNUmakefile: Conditionally compile in FFI classes if + enabled. + * Source/NSConnection.m (-forwardInvocation:forProxy:): New method. + (_service_forwardForProxy:): For FFCALL don't autorelease memory, + call proper forwarding function. + * Source/NSDistantObject.m (forwardInvocation:): Implement. + (methodSignatureForSelector:): For FFCALL, forward through + invocation. + (conformsToProtocol:): Likewise. + (respondsToSelector:): Likewise. + * Source/NSInvocation.m: Convert to abstract class with subclasses + based on FFI interface. + (_get_arg, _set_arg, _arg_addr): New functions based on FFI interface. + (+allocWithZone:): Alloc proper concrete class. + (+initialize): Set proper concrete class. + (-initWithCoder:): Replace self with proper concrete class. + (initWithArgframe:selector:): Make subclassResponsibility. + (initWithMethodSignature:): Likewise. + (returnFrame:): Likewise. + Implement GSFrameInvocation + * Source/GSFFCallInvocation: New file. + * Source/GSFFIInvocation: Likewise. + * Source/cifframe.[hm]: Likewise. + * Source/callframe.[hm]: Likewise. + 2000-12-07 Richard Frith-Macdonald * Source/NSGSet.m: renamed to GSSet.m for consistency, tidied. diff --git a/Documentation/GNUmakefile b/Documentation/GNUmakefile index 112a418f5..d5a6a83a1 100644 --- a/Documentation/GNUmakefile +++ b/Documentation/GNUmakefile @@ -31,7 +31,7 @@ include ../Version include ../config.mak # The documents to be generated -DOCUMENT_NAME = gnustep-base coding-standards +DOCUMENT_NAME = coding-standards # The text documents to be generated DOCUMENT_TEXT_NAME = \ diff --git a/Documentation/gnustep-base.texi b/Documentation/gnustep-base.texi index 9f1a13c4e..1ac2416f6 100644 --- a/Documentation/gnustep-base.texi +++ b/Documentation/gnustep-base.texi @@ -114,47 +114,6 @@ site @url{http://www.gnustep.org/information}. Documentation for individual classes is included in gsdoc (and html) format in the gsdoc directory. -@node Configuration, Classes, Overview, Top -@chapter Configuration - -Configuration is performed by running the @file{configure} program at a -shell prompt. You may want to use some of the optional arguments to the -@file{configure} program. Type @code{configure --help} -for a list of these. It is not likely that you will need to use the -@code{--prefix} option, since gstep-base will automatically install in -the directory specified by the @code{GNUSTEP_SYSTEM_ROOT} environment -variable (specified when you installed gstep-make). - -The only feature you may want to use is the -@code{--enable-pass-arguments} or the @code{--enable-fake-main} -option(s). Normally, the configure script will determine if a program -can read process information directly from the system (for use by the -class NSProcessInfo) and enable or disable the fake-main hack -automatically, but if you find that configure is not doing this -correctly, you can force the fake-main hack to be used, which will -always work. Note that if the fake-main hack is enabled, you need to -include the header file GSConfig.h in you main program -- this is done -by default if you include NSObject.h or Foundation.h. If you want to -avoid the whole idea of the fake-main hack, you can use the -pass-arguments option. In this case you will be forced to call the -NSProcessInfo initializeWithArguments method to pass the program -arguments to NSProcessInfo (This would be done automatically if you use -the NSApplicationMain function in a gui application). - -Most other important configuration options are already set when you -configure the gstep-make package. - -@node Classes, Tools, Configuration, Top -@chapter Special Features of gstep-base Classes - -@node Tools, Installation, Classes, Top -@chapter Special Tools Included with gstep-base - -@node Installation, Implementation, Tools, Top -@chapter Installing GNU Objective-C Class Library - -Type @code{make install} to install the libraries and programs - @node Implementation, Concept Index, Installation, Top @chapter Implementation Details @@ -241,42 +200,5 @@ so you don't need to worry about releasing it yourself. However, if you wish to store the object for any length of time, you will need to send it a retain message, and then send it a release when you have finished with it. -@node Garbage Collection, Time Zone, Reference Counting, Implementation -@section Garbage Collection - - -@node Time Zone, , Garbage Collection, Implementation -@section Time Zones - -If the GNUstep time zone datafiles become too out of date, one can -download an updated database from @url{ftp://elsie.nci.nih.gov/pub/} and -compile it as specified in the README file in the NSTimeZones -directory. (In fact, I believe it's about time they're updated.) - -@example - Time zone names in NSDates should be GMT, MET etc. not - Europe/Berlin, America/Washington etc. -@end example - -The problem with this is that various time zones may use the same -abbreviation (e.g. Australia/@{Brisbane,...@} and America/@{New_York,...@} -both use EST), and some time zones may have different rules for -daylight saving time even if the abbreviation and offsets from UTC are -the same. - -The problems with depending on the OS for providing time zone info are -that some methods for the NSTimeZone classes might be difficult to -implement, and also that time zone names may vary wildly between OSes -(this could be a big problem when archiving is used between different -systems). - - - -@node Concept Index, , Implementation, Top -@unnumbered Concept Index -@printindex cp - -@summarycontents -@contents @bye diff --git a/Documentation/gsdoc/NSTimeZone.gsdoc b/Documentation/gsdoc/NSTimeZone.gsdoc index f457c93f3..cb24e1e88 100644 --- a/Documentation/gsdoc/NSTimeZone.gsdoc +++ b/Documentation/gsdoc/NSTimeZone.gsdoc @@ -18,6 +18,29 @@ NSCoding +

+ If the GNUstep time zone datafiles become too out of date, one + can download an updated database from ftp://elsie.nci.nih.gov/pub/ + and compile it as specified in the README file in the + NSTimeZones directory. + + Time zone names in NSDates should be GMT, MET etc. not + Europe/Berlin, America/Washington etc. + + The problem with this is that various time zones may use the + same abbreviation (e.g. Australia/Brisbane and + America/New_York both use EST), and some time zones + may have different rules for daylight saving time even if the + abbreviation and offsets from UTC are the same. + + The problems with depending on the OS for providing time zone + info are that some methods for the NSTimeZone classes might be + difficult to implement, and also that time zone names may vary + wildly between OSes (this could be a big problem when + archiving is used between different systems). +

+ abbreviationDictionary diff --git a/Documentation/install.texi b/Documentation/install.texi index 835e20691..64d992bc1 100644 --- a/Documentation/install.texi +++ b/Documentation/install.texi @@ -5,17 +5,129 @@ @c set the vars GNUSTEP_BASE_VERSION and GNUSTEP_BASE_GCC_VERSION @include version.texi -@ifset TEXT_ONLY -This file documents the installation of the GNUstep Base Library, -@samp{libgnustep-base}. Copyright (C) 1993, 1994, 1996, 1997 Free Software -Foundation, Inc. You may copy, distribute, and modify it freely as long -as you preserve this copyright notice and permission notice. -@chapter Installing @samp{libgnustep-base} -@end ifset +@node Top, Introduction, (dir), (dir) + +@menu +* Introduction:: +* Configuration:: +* Reading Command-Line Arguments:: +* FFI Library:: +* Compilation:: +@end menu + +@node Introduction, Configuration, Top, Top +@section Introduction + +If you are installing this package as part of the GNUstep core +libraries, read the file GNUstep-HOWTO for more complete instructions on +how to install the entire GNUstep package (including this library). +GNUstep-HOWTO comes with the core distribution and also is located at the +same ftp sites as this library. + +If you are instsalling the GNUstep libraries individually, make sure you +have installed the GNUstep Makefile package (gstep-make) already. Most of +the installation instructions for gstep-make also apply to this +library. When you configure this library, make sure you use the same +configuration options as with gstep-make. Some additional options to +configure are described below. + +@node Configuration, Reading Command-Line Arguments, Introduction, Top +@section Configuration + +Configuration is performed by running the @file{configure} program at a +shell prompt. You may want to use some of the optional arguments to the +@file{configure} program. Type @code{configure --help} +for a list of these. It is not likely that you will need to use the +@code{--prefix} option, since gstep-base will automatically install in +the directory specified by the @code{GNUSTEP_SYSTEM_ROOT} environment +variable (specified when you installed gstep-make). + +Many configuration options for the base library need to be specified +when configuring the gstep-make package. In most cases, it is a good +idea to specify the same configuration options when configuring both +packages, just to make sure. + +Also make sure you've read the machine-specific instructions for your +particular operating system and CPU. These instructions come with the +core libraries and are also located at the GNUstep web site at +@url{http://www.gnustep.org}. + +@menu +* Reading Command-Line Arguments:: +* FFI Library:: +@end menu + +@node Reading Command-Line Arguments, FFI Library, Configuration, Top +@section Reading Command-Line Arguments + +There are two features that change how GNUstep gets access to +command-line arguments and environment variables (normally passed to +the program in the @code{main()} function. These features are +@code{--enable-pass-arguments} and the @code{--enable-fake-main} +option(s). + +The fake-main option @emph{secretly} renames the @code{main()} function +and substitutes it's own function which stores the command line +arguments before calling the real main. + +The pass-arguments option absolves GNUstep of any effort to get the +command-line arguments and instead forces the developer to insert the +line + +@example + [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; +@end example + +in the @code{main()} function of their program. + +Normally, the configure script will determine if a program +can read process information directly from the system (for use by the +class NSProcessInfo) and enable or disable the fake-main hack +automatically, but if you find that configure is not doing this +correctly, you can force the fake-main hack to be used, which will +always work. Note that if the fake-main hack is enabled, you need to +include the header file GSConfig.h in you main program -- this is done +by default if you include NSObject.h or Foundation.h. If you want to +avoid the whole idea of the fake-main hack, you can use the +pass-arguments option. In this case you will be forced to call the +NSProcessInfo initializeWithArguments method to pass the program +arguments to NSProcessInfo (This would be done automatically if you use +the NSApplicationMain function in a gui application). + +@node FFI Library, Compilation, Reading Command-Line Arguments, Top +@section FFI Library + +GNUstep's NSInvocations and Distributed Objects code involves detailed +manipulation of function (method) calls, which does not work on all +machine architectures. A more robust and portable solution is to use a +library that implements a Foreign-Function Interface (FFI), such as the +ffcall libraries. If you use a non-x86 machine, you should seriously +consider enabling this option using @code{--enable-ffcall}. + +For this to work, you need to have the ffcall libraries, which you can +get from @url{ftp://ftp.santafe.edu/pub/gnu/} or +@url{http://clisp.cons.org/~haible/}. You also need to have a special +version of the Objective-C library (as of gcc 2.95.x the required hooks +are not in the standard library). You can get this library from +@url{ftp://www.gnustep.org/pub/gnustep/contrib/libobjc-hh.tar.gz} or +patch the standard library with the patch at +@url{ftp://www.gnustep.org/pub/gnustep/contrib/libobjc-ffi.patch}. + +Make sure you specify this option when configuring gstep-make also. + +@node Compilation, , FFI Library, Top +@section Compilation + +To compile this library, type make. After this is complete, type make +install (make sure you are the root user). Some additional options you +can use with make are @samp{debug=yes} to make a debugging version of +the library and @samp{shared=no} to make a static version of the +library. See the gstep-make package for more information on these options. -Read the file GNUstep-HOWTO for instructions on how to install the -entire GNUstep package (including the base library). -GNUstep-HOWTO comes with this distribution and also -is located at the same ftp sites as this library. @bye + + + + + diff --git a/Documentation/readme.texi b/Documentation/readme.texi index 1010662ab..b611964b4 100644 --- a/Documentation/readme.texi +++ b/Documentation/readme.texi @@ -11,8 +11,8 @@ Here is some introductory info to get you started: The file @samp{NEWS} has the library's feature history. -The file @samp{GNUstep-HOWTO} -give instructions for installing the library. +The files @samp{INSTALL} or @samp{GNUstep-HOWTO} (from the core package) +gives instructions for installing the library. @section How can you help? diff --git a/Headers/gnustep/base/GSInvocation.h b/Headers/gnustep/base/GSInvocation.h new file mode 100644 index 000000000..939ec1a1f --- /dev/null +++ b/Headers/gnustep/base/GSInvocation.h @@ -0,0 +1,51 @@ +/* Interface for NSInvocation concrete classes for GNUStep + Copyright (C) 1998 Free Software Foundation, Inc. + + Written: Adam Fedor + Date: Nov 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#ifndef __GSInvocation_h_GNUSTEP_BASE_INCLUDE +#define __GSInvocation_h_GNUSTEP_BASE_INCLUDE + +#include + +@interface GSFFIInvocation : NSInvocation +{ +} +@end + +@interface GSFFCallInvocation : NSInvocation +{ +} +@end + +@interface GSFrameInvocation : NSInvocation +{ +} +@end + +@interface NSInvocation (DistantCoding) +- (BOOL) encodeWithDistantCoder: (NSCoder*)coder passPointers: (BOOL)passp; +@end + +extern void +GSFFCallInvokeWithTargetAndImp(NSInvocation *inv, id anObject, IMP imp); + +#endif diff --git a/Headers/gnustep/base/NSConnection.h b/Headers/gnustep/base/NSConnection.h index db6efb240..5cf0f2ca5 100644 --- a/Headers/gnustep/base/NSConnection.h +++ b/Headers/gnustep/base/NSConnection.h @@ -36,6 +36,7 @@ @class NSPort; @class NSPortNameServer; @class NSData; +@class NSInvocation; /* * Keys for the NSDictionary returned by [NSConnection -statistics] @@ -159,6 +160,8 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */ - (retval_t) forwardForProxy: (NSDistantObject*)object selector: (SEL)sel argFrame: (arglist_t)frame; +- (void) forwardInvocation: (NSInvocation *)inv + forProxy: (NSDistantObject*)object; - (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target; @end diff --git a/Headers/gnustep/base/NSInvocation.h b/Headers/gnustep/base/NSInvocation.h index e4b2facff..f43eca8b6 100644 --- a/Headers/gnustep/base/NSInvocation.h +++ b/Headers/gnustep/base/NSInvocation.h @@ -31,6 +31,7 @@ { NSMethodSignature *_sig; arglist_t _argframe; + void *_cframe; void *_retval; id _target; SEL _selector; diff --git a/Headers/gnustep/base/config.h.in b/Headers/gnustep/base/config.h.in index df88462a3..f8b96fdab 100644 --- a/Headers/gnustep/base/config.h.in +++ b/Headers/gnustep/base/config.h.in @@ -48,6 +48,12 @@ /* Define if your system has a /proc/self/exe symlink to the executable */ #undef HAVE_PROC_FS_EXE_LINK +/* Define if using the libffi library for invocations */ +#undef USE_LIBFFI + +/* Define if using the ffcall library for invocations */ +#undef USE_FFCALL + /* The number of bytes in a double. */ #undef SIZEOF_DOUBLE @@ -135,12 +141,18 @@ /* Define if you have the vsprintf function. */ #undef HAVE_VSPRINTF +/* Define if you have the header file. */ +#undef HAVE_CALLBACK + /* Define if you have the header file. */ #undef HAVE_DIRENT_H /* Define if you have the header file. */ #undef HAVE_GETOPT_H +/* Define if you have the header file. */ +#undef HAVE_GMP_H + /* Define if you have the header file. */ #undef HAVE_GRP_H diff --git a/INSTALL b/INSTALL index 96e7d2bc9..2f6bf8071 100644 --- a/INSTALL +++ b/INSTALL @@ -1,5 +1,101 @@ -Read the file GNUstep-HOWTO for instructions on how to install the -entire GNUstep package (including the base library). GNUstep-HOWTO -comes with this distribution and also is located at the same ftp sites -as this library. +Introduction +============ + + If you are installing this package as part of the GNUstep core +libraries, read the file GNUstep-HOWTO for more complete instructions on +how to install the entire GNUstep package (including this library). +GNUstep-HOWTO comes with the core distribution and also is located at +the same ftp sites as this library. + + If you are instsalling the GNUstep libraries individually, make sure +you have installed the GNUstep Makefile package (gstep-make) already. +Most of the installation instructions for gstep-make also apply to this +library. When you configure this library, make sure you use the same +configuration options as with gstep-make. Some additional options to +configure are described below. + +Configuration +============= + + Configuration is performed by running the `configure' program at a +shell prompt. You may want to use some of the optional arguments to the +`configure' program. Type `configure --help' for a list of these. It is +not likely that you will need to use the `--prefix' option, since +gstep-base will automatically install in the directory specified by the +`GNUSTEP_SYSTEM_ROOT' environment variable (specified when you +installed gstep-make). + + Many configuration options for the base library need to be specified +when configuring the gstep-make package. In most cases, it is a good +idea to specify the same configuration options when configuring both +packages, just to make sure. + + Also make sure you've read the machine-specific instructions for your +particular operating system and CPU. These instructions come with the +core libraries and are also located at the GNUstep web site at +. + +Reading Command-Line Arguments +============================== + + There are two features that change how GNUstep gets access to +command-line arguments and environment variables (normally passed to +the program in the `main()' function. These features are +`--enable-pass-arguments' and the `--enable-fake-main' option(s). + + The fake-main option _secretly_ renames the `main()' function and +substitutes it's own function which stores the command line arguments +before calling the real main. + + The pass-arguments option absolves GNUstep of any effort to get the +command-line arguments and instead forces the developer to insert the +line + + [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; + + in the `main()' function of their program. + + Normally, the configure script will determine if a program can read +process information directly from the system (for use by the class +NSProcessInfo) and enable or disable the fake-main hack automatically, +but if you find that configure is not doing this correctly, you can +force the fake-main hack to be used, which will always work. Note that +if the fake-main hack is enabled, you need to include the header file +GSConfig.h in you main program - this is done by default if you include +NSObject.h or Foundation.h. If you want to avoid the whole idea of the +fake-main hack, you can use the pass-arguments option. In this case you +will be forced to call the NSProcessInfo initializeWithArguments method +to pass the program arguments to NSProcessInfo (This would be done +automatically if you use the NSApplicationMain function in a gui +application). + +FFI Library +=========== + + GNUstep's NSInvocations and Distributed Objects code involves +detailed manipulation of function (method) calls, which does not work +on all machine architectures. A more robust and portable solution is to +use a library that implements a Foreign-Function Interface (FFI), such +as the ffcall libraries. If you use a non-x86 machine, you should +seriously consider enabling this option using `--enable-ffcall'. + + For this to work, you need to have the ffcall libraries, which you +can get from or +. You also need to have a special +version of the Objective-C library (as of gcc 2.95.x the required hooks +are not in the standard library). You can get this library from + or patch +the standard library with the patch at +. + + Make sure you specify this option when configuring gstep-make also. + +Compilation +=========== + + To compile this library, type make. After this is complete, type make +install (make sure you are the root user). Some additional options you +can use with make are `debug=yes' to make a debugging version of the +library and `shared=no' to make a static version of the library. See +the gstep-make package for more information on these options. diff --git a/README b/README index 3074ebfb9..bae392f5e 100644 --- a/README +++ b/README @@ -18,8 +18,8 @@ Initial reading The file `NEWS' has the library's feature history. - The file `GNUstep-HOWTO' give instructions for installing the -library. + The files `INSTALL' or `GNUstep-HOWTO' (from the core package) gives +instructions for installing the library. How can you help? ================= diff --git a/Source/GNUmakefile b/Source/GNUmakefile index e17fe1a8e..1ac3fd232 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -234,6 +234,15 @@ ifeq ($(HAVE_LIBXML),1) BASE_MFILES += GSXML.m endif +ifeq ($(WITH_FFI),libffi) +GNU_MFILES += cifframe.m +BASE_MFILES += GSFFIInvocation.m +endif +ifeq ($(WITH_FFI),ffcall) +GNU_MFILES += callframe.m +BASE_MFILES += GSFFCallInvocation.m +endif + NSVALUE_MFILES = \ NSValue0.m NSValue1.m NSValue2.m NSValue3.m \ NSValue4.m diff --git a/Source/GSFFCallInvocation.m b/Source/GSFFCallInvocation.m new file mode 100644 index 000000000..b2b959d48 --- /dev/null +++ b/Source/GSFFCallInvocation.m @@ -0,0 +1,697 @@ +/* Implementation of GSFFCallInvocation for GNUStep + Copyright (C) 2000 Free Software Foundation, Inc. + + Written: Adam Fedor + Date: Nov 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#ifdef __powerpc__ +#define __rs6000__ +#define _AIX +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "callframe.h" + +typedef struct _NSInvocation_t { + @defs(NSInvocation) +} NSInvocation_t; + +void +GSInvocationCallback(void *callback_data, va_alist args); + +/* Callback for forwarding methods */ +static void *ff_callback; + +/* Callback data (which will hold the selector) */ +static SEL callback_sel; + +/* Recursively calculate the offset using the offset of the previous + sub-type */ +static int +gs_offset(const char *type, int index) +{ + int offset; + const char *subtype; + + if (index == 0) + return 0; + subtype = type; + while (*subtype != _C_STRUCT_E && *subtype++ != '='); /* skip "=" */ + + offset = (gs_offset(type, index-1) + objc_sizeof_type(&subtype[index-1]) + + objc_alignof_type(&subtype[index]) - 1) + & -(long)objc_alignof_type(&subtype[index]); + return offset; +} + +/* Determines if the structure type can be returned entirely in registers. + See the avcall or vacall man pages for more info. FIXME: I'm betting + this won't work if a structure contains another structure */ +int +gs_splittable(const char *type) +{ + int i, numtypes; + const char *subtype; + int result; + + subtype = type; + while (*subtype != _C_STRUCT_E && *subtype++ != '='); /* skip "=" */ + numtypes = 0; + while (*subtype != _C_STRUCT_E) + { + numtypes++; + subtype = objc_skip_typespec (subtype); + } + subtype = type; + while (*subtype != _C_STRUCT_E && *subtype++ != '='); /* skip "=" */ + + result = 1; + for (i = 0; i < numtypes; i++) + { + result = result + && (gs_offset(type, i)/sizeof(__avword) + == (gs_offset(type, i)+objc_sizeof_type(&subtype[i])-1) + / sizeof(__avword)); + } + //printf("Splittable for %s is %d\n", type, result); + return result; +} + +@implementation GSFFCallInvocation + +static IMP gs_objc_msg_lookup (id self, SEL _cmd) +{ + callback_sel = _cmd; + return ff_callback; +} + +static IMP gs_class_get_method (Class class, SEL _cmd) +{ + callback_sel = _cmd; + return ff_callback; +} + +static void gs_free_callback(void) +{ + if (ff_callback) + { + free_callback(ff_callback); + ff_callback = NULL; + } +} + ++ (void)load +{ + ff_callback = alloc_callback(&GSInvocationCallback, &callback_sel); + + __objc_msg_lookup = gs_objc_msg_lookup; + __objc_class_get_method = gs_class_get_method; +} + +- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector +{ + /* We should never get here */ + NSDeallocateObject(self); + [NSException raise: NSInternalInconsistencyException + format: @"Runtime incorrectly configured to pass argframes"]; + return nil; +} + +/* + * This is the de-signated initialiser. + */ +- (id) initWithMethodSignature: (NSMethodSignature*)aSignature +{ + _sig = RETAIN(aSignature); + _numArgs = [aSignature numberOfArguments]; + _info = [aSignature methodInfo]; + _cframe = callframe_from_info(_info, _numArgs, &_retval); + if (_retval == 0 && _info[0].size > 0) + { + _retval = NSZoneMalloc(NSDefaultMallocZone(), _info[0].size); + } + return self; +} + +/* This is implemented as a function so it can be used by other + routines (like the DO forwarding) +*/ + +void +GSFFCallInvokeWithTargetAndImp(NSInvocation_t *inv, id anObject, IMP imp) +{ + int i; + av_alist alist; + + /* Do an av call starting with the return type */ +#undef CASE_TYPE +#define CASE_TYPE(_T, _V, _F) \ + case _T: \ + _F(alist, imp, inv->_retval); \ + break; + + switch (*inv->_info[0].type) + { + case _C_ID: + av_start_ptr(alist, imp, id, inv->_retval); + break; + case _C_CLASS: + av_start_ptr(alist, imp, Class, inv->_retval); + break; + case _C_SEL: + av_start_ptr(alist, imp, SEL, inv->_retval); + break; + case _C_PTR: + av_start_ptr(alist, imp, void *, inv->_retval); + break; + case _C_CHARPTR: + av_start_ptr(alist, imp, char *, inv->_retval); + break; + + CASE_TYPE(_C_CHR, char, av_start_char) + CASE_TYPE(_C_UCHR, unsigned char, av_start_uchar) + CASE_TYPE(_C_SHT, short, av_start_short) + CASE_TYPE(_C_USHT, unsigned short, av_start_ushort) + CASE_TYPE(_C_INT, int, av_start_int) + CASE_TYPE(_C_UINT, unsigned int, av_start_uint) + CASE_TYPE(_C_LNG, long, av_start_long) + CASE_TYPE(_C_ULNG, unsigned long, av_start_ulong) + CASE_TYPE(_C_LNG_LNG, long long, av_start_longlong) + CASE_TYPE(_C_ULNG_LNG, unsigned long long, av_start_ulonglong) + CASE_TYPE(_C_FLT, float, av_start_float) + CASE_TYPE(_C_DBL, double, av_start_double) + + case _C_STRUCT_B: + { + int split = 0; + if (inv->_info[0].size > sizeof(long) && inv->_info[0].size <= 2*sizeof(long)) + split = gs_splittable(inv->_info[0].type); + _av_start_struct(alist, imp, inv->_info[0].size, split, inv->_retval); + break; + } + case _C_VOID: + av_start_void(alist, imp); + break; + default: + NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented", + inv->_info[0].type); + break; + } + + /* Set target and selector */ + av_ptr(alist, id, anObject); + av_ptr(alist, SEL, inv->_selector); + + /* Set the rest of the arguments */ + for (i = 2; i < inv->_numArgs; i++) + { + const char *type = inv->_info[i+1].type; + unsigned size = inv->_info[i+1].size; + void *datum; + + datum = callframe_arg_addr((callframe_t *)inv->_cframe, i); + +#undef CASE_TYPE +#define CASE_TYPE(_T, _V, _F) \ + case _T: \ + { \ + _V c; \ + memcpy(&c, datum, size); \ + _F(alist, c); \ + break; \ + } + + switch (*type) + { + case _C_ID: + { + id obj; + memcpy(&obj, datum, size); + av_ptr(alist, id, obj); + break; + } + case _C_CLASS: + { + Class obj; + memcpy(&obj, datum, size); + av_ptr(alist, Class, obj); + break; + } + case _C_SEL: + { + SEL sel; + memcpy(&sel, datum, size); + av_ptr(alist, SEL, sel); + break; + } + case _C_PTR: + { + void *ptr; + memcpy(&ptr, datum, size); + av_ptr(alist, void *, ptr); + break; + } + case _C_CHARPTR: + { + char *ptr; + memcpy(&ptr, datum, size); + av_ptr(alist, char *, ptr); + break; + } + + CASE_TYPE(_C_CHR, char, av_char) + CASE_TYPE(_C_UCHR, unsigned char, av_uchar) + CASE_TYPE(_C_SHT, short, av_short) + CASE_TYPE(_C_USHT, unsigned short, av_ushort) + CASE_TYPE(_C_INT, int, av_int) + CASE_TYPE(_C_UINT, unsigned int, av_uint) + CASE_TYPE(_C_LNG, long, av_long) + CASE_TYPE(_C_ULNG, unsigned long, av_ulong) + CASE_TYPE(_C_LNG_LNG, long long, av_longlong) + CASE_TYPE(_C_ULNG_LNG, unsigned long long, av_ulonglong) + CASE_TYPE(_C_FLT, float, av_float) + CASE_TYPE(_C_DBL, double, av_double) + + case _C_STRUCT_B: + _av_struct(alist, size, inv->_info[i+1].align, datum); + break; + default: + NSCAssert1(0, @"GSFFCallInvocation: Type '%s' not implemented", type); + break; + } + } + + /* Do it */ + av_call(alist); +} + +- (void) invokeWithTarget: (id)anObject +{ + id old_target; + IMP imp; + + /* + * A message to a nil object returns nil. + */ + if (anObject == nil) + { + memset(_retval, '\0', _info[0].size); /* Clear return value */ + return; + } + + NSAssert(_selector != 0, @"you must set the selector before invoking"); + + /* + * Temporarily set new target and copy it (and the selector) into the + * _argframe. + */ + old_target = RETAIN(_target); + [self setTarget: anObject]; + + callframe_set_arg((callframe_t *)_cframe, 0, &_target, _info[1].size); + callframe_set_arg((callframe_t *)_cframe, 1, &_selector, _info[2].size); + + imp = method_get_imp(object_is_instance(_target) ? + class_get_instance_method( + ((struct objc_class*)_target)->class_pointer, _selector) + : class_get_class_method( + ((struct objc_class*)_target)->class_pointer, _selector)); + /* + * If fast lookup failed, we may be forwarding or something ... + */ + if (imp == 0) + imp = objc_msg_lookup(_target, _selector); + + [self setTarget: old_target]; + RELEASE(old_target); + + GSFFCallInvokeWithTargetAndImp(self, anObject, imp); + _validReturn = YES; +} + +- (void*) returnFrame: (arglist_t)argFrame +{ + return _retval; +} +@end + +void GSInvocationCallback(void *callback_data, va_alist args) +{ + id obj; + SEL callback_sel, selector; + int i, num_args; + void *retval; + const char *callback_type; + NSArgumentInfo *info; + GSFFCallInvocation *invocation; + NSMethodSignature *sig; + + callback_sel = *(SEL *)callback_data; + callback_type = sel_get_type(callback_sel); + callback_type = objc_skip_type_qualifiers(callback_type); + +#undef CASE_TYPE +#define CASE_TYPE(_T, _V, _F) \ + case _T: \ + _F(args); \ + break; + + switch (*callback_type) + { + case _C_ID: + va_start_ptr(args, id); + break; + case _C_CLASS: + va_start_ptr(args, Class); + break; + case _C_SEL: + va_start_ptr(args, SEL); + break; + case _C_PTR: + va_start_ptr(args, void *); + break; + case _C_CHARPTR: + va_start_ptr(args, char *); + break; + + CASE_TYPE(_C_CHR, char, va_start_char) + CASE_TYPE(_C_UCHR, unsigned char, va_start_uchar) + CASE_TYPE(_C_SHT, short, va_start_short) + CASE_TYPE(_C_USHT, unsigned short, va_start_ushort) + CASE_TYPE(_C_INT, int, va_start_int) + CASE_TYPE(_C_UINT, unsigned int, va_start_uint) + CASE_TYPE(_C_LNG, long, va_start_long) + CASE_TYPE(_C_ULNG, unsigned long, va_start_ulong) + CASE_TYPE(_C_LNG_LNG, long long, va_start_longlong) + CASE_TYPE(_C_ULNG_LNG, unsigned long long, va_start_ulonglong) + CASE_TYPE(_C_FLT, float, va_start_float) + CASE_TYPE(_C_DBL, double, va_start_double) + + case _C_STRUCT_B: + { + int split, ssize; + ssize = objc_sizeof_type(callback_type); + if (ssize > sizeof(long) && ssize <= 2*sizeof(long)) + split = gs_splittable(callback_type); + _va_start_struct(args, ssize, objc_alignof_type(callback_type), split); + break; + } + case _C_VOID: + va_start_void(args); + break; + default: + NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented", + callback_type); + break; + } + + obj = va_arg_ptr(args, id); + selector = va_arg_ptr(args, SEL); + /* Invoking a NSDistantObject method is likely to cause infinite recursion. + So make sure we really can't find the selector locally .*/ + sig = nil; + if ([obj isKindOfClass: [NSDistantObject class]]) + { + const char *type = sel_get_type(selector); + if (type) + sig = [NSMethodSignature signatureWithObjCTypes: type]; + } + if (!sig) + { + NSLog(@"looking up sel %@", NSStringFromSelector(selector)); + sig = [obj methodSignatureForSelector: selector]; + } + NSCAssert1(sig, @"No signature for selector %@", + NSStringFromSelector(selector)); + + + invocation = [[GSFFCallInvocation alloc] initWithMethodSignature: sig]; + AUTORELEASE(invocation); + [invocation setTarget: obj]; + [invocation setSelector: selector]; + + /* Set the rest of the arguments */ + num_args = [sig numberOfArguments]; + info = [sig methodInfo]; + for (i = 2; i < num_args; i++) + { + const char *type = info[i+1].type; + unsigned size = info[i+1].size; + +#undef CASE_TYPE +#define CASE_TYPE(_T, _V, _F) \ + case _T: \ + { \ + _V c = _F(args); \ + [invocation setArgument: &c atIndex: i]; \ + break; \ + } + + switch (*type) + { + case _C_ID: + { + id obj = va_arg_ptr (args, id); + [invocation setArgument: &obj atIndex: i]; + break; + } + case _C_CLASS: + { + Class obj = va_arg_ptr (args, Class); + [invocation setArgument: &obj atIndex: i]; + break; + } + case _C_SEL: + { + SEL sel = va_arg_ptr (args, SEL); + [invocation setArgument: &sel atIndex: i]; + break; + } + case _C_PTR: + { + void *ptr = va_arg_ptr (args, void *); + [invocation setArgument: &ptr atIndex: i]; + break; + } + case _C_CHARPTR: + { + char *ptr = va_arg_ptr (args, char *); + [invocation setArgument: &ptr atIndex: i]; + break; + } + + CASE_TYPE(_C_CHR, char, va_arg_char) + CASE_TYPE(_C_UCHR, unsigned char, va_arg_uchar) + CASE_TYPE(_C_SHT, short, va_arg_short) + CASE_TYPE(_C_USHT, unsigned short, va_arg_ushort) + CASE_TYPE(_C_INT, int, va_arg_int) + CASE_TYPE(_C_UINT, unsigned int, va_arg_uint) + CASE_TYPE(_C_LNG, long, va_arg_long) + CASE_TYPE(_C_ULNG, unsigned long, va_arg_ulong) + CASE_TYPE(_C_LNG_LNG, long long, va_arg_longlong) + CASE_TYPE(_C_ULNG_LNG, unsigned long long, va_arg_ulonglong) + CASE_TYPE(_C_FLT, float, va_arg_float) + CASE_TYPE(_C_DBL, double, va_arg_double) + + case _C_STRUCT_B: + { + /* Here we actually get a ptr to the struct */ + void *ptr = _va_arg_struct(args, size, info[i+1].align); + [invocation setArgument: ptr atIndex: i]; + break; + } + default: + NSCAssert1(0, @"GSFFCallInvocation: Type '%s' not implemented", type); + break; + } + } + + /* Now do it */ + [obj forwardInvocation: invocation]; + + /* Return the proper type */ + retval = [invocation returnFrame: NULL]; + +#undef CASE_TYPE +#define CASE_TYPE(_T, _V, _F) \ + case _T: \ + _F(args, *(_V *)retval); \ + break; + + switch (*info[0].type) + { + case _C_ID: + va_return_ptr(args, id, *(id *)retval); + break; + case _C_CLASS: + va_return_ptr(args, Class, *(Class *)retval); + break; + case _C_SEL: + va_return_ptr(args, SEL, *(SEL *)retval); + break; + case _C_PTR: + va_return_ptr(args, void *, *(void **)retval); + break; + case _C_CHARPTR: + va_return_ptr(args, char *, *(char **)retval); + break; + + CASE_TYPE(_C_CHR, char, va_return_char) + CASE_TYPE(_C_UCHR, unsigned char, va_return_uchar) + CASE_TYPE(_C_SHT, short, va_return_short) + CASE_TYPE(_C_USHT, unsigned short, va_return_ushort) + CASE_TYPE(_C_INT, int, va_return_int) + CASE_TYPE(_C_UINT, unsigned int, va_return_uint) + CASE_TYPE(_C_LNG, long, va_return_long) + CASE_TYPE(_C_ULNG, unsigned long, va_return_ulong) + CASE_TYPE(_C_LNG_LNG, long long, va_return_longlong) + CASE_TYPE(_C_ULNG_LNG, unsigned long long, va_return_ulonglong) + CASE_TYPE(_C_FLT, float, va_return_float) + CASE_TYPE(_C_DBL, double, va_return_double) + + case _C_STRUCT_B: + _va_return_struct(args, info[0].size, info[0].align, retval); + break; + case _C_VOID: + va_return_void(args); + break; + default: + NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented", info[0].type); + break; + } +} + +@implementation NSInvocation (DistantCoding) + +/* An internal method used to help NSConnections code invocations + to send over the wire */ +- (BOOL) encodeWithDistantCoder: (NSCoder*)coder passPointers: (BOOL)passp +{ + int i; + BOOL out_parameters = NO; + + [coder encodeValueOfObjCType: @encode(char*) at: &_info[0].type]; + + for (i = 0; i < _numArgs; i++) + { + int flags = _info[i+1].qual; + const char *type = _info[i+1].type; + void *datum; + + if (i == 0) + datum = &_target; + else if (i == 1) + datum = &_selector; + else + datum = callframe_arg_addr((callframe_t *)_cframe, i); + + /* Decide how, (or whether or not), to encode the argument + depending on its FLAGS and TYPE. Only the first two cases + involve parameters that may potentially be passed by + reference, and thus only the first two may change the value + of OUT_PARAMETERS. */ + + switch (*type) + { + case _C_ID: + if (flags & _F_BYCOPY) + [coder encodeBycopyObject: *(id*)datum]; +#ifdef _F_BYREF + else if (flags & _F_BYREF) + [coder encodeByrefObject: *(id*)datum]; +#endif + else + [coder encodeObject: *(id*)datum]; + break; + case _C_CHARPTR: + /* Handle a (char*) argument. */ + /* If the char* is qualified as an OUT parameter, or if it + not explicitly qualified as an IN parameter, then we will + have to get this char* again after the method is run, + because the method may have changed it. Set + OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* If the char* is qualified as an IN parameter, or not + explicity qualified as an OUT parameter, then encode + it. */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + [coder encodeValueOfObjCType: type at: datum]; + break; + + case _C_PTR: + /* If the pointer's value is qualified as an OUT parameter, + or if it not explicitly qualified as an IN parameter, + then we will have to get the value pointed to again after + the method is run, because the method may have changed + it. Set OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if (passp) + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + [coder encodeValueOfObjCType: type at: datum]; + } + else + { + /* Handle an argument that is a pointer to a non-char. But + (void*) and (anything**) is not allowed. */ + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + type++; + /* If the pointer's value is qualified as an IN parameter, + or not explicity qualified as an OUT parameter, then + encode it. */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + [coder encodeValueOfObjCType: type at: *(void**)datum]; + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* Handle struct and array arguments. */ + /* Whether DATUM points to the data, or points to a pointer + that points to the data, depends on the value of + CALLFRAME_STRUCT_BYREF. Do the right thing + so that ENCODER gets a pointer to directly to the data. */ + [coder encodeValueOfObjCType: type at: datum]; + break; + + default: + /* Handle arguments of all other types. */ + [coder encodeValueOfObjCType: type at: datum]; + } + } + + /* Return a BOOL indicating whether or not there are parameters that + were passed by reference; we will need to get those values again + after the method has finished executing because the execution of + the method may have changed them.*/ + return out_parameters; +} + diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m new file mode 100644 index 000000000..7e8d79037 --- /dev/null +++ b/Source/GSFFIInvocation.m @@ -0,0 +1,101 @@ +/* Implementation of GSFFIInvocation for GNUStep + Copyright (C) 2000 Free Software Foundation, Inc. + + Written: Adam Fedor + Date: Nov 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#include +#include +#include +#include +#include +#include "cifframe.h" + +/* The FFI library doesn't have closures (well it does, but only for ix86), so + we still use a lot of the argframe (mframe) functions for things like + forwarding +*/ + +@implementation GSFFIInvocation + +- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector +{ + const char *types; + NSMethodSignature *newSig; + + types = sel_get_type(aSelector); + if (types == 0) + { + types = sel_get_type(sel_get_any_typed_uid(sel_get_name(aSelector))); + } + if (types == 0) + { + [NSException raise: NSInvalidArgumentException + format: @"Couldn't find encoding type for selector %s.", + sel_get_name(aSelector)]; + } + newSig = [NSMethodSignature signatureWithObjCTypes: types]; + self = [self initWithMethodSignature: newSig]; + + if (self) + { + [self setSelector: aSelector]; + /* + * Copy the _argframe we were given. + */ + if (frame) + { + int i; + + mframe_get_arg(frame, &_info[1], &_target); + for (i = 1; i <= _numArgs; i++) + { + mframe_get_arg(frame, &_info[i], + ((cifframe_t *)_cframe)->values[i-1]); + } + } + } + return self; +} + +/* + * This is the de_signated initialiser. + */ +- (id) initWithMethodSignature: (NSMethodSignature*)aSignature +{ + _sig = RETAIN(aSignature); + _numArgs = [aSignature numberOfArguments]; + _info = [aSignature methodInfo]; + _argframe = mframe_create_argframe([_sig methodType], &_retval); + _cframe = cifframe_from_sig([_sig methodType], &_retval); + if (_retval == 0 && _info[0].size > 0) + { + _retval = NSZoneMalloc(NSDefaultMallocZone(), _info[0].size); + } + return self; +} + + +- (void*) returnFrame: (arglist_t)argFrame +{ + return mframe_handle_return(_info[0].type, _retval, argFrame); +} +@end + diff --git a/Source/NSConnection.m b/Source/NSConnection.m index d2ac27a79..7f4fd5be6 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -28,6 +28,11 @@ #include #include #include +#if defined(USE_LIBFFI) +#include "cifframe.h" +#elif defined(USE_FFCALL) +#include "callframe.h" +#endif /* * Setup for inline operation of pointer map tables. @@ -65,6 +70,7 @@ #include #include #include +#include #define F_LOCK(X) {NSDebugFLLog(@"GSConnection",@"Lock %@",X);[X lock];} #define F_UNLOCK(X) {NSDebugFLLog(@"GSConnection",@"Unlock %@",X);[X unlock];} @@ -1560,6 +1566,142 @@ static BOOL multi_threaded = NO; return retframe; } +/* + * NSDistantObject's -forwardInvocation: method calls this to send the message + * over the wire. + */ +- (void) forwardInvocation: (NSInvocation *)inv + forProxy: (NSDistantObject*)object +{ + NSPortCoder *op; + BOOL outParams; + BOOL needsResponse; + const char *type; + int seq_num; + + /* Encode the method on an RMC, and send it. */ + + NSParameterAssert (_isValid); + + /* get the method types from the selector */ + type = [[inv methodSignature] methodType]; + if (type == 0 || *type == '\0') + { + type = [[object methodSignatureForSelector: [inv selector]] methodType]; + if (type) + { + sel_register_typed_name(sel_get_name([inv selector]), type); + } + } + NSParameterAssert(type); + NSParameterAssert(*type); + + op = [self _makeOutRmc: 0 generate: &seq_num reply: YES]; + + if (debug_connection > 4) + NSLog(@"building packet seq %d", seq_num); + + outParams = [inv encodeWithDistantCoder: op passPointers: YES]; + + if (outParams == YES) + { + needsResponse = YES; + } + else + { + int flags; + + needsResponse = NO; + flags = objc_get_type_qualifiers(type); + if ((flags & _F_ONEWAY) == 0) + { + needsResponse = YES; + } + else + { + const char *tmptype = objc_skip_type_qualifiers(type); + + if (*tmptype != _C_VOID) + { + needsResponse = YES; + } + } + } + + [self _sendOutRmc: op type: METHOD_REQUEST]; + NSDebugMLLog(@"NSConnection", @"Sent message to 0x%x", (gsaddr)self); + + if (needsResponse == NO) + { + /* + * Since we don't need a response, we can remove the placeholder from + * the _replyMap. + */ + M_LOCK(_refGate); + GSIMapRemoveKey(_replyMap, (GSIMapKey)seq_num); + M_UNLOCK(_refGate); + } + else + { + NSPortCoder *ip = nil; + BOOL is_exception = NO; + + void decoder(int argnum, void *datum, const char *type, int flags) + { + if (type == 0) + { + if (ip != nil) + { + DESTROY(ip); + /* this must be here to avoid trashing alloca'ed retframe */ + ip = (id)-1; + _repInCount++; /* received a reply */ + } + return; + } + /* If we didn't get the reply packet yet, get it now. */ + if (!ip) + { + if (!_isValid) + { + [NSException raise: NSGenericException + format: @"connection waiting for request was shut down"]; + } + ip = [self _getReplyRmc: seq_num]; + /* + * Find out if the server is returning an exception instead + * of the return values. + */ + [ip decodeValueOfObjCType: @encode(BOOL) at: &is_exception]; + if (is_exception) + { + /* Decode the exception object, and raise it. */ + id exc; + [ip decodeValueOfObjCType: @encode(id) at: &exc]; + DESTROY(ip); + ip = (id)-1; + /* xxx Is there anything else to clean up in + dissect_method_return()? */ + [exc raise]; + } + } + [ip decodeValueOfObjCType: type at: datum]; + if (*type == _C_ID) + AUTORELEASE(*(id*)datum); + } + +#ifdef USE_FFCALL + callframe_build_return (inv, type, outParams, decoder); +#endif + /* Make sure we processed all arguments, and dismissed the IP. + IP is always set to -1 after being dismissed; the only places + this is done is in this function DECODER(). IP will be nil + if mframe_build_return() never called DECODER(), i.e. when + we are just returning (void).*/ + NSAssert(ip == (id)-1 || ip == nil, NSInternalInconsistencyException); + } +} + - (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target { id op, ip; @@ -1811,6 +1953,9 @@ static BOOL multi_threaded = NO; } [aRmc decodeValueOfObjCType: type at: datum]; +#ifdef USE_FFCALL + if (*type == _C_ID) +#else /* -decodeValueOfObjCType: at: malloc's new memory for char*'s. We need to make sure it gets freed eventually so we don't have a memory leak. Request here that it be @@ -1818,6 +1963,7 @@ static BOOL multi_threaded = NO; if ((*type == _C_CHARPTR || *type == _C_PTR) && *(void**)datum != 0) [NSData dataWithBytesNoCopy: *(void**)datum length: 1]; else if (*type == _C_ID) +#endif AUTORELEASE(*(id*)datum); } @@ -1871,7 +2017,13 @@ static BOOL multi_threaded = NO; if (debug_connection > 1) NSLog(@"Handling message from 0x%x", (gsaddr)self); _reqInCount++; /* Handling an incoming request. */ +#if defined(USE_LIBFFI) + cifframe_do_call (forward_type, decoder, encoder); +#elif defined(USE_FFCALL) + callframe_do_call (forward_type, decoder, encoder); +#else mframe_do_call (forward_type, decoder, encoder); +#endif if (op != nil) { [self _sendOutRmc: op type: METHOD_REPLY]; diff --git a/Source/NSDistantObject.m b/Source/NSDistantObject.m index 88578d781..a807f6d34 100644 --- a/Source/NSDistantObject.m +++ b/Source/NSDistantObject.m @@ -31,6 +31,16 @@ #include #include +#define DO_FORWARD_INVOCATION(_SELX, _ARG1) \ + sig = [self methodSignatureForSelector: @selector(_SELX)]; \ + inv = [NSInvocation invocationWithMethodSignature: sig]; \ + [inv setSelector: @selector(_SELX)]; \ + [inv setTarget: self]; \ + [inv setArgument: _ARG1 atIndex: 2]; \ + [self forwardInvocation: inv]; \ + [inv getReturnValue: &m] + + static int debug_proxy = 0; static Class placeHolder = 0; static Class distantObjectClass = 0; @@ -482,8 +492,17 @@ enum */ - (void) forwardInvocation: (NSInvocation*)anInvocation { - [NSException raise: NSInvalidArgumentException - format: @"Not yet implemented '%s'", sel_get_name(_cmd)]; + if (debug_proxy) + NSLog(@"NSDistantObject forwardInvocation: %@\n", anInvocation); + + if (![_connection isValid]) + [NSException + raise: NSGenericException + format: @"Trying to send message to an invalid Proxy.\n" + @"You should request NSConnectionDidDieNotification's and\n" + @"release all references to the proxy's of invalid Connections."]; + + [_connection forwardInvocation: anInvocation forProxy: self]; } - (id) initWithCoder: (NSCoder*)aCoder @@ -778,6 +797,10 @@ enum { id m; const char *types; +#ifdef USE_FFCALL + id inv, sig; + DO_FORWARD_INVOCATION(_cmd, aSelector); +#else arglist_t args; void *retframe; @@ -792,6 +815,7 @@ enum args = __builtin_apply_args(); retframe = [self forward: _cmd : args]; m = retframe_id(retframe); +#endif types = [m methodType]; return [NSMethodSignature signatureWithObjCTypes: types]; @@ -901,6 +925,12 @@ static inline BOOL class_is_kind_of (Class self, Class aClassObject) - (BOOL) conformsToProtocol: (Protocol*)aProtocol { +#ifdef USE_FFCALL + BOOL m; + id inv, sig; + DO_FORWARD_INVOCATION(_cmd, aProtocol); + return m; +#else arglist_t args; void *retframe; @@ -915,10 +945,17 @@ static inline BOOL class_is_kind_of (Class self, Class aClassObject) args = __builtin_apply_args(); retframe = [self forward: _cmd : args]; return retframe_bool(retframe); +#endif } - (BOOL) respondsToSelector: (SEL)aSelector { +#ifdef USE_FFCALL + BOOL m; + id inv, sig; + DO_FORWARD_INVOCATION(_cmd, aSelector); + return m; +#else arglist_t args; void *retframe; @@ -933,6 +970,7 @@ static inline BOOL class_is_kind_of (Class self, Class aClassObject) args = __builtin_apply_args(); retframe = [self forward: _cmd : args]; return retframe_bool(retframe); +#endif } - (id) replacementObjectForCoder: (NSCoder*)aCoder diff --git a/Source/NSInvocation.m b/Source/NSInvocation.m index 29deaf6c2..40104f9a6 100644 --- a/Source/NSInvocation.m +++ b/Source/NSInvocation.m @@ -22,18 +22,114 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#include "config.h" #include #include #include +#include #include #include +#if defined(USE_LIBFFI) +#include "cifframe.h" +#elif defined(USE_FFCALL) +#include "callframe.h" +#endif + + +static Class NSInvocation_abstract_class; +static Class NSInvocation_concrete_class; @implementation NSInvocation +#ifdef USE_LIBFFI +static inline void +_get_arg(NSInvocation *inv, int index, void *buffer) +{ + cifframe_get_arg((cifframe_t *)inv->_cframe, index, buffer); +} + +static inline void +_set_arg(NSInvocation *inv, int index, void *buffer) +{ + cifframe_set_arg((cifframe_t *)inv->_cframe, index, buffer); +} + +static inline void * +_arg_addr(NSInvocation *inv, int index) +{ + return cifframe_arg_addr((cifframe_t *)inv->_cframe, index); +} + +#elif defined(USE_FFCALL) +static inline void +_get_arg(NSInvocation *inv, int index, void *buffer) +{ + callframe_get_arg((callframe_t *)inv->_cframe, index, buffer, + inv->_info[index+1].size); +} + +static inline void +_set_arg(NSInvocation *inv, int index, void *buffer) +{ + callframe_set_arg((callframe_t *)inv->_cframe, index, buffer, + inv->_info[index+1].size); +} + +static inline void * +_arg_addr(NSInvocation *inv, int index) +{ + return callframe_arg_addr((callframe_t *)inv->_cframe, index); +} + +#else +_get_arg(NSInvocation *inv, int index, void *buffer) +{ + mframe_get_arg(inv->_argframe, &inv->_info[index+1], &buffer); +} + +static inline void +_set_arg(NSInvocation *inv, int index, void *buffer) +{ + mframe_set_arg(inv->_argframe, &inv->_info[index+1], buffer); +} + +static inline void * +_arg_addr(NSInvocation *inv, int index) +{ + return mframe_arg_addr(inv->_argframe, &inv->_info[index+1]); +} + +#endif + ++ (id) allocWithZone: (NSZone*)aZone +{ + if (self == NSInvocation_abstract_class) + { + return NSAllocateObject(NSInvocation_concrete_class, 0, aZone); + } + else + { + return NSAllocateObject(self, 0, aZone); + } +} + ++ (void) initialize +{ + if (self == [NSInvocation class]) + { + NSInvocation_abstract_class = self; +#if defined(USE_LIBFFI) + NSInvocation_concrete_class = [GSFFIInvocation class]; +#elif defined(USE_FFCALL) + NSInvocation_concrete_class = [GSFFCallInvocation class]; +#else + NSInvocation_concrete_class = [GSFrameInvocation class]; +#endif + } +} + + (NSInvocation*) invocationWithMethodSignature: (NSMethodSignature*)_signature { - return AUTORELEASE([[NSInvocation alloc] + return AUTORELEASE([[NSInvocation_concrete_class alloc] initWithMethodSignature: _signature]); } @@ -53,19 +149,28 @@ { char *str; - mframe_get_arg(_argframe, &_info[i], &str); + _get_arg(self, i-1, &str); NSZoneFree(NSDefaultMallocZone(), str); } else if (*_info[i].type == _C_ID) { id obj; - mframe_get_arg(_argframe, &_info[i], &obj); + _get_arg(self, i-1, &obj); RELEASE(obj); } } } } +#ifdef USE_LIBFFI + if (_cframe) + cifframe_free((cifframe_t *)_cframe); +#else +#ifdef USE_FFCALL + if (_cframe) + callframe_free((callframe_t *)_cframe); +#endif +#endif if (_argframe) { mframe_destroy_argframe([_sig methodType], _argframe); @@ -100,8 +205,7 @@ } else { - index++; /* Allow offset for return type _info. */ - mframe_get_arg(_argframe, &_info[index], buffer); + _get_arg(self, index, buffer); } } @@ -160,8 +264,8 @@ { id old; - mframe_get_arg(_argframe, &_info[i], &old); - mframe_set_arg(_argframe, &_info[i], buffer); + _get_arg(self, index, &old); + _set_arg(self, index, buffer); IF_NO_GC(RETAIN(*(id*)buffer)); if (old != nil) { @@ -173,10 +277,10 @@ char *oldstr; char *newstr = *(char**)buffer; - mframe_get_arg(_argframe, &_info[i], &oldstr); + _get_arg(self, index, &oldstr); if (newstr == 0) { - mframe_set_arg(_argframe, &_info[i], buffer); + _set_arg(self, index, buffer); } else { @@ -184,7 +288,7 @@ tmp = NSZoneMalloc(NSDefaultMallocZone(), strlen(newstr)+1); strcpy(tmp, newstr); - mframe_set_arg(_argframe, &_info[i], tmp); + _set_arg(self, index, tmp); } if (oldstr != 0) { @@ -194,7 +298,7 @@ } else { - mframe_set_arg(_argframe, &_info[i], buffer); + _set_arg(self, index, buffer); } } } @@ -270,7 +374,7 @@ { id old; - mframe_get_arg(_argframe, &_info[i], &old); + _get_arg(self, i-1, &old); if (old != nil) { IF_NO_GC(RETAIN(old)); @@ -280,14 +384,14 @@ { char *str; - mframe_get_arg(_argframe, &_info[i], &str); + _get_arg(self, i-1, &str); if (str != 0) { char *tmp; tmp = NSZoneMalloc(NSDefaultMallocZone(), strlen(str)+1); strcpy(tmp, str); - mframe_set_arg(_argframe, &_info[i], &tmp); + _set_arg(self, i-1, &tmp); } } } @@ -329,9 +433,8 @@ old_target = RETAIN(_target); [self setTarget: anObject]; - mframe_set_arg(_argframe, &_info[1], &_target); - - mframe_set_arg(_argframe, &_info[2], &_selector); + _set_arg(self, 0, &_target); + _set_arg(self, 1, &_selector); imp = method_get_imp(object_is_instance(_target) ? class_get_instance_method( @@ -349,11 +452,20 @@ stack_argsize = [_sig frameLength]; +#ifdef USE_LIBFFI + ffi_call(&((cifframe_t *)_cframe)->cif, (void(*)(void))imp, _retval, + ((cifframe_t *)_cframe)->values); + if (_info[0].size) + { + cifframe_decode_return(_info[0].type, _retval); + } +#else returned = __builtin_apply((void(*)(void))imp, _argframe, stack_argsize); if (_info[0].size) { mframe_decode_return(_info[0].type, _retval, returned); } +#endif _validReturn = YES; } @@ -402,17 +514,19 @@ const char *type = _info[i].type; void *datum; - datum = mframe_arg_addr(_argframe, &_info[i]); + datum = _arg_addr(self, i-1); if (*type == _C_ID) { [aCoder encodeObject: *(id*)datum]; } +#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) #if MFRAME_STRUCT_BYREF else if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) { [aCoder encodeValueOfObjCType: type at: *(void**)datum]; } +#endif #endif else { @@ -439,7 +553,10 @@ [aCoder decodeValueOfObjCType: @encode(char*) at: &types]; newSig = [NSMethodSignature signatureWithObjCTypes: types]; NSZoneFree(NSDefaultMallocZone(), (void*)types); - self = [self initWithMethodSignature: newSig]; + + RELEASE(self); + self = [NSInvocation invocationWithMethodSignature: newSig]; + RETAIN(self); [aCoder decodeValueOfObjCType: @encode(id) at: &_target]; @@ -447,7 +564,8 @@ for (i = 3; i <= _numArgs; i++) { - datum = mframe_arg_addr(_argframe, &_info[i]); + datum = _arg_addr(self, i-1); +#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) #if MFRAME_STRUCT_BYREF { const char *t = _info[i].type; @@ -457,6 +575,7 @@ datum = *(void**)datum; } } +#endif #endif [aCoder decodeValueOfObjCType: _info[i].type at: datum]; } @@ -472,12 +591,144 @@ return self; } - - @end @implementation NSInvocation (GNUstep) +- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector +{ + [self subclassResponsibility: _cmd]; + return nil; +} + +/* + * This is the de_signated initialiser. + */ +- (id) initWithMethodSignature: (NSMethodSignature*)aSignature +{ + [self subclassResponsibility: _cmd]; + return nil; +} + +- (id) initWithSelector: (SEL)aSelector +{ + return [self initWithArgframe: 0 selector: aSelector]; +} + +- (id) initWithTarget: anObject selector: (SEL)aSelector, ... +{ + va_list ap; + + self = [self initWithArgframe: 0 selector: aSelector]; + if (self) + { + int i; + + [self setTarget: anObject]; + va_start (ap, aSelector); + for (i = 3; i <= _numArgs; i++) + { + const char *type = _info[i].type; + unsigned size = _info[i].size; + void *datum; + +#ifdef USE_LIBFFI + size = ((cifframe_t *)_cframe)->args[i-1]->size; +#endif + datum = _arg_addr(self, i-1); + +#define CASE_TYPE(_C,_T) case _C: *(_T*)datum = va_arg (ap, _T); break + switch (*type) + { + case _C_ID: + *(id*)datum = va_arg (ap, id); + if (_argsRetained) + { + IF_NO_GC(RETAIN(*(id*)datum)); + } + break; + case _C_CHARPTR: + *(char**)datum = va_arg (ap, char*); + if (_argsRetained) + { + char *old = *(char**)datum; + + if (old != 0) + { + char *tmp; + + tmp = NSZoneMalloc(NSDefaultMallocZone(),strlen(old)+1); + strcpy(tmp, old); + *(char**)datum = tmp; + } + } + break; + CASE_TYPE(_C_CLASS, Class); + CASE_TYPE(_C_SEL, SEL); + CASE_TYPE(_C_LNG, long); + CASE_TYPE(_C_ULNG, unsigned long); + CASE_TYPE(_C_INT, int); + CASE_TYPE(_C_UINT, unsigned int); + case _C_SHT: + *(short*)datum = (short)va_arg(ap, int); + break; + case _C_USHT: + *(unsigned short*)datum = (unsigned short)va_arg(ap, int); + break; + case _C_CHR: + *(char*)datum = (char)va_arg(ap, int); + break; + case _C_UCHR: + *(unsigned char*)datum = (unsigned char)va_arg(ap, int); + break; + case _C_FLT: + *(float*)datum = (float)va_arg(ap, double); + break; + CASE_TYPE(_C_DBL, double); + CASE_TYPE(_C_PTR, void*); + case _C_STRUCT_B: + default: +#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) +#if defined(sparc) || defined(powerpc) + /* FIXME: This only appears on sparc and ppc machines so far. + structures appear to be aligned on word boundaries. + Hopefully there is a more general way to figure this out */ + size = (size + Created: Nov 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#ifndef callframe_h_INCLUDE +#define callframe_h_INCLUDE + +#include + +@class NSInvocation; + +typedef struct _callframe_t { + int nargs; + void *rtype; + void **args; +} callframe_t; + +extern callframe_t *callframe_from_info (NSArgumentInfo *info, int numargs, + void **retval); +extern void callframe_free(callframe_t *cframe); +extern void callframe_set_arg(callframe_t *cframe, int index, void *buffer, + int size); +extern void callframe_get_arg(callframe_t *cframe, int index, void *buffer, + int size); +extern void *callframe_arg_addr(callframe_t *cframe, int index); + +extern void callframe_do_call (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int)); +extern void callframe_build_return (NSInvocation *inv, + const char *type, + BOOL out_parameters, + void(*decoder)(int,void*,const char*,int)); +#endif + diff --git a/Source/callframe.m b/Source/callframe.m new file mode 100644 index 000000000..c9c2af3f2 --- /dev/null +++ b/Source/callframe.m @@ -0,0 +1,766 @@ +/* callframe.m - Wrapper/Objective-C interface for ffcall function interface + + Copyright (C) 2000, Free Software Foundation, Inc. + + Written by: Adam Fedor + Created: Nov 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#include +#include +#include "callframe.h" +#include +#include +#include + +#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32)) +typedef long long smallret_t; +#else +typedef int smallret_t; +#endif + +/* Return the number of arguments that the method MTH expects. Note + that all methods need two implicit arguments `self' and `_cmd'. + From mframe.m */ +extern int method_types_get_number_of_arguments (const char *type); + +extern BOOL sel_types_match(const char* t1, const char* t2); + +callframe_t * +callframe_from_info (NSArgumentInfo *info, int numargs, void **retval) +{ + int i; + callframe_t *cframe; + + cframe = malloc(sizeof(callframe_t)); + cframe->nargs = numargs; + if (cframe) + { + cframe->args = malloc(cframe->nargs * sizeof(void *)); + for (i = 0; i < cframe->nargs; i++) + cframe->args[i] = malloc(info[i+1].size); + } + + if (retval) + { + *retval = NSZoneMalloc(NSDefaultMallocZone(), + MAX(info[0].size, sizeof(smallret_t)) ); + } + return cframe; +} + +void +callframe_free(callframe_t *cframe) +{ + int i; + for (i = 0; i < cframe->nargs; i++) + { + free(cframe->args[i]); + cframe->args[i] = 0; + } + + cframe->nargs = 0; + free(cframe->args); + free(cframe); +} + +void +callframe_set_arg(callframe_t *cframe, int index, void *buffer, int size) +{ + if (index < 0 || index >= cframe->nargs) + return; + memcpy(cframe->args[index], buffer, size); +} + +void +callframe_get_arg(callframe_t *cframe, int index, void *buffer, int size) +{ + if (index < 0 || index >= cframe->nargs) + return; + memcpy(buffer, cframe->args[index], size); +} + +void * +callframe_arg_addr(callframe_t *cframe, int index) +{ + if (index < 0 || index >= cframe->nargs) + return NULL; + return cframe->args[index]; +} + + + +/* Ugly hack to make it easier to invoke a method from outside + an NSInvocation class. Hopefully simplication of NSConnection + could remove this hack */ +typedef struct _NSInvocation_t { + @defs(NSInvocation) +} NSInvocation_t; + +/*-------------------------------------------------------------------------*/ +/* Functions for handling sending and receiving messages accross a + connection +*/ + +/* callframe_do_call() + + This function decodes the arguments of method call, builds an + argframe of type arglist_t, and invokes the method using + __builtin_apply; then it encodes the return value and any + pass-by-reference arguments. + + ENCODED_TYPES should be a string that describes the return value + and arguments. It's argument types and argument type qualifiers + should match exactly those that were used when the arguments were + encoded with callframe_dissect_call()---callframe_do_call() uses + ENCODED_TYPES to determine which variable types it should decode. + + ENCODED_TYPES is used to get the types and type qualifiers, but not + to get the register and stack locations---we get that information + from the selector type of the SEL that is decoded as the second + argument. In this way, the ENCODED_TYPES may come from a machine + of a different architecture. Having the original ENCODED_TYPES is + good, just in case the machine running callframe_do_call() has some + slightly different qualifiers. Using different qualifiers for + encoding and decoding could lead to massive confusion. + + + DECODER should be a pointer to a function that obtains the method's + argument values. For example: + + void my_decoder (int argnum, void *data, const char *type) + + ARGNUM is the number of the argument, beginning at 0. + DATA is a pointer to the memory where the value should be placed. + TYPE is a pointer to the type string of this value. + + callframe_do_call() calls this function once for each of the methods + arguments. The DECODER function should place the ARGNUM'th + argument's value at the memory location DATA. + callframe_do_call() calls this function once with ARGNUM -1, DATA 0, + and TYPE 0 to denote completion of decoding. + + + If DECODER malloc's new memory in the course of doing its + business, then DECODER is responsible for making sure that the + memory will get free eventually. For example, if DECODER uses + -decodeValueOfCType:at:withName: to decode a char* string, you + should remember that -decodeValueOfCType:at:withName: malloc's + new memory to hold the string, and DECODER should autorelease the + malloc'ed pointer, using the NSData class. + + + ENCODER should be a pointer to a function that records the method's + return value and pass-by-reference values. For example: + + void my_encoder (int argnum, void *data, const char *type, int flags) + + ARGNUM is the number of the argument; this will be -1 for the + return value, and the argument index for the pass-by-reference + values; the indices start at 0. + DATA is a pointer to the memory where the value can be found. + TYPE is a pointer to the type string of this value. + FLAGS is a copy of the type qualifier flags for this argument; + (see ). + + callframe_do_call() calls this function after the method has been + run---once for the return value, and once for each of the + pass-by-reference parameters. The ENCODER function should place + the value at memory location DATA wherever the user wants to + record the ARGNUM'th return value. + + PASS_POINTERS is a flag saying whether pointers should be passed + as pointers (for local stuff) or should be assumed to point to a + single data item (for distributed objects). +*/ + +void +callframe_do_call_opts (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int), + BOOL pass_pointers) +{ + /* The method type string obtained from the target's OBJC_METHOD + structure for the selector we're sending. */ + const char *type; + /* A pointer into the local variable TYPE string. */ + const char *tmptype; + /* A pointer into the argument ENCODED_TYPES string. */ + const char *etmptype; + /* The target object that will receive the message. */ + id object; + /* The selector for the message we're sending to the TARGET. */ + SEL selector; + /* The OBJECT's implementation of the SELECTOR. */ + IMP method_implementation; + /* A pointer into the ARGFRAME; points at individual arguments. */ + char *datum; + /* Type qualifier flags; see . */ + unsigned flags; + /* Which argument number are we processing now? */ + int argnum; + /* A pointer to the memory holding the return value of the method. */ + void *retval; + /* The cif information for calling the method */ + callframe_t *cframe; + /* Does the method have any arguments that are passed by reference? + If so, we need to encode them, since the method may have changed them. */ + BOOL out_parameters = NO; + /* A dummy invocation to pass to the function that invokes our method */ + NSInvocation_t *inv; + /* Signature information */ + NSMethodSignature *sig; + + /* Decode the object, (which is always the first argument to a method), + into the local variable OBJECT. */ + (*decoder) (0, &object, @encode(id)); + NSCParameterAssert (object); + + /* Decode the selector, (which is always the second argument to a + method), into the local variable SELECTOR. */ + /* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ + (*decoder) (1, &selector, ":"); + NSCParameterAssert (selector); + + /* Get the "selector type" for this method. The "selector type" is + a string that lists the return and argument types, and also + indicates in which registers and where on the stack the arguments + should be placed before the method call. The selector type + string we get here should have the same argument and return types + as the ENCODED_TYPES string, but it will have different register + and stack locations if the ENCODED_TYPES came from a machine of a + different architecture. */ +#if NeXT_runtime + { + Method m; + m = class_getInstanceMethod(object->isa, selector); + if (!m) + abort(); + type = m->method_types; + } +#elif 0 + { + Method_t m; + m = class_get_instance_method (object->class_pointer, + selector); + NSCParameterAssert (m); + type = m->method_types; + } +#else + type = sel_get_type (selector); +#endif /* NeXT_runtime */ + + /* Make sure we successfully got the method type, and that its + types match the ENCODED_TYPES. */ + NSCParameterAssert (type); + NSCParameterAssert (sel_types_match(encoded_types, type)); + + /* Build the cif frame */ + sig = [NSMethodSignature signatureWithObjCTypes: type]; + cframe = callframe_from_info([sig methodInfo], [sig numberOfArguments], + &retval); + + /* Put OBJECT and SELECTOR into the ARGFRAME. */ + + /* Initialize our temporary pointers into the method type strings. */ + tmptype = objc_skip_argspec (type); + etmptype = objc_skip_argspec (encoded_types); + NSCParameterAssert (*tmptype == _C_ID); + /* Put the target object there. */ + callframe_set_arg(cframe, 0, &object, sizeof(id)); + /* Get a pointer into ARGFRAME, pointing to the location where the + second argument is to be stored. */ + tmptype = objc_skip_argspec (tmptype); + etmptype = objc_skip_argspec(etmptype); + NSCParameterAssert (*tmptype == _C_SEL); + /* Put the selector there. */ + callframe_set_arg(cframe, 1, &selector, sizeof(SEL)); + + + /* Decode arguments after OBJECT and SELECTOR, and put them into the + ARGFRAME. Step TMPTYPE and ETMPTYPE in lock-step through their + method type strings. */ + + for (tmptype = objc_skip_argspec (tmptype), + etmptype = objc_skip_argspec (etmptype), argnum = 2; + *tmptype != '\0'; + tmptype = objc_skip_argspec (tmptype), + etmptype = objc_skip_argspec (etmptype), argnum++) + { + /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ + flags = objc_get_type_qualifiers (etmptype); + /* Skip over the type qualifiers, so now TYPE is pointing directly + at the char corresponding to the argument's type, as defined + in */ + tmptype = objc_skip_type_qualifiers(tmptype); + + datum = callframe_arg_addr(cframe, argnum); + + /* Decide how, (or whether or not), to decode the argument + depending on its FLAGS and TMPTYPE. Only the first two cases + involve parameters that may potentially be passed by + reference, and thus only the first two may change the value + of OUT_PARAMETERS. *** Note: This logic must match exactly + the code in callframe_dissect_call(); that function should + encode exactly what we decode here. *** */ + + switch (*tmptype) + { + + case _C_CHARPTR: + /* Handle a (char*) argument. */ + /* If the char* is qualified as an OUT parameter, or if it + not explicitly qualified as an IN parameter, then we will + have to get this char* again after the method is run, + because the method may have changed it. Set + OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* If the char* is qualified as an IN parameter, or not + explicity qualified as an OUT parameter, then decode it. + Note: the decoder allocates memory for holding the + string, and it is also responsible for making sure that + the memory gets freed eventually, (usually through the + autorelease of NSData object). */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, datum, tmptype); + + break; + + case _C_PTR: + /* If the pointer's value is qualified as an OUT parameter, + or if it not explicitly qualified as an IN parameter, + then we will have to get the value pointed to again after + the method is run, because the method may have changed + it. Set OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if (pass_pointers) + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, datum, tmptype); + } + else + { + /* Handle an argument that is a pointer to a non-char. But + (void*) and (anything**) is not allowed. */ + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Allocate some memory to be pointed to, and to hold the + value. Note that it is allocated on the stack, and + methods that want to keep the data pointed to, will have + to make their own copies. */ + *(void**)datum = alloca (objc_sizeof_type (tmptype)); + /* If the pointer's value is qualified as an IN parameter, + or not explicity qualified as an OUT parameter, then + decode it. */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, *(void**)datum, tmptype); + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* Handle struct and array arguments. */ + (*decoder) (argnum, datum, tmptype); + break; + + default: + /* Handle arguments of all other types. */ + /* NOTE FOR OBJECTS: Unlike [Decoder decodeObjectAt:..], + this function does not generate a reference to the + object; the object may be autoreleased; if the method + wants to keep a reference to the object, it will have to + -retain it. */ + (*decoder) (argnum, datum, tmptype); + } + } + /* End of the for() loop that enumerates the method's arguments. */ + (*decoder) (-1, 0, 0); + + + /* Invoke the method! */ + + /* Find the target object's implementation of this selector. */ + method_implementation = objc_msg_lookup (object, selector); + NSCParameterAssert (method_implementation); + /* Do it! Send the message to the target, and get the return value + in retval. We need to rencode any pass-by-reference info */ + inv = (NSInvocation_t *)NSAllocateObject([NSInvocation class], 0, + NSDefaultMallocZone()); + inv->_retval = retval; + inv->_selector = selector; + inv->_cframe = cframe; + inv->_info = [sig methodInfo]; + inv->_numArgs = [sig numberOfArguments]; + GSFFCallInvokeWithTargetAndImp((NSInvocation *)inv, object, + method_implementation); + NSDeallocateObject((NSInvocation *)inv); + + /* Encode the return value and pass-by-reference values, if there + are any. This logic must match exactly that in + callframe_build_return(). */ + /* OUT_PARAMETERS should be true here in exactly the same + situations as it was true in callframe_dissect_call(). */ + + /* Get the qualifier type of the return value. */ + flags = objc_get_type_qualifiers (encoded_types); + /* Get the return type; store it our two temporary char*'s. */ + etmptype = objc_skip_type_qualifiers (encoded_types); + tmptype = objc_skip_type_qualifiers (type); + + /* Only encode return values if there is a non-void return value, + a non-oneway void return value, or if there are values that were + passed by reference. */ + + /* If there is a return value, encode it. */ + switch (*tmptype) + { + case _C_VOID: + if ((flags & _F_ONEWAY) == 0) + { + int dummy = 0; + (*encoder) (-1, (void*)&dummy, @encode(int), 0); + } + /* No return value to encode; do nothing. */ + break; + + case _C_PTR: + if (pass_pointers) + { + (*encoder) (-1, retval, tmptype, flags); + } + else + { + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Encode the value that was pointed to. */ + (*encoder) (-1, *(void**)retval, tmptype, flags); + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* The argument is a structure or array returned by value. + (In C, are array's allowed to be returned by value?) */ + (*encoder)(-1, retval, tmptype, flags); + break; + + case _C_FLT: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_DBL: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_SHT: + case _C_USHT: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_CHR: + case _C_UCHR: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + default: + /* case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: + case _C_CHARPTR: case: _C_ID: */ + /* xxx I think this assumes that sizeof(int)==sizeof(void*) */ + (*encoder) (-1, retval, tmptype, flags); + } + + + /* Encode the values returned by reference. Note: this logic + must match exactly the code in callframe_build_return(); that + function should decode exactly what we encode here. */ + + if (out_parameters) + { + /* Step through all the arguments, finding the ones that were + passed by reference. */ + for (tmptype = objc_skip_argspec (tmptype), + argnum = 0, + etmptype = objc_skip_argspec (etmptype); + *tmptype != '\0'; + tmptype = objc_skip_argspec (tmptype), + argnum++, + etmptype = objc_skip_argspec (etmptype)) + { + /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ + flags = objc_get_type_qualifiers(etmptype); + /* Skip over the type qualifiers, so now TYPE is pointing directly + at the char corresponding to the argument's type, as defined + in */ + tmptype = objc_skip_type_qualifiers (tmptype); + + /* Decide how, (or whether or not), to encode the argument + depending on its FLAGS and TMPTYPE. */ + datum = callframe_arg_addr(cframe, argnum); + + if ((*tmptype == _C_PTR) + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + /* The argument is a pointer (to a non-char), and the + pointer's value is qualified as an OUT parameter, or + it not explicitly qualified as an IN parameter, then + it is a pass-by-reference argument.*/ + /* Encode it. */ + (*encoder) (argnum, datum, tmptype, flags); + } + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + /* The argument is a pointer char string, and the + pointer's value is qualified as an OUT parameter, or + it not explicitly qualified as an IN parameter, then + it is a pass-by-reference argument. Encode it.*/ + /* xxx Perhaps we could save time and space by saving + a copy of the string before the method call, and then + comparing it to this string; if it didn't change, don't + bother to send it back again. */ + (*encoder) (argnum, datum, tmptype, flags); + } + } + } + + return; +} + +void +callframe_do_call (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int)) +{ + callframe_do_call_opts(encoded_types, decoder, encoder, YES); +} + +/* callframe_build_return() + + This function decodes the values returned from a method call, + sets up the invocation with the return value, and updates the + pass-by-reference arguments. + + The callback function is finally called with the 'type' set to a nul pointer + to tell it that the return value and all return parameters have been + dealt with. This permits the function to do any tidying up necessary. */ + +void +callframe_build_return_opts (NSInvocation *inv, + const char *type, + BOOL out_parameters, + void(*decoder)(int,void*,const char*,int), + BOOL pass_pointers) +{ + /* The size, in bytes, of memory pointed to by RETFRAME. */ + int retsize; + /* Which argument number are we processing now? */ + int argnum; + /* Type qualifier flags; see . */ + int flags; + /* A pointer into the TYPE string. */ + const char *tmptype; + /* Points at individual arguments. */ + void *datum; + const char *rettype; + /* A pointer to the memory holding the return value of the method. */ + void *retval; + /* Storage for the argument information */ + callframe_t *cframe; + /* Signature information */ + NSMethodSignature *sig; + + /* Build the call frame */ + sig = [NSMethodSignature signatureWithObjCTypes: type]; + cframe = callframe_from_info([sig methodInfo], [sig numberOfArguments], + &retval); + + /* Get the return type qualifier flags, and the return type. */ + flags = objc_get_type_qualifiers(type); + tmptype = objc_skip_type_qualifiers(type); + rettype = tmptype; + + /* Decode the return value and pass-by-reference values, if there + are any. OUT_PARAMETERS should be the value returned by + callframe_dissect_call(). */ + if (out_parameters || *tmptype != _C_VOID || (flags & _F_ONEWAY) == 0) + /* xxx What happens with method declared "- (oneway) foo: (out int*)ip;" */ + /* xxx What happens with method declared "- (in char *) bar;" */ + /* xxx Is this right? Do we also have to check _F_ONEWAY? */ + { + /* ARGNUM == -1 signifies to DECODER() that this is the return + value, not an argument. */ + + /* If there is a return value, decode it, and put it in retval. */ + if (*tmptype != _C_VOID || (flags & _F_ONEWAY) == 0) + { + switch (*tmptype) + { + case _C_PTR: + if (pass_pointers) + { + (*decoder) (-1, retval, tmptype, flags); + } + else + { + unsigned retLength; + + /* We are returning a pointer to something. */ + /* Increment TYPE so we can see what it is a pointer to. */ + tmptype++; + retLength = objc_sizeof_type(tmptype); + /* Allocate memory to hold the value we're pointing to. */ + *(void**)retval = + NSZoneMalloc(NSDefaultMallocZone(), retLength); + /* We are responsible for making sure this memory gets free'd + eventually. Ask NSData class to autorelease it. */ + [NSData dataWithBytesNoCopy: *(void**)retval + length: retLength]; + /* Decode the return value into the memory we allocated. */ + (*decoder) (-1, *(void**)retval, tmptype, flags); + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* Decode the return value into the memory we allocated. */ + (*decoder) (-1, retval, tmptype, flags); + break; + + case _C_FLT: + case _C_DBL: + (*decoder) (-1, ((char*)retval), tmptype, flags); + break; + + case _C_VOID: + { + (*decoder) (-1, retval, @encode(int), 0); + } + break; + + default: + /* (Among other things, _C_CHARPTR is handled here). */ + /* Special case BOOL (and other types smaller than int) + because retval doesn't actually point to the char */ + /* xxx What about structures smaller than int's that + are passed by reference on true structure reference- + passing architectures? */ + /* xxx Is this the right test? Use sizeof(int) instead? */ + if (retsize < sizeof(void*)) + { +#if 1 + /* Frith-Macdonald said this worked better 21 Nov 96. */ + (*decoder) (-1, retval, tmptype, flags); +#else + *(void**)retval = 0; + (*decoder) (-1, ((char*)retval)+sizeof(void*)-retsize, + tmptype, flags); +#endif + } + else + { + (*decoder) (-1, retval, tmptype, flags); + } + } + } + [inv setReturnValue: retval]; + + /* Decode the values returned by reference. Note: this logic + must match exactly the code in callframe_do_call(); that + function should decode exactly what we encode here. */ + + if (out_parameters) + { + /* Step through all the arguments, finding the ones that were + passed by reference. */ + for (tmptype = objc_skip_argspec (tmptype), argnum = 0; + *tmptype != '\0'; + tmptype = objc_skip_argspec (tmptype), argnum++) + { + /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ + flags = objc_get_type_qualifiers(tmptype); + /* Skip over the type qualifiers, so now TYPE is + pointing directly at the char corresponding to the + argument's type, as defined in */ + tmptype = objc_skip_type_qualifiers(tmptype); + + /* Decide how, (or whether or not), to encode the + argument depending on its FLAGS and TMPTYPE. */ + datum = callframe_arg_addr(cframe, argnum); + + if (*tmptype == _C_PTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + void *ptr; + /* The argument is a pointer (to a non-char), and + the pointer's value is qualified as an OUT + parameter, or it not explicitly qualified as an + IN parameter, then it is a pass-by-reference + argument.*/ + (*decoder) (argnum, datum, tmptype, flags); + /* Copy the pointed-to data back to the original + pointer */ + [inv getArgument: &ptr atIndex: argnum]; + memcpy(ptr, *(void **)datum, objc_sizeof_type(tmptype+1)); + } + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + /* The argument is a pointer char string, and the + pointer's value is qualified as an OUT parameter, + or it not explicitly qualified as an IN + parameter, then it is a pass-by-reference + argument. Encode it.*/ + /* xxx Perhaps we could save time and space by + saving a copy of the string before the method + call, and then comparing it to this string; if it + didn't change, don't bother to send it back + again. */ + (*decoder) (argnum, datum, tmptype, flags); + [inv setArgument: datum atIndex: argnum]; + } + } + } + (*decoder) (0, 0, 0, 0); /* Tell it we have finished. */ + } + callframe_free(cframe); +} + +void +callframe_build_return (NSInvocation *inv, + const char *type, + BOOL out_parameters, + void(*decoder)(int,void*,const char*,int)) +{ + callframe_build_return_opts(inv, type, out_parameters, decoder, YES); +} diff --git a/Source/cifframe.h b/Source/cifframe.h new file mode 100644 index 000000000..7f65db2a9 --- /dev/null +++ b/Source/cifframe.h @@ -0,0 +1,50 @@ +/* cifframe - Wrapper/Objective-C interface for ffi function interface + + Copyright (C) 1999, Free Software Foundation, Inc. + + Written by: Adam Fedor + Created: Feb 2000 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#ifndef cifframe_h_INCLUDE +#define cifframe_h_INCLUDE + +#include +#include + +typedef struct _cifframe_t { + ffi_cif cif; + int nargs; + ffi_type *rtype; + ffi_type **args; + void **values; +} cifframe_t; + +extern cifframe_t *cifframe_from_sig (const char *typePtr, void **retval); +extern void cifframe_free(cifframe_t *cframe); +extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer); +extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer); +extern void *cifframe_arg_addr(cifframe_t *cframe, int index); +extern BOOL cifframe_decode_return (const char *type, void* buffer); + +extern void cifframe_do_call (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int)); + +#endif diff --git a/Source/cifframe.m b/Source/cifframe.m new file mode 100644 index 000000000..79ee43f31 --- /dev/null +++ b/Source/cifframe.m @@ -0,0 +1,847 @@ +/* cifframe.m - Wrapper/Objective-C interface for ffi function interface + + Copyright (C) 1999, Free Software Foundation, Inc. + + Written by: Adam Fedor + Created: Dec 1999 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + */ + +#include +#include +#include "cifframe.h" +#include + +#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32)) +typedef long long smallret_t; +#else +typedef int smallret_t; +#endif + +/* Return the number of arguments that the method MTH expects. Note + that all methods need two implicit arguments `self' and `_cmd'. + From mframe.m */ +extern int method_types_get_number_of_arguments (const char *type); + +extern BOOL sel_types_match(const char* t1, const char* t2); + +const char *cifframe_next_arg(const char *typePtr, ffi_type **ftype_ret); + +cifframe_t * +cifframe_from_sig (const char *typePtr, void **retval) +{ + int i; + cifframe_t *cframe; + + cframe = malloc(sizeof(cifframe_t)); + cframe->nargs = method_types_get_number_of_arguments(typePtr); + cframe->args = malloc(cframe->nargs * sizeof(ffi_type)); + + typePtr = cifframe_next_arg(typePtr, &cframe->rtype); + for (i = 0; i < cframe->nargs; i++) + typePtr = cifframe_next_arg(typePtr, &cframe->args[i]); + + if (ffi_prep_cif(&cframe->cif, FFI_DEFAULT_ABI, cframe->nargs, + cframe->rtype, cframe->args) != FFI_OK) + { + free(cframe->args); + free(cframe); + cframe = NULL; + } + + if (cframe) + { + cframe->values = malloc(cframe->nargs * sizeof(void *)); + for (i = 0; i < cframe->nargs; i++) + cframe->values[i] = malloc(cframe->args[i]->size); + } + + if (retval) + { + *retval = NSZoneMalloc(NSDefaultMallocZone(), + MAX(cframe->rtype->size, sizeof(smallret_t)) ); + } + return cframe; +} + +void +cifframe_free(cifframe_t *cframe) +{ + int i; + if (cframe->rtype->type == FFI_TYPE_STRUCT) + free(cframe->rtype->elements); + for (i = 0; i < cframe->nargs; i++) + { + free(cframe->values[i]); + cframe->values[i] = 0; + if (cframe->args[i]->type == FFI_TYPE_STRUCT) + free(cframe->rtype->elements); + } + + cframe->nargs = 0; + free(cframe->args); + free(cframe->values); + free(cframe); +} + +void +cifframe_set_arg(cifframe_t *cframe, int index, void *buffer) +{ + if (index < 0 || index >= cframe->nargs) + return; + memcpy(cframe->values[index], buffer, cframe->args[index]->size); +} + +void +cifframe_get_arg(cifframe_t *cframe, int index, void *buffer) +{ + if (index < 0 || index >= cframe->nargs) + return; + memcpy(buffer, cframe->values[index], cframe->args[index]->size); +} + +void * +cifframe_arg_addr(cifframe_t *cframe, int index) +{ + if (index < 0 || index >= cframe->nargs) + return NULL; + return cframe->values[index]; +} + +/* + * Step through method encoding information extracting details. + */ +const char * +cifframe_next_arg(const char *typePtr, ffi_type **ftype_ret) +{ + BOOL flag; + const char *type; + ffi_type *ftype; + + /* + * Skip past any type qualifiers + */ + flag = YES; + while (flag) + { + switch (*typePtr) + { + case _C_CONST: + case _C_IN: + case _C_INOUT: + case _C_OUT: + case _C_BYCOPY: +#ifdef _C_BYREF + case _C_BYREF: +#endif + case _C_ONEWAY: +#ifdef _C_GCINVISIBLE + case _C_GCINVISIBLE: +#endif + break; + default: flag = NO; + } + if (flag) + { + typePtr++; + } + } + + type = typePtr; + + /* + * Scan for size and alignment information. + */ + switch (*typePtr++) + { + case _C_ID: ftype = &ffi_type_pointer; + break; + case _C_CLASS: ftype = &ffi_type_pointer; + break; + case _C_SEL: ftype = &ffi_type_pointer; + break; + case _C_CHR: ftype = &ffi_type_schar; + break; + case _C_UCHR: ftype = &ffi_type_uchar; + break; + case _C_SHT: ftype = &ffi_type_sshort; + break; + case _C_USHT: ftype = &ffi_type_ushort; + break; + case _C_INT: ftype = &ffi_type_sint; + break; + case _C_UINT: ftype = &ffi_type_uint; + break; + case _C_LNG: ftype = &ffi_type_slong; + break; + case _C_ULNG: ftype = &ffi_type_ulong; + break; +#ifdef _C_LNG_LNG + case _C_LNG_LNG: ftype = 0; + NSCAssert(ftype, @"long long encoding not implemented"); + break; + case _C_ULNG_LNG: ftype = 0; + NSCAssert(ftype, @"long long encoding not implemented"); + break; +#endif + case _C_FLT: ftype = &ffi_type_float; + break; + case _C_DBL: ftype = &ffi_type_double; + break; + case _C_PTR: + ftype = &ffi_type_pointer; + if (*typePtr == '?') + { + typePtr++; + } + else + { + ffi_type *local; + typePtr = cifframe_next_arg(typePtr, &local); + } + break; + + case _C_ATOM: + case _C_CHARPTR: + ftype = &ffi_type_pointer; + break; + + case _C_ARY_B: + { + ffi_type *local; + ftype = &ffi_type_pointer; + + while (isdigit(*typePtr)) + { + typePtr++; + } + typePtr = cifframe_next_arg(typePtr, &local); + typePtr++; /* Skip end-of-array */ + } + break; + + case _C_STRUCT_B: + { + int types, maxtypes; + ffi_type *local; + + ftype = malloc(sizeof(ffi_type)); + ftype->size = 0; + ftype->alignment = 0; + ftype->type = FFI_TYPE_STRUCT; + /* + * Skip "=" stuff. + */ + while (*typePtr != _C_STRUCT_E) + { + if (*typePtr++ == '=') + { + break; + } + } + types = 0; + maxtypes = 4; + ftype->elements = malloc(maxtypes*sizeof(ffi_type)); + /* + * Continue accumulating structure size. + */ + while (*typePtr != _C_STRUCT_E) + { + typePtr = cifframe_next_arg(typePtr, &local); + NSCAssert(typePtr, @"End of signature while parsing"); + ftype->elements[types++] = local; + if (types >= maxtypes) + { + maxtypes *=2; + ftype->elements = realloc(ftype->elements, + maxtypes*sizeof(ffi_type)); + } + } + ftype->elements[types] = NULL; + typePtr++; /* Skip end-of-struct */ + } + break; + + case _C_UNION_B: + { + ffi_type *local; + int max_align = 0; + + /* + * Skip "=" stuff. + */ + while (*typePtr != _C_UNION_E) + { + if (*typePtr++ == '=') + { + break; + } + } + ftype = NULL; + while (*typePtr != _C_UNION_E) + { + int align = objc_alignof_type(typePtr); + typePtr = cifframe_next_arg(typePtr, &local); + NSCAssert(typePtr, @"End of signature while parsing"); + if (align > max_align) + { + if (ftype && ftype->type == FFI_TYPE_STRUCT) + free(ftype->elements); + ftype = local; + max_align = align; + } + } + typePtr++; /* Skip end-of-union */ + } + break; + + case _C_VOID: ftype = &ffi_type_void; + break; + default: + NSCAssert(0, @"Unknown type in sig"); + } + + /* Skip past any offset information, if there is any */ + if (*type != _C_PTR || *type == '?') + { + if (*typePtr == '+') + typePtr++; + if (*typePtr == '-') + typePtr++; + while (isdigit(*typePtr)) + typePtr++; + } + + NSCAssert(typePtr, @"Unfinished signature"); + *ftype_ret = ftype; + return typePtr; +} + +/* Some return types actually get coded differently. We need to convert + back to the expected return type */ +BOOL +cifframe_decode_return (const char *type, void* buffer) +{ + int size = 0; + + type = objc_skip_type_qualifiers(type); + NSGetSizeAndAlignment(type, &size, 0); + + switch (*type) + { + case _C_ID: + break; + case _C_CLASS: + break; + case _C_SEL: + break; + case _C_CHR: + case _C_UCHR: + { + *(unsigned char*)buffer = (unsigned char)(*((smallret_t *)buffer)); + break; + } + + case _C_SHT: + case _C_USHT: + { + *(unsigned short*)buffer = (unsigned short)(*((smallret_t *)buffer)); + break; + } + + case _C_INT: + case _C_UINT: + { + *(unsigned int*)buffer = (unsigned int)(*((smallret_t *)buffer)); + break; + } + + case _C_LNG: + case _C_ULNG: + break; + + case _C_LNG_LNG: + case _C_ULNG_LNG: + break; + + case _C_FLT: + break; + + case _C_DBL: + break; + + case _C_PTR: + case _C_ATOM: + case _C_CHARPTR: + break; + + case _C_ARY_B: + case _C_STRUCT_B: + case _C_UNION_B: + break; + + case _C_VOID: + break; + + default: + return NO; /* Unknown type. */ + } + return YES; +} + + +/*-------------------------------------------------------------------------*/ +/* Functions for handling sending and receiving messages accross a + connection +*/ + +/* cifframe_do_call() + + This function decodes the arguments of method call, builds an + argframe of type arglist_t, and invokes the method using + __builtin_apply; then it encodes the return value and any + pass-by-reference arguments. + + ENCODED_TYPES should be a string that describes the return value + and arguments. It's argument types and argument type qualifiers + should match exactly those that were used when the arguments were + encoded with cifframe_dissect_call()---cifframe_do_call() uses + ENCODED_TYPES to determine which variable types it should decode. + + ENCODED_TYPES is used to get the types and type qualifiers, but not + to get the register and stack locations---we get that information + from the selector type of the SEL that is decoded as the second + argument. In this way, the ENCODED_TYPES may come from a machine + of a different architecture. Having the original ENCODED_TYPES is + good, just in case the machine running cifframe_do_call() has some + slightly different qualifiers. Using different qualifiers for + encoding and decoding could lead to massive confusion. + + + DECODER should be a pointer to a function that obtains the method's + argument values. For example: + + void my_decoder (int argnum, void *data, const char *type) + + ARGNUM is the number of the argument, beginning at 0. + DATA is a pointer to the memory where the value should be placed. + TYPE is a pointer to the type string of this value. + + cifframe_do_call() calls this function once for each of the methods + arguments. The DECODER function should place the ARGNUM'th + argument's value at the memory location DATA. + cifframe_do_call() calls this function once with ARGNUM -1, DATA 0, + and TYPE 0 to denote completion of decoding. + + + If DECODER malloc's new memory in the course of doing its + business, then DECODER is responsible for making sure that the + memory will get free eventually. For example, if DECODER uses + -decodeValueOfCType:at:withName: to decode a char* string, you + should remember that -decodeValueOfCType:at:withName: malloc's + new memory to hold the string, and DECODER should autorelease the + malloc'ed pointer, using the NSData class. + + + ENCODER should be a pointer to a function that records the method's + return value and pass-by-reference values. For example: + + void my_encoder (int argnum, void *data, const char *type, int flags) + + ARGNUM is the number of the argument; this will be -1 for the + return value, and the argument index for the pass-by-reference + values; the indices start at 0. + DATA is a pointer to the memory where the value can be found. + TYPE is a pointer to the type string of this value. + FLAGS is a copy of the type qualifier flags for this argument; + (see ). + + cifframe_do_call() calls this function after the method has been + run---once for the return value, and once for each of the + pass-by-reference parameters. The ENCODER function should place + the value at memory location DATA wherever the user wants to + record the ARGNUM'th return value. + + PASS_POINTERS is a flag saying whether pointers should be passed + as pointers (for local stuff) or should be assumed to point to a + single data item (for distributed objects). +*/ + +void +cifframe_do_call_opts (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int), + BOOL pass_pointers) +{ + /* The method type string obtained from the target's OBJC_METHOD + structure for the selector we're sending. */ + const char *type; + /* A pointer into the local variable TYPE string. */ + const char *tmptype; + /* A pointer into the argument ENCODED_TYPES string. */ + const char *etmptype; + /* The target object that will receive the message. */ + id object; + /* The selector for the message we're sending to the TARGET. */ + SEL selector; + /* The OBJECT's implementation of the SELECTOR. */ + IMP method_implementation; + /* A pointer into the ARGFRAME; points at individual arguments. */ + char *datum; + /* Type qualifier flags; see . */ + unsigned flags; + /* Which argument number are we processing now? */ + int argnum; + /* A pointer to the memory holding the return value of the method. */ + void *retval; + /* The cif information for calling the method */ + cifframe_t *cframe; + /* Does the method have any arguments that are passed by reference? + If so, we need to encode them, since the method may have changed them. */ + BOOL out_parameters = NO; + + /* Decode the object, (which is always the first argument to a method), + into the local variable OBJECT. */ + (*decoder) (0, &object, @encode(id)); + NSCParameterAssert (object); + + /* Decode the selector, (which is always the second argument to a + method), into the local variable SELECTOR. */ + /* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ + (*decoder) (1, &selector, ":"); + NSCParameterAssert (selector); + + /* Get the "selector type" for this method. The "selector type" is + a string that lists the return and argument types, and also + indicates in which registers and where on the stack the arguments + should be placed before the method call. The selector type + string we get here should have the same argument and return types + as the ENCODED_TYPES string, but it will have different register + and stack locations if the ENCODED_TYPES came from a machine of a + different architecture. */ +#if NeXT_runtime + { + Method m; + m = class_getInstanceMethod(object->isa, selector); + if (!m) + abort(); + type = m->method_types; + } +#elif 0 + { + Method_t m; + m = class_get_instance_method (object->class_pointer, + selector); + NSCParameterAssert (m); + type = m->method_types; + } +#else + type = sel_get_type (selector); +#endif /* NeXT_runtime */ + + /* Make sure we successfully got the method type, and that its + types match the ENCODED_TYPES. */ + NSCParameterAssert (type); + NSCParameterAssert (sel_types_match(encoded_types, type)); + + /* Build the cif frame */ + cframe = cifframe_from_sig(type, &retval); + + /* Put OBJECT and SELECTOR into the ARGFRAME. */ + + /* Initialize our temporary pointers into the method type strings. */ + tmptype = objc_skip_argspec (type); + etmptype = objc_skip_argspec (encoded_types); + NSCParameterAssert (*tmptype == _C_ID); + /* Put the target object there. */ + cifframe_set_arg(cframe, 0, &object); + /* Get a pointer into ARGFRAME, pointing to the location where the + second argument is to be stored. */ + tmptype = objc_skip_argspec (tmptype); + etmptype = objc_skip_argspec(etmptype); + NSCParameterAssert (*tmptype == _C_SEL); + /* Put the selector there. */ + cifframe_set_arg(cframe, 1, &selector); + + + /* Decode arguments after OBJECT and SELECTOR, and put them into the + ARGFRAME. Step TMPTYPE and ETMPTYPE in lock-step through their + method type strings. */ + + for (tmptype = objc_skip_argspec (tmptype), + etmptype = objc_skip_argspec (etmptype), argnum = 2; + *tmptype != '\0'; + tmptype = objc_skip_argspec (tmptype), + etmptype = objc_skip_argspec (etmptype), argnum++) + { + /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ + flags = objc_get_type_qualifiers (etmptype); + /* Skip over the type qualifiers, so now TYPE is pointing directly + at the char corresponding to the argument's type, as defined + in */ + tmptype = objc_skip_type_qualifiers(tmptype); + + datum = cifframe_arg_addr(cframe, argnum); + + /* Decide how, (or whether or not), to decode the argument + depending on its FLAGS and TMPTYPE. Only the first two cases + involve parameters that may potentially be passed by + reference, and thus only the first two may change the value + of OUT_PARAMETERS. *** Note: This logic must match exactly + the code in cifframe_dissect_call(); that function should + encode exactly what we decode here. *** */ + + switch (*tmptype) + { + + case _C_CHARPTR: + /* Handle a (char*) argument. */ + /* If the char* is qualified as an OUT parameter, or if it + not explicitly qualified as an IN parameter, then we will + have to get this char* again after the method is run, + because the method may have changed it. Set + OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* If the char* is qualified as an IN parameter, or not + explicity qualified as an OUT parameter, then decode it. + Note: the decoder allocates memory for holding the + string, and it is also responsible for making sure that + the memory gets freed eventually, (usually through the + autorelease of NSData object). */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, datum, tmptype); + + break; + + case _C_PTR: + /* If the pointer's value is qualified as an OUT parameter, + or if it not explicitly qualified as an IN parameter, + then we will have to get the value pointed to again after + the method is run, because the method may have changed + it. Set OUT_PARAMETERS accordingly. */ + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if (pass_pointers) + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, datum, tmptype); + } + else + { + /* Handle an argument that is a pointer to a non-char. But + (void*) and (anything**) is not allowed. */ + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Allocate some memory to be pointed to, and to hold the + value. Note that it is allocated on the stack, and + methods that want to keep the data pointed to, will have + to make their own copies. */ + *(void**)datum = alloca (objc_sizeof_type (tmptype)); + /* If the pointer's value is qualified as an IN parameter, + or not explicity qualified as an OUT parameter, then + decode it. */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, *(void**)datum, tmptype); + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* Handle struct and array arguments. */ + (*decoder) (argnum, datum, tmptype); + break; + + default: + /* Handle arguments of all other types. */ + /* NOTE FOR OBJECTS: Unlike [Decoder decodeObjectAt:..], + this function does not generate a reference to the + object; the object may be autoreleased; if the method + wants to keep a reference to the object, it will have to + -retain it. */ + (*decoder) (argnum, datum, tmptype); + } + } + /* End of the for() loop that enumerates the method's arguments. */ + (*decoder) (-1, 0, 0); + + + /* Invoke the method! */ + + /* Find the target object's implementation of this selector. */ + method_implementation = objc_msg_lookup (object, selector); + NSCParameterAssert (method_implementation); + /* Do it! Send the message to the target, and get the return value + in retval. We need to rencode any pass-by-reference info */ + ffi_call(&(cframe->cif), FFI_FN(method_implementation), retval, + cframe->values); + + /* Encode the return value and pass-by-reference values, if there + are any. This logic must match exactly that in + cifframe_build_return(). */ + /* OUT_PARAMETERS should be true here in exactly the same + situations as it was true in cifframe_dissect_call(). */ + + /* Get the qualifier type of the return value. */ + flags = objc_get_type_qualifiers (encoded_types); + /* Get the return type; store it our two temporary char*'s. */ + etmptype = objc_skip_type_qualifiers (encoded_types); + tmptype = objc_skip_type_qualifiers (type); + + /* Only encode return values if there is a non-void return value, + a non-oneway void return value, or if there are values that were + passed by reference. */ + + /* If there is a return value, encode it. */ + cifframe_decode_return(tmptype, retval); + switch (*tmptype) + { + case _C_VOID: + if ((flags & _F_ONEWAY) == 0) + { + int dummy = 0; + (*encoder) (-1, (void*)&dummy, @encode(int), 0); + } + /* No return value to encode; do nothing. */ + break; + + case _C_PTR: + if (pass_pointers) + { + (*encoder) (-1, retval, tmptype, flags); + } + else + { + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Encode the value that was pointed to. */ + (*encoder) (-1, *(void**)retval, tmptype, flags); + } + break; + + case _C_STRUCT_B: + case _C_UNION_B: + case _C_ARY_B: + /* The argument is a structure or array returned by value. + (In C, are array's allowed to be returned by value?) */ + (*encoder)(-1, retval, tmptype, flags); + break; + + case _C_FLT: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_DBL: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_SHT: + case _C_USHT: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + case _C_CHR: + case _C_UCHR: + { + (*encoder) (-1, retval, tmptype, flags); + break; + } + + default: + /* case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: + case _C_CHARPTR: case: _C_ID: */ + /* xxx I think this assumes that sizeof(int)==sizeof(void*) */ + (*encoder) (-1, retval, tmptype, flags); + } + + + /* Encode the values returned by reference. Note: this logic + must match exactly the code in cifframe_build_return(); that + function should decode exactly what we encode here. */ + + if (out_parameters) + { + /* Step through all the arguments, finding the ones that were + passed by reference. */ + for (tmptype = objc_skip_argspec (tmptype), + argnum = 0, + etmptype = objc_skip_argspec (etmptype); + *tmptype != '\0'; + tmptype = objc_skip_argspec (tmptype), + argnum++, + etmptype = objc_skip_argspec (etmptype)) + { + /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ + flags = objc_get_type_qualifiers(etmptype); + /* Skip over the type qualifiers, so now TYPE is pointing directly + at the char corresponding to the argument's type, as defined + in */ + tmptype = objc_skip_type_qualifiers (tmptype); + + /* Decide how, (or whether or not), to encode the argument + depending on its FLAGS and TMPTYPE. */ + datum = cifframe_arg_addr(cframe, argnum); + + if ((*tmptype == _C_PTR) + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + /* The argument is a pointer (to a non-char), and the + pointer's value is qualified as an OUT parameter, or + it not explicitly qualified as an IN parameter, then + it is a pass-by-reference argument.*/ + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Encode it. */ + (*encoder) (argnum, *(void**)datum, tmptype, flags); + } + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + /* The argument is a pointer char string, and the + pointer's value is qualified as an OUT parameter, or + it not explicitly qualified as an IN parameter, then + it is a pass-by-reference argument. Encode it.*/ + /* xxx Perhaps we could save time and space by saving + a copy of the string before the method call, and then + comparing it to this string; if it didn't change, don't + bother to send it back again. */ + (*encoder) (argnum, datum, tmptype, flags); + } + } + } + + return; +} + +void +cifframe_do_call (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int)) +{ + cifframe_do_call_opts(encoded_types, decoder, encoder, NO); +} diff --git a/Testing/nsconnection_client.m b/Testing/nsconnection_client.m index bfc907b9c..6e3300c93 100644 --- a/Testing/nsconnection_client.m +++ b/Testing/nsconnection_client.m @@ -88,7 +88,7 @@ int con_data (id prx) printf(send, var); \ varr = [prx msg1 var]; \ printf(got, varr); \ - if (varr != var+ADD_CONST) \ + if (varr != (var+ADD_CONST)) \ printf(" *** ERROR ***\n"); \ else \ printf(" ...ok\n"); \ @@ -96,20 +96,37 @@ int con_data (id prx) printf(sendp, varr); \ [prx msg2 &varr]; \ printf(got, varr); \ - if (varr != var+ADD_CONST) \ + if (varr != (var+ADD_CONST)) \ printf(" *** ERROR ***\n"); \ else \ printf(" ...ok\n"); - TEST_CALL("UChar:\n", " sending %x", " got %x", " sending ptr to %x", +#define TEST_FCALL(test, send, got, sendp, var, varr, val, msg1, msg2) \ + printf(test); \ + var = val; \ + printf(send, var); \ + varr = [prx msg1 var]; \ + printf(got, varr); \ + if (varr - (var+ADD_CONST) > 1e-3) \ + printf(" *** ERROR ***\n"); \ + else \ + printf(" ...ok\n"); \ + varr = var = val+1; \ + printf(sendp, varr); \ + [prx msg2 &varr]; \ + printf(got, varr); \ + if (varr - (var+ADD_CONST) > 1e-3) \ + printf(" *** ERROR ***\n"); \ + else \ + printf(" ...ok\n"); + + TEST_CALL("UChar:\n", " sending %d", " got %d", " sending ptr to %d", uc, ucr, 23, sendUChar:, getUChar:) - printf(" (should get error returning ptr)\n"); - TEST_CALL("Char:\n", " sending %x", " got %x", " sending ptr to %x", + TEST_CALL("Char:\n", " sending %d", " got %d", " sending ptr to %d", c, cr, 23, sendChar:, getChar:) - printf(" (should get error returning ptr)\n"); - TEST_CALL("Short:\n", " sending %d", " got %d", " sending ptr to %d", + TEST_CALL("Short:\n", " sending %hd", " got %hd", " sending ptr to %hd", s, sr, 23, sendShort:, getShort:) TEST_CALL("Int:\n", " sending %d", " got %d", " sending ptr to %d", @@ -118,10 +135,10 @@ int con_data (id prx) TEST_CALL("Long:\n", " sending %ld", " got %ld", " sending ptr to %ld", l, lr, 23, sendLong:, getLong:) - TEST_CALL("Float:\n", " sending %f", " got %f", " sending ptr to %f", + TEST_FCALL("Float:\n", " sending %f", " got %f", " sending ptr to %f", flt, fltr, 23.2, sendFloat:, getFloat:) - TEST_CALL("Double:\n", " sending %g", " got %g", " sending ptr to %g", + TEST_FCALL("Double:\n", " sending %g", " got %g", " sending ptr to %g", dbl, dblr, 23.2, sendDouble:, getDouble:) flt = 2.718; diff --git a/Testing/nsconnection_server.m b/Testing/nsconnection_server.m index 248405606..8219f476b 100644 --- a/Testing/nsconnection_server.m +++ b/Testing/nsconnection_server.m @@ -74,7 +74,7 @@ - (BOOL) sendBoolean: (BOOL)b { - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), b, !b); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), (int)b, (int)(!b)); fflush(stdout); return !b; } @@ -82,16 +82,18 @@ /* This causes problems, because the runtime encodes this as "*", a string! */ - (void) getBoolean: (BOOL*)bp { - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), *bp, !(*bp)); + BOOL rbp = !(*bp); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), + (int)*bp, (int)rbp); fflush(stdout); - *bp = !(*bp); + *bp = rbp; } -/* This causes problems, because the runtime encodes this as "*", a string! */ - (unsigned char) sendUChar: (unsigned char)num { unsigned char rnum = num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), num, rnum); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), + (int)num, (int)rnum); fflush(stdout); return rnum; } @@ -100,7 +102,8 @@ - (void) getUChar: (unsigned char *)num { unsigned char rnum = *num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), *num, rnum); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), + (int)(*num), (int)rnum); *num = rnum; fflush(stdout); } @@ -108,7 +111,8 @@ - (char) sendChar: (char)num { char rnum = num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), num, rnum); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), + (int)num, (int)rnum); fflush(stdout); return rnum; } @@ -116,7 +120,8 @@ - (void) getChar: (char *)num { char rnum = *num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), *num, rnum); + printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), + (int)(*num), (int)rnum); *num = rnum; fflush(stdout); } @@ -124,7 +129,8 @@ - (short) sendShort: (short)num { short rnum = num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), num, rnum); + printf("(%s) got %hd, returning %hd\n", sel_get_name(_cmd), + num, rnum); fflush(stdout); return rnum; } @@ -132,7 +138,8 @@ - (void) getShort: (short *)num { short rnum = *num + ADD_CONST; - printf("(%s) got %d, returning %d\n", sel_get_name(_cmd), *num, rnum); + printf("(%s) got %hd, returning %hd\n", sel_get_name(_cmd), + (*num), rnum); *num = rnum; fflush(stdout); } diff --git a/acconfig.h b/acconfig.h index 746dce261..4bfa5ec34 100644 --- a/acconfig.h +++ b/acconfig.h @@ -138,3 +138,10 @@ /* Define if your system has a /proc/self/exe symlink to the executable */ #undef HAVE_PROC_FS_EXE_LINK + +/* Define if using the libffi library for invocations */ +#undef USE_LIBFFI + +/* Define if using the ffcall library for invocations */ +#undef USE_FFCALL + diff --git a/config.mak.in b/config.mak.in index 8b3476e86..eb2a1e78c 100644 --- a/config.mak.in +++ b/config.mak.in @@ -8,3 +8,4 @@ DYNAMIC_LINKER=@DYNAMIC_LINKER@ HAVE_LIBXML=@HAVE_LIBXML@ +WITH_FFI=@WITH_FFI@ diff --git a/configure b/configure index 6c266a554..8f300bedc 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.13.1 +# Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -12,9 +12,13 @@ ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help - --enable-pass-arguments User main calls NSProcessInfo initialization" + --enable-pass-arguments Force user main call to NSProcessInfo initialize" ac_help="$ac_help - --enable-fake-main Force use of redefine of the main function" + --enable-fake-main Force redefine of user main function" +ac_help="$ac_help + --enable-libffi Enable use of libffi library" +ac_help="$ac_help + --enable-ffcall Enable use of ffcall library" ac_help="$ac_help --with-libxml-include=PATH include path for libxml headers" ac_help="$ac_help @@ -349,7 +353,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.13.1" + echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) @@ -509,7 +513,7 @@ done if test -r "$cache_file"; then echo "loading cache $cache_file" - test -f "$cache_file" && . $cache_file + . $cache_file else echo "creating cache $cache_file" > $cache_file @@ -585,130 +589,9 @@ done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. - - -echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:595: checking host system type" >&5 -if test "x$ac_cv_host" = "x" || (test "x$host" != "xNONE" && test "x$host" != "x$ac_cv_host_alias"); then - -# Make sure we can run config.sub. - if $ac_config_sub sun4 >/dev/null 2>&1; then : - else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } - fi - - ac_cv_host_alias=$host - case "$ac_cv_host_alias" in - NONE) - case $nonopt in - NONE) - if ac_cv_host_alias=`$ac_config_guess`; then : - else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } - fi ;; - *) ac_cv_host_alias=$nonopt ;; - esac ;; - esac - - ac_cv_host=`$ac_config_sub $ac_cv_host_alias` - ac_cv_host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` - ac_cv_host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` - ac_cv_host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -else - echo $ac_n "(cached) $ac_c" 1>&6 -fi - -echo "$ac_t""$ac_cv_host" 1>&6 - -host=$ac_cv_host -host_alias=$ac_cv_host_alias -host_cpu=$ac_cv_host_cpu -host_vendor=$ac_cv_host_vendor -host_os=$ac_cv_host_os - - - - - -echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:636: checking target system type" >&5 -if test "x$ac_cv_target" = "x" || (test "x$target" != "xNONE" && test "x$target" != "x$ac_cv_target_alias"); then - -# Make sure we can run config.sub. - if $ac_config_sub sun4 >/dev/null 2>&1; then : - else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } - fi - - ac_cv_target_alias=$target - case "$ac_cv_target_alias" in - NONE) - case $nonopt in - NONE) - ac_cv_target_alias=$host_alias ;; - - *) ac_cv_target_alias=$nonopt ;; - esac ;; - esac - - ac_cv_target=`$ac_config_sub $ac_cv_target_alias` - ac_cv_target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` - ac_cv_target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` - ac_cv_target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -else - echo $ac_n "(cached) $ac_c" 1>&6 -fi - -echo "$ac_t""$ac_cv_target" 1>&6 - -target=$ac_cv_target -target_alias=$ac_cv_target_alias -target_cpu=$ac_cv_target_cpu -target_vendor=$ac_cv_target_vendor -target_os=$ac_cv_target_os - - - - - -echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:676: checking build system type" >&5 -if test "x$ac_cv_build" = "x" || (test "x$build" != "xNONE" && test "x$build" != "x$ac_cv_build_alias"); then - -# Make sure we can run config.sub. - if $ac_config_sub sun4 >/dev/null 2>&1; then : - else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } - fi - - ac_cv_build_alias=$build - case "$ac_cv_build_alias" in - NONE) - case $nonopt in - NONE) - ac_cv_build_alias=$host_alias ;; - - *) ac_cv_build_alias=$nonopt ;; - esac ;; - esac - - ac_cv_build=`$ac_config_sub $ac_cv_build_alias` - ac_cv_build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` - ac_cv_build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` - ac_cv_build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -else - echo $ac_n "(cached) $ac_c" 1>&6 -fi - -echo "$ac_t""$ac_cv_build" 1>&6 - -build=$ac_cv_build -build_alias=$ac_cv_build_alias -build_cpu=$ac_cv_build_cpu -build_vendor=$ac_cv_build_vendor -build_os=$ac_cv_build_os - - - +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Do some error checking and defaulting for the host and target type. @@ -731,6 +614,69 @@ NONE---*---* | *---NONE---* | *---*---NONE) ;; *) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; esac + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:625: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:646: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:664: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + test "$host_alias" != "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && @@ -743,8 +689,8 @@ test "$host_alias" != "$target_alias" && # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:747: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +echo "configure:693: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -773,8 +719,8 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:777: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +echo "configure:723: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -820,12 +766,12 @@ fi if test -z "$CC"; then case "`uname -s`" in - *win32* | *WIN32* | *CYGWIN*) + *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:828: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then +echo "configure:774: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then @@ -855,8 +801,8 @@ fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:860: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5 +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:806: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -867,12 +813,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 871 "configure" +#line 817 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:876: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:822: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -897,14 +843,14 @@ echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:902: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:848: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:907: checking whether we are using GNU C" >&5 -if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then +echo "configure:853: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:862: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -931,8 +877,8 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:935: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then +echo "configure:881: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c @@ -963,13 +909,13 @@ else fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:967: checking how to run the C preprocessor" >&5 +echo "configure:913: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then -if eval "test \"\${ac_cv_prog_CPP+set}\" = set"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get @@ -978,13 +924,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:988: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:934: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -995,13 +941,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1005: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:951: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1012,13 +958,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:968: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1046,8 +992,8 @@ echo "$ac_t""$CPP" 1>&6 # Extract the first word of "whoami", so it can be a program name with args. set dummy whoami; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1050: checking for $ac_word" >&5 -if eval "test \"\${ac_cv_path_WHOAMI+set}\" = set"; then +echo "configure:996: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_WHOAMI'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$WHOAMI" in @@ -1102,14 +1048,14 @@ esac # include implementations of List, HashTable etc. #-------------------------------------------------------------------- echo $ac_n "checking whether we are using NeXT's compiler""... $ac_c" 1>&6 -echo "configure:1106: checking whether we are using NeXT's compiler" >&5 +echo "configure:1052: checking whether we are using NeXT's compiler" >&5 cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1059: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1129,16 +1075,16 @@ if test $NeXTCC = 0; then # Find out if nested functions work on this machine #---------------------------------------------------------------- echo $ac_n "checking whether nested functions work""... $ac_c" 1>&6 -echo "configure:1133: checking whether nested functions work" >&5 +echo "configure:1079: checking whether nested functions work" >&5 if test "$cross_compiling" = yes; then gcc_nested=1 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then gcc_nested=1 else @@ -1170,16 +1116,16 @@ fi # Find out if we're on a NEXTSTEP machine #---------------------------------------------------------------- echo $ac_n "checking whether we are running under NEXTSTEP""... $ac_c" 1>&6 -echo "configure:1174: checking whether we are running under NEXTSTEP" >&5 +echo "configure:1120: checking whether we are running under NEXTSTEP" >&5 cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1129: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1207,16 +1153,16 @@ rm -f conftest* saved_ac_ext=$ac_ext ac_ext=m echo $ac_n "checking whether we are using GNU Objective C runtime""... $ac_c" 1>&6 -echo "configure:1211: checking whether we are using GNU Objective C runtime" >&5 +echo "configure:1157: checking whether we are using GNU Objective C runtime" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* NeXT_runtime=1 else @@ -1262,16 +1208,16 @@ else # Find out if we have NEXTSTEP 3.2 or lower #---------------------------------------------------------------- echo "checking NEXTSTEP version" 1>&6 -echo "configure:1266: checking NEXTSTEP version" >&5 +echo "configure:1212: checking NEXTSTEP version" >&5 cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1221: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1332,8 +1278,8 @@ fi # Check if Objective-C is installed #-------------------------------------------------------------------- echo $ac_n "checking for alternate objc library""... $ac_c" 1>&6 -echo "configure:1336: checking for alternate objc library" >&5 -if eval "test \"\${gs_cv_objc_libdir+set}\" = set"; then +echo "configure:1282: checking for alternate objc library" >&5 +if eval "test \"`echo '$''{'gs_cv_objc_libdir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else gs_cv_objc_libdir=NONE @@ -1361,17 +1307,17 @@ for ac_hdr in objc/objc.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1365: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:1311: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1375: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1321: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1408,7 +1354,7 @@ fi # Check if libobjc was compiled with thread support. #-------------------------------------------------------------------- echo $ac_n "checking whether objc has thread support""... $ac_c" 1>&6 -echo "configure:1412: checking whether objc has thread support" >&5 +echo "configure:1358: checking whether objc has thread support" >&5 saved_LIBS="$LIBS" extra_LIBS="" case "${target_os}" in @@ -1423,11 +1369,11 @@ if test $host_os = linux-gnu; then objc_threaded="-lpthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-lpthread" else @@ -1445,11 +1391,11 @@ fi objc_threaded="-lpcthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1399: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-lpcthread" else @@ -1468,11 +1414,11 @@ elif test "`echo $host_os|sed 's/[0-9].*//'|sed s/elf//`" = freebsd; then objc_threaded="-pthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-pthread" else @@ -1490,11 +1436,11 @@ fi objc_threaded="-lpthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-lpthread" else @@ -1513,11 +1459,11 @@ fi objc_threaded="-lpcthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-lpcthread" else @@ -1536,11 +1482,11 @@ else objc_threaded="-lthread" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1490: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_threaded="-lthread" else @@ -1567,14 +1513,14 @@ ac_cv_objc_threaded=$objc_threaded # Byte order information needed for foundation headers. #-------------------------------------------------------------------- echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:1571: checking whether byte ordering is bigendian" >&5 -if eval "test \"\${ac_cv_c_bigendian+set}\" = set"; then +echo "configure:1517: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -1585,11 +1531,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1589: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -1600,7 +1546,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1550: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -1620,7 +1566,7 @@ if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -1667,15 +1613,15 @@ fi # Type size information needed for foundation headers. #-------------------------------------------------------------------- echo $ac_n "checking size of void*""... $ac_c" 1>&6 -echo "configure:1671: checking size of void*" >&5 -if eval "test \"\${ac_cv_sizeof_voidp+set}\" = set"; then +echo "configure:1617: checking size of void*" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_voidp'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1686,7 +1632,7 @@ main() exit(0); } EOF -if { (eval echo configure:1690: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_voidp=`cat conftestval` else @@ -1712,15 +1658,15 @@ GS_UINT8="unsigned char" echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:1716: checking size of short" >&5 -if eval "test \"\${ac_cv_sizeof_short+set}\" = set"; then +echo "configure:1662: checking size of short" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1731,7 +1677,7 @@ main() exit(0); } EOF -if { (eval echo configure:1735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_short=`cat conftestval` else @@ -1753,15 +1699,15 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:1757: checking size of int" >&5 -if eval "test \"\${ac_cv_sizeof_int+set}\" = set"; then +echo "configure:1703: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1772,7 +1718,7 @@ main() exit(0); } EOF -if { (eval echo configure:1776: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1722: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else @@ -1794,15 +1740,15 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:1798: checking size of long" >&5 -if eval "test \"\${ac_cv_sizeof_long+set}\" = set"; then +echo "configure:1744: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1813,7 +1759,7 @@ main() exit(0); } EOF -if { (eval echo configure:1817: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1763: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long=`cat conftestval` else @@ -1835,15 +1781,15 @@ EOF echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:1839: checking size of long long" >&5 -if eval "test \"\${ac_cv_sizeof_long_long+set}\" = set"; then +echo "configure:1785: checking size of long long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1854,7 +1800,7 @@ main() exit(0); } EOF -if { (eval echo configure:1858: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long=`cat conftestval` else @@ -1876,15 +1822,15 @@ EOF echo $ac_n "checking size of float""... $ac_c" 1>&6 -echo "configure:1880: checking size of float" >&5 -if eval "test \"\${ac_cv_sizeof_float+set}\" = set"; then +echo "configure:1826: checking size of float" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1895,7 +1841,7 @@ main() exit(0); } EOF -if { (eval echo configure:1899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1845: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_float=`cat conftestval` else @@ -1917,15 +1863,15 @@ EOF echo $ac_n "checking size of double""... $ac_c" 1>&6 -echo "configure:1921: checking size of double" >&5 -if eval "test \"\${ac_cv_sizeof_double+set}\" = set"; then +echo "configure:1867: checking size of double" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1936,7 +1882,7 @@ main() exit(0); } EOF -if { (eval echo configure:1940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1886: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_double=`cat conftestval` else @@ -2140,8 +2086,8 @@ fi # Defines CON_AUTOLOAD (whether constructor functions are autoloaded) #-------------------------------------------------------------------- echo $ac_n "checking loading of constructor functions""... $ac_c" 1>&6 -echo "configure:2144: checking loading of constructor functions" >&5 -if eval "test \"\${objc_cv_con_autoload+set}\" = set"; then +echo "configure:2090: checking loading of constructor functions" >&5 +if eval "test \"`echo '$''{'objc_cv_con_autoload'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.constructor.c <&6 -echo "configure:2185: checking for dlfcn.h" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2131: checking for dlfcn.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2195: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2141: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2215,17 +2161,17 @@ fi if test $DYNAMIC_LINKER = null; then ac_safe=`echo "dl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dl.h""... $ac_c" 1>&6 -echo "configure:2219: checking for dl.h" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2165: checking for dl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2229: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2175: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2250,17 +2196,17 @@ fi if test $DYNAMIC_LINKER = null; then ac_safe=`echo "windows.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for windows.h""... $ac_c" 1>&6 -echo "configure:2254: checking for windows.h" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2200: checking for windows.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2264: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2210: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2285,17 +2231,17 @@ fi if test $DYNAMIC_LINKER = null; then ac_safe=`echo "dld/defs.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dld/defs.h""... $ac_c" 1>&6 -echo "configure:2289: checking for dld/defs.h" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2235: checking for dld/defs.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2299: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2245: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2320,14 +2266,14 @@ fi if test $DYNAMIC_LINKER = simple; then cat > conftest.$ac_ext < int main() { dladdr(0,0); ; return 0; } EOF -if { (eval echo configure:2331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_DLADDR 1 @@ -2357,19 +2303,19 @@ if test x"$ac_cv_objc_threaded" != x""; then fi LIBS="$LIBS $extra_LIBS" echo $ac_n "checking if +load method is executed before main""... $ac_c" 1>&6 -echo "configure:2361: checking if +load method is executed before main" >&5 -if eval "test \"\${objc_load_method_worked+set}\" = set"; then +echo "configure:2307: checking if +load method is executed before main" >&5 +if eval "test \"`echo '$''{'objc_load_method_worked'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then objc_load_method_worked=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then objc_load_method_worked=yes else @@ -2404,12 +2350,12 @@ CPPFLAGS="$saved_CPPFLAGS" for ac_func in objc_condition_timedwait do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2408: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:2354: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2382: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2459,7 +2404,7 @@ done cat > conftest.$ac_ext < EOF @@ -2480,12 +2425,12 @@ LIBS="$saved_LIBS" # Generic settings needed by NSZone.m #-------------------------------------------------------------------- echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2484: checking for ANSI C header files" >&5 -if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then +echo "configure:2429: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2493,7 +2438,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2497: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2510,7 +2455,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2528,7 +2473,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2549,7 +2494,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2560,7 +2505,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2584,12 +2529,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2588: checking for size_t" >&5 -if eval "test \"\${ac_cv_type_size_t+set}\" = set"; then +echo "configure:2533: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2600,40 +2545,38 @@ EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* - eval "ac_cv_type_size_t=yes" + ac_cv_type_size_t=yes else rm -rf conftest* - eval "ac_cv_type_size_t=no" + ac_cv_type_size_t=no fi rm -f conftest* fi -if eval "test \"`echo '$ac_cv_type_'size_t`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 - cat >> confdefs.h <&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:2623: checking for inline" >&5 -if eval "test \"\${ac_cv_c_inline+set}\" = set"; then +echo "configure:2566: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2580: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -2663,12 +2606,12 @@ esac # Following header checks needed for bzero in Storage.m and other places #-------------------------------------------------------------------- echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2667: checking for ANSI C header files" >&5 -if eval "test \"\${ac_cv_header_stdc+set}\" = set"; then +echo "configure:2610: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2676,7 +2619,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2680: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2623: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2693,7 +2636,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2711,7 +2654,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2732,7 +2675,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2743,7 +2686,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2690: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2770,17 +2713,17 @@ for ac_hdr in string.h memory.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2774: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2717: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2784: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2814,17 +2757,17 @@ for ac_hdr in values.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2818: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2761: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2828: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2771: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2858,17 +2801,17 @@ for ac_hdr in sys/stat.h sys/vfs.h sys/statfs.h sys/statvfs.h pwd.h grp.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2862: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2805: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2872: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2815: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2898,17 +2841,17 @@ for ac_hdr in sys/mount.h sys/types.h windows.h locale.h langinfo.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2902: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2845: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2912: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2939,12 +2882,12 @@ LIBS="$LIBS -lm" for ac_func in statvfs symlink readlink geteuid rint do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2943: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:2886: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3002,17 +2944,17 @@ for ac_hdr in sys/time.h sys/rusage.h ucbinclude/sys/resource.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3006: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2948: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3016: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2958: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3046,17 +2988,17 @@ for ac_hdr in sys/socket.h netinet/in.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3050: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:2992: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3090,17 +3032,17 @@ for ac_hdr in syslog.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3094: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:3036: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3104: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3046: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3129,12 +3071,12 @@ done for ac_func in syslog do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3133: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3075: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3189,12 +3130,12 @@ done for ac_func in vsprintf vasprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3193: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3134: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3247,11 +3187,11 @@ if test $ac_cv_func_vsprintf = yes ; then VSPRINTF_RETURNS_LENGTH=1 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then VSPRINTF_RETURNS_LENGTH=1 else @@ -3273,11 +3213,11 @@ if test $ac_cv_func_vasprintf = yes ; then VASPRINTF_RETURNS_LENGTH=1 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3221: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then VASPRINTF_RETURNS_LENGTH=1 else @@ -3301,12 +3241,12 @@ fi for ac_func in getcwd do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3305: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3245: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3359,12 +3298,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:3363: checking for $ac_hdr that defines DIR" >&5 -if eval "test \"\${ac_cv_header_dirent_$ac_safe+set}\" = set"; then +echo "configure:3302: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -3372,7 +3311,7 @@ int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:3376: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3315: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -3397,15 +3336,15 @@ done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:3401: checking for opendir in -ldir" >&5 -ac_lib_var=`echo dir'_'opendir | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "configure:3340: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3438,15 +3377,15 @@ fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:3442: checking for opendir in -lx" >&5 -ac_lib_var=`echo x'_'opendir | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "configure:3381: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3487,17 +3426,17 @@ for ac_hdr in getopt.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3491: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:3430: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3501: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3440: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3530,12 +3469,12 @@ done for ac_func in valloc do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3534: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3473: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3501: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3590,12 +3528,12 @@ done for ac_func in times do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3594: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3532: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3650,12 +3587,12 @@ done for ac_func in mkstemp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3654: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3591: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3706,12 +3642,12 @@ done for ac_func in shmctl do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3710: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3646: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3674: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3762,12 +3697,12 @@ done for ac_func in mmap do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3766: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3701: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3822,12 +3756,12 @@ done for ac_func in inet_aton do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3826: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3760: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3788: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3882,12 +3815,12 @@ done for ac_func in killpg setpgrp setpgid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3886: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3819: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3936,15 +3868,15 @@ fi done echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:3940: checking whether setpgrp takes no argument" >&5 -if eval "test \"\${ac_cv_func_setpgrp_void+set}\" = set"; then +echo "configure:3872: checking whether setpgrp takes no argument" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_setpgrp_void=no else @@ -3994,12 +3926,12 @@ fi for ac_func in usleep do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3998: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3930: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4054,12 +3985,12 @@ done for ac_func in strerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4058: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:3989: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4112,12 +4042,12 @@ done # This function needed by NSString for handling of %@ printf directive. #-------------------------------------------------------------------- echo $ac_n "checking for register_printf_function""... $ac_c" 1>&6 -echo "configure:4116: checking for register_printf_function" >&5 -if eval "test \"\${ac_cv_func_register_printf_function+set}\" = set"; then +echo "configure:4046: checking for register_printf_function" >&5 +if eval "test \"`echo '$''{'ac_cv_func_register_printf_function'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_register_printf_function=yes" else @@ -4166,11 +4095,11 @@ if test $register_printf = 1; then working_register_printf=1 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then working_register_printf=1 else @@ -4196,12 +4125,12 @@ fi for ac_func in realpath do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4200: checking for $ac_func" >&5 -if eval "test \"\${ac_cv_func_$ac_func+set}\" = set"; then +echo "configure:4129: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4255,15 +4183,15 @@ done # Used in critical cases by NSProcessInfo.m #-------------------------------------------------------------------- echo $ac_n "checking program_invocation_name in C Library""... $ac_c" 1>&6 -echo "configure:4259: checking program_invocation_name in C Library" >&5 -if eval "test \"\${program_invocation_name_worked+set}\" = set"; then +echo "configure:4187: checking program_invocation_name in C Library" >&5 +if eval "test \"`echo '$''{'program_invocation_name_worked'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then program_invocation_name_worked=no else cat > conftest.$ac_ext < @@ -4275,7 +4203,7 @@ main (int argc, char *argv[]) } EOF -if { (eval echo configure:4279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then program_invocation_name_worked=yes else @@ -4304,7 +4232,7 @@ fi # Needed by NSProcessInfo.m #-------------------------------------------------------------------- echo $ac_n "checking kernel support for /proc filesystem""... $ac_c" 1>&6 -echo "configure:4308: checking kernel support for /proc filesystem" >&5 +echo "configure:4236: checking kernel support for /proc filesystem" >&5 if (grep proc /etc/fstab >/dev/null 2>/dev/null); then sys_proc_fs=yes; cat >> confdefs.h <<\EOF @@ -4327,7 +4255,7 @@ fi sys_proc_fs_exe=no; if test $sys_proc_fs = yes; then echo $ac_n "checking link to executable in /proc""... $ac_c" 1>&6 -echo "configure:4331: checking link to executable in /proc" >&5 +echo "configure:4259: checking link to executable in /proc" >&5 if test -L /proc/self/exe; then sys_proc_fs_exe=yes; echo "$ac_t""yes" 1>&6 @@ -4340,16 +4268,16 @@ fi # Check if short and int values need to be word aligned #-------------------------------------------------------------------- echo $ac_n "checking short/int needs to be word aligned""... $ac_c" 1>&6 -echo "configure:4344: checking short/int needs to be word aligned" >&5 +echo "configure:4272: checking short/int needs to be word aligned" >&5 if test "$cross_compiling" = yes; then NEED_WORD_ALIGNMENT=1 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4281: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then NEED_WORD_ALIGNMENT=0 else @@ -4377,7 +4305,7 @@ fi # doesn't work. Allow NSProcessInfo initialization method also. #-------------------------------------------------------------------- echo $ac_n "checking "use of pass-through arguments"""... $ac_c" 1>&6 -echo "configure:4381: checking "use of pass-through arguments"" >&5 +echo "configure:4309: checking "use of pass-through arguments"" >&5 # Check whether --enable-pass-arguments or --disable-pass-arguments was given. if test "${enable_pass_arguments+set}" = set; then enableval="$enable_pass_arguments" @@ -4399,7 +4327,7 @@ fi echo "$ac_t""$enable_pass_arguments" 1>&6 echo $ac_n "checking "use of fake-main definition"""... $ac_c" 1>&6 -echo "configure:4403: checking "use of fake-main definition"" >&5 +echo "configure:4331: checking "use of fake-main definition"" >&5 # Check whether --enable-fake-main or --disable-fake-main was given. if test "${enable_fake_main+set}" = set; then enableval="$enable_fake_main" @@ -4442,6 +4370,146 @@ esac echo "$ac_t""$enable_fake_main" 1>&6 +#-------------------------------------------------------------------- +# Check for FFI interface libraries for invocations +#-------------------------------------------------------------------- +# Check whether --enable-libffi or --disable-libffi was given. +if test "${enable_libffi+set}" = set; then + enableval="$enable_libffi" + : +else + enable_libffi=no +fi + +# Check whether --enable-ffcall or --disable-ffcall was given. +if test "${enable_ffcall+set}" = set; then + enableval="$enable_ffcall" + : +else + enable_ffcall=no +fi + + +ac_safe=`echo "ffi.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for ffi.h""... $ac_c" 1>&6 +echo "configure:4396: checking for ffi.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4406: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +enable_libffi=no +fi + + +cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + enable_ffcall=no +fi +rm -f conftest* +for ac_hdr in callback.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4454: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4464: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +enable_ffcall=no +fi +done + + +echo $ac_n "checking "FFI library usage"""... $ac_c" 1>&6 +echo "configure:4493: checking "FFI library usage"" >&5 +WITH_FFI=none +if test $enable_libffi = yes; then + cat >> confdefs.h <<\EOF +#define USE_LIBFFI 1 +EOF + + WITH_FFI=libffi + echo "$ac_t""libffi" 1>&6 +elif test $enable_ffcall = yes; then + cat >> confdefs.h <<\EOF +#define USE_FFCALL 1 +EOF + + WITH_FFI=ffcall + echo "$ac_t""ffcall" 1>&6 +else + echo "$ac_t""none" 1>&6 +fi + + #-------------------------------------------------------------------- # Check recent libxlm for Properytlists, GSXML, GSDoc etc. #-------------------------------------------------------------------- @@ -4478,17 +4546,17 @@ for ac_hdr in libxml/xmlversion.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4482: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:4550: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4560: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4521,7 +4589,7 @@ if test $ac_cv_header_libxml_xmlversion_h = no; then HAVE_LIBXML=0 else cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4601: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4593,17 +4661,17 @@ for ac_hdr in openssl/ssl.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4597: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:4665: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4607: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4675: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4635,15 +4703,15 @@ if test $ac_cv_header_openssl_ssl_h = no; then echo "configure: warning: Could not find openssl headers" 1>&2 else echo $ac_n "checking for CRYPTO_malloc in -lcrypto""... $ac_c" 1>&6 -echo "configure:4639: checking for CRYPTO_malloc in -lcrypto" >&5 -ac_lib_var=`echo crypto'_'CRYPTO_malloc | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "configure:4707: checking for CRYPTO_malloc in -lcrypto" >&5 +ac_lib_var=`echo crypto'_'CRYPTO_malloc | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lcrypto $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4679,15 +4747,15 @@ fi base_libs="$LIBS" LIBS="$LIBS -lcrypto" echo $ac_n "checking for ssl2_clear in -lssl""... $ac_c" 1>&6 -echo "configure:4683: checking for ssl2_clear in -lssl" >&5 -ac_lib_var=`echo ssl'_'ssl2_clear | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "configure:4751: checking for ssl2_clear in -lssl" >&5 +ac_lib_var=`echo ssl'_'ssl2_clear | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lssl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4773,17 +4841,17 @@ for ac_hdr in gmp.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4777: checking for $ac_hdr" >&5 -if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then +echo "configure:4845: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4787: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4811,19 +4879,19 @@ done if test $ac_cv_header_gmp_h = no; then echo "Could not find gmp headers" - echo "Check to make sure you have a recent version of gmp installed" + echo "Check to make sure you have gmp installed" echo "configure: warning: Could not find gmp headers" 1>&2 else echo $ac_n "checking for mpf_abs in -lgmp""... $ac_c" 1>&6 -echo "configure:4819: checking for mpf_abs in -lgmp" >&5 -ac_lib_var=`echo gmp'_'mpf_abs | sed 'y%./+-:%__p__%'` -if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then +echo "configure:4887: checking for mpf_abs in -lgmp" >&5 +ac_lib_var=`echo gmp'_'mpf_abs | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lgmp $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4860,6 +4928,10 @@ fi LIBS="$LIBS -lgmp" HAVE_GMP=1 + else + echo "Could not find gmp library" + echo "Check to make sure you have gmp installed" + echo "configure: warning: Could not find gmp library" 1>&2 fi fi @@ -4982,7 +5054,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.13.1" + echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -5079,6 +5151,7 @@ s%@_GSC_S_LNG_LNG@%$_GSC_S_LNG_LNG%g s%@DYNAMIC_LINKER@%$DYNAMIC_LINKER%g s%@GS_PASS_ARGUMENTS@%$GS_PASS_ARGUMENTS%g s%@GS_FAKE_MAIN@%$GS_FAKE_MAIN%g +s%@WITH_FFI@%$WITH_FFI%g s%@HAVE_LIBXML@%$HAVE_LIBXML%g s%@HAVE_GMP@%$HAVE_GMP%g s%@whole_archive@%$whole_archive%g @@ -5302,7 +5375,7 @@ exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || $SHELL $CONFIG_STATUS || exit 1 +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 if test "$no_recursion" != yes; then @@ -5366,7 +5439,7 @@ if test "$no_recursion" != yes; then # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_sub_srcdir/configure; then - ac_sub_configure="$SHELL $ac_sub_srcdir/configure" + ac_sub_configure=$ac_sub_srcdir/configure elif test -f $ac_sub_srcdir/configure.in; then ac_sub_configure=$ac_configure else @@ -5384,9 +5457,9 @@ if test "$no_recursion" != yes; then ac_sub_cache_file="$ac_dots$cache_file" ;; esac - echo "running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" # The eval makes quoting arguments work. - if eval $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir then : else { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } diff --git a/configure.in b/configure.in index 73cf3f9d8..e384bb01c 100644 --- a/configure.in +++ b/configure.in @@ -736,7 +736,7 @@ fi #-------------------------------------------------------------------- AC_MSG_CHECKING("use of pass-through arguments") AC_ARG_ENABLE(pass-arguments, - [ --enable-pass-arguments User main calls NSProcessInfo initialization],, + [ --enable-pass-arguments Force user main call to NSProcessInfo initialize],, enable_pass_arguments=no) case "$target_os" in @@ -752,7 +752,7 @@ AC_MSG_RESULT($enable_pass_arguments) AC_MSG_CHECKING("use of fake-main definition") AC_ARG_ENABLE(fake-main, - [ --enable-fake-main Force use of redefine of the main function],, + [ --enable-fake-main Force redefine of user main function],, enable_fake_main=no) if test "$enable_pass_arguments" = "no"; then @@ -785,6 +785,39 @@ esac AC_SUBST(GS_FAKE_MAIN) AC_MSG_RESULT($enable_fake_main) +#-------------------------------------------------------------------- +# Check for FFI interface libraries for invocations +#-------------------------------------------------------------------- +AC_ARG_ENABLE(libffi, + [ --enable-libffi Enable use of libffi library],, + enable_libffi=no) +AC_ARG_ENABLE(ffcall, + [ --enable-ffcall Enable use of ffcall library],, + enable_ffcall=no) + +AC_CHECK_HEADER(ffi.h, , enable_libffi=no) + +AC_TRY_CPP([#include "objc/objc-api.h" + #ifndef OBJC_METHOD_LOOKUP_HOOKS + #error + #endif], , enable_ffcall=no) +AC_CHECK_HEADERS(callback.h, , enable_ffcall=no) + +AC_MSG_CHECKING("FFI library usage") +WITH_FFI=none +if test $enable_libffi = yes; then + AC_DEFINE(USE_LIBFFI) + WITH_FFI=libffi + AC_MSG_RESULT(libffi) +elif test $enable_ffcall = yes; then + AC_DEFINE(USE_FFCALL) + WITH_FFI=ffcall + AC_MSG_RESULT(ffcall) +else + AC_MSG_RESULT(none) +fi +AC_SUBST(WITH_FFI) + #-------------------------------------------------------------------- # Check recent libxlm for Properytlists, GSXML, GSDoc etc. #--------------------------------------------------------------------