summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-09-13 20:28:16 +0200
committerGravatar Nikias Bassen2021-09-13 20:28:16 +0200
commit40b25fd572bf94d65e880a216bba5e825e5bbf2d (patch)
treeb6df709be2dbdec2186df1c7e2bec211b8d0dec5
parentbcf56b30fea3b841ee11a9b4f3ac74f6de465f3d (diff)
downloadlibirecovery-40b25fd572bf94d65e880a216bba5e825e5bbf2d.tar.gz
libirecovery-40b25fd572bf94d65e880a216bba5e825e5bbf2d.tar.bz2
Remove duplicated thread/collection code and use new libimobiledevice-glue instead
-rw-r--r--configure.ac10
-rw-r--r--m4/ax_pthread.m4522
-rw-r--r--src/Makefile.am7
-rw-r--r--src/libirecovery-1.0.pc.in2
-rw-r--r--src/libirecovery.c11
-rw-r--r--src/thread.c215
-rw-r--r--src/thread.h87
-rw-r--r--src/utils.c92
-rw-r--r--src/utils.h52
9 files changed, 15 insertions, 983 deletions
diff --git a/configure.ac b/configure.ac
index 7617d61..d571f48 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,8 +19,10 @@ LIBIRECOVERY_SO_VERSION=3:0:0
19 19
20dnl Minimum package versions 20dnl Minimum package versions
21LIBUSB_VERSION=1.0.3 21LIBUSB_VERSION=1.0.3
22LIMD_GLUE_VERSION=1.0.0
22 23
23AC_SUBST(LIBIRECOVERY_SO_VERSION) 24AC_SUBST(LIBIRECOVERY_SO_VERSION)
25AC_SUBST(LIMD_GLUE_VERSION)
24 26
25# Checks for programs. 27# Checks for programs.
26AC_PROG_CC 28AC_PROG_CC
@@ -28,6 +30,9 @@ AC_PROG_CC
28AM_PROG_CC_C_O 30AM_PROG_CC_C_O
29LT_INIT 31LT_INIT
30 32
33# Checks for libraries.
34PKG_CHECK_MODULES(limd_glue, libimobiledevice-glue-1.0 >= $LIMD_GLUE_VERSION)
35
31# Checks for header files. 36# Checks for header files.
32AC_CHECK_HEADERS([stdint.h stdlib.h string.h]) 37AC_CHECK_HEADERS([stdint.h stdlib.h string.h])
33 38
@@ -58,7 +63,6 @@ case ${host_os} in
58 have_iokit=yes 63 have_iokit=yes
59 ], []) 64 ], [])
60 ], []) 65 ], [])
61 AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE])])
62 ;; 66 ;;
63 mingw32*) 67 mingw32*)
64 AC_MSG_RESULT([${host_os}]) 68 AC_MSG_RESULT([${host_os}])
@@ -74,7 +78,6 @@ case ${host_os} in
74 ;; 78 ;;
75 *) 79 *)
76 AC_MSG_RESULT([${host_os}]) 80 AC_MSG_RESULT([${host_os}])
77 AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE])])
78 ;; 81 ;;
79esac 82esac
80AM_CONDITIONAL(WIN32, test x$win32 = xtrue) 83AM_CONDITIONAL(WIN32, test x$win32 = xtrue)
@@ -111,8 +114,7 @@ AS_IF([test "x$with_dummy" = "xyes"], [
111 ]) 114 ])
112]) 115])
113 116
114AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fvisibility=hidden $PTHREAD_CFLAGS") 117AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fvisibility=hidden")
115GLOBAL_LDFLAGS+=" $PTHREAD_LIBS"
116AC_SUBST(GLOBAL_CFLAGS) 118AC_SUBST(GLOBAL_CFLAGS)
117AC_SUBST(GLOBAL_LDFLAGS) 119AC_SUBST(GLOBAL_LDFLAGS)
118 120
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
deleted file mode 100644
index 9f35d13..0000000
--- a/m4/ax_pthread.m4
+++ /dev/null
@@ -1,522 +0,0 @@
1# ===========================================================================
2# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
3# ===========================================================================
4#
5# SYNOPSIS
6#
7# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
8#
9# DESCRIPTION
10#
11# This macro figures out how to build C programs using POSIX threads. It
12# sets the PTHREAD_LIBS output variable to the threads library and linker
13# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
14# flags that are needed. (The user can also force certain compiler
15# flags/libs to be tested by setting these environment variables.)
16#
17# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
18# needed for multi-threaded programs (defaults to the value of CC
19# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
20# special cc_r/CC_r compiler alias.)
21#
22# NOTE: You are assumed to not only compile your program with these flags,
23# but also to link with them as well. For example, you might link with
24# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
25# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
26#
27# If you are only building threaded programs, you may wish to use these
28# variables in your default LIBS, CFLAGS, and CC:
29#
30# LIBS="$PTHREAD_LIBS $LIBS"
31# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
32# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
33# CC="$PTHREAD_CC"
34# CXX="$PTHREAD_CXX"
35#
36# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
37# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
38# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
39#
40# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
41# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
42# PTHREAD_CFLAGS.
43#
44# ACTION-IF-FOUND is a list of shell commands to run if a threads library
45# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
46# is not found. If ACTION-IF-FOUND is not specified, the default action
47# will define HAVE_PTHREAD.
48#
49# Please let the authors know if this macro fails on any platform, or if
50# you have any other suggestions or comments. This macro was based on work
51# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
52# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
53# Alejandro Forero Cuervo to the autoconf macro repository. We are also
54# grateful for the helpful feedback of numerous users.
55#
56# Updated for Autoconf 2.68 by Daniel Richard G.
57#
58# LICENSE
59#
60# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
61# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
62# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
63#
64# This program is free software: you can redistribute it and/or modify it
65# under the terms of the GNU General Public License as published by the
66# Free Software Foundation, either version 3 of the License, or (at your
67# option) any later version.
68#
69# This program is distributed in the hope that it will be useful, but
70# WITHOUT ANY WARRANTY; without even the implied warranty of
71# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
72# Public License for more details.
73#
74# You should have received a copy of the GNU General Public License along
75# with this program. If not, see <https://www.gnu.org/licenses/>.
76#
77# As a special exception, the respective Autoconf Macro's copyright owner
78# gives unlimited permission to copy, distribute and modify the configure
79# scripts that are the output of Autoconf when processing the Macro. You
80# need not follow the terms of the GNU General Public License when using
81# or distributing such scripts, even though portions of the text of the
82# Macro appear in them. The GNU General Public License (GPL) does govern
83# all other use of the material that constitutes the Autoconf Macro.
84#
85# This special exception to the GPL applies to versions of the Autoconf
86# Macro released by the Autoconf Archive. When you make and distribute a
87# modified version of the Autoconf Macro, you may extend this special
88# exception to the GPL to apply to your modified version as well.
89
90#serial 31
91
92AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
93AC_DEFUN([AX_PTHREAD], [
94AC_REQUIRE([AC_CANONICAL_HOST])
95AC_REQUIRE([AC_PROG_CC])
96AC_REQUIRE([AC_PROG_SED])
97AC_LANG_PUSH([C])
98ax_pthread_ok=no
99
100# We used to check for pthread.h first, but this fails if pthread.h
101# requires special compiler flags (e.g. on Tru64 or Sequent).
102# It gets checked for in the link test anyway.
103
104# First of all, check if the user has set any of the PTHREAD_LIBS,
105# etcetera environment variables, and if threads linking works using
106# them:
107if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
108 ax_pthread_save_CC="$CC"
109 ax_pthread_save_CFLAGS="$CFLAGS"
110 ax_pthread_save_LIBS="$LIBS"
111 AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
112 AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
113 CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
114 LIBS="$PTHREAD_LIBS $LIBS"
115 AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
116 AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
117 AC_MSG_RESULT([$ax_pthread_ok])
118 if test "x$ax_pthread_ok" = "xno"; then
119 PTHREAD_LIBS=""
120 PTHREAD_CFLAGS=""
121 fi
122 CC="$ax_pthread_save_CC"
123 CFLAGS="$ax_pthread_save_CFLAGS"
124 LIBS="$ax_pthread_save_LIBS"
125fi
126
127# We must check for the threads library under a number of different
128# names; the ordering is very important because some systems
129# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
130# libraries is broken (non-POSIX).
131
132# Create a list of thread flags to try. Items with a "," contain both
133# C compiler flags (before ",") and linker flags (after ","). Other items
134# starting with a "-" are C compiler flags, and remaining items are
135# library names, except for "none" which indicates that we try without
136# any flags at all, and "pthread-config" which is a program returning
137# the flags for the Pth emulation library.
138
139ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
140
141# The ordering *is* (sometimes) important. Some notes on the
142# individual items follow:
143
144# pthreads: AIX (must check this before -lpthread)
145# none: in case threads are in libc; should be tried before -Kthread and
146# other compiler flags to prevent continual compiler warnings
147# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
148# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
149# (Note: HP C rejects this with "bad form for `-t' option")
150# -pthreads: Solaris/gcc (Note: HP C also rejects)
151# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
152# doesn't hurt to check since this sometimes defines pthreads and
153# -D_REENTRANT too), HP C (must be checked before -lpthread, which
154# is present but should not be used directly; and before -mthreads,
155# because the compiler interprets this as "-mt" + "-hreads")
156# -mthreads: Mingw32/gcc, Lynx/gcc
157# pthread: Linux, etcetera
158# --thread-safe: KAI C++
159# pthread-config: use pthread-config program (for GNU Pth library)
160
161case $host_os in
162
163 freebsd*)
164
165 # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
166 # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
167
168 ax_pthread_flags="-kthread lthread $ax_pthread_flags"
169 ;;
170
171 hpux*)
172
173 # From the cc(1) man page: "[-mt] Sets various -D flags to enable
174 # multi-threading and also sets -lpthread."
175
176 ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
177 ;;
178
179 openedition*)
180
181 # IBM z/OS requires a feature-test macro to be defined in order to
182 # enable POSIX threads at all, so give the user a hint if this is
183 # not set. (We don't define these ourselves, as they can affect
184 # other portions of the system API in unpredictable ways.)
185
186 AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
187 [
188# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
189 AX_PTHREAD_ZOS_MISSING
190# endif
191 ],
192 [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
193 ;;
194
195 solaris*)
196
197 # On Solaris (at least, for some versions), libc contains stubbed
198 # (non-functional) versions of the pthreads routines, so link-based
199 # tests will erroneously succeed. (N.B.: The stubs are missing
200 # pthread_cleanup_push, or rather a function called by this macro,
201 # so we could check for that, but who knows whether they'll stub
202 # that too in a future libc.) So we'll check first for the
203 # standard Solaris way of linking pthreads (-mt -lpthread).
204
205 ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
206 ;;
207esac
208
209# Are we compiling with Clang?
210
211AC_CACHE_CHECK([whether $CC is Clang],
212 [ax_cv_PTHREAD_CLANG],
213 [ax_cv_PTHREAD_CLANG=no
214 # Note that Autoconf sets GCC=yes for Clang as well as GCC
215 if test "x$GCC" = "xyes"; then
216 AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
217 [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
218# if defined(__clang__) && defined(__llvm__)
219 AX_PTHREAD_CC_IS_CLANG
220# endif
221 ],
222 [ax_cv_PTHREAD_CLANG=yes])
223 fi
224 ])
225ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
226
227
228# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
229
230# Note that for GCC and Clang -pthread generally implies -lpthread,
231# except when -nostdlib is passed.
232# This is problematic using libtool to build C++ shared libraries with pthread:
233# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
234# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
235# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
236# To solve this, first try -pthread together with -lpthread for GCC
237
238AS_IF([test "x$GCC" = "xyes"],
239 [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
240
241# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
242
243AS_IF([test "x$ax_pthread_clang" = "xyes"],
244 [ax_pthread_flags="-pthread,-lpthread -pthread"])
245
246
247# The presence of a feature test macro requesting re-entrant function
248# definitions is, on some systems, a strong hint that pthreads support is
249# correctly enabled
250
251case $host_os in
252 darwin* | hpux* | linux* | osf* | solaris*)
253 ax_pthread_check_macro="_REENTRANT"
254 ;;
255
256 aix*)
257 ax_pthread_check_macro="_THREAD_SAFE"
258 ;;
259
260 *)
261 ax_pthread_check_macro="--"
262 ;;
263esac
264AS_IF([test "x$ax_pthread_check_macro" = "x--"],
265 [ax_pthread_check_cond=0],
266 [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
267
268
269if test "x$ax_pthread_ok" = "xno"; then
270for ax_pthread_try_flag in $ax_pthread_flags; do
271
272 case $ax_pthread_try_flag in
273 none)
274 AC_MSG_CHECKING([whether pthreads work without any flags])
275 ;;
276
277 *,*)
278 PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
279 PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
280 AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
281 ;;
282
283 -*)
284 AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
285 PTHREAD_CFLAGS="$ax_pthread_try_flag"
286 ;;
287
288 pthread-config)
289 AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
290 AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
291 PTHREAD_CFLAGS="`pthread-config --cflags`"
292 PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
293 ;;
294
295 *)
296 AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
297 PTHREAD_LIBS="-l$ax_pthread_try_flag"
298 ;;
299 esac
300
301 ax_pthread_save_CFLAGS="$CFLAGS"
302 ax_pthread_save_LIBS="$LIBS"
303 CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
304 LIBS="$PTHREAD_LIBS $LIBS"
305
306 # Check for various functions. We must include pthread.h,
307 # since some functions may be macros. (On the Sequent, we
308 # need a special flag -Kthread to make this header compile.)
309 # We check for pthread_join because it is in -lpthread on IRIX
310 # while pthread_create is in libc. We check for pthread_attr_init
311 # due to DEC craziness with -lpthreads. We check for
312 # pthread_cleanup_push because it is one of the few pthread
313 # functions on Solaris that doesn't have a non-functional libc stub.
314 # We try pthread_create on general principles.
315
316 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
317# if $ax_pthread_check_cond
318# error "$ax_pthread_check_macro must be defined"
319# endif
320 static void *some_global = NULL;
321 static void routine(void *a)
322 {
323 /* To avoid any unused-parameter or
324 unused-but-set-parameter warning. */
325 some_global = a;
326 }
327 static void *start_routine(void *a) { return a; }],
328 [pthread_t th; pthread_attr_t attr;
329 pthread_create(&th, 0, start_routine, 0);
330 pthread_join(th, 0);
331 pthread_attr_init(&attr);
332 pthread_cleanup_push(routine, 0);
333 pthread_cleanup_pop(0) /* ; */])],
334 [ax_pthread_ok=yes],
335 [])
336
337 CFLAGS="$ax_pthread_save_CFLAGS"
338 LIBS="$ax_pthread_save_LIBS"
339
340 AC_MSG_RESULT([$ax_pthread_ok])
341 AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
342
343 PTHREAD_LIBS=""
344 PTHREAD_CFLAGS=""
345done
346fi
347
348
349# Clang needs special handling, because older versions handle the -pthread
350# option in a rather... idiosyncratic way
351
352if test "x$ax_pthread_clang" = "xyes"; then
353
354 # Clang takes -pthread; it has never supported any other flag
355
356 # (Note 1: This will need to be revisited if a system that Clang
357 # supports has POSIX threads in a separate library. This tends not
358 # to be the way of modern systems, but it's conceivable.)
359
360 # (Note 2: On some systems, notably Darwin, -pthread is not needed
361 # to get POSIX threads support; the API is always present and
362 # active. We could reasonably leave PTHREAD_CFLAGS empty. But
363 # -pthread does define _REENTRANT, and while the Darwin headers
364 # ignore this macro, third-party headers might not.)
365
366 # However, older versions of Clang make a point of warning the user
367 # that, in an invocation where only linking and no compilation is
368 # taking place, the -pthread option has no effect ("argument unused
369 # during compilation"). They expect -pthread to be passed in only
370 # when source code is being compiled.
371 #
372 # Problem is, this is at odds with the way Automake and most other
373 # C build frameworks function, which is that the same flags used in
374 # compilation (CFLAGS) are also used in linking. Many systems
375 # supported by AX_PTHREAD require exactly this for POSIX threads
376 # support, and in fact it is often not straightforward to specify a
377 # flag that is used only in the compilation phase and not in
378 # linking. Such a scenario is extremely rare in practice.
379 #
380 # Even though use of the -pthread flag in linking would only print
381 # a warning, this can be a nuisance for well-run software projects
382 # that build with -Werror. So if the active version of Clang has
383 # this misfeature, we search for an option to squash it.
384
385 AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
386 [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
387 [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
388 # Create an alternate version of $ac_link that compiles and
389 # links in two steps (.c -> .o, .o -> exe) instead of one
390 # (.c -> exe), because the warning occurs only in the second
391 # step
392 ax_pthread_save_ac_link="$ac_link"
393 ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
394 ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
395 ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
396 ax_pthread_save_CFLAGS="$CFLAGS"
397 for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
398 AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
399 CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
400 ac_link="$ax_pthread_save_ac_link"
401 AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
402 [ac_link="$ax_pthread_2step_ac_link"
403 AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
404 [break])
405 ])
406 done
407 ac_link="$ax_pthread_save_ac_link"
408 CFLAGS="$ax_pthread_save_CFLAGS"
409 AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
410 ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
411 ])
412
413 case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
414 no | unknown) ;;
415 *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
416 esac
417
418fi # $ax_pthread_clang = yes
419
420
421
422# Various other checks:
423if test "x$ax_pthread_ok" = "xyes"; then
424 ax_pthread_save_CFLAGS="$CFLAGS"
425 ax_pthread_save_LIBS="$LIBS"
426 CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
427 LIBS="$PTHREAD_LIBS $LIBS"
428
429 # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
430 AC_CACHE_CHECK([for joinable pthread attribute],
431 [ax_cv_PTHREAD_JOINABLE_ATTR],
432 [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
433 for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
434 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
435 [int attr = $ax_pthread_attr; return attr /* ; */])],
436 [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
437 [])
438 done
439 ])
440 AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
441 test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
442 test "x$ax_pthread_joinable_attr_defined" != "xyes"],
443 [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
444 [$ax_cv_PTHREAD_JOINABLE_ATTR],
445 [Define to necessary symbol if this constant
446 uses a non-standard name on your system.])
447 ax_pthread_joinable_attr_defined=yes
448 ])
449
450 AC_CACHE_CHECK([whether more special flags are required for pthreads],
451 [ax_cv_PTHREAD_SPECIAL_FLAGS],
452 [ax_cv_PTHREAD_SPECIAL_FLAGS=no
453 case $host_os in
454 solaris*)
455 ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
456 ;;
457 esac
458 ])
459 AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
460 test "x$ax_pthread_special_flags_added" != "xyes"],
461 [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
462 ax_pthread_special_flags_added=yes])
463
464 AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
465 [ax_cv_PTHREAD_PRIO_INHERIT],
466 [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
467 [[int i = PTHREAD_PRIO_INHERIT;
468 return i;]])],
469 [ax_cv_PTHREAD_PRIO_INHERIT=yes],
470 [ax_cv_PTHREAD_PRIO_INHERIT=no])
471 ])
472 AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
473 test "x$ax_pthread_prio_inherit_defined" != "xyes"],
474 [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
475 ax_pthread_prio_inherit_defined=yes
476 ])
477
478 CFLAGS="$ax_pthread_save_CFLAGS"
479 LIBS="$ax_pthread_save_LIBS"
480
481 # More AIX lossage: compile with *_r variant
482 if test "x$GCC" != "xyes"; then
483 case $host_os in
484 aix*)
485 AS_CASE(["x/$CC"],
486 [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
487 [#handle absolute path differently from PATH based program lookup
488 AS_CASE(["x$CC"],
489 [x/*],
490 [
491 AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
492 AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
493 ],
494 [
495 AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
496 AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
497 ]
498 )
499 ])
500 ;;
501 esac
502 fi
503fi
504
505test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
506test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
507
508AC_SUBST([PTHREAD_LIBS])
509AC_SUBST([PTHREAD_CFLAGS])
510AC_SUBST([PTHREAD_CC])
511AC_SUBST([PTHREAD_CXX])
512
513# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
514if test "x$ax_pthread_ok" = "xyes"; then
515 ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
516 :
517else
518 ax_pthread_ok=no
519 $2
520fi
521AC_LANG_POP
522])dnl AX_PTHREAD
diff --git a/src/Makefile.am b/src/Makefile.am
index 06a6374..f80ffa7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,19 +3,18 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
3AM_CFLAGS = \ 3AM_CFLAGS = \
4 $(GLOBAL_CFLAGS) \ 4 $(GLOBAL_CFLAGS) \
5 $(LFS_CFLAGS) \ 5 $(LFS_CFLAGS) \
6 $(limd_glue_CFLAGS) \
6 $(libusb_CFLAGS) 7 $(libusb_CFLAGS)
7 8
8AM_LDFLAGS = \ 9AM_LDFLAGS = \
9 $(GLOBAL_LDFLAGS) \ 10 $(GLOBAL_LDFLAGS) \
11 $(limd_glue_LIBS) \
10 $(libusb_LIBS) 12 $(libusb_LIBS)
11 13
12lib_LTLIBRARIES = libirecovery-1.0.la 14lib_LTLIBRARIES = libirecovery-1.0.la
13libirecovery_1_0_la_CFLAGS = $(AM_CFLAGS) 15libirecovery_1_0_la_CFLAGS = $(AM_CFLAGS)
14libirecovery_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIRECOVERY_SO_VERSION) -no-undefined 16libirecovery_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIRECOVERY_SO_VERSION) -no-undefined
15libirecovery_1_0_la_SOURCES = \ 17libirecovery_1_0_la_SOURCES = libirecovery.c
16 libirecovery.c \
17 utils.c utils.h \
18 thread.c thread.h
19 18
20if WIN32 19if WIN32
21libirecovery_1_0_la_LDFLAGS += -avoid-version 20libirecovery_1_0_la_LDFLAGS += -avoid-version
diff --git a/src/libirecovery-1.0.pc.in b/src/libirecovery-1.0.pc.in
index 25144da..e6c94a3 100644
--- a/src/libirecovery-1.0.pc.in
+++ b/src/libirecovery-1.0.pc.in
@@ -8,4 +8,4 @@ Description: A library to communicate with iBoot/iBSS on iOS devices via USB
8Version: @PACKAGE_VERSION@ 8Version: @PACKAGE_VERSION@
9Libs: -L${libdir} -lirecovery-1.0 9Libs: -L${libdir} -lirecovery-1.0
10Cflags: -I${includedir} 10Cflags: -I${includedir}
11Requires.private: @LIBUSB_REQUIRED@ 11Requires.private: libimobiledevice-glue-1.0 >= @LIMD_GLUE_VERSION@ @LIBUSB_REQUIRED@
diff --git a/src/libirecovery.c b/src/libirecovery.c
index 2219f36..0446e01 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -32,11 +32,13 @@
32#include <unistd.h> 32#include <unistd.h>
33#include <sys/stat.h> 33#include <sys/stat.h>
34 34
35#include <libimobiledevice-glue/collection.h>
36#include <libimobiledevice-glue/thread.h>
37
35#ifndef USE_DUMMY 38#ifndef USE_DUMMY
36#ifndef WIN32 39#ifndef WIN32
37#ifndef HAVE_IOKIT 40#ifndef HAVE_IOKIT
38#include <libusb.h> 41#include <libusb.h>
39#include <pthread.h>
40#if (defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102)) || (defined(LIBUSBX_API_VERSION) && (LIBUSBX_API_VERSION >= 0x01000102)) 42#if (defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102)) || (defined(LIBUSBX_API_VERSION) && (LIBUSBX_API_VERSION >= 0x01000102))
41#define HAVE_LIBUSB_HOTPLUG_API 1 43#define HAVE_LIBUSB_HOTPLUG_API 1
42#endif 44#endif
@@ -44,7 +46,6 @@
44#include <CoreFoundation/CoreFoundation.h> 46#include <CoreFoundation/CoreFoundation.h>
45#include <IOKit/usb/IOUSBLib.h> 47#include <IOKit/usb/IOUSBLib.h>
46#include <IOKit/IOCFPlugIn.h> 48#include <IOKit/IOCFPlugIn.h>
47#include <pthread.h>
48#endif 49#endif
49#else 50#else
50#define WIN32_LEAN_AND_MEAN 51#define WIN32_LEAN_AND_MEAN
@@ -67,8 +68,6 @@
67#endif 68#endif
68 69
69#include "libirecovery.h" 70#include "libirecovery.h"
70#include "utils.h"
71#include "thread.h"
72 71
73struct irecv_client_private { 72struct irecv_client_private {
74 int debug; 73 int debug;
@@ -2977,8 +2976,8 @@ IRECV_API irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client) {
2977 // which can be accomplished by sending on another thread. 2976 // which can be accomplished by sending on another thread.
2978 2977
2979 void *args[2] = { client->handle, &req }; 2978 void *args[2] = { client->handle, &req };
2980 pthread_t thread; 2979 THREAD_T thread;
2981 pthread_create(&thread, NULL, iokit_limera1n_usb_submit_request, args); 2980 thread_new(&thread, iokit_limera1n_usb_submit_request, args);
2982 2981
2983 usleep(5 * 1000); 2982 usleep(5 * 1000);
2984 result = (*client->handle)->USBDeviceAbortPipeZero(client->handle); 2983 result = (*client->handle)->USBDeviceAbortPipeZero(client->handle);
diff --git a/src/thread.c b/src/thread.c
deleted file mode 100644
index 796ea0b..0000000
--- a/src/thread.c
+++ /dev/null
@@ -1,215 +0,0 @@
1/*
2 * thread.c
3 *
4 * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25#include "thread.h"
26
27int thread_new(THREAD_T *thread, thread_func_t thread_func, void* data)
28{
29#ifdef WIN32
30 HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
31 if (th == NULL) {
32 return -1;
33 }
34 *thread = th;
35 return 0;
36#else
37 int res = pthread_create(thread, NULL, thread_func, data);
38 return res;
39#endif
40}
41
42void thread_detach(THREAD_T thread)
43{
44#ifdef WIN32
45 CloseHandle(thread);
46#else
47 pthread_detach(thread);
48#endif
49}
50
51void thread_free(THREAD_T thread)
52{
53#ifdef WIN32
54 CloseHandle(thread);
55#endif
56}
57
58int thread_join(THREAD_T thread)
59{
60 /* wait for thread to complete */
61#ifdef WIN32
62 return (int)WaitForSingleObject(thread, INFINITE);
63#else
64 return pthread_join(thread, NULL);
65#endif
66}
67
68int thread_alive(THREAD_T thread)
69{
70 if (!thread)
71 return 0;
72#ifdef WIN32
73 return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT;
74#else
75 return pthread_kill(thread, 0) == 0;
76#endif
77}
78
79int thread_cancel(THREAD_T thread)
80{
81#ifdef WIN32
82 return -1;
83#else
84#ifdef HAVE_PTHREAD_CANCEL
85 return pthread_cancel(thread);
86#else
87 return -1;
88#endif
89#endif
90}
91
92void mutex_init(mutex_t* mutex)
93{
94#ifdef WIN32
95 InitializeCriticalSection(mutex);
96#else
97 pthread_mutex_init(mutex, NULL);
98#endif
99}
100
101void mutex_destroy(mutex_t* mutex)
102{
103#ifdef WIN32
104 DeleteCriticalSection(mutex);
105#else
106 pthread_mutex_destroy(mutex);
107#endif
108}
109
110void mutex_lock(mutex_t* mutex)
111{
112#ifdef WIN32
113 EnterCriticalSection(mutex);
114#else
115 pthread_mutex_lock(mutex);
116#endif
117}
118
119void mutex_unlock(mutex_t* mutex)
120{
121#ifdef WIN32
122 LeaveCriticalSection(mutex);
123#else
124 pthread_mutex_unlock(mutex);
125#endif
126}
127
128void thread_once(thread_once_t *once_control, void (*init_routine)(void))
129{
130#ifdef WIN32
131 while (InterlockedExchange(&(once_control->lock), 1) != 0) {
132 Sleep(1);
133 }
134 if (!once_control->state) {
135 once_control->state = 1;
136 init_routine();
137 }
138 InterlockedExchange(&(once_control->lock), 0);
139#else
140 pthread_once(once_control, init_routine);
141#endif
142}
143
144void cond_init(cond_t* cond)
145{
146#ifdef WIN32
147 cond->sem = CreateSemaphore(NULL, 0, 32767, NULL);
148#else
149 pthread_cond_init(cond, NULL);
150#endif
151}
152
153void cond_destroy(cond_t* cond)
154{
155#ifdef WIN32
156 CloseHandle(cond->sem);
157#else
158 pthread_cond_destroy(cond);
159#endif
160}
161
162int cond_signal(cond_t* cond)
163{
164#ifdef WIN32
165 int result = 0;
166 if (!ReleaseSemaphore(cond->sem, 1, NULL)) {
167 result = -1;
168 }
169 return result;
170#else
171 return pthread_cond_signal(cond);
172#endif
173}
174
175int cond_wait(cond_t* cond, mutex_t* mutex)
176{
177#ifdef WIN32
178 mutex_unlock(mutex);
179 DWORD res = WaitForSingleObject(cond->sem, INFINITE);
180 switch (res) {
181 case WAIT_OBJECT_0:
182 return 0;
183 default:
184 return -1;
185 }
186#else
187 return pthread_cond_wait(cond, mutex);
188#endif
189}
190
191int cond_wait_timeout(cond_t* cond, mutex_t* mutex, unsigned int timeout_ms)
192{
193#ifdef WIN32
194 mutex_unlock(mutex);
195 DWORD res = WaitForSingleObject(cond->sem, timeout_ms);
196 switch (res) {
197 case WAIT_OBJECT_0:
198 case WAIT_TIMEOUT:
199 return 0;
200 default:
201 return -1;
202 }
203#else
204 struct timespec ts;
205 struct timeval now;
206 gettimeofday(&now, NULL);
207
208 ts.tv_sec = now.tv_sec + timeout_ms / 1000;
209 ts.tv_nsec = now.tv_usec * 1000 + 1000 * 1000 * (timeout_ms % 1000);
210 ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
211 ts.tv_nsec %= (1000 * 1000 * 1000);
212
213 return pthread_cond_timedwait(cond, mutex, &ts);
214#endif
215}
diff --git a/src/thread.h b/src/thread.h
deleted file mode 100644
index 2aadc6e..0000000
--- a/src/thread.h
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * thread.h
3 *
4 * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef __THREAD_H
23#define __THREAD_H
24
25#include <stddef.h>
26
27#ifdef WIN32
28#include <windows.h>
29typedef HANDLE THREAD_T;
30typedef CRITICAL_SECTION mutex_t;
31typedef struct {
32 HANDLE sem;
33} cond_t;
34typedef volatile struct {
35 LONG lock;
36 int state;
37} thread_once_t;
38#define THREAD_ONCE_INIT {0, 0}
39#define THREAD_ID GetCurrentThreadId()
40#define THREAD_T_NULL (THREAD_T)NULL
41#else
42#include <pthread.h>
43#include <signal.h>
44#include <sys/time.h>
45typedef pthread_t THREAD_T;
46typedef pthread_mutex_t mutex_t;
47typedef pthread_cond_t cond_t;
48typedef pthread_once_t thread_once_t;
49#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT
50#define THREAD_ID pthread_self()
51#define THREAD_T_NULL (THREAD_T)NULL
52#endif
53
54typedef void* (*thread_func_t)(void* data);
55
56int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data);
57void thread_detach(THREAD_T thread);
58void thread_free(THREAD_T thread);
59int thread_join(THREAD_T thread);
60int thread_alive(THREAD_T thread);
61
62int thread_cancel(THREAD_T thread);
63
64#ifdef WIN32
65#undef HAVE_THREAD_CLEANUP
66#else
67#ifdef HAVE_PTHREAD_CANCEL
68#define HAVE_THREAD_CLEANUP 1
69#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg)
70#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
71#endif
72#endif
73
74void mutex_init(mutex_t* mutex);
75void mutex_destroy(mutex_t* mutex);
76void mutex_lock(mutex_t* mutex);
77void mutex_unlock(mutex_t* mutex);
78
79void thread_once(thread_once_t *once_control, void (*init_routine)(void));
80
81void cond_init(cond_t* cond);
82void cond_destroy(cond_t* cond);
83int cond_signal(cond_t* cond);
84int cond_wait(cond_t* cond, mutex_t* mutex);
85int cond_wait_timeout(cond_t* cond, mutex_t* mutex, unsigned int timeout_ms);
86
87#endif
diff --git a/src/utils.c b/src/utils.c
deleted file mode 100644
index 826bfbe..0000000
--- a/src/utils.c
+++ /dev/null
@@ -1,92 +0,0 @@
1/*
2 * utils.c
3 *
4 * Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
5 * Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
6 * Copyright (c) 2013 Federico Mena Quintero
7 *
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation, either version 2.1 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30#include <errno.h>
31
32#include "utils.h"
33
34#define CAPACITY_STEP 8
35
36void collection_init(struct collection *col)
37{
38 col->list = malloc(sizeof(void *) * CAPACITY_STEP);
39 memset(col->list, 0, sizeof(void *) * CAPACITY_STEP);
40 col->capacity = CAPACITY_STEP;
41}
42
43void collection_free(struct collection *col)
44{
45 free(col->list);
46 col->list = NULL;
47 col->capacity = 0;
48}
49
50void collection_add(struct collection *col, void *element)
51{
52 int i;
53 for(i=0; i<col->capacity; i++) {
54 if(!col->list[i]) {
55 col->list[i] = element;
56 return;
57 }
58 }
59 col->list = realloc(col->list, sizeof(void*) * (col->capacity + CAPACITY_STEP));
60 memset(&col->list[col->capacity], 0, sizeof(void *) * CAPACITY_STEP);
61 col->list[col->capacity] = element;
62 col->capacity += CAPACITY_STEP;
63}
64
65void collection_remove(struct collection *col, void *element)
66{
67 int i;
68 for(i=0; i<col->capacity; i++) {
69 if(col->list[i] == element) {
70 col->list[i] = NULL;
71 return;
72 }
73 }
74}
75
76int collection_count(struct collection *col)
77{
78 int i, cnt = 0;
79 for(i=0; i<col->capacity; i++) {
80 if(col->list[i])
81 cnt++;
82 }
83 return cnt;
84}
85
86void collection_copy(struct collection *dest, struct collection *src)
87{
88 if (!dest || !src) return;
89 dest->capacity = src->capacity;
90 dest->list = malloc(sizeof(void*) * src->capacity);
91 memcpy(dest->list, src->list, sizeof(void*) * src->capacity);
92}
diff --git a/src/utils.h b/src/utils.h
deleted file mode 100644
index ccb3a09..0000000
--- a/src/utils.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * utils.h
3 *
4 * Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
5 * Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 2.1 of the
10 * License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef UTILS_H
23#define UTILS_H
24
25struct collection {
26 void **list;
27 int capacity;
28};
29
30void collection_init(struct collection *col);
31void collection_add(struct collection *col, void *element);
32void collection_remove(struct collection *col, void *element);
33int collection_count(struct collection *col);
34void collection_free(struct collection *col);
35void collection_copy(struct collection *dest, struct collection *src);
36
37#define MERGE_(a,b) a ## _ ## b
38#define LABEL_(a,b) MERGE_(a, b)
39#define UNIQUE_VAR(a) LABEL_(a, __LINE__)
40
41#define FOREACH(var, col) \
42 do { \
43 int UNIQUE_VAR(_iter); \
44 for(UNIQUE_VAR(_iter)=0; UNIQUE_VAR(_iter)<(col)->capacity; UNIQUE_VAR(_iter)++) { \
45 if(!(col)->list[UNIQUE_VAR(_iter)]) continue; \
46 var = (col)->list[UNIQUE_VAR(_iter)];
47
48#define ENDFOREACH \
49 } \
50 } while(0);
51
52#endif