rugged 0.24.6.1 → 0.25.0b1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_repo.c +44 -36
  3. data/lib/rugged/version.rb +1 -1
  4. data/vendor/libgit2/CMakeLists.txt +10 -21
  5. data/vendor/libgit2/include/git2/checkout.h +0 -7
  6. data/vendor/libgit2/include/git2/commit.h +46 -0
  7. data/vendor/libgit2/include/git2/common.h +1 -16
  8. data/vendor/libgit2/include/git2/odb.h +47 -1
  9. data/vendor/libgit2/include/git2/version.h +2 -2
  10. data/vendor/libgit2/src/array.h +0 -40
  11. data/vendor/libgit2/src/blame.c +3 -8
  12. data/vendor/libgit2/src/blame_git.c +9 -20
  13. data/vendor/libgit2/src/checkout.c +5 -13
  14. data/vendor/libgit2/src/commit.c +132 -52
  15. data/vendor/libgit2/src/common.h +1 -1
  16. data/vendor/libgit2/src/config_cache.c +1 -2
  17. data/vendor/libgit2/src/config_file.c +20 -14
  18. data/vendor/libgit2/src/delta-apply.c +5 -36
  19. data/vendor/libgit2/src/delta-apply.h +0 -12
  20. data/vendor/libgit2/src/describe.c +1 -2
  21. data/vendor/libgit2/src/diff_tform.c +3 -5
  22. data/vendor/libgit2/src/filebuf.c +1 -6
  23. data/vendor/libgit2/src/global.c +8 -28
  24. data/vendor/libgit2/src/global.h +0 -1
  25. data/vendor/libgit2/src/ignore.c +19 -56
  26. data/vendor/libgit2/src/index.c +8 -27
  27. data/vendor/libgit2/src/indexer.c +7 -11
  28. data/vendor/libgit2/src/iterator.c +2 -2
  29. data/vendor/libgit2/src/merge.c +0 -1
  30. data/vendor/libgit2/src/mwindow.c +19 -8
  31. data/vendor/libgit2/src/mwindow.h +2 -1
  32. data/vendor/libgit2/src/object.c +6 -3
  33. data/vendor/libgit2/src/odb.c +188 -48
  34. data/vendor/libgit2/src/odb_loose.c +1 -1
  35. data/vendor/libgit2/src/odb_pack.c +3 -0
  36. data/vendor/libgit2/src/openssl_stream.c +27 -60
  37. data/vendor/libgit2/src/openssl_stream.h +0 -106
  38. data/vendor/libgit2/src/pack-objects.c +2 -4
  39. data/vendor/libgit2/src/pack.c +9 -5
  40. data/vendor/libgit2/src/posix.c +0 -7
  41. data/vendor/libgit2/src/posix.h +0 -1
  42. data/vendor/libgit2/src/push.c +6 -6
  43. data/vendor/libgit2/src/refdb_fs.c +0 -1
  44. data/vendor/libgit2/src/refs.c +0 -3
  45. data/vendor/libgit2/src/refspec.c +2 -4
  46. data/vendor/libgit2/src/remote.c +5 -15
  47. data/vendor/libgit2/src/repository.c +21 -29
  48. data/vendor/libgit2/src/settings.c +1 -23
  49. data/vendor/libgit2/src/stransport_stream.c +9 -15
  50. data/vendor/libgit2/src/submodule.c +2 -3
  51. data/vendor/libgit2/src/sysdir.c +47 -41
  52. data/vendor/libgit2/src/sysdir.h +5 -0
  53. data/vendor/libgit2/src/tag.c +2 -8
  54. data/vendor/libgit2/src/thread-utils.h +51 -5
  55. data/vendor/libgit2/src/transports/http.c +3 -3
  56. data/vendor/libgit2/src/transports/smart_pkt.c +4 -13
  57. data/vendor/libgit2/src/transports/smart_protocol.c +17 -61
  58. data/vendor/libgit2/src/tree.c +100 -83
  59. data/vendor/libgit2/src/tree.h +5 -4
  60. data/vendor/libgit2/src/unix/map.c +0 -5
  61. data/vendor/libgit2/src/util.c +3 -3
  62. data/vendor/libgit2/src/win32/map.c +5 -24
  63. data/vendor/libgit2/src/win32/precompiled.h +1 -1
  64. data/vendor/libgit2/src/win32/{thread.c → pthread.c} +80 -50
  65. data/vendor/libgit2/src/win32/pthread.h +92 -0
  66. data/vendor/libgit2/src/xdiff/xprepare.c +1 -2
  67. metadata +7 -8
  68. data/vendor/libgit2/src/unix/pthread.h +0 -54
  69. data/vendor/libgit2/src/win32/thread.h +0 -62
