From 7cea2578637b823e93798e308ab0811c7fd7b7a4 Mon Sep 17 00:00:00 2001 From: Matthias Benkard Date: Mon, 28 Jan 2008 19:17:00 +0100 Subject: Directory layout: Put code imported from PyObjC into its own directory. darcs-hash:e3dd1138105e4eece0fbcbc13365eb3a25ffb808 --- Objective-C/PyObjC/objc_support.m | 505 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 Objective-C/PyObjC/objc_support.m (limited to 'Objective-C/PyObjC/objc_support.m') diff --git a/Objective-C/PyObjC/objc_support.m b/Objective-C/PyObjC/objc_support.m new file mode 100644 index 0000000..862879c --- /dev/null +++ b/Objective-C/PyObjC/objc_support.m @@ -0,0 +1,505 @@ +/* Copyright (c) 1996,97,98 by Lele Gaifax. All Rights Reserved + * Copyright (c) 2002, 2003 Ronald Oussoren + * + * This software may be used and distributed freely for any purpose + * provided that this notice is included unchanged on any and all + * copies. The author does not warrant or guarantee this software in + * any way. + * + * This file is part of the PyObjC package. + * + * RCSfile: objc_support.m,v + * Revision: 1.24 + * Date: 1998/08/18 15:35:58 + * + * Created Tue Sep 10 14:16:02 1996. + */ + +#include "objc_support.h" +#include "pyobjc.h" + +#include + +#include + +#ifdef MACOSX +/* OSX 10.1 doesn't define LLONG_MIN, LLONG_MAX and ULLONG_MAX */ +#ifndef LLONG_MIN +#error "Mac OS X 10.1 not supported" +#endif +#endif + +#import +#import +#import +#import + +#ifdef MACOSX +#include +#endif /* MACOSX */ + + +/* Define in order to throw exceptions when a typespec cannot be parsed. */ +#undef STRICT_TYPE_PARSING + + +#ifndef MAX +static inline ssize_t +MAX(ssize_t x, ssize_t y) +{ + return x > y ? x : y; +} +#endif + +static inline ssize_t +ROUND(ssize_t v, ssize_t a) +{ + if (v % a == 0) { + return v; + } else { + return v + a - (v % a); + } +} + + +const char* +PyObjCRT_SkipTypeQualifiers (const char* type) +{ + while ( + *type == _C_CONST || + *type == _C_IN || + *type == _C_INOUT || + *type == _C_OUT || + *type == _C_BYCOPY || + *type == _C_ONEWAY) { + type++; + } + while (*type && isdigit(*type)) type++; + return type; +} + + +const char * +PyObjCRT_SkipTypeSpec (const char *type) +{ + type = PyObjCRT_SkipTypeQualifiers (type); + + switch (*type) { + /* The following are one character type codes */ + case _C_UNDEF: + case _C_CLASS: + case _C_SEL: + case _C_CHR: + case _C_UCHR: + case _C_CHARPTR: +#ifdef _C_ATOM + case _C_ATOM: +#endif +#ifdef _C_BOOL + case _C_BOOL: +#endif + case _C_SHT: + case _C_USHT: + case _C_INT: + case _C_UINT: + case _C_LNG: + case _C_ULNG: + case _C_FLT: + case _C_DBL: + case _C_VOID: + case _C_LNGLNG: + case _C_ULNGLNG: + case _C_BFLD: /* Not really 1 character, but close enough */ + ++type; + break; + + case _C_ID: + ++type; +#ifdef MACOSX + if (*type == '"') { + /* embedded field name in an ivar_type */ + type=strchr(type+1, '"'); + if (type != NULL) { + type++; + } + } +#endif + break; + + case _C_ARY_B: + /* skip digits, typespec and closing ']' */ + + while (isdigit (*++type)); + type = PyObjCRT_SkipTypeSpec (type); + assert (type == NULL || *type == _C_ARY_E); + if (type) type++; + break; + + case _C_STRUCT_B: + /* skip name, and elements until closing '}' */ + while (*type != _C_STRUCT_E && *type++ != '='); + while (type && *type != _C_STRUCT_E) { + if (*type == '"') { + /* embedded field names */ + type = strchr(type+1, '"'); + if (type != NULL) { + type++; + } else { + return NULL; + } + } + type = PyObjCRT_SkipTypeSpec (type); + } + if (type) type++; + break; + + case _C_UNION_B: + /* skip name, and elements until closing ')' */ + while (*type != _C_UNION_E && *type++ != '='); + while (type && *type != _C_UNION_E) { + type = PyObjCRT_SkipTypeSpec (type); + } + if (type) type++; + break; + + case _C_PTR: + case _C_CONST: + case _C_IN: + case _C_INOUT: + case _C_OUT: + case _C_BYCOPY: + case _C_ONEWAY: + + /* Just skip the following typespec */ + type = PyObjCRT_SkipTypeSpec (type+1); + break; + + + default: +#ifdef STRICT_TYPE_PARSING + [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec" + reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type] + userInfo: NULL] raise]; +#else + NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type); +#endif + return NULL; + } + + /* The compiler inserts a number after the actual signature, + * this number may or may not be usefull depending on the compiler + * version. We never use it. + */ + while (type && *type && isdigit(*type)) type++; + return type; +} + +/* +Return the alignment of an object specified by type +*/ + +/* +* On MacOS X, the elements of a struct are aligned differently inside the +* struct than outside. That is, the maximum alignment of any struct field +* (except the first) is 4, doubles outside of a struct have an alignment of +* 8. +* +* Other platform don't seem to have this inconsistency. +* +* XXX: sizeof_struct, alignof_struct and {de,}pythonify_c_struct should +* probably be moved to platform dependend files. As long as this is the +* only platform dependent code this isn't worth the effort. +*/ +#ifdef MACOSX + +static inline ssize_t +PyObjC_EmbeddedAlignOfType (const char* type) +{ + ssize_t align = PyObjCRT_AlignOfType(type); + +#ifdef __i386__ + return align; + +#else + if (align < 4 || align == 16) { + return align; + } else { + return 4; + } +#endif +} + +#else + +static inline int +PyObjC_EmbeddedAlignOfType (const char* type) +{ + ssize_t align = PyObjCRT_AlignOfType(type); + + /* GNUstep/ix86 seems to behave like this: */ + if (align < 4) { + return align; + } else { + return 4; + } +} + +#endif + +ssize_t +PyObjCRT_AlignOfType (const char *type) +{ + switch (*type) { + case _C_ID: return __alignof__ (id); + case _C_CLASS: return __alignof__ (Class); + case _C_SEL: return __alignof__ (SEL); + case _C_CHR: return __alignof__ (char); + case _C_UCHR: return __alignof__ (unsigned char); + case _C_SHT: return __alignof__ (short); + case _C_USHT: return __alignof__ (unsigned short); +#ifdef _C_BOOL + case _C_BOOL: return __alignof__ (bool); +#endif + case _C_INT: return __alignof__ (int); + case _C_UINT: return __alignof__ (unsigned int); + case _C_LNG: return __alignof__ (long); + case _C_ULNG: return __alignof__ (unsigned long); + case _C_FLT: return __alignof__ (float); + case _C_DBL: +#if defined(__APPLE__) && defined(__i386__) + /* The ABI says natural alignment is 4 bytes, but + * GCC's __alignof__ says 8. The latter is wrong. + */ + return 4; +#else + return __alignof__ (double); +#endif + + case _C_CHARPTR: return __alignof__ (char *); +#ifdef _C_ATOM + case _C_ATOM: return __alignof__ (char *); +#endif + case _C_PTR: return __alignof__ (void *); +#if defined(__APPLE__) && defined(__i386__) + /* The ABI says natural alignment is 4 bytes, but + * GCC's __alignof__ says 8. The latter is wrong. + */ + case _C_LNGLNG: return 4; + case _C_ULNGLNG: return 4; +#else + case _C_LNGLNG: return __alignof__(long long); + case _C_ULNGLNG: return __alignof__(unsigned long long); +#endif + + case _C_ARY_B: + while (isdigit(*++type)) /* do nothing */; + return PyObjCRT_AlignOfType (type); + + case _C_STRUCT_B: + { + struct { int x; double y; } fooalign; + while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */; + if (*type != _C_STRUCT_E) { + int have_align = 0; + ssize_t align = 0; + + while (type != NULL && *type != _C_STRUCT_E) { + if (*type == '"') { + type = strchr(type+1, '"'); + if (type) type++; + } + if (have_align) { + align = MAX(align, + PyObjC_EmbeddedAlignOfType(type)); + } else { + align = PyObjCRT_AlignOfType(type); + have_align = 1; + } + type = PyObjCRT_SkipTypeSpec(type); + } + if (type == NULL) return -1; + return align; + } else { + return __alignof__ (fooalign); + } + } + + case _C_UNION_B: + { + int maxalign = 0; + type++; + while (*type != _C_UNION_E) + { + int item_align = PyObjCRT_AlignOfType(type); + if (item_align == -1) return -1; + maxalign = MAX (maxalign, item_align); + type = PyObjCRT_SkipTypeSpec (type); + } + return maxalign; + } + + case _C_CONST: + case _C_IN: + case _C_INOUT: + case _C_OUT: + case _C_BYCOPY: + case _C_ONEWAY: + return PyObjCRT_AlignOfType(type+1); + + default: +#ifdef STRICT_TYPE_PARSING + [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec" + reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type] + userInfo: NULL] raise]; +#else + NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type); +#endif + return -1; + } +} + +/* +The aligned size if the size rounded up to the nearest alignment. +*/ + +static ssize_t +PyObjCRT_AlignedSize (const char *type) +{ + ssize_t size = PyObjCRT_SizeOfType (type); + ssize_t align = PyObjCRT_AlignOfType (type); + + if (size == -1 || align == -1) return -1; + return ROUND(size, align); +} + +/* +return the size of an object specified by type +*/ + +ssize_t +PyObjCRT_SizeOfType (const char *type) +{ + ssize_t itemSize; + switch (*type) { + case _C_VOID: return 0; + case _C_ID: return sizeof(id); + case _C_CLASS: return sizeof(Class); + case _C_SEL: return sizeof(SEL); + case _C_CHR: return sizeof(char); + case _C_UCHR: return sizeof(unsigned char); + case _C_SHT: return sizeof(short); + case _C_USHT: return sizeof(unsigned short); +#ifdef _C_BOOL + case _C_BOOL: return sizeof(bool); +#endif + case _C_INT: return sizeof(int); + case _C_UINT: return sizeof(unsigned int); + case _C_LNG: return sizeof(long); + case _C_ULNG: return sizeof(unsigned long); + case _C_FLT: return sizeof(float); + case _C_DBL: return sizeof(double); + case _C_LNGLNG: return sizeof(long long); + case _C_ULNGLNG: return sizeof(unsigned long long); + + case _C_PTR: + case _C_CHARPTR: +#ifdef _C_ATOM + case _C_ATOM: +#endif + return sizeof(char*); + + case _C_ARY_B: + { + ssize_t len = atoi(type+1); + ssize_t item_align; + while (isdigit(*++type)) + ; + item_align = PyObjCRT_AlignedSize(type); + if (item_align == -1) return -1; + return len*item_align; + } + break; + + case _C_STRUCT_B: + { + ssize_t acc_size = 0; + int have_align = 0; + ssize_t align; + ssize_t max_align = 0; + + while (*type != _C_STRUCT_E && *type++ != '=') + ; /* skip "=" */ + while (*type != _C_STRUCT_E) { + if (*type == '"') { + type = strchr(type+1, '"'); + if (type) type++; + } + if (have_align) { + align = PyObjC_EmbeddedAlignOfType(type); + if (align == -1) return -1; + } else { + align = PyObjCRT_AlignOfType(type); + if (align == -1) return -1; + have_align = 1; + } + max_align = MAX(align, max_align); + acc_size = ROUND (acc_size, align); + + itemSize = PyObjCRT_SizeOfType (type); + if (itemSize == -1) return -1; + acc_size += itemSize; + type = PyObjCRT_SkipTypeSpec (type); + } + if (max_align) { + acc_size = ROUND(acc_size, max_align); + } + return acc_size; + } + + case _C_UNION_B: + { + ssize_t max_size = 0; + type++; + while (*type != _C_UNION_E) { + itemSize = PyObjCRT_SizeOfType (type); + if (itemSize == -1) return -1; + max_size = MAX (max_size, itemSize); + type = PyObjCRT_SkipTypeSpec (type); + } + return max_size; + } + + case _C_CONST: + case _C_IN: + case _C_INOUT: + case _C_OUT: + case _C_BYCOPY: + case _C_ONEWAY: + return PyObjCRT_SizeOfType(type+1); + + default: +#ifdef STRICT_TYPE_PARSING + [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec" + reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type] + userInfo: NULL] raise]; +#else + NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type); +#endif + return -1; + } +} + + +ssize_t +PyObjCRT_SizeOfReturnType(const char* type) +{ + switch(*type) { + case _C_CHR: + case _C_UCHR: + case _C_SHT: + case _C_USHT: + return sizeof(int); + default: + return PyObjCRT_SizeOfType(type); + } +} -- cgit v1.2.3