mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
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:
parent
060ba55854
commit
38ea0d2b27
6 changed files with 983 additions and 1 deletions
|
@ -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>
|
2013-07-03 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Headers/Foundation/NSException.h:
|
* Headers/Foundation/NSException.h:
|
||||||
|
|
226
Headers/GNUstepBase/GSTypeEncoding.h
Normal file
226
Headers/GNUstepBase/GSTypeEncoding.h
Normal 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 */
|
|
@ -31,6 +31,9 @@ include ../../config.mak
|
||||||
|
|
||||||
SUBPROJECT_NAME = Additions
|
SUBPROJECT_NAME = Additions
|
||||||
|
|
||||||
|
Additions_C_FILES =\
|
||||||
|
GSTypeEncoding.c \
|
||||||
|
|
||||||
Additions_OBJC_FILES =\
|
Additions_OBJC_FILES =\
|
||||||
GSObjCRuntime.m \
|
GSObjCRuntime.m \
|
||||||
GCObject.m \
|
GCObject.m \
|
||||||
|
@ -61,7 +64,6 @@ Additions_OBJC_FILES =\
|
||||||
NSThread+GNUstepBase.m \
|
NSThread+GNUstepBase.m \
|
||||||
NSURL+GNUstepBase.m \
|
NSURL+GNUstepBase.m \
|
||||||
|
|
||||||
|
|
||||||
Additions_OBJC_FILES += Unicode.m
|
Additions_OBJC_FILES += Unicode.m
|
||||||
|
|
||||||
-include Makefile.preamble
|
-include Makefile.preamble
|
||||||
|
|
729
Source/Additions/GSTypeEncoding.c
Normal file
729
Source/Additions/GSTypeEncoding.c
Normal 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
9
configure
vendored
|
@ -3394,6 +3394,15 @@ LDFLAGS="$LDFLAGS -L$GNUSTEP_SYSTEM_LIBRARIES -L$GNUSTEP_NETWORK_LIBRARIES -L$GN
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Find the compiler
|
# 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_ext=c
|
||||||
ac_cpp='$CPP $CPPFLAGS'
|
ac_cpp='$CPP $CPPFLAGS'
|
||||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||||
|
|
|
@ -1048,6 +1048,15 @@ LDFLAGS="$LDFLAGS -L$GNUSTEP_SYSTEM_LIBRARIES -L$GNUSTEP_NETWORK_LIBRARIES -L$GN
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Find the compiler
|
# 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_CC
|
||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue