1/*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*	CoreFoundation_Prefix.h
25	Copyright (c) 2005-2013, Apple Inc. All rights reserved.
26*/
27
28
29#define _DARWIN_UNLIMITED_SELECT 1
30
31#include <CoreFoundation/CFBase.h>
32
33
34#include <stdlib.h>
35#include <stdint.h>
36#include <string.h>
37
38#if DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
39extern "C" {
40#endif
41
42#define SystemIntegrityCheck(A, B)	do {} while (0)
43
44
45#if INCLUDE_OBJC
46#include <objc/objc.h>
47#else
48typedef signed char	BOOL;
49typedef char * id;
50typedef char * Class;
51#define YES (BOOL)1
52#define NO (BOOL)0
53#define nil NULL
54#endif
55
56#define CRSetCrashLogMessage(A) do {} while (0)
57#define CRSetCrashLogMessage2(A) do {} while (0)
58
59#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
60#import <libkern/OSAtomic.h>
61#import <pthread.h>
62#endif
63
64/* This macro creates some helper functions which are useful in dealing with libdispatch:
65 *  __ PREFIX Queue -- manages and returns a singleton serial queue
66 *
67 * Use the macro like this:
68 *   DISPATCH_HELPER_FUNCTIONS(fh, NSFileHandle)
69 */
70
71#define DISPATCH_HELPER_FUNCTIONS(PREFIX, QNAME)			\
72static dispatch_queue_t __ ## PREFIX ## Queue(void) {			\
73    static volatile dispatch_queue_t __ ## PREFIX ## dq = NULL;		\
74    if (!__ ## PREFIX ## dq) {						\
75        dispatch_queue_t dq = dispatch_queue_create(# QNAME, NULL);	\
76        void * volatile *loc = (void * volatile *)&__ ## PREFIX ## dq;	\
77        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dq, loc)) {		\
78            dispatch_release(dq);					\
79        }								\
80    }									\
81    return __ ## PREFIX ## dq;						\
82}									\
83
84
85#define LIBAUTO_STUB	1
86
87#ifndef LIBAUTO_STUB
88
89#if DEPLOYMENT_TARGET_MACOSX
90#include <auto_zone.h>
91#endif
92#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
93#include <objc/objc-auto.h>
94#endif
95
96#endif // LIBAUTO_STUB
97
98#if DEPLOYMENT_TARGET_WINDOWS
99// Compatibility with boolean.h
100#if defined(__x86_64__)
101typedef unsigned int	boolean_t;
102#else
103typedef int		boolean_t;
104#endif
105#endif
106
107#if DEPLOYMENT_TARGET_LINUX
108
109#define CF_PRIVATE
110#define __strong
111#define __weak
112
113#define strtod_l(a,b,locale) strtod(a,b)
114#define strtoul_l(a,b,c,locale) strtoul(a,b,c)
115#define strtol_l(a,b,c,locale) strtol(a,b,c)
116#define strtoll_l(a,b,c,locale) strtoll(a,b,c)
117#define strncasecmp_l(a, b, c, d) strncasecmp(a, b, c)
118
119#define fprintf_l(a,locale,b,...) fprintf(a, b, __VA_ARGS__)
120
121#include <pthread.h>
122
123CF_INLINE size_t
124strlcpy(char * dst, const char * src, size_t maxlen) {
125    const size_t srclen = strlen(src);
126    if (srclen < maxlen) {
127        memcpy(dst, src, srclen+1);
128    } else if (maxlen != 0) {
129        memcpy(dst, src, maxlen-1);
130        dst[maxlen-1] = '\0';
131    }
132    return srclen;
133}
134
135CF_INLINE size_t
136strlcat(char * dst, const char * src, size_t maxlen) {
137    const size_t srclen = strlen(src);
138    const size_t dstlen = strnlen(dst, maxlen);
139    if (dstlen == maxlen) return maxlen+srclen;
140    if (srclen < maxlen-dstlen) {
141        memcpy(dst+dstlen, src, srclen+1);
142    } else {
143        memcpy(dst+dstlen, src, maxlen-dstlen-1);
144        dst[maxlen-1] = '\0';
145    }
146    return dstlen + srclen;
147}
148
149#define issetugid() 0
150
151// Implemented in CFPlatform.c
152bool OSAtomicCompareAndSwapPtr(void *oldp, void *newp, void *volatile *dst);
153bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst);
154bool OSAtomicCompareAndSwapPtrBarrier(void *oldp, void *newp, void *volatile *dst);
155bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
156
157int32_t OSAtomicDecrement32Barrier(volatile int32_t *dst);
158int32_t OSAtomicIncrement32Barrier(volatile int32_t *dst);
159int32_t OSAtomicIncrement32(volatile int32_t *theValue);
160int32_t OSAtomicDecrement32(volatile int32_t *theValue);
161
162int32_t OSAtomicAdd32( int32_t theAmount, volatile int32_t *theValue );
163int32_t OSAtomicAdd32Barrier( int32_t theAmount, volatile int32_t *theValue );
164bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, volatile int32_t *theValue );
165
166void OSMemoryBarrier();
167
168#include <malloc.h>
169CF_INLINE size_t malloc_size(void *memblock) {
170    return malloc_usable_size(memblock);
171}
172
173// substitute for dispatch_once
174typedef pthread_once_t dispatch_once_t;
175typedef void (^dispatch_block_t)(void);
176void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
177
178#endif
179
180#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
181#if !defined(MIN)
182#define MIN(A,B)	((A) < (B) ? (A) : (B))
183#endif
184
185#if !defined(MAX)
186#define MAX(A,B)	((A) > (B) ? (A) : (B))
187#endif
188
189#if !defined(ABS)
190#define ABS(A)	((A) < 0 ? (-(A)) : (A))
191#endif
192#endif
193
194#if DEPLOYMENT_TARGET_WINDOWS
195
196#define MAXPATHLEN MAX_PATH
197#undef MAX_PATH
198#undef INVALID_HANDLE_VALUE
199
200// Defined for source compatibility
201#define ino_t _ino_t
202#define off_t _off_t
203#define mode_t uint16_t
204
205// This works because things aren't actually exported from the DLL unless they have a __declspec(dllexport) on them... so extern by itself is closest to __private_extern__ on Mac OS
206#define CF_PRIVATE extern
207
208#define __builtin_expect(P1,P2) P1
209
210// These are replacements for POSIX calls on Windows, ensuring that the UTF8 parameters are converted to UTF16 before being passed to Windows
211CF_EXPORT int _NS_stat(const char *name, struct _stat *st);
212CF_EXPORT int _NS_mkdir(const char *name);
213CF_EXPORT int _NS_rmdir(const char *name);
214CF_EXPORT int _NS_chmod(const char *name, int mode);
215CF_EXPORT int _NS_unlink(const char *name);
216CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size);     // Warning: this doesn't support dstbuf as null even though 'getcwd' does
217CF_EXPORT char *_NS_getenv(const char *name);
218CF_EXPORT int _NS_rename(const char *oldName, const char *newName);
219CF_EXPORT int _NS_open(const char *name, int oflag, int pmode = 0);
220CF_EXPORT int _NS_chdir(const char *name);
221CF_EXPORT int _NS_mkstemp(char *name, int bufSize);
222CF_EXPORT int _NS_access(const char *name, int amode);
223
224#define BOOL WINDOWS_BOOL
225
226#define WIN32_LEAN_AND_MEAN
227
228#ifndef WINVER
229#define WINVER  0x0501
230#endif
231
232#ifndef _WIN32_WINNT
233#define _WIN32_WINNT 0x0501
234#endif
235
236// The order of these includes is important
237#define FD_SETSIZE 1024
238#include <winsock2.h>
239#include <windows.h>
240#include <pthread.h>
241
242#undef BOOL
243
244#ifndef HAVE_STRUCT_TIMESPEC
245#define HAVE_STRUCT_TIMESPEC 1
246struct timespec {
247        long tv_sec;
248        long tv_nsec;
249};
250#endif /* HAVE_STRUCT_TIMESPEC */
251
252#define __PRETTY_FUNCTION__ __FUNCTION__
253
254#define malloc_default_zone() (void *)0
255#define malloc_zone_from_ptr(a) (void *)0
256#define malloc_zone_malloc(zone,size) malloc(size)
257#define malloc_zone_memalign(zone,align,size) malloc(size)
258#define malloc_zone_calloc(zone,count,size) calloc(count,size)
259#define bcopy(b1,b2,len) memmove(b2, b1, (size_t)(len))
260typedef int malloc_zone_t;
261typedef int uid_t;
262typedef int gid_t;
263#define geteuid() 0
264#define getuid() 0
265#define getegid() 0
266
267#define scalbn(A, B) _scalb(A, B)
268
269#define fsync(a) _commit(a)
270#define malloc_create_zone(a,b) 123
271#define malloc_set_zone_name(zone,name)
272#define malloc_zone_realloc(zone,ptr,size) realloc(ptr,size)
273#define malloc_zone_free(zone,ptr) free(ptr)
274
275// implemented in CFInternal.h
276#define OSSpinLockLock(A) __CFSpinLock(A)
277#define OSSpinLockUnlock(A) __CFSpinUnlock(A)
278
279typedef int32_t OSSpinLock;
280
281#define OS_SPINLOCK_INIT       0
282
283#include <stdint.h>
284#include <stdbool.h>
285#include <stdio.h>
286#include <malloc.h>
287
288CF_INLINE size_t malloc_size(void *memblock) {
289    return _msize(memblock);
290}
291
292CF_INLINE uint64_t mach_absolute_time() {
293    LARGE_INTEGER count;
294    QueryPerformanceCounter(&count);
295    // mach_absolute_time is unsigned, but this function returns a signed value.
296    return (uint64_t)count.QuadPart;
297}
298
299CF_INLINE long long llabs(long long v) {
300    if (v < 0) return -v;
301    return v;
302}
303
304#define strtod_l(a,b,locale) strtod(a,b)
305#define strtoul_l(a,b,c,locale) strtoul(a,b,c)
306#define strtol_l(a,b,c,locale) strtol(a,b,c)
307#define strtoll_l(a,b,c,locale) _strtoi64(a,b,c)
308#define strncasecmp(a, b, c) _strnicmp(a, b, c)
309#define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c)
310#define snprintf _snprintf
311
312#define fprintf_l(a,locale,b,...) fprintf(a, b, __VA_ARGS__)
313
314CF_INLINE size_t
315strlcpy(char * dst, const char * src, size_t maxlen) {
316    const size_t srclen = strlen(src);
317    if (srclen < maxlen) {
318        memcpy(dst, src, srclen+1);
319    } else if (maxlen != 0) {
320        memcpy(dst, src, maxlen-1);
321        dst[maxlen-1] = '\0';
322    }
323    return srclen;
324}
325
326CF_INLINE size_t
327strlcat(char * dst, const char * src, size_t maxlen) {
328    const size_t srclen = strlen(src);
329    const size_t dstlen = strnlen(dst, maxlen);
330    if (dstlen == maxlen) return maxlen+srclen;
331    if (srclen < maxlen-dstlen) {
332        memcpy(dst+dstlen, src, srclen+1);
333    } else {
334        memcpy(dst+dstlen, src, maxlen-dstlen-1);
335        dst[maxlen-1] = '\0';
336    }
337    return dstlen + srclen;
338}
339
340#define sleep(x) Sleep(1000*x)
341
342#define issetugid() 0
343
344// CF exports these useful atomic operation functions on Windows
345CF_EXPORT bool OSAtomicCompareAndSwapPtr(void *oldp, void *newp, void *volatile *dst);
346CF_EXPORT bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst);
347CF_EXPORT bool OSAtomicCompareAndSwapPtrBarrier(void *oldp, void *newp, void *volatile *dst);
348
349CF_EXPORT int32_t OSAtomicDecrement32Barrier(volatile int32_t *dst);
350CF_EXPORT int32_t OSAtomicIncrement32Barrier(volatile int32_t *dst);
351CF_EXPORT int32_t OSAtomicIncrement32(volatile int32_t *theValue);
352CF_EXPORT int32_t OSAtomicDecrement32(volatile int32_t *theValue);
353
354CF_EXPORT int32_t OSAtomicAdd32( int32_t theAmount, volatile int32_t *theValue );
355CF_EXPORT int32_t OSAtomicAdd32Barrier( int32_t theAmount, volatile int32_t *theValue );
356CF_EXPORT bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, volatile int32_t *theValue );
357
358/*
359CF_EXPORT bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
360CF_EXPORT bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
361
362CF_EXPORT int64_t OSAtomicAdd64( int64_t __theAmount, volatile int64_t *__theValue );
363CF_EXPORT int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue );
364*/
365
366//#ifndef NTDDI_VERSION
367//#define NTDDI_VERSION NTDDI_WINXP
368//#endif
369
370#include <io.h>
371#include <fcntl.h>
372#include <errno.h>
373
374#endif
375
376#if !defined(CF_PRIVATE)
377#define CF_PRIVATE __attribute__((__visibility__("hidden")))
378#endif
379
380#if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS
381
382#include <stdarg.h>
383
384CF_INLINE int flsl( long mask ) {
385    int idx = 0;
386    while (mask != 0) mask = (unsigned long)mask >> 1, idx++;
387    return idx;
388}
389
390CF_INLINE int popcountll(long long x) {
391    int count = 0;
392    while (x) {
393        count++;
394        x &= x - 1; // reset LS1B
395    }
396    return count;
397}
398
399CF_PRIVATE int asprintf(char **ret, const char *format, ...);
400
401#endif
402
403#ifdef LIBAUTO_STUB
404
405#include <stddef.h>
406
407/* Stubs for functions in libauto. */
408
409enum {OBJC_GENERATIONAL = (1 << 0)};
410
411enum {
412    OBJC_RATIO_COLLECTION        = (0 << 0),
413    OBJC_GENERATIONAL_COLLECTION = (1 << 0),
414    OBJC_FULL_COLLECTION         = (2 << 0),
415    OBJC_EXHAUSTIVE_COLLECTION   = (3 << 0),
416    OBJC_COLLECT_IF_NEEDED       = (1 << 3),
417    OBJC_WAIT_UNTIL_DONE         = (1 << 4),
418};
419
420
421enum {
422    AUTO_TYPE_UNKNOWN = -1,
423    AUTO_UNSCANNED = (1 << 0),
424    AUTO_OBJECT = (1 << 1),
425    AUTO_POINTERS_ONLY = (1 << 2),
426    AUTO_MEMORY_SCANNED = !AUTO_UNSCANNED,
427    AUTO_MEMORY_UNSCANNED = AUTO_UNSCANNED,
428    AUTO_MEMORY_ALL_POINTERS = AUTO_POINTERS_ONLY,
429    AUTO_MEMORY_ALL_WEAK_POINTERS = (AUTO_UNSCANNED | AUTO_POINTERS_ONLY),
430    AUTO_OBJECT_SCANNED = AUTO_OBJECT,
431    AUTO_OBJECT_UNSCANNED = AUTO_OBJECT | AUTO_UNSCANNED,
432    AUTO_OBJECT_ALL_POINTERS = AUTO_OBJECT | AUTO_POINTERS_ONLY
433};
434typedef unsigned long auto_memory_type_t;
435typedef struct _auto_zone_t auto_zone_t;
436typedef struct auto_weak_callback_block {
437    struct auto_weak_callback_block *next;
438    void (*callback_function)(void *arg1, void *arg2);
439    void *arg1;
440    void *arg2;
441} auto_weak_callback_block_t;
442
443CF_INLINE void *objc_memmove_collectable(void *a, const void *b, size_t c) { return memmove(a, b, c); }
444CF_INLINE void *objc_collectableZone(void) { return 0; }
445
446CF_INLINE void *auto_zone_allocate_object(void *zone, size_t size, auto_memory_type_t type, int rc, int clear) { return 0; }
447CF_INLINE const void *auto_zone_base_pointer(void *zone, const void *ptr) { return 0; }
448CF_INLINE void auto_zone_set_scan_exactly(void *zone, void *ptr) {}
449CF_INLINE void auto_zone_retain(void *zone, void *ptr) {}
450CF_INLINE unsigned int auto_zone_release(void *zone, void *ptr) { return 0; }
451CF_INLINE unsigned int auto_zone_retain_count(void *zone, const void *ptr) { return 0; }
452CF_INLINE void auto_zone_set_unscanned(void *zone, void *ptr) {}
453CF_INLINE void auto_zone_set_nofinalize(void *zone, void *ptr) {}
454CF_INLINE int auto_zone_is_finalized(void *zone, const void *ptr) { return 0; }
455CF_INLINE size_t auto_zone_size(void *zone, const void *ptr) { return 0; }
456CF_INLINE void auto_register_weak_reference(void *zone, const void *referent, void **referrer, uintptr_t *counter, void **listHead, void **listElement) {}
457CF_INLINE void auto_unregister_weak_reference(void *zone, const void *referent, void **referrer) {}
458CF_INLINE int auto_zone_is_valid_pointer(void *zone, const void *ptr) { return 0; }
459CF_INLINE BOOL objc_isAuto(id object) { return 0; }
460CF_INLINE void* auto_read_weak_reference(void *zone, void **referrer) { void *result = *referrer; return result; }
461CF_INLINE void auto_assign_weak_reference(void *zone, const void *value, const void **location, auto_weak_callback_block_t *block) { *location = (void *)value; }
462CF_INLINE auto_memory_type_t auto_zone_get_layout_type(void *zone, void *ptr) { return AUTO_UNSCANNED; }
463CF_INLINE int auto_zone_set_write_barrier(void *zone, const void *dest, const void *new_value) { return false; }
464
465CF_INLINE void objc_assertRegisteredThreadWithCollector(void) {}
466CF_INLINE void objc_registerThreadWithCollector(void) {}
467
468CF_INLINE uintptr_t _object_getExternalHash(id obj) {
469    return (uintptr_t)obj;
470}
471
472// from objc-auto.h
473
474CF_INLINE BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation)
475{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
476
477CF_INLINE BOOL objc_atomicCompareAndSwapPtrBarrier(id predicate, id replacement, volatile id *objectLocation)
478{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
479
480CF_INLINE BOOL objc_atomicCompareAndSwapGlobal(id predicate, id replacement, volatile id *objectLocation)
481{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
482
483CF_INLINE BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate, id replacement, volatile id *objectLocation)
484{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
485
486CF_INLINE BOOL objc_atomicCompareAndSwapInstanceVariable(id predicate, id replacement, volatile id *objectLocation)
487{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
488
489CF_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate, id replacement, volatile id *objectLocation)
490{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
491
492CF_INLINE id objc_assign_strongCast(id val, id *dest)
493{ return (*dest = val); }
494
495CF_INLINE id objc_assign_global(id val, id *dest)
496{ return (*dest = val); }
497
498CF_INLINE id objc_assign_ivar(id val, id dest, ptrdiff_t offset)
499{ return (*(id*)((char *)dest+offset) = val); }
500
501//CF_INLINE void *objc_memmove_collectable(void *dst, const void *src, size_t size) { return memmove(dst, src, size); }
502
503CF_INLINE id objc_read_weak(id *location)
504{ return *location; }
505
506CF_INLINE id objc_assign_weak(id value, id *location)
507{ return (*location = value); }
508
509
510CF_INLINE void objc_finalizeOnMainThread(Class cls) { }
511CF_INLINE BOOL objc_is_finalized(void *ptr) { return NO; }
512CF_INLINE void objc_clear_stack(unsigned long options) { }
513
514CF_INLINE BOOL objc_collectingEnabled(void) { return NO; }
515CF_INLINE void objc_start_collector_thread(void) { }
516
517CF_INLINE void objc_collect(unsigned long options) { }
518
519#endif
520
521#if DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
522} // extern "C"
523#endif
524