~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/GSFFCallInvocation.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/** Implementation of GSFFCallInvocation for GNUStep
2
2
   Copyright (C) 2000 Free Software Foundation, Inc.
3
 
   
 
3
 
4
4
   Written: Adam Fedor <fedor@gnu.org>
5
5
   Date: Nov 2000
6
 
   
 
6
 
7
7
   This file is part of the GNUstep Base Library.
8
8
 
9
9
   This library is free software; you can redistribute it and/or
10
10
   modify it under the terms of the GNU Library General Public
11
11
   License as published by the Free Software Foundation; either
12
12
   version 2 of the License, or (at your option) any later version.
13
 
   
 
13
 
14
14
   This library is distributed in the hope that it will be useful,
15
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
17
   Library General Public License for more details.
18
 
   
 
18
 
19
19
   You should have received a copy of the GNU Library General Public
20
20
   License along with this library; if not, write to the Free
21
21
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
22
 
   */ 
23
 
#include <Foundation/NSException.h>
24
 
#include <Foundation/NSCoder.h>
25
 
#include <Foundation/NSDistantObject.h>
26
 
#include <base/GSInvocation.h>
 
22
   */
 
23
#include "Foundation/NSException.h"
 
24
#include "Foundation/NSCoder.h"
 
25
#include "Foundation/NSDistantObject.h"
 
26
#include "Foundation/NSDebug.h"
 
27
#include "GSInvocation.h"
27
28
#include <config.h>
28
29
#include <objc/objc-api.h>
29
30
#include <avcall.h>
57
58
  unsigned structSplit;
58
59
} vacallReturnTypeInfo;
59
60
 
60
 
/* 
 
61
/*
61
62
   Create the map table for the forwarding functions
62
63
 */
63
64
#define GSI_MAP_KTYPES GSUNION_PTR
84
85
ReturnTypeHash (vacallReturnTypeInfo *ret_type)
85
86
{
86
87
  return ret_type->type
87
 
    ^ ret_type->structSplit << 4 
88
 
    ^ ret_type->structAlign << 5 
 
88
    ^ ret_type->structSplit << 4
 
89
    ^ ret_type->structAlign << 5
89
90
    ^ ret_type->structSize << 8;
90
91
}
91
92
 
114
115
#define GSI_MAP_RELEASE_VAL(M, X)
115
116
#define GSI_MAP_NOCLEAN 1
116
117
 
117
 
#include <base/GSIMap.h>
 
118
#include "GNUstepBase/GSIMap.h"
118
119
 
119
120
/* This determines the number of precomputed
120
121
   callback data entries.  The list is indexed
134
135
 
135
136
static objc_mutex_t  ff_callback_map_lock = NULL;
136
137
 
137
 
/* Static pre-computed return type info */ 
 
138
/* Static pre-computed return type info */
138
139
 
139
140
static vacallReturnTypeInfo returnTypeInfo [STATIC_CALLBACK_LIST_SIZE];
140
141
 
