objc-typeencoding.mm 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
  3. *
  4. * @APPLE_LICENSE_HEADER_START@
  5. *
  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
  11. * file.
  12. *
  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.
  20. *
  21. * @APPLE_LICENSE_HEADER_END@
  22. */
  23. /***********************************************************************
  24. * objc-typeencoding.m
  25. * Parsing of old-style type strings.
  26. **********************************************************************/
  27. #include "objc-private.h"
  28. /***********************************************************************
  29. * SubtypeUntil.
  30. *
  31. * Delegation.
  32. **********************************************************************/
  33. static int SubtypeUntil (const char * type,
  34. char end)
  35. {
  36. int level = 0;
  37. const char * head = type;
  38. //
  39. while (*type)
  40. {
  41. if (!*type || (!level && (*type == end)))
  42. return (int)(type - head);
  43. switch (*type)
  44. {
  45. case ']': case '}': case ')': level--; break;
  46. case '[': case '{': case '(': level += 1; break;
  47. }
  48. type += 1;
  49. }
  50. _objc_fatal ("Object: SubtypeUntil: end of type encountered prematurely\n");
  51. return 0;
  52. }
  53. /***********************************************************************
  54. * SkipFirstType.
  55. **********************************************************************/
  56. static const char * SkipFirstType (const char * type)
  57. {
  58. while (1)
  59. {
  60. switch (*type++)
  61. {
  62. case 'O': /* bycopy */
  63. case 'n': /* in */
  64. case 'o': /* out */
  65. case 'N': /* inout */
  66. case 'r': /* const */
  67. case 'V': /* oneway */
  68. case '^': /* pointers */
  69. break;
  70. case '@': /* objects */
  71. if (type[0] == '?') type++; /* Blocks */
  72. return type;
  73. /* arrays */
  74. case '[':
  75. while ((*type >= '0') && (*type <= '9'))
  76. type += 1;
  77. return type + SubtypeUntil (type, ']') + 1;
  78. /* structures */
  79. case '{':
  80. return type + SubtypeUntil (type, '}') + 1;
  81. /* unions */
  82. case '(':
  83. return type + SubtypeUntil (type, ')') + 1;
  84. /* basic types */
  85. default:
  86. return type;
  87. }
  88. }
  89. }
  90. /***********************************************************************
  91. * encoding_getNumberOfArguments.
  92. **********************************************************************/
  93. unsigned int
  94. encoding_getNumberOfArguments(const char *typedesc)
  95. {
  96. unsigned nargs;
  97. // First, skip the return type
  98. typedesc = SkipFirstType (typedesc);
  99. // Next, skip stack size
  100. while ((*typedesc >= '0') && (*typedesc <= '9'))
  101. typedesc += 1;
  102. // Now, we have the arguments - count how many
  103. nargs = 0;
  104. while (*typedesc)
  105. {
  106. // Traverse argument type
  107. typedesc = SkipFirstType (typedesc);
  108. // Skip GNU runtime's register parameter hint
  109. if (*typedesc == '+') typedesc++;
  110. // Traverse (possibly negative) argument offset
  111. if (*typedesc == '-')
  112. typedesc += 1;
  113. while ((*typedesc >= '0') && (*typedesc <= '9'))
  114. typedesc += 1;
  115. // Made it past an argument
  116. nargs += 1;
  117. }
  118. return nargs;
  119. }
  120. /***********************************************************************
  121. * encoding_getSizeOfArguments.
  122. **********************************************************************/
  123. unsigned
  124. encoding_getSizeOfArguments(const char *typedesc)
  125. {
  126. unsigned stack_size;
  127. // Get our starting points
  128. stack_size = 0;
  129. // Skip the return type
  130. typedesc = SkipFirstType (typedesc);
  131. // Convert ASCII number string to integer
  132. while ((*typedesc >= '0') && (*typedesc <= '9'))
  133. stack_size = (stack_size * 10) + (*typedesc++ - '0');
  134. return stack_size;
  135. }
  136. /***********************************************************************
  137. * encoding_getArgumentInfo.
  138. **********************************************************************/
  139. unsigned int
  140. encoding_getArgumentInfo(const char *typedesc, unsigned int arg,
  141. const char **type, int *offset)
  142. {
  143. unsigned nargs = 0;
  144. int self_offset = 0;
  145. bool offset_is_negative = NO;
  146. // First, skip the return type
  147. typedesc = SkipFirstType (typedesc);
  148. // Next, skip stack size
  149. while ((*typedesc >= '0') && (*typedesc <= '9'))
  150. typedesc += 1;
  151. // Now, we have the arguments - position typedesc to the appropriate argument
  152. while (*typedesc && nargs != arg)
  153. {
  154. // Skip argument type
  155. typedesc = SkipFirstType (typedesc);
  156. if (nargs == 0)
  157. {
  158. // Skip GNU runtime's register parameter hint
  159. if (*typedesc == '+') typedesc++;
  160. // Skip negative sign in offset
  161. if (*typedesc == '-')
  162. {
  163. offset_is_negative = YES;
  164. typedesc += 1;
  165. }
  166. else
  167. offset_is_negative = NO;
  168. while ((*typedesc >= '0') && (*typedesc <= '9'))
  169. self_offset = self_offset * 10 + (*typedesc++ - '0');
  170. if (offset_is_negative)
  171. self_offset = -(self_offset);
  172. }
  173. else
  174. {
  175. // Skip GNU runtime's register parameter hint
  176. if (*typedesc == '+') typedesc++;
  177. // Skip (possibly negative) argument offset
  178. if (*typedesc == '-')
  179. typedesc += 1;
  180. while ((*typedesc >= '0') && (*typedesc <= '9'))
  181. typedesc += 1;
  182. }
  183. nargs += 1;
  184. }
  185. if (*typedesc)
  186. {
  187. int arg_offset = 0;
  188. *type = typedesc;
  189. typedesc = SkipFirstType (typedesc);
  190. if (arg == 0)
  191. {
  192. *offset = 0;
  193. }
  194. else
  195. {
  196. // Skip GNU register parameter hint
  197. if (*typedesc == '+') typedesc++;
  198. // Pick up (possibly negative) argument offset
  199. if (*typedesc == '-')
  200. {
  201. offset_is_negative = YES;
  202. typedesc += 1;
  203. }
  204. else
  205. offset_is_negative = NO;
  206. while ((*typedesc >= '0') && (*typedesc <= '9'))
  207. arg_offset = arg_offset * 10 + (*typedesc++ - '0');
  208. if (offset_is_negative)
  209. arg_offset = - arg_offset;
  210. *offset = arg_offset - self_offset;
  211. }
  212. }
  213. else
  214. {
  215. *type = 0;
  216. *offset = 0;
  217. }
  218. return nargs;
  219. }
  220. void
  221. encoding_getReturnType(const char *t, char *dst, size_t dst_len)
  222. {
  223. size_t len;
  224. const char *end;
  225. if (!dst) return;
  226. if (!t) {
  227. strncpy(dst, "", dst_len);
  228. return;
  229. }
  230. end = SkipFirstType(t);
  231. len = end - t;
  232. strncpy(dst, t, MIN(len, dst_len));
  233. if (len < dst_len) memset(dst+len, 0, dst_len - len);
  234. }
  235. /***********************************************************************
  236. * encoding_copyReturnType. Returns the method's return type string
  237. * on the heap.
  238. **********************************************************************/
  239. char *
  240. encoding_copyReturnType(const char *t)
  241. {
  242. size_t len;
  243. const char *end;
  244. char *result;
  245. if (!t) return NULL;
  246. end = SkipFirstType(t);
  247. len = end - t;
  248. result = (char *)malloc(len + 1);
  249. strncpy(result, t, len);
  250. result[len] = '\0';
  251. return result;
  252. }
  253. void
  254. encoding_getArgumentType(const char *t, unsigned int index,
  255. char *dst, size_t dst_len)
  256. {
  257. size_t len;
  258. const char *end;
  259. int offset;
  260. if (!dst) return;
  261. if (!t) {
  262. strncpy(dst, "", dst_len);
  263. return;
  264. }
  265. encoding_getArgumentInfo(t, index, &t, &offset);
  266. if (!t) {
  267. strncpy(dst, "", dst_len);
  268. return;
  269. }
  270. end = SkipFirstType(t);
  271. len = end - t;
  272. strncpy(dst, t, MIN(len, dst_len));
  273. if (len < dst_len) memset(dst+len, 0, dst_len - len);
  274. }
  275. /***********************************************************************
  276. * encoding_copyArgumentType. Returns a single argument's type string
  277. * on the heap. Argument 0 is `self`; argument 1 is `_cmd`.
  278. **********************************************************************/
  279. char *
  280. encoding_copyArgumentType(const char *t, unsigned int index)
  281. {
  282. size_t len;
  283. const char *end;
  284. char *result;
  285. int offset;
  286. if (!t) return NULL;
  287. encoding_getArgumentInfo(t, index, &t, &offset);
  288. if (!t) return NULL;
  289. end = SkipFirstType(t);
  290. len = end - t;
  291. result = (char *)malloc(len + 1);
  292. strncpy(result, t, len);
  293. result[len] = '\0';
  294. return result;
  295. }