1 /*
2  * Objective-C type encoding support
3  *
4  * Copyright (C) 2012-2014 Free Software Foundation, Inc.
5  *
6  * Written by Marat Ibadinov <ibadinov@me.com>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #ifndef GS_TYPE_ENCODING_H
28 #define GS_TYPE_ENCODING_H
29 
30 #include <GNUstepBase/GSVersionMacros.h>
31 
32 #if defined(__MINGW__)
33 /* On MINGW we need to get the boolean type from the runtime at this point.
34  */
35 #define _NO_BOOL_TYPEDEF
36 #endif
37 
38 #if defined (NeXT_RUNTIME)
39 #  include <objc/objc-runtime.h>
40 #else
41 #  include <objc/objc.h>
42 #  if defined (__GNU_LIBOBJC__)
43 #    include <objc/runtime.h>
44 #  else
45 #    include <objc/objc-api.h>
46 #    include <objc/encoding.h>
47 #  endif
48 #endif
49 
50 #if !defined(GS_STATIC_INLINE)
51 #  if defined(__GNUC__)
52 #    define GS_STATIC_INLINE static __inline__ __attribute__((always_inline))
53 #  else
54 #    define GS_STATIC_INLINE static inline
55 #  endif
56 #endif
57 
58 /* type mangling is compiler independent so we can safely define this by hand */
59 
60 typedef enum GSObjCTypeQualifier
61 {
62   GSObjCQualifierConst        = 'r',
63   GSObjCQualifierIn           = 'n',
64   GSObjCQualifierInOut        = 'N',
65   GSObjCQualifierOut          = 'o',
66   GSObjCQualifierByCopy       = 'O',
67   GSObjCQualifierByRef        = 'R',
68   GSObjCQualifierOneWay       = 'V',
69   GSObjCQualifierInvisible    = '!'
70 } GSObjCTypeQualifier;
71 
72 typedef enum GSObjCType
73 {
74   GSObjCTypeId                = '@',
75   GSObjCTypeClass             = '#',
76   GSObjCTypeSelector          = ':',
77   GSObjCTypeChar              = 'c',
78   GSObjCTypeUnsignedChar      = 'C',
79   GSObjCTypeShort             = 's',
80   GSObjCTypeUnsignedShort     = 'S',
81   GSObjCTypeInt               = 'i',
82   GSObjCTypeUnsignedInt       = 'I',
83   GSObjCTypeLong              = 'l',
84   GSObjCTypeUnsignedLong      = 'L',
85   GSObjCTypeLongLong          = 'q',
86   GSObjCTypeUnsignedLongLong  = 'Q',
87   GSObjCTypeFloat             = 'f',
88   GSObjCTypeDouble            = 'd',
89   GSObjCTypeComplex           = 'j',
90   GSObjCTypeBitField          = 'b',
91   GSObjCTypeBool              = 'B',
92   GSObjCTypeVoid              = 'v',
93   GSObjCTypePointer           = '^',
94   GSObjCTypeCharPointer       = '*',
95   GSObjCTypeAtom              = '%',
96   GSObjCTypeArrayBegin        = '[',
97   GSObjCTypeArrayEnd          = ']',
98   GSObjCTypeStructureBegin    = '{',
99   GSObjCTypeStructureEnd      = '}',
100   GSObjCTypeUnionBegin        = '(',
101   GSObjCTypeUnionEnd          = ')',
102   GSObjCTypeUnknown           = '?'
103 } GSObjCType;
104 
105 /* maximum and minimum char values in a type specification */
106 typedef enum GSObjCTypeBound
107 {
108   GSObjCTypeMin               = ' ',
109   GSObjCTypeMax               = '~'
110 } GSObjCTypeBound;
111 
112 #if defined (NeXT_RUNTIME)
113 typedef enum GSObjCTypeQualifierMask
114 {
115   GSObjCQualifierConstMask        = 0x01,
116   GSObjCQualifierInMask           = 0x01,
117   GSObjCQualifierOutMask          = 0x02,
118   GSObjCQualifierInOutMask        = 0x03,
119   GSObjCQualifierByCopyMask       = 0x04,
120   GSObjCQualifierByRefMask        = 0x08,
121   GSObjCQualifierOneWayMask       = 0x10,
122   GSObjCQualifierInvisibleMask    = 0x20
123 } GSObjCTypeQualifierMask;
124 #else
125 typedef enum GSObjCTypeQualifierMask
126 {
127   GSObjCQualifierConstMask        = _F_CONST,
128   GSObjCQualifierInMask           = _F_IN,
129   GSObjCQualifierOutMask          = _F_OUT,
130   GSObjCQualifierInOutMask        = _F_INOUT,
131   GSObjCQualifierByCopyMask       = _F_BYCOPY,
132   GSObjCQualifierByRefMask        = _F_BYREF,
133   GSObjCQualifierOneWayMask       = _F_ONEWAY,
134   GSObjCQualifierInvisibleMask    = _F_GCINVISIBLE
135 } GSObjCTypeQualifierMask;
136 #endif
137 
138 /*
139  * parser-related stuff
140  */
141 
142 typedef struct GSObjCTypeInfo {
143   /* store pointer to allow recursive parsing of pointer types, e.g. ^{^[2*]} */
144   const char  *type;
145   size_t      size;
146   uint8_t     alignment;
147   uint8_t     qualifiers;
148 } GSObjCTypeInfo;
149 
150 typedef void (*GSObjCTypeParserDelegate)(void *context, GSObjCTypeInfo type);
151 
152 typedef enum GSObjCParserOptions {
153   GSObjCReportArrayOnceMask = 1
154 } GSObjCParserOptions;
155 
156 const char *
157 GSObjCParseTypeSpecification (const char *cursor,
158                               GSObjCTypeParserDelegate delegate,
159                               void *context,
160                               unsigned options);
161 
162 GS_STATIC_INLINE size_t
GSObjCPadSize(size_t size,uint8_t alignment)163 GSObjCPadSize (size_t size, uint8_t alignment)
164 {
165   return alignment * ((size + alignment - 1) / alignment);
166 }
167 
168 GS_STATIC_INLINE size_t
GSObjCGetPadding(size_t size,uint8_t alignment)169 GSObjCGetPadding (size_t size, uint8_t alignment)
170 {
171   return (alignment - (size & (alignment - 1))) & (alignment - 1);
172 }
173 
174 const char *
175 GSGetSizeAndAlignment (const char *type, size_t *sizep, uint8_t *alignp);
176 
177 
178 #if defined (NeXT_RUNTIME)
179 
180 /* GNU API support for NeXT runtime */
181 
182 int
183 objc_sizeof_type (const char* type);
184 int
185 objc_alignof_type (const char* type);
186 int
187 objc_aligned_size (const char* type);
188 int
189 objc_promoted_size (const char* type);
190 
191 unsigned
192 objc_get_type_qualifiers (const char* type);
193 
194 const char *
195 objc_skip_typespec (const char* type);
196 const char *
197 objc_skip_offset (const char* type);
198 const char *
199 objc_skip_argspec (const char* type);
200 const char *
201 objc_skip_type_qualifiers (const char* type);
202 
203 struct objc_struct_layout
204 {
205   GSObjCTypeInfo  *info;
206   long            position;
207   unsigned        count;
208   unsigned        allocated;
209   unsigned        depth;
210   unsigned        offset;
211   unsigned        alignment;
212 };
213 
214 void
215 objc_layout_structure (const char *type,
216                        struct objc_struct_layout *layout);
217 
218 BOOL
219 objc_layout_structure_next_member (struct objc_struct_layout *layout);
220 
221 void
222 objc_layout_structure_get_info (struct objc_struct_layout *layout,
223                                 unsigned int *offset,
224                                 unsigned int *align,
225                                 const char **type);
226 
227 void
228 objc_layout_finish_structure (struct objc_struct_layout *layout,
229                               unsigned int *size,
230                               unsigned int *align);
231 
232 #endif /* NeXT_RUNTIME */
233 #endif /* GS_TYPE_ENCODING_H */
234