123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /*
- * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
- /***********************************************************************
- * objc-typeencoding.m
- * Parsing of old-style type strings.
- **********************************************************************/
- #include "objc-private.h"
- /***********************************************************************
- * SubtypeUntil.
- *
- * Delegation.
- **********************************************************************/
- static int SubtypeUntil (const char * type,
- char end)
- {
- int level = 0;
- const char * head = type;
- //
- while (*type)
- {
- if (!*type || (!level && (*type == end)))
- return (int)(type - head);
- switch (*type)
- {
- case ']': case '}': case ')': level--; break;
- case '[': case '{': case '(': level += 1; break;
- }
- type += 1;
- }
- _objc_fatal ("Object: SubtypeUntil: end of type encountered prematurely\n");
- return 0;
- }
- /***********************************************************************
- * SkipFirstType.
- **********************************************************************/
- static const char * SkipFirstType (const char * type)
- {
- while (1)
- {
- switch (*type++)
- {
- case 'O': /* bycopy */
- case 'n': /* in */
- case 'o': /* out */
- case 'N': /* inout */
- case 'r': /* const */
- case 'V': /* oneway */
- case '^': /* pointers */
- break;
- case '@': /* objects */
- if (type[0] == '?') type++; /* Blocks */
- return type;
- /* arrays */
- case '[':
- while ((*type >= '0') && (*type <= '9'))
- type += 1;
- return type + SubtypeUntil (type, ']') + 1;
- /* structures */
- case '{':
- return type + SubtypeUntil (type, '}') + 1;
- /* unions */
- case '(':
- return type + SubtypeUntil (type, ')') + 1;
- /* basic types */
- default:
- return type;
- }
- }
- }
- /***********************************************************************
- * encoding_getNumberOfArguments.
- **********************************************************************/
- unsigned int
- encoding_getNumberOfArguments(const char *typedesc)
- {
- unsigned nargs;
- // First, skip the return type
- typedesc = SkipFirstType (typedesc);
- // Next, skip stack size
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- typedesc += 1;
- // Now, we have the arguments - count how many
- nargs = 0;
- while (*typedesc)
- {
- // Traverse argument type
- typedesc = SkipFirstType (typedesc);
- // Skip GNU runtime's register parameter hint
- if (*typedesc == '+') typedesc++;
- // Traverse (possibly negative) argument offset
- if (*typedesc == '-')
- typedesc += 1;
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- typedesc += 1;
- // Made it past an argument
- nargs += 1;
- }
- return nargs;
- }
- /***********************************************************************
- * encoding_getSizeOfArguments.
- **********************************************************************/
- unsigned
- encoding_getSizeOfArguments(const char *typedesc)
- {
- unsigned stack_size;
- // Get our starting points
- stack_size = 0;
- // Skip the return type
- typedesc = SkipFirstType (typedesc);
- // Convert ASCII number string to integer
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- stack_size = (stack_size * 10) + (*typedesc++ - '0');
- return stack_size;
- }
- /***********************************************************************
- * encoding_getArgumentInfo.
- **********************************************************************/
- unsigned int
- encoding_getArgumentInfo(const char *typedesc, unsigned int arg,
- const char **type, int *offset)
- {
- unsigned nargs = 0;
- int self_offset = 0;
- bool offset_is_negative = NO;
- // First, skip the return type
- typedesc = SkipFirstType (typedesc);
- // Next, skip stack size
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- typedesc += 1;
- // Now, we have the arguments - position typedesc to the appropriate argument
- while (*typedesc && nargs != arg)
- {
- // Skip argument type
- typedesc = SkipFirstType (typedesc);
- if (nargs == 0)
- {
- // Skip GNU runtime's register parameter hint
- if (*typedesc == '+') typedesc++;
- // Skip negative sign in offset
- if (*typedesc == '-')
- {
- offset_is_negative = YES;
- typedesc += 1;
- }
- else
- offset_is_negative = NO;
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- self_offset = self_offset * 10 + (*typedesc++ - '0');
- if (offset_is_negative)
- self_offset = -(self_offset);
- }
- else
- {
- // Skip GNU runtime's register parameter hint
- if (*typedesc == '+') typedesc++;
- // Skip (possibly negative) argument offset
- if (*typedesc == '-')
- typedesc += 1;
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- typedesc += 1;
- }
- nargs += 1;
- }
- if (*typedesc)
- {
- int arg_offset = 0;
- *type = typedesc;
- typedesc = SkipFirstType (typedesc);
- if (arg == 0)
- {
- *offset = 0;
- }
- else
- {
- // Skip GNU register parameter hint
- if (*typedesc == '+') typedesc++;
- // Pick up (possibly negative) argument offset
- if (*typedesc == '-')
- {
- offset_is_negative = YES;
- typedesc += 1;
- }
- else
- offset_is_negative = NO;
- while ((*typedesc >= '0') && (*typedesc <= '9'))
- arg_offset = arg_offset * 10 + (*typedesc++ - '0');
- if (offset_is_negative)
- arg_offset = - arg_offset;
- *offset = arg_offset - self_offset;
- }
- }
- else
- {
- *type = 0;
- *offset = 0;
- }
- return nargs;
- }
- void
- encoding_getReturnType(const char *t, char *dst, size_t dst_len)
- {
- size_t len;
- const char *end;
- if (!dst) return;
- if (!t) {
- strncpy(dst, "", dst_len);
- return;
- }
- end = SkipFirstType(t);
- len = end - t;
- strncpy(dst, t, MIN(len, dst_len));
- if (len < dst_len) memset(dst+len, 0, dst_len - len);
- }
- /***********************************************************************
- * encoding_copyReturnType. Returns the method's return type string
- * on the heap.
- **********************************************************************/
- char *
- encoding_copyReturnType(const char *t)
- {
- size_t len;
- const char *end;
- char *result;
- if (!t) return NULL;
- end = SkipFirstType(t);
- len = end - t;
- result = (char *)malloc(len + 1);
- strncpy(result, t, len);
- result[len] = '\0';
- return result;
- }
- void
- encoding_getArgumentType(const char *t, unsigned int index,
- char *dst, size_t dst_len)
- {
- size_t len;
- const char *end;
- int offset;
- if (!dst) return;
- if (!t) {
- strncpy(dst, "", dst_len);
- return;
- }
- encoding_getArgumentInfo(t, index, &t, &offset);
- if (!t) {
- strncpy(dst, "", dst_len);
- return;
- }
- end = SkipFirstType(t);
- len = end - t;
- strncpy(dst, t, MIN(len, dst_len));
- if (len < dst_len) memset(dst+len, 0, dst_len - len);
- }
- /***********************************************************************
- * encoding_copyArgumentType. Returns a single argument's type string
- * on the heap. Argument 0 is `self`; argument 1 is `_cmd`.
- **********************************************************************/
- char *
- encoding_copyArgumentType(const char *t, unsigned int index)
- {
- size_t len;
- const char *end;
- char *result;
- int offset;
- if (!t) return NULL;
- encoding_getArgumentInfo(t, index, &t, &offset);
- if (!t) return NULL;
- end = SkipFirstType(t);
- len = end - t;
- result = (char *)malloc(len + 1);
- strncpy(result, t, len);
- result[len] = '\0';
- return result;
- }
|