1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #if __GNUC__ >= 3
19 @PRAGMA_SYSTEM_HEADER@
20 #endif
21 @PRAGMA_COLUMNS@
22
23 #ifndef _@GUARD_PREFIX@_THREADS_H
24
25
26 #if @HAVE_THREADS_H@
27 # @INCLUDE_NEXT@ @NEXT_THREADS_H@
28 #endif
29
30 #ifndef _@GUARD_PREFIX@_THREADS_H
31 #define _@GUARD_PREFIX@_THREADS_H
32
33 #if !@HAVE_THREADS_H@
34
35 # include <time.h>
36
37 # if defined _WIN32 && ! defined __CYGWIN__
38
39
40 # define WIN32_LEAN_AND_MEAN
41 # include <windows.h>
42
43 # else
44
45
46 # include <pthread.h>
47
48 # endif
49
50 #endif
51
52
53
54 #ifndef _GL_ATTRIBUTE_PURE
55 # if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
56 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
57 # else
58 # define _GL_ATTRIBUTE_PURE
59 # endif
60 #endif
61
62
63
64
65
66
67
68
69
70
71
72 #ifdef _AIX
73
74
75 # undef thread_local
76 #endif
77 #if !@HAVE_THREADS_H@ || !defined thread_local
78 # define thread_local _Thread_local
79 #endif
80
81 #if !@HAVE_THREAD_LOCAL@
82 # undef thread_local
83 #endif
84
85
86
87
88 #if !@HAVE_THREADS_H@
89
90
91 enum
92 {
93 thrd_success = 0,
94 thrd_timedout = 1,
95 thrd_busy = 2,
96 thrd_nomem = 3,
97 thrd_error = 4
98 };
99
100 # if defined _WIN32 && ! defined __CYGWIN__
101
102
103 # include "windows-thread.h"
104
105 typedef glwthread_thread_t thrd_t;
106
107 # else
108
109
110 typedef pthread_t thrd_t;
111
112 # endif
113
114 #endif
115
116 #if @BROKEN_THRD_START_T@
117
118 # define thrd_start_t rpl_thrd_start_t
119
120 struct thrd_with_exitcode
121 {
122 thrd_t volatile tid;
123 int volatile detached;
124 int volatile exitcode;
125 };
126 typedef struct thrd_with_exitcode *rpl_thrd_t;
127 # define thrd_t rpl_thrd_t
128 #endif
129
130 #if !@HAVE_THREADS_H@ || @BROKEN_THRD_START_T@
131 typedef int (* thrd_start_t) (void *);
132 #endif
133
134 #if @GNULIB_THRD@
135 # if @REPLACE_THRD_CREATE@
136 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
137 # define thrd_create rpl_thrd_create
138 # endif
139 _GL_FUNCDECL_RPL (thrd_create, int, (thrd_t *, thrd_start_t, void *)
140 _GL_ARG_NONNULL ((1, 2)));
141 _GL_CXXALIAS_RPL (thrd_create, int, (thrd_t *, thrd_start_t, void *));
142 # else
143 # if !@HAVE_THREADS_H@
144 _GL_FUNCDECL_SYS (thrd_create, int, (thrd_t *, thrd_start_t, void *)
145 _GL_ARG_NONNULL ((1, 2)));
146 # endif
147 _GL_CXXALIAS_SYS (thrd_create, int, (thrd_t *, thrd_start_t, void *));
148 # endif
149 _GL_CXXALIASWARN (thrd_create);
150 #elif defined GNULIB_POSIXCHECK
151 # undef thrd_create
152 # if HAVE_RAW_DECL_THRD_CREATE
153 _GL_WARN_ON_USE (thrd_create, "thrd_create is unportable - "
154 "use gnulib module thrd for portability");
155 # endif
156 #endif
157
158 #if @GNULIB_THRD@
159 # if @REPLACE_THRD_CURRENT@
160 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
161 # define thrd_current rpl_thrd_current
162 # endif
163 _GL_FUNCDECL_RPL (thrd_current, thrd_t, (void) _GL_ATTRIBUTE_PURE);
164 _GL_CXXALIAS_RPL (thrd_current, thrd_t, (void));
165 # else
166 # if !@HAVE_THREADS_H@
167 _GL_FUNCDECL_SYS (thrd_current, thrd_t, (void) _GL_ATTRIBUTE_PURE);
168 # endif
169 _GL_CXXALIAS_SYS (thrd_current, thrd_t, (void));
170 # endif
171 _GL_CXXALIASWARN (thrd_current);
172 #elif defined GNULIB_POSIXCHECK
173 # undef thrd_current
174 # if HAVE_RAW_DECL_THRD_CURRENT
175 _GL_WARN_ON_USE (thrd_current, "thrd_current is unportable - "
176 "use gnulib module thrd for portability");
177 # endif
178 #endif
179
180 #if @GNULIB_THRD@
181 # if @REPLACE_THRD_EQUAL@
182 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
183 # define thrd_equal rpl_thrd_equal
184 # endif
185 _GL_FUNCDECL_RPL (thrd_equal, int, (thrd_t, thrd_t) _GL_ATTRIBUTE_PURE);
186 _GL_CXXALIAS_RPL (thrd_equal, int, (thrd_t, thrd_t));
187 # else
188 # if !@HAVE_THREADS_H@
189 _GL_FUNCDECL_SYS (thrd_equal, int, (thrd_t, thrd_t) _GL_ATTRIBUTE_PURE);
190 # endif
191 _GL_CXXALIAS_SYS (thrd_equal, int, (thrd_t, thrd_t));
192 # endif
193 _GL_CXXALIASWARN (thrd_equal);
194 #elif defined GNULIB_POSIXCHECK
195 # undef thrd_equal
196 # if HAVE_RAW_DECL_THRD_EQUAL
197 _GL_WARN_ON_USE (thrd_equal, "thrd_equal is unportable - "
198 "use gnulib module thrd for portability");
199 # endif
200 #endif
201
202 #if @GNULIB_THRD@
203 # if !@HAVE_THREADS_H@
204 _GL_FUNCDECL_SYS (thrd_sleep, int,
205 (const struct timespec *, struct timespec *)
206 _GL_ARG_NONNULL ((1)));
207 # endif
208 _GL_CXXALIAS_SYS (thrd_sleep, int,
209 (const struct timespec *, struct timespec *));
210 _GL_CXXALIASWARN (thrd_sleep);
211 #elif defined GNULIB_POSIXCHECK
212 # undef thrd_sleep
213 # if HAVE_RAW_DECL_THRD_SLEEP
214 _GL_WARN_ON_USE (thrd_sleep, "thrd_sleep is unportable - "
215 "use gnulib module thrd for portability");
216 # endif
217 #endif
218
219 #if @GNULIB_THRD@
220 # if !@HAVE_THREADS_H@
221 _GL_FUNCDECL_SYS (thrd_yield, void, (void));
222 # endif
223 _GL_CXXALIAS_SYS (thrd_yield, void, (void));
224 _GL_CXXALIASWARN (thrd_yield);
225 #elif defined GNULIB_POSIXCHECK
226 # undef thrd_yield
227 # if HAVE_RAW_DECL_THRD_YIELD
228 _GL_WARN_ON_USE (thrd_yield, "thrd_yield is unportable - "
229 "use gnulib module thrd for portability");
230 # endif
231 #endif
232
233 #if @GNULIB_THRD@
234 # if @REPLACE_THRD_DETACH@
235 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
236 # define thrd_detach rpl_thrd_detach
237 # endif
238 _GL_FUNCDECL_RPL (thrd_detach, int, (thrd_t));
239 _GL_CXXALIAS_RPL (thrd_detach, int, (thrd_t));
240 # else
241 # if !@HAVE_THREADS_H@
242 _GL_FUNCDECL_SYS (thrd_detach, int, (thrd_t));
243 # endif
244 _GL_CXXALIAS_SYS (thrd_detach, int, (thrd_t));
245 # endif
246 _GL_CXXALIASWARN (thrd_detach);
247 #elif defined GNULIB_POSIXCHECK
248 # undef thrd_detach
249 # if HAVE_RAW_DECL_THRD_DETACH
250 _GL_WARN_ON_USE (thrd_detach, "thrd_detach is unportable - "
251 "use gnulib module thrd for portability");
252 # endif
253 #endif
254
255 #if @GNULIB_THRD@
256 # if @REPLACE_THRD_JOIN@
257 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
258 # define thrd_join rpl_thrd_join
259 # endif
260 _GL_FUNCDECL_RPL (thrd_join, int, (thrd_t, int *));
261 _GL_CXXALIAS_RPL (thrd_join, int, (thrd_t, int *));
262 # else
263 # if !@HAVE_THREADS_H@
264 _GL_FUNCDECL_SYS (thrd_join, int, (thrd_t, int *));
265 # endif
266 _GL_CXXALIAS_SYS (thrd_join, int, (thrd_t, int *));
267 # endif
268 _GL_CXXALIASWARN (thrd_join);
269 #elif defined GNULIB_POSIXCHECK
270 # undef thrd_join
271 # if HAVE_RAW_DECL_THRD_JOIN
272 _GL_WARN_ON_USE (thrd_join, "thrd_join is unportable - "
273 "use gnulib module thrd for portability");
274 # endif
275 #endif
276
277 #if @GNULIB_THRD@
278 # if !@HAVE_THREADS_H@
279 _GL_FUNCDECL_SYS (thrd_exit, _Noreturn void, (int));
280 # endif
281
282 _GL_CXXALIAS_SYS_CAST (thrd_exit, void, (int));
283 _GL_CXXALIASWARN (thrd_exit);
284 #elif defined GNULIB_POSIXCHECK
285 # undef thrd_exit
286 # if HAVE_RAW_DECL_THRD_EXIT
287 _GL_WARN_ON_USE (thrd_exit, "thrd_exit is unportable - "
288 "use gnulib module thrd for portability");
289 # endif
290 #endif
291
292
293
294
295 #if !@HAVE_THREADS_H@
296
297
298 enum
299 {
300 mtx_plain = 0,
301 mtx_timed = 1,
302 mtx_recursive = 2
303 };
304
305 # if defined _WIN32 && ! defined __CYGWIN__
306
307
308 # include "windows-mutex.h"
309 # include "windows-recmutex.h"
310 # include "windows-timedmutex.h"
311 # include "windows-timedrecmutex.h"
312
313 typedef struct
314 {
315 int type;
316 union
317 {
318 glwthread_mutex_t u_mutex;
319 glwthread_recmutex_t u_recmutex;
320 glwthread_timedmutex_t u_timedmutex;
321 glwthread_timedrecmutex_t u_timedrecmutex;
322 }
323 u;
324 }
325 mtx_t;
326
327 # else
328
329
330 typedef pthread_mutex_t mtx_t;
331
332 # endif
333
334 #endif
335
336 #if @GNULIB_MTX@
337 # if !@HAVE_THREADS_H@
338 _GL_FUNCDECL_SYS (mtx_init, int, (mtx_t *, int) _GL_ARG_NONNULL ((1)));
339 # endif
340 _GL_CXXALIAS_SYS (mtx_init, int, (mtx_t *, int));
341 _GL_CXXALIASWARN (mtx_init);
342 #elif defined GNULIB_POSIXCHECK
343 # undef mtx_init
344 # if HAVE_RAW_DECL_MTX_INIT
345 _GL_WARN_ON_USE (mtx_init, "mtx_init is unportable - "
346 "use gnulib module mtx for portability");
347 # endif
348 #endif
349
350 #if @GNULIB_MTX@
351 # if !@HAVE_THREADS_H@
352 _GL_FUNCDECL_SYS (mtx_lock, int, (mtx_t *) _GL_ARG_NONNULL ((1)));
353 # endif
354 _GL_CXXALIAS_SYS (mtx_lock, int, (mtx_t *));
355 _GL_CXXALIASWARN (mtx_lock);
356 #elif defined GNULIB_POSIXCHECK
357 # undef mtx_lock
358 # if HAVE_RAW_DECL_MTX_LOCK
359 _GL_WARN_ON_USE (mtx_lock, "mtx_lock is unportable - "
360 "use gnulib module mtx for portability");
361 # endif
362 #endif
363
364 #if @GNULIB_MTX@
365 # if !@HAVE_THREADS_H@
366 _GL_FUNCDECL_SYS (mtx_trylock, int, (mtx_t *) _GL_ARG_NONNULL ((1)));
367 # endif
368 _GL_CXXALIAS_SYS (mtx_trylock, int, (mtx_t *));
369 _GL_CXXALIASWARN (mtx_trylock);
370 #elif defined GNULIB_POSIXCHECK
371 # undef mtx_trylock
372 # if HAVE_RAW_DECL_MTX_TRYLOCK
373 _GL_WARN_ON_USE (mtx_trylock, "mtx_trylock is unportable - "
374 "use gnulib module mtx for portability");
375 # endif
376 #endif
377
378 #if @GNULIB_MTX@
379 # if !@HAVE_THREADS_H@
380 _GL_FUNCDECL_SYS (mtx_timedlock, int, (mtx_t *, const struct timespec *)
381 _GL_ARG_NONNULL ((1, 2)));
382 # endif
383 _GL_CXXALIAS_SYS (mtx_timedlock, int, (mtx_t *, const struct timespec *));
384 _GL_CXXALIASWARN (mtx_timedlock);
385 #elif defined GNULIB_POSIXCHECK
386 # undef mtx_timedlock
387 # if HAVE_RAW_DECL_MTX_TIMEDLOCK
388 _GL_WARN_ON_USE (mtx_timedlock, "mtx_timedlock is unportable - "
389 "use gnulib module mtx for portability");
390 # endif
391 #endif
392
393 #if @GNULIB_MTX@
394 # if !@HAVE_THREADS_H@
395 _GL_FUNCDECL_SYS (mtx_unlock, int, (mtx_t *) _GL_ARG_NONNULL ((1)));
396 # endif
397 _GL_CXXALIAS_SYS (mtx_unlock, int, (mtx_t *));
398 _GL_CXXALIASWARN (mtx_unlock);
399 #elif defined GNULIB_POSIXCHECK
400 # undef mtx_unlock
401 # if HAVE_RAW_DECL_MTX_UNLOCK
402 _GL_WARN_ON_USE (mtx_unlock, "mtx_unlock is unportable - "
403 "use gnulib module mtx for portability");
404 # endif
405 #endif
406
407 #if @GNULIB_MTX@
408 # if !@HAVE_THREADS_H@
409 _GL_FUNCDECL_SYS (mtx_destroy, void, (mtx_t *) _GL_ARG_NONNULL ((1)));
410 # endif
411 _GL_CXXALIAS_SYS (mtx_destroy, void, (mtx_t *));
412 _GL_CXXALIASWARN (mtx_destroy);
413 #elif defined GNULIB_POSIXCHECK
414 # undef mtx_destroy
415 # if HAVE_RAW_DECL_MTX_DESTROY
416 _GL_WARN_ON_USE (mtx_destroy, "mtx_destroy is unportable - "
417 "use gnulib module mtx for portability");
418 # endif
419 #endif
420
421
422
423
424 #if !@HAVE_THREADS_H@
425
426
427 # if defined _WIN32 && ! defined __CYGWIN__
428
429
430 # include "windows-once.h"
431
432 typedef glwthread_once_t once_flag;
433 # define ONCE_FLAG_INIT GLWTHREAD_ONCE_INIT
434
435 # else
436
437
438 typedef pthread_once_t once_flag;
439 # define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
440
441 # endif
442
443 #endif
444
445 #if @GNULIB_MTX@
446 # if !@HAVE_THREADS_H@
447 _GL_FUNCDECL_SYS (call_once, void, (once_flag *, void (*) (void))
448 _GL_ARG_NONNULL ((1, 2)));
449 # endif
450 _GL_CXXALIAS_SYS_CAST (call_once, void, (once_flag *, void (*) (void)));
451 _GL_CXXALIASWARN (call_once);
452 #elif defined GNULIB_POSIXCHECK
453 # undef call_once
454 # if HAVE_RAW_DECL_CALL_ONCE
455 _GL_WARN_ON_USE (call_once, "call_once is unportable - "
456 "use gnulib module mtx for portability");
457 # endif
458 #endif
459
460
461
462
463 #if !@HAVE_THREADS_H@
464
465 # if defined _WIN32 && ! defined __CYGWIN__
466
467
468 # include "windows-cond.h"
469
470 typedef glwthread_cond_t cnd_t;
471
472 # else
473
474
475 typedef pthread_cond_t cnd_t;
476
477 # endif
478
479 #endif
480
481 #if @GNULIB_CND@
482 # if !@HAVE_THREADS_H@
483 _GL_FUNCDECL_SYS (cnd_init, int, (cnd_t *) _GL_ARG_NONNULL ((1)));
484 # endif
485 _GL_CXXALIAS_SYS (cnd_init, int, (cnd_t *));
486 _GL_CXXALIASWARN (cnd_init);
487 #elif defined GNULIB_POSIXCHECK
488 # undef cnd_init
489 # if HAVE_RAW_DECL_CND_INIT
490 _GL_WARN_ON_USE (cnd_init, "cnd_init is unportable - "
491 "use gnulib module cnd for portability");
492 # endif
493 #endif
494
495 #if @GNULIB_CND@
496 # if !@HAVE_THREADS_H@
497 _GL_FUNCDECL_SYS (cnd_wait, int, (cnd_t *, mtx_t *) _GL_ARG_NONNULL ((1, 2)));
498 # endif
499 _GL_CXXALIAS_SYS (cnd_wait, int, (cnd_t *, mtx_t *));
500 _GL_CXXALIASWARN (cnd_wait);
501 #elif defined GNULIB_POSIXCHECK
502 # undef cnd_wait
503 # if HAVE_RAW_DECL_CND_WAIT
504 _GL_WARN_ON_USE (cnd_wait, "cnd_wait is unportable - "
505 "use gnulib module cnd for portability");
506 # endif
507 #endif
508
509 #if @GNULIB_CND@
510 # if !@HAVE_THREADS_H@
511 _GL_FUNCDECL_SYS (cnd_timedwait, int,
512 (cnd_t *, mtx_t *, const struct timespec *)
513 _GL_ARG_NONNULL ((1, 2, 3)));
514 # endif
515 _GL_CXXALIAS_SYS (cnd_timedwait, int,
516 (cnd_t *, mtx_t *, const struct timespec *));
517 _GL_CXXALIASWARN (cnd_timedwait);
518 #elif defined GNULIB_POSIXCHECK
519 # undef cnd_timedwait
520 # if HAVE_RAW_DECL_CND_TIMEDWAIT
521 _GL_WARN_ON_USE (cnd_timedwait, "cnd_timedwait is unportable - "
522 "use gnulib module cnd for portability");
523 # endif
524 #endif
525
526 #if @GNULIB_CND@
527 # if !@HAVE_THREADS_H@
528 _GL_FUNCDECL_SYS (cnd_signal, int, (cnd_t *) _GL_ARG_NONNULL ((1)));
529 # endif
530 _GL_CXXALIAS_SYS (cnd_signal, int, (cnd_t *));
531 _GL_CXXALIASWARN (cnd_signal);
532 #elif defined GNULIB_POSIXCHECK
533 # undef cnd_signal
534 # if HAVE_RAW_DECL_CND_SIGNAL
535 _GL_WARN_ON_USE (cnd_signal, "cnd_signal is unportable - "
536 "use gnulib module cnd for portability");
537 # endif
538 #endif
539
540 #if @GNULIB_CND@
541 # if !@HAVE_THREADS_H@
542 _GL_FUNCDECL_SYS (cnd_broadcast, int, (cnd_t *) _GL_ARG_NONNULL ((1)));
543 # endif
544 _GL_CXXALIAS_SYS (cnd_broadcast, int, (cnd_t *));
545 _GL_CXXALIASWARN (cnd_broadcast);
546 #elif defined GNULIB_POSIXCHECK
547 # undef cnd_broadcast
548 # if HAVE_RAW_DECL_CND_BROADCAST
549 _GL_WARN_ON_USE (cnd_broadcast, "cnd_broadcast is unportable - "
550 "use gnulib module cnd for portability");
551 # endif
552 #endif
553
554 #if @GNULIB_CND@
555 # if !@HAVE_THREADS_H@
556 _GL_FUNCDECL_SYS (cnd_destroy, void, (cnd_t *) _GL_ARG_NONNULL ((1)));
557 # endif
558 _GL_CXXALIAS_SYS (cnd_destroy, void, (cnd_t *));
559 _GL_CXXALIASWARN (cnd_destroy);
560 #elif defined GNULIB_POSIXCHECK
561 # undef cnd_destroy
562 # if HAVE_RAW_DECL_CND_DESTROY
563 _GL_WARN_ON_USE (cnd_destroy, "cnd_destroy is unportable - "
564 "use gnulib module cnd for portability");
565 # endif
566 #endif
567
568
569
570
571 #if !@HAVE_THREADS_H@
572
573 # if defined _WIN32 && ! defined __CYGWIN__
574
575
576 # include "windows-tls.h"
577
578 typedef glwthread_tls_key_t tss_t;
579 # define TSS_DTOR_ITERATIONS GLWTHREAD_DESTRUCTOR_ITERATIONS
580
581 # else
582
583
584 # include <limits.h>
585
586 typedef pthread_key_t tss_t;
587
588 # endif
589
590
591 typedef void (*tss_dtor_t) (void *);
592
593 #endif
594
595
596 #ifndef TSS_DTOR_ITERATIONS
597 # ifdef PTHREAD_DESTRUCTOR_ITERATIONS
598 # define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
599 # else
600
601
602 # define TSS_DTOR_ITERATIONS 1
603 # endif
604 #endif
605
606 #if @GNULIB_TSS@
607 # if !@HAVE_THREADS_H@
608 _GL_FUNCDECL_SYS (tss_create, int, (tss_t *, tss_dtor_t) _GL_ARG_NONNULL ((1)));
609 # endif
610 _GL_CXXALIAS_SYS (tss_create, int, (tss_t *, tss_dtor_t));
611 _GL_CXXALIASWARN (tss_create);
612 #elif defined GNULIB_POSIXCHECK
613 # undef tss_create
614 # if HAVE_RAW_DECL_TSS_CREATE
615 _GL_WARN_ON_USE (tss_create, "tss_create is unportable - "
616 "use gnulib module tss for portability");
617 # endif
618 #endif
619
620 #if @GNULIB_TSS@
621 # if !@HAVE_THREADS_H@
622 _GL_FUNCDECL_SYS (tss_set, int, (tss_t, void *));
623 # endif
624 _GL_CXXALIAS_SYS (tss_set, int, (tss_t, void *));
625 _GL_CXXALIASWARN (tss_set);
626 #elif defined GNULIB_POSIXCHECK
627 # undef tss_set
628 # if HAVE_RAW_DECL_TSS_SET
629 _GL_WARN_ON_USE (tss_set, "tss_set is unportable - "
630 "use gnulib module tss for portability");
631 # endif
632 #endif
633
634 #if @GNULIB_TSS@
635 # if !@HAVE_THREADS_H@
636 _GL_FUNCDECL_SYS (tss_get, void *, (tss_t));
637 # endif
638 _GL_CXXALIAS_SYS (tss_get, void *, (tss_t));
639 _GL_CXXALIASWARN (tss_get);
640 #elif defined GNULIB_POSIXCHECK
641 # undef tss_get
642 # if HAVE_RAW_DECL_TSS_GET
643 _GL_WARN_ON_USE (tss_get, "tss_get is unportable - "
644 "use gnulib module tss for portability");
645 # endif
646 #endif
647
648 #if @GNULIB_TSS@
649 # if !@HAVE_THREADS_H@
650 _GL_FUNCDECL_SYS (tss_delete, void, (tss_t));
651 # endif
652 _GL_CXXALIAS_SYS (tss_delete, void, (tss_t));
653 _GL_CXXALIASWARN (tss_delete);
654 #elif defined GNULIB_POSIXCHECK
655 # undef tss_delete
656 # if HAVE_RAW_DECL_TSS_DELETE
657 _GL_WARN_ON_USE (tss_delete, "tss_delete is unportable - "
658 "use gnulib module tss for portability");
659 # endif
660 #endif
661
662
663 #endif
664 #endif