151
152
{
152
153
  int offset;
153
154
  const char *subtype;
154
 
  
 
155
 
155
156
  if (index == 0)
156
157
    return 0;
157
158
  subtype = type;
172
173
  int i, numtypes;
173
174
  const char *subtype;
174
175
  int  result;
175
 
  
 
176
 
176
177
  subtype = type;
177
178
  while (*subtype != _C_STRUCT_E && *subtype++ != '='); /* skip "<name>=" */
178
179
  numtypes = 0;
187
188
  result = 1;
188
189
  for (i = 0; i < numtypes; i++)
189
190
    {
190
 
      result = result 
191
 
        && (gs_offset(type, i)/sizeof(__avword) 
 
191
      result = result
 
192
        && (gs_offset(type, i)/sizeof(__avword)
192
193
            == (gs_offset(type, i)+objc_sizeof_type(&subtype[i])-1)
193
194
               / sizeof(__avword));
194
195
    }
206
207
 * we work around it.
207
208
 */
208
209
 
209
 
static INLINE Method_t
 
210
static INLINE GSMethod
210
211
gs_method_for_receiver_and_selector (id receiver, SEL sel)
211
212
{
212
213
  if (receiver)
213
214
    {
214
 
      if (object_is_instance (receiver))
215
 
        {
216
 
          return class_get_instance_method (object_get_class
217
 
                                              (receiver), sel);
218
 
        }
219
 
      else if (object_is_class (receiver))
220
 
        {
221
 
          return class_get_class_method (object_get_meta_class
222
 
                                           (receiver), sel);
223
 
        }
 
215
      return GSGetMethod((GSObjCIsInstance(receiver)
 
216
                          ? GSObjCClass(receiver) : (Class)receiver),
 
217
                         sel,
 
218
                         GSObjCIsInstance(receiver),
 
219
                         YES);
224
220
    }
225
221
 
226
222
  return METHOD_NULL;
227
223
}
228
224
 
229
 
        
230
 
/* 
 
225
 
 
226
/*
231
227
 * Selectors are not unique, and not all selectors have
232
228
 * type information.  This method tries to find the
233
229
 * best equivalent selector with type information.
235
231
 * the conversion sel -> name -> sel
236
232
 * is not what we want.  However
237
233
 * I can not see a way to dispose of the
238
 
 * name, except if we can access the 
 
234
 * name, except if we can access the
239
235
 * internal data structures of the runtime.
240
 
 * 
 
236
 *
241
237
 * If we can access the private data structures
242
238
 * we can also check for incompatible
243
239
 * return types between all equivalent selectors.
244
240
 */
245
241
 
246
 
static INLINE SEL 
 
242
static INLINE SEL
247
243
gs_find_best_typed_sel (SEL sel)
248
244
{
249
245
  if (!sel_get_type (sel))
250
246
    {
251
 
      const char *name = sel_get_name (sel);
252
 
      
 
247
      const char *name = GSNameFromSelector(sel);
 
248
 
253
249
      if (name)
254
250
        {
255
251
          SEL tmp_sel = sel_get_any_typed_uid (name);
269
265
 *
270
266
 * In all other cases fallback
271
267
 * to gs_find_best_typed_sel ().
272
 
 */  
 
268
 */
273
269
static INLINE SEL
274
270
gs_find_by_receiver_best_typed_sel (id receiver, SEL sel)
275
271
{
278
274
 
279
275
  if (receiver)
280
276
    {
281
 
      Method_t method;
 
277
      GSMethod method;
282
278
 
283
279
      method = gs_method_for_receiver_and_selector (receiver, sel);
284
280
      /* CHECKME:  Can we assume that:
299
295
  Convert objc selector type to a vacallReturnTypeInfo.
300
296
  Only passes the first part.  Is used for determining
301
297
  the return type for the vacall macros.
302
 
*/ 
303
 
void 
304
 
gs_sel_type_to_callback_type (const char *sel_type, 
 
298
*/
 
299
void
 
300
gs_sel_type_to_callback_type (const char *sel_type,
305
301
  vacallReturnTypeInfo *vatype)
306
302
{
307
303
  switch (*sel_type)
310
306
      case _C_CLASS:
311
307
      case _C_SEL:
312
308
      case _C_PTR:
313
 
      case _C_CHARPTR: 
 
309
      case _C_CHARPTR:
314
310
        vatype->type = __VAvoidp;
315
311
        break;
316
 
      case _C_CHR: 
317
 
        vatype->type = __VAchar; 
 
312
      case _C_CHR:
 
313
        vatype->type = __VAchar;
318
314
        break;
319
315
      case _C_UCHR:
320
 
        vatype->type = __VAuchar; 
 
316
        vatype->type = __VAuchar;
321
317
        break;
322
318
      case _C_SHT:
323
 
        vatype->type = __VAshort; 
 
319
        vatype->type = __VAshort;
324
320
        break;
325
321
      case _C_USHT:
326
 
        vatype->type = __VAushort; 
 
322
        vatype->type = __VAushort;
327
323
        break;
328
324
      case _C_INT:
329
 
        vatype->type = __VAint; 
 
325
        vatype->type = __VAint;
330
326
        break;
331
327
      case _C_UINT:
332
 
        vatype->type = __VAuint; 
 
328
        vatype->type = __VAuint;
333
329
        break;
334
330
      case _C_LNG:
335
 
        vatype->type = __VAlong; 
 
331
        vatype->type = __VAlong;
336
332
        break;
337
333
      case _C_ULNG:
338
 
        vatype->type = __VAulong; 
 
334
        vatype->type = __VAulong;
339
335
        break;
340
336
      case _C_LNG_LNG:
341
 
        vatype->type = __VAlonglong; 
 
337
        vatype->type = __VAlonglong;
342
338
        break;
343
339
      case _C_ULNG_LNG:
344
 
        vatype->type = __VAulonglong; 
 
340
        vatype->type = __VAulonglong;
345
341
        break;
346
342
      case _C_FLT:
347
 
        vatype->type = __VAfloat; 
 
343
        vatype->type = __VAfloat;
348
344
        break;
349
345
      case _C_DBL:
350
 
        vatype->type = __VAdouble; 
 
346
        vatype->type = __VAdouble;
351
347
        break;
352
348
      case _C_STRUCT_B:
353
349
        vatype->structSize = objc_sizeof_type (sel_type);
377
373
  void                  *forwarding_callback;
378
374
 
379
375
  /*
380
 
   * 1. determine return type.
 
376
   * 1. determine return type.  The compiler should have provided us with
 
377
   * a typed selector if possible, if not we have to assume an id return.
381
378
   */
382
 
  sel = gs_find_best_typed_sel (sel);
383
379
  sel_type = sel_get_type (sel);
384
380
 
385
381
  if (!sel_type)
386
382
    {
387
 
      NSLog(@"Invalid selector %s (no type information)", sel_get_name (sel));
388
383
      sel_type = "@";   // Default to id return type
389
384
    }
390
385
 
391
386
  sel_type = objc_skip_type_qualifiers (sel_type);
392
387
  gs_sel_type_to_callback_type (sel_type, &returnInfo);
393
 
  
 
388
 
394
389
  /*
395
390
   * 2. Check if we have already a callback
396
391
   */
404
399
    {
405
400
      // 2.b Or do we have it already in our hash table
406
401
      GSIMapNode node;
407
 
      
 
402
 
408
403
      // Lock
409
404
      objc_mutex_lock (ff_callback_map_lock);
410
405
 
411
406
      node = GSIMapNodeForKey (&ff_callback_map,
412
407
        (GSIMapKey) ((void *) &returnInfo));
413
 
      
 
408
 
414
409
      if (node)
415
410
        {
416
411
          // 2.b.1 YES, we have it in our cache
422
417
          vacallReturnTypeInfo *ret_info;
423
418
 
424
419
          ret_info = objc_malloc (sizeof (vacallReturnTypeInfo));
425
 
          *ret_info = returnInfo; 
426
 
          
 
420
          *ret_info = returnInfo;
 
421
        
427
422
          forwarding_callback
428
423
            = alloc_callback (&GSInvocationCallback, ret_info);
429
 
        
430
 
          GSIMapAddPairNoRetain (&ff_callback_map, 
 
424
 
 
425
          GSIMapAddPairNoRetain (&ff_callback_map,
431
426
            (GSIMapKey) (void *) ret_info,
432
427
            (GSIMapVal) forwarding_callback);
433
428
        }
449
444
      ff_callback[index] = alloc_callback (&GSInvocationCallback,
450
445
        &returnTypeInfo [index]);
451
446
    }
452
 
  
453
 
  GSIMapInitWithZoneAndCapacity (&ff_callback_map, 0, 9);
 
447
 
 
448
  GSIMapInitWithZoneAndCapacity (&ff_callback_map, NSDefaultMallocZone(), 9);
454
449
 
455
450
  __objc_msg_forward = gs_objc_msg_forward;
456
451
}
469
464
 */
470
465
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature
471
466
{
 
467
  if (aSignature == nil)
 
468
    {
 
469
      RELEASE(self);
 
470
      return nil;
 
471
    }
472
472
  _sig = RETAIN(aSignature);
473
473
  _numArgs = [aSignature numberOfArguments];
474
474
  _info = [aSignature methodInfo];
483
483
void
484
484
GSFFCallInvokeWithTargetAndImp(NSInvocation *_inv, id anObject, IMP imp)
485
485
{
486
 
  int                   i;
 
486
  unsigned int          i;
487
487
  av_alist              alist;
488
488
  NSInvocation_t        *inv = (NSInvocation_t*)_inv;
489
489
  void                  *retval = inv->_retval;
512
512
      case _C_CHARPTR:
513
513
        av_start_ptr(alist, imp, char *, retval);
514
514
        break;
515
 
          
 
515
        
516
516
        CASE_TYPE(_C_CHR,  char, av_start_char)
517
517
        CASE_TYPE(_C_UCHR, unsigned char, av_start_uchar)
518
518
        CASE_TYPE(_C_SHT,  short, av_start_short)
542
542
        av_start_void(alist, imp);
543
543
        break;
544
544
      default:
545
 
        NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented", 
 
545
        NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented",
546
546
          inv->_info[0].type);
547
547
        break;
548
548
    }
607
607
              av_ptr(alist, char *, ptr);
608
608
              break;
609
609
            }
610
 
            
 
610
        
611
611
            CASE_TYPE(_C_CHR,  char, av_char)
612
612
            CASE_TYPE(_C_UCHR, unsigned char, av_uchar)
613
613
            CASE_TYPE(_C_SHT,  short, av_short)
620
620
            CASE_TYPE(_C_ULNG_LNG, unsigned long long, av_ulonglong)
621
621
            CASE_TYPE(_C_FLT,  float, av_float)
622
622
            CASE_TYPE(_C_DBL,  double, av_double)
623
 
            
 
623
        
624
624
          case _C_STRUCT_B:
625
625
            _av_struct(alist, size, inv->_info[i+1].align, datum);
626
626
            break;
640
640
  id            old_target;
641
641
  IMP           imp;
642
642
 
 
643
  CLEAR_RETURN_VALUE_IF_OBJECT;
 
644
  _validReturn = NO;
 
645
 
643
646
  /*
644
647
   *    A message to a nil object returns nil.
645
648
   */
646
649
  if (anObject == nil)
647
650
    {
648
651
      memset(_retval, '\0', _info[0].size);     /* Clear return value */
 
652
      if (*_info[0].type != _C_VOID)
 
653
        {
 
654
          _validReturn = YES;
 
655
        }
649
656
      return;
650
657
    }
651
658
 
 
659
 
652
660
  NSAssert(_selector != 0, @"you must set the selector before invoking");
653
661
 
654
662
  /*
667
675
 
668
676
      s.self = _target;
669
677
      if (GSObjCIsInstance(_target))
670
 
        s.class = class_get_super_class(GSObjCClass(_target));
 
678
        s.class = GSObjCSuper(GSObjCClass(_target));
671
679
      else
672
 
        s.class = class_get_super_class((Class)_target);
 
680
        s.class = GSObjCSuper((Class)_target);
673
681
      imp = objc_msg_lookup_super(&s, _selector);
674
682
    }
675
683
  else
676
684
    {
677
 
      imp = method_get_imp(object_is_instance(_target) ?
678
 
        class_get_instance_method(
679
 
          ((struct objc_class*)_target)->class_pointer, _selector)
680
 
        : class_get_class_method(
681
 
          ((struct objc_class*)_target)->class_pointer, _selector));
 
685
      GSMethod method;
 
686
      method = GSGetMethod((GSObjCIsInstance(_target)
 
687
                            ? GSObjCClass(_target)
 
688
                            : _target),
 
689
                           _selector,
 
690
                           GSObjCIsInstance(_target),
 
691
                           YES);
 
692
      imp = method_get_imp(method);
682
693
      /*
683
694
       * If fast lookup failed, we may be forwarding or something ...
684
695
       */
690
701
 
691
702
  [self setTarget: old_target];
692
703
  RELEASE(old_target);
693
 
  
 
704
 
694
705
  GSFFCallInvokeWithTargetAndImp(self, anObject, imp);
 
706
 
 
707
  RETAIN_RETURN_VALUE;
695
708
  _validReturn = YES;
696
709
}
697
710
 
702
715
@end
703
716
 
704
717
/*
 
718
 * Return YES if the selector contains protocol qualifiers.
 
719
 */
 
720
static BOOL
 
721
gs_protocol_selector(const char *types)
 
722
{
 
723
  if (types == 0)
 
724
    {
 
725
      return NO;
 
726
    }
 
727
  while (*types != '\0')
 
728
    {
 
729
      if (*types == '-')
 
730
        {
 
731
          types++;
 
732
        }
 
733
      if (*types == '+' || isdigit(*types))
 
734
        {
 
735
          types = objc_skip_offset(types);
 
736
        }
 
737
      while (*types == _C_CONST || *types == _C_GCINVISIBLE)
 
738
        {
 
739
          types++;
 
740
        }
 
741
      if (*types == _C_IN
 
742
        || *types == _C_INOUT
 
743
        || *types == _C_OUT
 
744
        || *types == _C_BYCOPY
 
745
        || *types == _C_BYREF
 
746
        || *types == _C_ONEWAY)
 
747
        {
 
748
          return YES;
 
749
        }
 
750
      if (*types == '\0')
 
751
        {
 
752
          return NO;
 
753
        }
 
754
      types = objc_skip_typespec(types);
 
755
    }
 
756
  return NO;
 
757
}
 
758
 
 
759
/*
705
760
 * Wim Oudshoorn (6 aug 2001)
706
761
 *
707
762
 * The function that performs the actual forwarding
711
766
 *
712
767
 * TODO:
713
768
 * Add a check that the return type the selector
714
 
 * expects matches the the `callback_data' 
 
769
 * expects matches the the `callback_data'
715
770
 * information.
716
771
 */
717
772
 
718
 
void 
 
773
void
719
774
GSInvocationCallback (void *callback_data, va_alist args)
720
775
{
721
776
  id                    obj;
727
782
  NSArgumentInfo        *info;
728
783
  GSFFCallInvocation    *invocation;
729
784
  NSMethodSignature     *sig;
730
 
  Method_t               fwdInvMethod;
731
 
  
732
 
    
 
785
  GSMethod               fwdInvMethod;
 
786
 
733
787
  typeinfo = (vacallReturnTypeInfo *) callback_data;
734
 
    
 
788
 
735
789
  if (typeinfo->type != __VAstruct)
736
790
    {
737
791
      __va_start (args, typeinfo->type);
738
792
    }
739
793
  else
740
794
    {
741
 
      _va_start_struct (args, typeinfo->structSize, 
 
795
      _va_start_struct (args, typeinfo->structSize,
742
796
        typeinfo->structAlign, typeinfo->structSplit);
743
797
    }
744
798
 
747
801
 
748
802
  fwdInvMethod = gs_method_for_receiver_and_selector
749
803
    (obj, @selector (forwardInvocation:));
750
 
  
 
804
 
751
805
  if (!fwdInvMethod)
752
806
    {
753
 
      NSCAssert2 (0, @"GSFFCallInvocation: Class '%s' does not respond"
754
 
                  @" to forwardInvocation: for '%s'",
755
 
                  object_get_class_name (obj), sel_get_name(selector));
 
807
      [NSException raise: NSInvalidArgumentException
 
808
                   format: @"GSFFCallInvocation: Class '%s(%s)'"
 
809
                           @" does not respond"
 
810
                           @" to forwardInvocation: for '%s'",
 
811
                   GSClassNameFromObject(obj),
 
812
                   GSObjCIsInstance(obj) ? "instance" : "class",
 
813
                   selector ? GSNameFromSelector(selector) : "(null)"];
756
814
    }
757
 
       
758
 
  selector = gs_find_by_receiver_best_typed_sel (obj, selector);
 
815
 
759
816
  sig = nil;
760
 
  
761
 
  if (sel_get_type (selector))
 
817
  if (gs_protocol_selector(sel_get_type(selector)) == YES)
762
818
    {
 
819
      /*
 
820
       * We already have protocol information locally, so we don't need
 
821
       * to get it from the remote system.
 
822
       */
763
823
      sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
764
824
    }
765
 
 
766
 
  if (!sig)
 
825
  if (sig == nil)
767
826
    {
768
827
      sig = [obj methodSignatureForSelector: selector];
769
828
    }
770
 
  
771
 
  NSCAssert1(sig, @"No signature for selector %@", 
772
 
    NSStringFromSelector(selector));
773
 
    
 
829
 
 
830
  /*
 
831
   * If we got a method signature from the receiving object,
 
832
   * ensure that the selector we are using matches the types.
 
833
   */
 
834
  if (sig != nil)
 
835
    {
 
836
      const char        *receiverTypes = [sig methodType];
 
837
      const char        *runtimeTypes = sel_get_type (selector);
 
838
 
 
839
      if (runtimeTypes == 0 || strcmp(receiverTypes, runtimeTypes) != 0)
 
840
        {
 
841
          const char    *runtimeName = GSNameFromSelector(selector);
 
842
 
 
843
          selector = sel_get_typed_uid (runtimeName, receiverTypes);
 
844
          if (selector == 0)
 
845
            {
 
846
              selector = sel_register_typed_name (runtimeName, receiverTypes);
 
847
            }
 
848
          if (runtimeTypes != 0)
 
849
            {
 
850
              /*
 
851
               * FIXME ... if we have a typed selector, it probably came
 
852
               * from the compiler, and the types of the proxied method
 
853
               * MUST match those that the compiler supplied on the stack
 
854
               * and the type it expects to retrieve from the stack.
 
855
               * We should therefore discriminate between signatures where
 
856
               * type qalifiers and sizes differ, and those where the
 
857
               * actual types differ.
 
858
               */
 
859
              NSDebugFLog(@"Changed type signature '%s' to '%s' for '%s'",
 
860
                runtimeTypes, receiverTypes, runtimeName);
 
861
            }
 
862
        }
 
863
    }
 
864
 
 
865
  if (sig == nil)
 
866
    {
 
867
      selector = gs_find_best_typed_sel (selector);
 
868
 
 
869
      if (sel_get_type (selector) != 0)
 
870
    {
 
871
      sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
 
872
    }
 
873
    }
 
874
 
 
875
  if (sig == nil)
 
876
    {
 
877
      [NSException raise: NSInvalidArgumentException
 
878
                   format: @"Can not determine type information for %s[%s %s]",
 
879
                   GSObjCIsInstance(obj) ? "-" : "+",
 
880
         GSClassNameFromObject(obj),
 
881
         selector ? GSNameFromSelector(selector) : "(null)"];
 
882
    }
 
883
 
774
884
  invocation = [[GSFFCallInvocation alloc] initWithMethodSignature: sig];
775
885
  AUTORELEASE(invocation);
776
886
  [invocation setTarget: obj];
778
888
 
779
889
  /* Set the rest of the arguments */
780
890
  num_args = [sig numberOfArguments];
781
 
  info = [sig methodInfo]; 
 
891
  info = [sig methodInfo];
782
892
  for (i = 2; i < num_args; i++)
783
893
    {
784
894
      const char        *type = info[i+1].type;
825
935
              [invocation setArgument: &ptr atIndex: i];
826
936
              break;
827
937
            }
828
 
            
 
938
        
829
939
          CASE_TYPE(_C_CHR,  char, va_arg_char)
830
940
          CASE_TYPE(_C_UCHR, unsigned char, va_arg_uchar)
831
941
          CASE_TYPE(_C_SHT,  short, va_arg_short)
838
948
          CASE_TYPE(_C_ULNG_LNG, unsigned long long, va_arg_ulonglong)
839
949
          CASE_TYPE(_C_FLT,  float, va_arg_float)
840
950
          CASE_TYPE(_C_DBL,  double, va_arg_double)
841
 
            
 
951
        
842
952
          case _C_STRUCT_B:
843
953
            {
844
954
              /* Here we actually get a ptr to the struct */
852
962
            break;
853
963
        }
854
964
    }
855
 
  
 
965
 
856
966
  /*
857
967
   * Now do it.
858
968
   * The next line is equivalent to
859
969
   *
860
970
   *   [obj forwardInvocation: invocation];
861
971
   *
862
 
   * but we have already the Method_t for forwardInvocation
 
972
   * but we have already the GSMethod for forwardInvocation
863
973
   * so the line below is somewhat faster. */
864
974
  fwdInvMethod->method_imp (obj, fwdInvMethod->method_name, invocation);
865
975
 
866
 
  /* Return the proper type */  
 
976
  /* Return the proper type */
867
977
  retval = [invocation returnFrame: NULL];
868
978
 
869
979
#undef CASE_TYPE
881
991
      case _C_CHARPTR:
882
992
        va_return_ptr(args, void *, *(void **)retval);
883
993
        break;
884
 
          
 
994
        
885
995
      CASE_TYPE(_C_CHR,  char, va_return_char)
886
996
      CASE_TYPE(_C_UCHR, unsigned char, va_return_uchar)
887
997
      CASE_TYPE(_C_SHT,  short, va_return_short)
899
1009
        _va_return_struct(args, info[0].size, info[0].align, retval);
900
1010
        break;
901
1011
      case _C_VOID:
902
 
        va_return_void(args);
 
1012
        /* FIXME ... evil hack ... where the compiler did not know
 
1013
         * selector types, if may have had to assume a method returning
 
1014
         * an id, but the actual method may have returned void ...
 
1015
         * we check for that case here, and use the fact that in the case
 
1016
         * of a void return value, passing retval back as a voipd will
 
1017
         * look like the method actually returned nil.
 
1018
         */
 
1019
        if (typeinfo->type == __VAvoidp)
 
1020
          {
 
1021
            va_return_ptr(args, void *, *(void **)retval);
 
1022
          }
 
1023
        else
 
1024
          {
 
1025
            va_return_void(args);
 
1026
          }
903
1027
        break;
904
1028
      default:
905
1029
        NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented",
914
1038
   to send over the wire */
915
1039
- (BOOL) encodeWithDistantCoder: (NSCoder*)coder passPointers: (BOOL)passp
916
1040
{
917
 
  int           i;
 
1041
  unsigned int  i;
918
1042
  BOOL          out_parameters = NO;
919
1043
  const char    *type = [_sig methodType];
920
1044
 
925
1049
      int               flags = _info[i+1].qual;
926
1050
      const char        *type = _info[i+1].type;
927
1051
      void              *datum;
928
 
      
 
1052
 
929
1053
      if (i == 0)
930
1054
        {
931
1055
          datum = &_target;
949
1073
 
950
1074
      switch (*type)
951
1075
        {
952
 
          case _C_ID: 
 
1076
          case _C_ID:
953
1077
            if (flags & _F_BYCOPY)
954
1078
              {
955
1079
                [coder encodeBycopyObject: *(id*)datum];
1001
1125
              {
1002
1126
                out_parameters = YES;
1003
1127
              }
1004
 
            if (passp) 
 
1128
            if (passp)
1005
1129
              {
1006
1130
                if ((flags & _F_IN) || !(flags & _F_OUT))
1007
1131
                  {
1008
1132
                    [coder encodeValueOfObjCType: type at: datum];
1009
1133
                  }
1010
1134
              }
1011
 
            else 
 
1135
            else
1012
1136
              {
1013
1137
                /*
1014
1138
                 * Handle an argument that is a pointer to a non-char.  But
1057
1181
  return out_parameters;
1058
1182
}
1059
1183
 
 
1184
@end