|
|
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.