Add new type encoding parser by Ibadinov Marat, modified to build on gnu/linux

without warnings, using gcc.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@36813 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2013-07-03 07:55:48 +00:00
parent 060ba55854
commit 38ea0d2b27
6 changed files with 983 additions and 1 deletions

View file

@ -1,3 +1,10 @@
2013-07-03 Ibadinov Marat <ibadinov@me.com>
* Source/Additions/GNUmakefile:
* Headers/GNUstepBase/GSTypeEncoding.c:
* Headers/GNUstepBase/GSTypeEncoding.h:
New type encoding parser.
2013-07-03 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSException.h:

View file

@ -0,0 +1,226 @@
/*
* Objective-C type encoding support
*
* Copyright (C) 2012-2013 Free Software Foundation, Inc.
*
* Written by Marat Ibadinov <ibadinov@me.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef GS_TYPE_ENCODING_H
#define GS_TYPE_ENCODING_H
#include <stdint.h>
#if defined (NeXT_RUNTIME)
# include <objc/objc-runtime.h>
#else
# if defined (__GNU_LIBOBJC__)
# include <objc/runtime.h>
# else
# include <objc/objc-api.h>
# include <objc/encoding.h>
# endif
#endif
#if !defined(ENCODING_INLINE)
# if defined(__GNUC__)
# define ENCODING_INLINE static __inline__ __attribute__((always_inline))
# elif
# define ENCODING_INLINE static inline
# endif
#endif
/* type mangling is compiler independent so we can safely define this by hand */
typedef enum GSObjCTypeQualifier
{
GSObjCQualifierConst = 'r',
GSObjCQualifierIn = 'n',
GSObjCQualifierInOut = 'N',
GSObjCQualifierOut = 'o',
GSObjCQualifierByCopy = 'O',
GSObjCQualifierByRef = 'R',
GSObjCQualifierOneWay = 'V',
GSObjCQualifierInvisible = '!'
} GSObjCTypeQualifier;
typedef enum GSObjCType
{
GSObjCTypeId = '@',
GSObjCTypeClass = '#',
GSObjCTypeSelector = ':',
GSObjCTypeChar = 'c',
GSObjCTypeUnsignedChar = 'C',
GSObjCTypeShort = 's',
GSObjCTypeUnsignedShort = 'S',
GSObjCTypeInt = 'i',
GSObjCTypeUnsignedInt = 'I',
GSObjCTypeLong = 'l',
GSObjCTypeUnsignedLong = 'L',
GSObjCTypeLongLong = 'q',
GSObjCTypeUnsignedLongLong = 'Q',
GSObjCTypeFloat = 'f',
GSObjCTypeDouble = 'd',
GSObjCTypeComplex = 'j',
GSObjCTypeBitField = 'b',
GSObjCTypeBool = 'B',
GSObjCTypeVoid = 'v',
GSObjCTypePointer = '^',
GSObjCTypeCharPointer = '*',
GSObjCTypeAtom = '%',
GSObjCTypeArrayBegin = '[',
GSObjCTypeArrayEnd = ']',
GSObjCTypeStructureBegin = '{',
GSObjCTypeStructureEnd = '}',
GSObjCTypeUnionBegin = '(',
GSObjCTypeUnionEnd = ')',
GSObjCTypeUnknown = '?'
} GSObjCType;
/* maximum an minimum char values in a type specification */
typedef enum GSObjCTypeBound
{
GSObjCTypeMin = ' ',
GSObjCTypeMax = '~'
} GSObjCTypeBound;
#if defined (NeXT_RUNTIME)
typedef enum GSObjCTypeQualifierMask
{
GSObjCQualifierConstMask = 0x01,
GSObjCQualifierInMask = 0x01,
GSObjCQualifierOutMask = 0x02,
GSObjCQualifierInOutMask = 0x03,
GSObjCQualifierByCopyMask = 0x04,
GSObjCQualifierByRefMask = 0x08,
GSObjCQualifierOneWayMask = 0x10,
GSObjCQualifierInvisibleMask = 0x20
} GSObjCTypeQualifierMask;
#else
typedef enum GSObjCTypeQualifierMask
{
GSObjCQualifierConstMask = _F_CONST,
GSObjCQualifierInMask = _F_IN,
GSObjCQualifierOutMask = _F_OUT,
GSObjCQualifierInOutMask = _F_INOUT,
GSObjCQualifierByCopyMask = _F_BYCOPY,
GSObjCQualifierByRefMask = _F_BYREF,
GSObjCQualifierOneWayMask = _F_ONEWAY,
GSObjCQualifierInvisibleMask = _F_GCINVISIBLE
} GSObjCTypeQualifierMask;
#endif
/*
* parser-related stuff
*/
typedef struct GSObjCTypeInfo {
/* store pointer to allow recursive parsing of pointer types, e.g. ^{^[2*]} */
const char *type;
size_t size;
uint8_t alignment;
uint8_t qualifiers;
} GSObjCTypeInfo;
typedef void (*GSObjCTypeParserDelegate)(void *context, GSObjCTypeInfo type);
typedef enum GSObjCParserOptions {
GSObjCReportArrayOnceMask = 1
} GSObjCParserOptions;
const char *
GSObjCParseTypeSpecification (const char *cursor,
GSObjCTypeParserDelegate delegate,
void *context,
unsigned options);
ENCODING_INLINE size_t
GSObjCPadSize (size_t size, uint8_t alignment)
{
return alignment * ((size + alignment - 1) / alignment);
}
ENCODING_INLINE size_t
GSObjCGetPadding (size_t size, uint8_t alignment)
{
return (alignment - (size & (alignment - 1))) & (alignment - 1);
}
const char *
GSGetSizeAndAlignment (const char *type, size_t *sizep, uint8_t *alignp);
#if defined (NeXT_RUNTIME)
/* GNU API support for NeXT runtime */
int
objc_sizeof_type (const char* type);
int
objc_alignof_type (const char* type);
int
objc_aligned_size (const char* type);
int
objc_promoted_size (const char* type);
unsigned
objc_get_type_qualifiers (const char* type);
const char *
objc_skip_typespec (const char* type);
const char *
objc_skip_offset (const char* type);
const char *
objc_skip_argspec (const char* type);
const char *
objc_skip_type_qualifiers (const char* type);
struct objc_struct_layout
{
GSObjCTypeInfo *info;
long position;
unsigned count;
unsigned allocated;
unsigned depth;
unsigned offset;
unsigned alignment;
};
void
objc_layout_structure (const char *type,
struct objc_struct_layout *layout);
BOOL
objc_layout_structure_next_member (struct objc_struct_layout *layout);
void
objc_layout_structure_get_info (struct objc_struct_layout *layout,
unsigned int *offset,
unsigned int *align,
const char **type);
void
objc_layout_finish_structure (struct objc_struct_layout *layout,
unsigned int *size,
unsigned int *align);
#endif /* NeXT_RUNTIME */
#endif /* GS_TYPE_ENCODING_H */

