2005-02-22 11:22:44 +00:00
|
|
|
|
/** Implementation of functions for dissecting/making method calls
|
1998-11-02 10:55:53 +00:00
|
|
|
|
Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1996-03-30 01:29:07 +00:00
|
|
|
|
Created: Oct 1994
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1994-11-04 16:29:24 +00:00
|
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1994-11-04 16:29:24 +00:00
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1994-11-04 16:29:24 +00:00
|
|
|
|
License along with this library; if not, write to the Free
|
2006-10-20 10:56:27 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
Boston, MA 02111 USA.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
|
|
|
|
/* These functions can be used for dissecting and making method calls
|
|
|
|
|
for many different situations. They are used for distributed
|
|
|
|
|
objects; they could also be used to make interfaces between
|
1996-03-30 01:29:07 +00:00
|
|
|
|
Objective C and Scheme, Perl, Tcl, or other languages.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
2001-06-06 11:01:25 +00:00
|
|
|
|
/* Remove `inline' nested functions if they crash your compiler */
|
2005-02-22 11:22:44 +00:00
|
|
|
|
//#define inline
|
2001-06-05 11:52:27 +00:00
|
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "config.h"
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/preface.h"
|
2007-12-21 13:46:50 +00:00
|
|
|
|
#ifdef HAVE_ALLOCA_H
|
|
|
|
|
#include <alloca.h>
|
|
|
|
|
#endif
|
2001-05-04 21:14:06 +00:00
|
|
|
|
#include <stdio.h>
|
1994-11-04 16:29:24 +00:00
|
|
|
|
#include <stdlib.h>
|
2001-05-04 21:14:06 +00:00
|
|
|
|
#include <ctype.h>
|
2007-12-21 13:46:50 +00:00
|
|
|
|
#include <mframe.h>
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
|
|
|
|
/* Deal with strrchr: */
|
2002-05-08 05:43:15 +00:00
|
|
|
|
#if STDC_HEADERS || defined(HAVE_STRING_H)
|
1994-11-04 16:29:24 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
|
2002-05-08 05:43:15 +00:00
|
|
|
|
#if !STDC_HEADERS && defined(HAVE_MEMORY_H)
|
1994-11-04 16:29:24 +00:00
|
|
|
|
#include <memory.h>
|
|
|
|
|
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
|
|
|
|
|
#define index strchr
|
|
|
|
|
#define rindex strrchr
|
|
|
|
|
#define bcopy(s, d, n) memcpy ((d), (s), (n))
|
|
|
|
|
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
|
|
|
|
|
#define bzero(s, n) memset ((s), 0, (n))
|
|
|
|
|
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
|
|
|
|
#include <strings.h>
|
|
|
|
|
/* memory.h and strings.h conflict on some systems. */
|
|
|
|
|
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
|
|
|
|
|
2007-12-21 13:46:50 +00:00
|
|
|
|
#include "Foundation/NSObjCRuntime.h"
|
|
|
|
|
#include "Foundation/NSData.h"
|
|
|
|
|
#include "Foundation/NSException.h"
|
|
|
|
|
#include "Foundation/NSDebug.h"
|
|
|
|
|
|
1999-06-24 19:57:52 +00:00
|
|
|
|
|
1996-03-30 01:29:07 +00:00
|
|
|
|
|
1994-11-04 16:29:24 +00:00
|
|
|
|
/* For encoding and decoding the method arguments, we have to know where
|
|
|
|
|
to find things in the "argframe" as returned by __builtin_apply_args.
|
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
|
For some situations this is obvious just from the selector type
|
1994-11-04 16:29:24 +00:00
|
|
|
|
encoding, but structures passed by value cause a problem because some
|
|
|
|
|
architectures actually pass these by reference, i.e. use the
|
|
|
|
|
structure-value-address mentioned in the gcc/config/_/_.h files.
|
|
|
|
|
|
|
|
|
|
These differences are not encoded in the selector types.
|
|
|
|
|
|
|
|
|
|
Below is my current guess for which architectures do this.
|
|
|
|
|
xxx I really should do this properly by looking at the gcc config values.
|
|
|
|
|
|
|
|
|
|
I've also been told that some architectures may pass structures with
|
|
|
|
|
sizef(structure) > sizeof(void*) by reference, but pass smaller ones by
|
|
|
|
|
value. The code doesn't currently handle that case.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
1998-08-13 20:45:32 +00:00
|
|
|
|
char*
|
|
|
|
|
mframe_build_signature(const char *typePtr, int *size, int *narg, char *buf)
|
|
|
|
|
{
|
1998-11-02 10:55:53 +00:00
|
|
|
|
MFRAME_ARGS cum;
|
|
|
|
|
BOOL doMalloc = NO;
|
|
|
|
|
const char *types;
|
|
|
|
|
char *start;
|
|
|
|
|
char *dest;
|
|
|
|
|
int total = 0;
|
|
|
|
|
int count = 0;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* If we have not been given a buffer - allocate space on the stack for
|
|
|
|
|
* the largest concievable type encoding.
|
|
|
|
|
*/
|
|
|
|
|
if (buf == 0)
|
|
|
|
|
{
|
|
|
|
|
doMalloc = YES;
|
|
|
|
|
buf = alloca((strlen(typePtr)+1)*16);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copy the return type info (including qualifiers) into the buffer.
|
|
|
|
|
*/
|
|
|
|
|
types = objc_skip_typespec(typePtr);
|
|
|
|
|
strncpy(buf, typePtr, types - typePtr);
|
2005-02-22 11:22:44 +00:00
|
|
|
|
buf[types-typePtr] = '\0';
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Point to the return type, initialise size of stack args, and skip
|
|
|
|
|
* to the first argument.
|
|
|
|
|
*/
|
|
|
|
|
types = objc_skip_type_qualifiers(typePtr);
|
|
|
|
|
MFRAME_INIT_ARGS(cum, types);
|
|
|
|
|
types = objc_skip_typespec(types);
|
|
|
|
|
if (*types == '+')
|
|
|
|
|
{
|
|
|
|
|
types++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
2000-04-14 10:38:22 +00:00
|
|
|
|
if (*types == '-')
|
|
|
|
|
{
|
|
|
|
|
types++;
|
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
while (isdigit(*types))
|
|
|
|
|
{
|
|
|
|
|
types++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Where to start putting encoding information - leave enough room for
|
|
|
|
|
* the size of the stack args to be stored after the return type.
|
|
|
|
|
*/
|
|
|
|
|
start = &buf[strlen(buf)+10];
|
|
|
|
|
dest = start;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Now step through all the arguments - copy any type qualifiers, but
|
|
|
|
|
* let the macro write all the other info into the buffer.
|
|
|
|
|
*/
|
|
|
|
|
while (types && *types)
|
|
|
|
|
{
|
|
|
|
|
const char *qual = types;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are any type qualifiers - copy the through to the
|
|
|
|
|
* destination.
|
|
|
|
|
*/
|
|
|
|
|
types = objc_skip_type_qualifiers(types);
|
|
|
|
|
while (qual < types)
|
|
|
|
|
{
|
|
|
|
|
*dest++ = *qual++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
MFRAME_ARG_ENCODING(cum, types, total, dest);
|
|
|
|
|
count++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
*dest = '\0';
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Write the total size of the stack arguments after the return type,
|
|
|
|
|
* then copy the remaining type information to fill the gap.
|
|
|
|
|
*/
|
|
|
|
|
sprintf(&buf[strlen(buf)], "%d", total);
|
|
|
|
|
dest = &buf[strlen(buf)];
|
|
|
|
|
while (*start)
|
|
|
|
|
{
|
|
|
|
|
*dest++ = *start++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
*dest = '\0';
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* If we have written into a local buffer - we need to allocate memory
|
|
|
|
|
* in which to return our result.
|
|
|
|
|
*/
|
|
|
|
|
if (doMalloc)
|
|
|
|
|
{
|
1999-09-28 11:10:34 +00:00
|
|
|
|
char *tmp = NSZoneMalloc(NSDefaultMallocZone(), dest - buf + 1);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
strcpy(tmp, buf);
|
|
|
|
|
buf = tmp;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* If the caller wants to know the total size of the stack and/or the
|
|
|
|
|
* number of arguments, return them in the appropriate variables.
|
|
|
|
|
*/
|
|
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
*size = total;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (narg)
|
|
|
|
|
{
|
|
|
|
|
*narg = count;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
return buf;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
1996-03-30 01:29:07 +00:00
|
|
|
|
|
2008-02-22 12:59:30 +00:00
|
|
|
|
/* Step through method encoding information extracting details.
|
|
|
|
|
* If outTypes is non-nul then we copy the argument type into
|
|
|
|
|
* the buffer as a nul terminated string and use the values in
|
|
|
|
|
* this buffer as the types in info, rather than pointers to
|
|
|
|
|
* positions in typePtr
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
|
|
|
|
const char *
|
2008-02-22 12:59:30 +00:00
|
|
|
|
mframe_next_arg(const char *typePtr, NSArgumentInfo *info, char *outTypes)
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
1998-11-02 10:55:53 +00:00
|
|
|
|
NSArgumentInfo local;
|
|
|
|
|
BOOL flag;
|
2002-11-28 11:48:35 +00:00
|
|
|
|
BOOL negative = NO;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (info == 0)
|
|
|
|
|
{
|
|
|
|
|
info = &local;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Skip past any type qualifiers - if the caller wants them, return them.
|
|
|
|
|
*/
|
|
|
|
|
flag = YES;
|
|
|
|
|
info->qual = 0;
|
|
|
|
|
while (flag)
|
|
|
|
|
{
|
|
|
|
|
switch (*typePtr)
|
|
|
|
|
{
|
|
|
|
|
case _C_CONST: info->qual |= _F_CONST; break;
|
|
|
|
|
case _C_IN: info->qual |= _F_IN; break;
|
|
|
|
|
case _C_INOUT: info->qual |= _F_INOUT; break;
|
|
|
|
|
case _C_OUT: info->qual |= _F_OUT; break;
|
|
|
|
|
case _C_BYCOPY: info->qual |= _F_BYCOPY; break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
#ifdef _C_BYREF
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_BYREF: info->qual |= _F_BYREF; break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
#endif
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_ONEWAY: info->qual |= _F_ONEWAY; break;
|
1999-09-29 14:13:52 +00:00
|
|
|
|
#ifdef _C_GCINVISIBLE
|
|
|
|
|
case _C_GCINVISIBLE: info->qual |= _F_GCINVISIBLE; break;
|
|
|
|
|
#endif
|
1998-11-02 10:55:53 +00:00
|
|
|
|
default: flag = NO;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (flag)
|
|
|
|
|
{
|
|
|
|
|
typePtr++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
info->type = typePtr;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Scan for size and alignment information.
|
|
|
|
|
*/
|
|
|
|
|
switch (*typePtr++)
|
|
|
|
|
{
|
|
|
|
|
case _C_ID:
|
|
|
|
|
info->size = sizeof(id);
|
|
|
|
|
info->align = __alignof__(id);
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_CLASS:
|
|
|
|
|
info->size = sizeof(Class);
|
|
|
|
|
info->align = __alignof__(Class);
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_SEL:
|
|
|
|
|
info->size = sizeof(SEL);
|
|
|
|
|
info->align = __alignof__(SEL);
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_CHR:
|
|
|
|
|
info->size = sizeof(char);
|
|
|
|
|
info->align = __alignof__(char);
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_UCHR:
|
|
|
|
|
info->size = sizeof(unsigned char);
|
|
|
|
|
info->align = __alignof__(unsigned char);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_SHT:
|
|
|
|
|
info->size = sizeof(short);
|
|
|
|
|
info->align = __alignof__(short);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_USHT:
|
|
|
|
|
info->size = sizeof(unsigned short);
|
|
|
|
|
info->align = __alignof__(unsigned short);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_INT:
|
|
|
|
|
info->size = sizeof(int);
|
|
|
|
|
info->align = __alignof__(int);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_UINT:
|
|
|
|
|
info->size = sizeof(unsigned int);
|
|
|
|
|
info->align = __alignof__(unsigned int);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_LNG:
|
|
|
|
|
info->size = sizeof(long);
|
|
|
|
|
info->align = __alignof__(long);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_ULNG:
|
|
|
|
|
info->size = sizeof(unsigned long);
|
|
|
|
|
info->align = __alignof__(unsigned long);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
|
info->size = sizeof(long long);
|
|
|
|
|
info->align = __alignof__(long long);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
|
info->size = sizeof(unsigned long long);
|
|
|
|
|
info->align = __alignof__(unsigned long long);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_FLT:
|
|
|
|
|
info->size = sizeof(float);
|
|
|
|
|
info->align = __alignof__(float);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_DBL:
|
|
|
|
|
info->size = sizeof(double);
|
|
|
|
|
info->align = __alignof__(double);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_PTR:
|
|
|
|
|
info->size = sizeof(char*);
|
|
|
|
|
info->align = __alignof__(char*);
|
|
|
|
|
if (*typePtr == '?')
|
|
|
|
|
{
|
|
|
|
|
typePtr++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-11-28 11:48:35 +00:00
|
|
|
|
typePtr = objc_skip_typespec(typePtr);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_ATOM:
|
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
info->size = sizeof(char*);
|
|
|
|
|
info->align = __alignof__(char*);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
int length = atoi(typePtr);
|
|
|
|
|
|
|
|
|
|
while (isdigit(*typePtr))
|
|
|
|
|
{
|
|
|
|
|
typePtr++;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
2008-02-22 12:59:30 +00:00
|
|
|
|
typePtr = mframe_next_arg(typePtr, &local, 0);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
info->size = length * ROUND(local.size, local.align);
|
|
|
|
|
info->align = local.align;
|
|
|
|
|
typePtr++; /* Skip end-of-array */
|
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int acc_size = 0;
|
|
|
|
|
unsigned int def_align = objc_alignof_type(typePtr-1);
|
|
|
|
|
unsigned int acc_align = def_align;
|
2003-06-02 06:03:04 +00:00
|
|
|
|
const char *ptr = typePtr;
|
1998-11-02 10:55:53 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Skip "<name>=" stuff.
|
|
|
|
|
*/
|
2003-06-02 06:03:04 +00:00
|
|
|
|
while (*ptr != _C_STRUCT_E && *ptr != '=') ptr++;
|
|
|
|
|
if (*ptr == '=') typePtr = ptr;
|
|
|
|
|
typePtr++;
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
|
|
|
|
* Base structure alignment on first element.
|
|
|
|
|
*/
|
|
|
|
|
if (*typePtr != _C_STRUCT_E)
|
|
|
|
|
{
|
2008-02-22 12:59:30 +00:00
|
|
|
|
typePtr = mframe_next_arg(typePtr, &local, 0);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (typePtr == 0)
|
|
|
|
|
{
|
|
|
|
|
return 0; /* error */
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
acc_size = ROUND(acc_size, local.align);
|
|
|
|
|
acc_size += local.size;
|
2002-11-27 17:31:38 +00:00
|
|
|
|
acc_align = MAX(local.align, def_align);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
}
|
|
|
|
|
/*
|
2006-01-10 18:01:15 +00:00
|
|
|
|
* Continue accumulating structure size
|
|
|
|
|
* and adjust alignment if necessary
|
1998-11-02 10:55:53 +00:00
|
|
|
|
*/
|
|
|
|
|
while (*typePtr != _C_STRUCT_E)
|
|
|
|
|
{
|
2008-02-22 12:59:30 +00:00
|
|
|
|
typePtr = mframe_next_arg(typePtr, &local, 0);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (typePtr == 0)
|
|
|
|
|
{
|
|
|
|
|
return 0; /* error */
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
acc_size = ROUND(acc_size, local.align);
|
|
|
|
|
acc_size += local.size;
|
2006-01-10 18:01:15 +00:00
|
|
|
|
acc_align = MAX(local.align, acc_align);
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Size must be a multiple of alignment
|
|
|
|
|
*/
|
|
|
|
|
if (acc_size % acc_align != 0)
|
|
|
|
|
{
|
|
|
|
|
acc_size += acc_align - acc_size % acc_align;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
info->size = acc_size;
|
|
|
|
|
info->align = acc_align;
|
|
|
|
|
typePtr++; /* Skip end-of-struct */
|
|
|
|
|
}
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_UNION_B:
|
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int max_size = 0;
|
|
|
|
|
unsigned int max_align = 0;
|
1998-11-02 10:55:53 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Skip "<name>=" stuff.
|
|
|
|
|
*/
|
|
|
|
|
while (*typePtr != _C_UNION_E)
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (*typePtr++ == '=')
|
|
|
|
|
{
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
}
|
|
|
|
|
while (*typePtr != _C_UNION_E)
|
|
|
|
|
{
|
2008-02-22 12:59:30 +00:00
|
|
|
|
typePtr = mframe_next_arg(typePtr, &local, 0);
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (typePtr == 0)
|
|
|
|
|
{
|
|
|
|
|
return 0; /* error */
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
max_size = MAX(max_size, local.size);
|
|
|
|
|
max_align = MAX(max_align, local.align);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-11-02 10:55:53 +00:00
|
|
|
|
info->size = max_size;
|
|
|
|
|
info->align = max_align;
|
|
|
|
|
typePtr++; /* Skip end-of-union */
|
|
|
|
|
}
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
case _C_VOID:
|
|
|
|
|
info->size = 0;
|
|
|
|
|
info->align = __alignof__(char*);
|
|
|
|
|
break;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
default:
|
1998-08-13 20:45:32 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
if (typePtr == 0)
|
|
|
|
|
{ /* Error condition. */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-22 12:59:30 +00:00
|
|
|
|
/* Copy tye type information into the buffer if provided.
|
|
|
|
|
*/
|
|
|
|
|
if (outTypes != 0)
|
|
|
|
|
{
|
|
|
|
|
unsigned len = typePtr - info->type;
|
|
|
|
|
|
|
|
|
|
strncpy(outTypes, info->type, len);
|
|
|
|
|
outTypes[len] = '\0';
|
|
|
|
|
info->type = outTypes;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
/*
|
2002-11-28 11:48:35 +00:00
|
|
|
|
* May tell the caller if the item is stored in a register.
|
1998-11-02 10:55:53 +00:00
|
|
|
|
*/
|
2002-11-28 11:48:35 +00:00
|
|
|
|
if (*typePtr == '+')
|
1998-11-02 10:55:53 +00:00
|
|
|
|
{
|
2002-11-28 11:48:35 +00:00
|
|
|
|
typePtr++;
|
|
|
|
|
info->isReg = YES;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info->isReg = NO;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Cope with negative offsets.
|
|
|
|
|
*/
|
|
|
|
|
if (*typePtr == '-')
|
|
|
|
|
{
|
|
|
|
|
typePtr++;
|
|
|
|
|
negative = YES;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* May tell the caller what the stack/register offset is for
|
|
|
|
|
* this argument.
|
|
|
|
|
*/
|
|
|
|
|
info->offset = 0;
|
|
|
|
|
while (isdigit(*typePtr))
|
|
|
|
|
{
|
|
|
|
|
info->offset = info->offset * 10 + (*typePtr++ - '0');
|
|
|
|
|
}
|
|
|
|
|
if (negative == YES)
|
|
|
|
|
{
|
|
|
|
|
info->offset = -info->offset;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 10:55:53 +00:00
|
|
|
|
return typePtr;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
1996-03-30 01:29:07 +00:00
|
|
|
|
|
|
|
|
|
/* Return the number of arguments that the method MTH expects. Note
|
|
|
|
|
that all methods need two implicit arguments `self' and `_cmd'. */
|
|
|
|
|
|
1994-11-04 16:29:24 +00:00
|
|
|
|
int
|
|
|
|
|
method_types_get_number_of_arguments (const char *type)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
1998-11-02 10:55:53 +00:00
|
|
|
|
|
1994-11-04 16:29:24 +00:00
|
|
|
|
while (*type)
|
|
|
|
|
{
|
|
|
|
|
type = objc_skip_argspec (type);
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
return i - 1;
|
|
|
|
|
}
|
|
|
|
|
|
1996-03-30 01:29:07 +00:00
|
|
|
|
|
|
|
|
|
/* Return the size of the argument block needed on the stack to invoke
|
1994-11-04 16:29:24 +00:00
|
|
|
|
the method MTH. This may be zero, if all arguments are passed in
|
1996-03-30 01:29:07 +00:00
|
|
|
|
registers. */
|
1994-11-04 16:29:24 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
method_types_get_size_of_stack_arguments (const char *type)
|
|
|
|
|
{
|
|
|
|
|
type = objc_skip_typespec (type);
|
|
|
|
|
return atoi (type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
method_types_get_size_of_register_arguments(const char *types)
|
|
|
|
|
{
|
|
|
|
|
const char* type = strrchr(types, '+');
|
1998-11-02 10:55:53 +00:00
|
|
|
|
|
1994-11-04 16:29:24 +00:00
|
|
|
|
if (type)
|
1998-11-02 10:55:53 +00:00
|
|
|
|
{
|
|
|
|
|
return atoi(++type) + sizeof(void*);
|
|
|
|
|
}
|
1994-11-04 16:29:24 +00:00
|
|
|
|
else
|
1998-11-02 10:55:53 +00:00
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
1994-11-04 16:29:24 +00:00
|
|
|
|
}
|
|
|
|
|
|