2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 /***********************************************************************
26 * Parsing of old-style type strings.
27 **********************************************************************/
29 #include "objc-private.h"
31 /***********************************************************************
35 **********************************************************************/
36 static int SubtypeUntil (const char * type,
40 const char * head = type;
45 if (!*type || (!level && (*type == end)))
46 return (int)(type - head);
50 case ']': case '}': case ')': level--; break;
51 case '[': case '{': case '(': level += 1; break;
57 _objc_fatal ("Object: SubtypeUntil: end of type encountered prematurely\n");
62 /***********************************************************************
64 **********************************************************************/
65 static const char * SkipFirstType (const char * type)
71 case 'O': /* bycopy */
76 case 'V': /* oneway */
77 case '^': /* pointers */
82 while ((*type >= '0') && (*type <= '9'))
84 return type + SubtypeUntil (type, ']') + 1;
88 return type + SubtypeUntil (type, '}') + 1;
92 return type + SubtypeUntil (type, ')') + 1;
102 /***********************************************************************
103 * encoding_getNumberOfArguments.
104 **********************************************************************/
105 __private_extern__ unsigned int
106 encoding_getNumberOfArguments(const char *typedesc)
110 // First, skip the return type
111 typedesc = SkipFirstType (typedesc);
113 // Next, skip stack size
114 while ((*typedesc >= '0') && (*typedesc <= '9'))
117 // Now, we have the arguments - count how many
121 // Traverse argument type
122 typedesc = SkipFirstType (typedesc);
124 // Skip GNU runtime's register parameter hint
125 if (*typedesc == '+') typedesc++;
127 // Traverse (possibly negative) argument offset
128 if (*typedesc == '-')
130 while ((*typedesc >= '0') && (*typedesc <= '9'))
133 // Made it past an argument
140 /***********************************************************************
141 * encoding_getSizeOfArguments.
142 **********************************************************************/
143 __private_extern__ unsigned
144 encoding_getSizeOfArguments(const char *typedesc)
147 #if defined(__ppc__) || defined(ppc)
148 unsigned trueBaseOffset;
149 unsigned foundBaseOffset;
152 // Get our starting points
155 // Skip the return type
156 #if defined (__ppc__) || defined(ppc)
157 // Struct returns cause the parameters to be bumped
158 // by a register, so the offset to the receiver is
159 // 4 instead of the normal 0.
160 trueBaseOffset = (*typedesc == '{') ? (unsigned)sizeof(void *) : 0;
162 typedesc = SkipFirstType (typedesc);
164 // Convert ASCII number string to integer
165 while ((*typedesc >= '0') && (*typedesc <= '9'))
166 stack_size = (stack_size * 10) + (*typedesc++ - '0');
167 #if defined (__ppc__) || defined(ppc)
168 // NOTE: This is a temporary measure pending a compiler fix.
169 // Work around PowerPC compiler bug wherein the method argument
170 // string contains an incorrect value for the "stack size."
171 // Generally, the size is reported 4 bytes too small, so we apply
172 // that fudge factor. Unfortunately, there is at least one case
173 // where the error is something other than -4: when the last
174 // parameter is a double, the reported stack is much too high
175 // (about 32 bytes). We do not attempt to detect that case.
176 // The result of returning a too-high value is that objc_msgSendv
177 // can bus error if the destination of the marg_list copying
178 // butts up against excluded memory.
179 // This fix disables itself when it sees a correctly built
180 // type string (i.e. the offset for the Id is correct). This
181 // keeps us out of lockstep with the compiler.
183 // skip the '@' marking the Id field
184 typedesc = SkipFirstType (typedesc);
186 // Skip GNU runtime's register parameter hint
187 if (*typedesc == '+') typedesc++;
189 // pick up the offset for the Id field
191 while ((*typedesc >= '0') && (*typedesc <= '9'))
192 foundBaseOffset = (foundBaseOffset * 10) + (*typedesc++ - '0');
194 // add fudge factor iff the Id field offset was wrong
195 if (foundBaseOffset != trueBaseOffset)
203 /***********************************************************************
204 * encoding_getArgumentInfo.
205 **********************************************************************/
206 __private_extern__ unsigned int
207 encoding_getArgumentInfo(const char *typedesc, int arg,
208 const char **type, int *offset)
212 BOOL offset_is_negative = NO;
214 // First, skip the return type
215 typedesc = SkipFirstType (typedesc);
217 // Next, skip stack size
218 while ((*typedesc >= '0') && (*typedesc <= '9'))
221 // Now, we have the arguments - position typedesc to the appropriate argument
222 while (*typedesc && nargs != arg)
225 // Skip argument type
226 typedesc = SkipFirstType (typedesc);
230 // Skip GNU runtime's register parameter hint
231 if (*typedesc == '+') typedesc++;
233 // Skip negative sign in offset
234 if (*typedesc == '-')
236 offset_is_negative = YES;
240 offset_is_negative = NO;
242 while ((*typedesc >= '0') && (*typedesc <= '9'))
243 self_offset = self_offset * 10 + (*typedesc++ - '0');
244 if (offset_is_negative)
245 self_offset = -(self_offset);
251 // Skip GNU runtime's register parameter hint
252 if (*typedesc == '+') typedesc++;
254 // Skip (possibly negative) argument offset
255 if (*typedesc == '-')
257 while ((*typedesc >= '0') && (*typedesc <= '9'))
269 typedesc = SkipFirstType (typedesc);
278 // Skip GNU register parameter hint
279 if (*typedesc == '+') typedesc++;
281 // Pick up (possibly negative) argument offset
282 if (*typedesc == '-')
284 offset_is_negative = YES;
288 offset_is_negative = NO;
290 while ((*typedesc >= '0') && (*typedesc <= '9'))
291 arg_offset = arg_offset * 10 + (*typedesc++ - '0');
292 if (offset_is_negative)
293 arg_offset = - arg_offset;
295 *offset = arg_offset - self_offset;
310 __private_extern__ void
311 encoding_getReturnType(const char *t, char *dst, size_t dst_len)
318 strncpy(dst, "", dst_len);
322 end = SkipFirstType(t);
324 strncpy(dst, t, MIN(len, dst_len));
325 if (len < dst_len) memset(dst+len, 0, dst_len - len);
328 /***********************************************************************
329 * encoding_copyReturnType. Returns the method's return type string
331 **********************************************************************/
332 __private_extern__ char *
333 encoding_copyReturnType(const char *t)
341 end = SkipFirstType(t);
343 result = malloc(len + 1);
344 strncpy(result, t, len);
350 __private_extern__ void
351 encoding_getArgumentType(const char *t, unsigned int index,
352 char *dst, size_t dst_len)
360 strncpy(dst, "", dst_len);
364 encoding_getArgumentInfo(t, index, &t, &offset);
367 strncpy(dst, "", dst_len);
371 end = SkipFirstType(t);
373 strncpy(dst, t, MIN(len, dst_len));
374 if (len < dst_len) memset(dst+len, 0, dst_len - len);
378 /***********************************************************************
379 * encoding_copyArgumentType. Returns a single argument's type string
380 * on the heap. Argument 0 is `self`; argument 1 is `_cmd`.
381 **********************************************************************/
382 __private_extern__ char *
383 encoding_copyArgumentType(const char *t, unsigned int index)
392 encoding_getArgumentInfo(t, index, &t, &offset);
396 end = SkipFirstType(t);
398 result = malloc(len + 1);
399 strncpy(result, t, len);