View file

@ -31,6 +31,9 @@ include ../../config.mak
SUBPROJECT_NAME = Additions
Additions_C_FILES =\
GSTypeEncoding.c \
Additions_OBJC_FILES =\
GSObjCRuntime.m \
GCObject.m \
@ -61,7 +64,6 @@ Additions_OBJC_FILES =\
NSThread+GNUstepBase.m \
NSURL+GNUstepBase.m \
Additions_OBJC_FILES += Unicode.m
-include Makefile.preamble

View file

@ -0,0 +1,729 @@
/*
* Objective-C type encoding support
*
* Copyright (C) 2012-2013 Free Software Foundation, Inc.
*
* Written by Marat Ibadinov <ibadinov@me.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "GNUstepBase/GSTypeEncoding.h"
#undef MAX
#define MAX(X, Y) \
({ \
typeof (X) __x = (X), __y = (Y); \
(__x > __y ? __x : __y); \
})
/*
* We store here aligned sizes of primitive types
* and bit-masks of type qualifiers
*/
static const int8_t typeInfoTable[] =
{
/* types */
[GSObjCTypeId] = sizeof(id),
[GSObjCTypeClass] = sizeof(Class),
[GSObjCTypeSelector] = sizeof(SEL),
[GSObjCTypeChar] = sizeof(char),
[GSObjCTypeUnsignedChar] = sizeof(unsigned char),
[GSObjCTypeShort] = sizeof(short),
[GSObjCTypeUnsignedShort] = sizeof(unsigned short),
[GSObjCTypeInt] = sizeof(int),
[GSObjCTypeUnsignedInt] = sizeof(unsigned int),
[GSObjCTypeLong] = sizeof(long),
[GSObjCTypeUnsignedLong] = sizeof(unsigned long),
[GSObjCTypeLongLong] = sizeof(long long),
[GSObjCTypeUnsignedLongLong] = sizeof(unsigned long long),
[GSObjCTypeFloat] = sizeof(float),
[GSObjCTypeDouble] = sizeof(double),
[GSObjCTypeBool] = sizeof(_Bool),
[GSObjCTypeVoid] = sizeof(void),
/* here would go Pointer, but in most cases it needs special treatment */
[GSObjCTypeCharPointer] = sizeof(char *),
[GSObjCTypeAtom] = sizeof(void *),
/* type qualifiers (negated for distinctiveness) */
[GSObjCQualifierConst] = -GSObjCQualifierConstMask,
[GSObjCQualifierIn] = -GSObjCQualifierInMask,
[GSObjCQualifierInOut] = -GSObjCQualifierInOutMask,
[GSObjCQualifierOut] = -GSObjCQualifierOutMask,
[GSObjCQualifierByCopy] = -GSObjCQualifierByCopyMask,
[GSObjCQualifierByRef] = -GSObjCQualifierByRefMask,
[GSObjCQualifierOneWay] = -GSObjCQualifierOneWayMask,
[GSObjCQualifierInvisible] = -GSObjCQualifierInvisible,
/* ensure an appropriate table size */
[GSObjCTypeMax] = 0
};
/* all substripts of typeInfoTable are of char type */
#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wchar-subscripts"
#endif
ENCODING_INLINE uint8_t
RoundToThePowerOfTwo (uint8_t value)
{
--value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
return ++value;
}
ENCODING_INLINE const char *
GetNumericValue (const char *cursor, int *value)
{
*value = 0;
while (*cursor >= '0' && *cursor <= '9')
{
*value = 10 * (*value) + (*cursor++ - '0');
}
return cursor;
}
ENCODING_INLINE const char *
SkipName (const char *cursor)
{
if (*cursor == '"')
{
for (++cursor; *cursor++ != '"';);
}
return cursor;
}
ENCODING_INLINE const char *
SkipType (const char *cursor)
{
unsigned depth = 0;
do {
while (typeInfoTable[(int)*cursor] < 0)
{
++cursor;
}
if (!typeInfoTable[(int)*cursor])
{
switch (*cursor)
{
case GSObjCTypeArrayBegin:
case GSObjCTypeStructureBegin:
case GSObjCTypeUnionBegin:
++depth;
break;
case GSObjCTypeArrayEnd:
case GSObjCTypeStructureEnd:
case GSObjCTypeUnionEnd:
--depth;
break;
case GSObjCTypePointer:
++cursor;
default:
break;
}
}
cursor = SkipName(++cursor);
} while (depth);
return cursor;
}
ENCODING_INLINE const char *
GetQualifiers (const char *cursor, uint8_t *qualifiers)
{
*qualifiers = 0;
while (typeInfoTable[(int)*cursor] < 0)
{
*qualifiers |= (uint8_t) -typeInfoTable[(int)*cursor];
++cursor;
}
return cursor;
}
typedef struct ParserStackElement
{
const char *cursor;
size_t size;
size_t count; /* for arrays */
char alignment;
char qualifiers;
} ParserStackElement;
typedef struct ParserOutput
{
GSObjCTypeInfo info;
unsigned parentDepth;
BOOL suppressed;
} ParserOutput;
typedef struct ParserState
{
ParserStackElement *stack;
ParserOutput *buffer;
unsigned stackSize;
unsigned bufferSize;
unsigned allocated;
unsigned stackSpace;
unsigned bufferSpace;
} ParserState;
/**
* Complex type nesting level of 4 or greater is a rare case.
* With initial size of 3 total memory footprint of stack and
* buffer is 224 bytes (on machines with 64-bit word).
*
* Nesting depth of 16 will require circa 1K of memory, 64 - approximately 4K.
* Maybe it would be better to place an upper bound on nesting depth and simply
* allocate space on stack once. This will certainly be a performance again.
*/
static const unsigned ParserInitialStackSize = 3;
ENCODING_INLINE ParserStackElement *
ParserStackTop (ParserState *state)
{
return state->stackSize ? &state->stack[state->stackSize - 1] : NULL;
}
const char *
GSObjCParseTypeSpecification (const char *cursor,
GSObjCTypeParserDelegate delegate,
void *context,
unsigned options)
{
ParserState state;
unsigned suppressionDepth = 0;
unsigned bitFieldSpaceAvailable = 0;
ParserStackElement el;
unsigned index;
state.stackSize = state.bufferSize = 0;
state.stackSpace = sizeof(ParserStackElement) * ParserInitialStackSize;
state.bufferSpace = sizeof(ParserOutput) * (ParserInitialStackSize + 1);
state.stack = malloc(state.stackSpace + state.bufferSpace);
state.buffer = (void *)state.stack + state.stackSpace;
state.allocated = ParserInitialStackSize;
do {
GSObjCTypeInfo info = {cursor, 0, 1, 0};
BOOL pushStack = NO;
BOOL popStack = NO;
BOOL pushBuffer = YES;
BOOL suppress = suppressionDepth != 0;
unsigned parentDepth;
cursor = GetQualifiers(cursor, &info.qualifiers);
cursor = SkipName(cursor);
parentDepth = state.stackSize;
/* is it a primitive type? */
if (typeInfoTable[(int)*cursor])
{
info.size = info.alignment = typeInfoTable[(int)*cursor];
cursor = SkipName(++cursor);
}
else
{
switch (*cursor) {
case GSObjCTypeBitField:
{
int totalBitCount = -bitFieldSpaceAvailable;
int bitCount = 0;
info.alignment = 1;
while (totalBitCount < 8 && *cursor == GSObjCTypeBitField)
/* can we emit token */
{
cursor = GetNumericValue(++cursor, &bitCount);
totalBitCount += bitCount;
/* round bitCount to the nearest power of 2 */
info.alignment
= MAX(info.alignment, RoundToThePowerOfTwo(bitCount) / 8);
}
info.size = totalBitCount / 8
+ ((totalBitCount & 7 /* mod 8 */) != 0);
if (*cursor == GSObjCTypeBitField)
{
bitFieldSpaceAvailable
= (unsigned)info.alignment * 8 - totalBitCount;
}
else
bitFieldSpaceAvailable = 0;
break;
}
case GSObjCTypePointer:
{
info.size = info.alignment = sizeof(void *);
cursor = SkipType(++cursor);
break;
}
case GSObjCTypeComplex:
{
info.size = 2 * (info.alignment = typeInfoTable[(int)*++cursor]);
++cursor;
break;
}
case GSObjCTypeArrayBegin:
{
int length;
cursor = GetNumericValue(++cursor, &length);
el = (ParserStackElement){
cursor, 0, length - 1, 1, info.qualifiers
};
pushStack = YES;
suppressionDepth += (options & GSObjCReportArrayOnceMask) != 0;
break;
}
case GSObjCTypeStructureBegin:
{
el = (ParserStackElement){cursor, 0, 0, 1, info.qualifiers};
/* skip typename annotation */
while (*cursor != GSObjCTypeStructureEnd && *cursor++ != '=');
pushStack = YES;
break;
}
case GSObjCTypeUnionBegin:
{
el = (ParserStackElement){cursor, 0, 0, 1, info.qualifiers};
/* skip typename annotation */
while (*cursor != GSObjCTypeUnionEnd && *cursor++ != '=');
++suppressionDepth;
pushStack = YES;
break;
}
case GSObjCTypeUnionEnd:
case GSObjCTypeArrayEnd:
case GSObjCTypeStructureEnd:
{
popStack = YES;
break;
}
default:
abort();
}
}
if (pushStack)
{
if (state.stackSize == state.allocated)
{
unsigned stackSpace;
unsigned bufferSpace;
void *data;
state.allocated *= 2;
stackSpace = sizeof(ParserStackElement) * state.allocated;
bufferSpace = sizeof(ParserOutput) * (state.allocated + 1);
data = malloc(stackSpace + bufferSpace);
memcpy(data, state.stack, state.stackSpace);
memcpy(data + stackSpace, state.buffer, state.bufferSpace);
free(state.stack);
state.stack = data;
state.buffer = (void *)data + stackSpace;
state.stackSpace = stackSpace;
state.bufferSpace = bufferSpace;
}
state.stack[state.stackSize] = el;
++state.stackSize;
}
else
{
/* we can safely flush the buffer */
for (index = 0; index < state.bufferSize; ++index)
{
GSObjCTypeInfo output = state.buffer[index].info;
unsigned depth = state.buffer[index].parentDepth;
if (depth)
{
ParserStackElement *parent = &state.stack[depth - 1];
if (*parent->cursor != GSObjCTypeUnionBegin)
{
size_t alignedSize;
/* in array and structure we should align data according
* to the element that triggered flushing (it may be the
* next real member of the data-structure or a closing
* tag)
*/
output.alignment = MAX(output.alignment, info.alignment);
alignedSize = GSObjCPadSize(output.size, output.alignment);
parent->size += alignedSize;
}
else
{
parent->size = MAX(parent->size, output.size);
}
parent->alignment = MAX(parent->alignment, output.alignment);
}
if (!state.buffer[index].suppressed)
{
delegate(context, output);
}
}
state.bufferSize = 0;
}
if (popStack)
{
ParserStackElement *element = ParserStackTop(&state);
switch (*cursor)
{
case GSObjCTypeUnionEnd:
--suppressionDepth;
case GSObjCTypeArrayEnd:
{
if (element->count)
{
if (options & GSObjCReportArrayOnceMask)
{
/* we need to compensate "length - 1" */
element->size *= (element->count + 1);
--suppressionDepth;
}
else
{
/* decrease length and rewind */
--element->count;
cursor = element->cursor;
pushBuffer = NO;
break;
}
}
}
case GSObjCTypeStructureEnd:
{
info.qualifiers = element->qualifiers;
info.size = element->size;
info.alignment = element->alignment;
parentDepth = --state.stackSize;
++cursor;
break;
}
}
}
if (pushBuffer)
{
/* outermost GSObjCTypeUnionBegin and GSObjCTypeUnionEnd
* should be reported
*/
state.buffer[state.bufferSize].suppressed
= suppress && suppressionDepth != 0;
state.buffer[state.bufferSize].parentDepth = parentDepth;
state.buffer[state.bufferSize].info = info;
++state.bufferSize;
}
} while (state.stackSize);
for (index = 0; index < state.bufferSize; ++index)
{
if (!state.buffer[index].suppressed)
{
delegate(context, state.buffer[index].info);
}
}
free(state.stack);
return cursor;
}
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
typedef struct InfoAccumulator
{
size_t size;
char alignment;
} InfoAccumulator;
static void
InfoAccumulatorAddInfo (InfoAccumulator *this, GSObjCTypeInfo info)
{
/* if it's the end of structure, accumulate only padding */
if (*info.type == GSObjCTypeStructureEnd)
this->size += GSObjCGetPadding (info.size, info.alignment);
else
this->size += GSObjCPadSize (info.size, info.alignment);
this->alignment = MAX(this->alignment, info.alignment);
}
const char *
GSGetSizeAndAlignment (const char *type, size_t *sizep, uint8_t *alignp)
{
InfoAccumulator accumulator = {0, 0};
type = GSObjCParseTypeSpecification (type,
(GSObjCTypeParserDelegate)&InfoAccumulatorAddInfo,
&accumulator,
GSObjCReportArrayOnceMask);
if (sizep)
{
*sizep = accumulator.size;
}
if (alignp)
{
*alignp = accumulator.alignment;
}
return type;
}
#if defined (NeXT_RUNTIME)
/* emulate GNU API */
typedef struct SizeInfoAccumulator
{
size_t size;
unsigned depth;
} SizeInfoAccumulator;
static void
SizeInfoAccumulatorAddInfo (SizeInfoAccumulator *this, GSObjCTypeInfo info)
{
/* we wait until typespec's last element and save it's unaligned size */
switch (*info.type)
{
case GSObjCTypeArrayBegin:
case GSObjCTypeStructureBegin:
case GSObjCTypeUnionBegin:
++this->depth;
break;
case GSObjCTypeArrayEnd:
case GSObjCTypeStructureEnd:
case GSObjCTypeUnionEnd:
--this->depth;
break;
default:
break;
}
if (!this->depth)
{
this->size += info.size;
}
}
int
objc_sizeof_type (const char* type)
{
SizeInfoAccumulator accumulator = {0, 0};
GSObjCParseTypeSpecification (type,
(GSObjCTypeParserDelegate)&SizeInfoAccumulatorAddInfo,
&accumulator,
GSObjCReportArrayOnceMask);
return (int)accumulator.size;
}
int
objc_alignof_type (const char* type)
{
uint8_t alignment;
GSGetSizeAndAlignment (type, NULL, &alignment);
return (int)alignment;
}
int
objc_aligned_size (const char* type)
{
size_t size;
GSGetSizeAndAlignment (type, &size, NULL);
return (int)size;
}
int
objc_promoted_size (const char* type)
{
size_t size;
GSGetSizeAndAlignment (type, &size, NULL);
return (int)GSObjCPadSize (size, sizeof(void *));
}
/* we should not instantiate this function more than once */
static const char *
GetQualifiersInst (const char *cursor, uint8_t *qualifiers)
{
return GetQualifiers (cursor, qualifiers);
}
/* we should not instantiate this function more than once */
static const char *
SkipTypeInst (const char *cursor)
{
return SkipType(cursor);
}
unsigned
objc_get_type_qualifiers (const char* type)
{
uint8_t qualifiers;
GetQualifiersInst (type, &qualifiers);
return qualifiers;
}
const char *
objc_skip_type_qualifiers (const char* type)
{
uint8_t qualifiers;
return GetQualifiersInst (type, &qualifiers);
}
const char *
objc_skip_typespec (const char* type)
{
uint8_t qualifiers;
type = GetQualifiersInst (type, &qualifiers);
return SkipTypeInst (type);
}
const char *
objc_skip_offset (const char* type)
{
if (*type == '+' || *type == '-')
{
type++;
}
while (*type >= '0' && *type <= '9')
{
type++;
}
return type;
}
const char *
objc_skip_argspec (const char* type)
{
type = SkipTypeInst (type);
return objc_skip_offset (type);
}
static void
objc_layout_structure_append_info(struct objc_struct_layout *this,
GSObjCTypeInfo info)
{
if (this->count == this->allocated)
{
this->info = realloc(this->info, sizeof(GSObjCTypeInfo) * (this->allocated *= 2));
}
this->info[this->count] = info;
++this->count;
}
static void
objc_layout_structure_parser_delegate(struct objc_struct_layout *this,
GSObjCTypeInfo info)
{
unsigned initialDepth = this->depth;
switch (*info.type)
{
case GSObjCTypeArrayEnd:
case GSObjCTypeStructureEnd:
case GSObjCTypeUnionEnd:
{
if (--this->depth == 1)
{
this->info[this->count - 1].size = info.size;
this->info[this->count - 1].alignment = info.alignment;
}
break;
}
case GSObjCTypeArrayBegin:
case GSObjCTypeStructureBegin:
case GSObjCTypeUnionBegin:
++this->depth;
default:
if (initialDepth == 1)
{
objc_layout_structure_append_info(this, info);
}
break;
}
}
void
objc_layout_structure (const char *type,
struct objc_struct_layout *layout)
{
*layout = (struct objc_struct_layout)
{
malloc(8 * sizeof(GSObjCTypeInfo)),
-1, 0, 8, 0, 0, 0
};
GSObjCParseTypeSpecification(type,
(GSObjCTypeParserDelegate)&objc_layout_structure_parser_delegate,
layout,
GSObjCReportArrayOnceMask);
}
BOOL
objc_layout_structure_next_member (struct objc_struct_layout *layout)
{
return ++layout->position < layout->count;
}
void
objc_layout_structure_get_info (struct objc_struct_layout *layout,
unsigned int *offset,
unsigned int *align,
const char **type)
{
GSObjCTypeInfo info = layout->info[layout->position];
if (offset)
{
*offset = layout->offset;
}
if (align)
{
*align = info.alignment;
}
if (type)
{
*type = info.type;
}
layout->offset += GSObjCPadSize(info.size, info.alignment);
layout->alignment = MAX(layout->alignment, info.alignment);
}
void
objc_layout_finish_structure (struct objc_struct_layout *layout,
unsigned int *size,
unsigned int *align)
{
if (size)
{
*size = (unsigned int) GSObjCPadSize(layout->offset, layout->alignment);
}
if (align)
{
*align = layout->alignment;
}
free(layout->info);
}
#endif /* NeXT_RUNTIME */

