1# pthread_h.m4 serial 5
2dnl Copyright (C) 2009-2021 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_PTHREAD_H],
8[
9  dnl Use AC_REQUIRE here, so that the default behavior below is expanded
10  dnl once only, before all statements that occur in other macros.
11  AC_REQUIRE([gl_PTHREAD_H_DEFAULTS])
12
13  AC_REQUIRE([AC_CANONICAL_HOST])
14  AC_REQUIRE([gl_PTHREADLIB])
15
16  gl_CHECK_NEXT_HEADERS([pthread.h])
17  if test $ac_cv_header_pthread_h = yes; then
18    HAVE_PTHREAD_H=1
19    dnl On mingw, if --enable-threads=windows or gl_AVOID_WINPTHREAD is used,
20    dnl ignore the <pthread.h> from the mingw-w64 winpthreads library.
21    m4_ifdef([gl_][THREADLIB], [
22      AC_REQUIRE([gl_][THREADLIB])
23      if { case "$host_os" in mingw*) true;; *) false;; esac; } \
24         && test $gl_threads_api = windows; then
25        HAVE_PTHREAD_H=0
26      fi
27    ])
28  else
29    HAVE_PTHREAD_H=0
30  fi
31  AC_SUBST([HAVE_PTHREAD_H])
32
33  AC_CHECK_TYPES([pthread_t, pthread_spinlock_t], [], [],
34    [AC_INCLUDES_DEFAULT[
35     #if HAVE_PTHREAD_H
36      #include <pthread.h>
37     #endif]])
38  if test $ac_cv_type_pthread_t != yes; then
39    HAVE_PTHREAD_T=0
40  fi
41  if test $ac_cv_type_pthread_spinlock_t != yes; then
42    HAVE_PTHREAD_SPINLOCK_T=0
43  fi
44
45  dnl Constants may be defined as C preprocessor macros or as enum items.
46
47  AC_CACHE_CHECK([for PTHREAD_CREATE_DETACHED],
48    [gl_cv_const_PTHREAD_CREATE_DETACHED],
49    [AC_COMPILE_IFELSE(
50       [AC_LANG_PROGRAM(
51          [[#include <pthread.h>
52            int x = PTHREAD_CREATE_DETACHED;
53          ]],
54          [[]])],
55       [gl_cv_const_PTHREAD_CREATE_DETACHED=yes],
56       [gl_cv_const_PTHREAD_CREATE_DETACHED=no])
57    ])
58  if test $gl_cv_const_PTHREAD_CREATE_DETACHED != yes; then
59    HAVE_PTHREAD_CREATE_DETACHED=0
60  fi
61
62  AC_CACHE_CHECK([for PTHREAD_MUTEX_RECURSIVE],
63    [gl_cv_const_PTHREAD_MUTEX_RECURSIVE],
64    [AC_COMPILE_IFELSE(
65       [AC_LANG_PROGRAM(
66          [[#include <pthread.h>
67            int x = PTHREAD_MUTEX_RECURSIVE;
68          ]],
69          [[]])],
70       [gl_cv_const_PTHREAD_MUTEX_RECURSIVE=yes],
71       [gl_cv_const_PTHREAD_MUTEX_RECURSIVE=no])
72    ])
73  if test $gl_cv_const_PTHREAD_MUTEX_RECURSIVE != yes; then
74    HAVE_PTHREAD_MUTEX_RECURSIVE=0
75  fi
76
77  AC_CACHE_CHECK([for PTHREAD_MUTEX_ROBUST],
78    [gl_cv_const_PTHREAD_MUTEX_ROBUST],
79    [AC_COMPILE_IFELSE(
80       [AC_LANG_PROGRAM(
81          [[#include <pthread.h>
82            int x = PTHREAD_MUTEX_ROBUST;
83          ]],
84          [[]])],
85       [gl_cv_const_PTHREAD_MUTEX_ROBUST=yes],
86       [gl_cv_const_PTHREAD_MUTEX_ROBUST=no])
87    ])
88  if test $gl_cv_const_PTHREAD_MUTEX_ROBUST != yes; then
89    HAVE_PTHREAD_MUTEX_ROBUST=0
90  fi
91
92  AC_CACHE_CHECK([for PTHREAD_PROCESS_SHARED],
93    [gl_cv_const_PTHREAD_PROCESS_SHARED],
94    [AC_COMPILE_IFELSE(
95       [AC_LANG_PROGRAM(
96          [[#include <pthread.h>
97            int x = PTHREAD_PROCESS_SHARED;
98          ]],
99          [[]])],
100       [gl_cv_const_PTHREAD_PROCESS_SHARED=yes],
101       [gl_cv_const_PTHREAD_PROCESS_SHARED=no])
102    ])
103  if test $gl_cv_const_PTHREAD_PROCESS_SHARED != yes; then
104    HAVE_PTHREAD_PROCESS_SHARED=0
105  fi
106
107  dnl Check for declarations of anything we want to poison if the
108  dnl corresponding gnulib module is not in use, if it is not common
109  dnl enough to be declared everywhere.
110  gl_WARN_ON_USE_PREPARE([[#include <pthread.h>
111    ]], [
112    pthread_create pthread_attr_init pthread_attr_getdetachstate
113    pthread_attr_setdetachstate pthread_attr_destroy pthread_self pthread_equal
114    pthread_detach pthread_join pthread_exit
115    pthread_once
116    pthread_mutex_init pthread_mutexattr_init pthread_mutexattr_gettype
117    pthread_mutexattr_settype pthread_mutexattr_getrobust
118    pthread_mutexattr_setrobust pthread_mutexattr_destroy pthread_mutex_lock
119    pthread_mutex_trylock pthread_mutex_timedlock pthread_mutex_unlock
120    pthread_mutex_destroy
121    pthread_rwlock_init pthread_rwlockattr_init pthread_rwlockattr_destroy
122    pthread_rwlock_rdlock pthread_rwlock_wrlock pthread_rwlock_tryrdlock
123    pthread_rwlock_trywrlock pthread_rwlock_timedrdlock
124    pthread_rwlock_timedwrlock pthread_rwlock_unlock pthread_rwlock_destroy
125    pthread_cond_init pthread_condattr_init pthread_condattr_destroy
126    pthread_cond_wait pthread_cond_timedwait pthread_cond_signal
127    pthread_cond_broadcast pthread_cond_destroy
128    pthread_key_create pthread_setspecific pthread_getspecific
129    pthread_key_delete
130    pthread_spin_init pthread_spin_lock pthread_spin_trylock pthread_spin_unlock
131    pthread_spin_destroy])
132
133  AC_REQUIRE([AC_C_RESTRICT])
134
135  dnl For backward compatibility with gnulib versions <= 2019-07.
136  LIB_PTHREAD="$LIBPMULTITHREAD"
137  AC_SUBST([LIB_PTHREAD])
138])
139
140AC_DEFUN([gl_PTHREAD_MODULE_INDICATOR],
141[
142  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
143  AC_REQUIRE([gl_PTHREAD_H_DEFAULTS])
144  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
145  dnl Define it also as a C macro, for the benefit of the unit tests.
146  gl_MODULE_INDICATOR_FOR_TESTS([$1])
147])
148
149AC_DEFUN([gl_PTHREAD_H_DEFAULTS],
150[
151  GNULIB_PTHREAD_THREAD=0;               AC_SUBST([GNULIB_PTHREAD_THREAD])
152  GNULIB_PTHREAD_ONCE=0;                 AC_SUBST([GNULIB_PTHREAD_ONCE])
153  GNULIB_PTHREAD_MUTEX=0;                AC_SUBST([GNULIB_PTHREAD_MUTEX])
154  GNULIB_PTHREAD_RWLOCK=0;               AC_SUBST([GNULIB_PTHREAD_RWLOCK])
155  GNULIB_PTHREAD_COND=0;                 AC_SUBST([GNULIB_PTHREAD_COND])
156  GNULIB_PTHREAD_TSS=0;                  AC_SUBST([GNULIB_PTHREAD_TSS])
157  GNULIB_PTHREAD_SPIN=0;                 AC_SUBST([GNULIB_PTHREAD_SPIN])
158  GNULIB_PTHREAD_MUTEX_TIMEDLOCK=0;      AC_SUBST([GNULIB_PTHREAD_MUTEX_TIMEDLOCK])
159  dnl Assume proper GNU behavior unless another module says otherwise.
160  HAVE_PTHREAD_T=1;                      AC_SUBST([HAVE_PTHREAD_T])
161  HAVE_PTHREAD_SPINLOCK_T=1;             AC_SUBST([HAVE_PTHREAD_SPINLOCK_T])
162  HAVE_PTHREAD_CREATE_DETACHED=1;        AC_SUBST([HAVE_PTHREAD_CREATE_DETACHED])
163  HAVE_PTHREAD_MUTEX_RECURSIVE=1;        AC_SUBST([HAVE_PTHREAD_MUTEX_RECURSIVE])
164  HAVE_PTHREAD_MUTEX_ROBUST=1;           AC_SUBST([HAVE_PTHREAD_MUTEX_ROBUST])
165  HAVE_PTHREAD_PROCESS_SHARED=1;         AC_SUBST([HAVE_PTHREAD_PROCESS_SHARED])
166  HAVE_PTHREAD_CREATE=1;                 AC_SUBST([HAVE_PTHREAD_CREATE])
167  HAVE_PTHREAD_ATTR_INIT=1;              AC_SUBST([HAVE_PTHREAD_ATTR_INIT])
168  HAVE_PTHREAD_ATTR_GETDETACHSTATE=1;    AC_SUBST([HAVE_PTHREAD_ATTR_GETDETACHSTATE])
169  HAVE_PTHREAD_ATTR_SETDETACHSTATE=1;    AC_SUBST([HAVE_PTHREAD_ATTR_SETDETACHSTATE])
170  HAVE_PTHREAD_ATTR_DESTROY=1;           AC_SUBST([HAVE_PTHREAD_ATTR_DESTROY])
171  HAVE_PTHREAD_SELF=1;                   AC_SUBST([HAVE_PTHREAD_SELF])
172  HAVE_PTHREAD_EQUAL=1;                  AC_SUBST([HAVE_PTHREAD_EQUAL])
173  HAVE_PTHREAD_DETACH=1;                 AC_SUBST([HAVE_PTHREAD_DETACH])
174  HAVE_PTHREAD_JOIN=1;                   AC_SUBST([HAVE_PTHREAD_JOIN])
175  HAVE_PTHREAD_EXIT=1;                   AC_SUBST([HAVE_PTHREAD_EXIT])
176  HAVE_PTHREAD_ONCE=1;                   AC_SUBST([HAVE_PTHREAD_ONCE])
177  HAVE_PTHREAD_MUTEX_INIT=1;             AC_SUBST([HAVE_PTHREAD_MUTEX_INIT])
178  HAVE_PTHREAD_MUTEXATTR_INIT=1;         AC_SUBST([HAVE_PTHREAD_MUTEXATTR_INIT])
179  HAVE_PTHREAD_MUTEXATTR_GETTYPE=1;      AC_SUBST([HAVE_PTHREAD_MUTEXATTR_GETTYPE])
180  HAVE_PTHREAD_MUTEXATTR_SETTYPE=1;      AC_SUBST([HAVE_PTHREAD_MUTEXATTR_SETTYPE])
181  HAVE_PTHREAD_MUTEXATTR_GETROBUST=1;    AC_SUBST([HAVE_PTHREAD_MUTEXATTR_GETROBUST])
182  HAVE_PTHREAD_MUTEXATTR_SETROBUST=1;    AC_SUBST([HAVE_PTHREAD_MUTEXATTR_SETROBUST])
183  HAVE_PTHREAD_MUTEXATTR_DESTROY=1;      AC_SUBST([HAVE_PTHREAD_MUTEXATTR_DESTROY])
184  HAVE_PTHREAD_MUTEX_LOCK=1;             AC_SUBST([HAVE_PTHREAD_MUTEX_LOCK])
185  HAVE_PTHREAD_MUTEX_TRYLOCK=1;          AC_SUBST([HAVE_PTHREAD_MUTEX_TRYLOCK])
186  HAVE_PTHREAD_MUTEX_TIMEDLOCK=1;        AC_SUBST([HAVE_PTHREAD_MUTEX_TIMEDLOCK])
187  HAVE_PTHREAD_MUTEX_UNLOCK=1;           AC_SUBST([HAVE_PTHREAD_MUTEX_UNLOCK])
188  HAVE_PTHREAD_MUTEX_DESTROY=1;          AC_SUBST([HAVE_PTHREAD_MUTEX_DESTROY])
189  HAVE_PTHREAD_RWLOCK_INIT=1;            AC_SUBST([HAVE_PTHREAD_RWLOCK_INIT])
190  HAVE_PTHREAD_RWLOCKATTR_INIT=1;        AC_SUBST([HAVE_PTHREAD_RWLOCKATTR_INIT])
191  HAVE_PTHREAD_RWLOCKATTR_DESTROY=1;     AC_SUBST([HAVE_PTHREAD_RWLOCKATTR_DESTROY])
192  HAVE_PTHREAD_RWLOCK_RDLOCK=1;          AC_SUBST([HAVE_PTHREAD_RWLOCK_RDLOCK])
193  HAVE_PTHREAD_RWLOCK_WRLOCK=1;          AC_SUBST([HAVE_PTHREAD_RWLOCK_WRLOCK])
194  HAVE_PTHREAD_RWLOCK_TRYRDLOCK=1;       AC_SUBST([HAVE_PTHREAD_RWLOCK_TRYRDLOCK])
195  HAVE_PTHREAD_RWLOCK_TRYWRLOCK=1;       AC_SUBST([HAVE_PTHREAD_RWLOCK_TRYWRLOCK])
196  HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK=1;     AC_SUBST([HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK])
197  HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK=1;     AC_SUBST([HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK])
198  HAVE_PTHREAD_RWLOCK_UNLOCK=1;          AC_SUBST([HAVE_PTHREAD_RWLOCK_UNLOCK])
199  HAVE_PTHREAD_RWLOCK_DESTROY=1;         AC_SUBST([HAVE_PTHREAD_RWLOCK_DESTROY])
200  HAVE_PTHREAD_COND_INIT=1;              AC_SUBST([HAVE_PTHREAD_COND_INIT])
201  HAVE_PTHREAD_CONDATTR_INIT=1;          AC_SUBST([HAVE_PTHREAD_CONDATTR_INIT])
202  HAVE_PTHREAD_CONDATTR_DESTROY=1;       AC_SUBST([HAVE_PTHREAD_CONDATTR_DESTROY])
203  HAVE_PTHREAD_COND_WAIT=1;              AC_SUBST([HAVE_PTHREAD_COND_WAIT])
204  HAVE_PTHREAD_COND_TIMEDWAIT=1;         AC_SUBST([HAVE_PTHREAD_COND_TIMEDWAIT])
205  HAVE_PTHREAD_COND_SIGNAL=1;            AC_SUBST([HAVE_PTHREAD_COND_SIGNAL])
206  HAVE_PTHREAD_COND_BROADCAST=1;         AC_SUBST([HAVE_PTHREAD_COND_BROADCAST])
207  HAVE_PTHREAD_COND_DESTROY=1;           AC_SUBST([HAVE_PTHREAD_COND_DESTROY])
208  HAVE_PTHREAD_KEY_CREATE=1;             AC_SUBST([HAVE_PTHREAD_KEY_CREATE])
209  HAVE_PTHREAD_SETSPECIFIC=1;            AC_SUBST([HAVE_PTHREAD_SETSPECIFIC])
210  HAVE_PTHREAD_GETSPECIFIC=1;            AC_SUBST([HAVE_PTHREAD_GETSPECIFIC])
211  HAVE_PTHREAD_KEY_DELETE=1;             AC_SUBST([HAVE_PTHREAD_KEY_DELETE])
212  HAVE_PTHREAD_SPIN_INIT=1;              AC_SUBST([HAVE_PTHREAD_SPIN_INIT])
213  HAVE_PTHREAD_SPIN_LOCK=1;              AC_SUBST([HAVE_PTHREAD_SPIN_LOCK])
214  HAVE_PTHREAD_SPIN_TRYLOCK=1;           AC_SUBST([HAVE_PTHREAD_SPIN_TRYLOCK])
215  HAVE_PTHREAD_SPIN_UNLOCK=1;            AC_SUBST([HAVE_PTHREAD_SPIN_UNLOCK])
216  HAVE_PTHREAD_SPIN_DESTROY=1;           AC_SUBST([HAVE_PTHREAD_SPIN_DESTROY])
217  REPLACE_PTHREAD_CREATE=0;              AC_SUBST([REPLACE_PTHREAD_CREATE])
218  REPLACE_PTHREAD_ATTR_INIT=0;           AC_SUBST([REPLACE_PTHREAD_ATTR_INIT])
219  REPLACE_PTHREAD_ATTR_GETDETACHSTATE=0; AC_SUBST([REPLACE_PTHREAD_ATTR_GETDETACHSTATE])
220  REPLACE_PTHREAD_ATTR_SETDETACHSTATE=0; AC_SUBST([REPLACE_PTHREAD_ATTR_SETDETACHSTATE])
221  REPLACE_PTHREAD_ATTR_DESTROY=0;        AC_SUBST([REPLACE_PTHREAD_ATTR_DESTROY])
222  REPLACE_PTHREAD_SELF=0;                AC_SUBST([REPLACE_PTHREAD_SELF])
223  REPLACE_PTHREAD_EQUAL=0;               AC_SUBST([REPLACE_PTHREAD_EQUAL])
224  REPLACE_PTHREAD_DETACH=0;              AC_SUBST([REPLACE_PTHREAD_DETACH])
225  REPLACE_PTHREAD_JOIN=0;                AC_SUBST([REPLACE_PTHREAD_JOIN])
226  REPLACE_PTHREAD_EXIT=0;                AC_SUBST([REPLACE_PTHREAD_EXIT])
227  REPLACE_PTHREAD_ONCE=0;                AC_SUBST([REPLACE_PTHREAD_ONCE])
228  REPLACE_PTHREAD_MUTEX_INIT=0;          AC_SUBST([REPLACE_PTHREAD_MUTEX_INIT])
229  REPLACE_PTHREAD_MUTEXATTR_INIT=0;      AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_INIT])
230  REPLACE_PTHREAD_MUTEXATTR_GETTYPE=0;   AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_GETTYPE])
231  REPLACE_PTHREAD_MUTEXATTR_SETTYPE=0;   AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_SETTYPE])
232  REPLACE_PTHREAD_MUTEXATTR_GETROBUST=0; AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_GETROBUST])
233  REPLACE_PTHREAD_MUTEXATTR_SETROBUST=0; AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_SETROBUST])
234  REPLACE_PTHREAD_MUTEXATTR_DESTROY=0;   AC_SUBST([REPLACE_PTHREAD_MUTEXATTR_DESTROY])
235  REPLACE_PTHREAD_MUTEX_LOCK=0;          AC_SUBST([REPLACE_PTHREAD_MUTEX_LOCK])
236  REPLACE_PTHREAD_MUTEX_TRYLOCK=0;       AC_SUBST([REPLACE_PTHREAD_MUTEX_TRYLOCK])
237  REPLACE_PTHREAD_MUTEX_TIMEDLOCK=0;     AC_SUBST([REPLACE_PTHREAD_MUTEX_TIMEDLOCK])
238  REPLACE_PTHREAD_MUTEX_UNLOCK=0;        AC_SUBST([REPLACE_PTHREAD_MUTEX_UNLOCK])
239  REPLACE_PTHREAD_MUTEX_DESTROY=0;       AC_SUBST([REPLACE_PTHREAD_MUTEX_DESTROY])
240  REPLACE_PTHREAD_RWLOCK_INIT=0;         AC_SUBST([REPLACE_PTHREAD_RWLOCK_INIT])
241  REPLACE_PTHREAD_RWLOCKATTR_INIT=0;     AC_SUBST([REPLACE_PTHREAD_RWLOCKATTR_INIT])
242  REPLACE_PTHREAD_RWLOCKATTR_DESTROY=0;  AC_SUBST([REPLACE_PTHREAD_RWLOCKATTR_DESTROY])
243  REPLACE_PTHREAD_RWLOCK_RDLOCK=0;       AC_SUBST([REPLACE_PTHREAD_RWLOCK_RDLOCK])
244  REPLACE_PTHREAD_RWLOCK_WRLOCK=0;       AC_SUBST([REPLACE_PTHREAD_RWLOCK_WRLOCK])
245  REPLACE_PTHREAD_RWLOCK_TRYRDLOCK=0;    AC_SUBST([REPLACE_PTHREAD_RWLOCK_TRYRDLOCK])
246  REPLACE_PTHREAD_RWLOCK_TRYWRLOCK=0;    AC_SUBST([REPLACE_PTHREAD_RWLOCK_TRYWRLOCK])
247  REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK=0;  AC_SUBST([REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK])
248  REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK=0;  AC_SUBST([REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK])
249  REPLACE_PTHREAD_RWLOCK_UNLOCK=0;       AC_SUBST([REPLACE_PTHREAD_RWLOCK_UNLOCK])
250  REPLACE_PTHREAD_RWLOCK_DESTROY=0;      AC_SUBST([REPLACE_PTHREAD_RWLOCK_DESTROY])
251  REPLACE_PTHREAD_COND_INIT=0;           AC_SUBST([REPLACE_PTHREAD_COND_INIT])
252  REPLACE_PTHREAD_CONDATTR_INIT=0;       AC_SUBST([REPLACE_PTHREAD_CONDATTR_INIT])
253  REPLACE_PTHREAD_CONDATTR_DESTROY=0;    AC_SUBST([REPLACE_PTHREAD_CONDATTR_DESTROY])
254  REPLACE_PTHREAD_COND_WAIT=0;           AC_SUBST([REPLACE_PTHREAD_COND_WAIT])
255  REPLACE_PTHREAD_COND_TIMEDWAIT=0;      AC_SUBST([REPLACE_PTHREAD_COND_TIMEDWAIT])
256  REPLACE_PTHREAD_COND_SIGNAL=0;         AC_SUBST([REPLACE_PTHREAD_COND_SIGNAL])
257  REPLACE_PTHREAD_COND_BROADCAST=0;      AC_SUBST([REPLACE_PTHREAD_COND_BROADCAST])
258  REPLACE_PTHREAD_COND_DESTROY=0;        AC_SUBST([REPLACE_PTHREAD_COND_DESTROY])
259  REPLACE_PTHREAD_KEY_CREATE=0;          AC_SUBST([REPLACE_PTHREAD_KEY_CREATE])
260  REPLACE_PTHREAD_SETSPECIFIC=0;         AC_SUBST([REPLACE_PTHREAD_SETSPECIFIC])
261  REPLACE_PTHREAD_GETSPECIFIC=0;         AC_SUBST([REPLACE_PTHREAD_GETSPECIFIC])
262  REPLACE_PTHREAD_KEY_DELETE=0;          AC_SUBST([REPLACE_PTHREAD_KEY_DELETE])
263  REPLACE_PTHREAD_SPIN_INIT=0;           AC_SUBST([REPLACE_PTHREAD_SPIN_INIT])
264  REPLACE_PTHREAD_SPIN_LOCK=0;           AC_SUBST([REPLACE_PTHREAD_SPIN_LOCK])
265  REPLACE_PTHREAD_SPIN_TRYLOCK=0;        AC_SUBST([REPLACE_PTHREAD_SPIN_TRYLOCK])
266  REPLACE_PTHREAD_SPIN_UNLOCK=0;         AC_SUBST([REPLACE_PTHREAD_SPIN_UNLOCK])
267  REPLACE_PTHREAD_SPIN_DESTROY=0;        AC_SUBST([REPLACE_PTHREAD_SPIN_DESTROY])
268])
269