@@ -17,14 +17,15 @@
17
17
  struct git_tree_entry {
18
18
  uint16_t attr;
19
19
  uint16_t filename_len;
20
- const git_oid *oid;
21
- const char *filename;
20
+ git_oid oid;
21
+ bool pooled;
22
+ char filename[GIT_FLEX_ARRAY];
22
23
  };
23
24
 
24
25
  struct git_tree {
25
26
  git_object object;
26
- git_odb_object *odb_obj;
27
- git_array_t(git_tree_entry) entries;
27
+ git_vector entries;
28
+ git_pool pool;
28
29
  };
29
30
 
30
31
  struct git_treebuilder {
@@ -24,11 +24,6 @@ int git__page_size(size_t *page_size)
24
24
  return 0;
25
25
  }
26
26
 
27
- int git__mmap_alignment(size_t *alignment)
28
- {
29
- return git__page_size(alignment);
30
- }
31
-
32
27
  int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
33
28
  {
34
29
  int mprot = PROT_READ;
@@ -122,8 +122,8 @@ int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int ba
122
122
  v = c - 'A' + 10;
123
123
  if (v >= base)
124
124
  break;
125
- nn = n * base + (neg ? -v : v);
126
- if ((!neg && nn < n) || (neg && nn > n))
125
+ nn = n*base + v;
126
+ if (nn < n)
127
127
  ovfl = 1;
128
128
  n = nn;
129
129
  }
@@ -142,7 +142,7 @@ Return:
142
142
  return -1;
143
143
  }
144
144
 
145
- *result = n;
145
+ *result = neg ? -n : n;
146
146
  return 0;
147
147
  }
148
148
 
@@ -17,41 +17,22 @@ static DWORD get_page_size(void)
17
17
 
18
18
  if (!page_size) {
19
19
  GetSystemInfo(&sys);
20
- page_size = sys.dwPageSize;
20
+ page_size = sys.dwAllocationGranularity;
21
21
  }
22
22
 
23
23
  return page_size;
24
24
  }
25
25
 
26
- static DWORD get_allocation_granularity(void)
27
- {
28
- static DWORD granularity;
29
- SYSTEM_INFO sys;
30
-
31
- if (!granularity) {
32
- GetSystemInfo(&sys);
33
- granularity = sys.dwAllocationGranularity;
34
- }
35
-
36
- return granularity;
37
- }
38
-
39
26
  int git__page_size(size_t *page_size)
40
27
  {
41
28
  *page_size = get_page_size();
42
29
  return 0;
43
30
  }
44
31
 
45
- int git__mmap_alignment(size_t *page_size)
46
- {
47
- *page_size = get_allocation_granularity();
48
- return 0;
49
- }
50
-
51
32
  int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