9
configure vendored
View file

@ -3394,6 +3394,15 @@ LDFLAGS="$LDFLAGS -L$GNUSTEP_SYSTEM_LIBRARIES -L$GNUSTEP_NETWORK_LIBRARIES -L$GN
#--------------------------------------------------------------------
# Find the compiler
#--------------------------------------------------------------------
if test "$CC" = ""; then
CC=`gnustep-config --variable=CC`
fi
if test "$CPP" = ""; then
CPP=`gnustep-config --variable=CPP`
fi
if test "$CXX" = ""; then
CXX=`gnustep-config --variable=CXX`
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'

View file

@ -1048,6 +1048,15 @@ LDFLAGS="$LDFLAGS -L$GNUSTEP_SYSTEM_LIBRARIES -L$GNUSTEP_NETWORK_LIBRARIES -L$GN
#--------------------------------------------------------------------
# Find the compiler
#--------------------------------------------------------------------
if test "$CC" = ""; then
CC=`gnustep-config --variable=CC`
fi
if test "$CPP" = ""; then
CPP=`gnustep-config --variable=CPP`
fi
if test "$CXX" = ""; then
CXX=`gnustep-config --variable=CXX`
fi
AC_PROG_CC
AC_PROG_CPP
AC_USE_SYSTEM_EXTENSIONS