|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License." ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: #import <objc/Object.h> ! 26: #import <objc/HashTable.h> ! 27: #import <float.h> ! 28: #import <stdarg.h> ! 29: ! 30: struct foo ! 31: { ! 32: int i; ! 33: char c; ! 34: float f; ! 35: char *s; ! 36: }; ! 37: ! 38: static void foo_display(struct foo *s, int i) ! 39: { ! 40: printf("arg[%d]->i = %d\n", i, s->i); ! 41: printf("arg[%d]->c = '%c'\n", i, s->c); ! 42: printf("arg[%d]->f = %f\n", i, s->f); ! 43: printf("arg[%d]->s = %s\n", i, s->s); ! 44: }; ! 45: ! 46: struct large ! 47: { ! 48: int a[50]; ! 49: }; ! 50: ! 51: @implementation Tool : Object ! 52: ! 53: - large:(struct large)l small:(int)i ! 54: { ! 55: return self; ! 56: } ! 57: ! 58: - varargs:(int)n, ... ! 59: { ! 60: va_list ap; ! 61: int i; ! 62: ! 63: va_start(ap, n); ! 64: for (i = 0; i < n; i++) ! 65: printf("va_arg[%d] = %d ", i, va_arg(ap,int)); ! 66: va_end(ap); ! 67: printf("\n"); ! 68: } ! 69: ! 70: - double:(double)d char:(char)c float:(float)f double:(double)dd ! 71: { ! 72: return self; ! 73: } ! 74: - incrementMe:(int)i ! 75: { ! 76: printf("i = %d\n",i); ! 77: return self; ! 78: } ! 79: ! 80: - pointerToStructFoo:(struct foo *)s ! 81: { ! 82: printf("i = %d c = '%c' f = %f s = %s\n",s->i,s->c,s->f,s->s); ! 83: } ! 84: ! 85: - structFoo:(struct foo)s ! 86: { ! 87: printf("i = %d c = '%c' f = %f s = %s\n",s.i,s.c,s.f,s.s); ! 88: } ! 89: ! 90: - long:(long)l short:(short)a char:(char)c ! 91: { ! 92: return self; ! 93: } ! 94: ! 95: - array:(int [7])ary ! 96: { ! 97: return self; ! 98: } ! 99: ! 100: @end ! 101: ! 102: @implementation Forward : Object ! 103: { ! 104: id destination; ! 105: } ! 106: ! 107: - setDestination:dest ! 108: { ! 109: destination = dest; ! 110: } ! 111: ! 112: static int getTagLen(char *tag) ! 113: { ! 114: int len = 0; ! 115: ! 116: while (*tag++ != _C_STRUCT_E) len++; ! 117: ! 118: return len; ! 119: } ! 120: ! 121: /* ! 122: Purpose: Provide support required when forwarding messages ! 123: to remote objects. -performv::, -methodArgSize:, ! 124: method_getNumberOfArguments(), method_getSizeOfArguments(), ! 125: and method_getArgumentInfo() provide additional support ! 126: for understanding the format of the stack. This level of ! 127: support is currently used exclusively by Workspace and ! 128: is part of the Unpublished API for Remote Objects. ! 129: ! 130: Semantics: This function is responsible for two things: ! 131: (1) obtaining the object that does respond to the selector. ! 132: (2) sending the object the message via "performv::" ! 133: Features: (1) chance to analyze/transform arguments on the stack ! 134: before sending the message. ! 135: (2) chance to perform a post operation after sending ! 136: the message. ! 137: Limitations: (1) cannot forward methods that take a variable number ! 138: of arguments. ! 139: (2) forwarding methods that return values greater than ! 140: `sizeof(id)' are unreliable. ! 141: */ ! 142: ! 143: - forward:(SEL)asel :(marg_list)args ! 144: { ! 145: void *retval; ! 146: Method method; ! 147: int i, nargs; ! 148: ! 149: // analyze argument types of an anonymous (un-known) selector... ! 150: // ...necessary for doing remote objects. ! 151: ! 152: method = class_getInstanceMethod([destination class], asel); ! 153: nargs = method_getNumberOfArguments(method); ! 154: ! 155: for (i = 0; i < nargs; i++) { ! 156: char *type; ! 157: int offset; ! 158: ! 159: method_getArgumentInfo(method, i, &type, &offset); ! 160: ! 161: printf ("arg[%d] (offset = %d, type = '%c')", ! 162: i, offset, type[0]); ! 163: ! 164: switch (type[0]) { ! 165: case _C_ID: ! 166: { ! 167: id obj = marg_getValue(args, offset, id); ! 168: printf(" = %s\n", [obj name]); ! 169: break; ! 170: } ! 171: case _C_SEL: ! 172: { ! 173: SEL sel = marg_getValue(args, offset, SEL); ! 174: printf(" = %s\n", sel_getName(sel)); ! 175: break; ! 176: } ! 177: case _C_CHARPTR: ! 178: { ! 179: char *str = marg_getValue(args, offset, char *); ! 180: printf(" = %s\n", str); ! 181: break; ! 182: } ! 183: case _C_LNG: case _C_INT: ! 184: { ! 185: long longVal = marg_getValue(args, offset, long); ! 186: printf(" = %d\n", longVal); ! 187: ! 188: if (asel == @selector(incrementMe:)) ! 189: marg_setValue(args, offset, long, ++longVal); ! 190: break; ! 191: } ! 192: case _C_SHT: ! 193: { ! 194: short shortVal = marg_getValue(args, offset, short); ! 195: printf(" = %d\n", shortVal); ! 196: break; ! 197: } ! 198: case _C_CHR: ! 199: { ! 200: char charVal = marg_getValue(args, offset, char); ! 201: printf(" = '%c'\n", charVal); ! 202: break; ! 203: } ! 204: case _C_FLT: ! 205: { ! 206: float floatVal = marg_getValue(args, offset, float); ! 207: printf(" = %f\n", floatVal); ! 208: break; ! 209: } ! 210: case _C_DBL: ! 211: { ! 212: double doubleVal = marg_getValue(args, offset, double); ! 213: printf(" = %f\n", doubleVal); ! 214: break; ! 215: } ! 216: case _C_PTR: ! 217: { ! 218: if (type[1] == _C_STRUCT_B) ! 219: { ! 220: if (strncmp(&type[2], "foo", getTagLen(&type[2])) == 0) ! 221: { ! 222: struct foo *s = marg_getValue(args, offset, struct foo *); ! 223: foo_display(s, i); ! 224: } ! 225: } ! 226: break; ! 227: } ! 228: case _C_STRUCT_B: ! 229: { ! 230: if (strncmp(&type[1], "foo", getTagLen(&type[1])) == 0) ! 231: { ! 232: struct foo s = marg_getValue(args, offset, struct foo); ! 233: foo_display(marg_getRef(args, offset, struct foo), i); ! 234: ! 235: s.i++, s.c++, s.f++, s.s = "transformed string"; ! 236: marg_setValue(args, offset, struct foo, s); ! 237: } ! 238: break; ! 239: } ! 240: case _C_ARY_B: ! 241: { ! 242: printf("array type not recognized ('%s')\n", type); ! 243: } ! 244: default: ! 245: printf("type not recognized ('%c')\n", type[0]); ! 246: break; ! 247: } ! 248: } ! 249: retval = [destination performv:asel :args]; ! 250: ! 251: return retval; ! 252: } ! 253: ! 254: @end ! 255: ! 256: ! 257: main() ! 258: { ! 259: id forward = [Forward new]; ! 260: id tool = [Tool new]; ! 261: ! 262: struct foo afoo = {33, 'y', 9.9, "great"}; ! 263: struct large alarge; ! 264: int ary[7]; ! 265: ! 266: [tool varargs:3, 1,2,3]; ! 267: [tool long:77 short:7 char:'z']; ! 268: [tool incrementMe:100]; ! 269: [tool pointerToStructFoo:&afoo]; ! 270: [tool structFoo:afoo]; ! 271: [tool double:4.4 char:'5' float:3.4 double:8.8]; ! 272: [tool large:alarge small:7007]; ! 273: [tool array:ary]; ! 274: ! 275: [forward setDestination:tool]; ! 276: ! 277: [forward varargs:3, 1,2,3]; ! 278: [forward long:77 short:7 char:'z']; ! 279: [forward incrementMe:100]; ! 280: [forward pointerToStructFoo:&afoo]; ! 281: [forward structFoo:afoo]; ! 282: [forward double:4.4 char:'5' float:3.4 double:8.8]; ! 283: [forward large:alarge small:7007]; ! 284: [forward array:ary]; ! 285: printf("\n"); ! 286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.