52
33
  {
53
34
  HANDLE fh = (HANDLE)_get_osfhandle(fd);
54
- DWORD alignment = get_allocation_granularity();
35
+ DWORD page_size = get_page_size();
55
36
  DWORD fmap_prot = 0;
56
37
  DWORD view_prot = 0;
57
38
  DWORD off_low = 0;
@@ -81,12 +62,12 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
81
62
  if (prot & GIT_PROT_READ)
82
63
  view_prot |= FILE_MAP_READ;
83
64
 
84
- page_start = (offset / alignment) * alignment;
65
+ page_start = (offset / page_size) * page_size;
85
66
  page_offset = offset - page_start;
86
67
 
87
- if (page_offset != 0) { /* offset must be multiple of the allocation granularity */
68
+ if (page_offset != 0) { /* offset must be multiple of page size */
88
69
  errno = EINVAL;
89
- giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of allocation granularity");
70
+ giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of page size");
90
71
  return -1;
91
72
  }
92
73
 
@@ -16,7 +16,7 @@
16
16
  #include <io.h>
17
17
  #include <direct.h>
18
18
  #ifdef GIT_THREADS
19
- #include "win32/thread.h"
19
+ #include "win32/pthread.h"
20
20
  #endif
21
21
 
22
22
  #include "git2.h"
@@ -5,26 +5,18 @@
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
 
8
- #include "thread.h"
8
+ #include "pthread.h"
9
9
  #include "../global.h"
10
10
 
11
11
  #define CLEAN_THREAD_EXIT 0x6F012842
12
12
 
13
- typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
14
-
15
- static win32_srwlock_fn win32_srwlock_initialize;
16
- static win32_srwlock_fn win32_srwlock_acquire_shared;
17
- static win32_srwlock_fn win32_srwlock_release_shared;
18
- static win32_srwlock_fn win32_srwlock_acquire_exclusive;
19
- static win32_srwlock_fn win32_srwlock_release_exclusive;
20
-
21
13
  /* The thread procedure stub used to invoke the caller's procedure
22
14
  * and capture the return value for later collection. Windows will
23
15
  * only hold a DWORD, but we need to be able to store an entire
24
16
  * void pointer. This requires the indirection. */
25
17
  static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
26
18
  {
27
- git_thread *thread = lpParameter;
19
+ git_win32_thread *thread = lpParameter;
28
20
 
29
21
  thread->result = thread->proc(thread->param);
30
22
 
@@ -33,31 +25,14 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
33
25
  return CLEAN_THREAD_EXIT;
34
26
  }
35
27
 
36
- int git_threads_init(void)
37
- {
38
- HMODULE hModule = GetModuleHandleW(L"kernel32");
39
-
40
- if (hModule) {
41
- win32_srwlock_initialize = (win32_srwlock_fn)
42
- GetProcAddress(hModule, "InitializeSRWLock");
43
- win32_srwlock_acquire_shared = (win32_srwlock_fn)
44
- GetProcAddress(hModule, "AcquireSRWLockShared");
45
- win32_srwlock_release_shared = (win32_srwlock_fn)
46
- GetProcAddress(hModule, "ReleaseSRWLockShared");
47
- win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
48
- GetProcAddress(hModule, "AcquireSRWLockExclusive");
49
- win32_srwlock_release_exclusive = (win32_srwlock_fn)
50
- GetProcAddress(hModule, "ReleaseSRWLockExclusive");
51
- }
52
-
53
- return 0;
54
- }
55
-
56
- int git_thread_create(
57
- git_thread *GIT_RESTRICT thread,
28
+ int git_win32__thread_create(
29
+ git_win32_thread *GIT_RESTRICT thread,
30
+ const pthread_attr_t *GIT_RESTRICT attr,
58
31
  void *(*start_routine)(void*),
59
32
  void *GIT_RESTRICT arg)
60
33
  {
34
+ GIT_UNUSED(attr);
35
+
61
36
  thread->result = NULL;
62
37
  thread->param = arg;
63
38
  thread->proc = start_routine;
@@ -67,8 +42,8 @@ int git_thread_create(
67
42
  return thread->thread ? 0 : -1;
68
43
  }
69
44
 
70
- int git_thread_join(
71
- git_thread *thread,
45
+ int git_win32__thread_join(
46
+ git_win32_thread *thread,
72
47
  void **value_ptr)
73
48
  {
74
49
  DWORD exit;
@@ -95,32 +70,39 @@ int git_thread_join(
95
70
  return 0;
96
71
  }
97
72
 
98
- int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
73
+ int pthread_mutex_init(
74
+ pthread_mutex_t *GIT_RESTRICT mutex,
75
+ const pthread_mutexattr_t *GIT_RESTRICT mutexattr)
99
76
  {
77
+ GIT_UNUSED(mutexattr);
100
78
  InitializeCriticalSection(mutex);
101
79
  return 0;
102
80
  }
103
81
 
104
- int git_mutex_free(git_mutex *mutex)
82
+ int pthread_mutex_destroy(pthread_mutex_t *mutex)
105
83
  {
106
84
  DeleteCriticalSection(mutex);
107
85
  return 0;
108
86
  }
109
87
 
110
- int git_mutex_lock(git_mutex *mutex)
88
+ int pthread_mutex_lock(pthread_mutex_t *mutex)
111
89
  {
112
90
  EnterCriticalSection(mutex);
113
91
  return 0;
114
92
  }
115
93
 
116
- int git_mutex_unlock(git_mutex *mutex)
94
+ int pthread_mutex_unlock(pthread_mutex_t *mutex)
117
95
  {
118
96
  LeaveCriticalSection(mutex);
119
97
  return 0;
120
98
  }
121
99
 
122
- int git_cond_init(git_cond *cond)
100
+ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
123
101
  {
102
+ /* We don't support non-default attributes. */
103
+ if (attr)
104
+ return EINVAL;
105
+
124
106
  /* This is an auto-reset event. */
125
107
  *cond = CreateEventW(NULL, FALSE, FALSE, NULL);
126
108
  assert(*cond);
@@ -130,7 +112,7 @@ int git_cond_init(git_cond *cond)
130
112
  return *cond ? 0 : ENOMEM;
131
113
  }
132
114
 
133
- int git_cond_free(git_cond *cond)
115
+ int pthread_cond_destroy(pthread_cond_t *cond)
134
116
  {
135
117
  BOOL closed;
136
118
 
@@ -145,7 +127,7 @@ int git_cond_free(git_cond *cond)
145
127
  return 0;
146
128
  }
147
129
 
148
- int git_cond_wait(git_cond *cond, git_mutex *mutex)
130
+ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
149
131
  {
150
132
  int error;
151
133
  DWORD wait_result;
@@ -154,7 +136,7 @@ int git_cond_wait(git_cond *cond, git_mutex *mutex)
154
136
  return EINVAL;
155
137
 
156
138
  /* The caller must be holding the mutex. */
157
- error = git_mutex_unlock(mutex);
139
+ error = pthread_mutex_unlock(mutex);
158
140
 
159
141
  if (error)
160
142
  return error;
@@ -163,10 +145,10 @@ int git_cond_wait(git_cond *cond, git_mutex *mutex)
163
145
  assert(WAIT_OBJECT_0 == wait_result);
164
146
  GIT_UNUSED(wait_result);
165
147
 
166
- return git_mutex_lock(mutex);
148
+ return pthread_mutex_lock(mutex);
167
149
  }
168
150
 
169
- int git_cond_signal(git_cond *cond)
151
+ int pthread_cond_signal(pthread_cond_t *cond)
170
152
  {
171
153
  BOOL signaled;
172
154
 
@@ -180,8 +162,36 @@ int git_cond_signal(git_cond *cond)
180
162
  return 0;
181
163
  }
182
164
 
183
- int git_rwlock_init(git_rwlock *GIT_RESTRICT lock)
165
+ /* pthread_cond_broadcast is not implemented because doing so with just
166
+ * Win32 events is quite complicated, and no caller in libgit2 uses it
167
+ * yet.
168
+ */
169
+ int pthread_num_processors_np(void)
170
+ {
171
+ DWORD_PTR p, s;
172
+ int n = 0;
173
+
174
+ if (GetProcessAffinityMask(GetCurrentProcess(), &p, &s))
175
+ for (; p; p >>= 1)
176
+ n += p&1;
177
+
178
+ return n ? n : 1;
179
+ }
180
+
181
+ typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
182
+
183
+ static win32_srwlock_fn win32_srwlock_initialize;
184
+ static win32_srwlock_fn win32_srwlock_acquire_shared;
185
+ static win32_srwlock_fn win32_srwlock_release_shared;
186
+ static win32_srwlock_fn win32_srwlock_acquire_exclusive;
187
+ static win32_srwlock_fn win32_srwlock_release_exclusive;
188
+
189
+ int pthread_rwlock_init(
190
+ pthread_rwlock_t *GIT_RESTRICT lock,
191
+ const pthread_rwlockattr_t *GIT_RESTRICT attr)
184
192
  {
193
+ GIT_UNUSED(attr);
194
+
185
195
  if (win32_srwlock_initialize)
186
196
  win32_srwlock_initialize(&lock->native.srwl);
187
197
  else
@@ -190,7 +200,7 @@ int git_rwlock_init(git_rwlock *GIT_RESTRICT lock)
190
200
  return 0;
191
201
  }
192
202
 
193
- int git_rwlock_rdlock(git_rwlock *lock)
203
+ int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
194
204
  {
195
205
  if (win32_srwlock_acquire_shared)
196
206
  win32_srwlock_acquire_shared(&lock->native.srwl);
@@ -200,7 +210,7 @@ int git_rwlock_rdlock(git_rwlock *lock)
200
210
  return 0;
201
211
  }
202
212
 
203
- int git_rwlock_rdunlock(git_rwlock *lock)
213
+ int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
204
214
  {
205
215
  if (win32_srwlock_release_shared)
206
216
  win32_srwlock_release_shared(&lock->native.srwl);
@@ -210,7 +220,7 @@ int git_rwlock_rdunlock(git_rwlock *lock)
210
220
  return 0;
211
221
  }
212
222
 
213
- int git_rwlock_wrlock(git_rwlock *lock)
223
+ int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
214
224
  {
215
225
  if (win32_srwlock_acquire_exclusive)
216
226
  win32_srwlock_acquire_exclusive(&lock->native.srwl);
@@ -220,7 +230,7 @@ int git_rwlock_wrlock(git_rwlock *lock)
220
230
  return 0;
221
231
  }
222
232
 
223
- int git_rwlock_wrunlock(git_rwlock *lock)
233
+ int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
224
234
  {
225
235
  if (win32_srwlock_release_exclusive)
226
236
  win32_srwlock_release_exclusive(&lock->native.srwl);
@@ -230,10 +240,30 @@ int git_rwlock_wrunlock(git_rwlock *lock)
230
240
  return 0;
231
241
  }
232
242
 
233
- int git_rwlock_free(git_rwlock *lock)
243
+ int pthread_rwlock_destroy(pthread_rwlock_t *lock)
234
244
  {
235
245
  if (!win32_srwlock_initialize)
236
246
  DeleteCriticalSection(&lock->native.csec);
237
247
  git__memzero(lock, sizeof(*lock));
238
248
  return 0;
239
249
  }
250
+
251
+ int win32_pthread_initialize(void)
252
+ {
253
+ HMODULE hModule = GetModuleHandleW(L"kernel32");
254
+
255
+ if (hModule) {
256
+ win32_srwlock_initialize = (win32_srwlock_fn)
257
+ GetProcAddress(hModule, "InitializeSRWLock");
258
+ win32_srwlock_acquire_shared = (win32_srwlock_fn)
259
+ GetProcAddress(hModule, "AcquireSRWLockShared");
260
+ win32_srwlock_release_shared = (win32_srwlock_fn)
261
+ GetProcAddress(hModule, "ReleaseSRWLockShared");
262
+ win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
263
+ GetProcAddress(hModule, "AcquireSRWLockExclusive");
264
+ win32_srwlock_release_exclusive = (win32_srwlock_fn)
265
+ GetProcAddress(hModule, "ReleaseSRWLockExclusive");
266
+ }
267
+
268
+ return 0;
269
+ }
@@ -0,0 +1,92 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #ifndef GIT_PTHREAD_H
9
+ #define GIT_PTHREAD_H
10
+
11
+ #include "../common.h"
12
+
13
+ #if defined (_MSC_VER)
14
+ # define GIT_RESTRICT __restrict
15
+ #else
16
+ # define GIT_RESTRICT __restrict__
17
+ #endif
18
+
19
+ typedef struct {
20
+ HANDLE thread;
21
+ void *(*proc)(void *);
22
+ void *param;
23
+ void *result;
24
+ } git_win32_thread;
25
+
26
+ typedef int pthread_mutexattr_t;
27
+ typedef int pthread_condattr_t;
28
+ typedef int pthread_attr_t;
29
+ typedef int pthread_rwlockattr_t;
30
+
31
+ typedef CRITICAL_SECTION pthread_mutex_t;
32
+ typedef HANDLE pthread_cond_t;
33
+
34
+ typedef struct { void *Ptr; } GIT_SRWLOCK;
35
+
36
+ typedef struct {
37
+ union {
38
+ GIT_SRWLOCK srwl;
39
+ CRITICAL_SECTION csec;
40
+ } native;
41
+ } pthread_rwlock_t;
42
+
43
+ #define PTHREAD_MUTEX_INITIALIZER {(void*)-1}
44
+
45
+ int git_win32__thread_create(
46
+ git_win32_thread *GIT_RESTRICT,
47
+ const pthread_attr_t *GIT_RESTRICT,
48
+ void *(*) (void *),
49
+ void *GIT_RESTRICT);
50
+
51
+ int git_win32__thread_join(
52
+ git_win32_thread *,
53
+ void **);
54
+
55
+ #ifdef GIT_THREADS
56
+
57
+ typedef git_win32_thread git_thread;
58
+
59
+ #define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
60
+ git_win32__thread_create(git_thread_ptr, attr, start_routine, arg)
61
+ #define git_thread_join(git_thread_ptr, status) \
62
+ git_win32__thread_join(git_thread_ptr, status)
63
+
64
+ #endif
65
+
66
+ int pthread_mutex_init(
67
+ pthread_mutex_t *GIT_RESTRICT mutex,
68
+ const pthread_mutexattr_t *GIT_RESTRICT mutexattr);
69
+ int pthread_mutex_destroy(pthread_mutex_t *);
70
+ int pthread_mutex_lock(pthread_mutex_t *);
71
+ int pthread_mutex_unlock(pthread_mutex_t *);
72
+
73
+ int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
74
+ int pthread_cond_destroy(pthread_cond_t *);
75
+ int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
76
+ int pthread_cond_signal(pthread_cond_t *);
77
+ /* pthread_cond_broadcast is not supported on Win32 yet. */
78
+
79
+ int pthread_num_processors_np(void);
80
+
81
+ int pthread_rwlock_init(
82
+ pthread_rwlock_t *GIT_RESTRICT lock,
83
+ const pthread_rwlockattr_t *GIT_RESTRICT attr);
84
+ int pthread_rwlock_rdlock(pthread_rwlock_t *);
85
+ int pthread_rwlock_rdunlock(pthread_rwlock_t *);
86
+ int pthread_rwlock_wrlock(pthread_rwlock_t *);
87
+ int pthread_rwlock_wrunlock(pthread_rwlock_t *);
88
+ int pthread_rwlock_destroy(pthread_rwlock_t *);
89
+
90
+ extern int win32_pthread_initialize(void);
91
+
92
+ #endif