summaryrefslogtreecommitdiffstats
path: root/gl
diff options
context:
space:
mode:
authorTon Voon <tonvoon@users.sourceforge.net>2007-01-24 22:47:25 +0000
committerTon Voon <tonvoon@users.sourceforge.net>2007-01-24 22:47:25 +0000
commitfe856aa957978504137c1d425815d4ed8a22be40 (patch)
treea5bb46ce0e64b2056f75700eadbf27aba7c39418 /gl
parent210f39bc84cfbb21cd72dc054e43f13815ee0616 (diff)
downloadmonitoring-plugins-fe856aa957978504137c1d425815d4ed8a22be40.tar.gz
Sync with gnulib - lots of extraneous code removed in preference to GNU code
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1580 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'gl')
-rw-r--r--gl/Makefile.am607
-rw-r--r--gl/alloca.c489
-rw-r--r--gl/alloca_.h54
-rw-r--r--gl/asnprintf.c35
-rw-r--r--gl/asprintf.c35
-rw-r--r--gl/basename.c129
-rw-r--r--gl/c-strtod.c79
-rw-r--r--gl/c-strtod.h2
-rw-r--r--gl/cloexec.c59
-rw-r--r--gl/cloexec.h2
-rw-r--r--gl/creat-safer.c32
-rw-r--r--gl/dirname.c85
-rw-r--r--gl/dirname.h70
-rw-r--r--gl/dup-safer.c45
-rw-r--r--gl/error.c338
-rw-r--r--gl/error.h66
-rw-r--r--gl/exit.h32
-rw-r--r--gl/exitfail.c25
-rw-r--r--gl/exitfail.h20
-rw-r--r--gl/fcntl--.h28
-rw-r--r--gl/fcntl-safer.h24
-rw-r--r--gl/fd-safer.c57
-rw-r--r--gl/fsusage.c264
-rw-r--r--gl/fsusage.h41
-rw-r--r--gl/full-read.c19
-rw-r--r--gl/full-read.h24
-rw-r--r--gl/full-write.c81
-rw-r--r--gl/full-write.h35
-rw-r--r--gl/gai_strerror.c77
-rw-r--r--gl/getaddrinfo.c417
-rw-r--r--gl/getaddrinfo.h155
-rw-r--r--gl/gethostname.c52
-rw-r--r--gl/getloadavg.c1020
-rw-r--r--gl/getopt.c1191
-rw-r--r--gl/getopt1.c171
-rw-r--r--gl/getopt_.h226
-rw-r--r--gl/getopt_int.h131
-rw-r--r--gl/gettext.h270
-rw-r--r--gl/inet_ntop.c238
-rw-r--r--gl/inet_ntop.h42
-rw-r--r--gl/intprops.h78
-rw-r--r--gl/m4/absolute-header.m444
-rw-r--r--gl/m4/alloca.m450
-rw-r--r--gl/m4/arpa_inet_h.m418
-rw-r--r--gl/m4/c-strtod.m453
-rw-r--r--gl/m4/cloexec.m410
-rw-r--r--gl/m4/codeset.m421
-rw-r--r--gl/m4/dirname.m418
-rw-r--r--gl/m4/dos.m471
-rw-r--r--gl/m4/double-slash-root.m438
-rw-r--r--gl/m4/eoverflow.m470
-rw-r--r--gl/m4/error.m422
-rw-r--r--gl/m4/exitfail.m413
-rw-r--r--gl/m4/extensions.m458
-rw-r--r--gl/m4/fcntl-safer.m411
-rw-r--r--gl/m4/fstypename.m422
-rw-r--r--gl/m4/fsusage.m4265
-rw-r--r--gl/m4/getaddrinfo.m488
-rw-r--r--gl/m4/gethostname.m418
-rw-r--r--gl/m4/getloadavg.m4155
-rw-r--r--gl/m4/getopt.m483
-rw-r--r--gl/m4/gettext.m4419
-rw-r--r--gl/m4/glibc2.m430
-rw-r--r--gl/m4/glibc21.m430
-rw-r--r--gl/m4/gnulib-cache.m430
-rw-r--r--gl/m4/gnulib-common.m422
-rw-r--r--gl/m4/gnulib-comp.m4326
-rw-r--r--gl/m4/gnulib-tool.m433
-rw-r--r--gl/m4/iconv.m4101
-rw-r--r--gl/m4/inet_ntop.m419
-rw-r--r--gl/m4/inline.m440
-rw-r--r--gl/m4/intdiv0.m470
-rw-r--r--gl/m4/intl.m4259
-rw-r--r--gl/m4/intldir.m419
-rw-r--r--gl/m4/intmax.m433
-rw-r--r--gl/m4/intmax_t.m461
-rw-r--r--gl/m4/inttypes-pri.m436
-rw-r--r--gl/m4/inttypes_h.m426
-rw-r--r--gl/m4/lcmessage.m430
-rw-r--r--gl/m4/lib-ld.m4110
-rw-r--r--gl/m4/lib-link.m4709
-rw-r--r--gl/m4/lib-prefix.m4185
-rw-r--r--gl/m4/lock.m4311
-rw-r--r--gl/m4/longdouble.m431
-rw-r--r--gl/m4/longlong.m472
-rw-r--r--gl/m4/ls-mntd-fs.m4337
-rw-r--r--gl/m4/mbchar.m414
-rw-r--r--gl/m4/mbiter.m417
-rw-r--r--gl/m4/mbrtowc.m431
-rw-r--r--gl/m4/memchr.m418
-rw-r--r--gl/m4/minmax.m441
-rw-r--r--gl/m4/mountlist.m423
-rw-r--r--gl/m4/netinet_in_h.m418
-rw-r--r--gl/m4/nls.m431
-rw-r--r--gl/m4/onceonly_2_57.m486
-rw-r--r--gl/m4/po.m4428
-rw-r--r--gl/m4/printf-posix.m444
-rw-r--r--gl/m4/progtest.m492
-rw-r--r--gl/m4/regex.m4198
-rw-r--r--gl/m4/safe-read.m418
-rw-r--r--gl/m4/safe-write.m418
-rw-r--r--gl/m4/size_max.m468
-rw-r--r--gl/m4/snprintf.m415
-rw-r--r--gl/m4/socklen.m452
-rw-r--r--gl/m4/sockpfaf.m458
-rw-r--r--gl/m4/ssize_t.m421
-rw-r--r--gl/m4/stdbool.m4115
-rw-r--r--gl/m4/stdint.m4369
-rw-r--r--gl/m4/stdint_h.m426
-rw-r--r--gl/m4/strcase.m439
-rw-r--r--gl/m4/strdup.m415
-rw-r--r--gl/m4/strndup.m448
-rw-r--r--gl/m4/strnlen.m427
-rw-r--r--gl/m4/sys_socket_h.m423
-rw-r--r--gl/m4/uintmax_t.m430
-rw-r--r--gl/m4/ulonglong.m448
-rw-r--r--gl/m4/unistd-safer.m413
-rw-r--r--gl/m4/unistd_h.m432
-rw-r--r--gl/m4/vasnprintf.m457
-rw-r--r--gl/m4/vasprintf.m433
-rw-r--r--gl/m4/visibility.m452
-rw-r--r--gl/m4/vsnprintf.m415
-rw-r--r--gl/m4/wchar.m429
-rw-r--r--gl/m4/wchar_t.m420
-rw-r--r--gl/m4/wctype.m441
-rw-r--r--gl/m4/wcwidth.m430
-rw-r--r--gl/m4/wint_t.m428
-rw-r--r--gl/m4/xalloc.m424
-rw-r--r--gl/m4/xsize.m413
-rw-r--r--gl/m4/xstrndup.m415
-rw-r--r--gl/malloc.c35
-rw-r--r--gl/mbchar.c36
-rw-r--r--gl/mbchar.h353
-rw-r--r--gl/mbuiter.h203
-rw-r--r--gl/memchr.c201
-rw-r--r--gl/minmax.h60
-rw-r--r--gl/mountlist.c889
-rw-r--r--gl/mountlist.h41
-rw-r--r--gl/open-safer.c50
-rw-r--r--gl/pipe-safer.c57
-rw-r--r--gl/printf-args.c141
-rw-r--r--gl/printf-args.h136
-rw-r--r--gl/printf-parse.c543
-rw-r--r--gl/printf-parse.h74
-rw-r--r--gl/regcomp.c3858
-rw-r--r--gl/regex.c71
-rw-r--r--gl/regex.h671
-rw-r--r--gl/regex_internal.c1742
-rw-r--r--gl/regex_internal.h862
-rw-r--r--gl/regexec.c4398
-rw-r--r--gl/safe-read.c78
-rw-r--r--gl/safe-read.h35
-rw-r--r--gl/safe-write.c19
-rw-r--r--gl/safe-write.h25
-rw-r--r--gl/size_max.h31
-rw-r--r--gl/snprintf.c76
-rw-r--r--gl/snprintf.h29
-rw-r--r--gl/socket_.h70
-rw-r--r--gl/stdbool_.h115
-rw-r--r--gl/stdint_.h489
-rw-r--r--gl/strcase.h56
-rw-r--r--gl/strcasecmp.c103
-rw-r--r--gl/strdup.c55
-rw-r--r--gl/strdup.h39
-rw-r--r--gl/stripslash.c45
-rw-r--r--gl/strncasecmp.c63
-rw-r--r--gl/strndup.c39
-rw-r--r--gl/strndup.h32
-rw-r--r--gl/strnlen.c31
-rw-r--r--gl/strnlen.h32
-rw-r--r--gl/strnlen1.c36
-rw-r--r--gl/strnlen1.h40
-rw-r--r--gl/unistd--.h28
-rw-r--r--gl/unistd-safer.h23
-rw-r--r--gl/unistd_.h52
-rw-r--r--gl/vasnprintf.c889
-rw-r--r--gl/vasnprintf.h77
-rw-r--r--gl/vasprintf.c52
-rw-r--r--gl/vasprintf.h63
-rw-r--r--gl/vsnprintf.c77
-rw-r--r--gl/vsnprintf.h31
-rw-r--r--gl/wchar_.h42
-rw-r--r--gl/wctype_.h154
-rw-r--r--gl/wcwidth.h57
-rw-r--r--gl/xalloc-die.c42
-rw-r--r--gl/xalloc.h267
-rw-r--r--gl/xmalloc.c123
-rw-r--r--gl/xsize.h108
-rw-r--r--gl/xstrndup.c37
-rw-r--r--gl/xstrndup.h24
190 files changed, 31850 insertions, 0 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am
new file mode 100644
index 00000000..67c9872d
--- /dev/null
+++ b/gl/Makefile.am
@@ -0,0 +1,607 @@
1## DO NOT EDIT! GENERATED AUTOMATICALLY!
2## Process this file with automake to produce Makefile.in.
3# Copyright (C) 2004-2007 Free Software Foundation, Inc.
4#
5# This file is free software, distributed under the terms of the GNU
6# General Public License. As a special exception to the GNU General
7# Public License, this file may be distributed as part of a program
8# that contains a configuration script generated by Autoconf, under
9# the same distribution terms as the rest of that program.
10#
11# Generated by gnulib-tool.
12# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --aux-dir=. --no-libtool --macro-prefix=gl dirname fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex vasprintf vsnprintf
13
14AUTOMAKE_OPTIONS = 1.5 gnits
15
16noinst_HEADERS =
17noinst_LIBRARIES =
18noinst_LTLIBRARIES =
19EXTRA_DIST =
20BUILT_SOURCES =
21SUFFIXES =
22MOSTLYCLEANFILES = core *.stackdump
23MOSTLYCLEANDIRS =
24CLEANFILES =
25DISTCLEANFILES =
26MAINTAINERCLEANFILES =
27
28AM_CPPFLAGS =
29
30noinst_LIBRARIES += libgnu.a
31
32libgnu_a_SOURCES =
33libgnu_a_LIBADD = $(gl_LIBOBJS)
34libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
35EXTRA_libgnu_a_SOURCES =
36
37## begin gnulib module alloca
38
39
40EXTRA_DIST += alloca.c
41
42EXTRA_libgnu_a_SOURCES += alloca.c
43
44libgnu_a_LIBADD += @ALLOCA@
45libgnu_a_DEPENDENCIES += @ALLOCA@
46## end gnulib module alloca
47
48## begin gnulib module alloca-opt
49
50BUILT_SOURCES += $(ALLOCA_H)
51
52# We need the following in order to create <alloca.h> when the system
53# doesn't have one that works with the given compiler.
54alloca.h: alloca_.h
55 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
56 cat $(srcdir)/alloca_.h; \
57 } > $@-t
58 mv -f $@-t $@
59MOSTLYCLEANFILES += alloca.h alloca.h-t
60
61EXTRA_DIST += alloca_.h
62
63## end gnulib module alloca-opt
64
65## begin gnulib module arpa_inet
66
67BUILT_SOURCES += $(ARPA_INET_H)
68
69# We need the following in order to create <arpa/inet.h> when the system
70# doesn't have one.
71arpa/inet.h:
72 test -d arpa || mkdir arpa
73 rm -f $@-t $@
74 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
75 echo '#include <sys/socket.h>'; \
76 } > $@-t
77 mv $@-t $@
78MOSTLYCLEANFILES += arpa/inet.h arpa/inet.h-t
79MOSTLYCLEANDIRS += arpa
80
81## end gnulib module arpa_inet
82
83## begin gnulib module c-strtod
84
85
86EXTRA_DIST += c-strtod.c c-strtod.h
87
88EXTRA_libgnu_a_SOURCES += c-strtod.c
89
90## end gnulib module c-strtod
91
92## begin gnulib module cloexec
93
94
95EXTRA_DIST += cloexec.c cloexec.h
96
97EXTRA_libgnu_a_SOURCES += cloexec.c
98
99## end gnulib module cloexec
100
101## begin gnulib module dirname
102
103
104EXTRA_DIST += basename.c dirname.c dirname.h stripslash.c
105
106EXTRA_libgnu_a_SOURCES += basename.c dirname.c stripslash.c
107
108## end gnulib module dirname
109
110## begin gnulib module error
111
112
113EXTRA_DIST += error.c error.h
114
115EXTRA_libgnu_a_SOURCES += error.c
116
117## end gnulib module error
118
119## begin gnulib module exit
120
121libgnu_a_SOURCES += exit.h
122
123## end gnulib module exit
124
125## begin gnulib module exitfail
126
127
128EXTRA_DIST += exitfail.c exitfail.h
129
130EXTRA_libgnu_a_SOURCES += exitfail.c
131
132## end gnulib module exitfail
133
134## begin gnulib module fcntl-safer
135
136
137EXTRA_DIST += creat-safer.c fcntl--.h fcntl-safer.h open-safer.c
138
139EXTRA_libgnu_a_SOURCES += creat-safer.c open-safer.c
140
141## end gnulib module fcntl-safer
142
143## begin gnulib module fsusage
144
145
146EXTRA_DIST += fsusage.c fsusage.h
147
148EXTRA_libgnu_a_SOURCES += fsusage.c
149
150## end gnulib module fsusage
151
152## begin gnulib module full-read
153
154libgnu_a_SOURCES += full-read.h full-read.c
155
156## end gnulib module full-read
157
158## begin gnulib module full-write
159
160libgnu_a_SOURCES += full-write.h full-write.c
161
162## end gnulib module full-write
163
164## begin gnulib module getaddrinfo
165
166
167EXTRA_DIST += gai_strerror.c getaddrinfo.c getaddrinfo.h
168
169EXTRA_libgnu_a_SOURCES += gai_strerror.c getaddrinfo.c
170
171## end gnulib module getaddrinfo
172
173## begin gnulib module gethostname
174
175
176EXTRA_DIST += gethostname.c
177
178EXTRA_libgnu_a_SOURCES += gethostname.c
179
180## end gnulib module gethostname
181
182## begin gnulib module getloadavg
183
184
185EXTRA_DIST += getloadavg.c
186
187EXTRA_libgnu_a_SOURCES += getloadavg.c
188
189## end gnulib module getloadavg
190
191## begin gnulib module getopt
192
193BUILT_SOURCES += $(GETOPT_H)
194
195# We need the following in order to create <getopt.h> when the system
196# doesn't have one that works with the given compiler.
197getopt.h: getopt_.h
198 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
199 cat $(srcdir)/getopt_.h; \
200 } > $@-t
201 mv -f $@-t $@
202MOSTLYCLEANFILES += getopt.h getopt.h-t
203
204EXTRA_DIST += getopt.c getopt1.c getopt_.h getopt_int.h
205
206EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c
207
208## end gnulib module getopt
209
210## begin gnulib module gettext
211
212# This is for those projects which use "gettextize --intl" to put a source-code
213# copy of libintl into their package. In such projects, every Makefile.am needs
214# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
215# For the Makefile.ams in other directories it is the maintainer's
216# responsibility; for the one from gnulib we do it here.
217# This option has no effect when the user disables NLS (because then the intl
218# directory contains no libintl.h file) or when the project does not use
219# "gettextize --intl".
220AM_CPPFLAGS += -I$(top_builddir)/intl
221
222## end gnulib module gettext
223
224## begin gnulib module gettext-h
225
226libgnu_a_SOURCES += gettext.h
227
228## end gnulib module gettext-h
229
230## begin gnulib module inet_ntop
231
232
233EXTRA_DIST += inet_ntop.c inet_ntop.h
234
235EXTRA_libgnu_a_SOURCES += inet_ntop.c
236
237## end gnulib module inet_ntop
238
239## begin gnulib module intprops
240
241
242EXTRA_DIST += intprops.h
243
244## end gnulib module intprops
245
246## begin gnulib module malloc
247
248
249EXTRA_DIST += malloc.c
250
251EXTRA_libgnu_a_SOURCES += malloc.c
252
253## end gnulib module malloc
254
255## begin gnulib module mbchar
256
257
258EXTRA_DIST += mbchar.c mbchar.h
259
260EXTRA_libgnu_a_SOURCES += mbchar.c
261
262## end gnulib module mbchar
263
264## begin gnulib module mbuiter
265
266libgnu_a_SOURCES += mbuiter.h
267
268## end gnulib module mbuiter
269
270## begin gnulib module memchr
271
272
273EXTRA_DIST += memchr.c
274
275EXTRA_libgnu_a_SOURCES += memchr.c
276
277## end gnulib module memchr
278
279## begin gnulib module minmax
280
281libgnu_a_SOURCES += minmax.h
282
283## end gnulib module minmax
284
285## begin gnulib module mountlist
286
287
288EXTRA_DIST += mountlist.c mountlist.h
289
290EXTRA_libgnu_a_SOURCES += mountlist.c
291
292## end gnulib module mountlist
293
294## begin gnulib module netinet_in
295
296BUILT_SOURCES += $(NETINET_IN_H)
297
298# We need the following in order to create <netinet/in.h> when the system
299# doesn't have one.
300netinet/in.h:
301 test -d netinet || mkdir netinet
302 rm -f $@-t $@
303 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
304 echo '#include <sys/socket.h>'; \
305 } > $@-t
306 mv $@-t $@
307MOSTLYCLEANFILES += netinet/in.h netinet/in.h-t
308MOSTLYCLEANDIRS += netinet
309
310## end gnulib module netinet_in
311
312## begin gnulib module regex
313
314
315EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c
316
317EXTRA_libgnu_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c
318
319## end gnulib module regex
320
321## begin gnulib module safe-read
322
323
324EXTRA_DIST += safe-read.c safe-read.h
325
326EXTRA_libgnu_a_SOURCES += safe-read.c
327
328## end gnulib module safe-read
329
330## begin gnulib module safe-write
331
332
333EXTRA_DIST += safe-write.c safe-write.h
334
335EXTRA_libgnu_a_SOURCES += safe-write.c
336
337## end gnulib module safe-write
338
339## begin gnulib module size_max
340
341libgnu_a_SOURCES += size_max.h
342
343## end gnulib module size_max
344
345## begin gnulib module snprintf
346
347
348EXTRA_DIST += snprintf.c snprintf.h
349
350EXTRA_libgnu_a_SOURCES += snprintf.c
351
352## end gnulib module snprintf
353
354## begin gnulib module stdbool
355
356BUILT_SOURCES += $(STDBOOL_H)
357
358# We need the following in order to create <stdbool.h> when the system
359# doesn't have one that works.
360stdbool.h: stdbool_.h
361 rm -f $@-t $@
362 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
363 sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h; \
364 } > $@-t
365 mv $@-t $@
366MOSTLYCLEANFILES += stdbool.h stdbool.h-t
367
368EXTRA_DIST += stdbool_.h
369
370## end gnulib module stdbool
371
372## begin gnulib module stdint
373
374BUILT_SOURCES += $(STDINT_H)
375
376# We need the following in order to create <stdint.h> when the system
377# doesn't have one that works with the given compiler.
378stdint.h: stdint_.h
379 rm -f $@-t $@
380 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
381 sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
382 -e 's|@''ABSOLUTE_STDINT_H''@|$(ABSOLUTE_STDINT_H)|g' \
383 -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
384 -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
385 -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
386 -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
387 -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
388 -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
389 -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
390 -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
391 -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
392 -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
393 -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
394 -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
395 -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
396 -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
397 -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
398 -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
399 -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
400 -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
401 -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
402 < $(srcdir)/stdint_.h; \
403 } > $@-t
404 mv $@-t $@
405MOSTLYCLEANFILES += stdint.h stdint.h-t
406
407EXTRA_DIST += stdint_.h
408
409## end gnulib module stdint
410
411## begin gnulib module strcase
412
413
414EXTRA_DIST += strcase.h strcasecmp.c strncasecmp.c
415
416EXTRA_libgnu_a_SOURCES += strcasecmp.c strncasecmp.c
417
418## end gnulib module strcase
419
420## begin gnulib module strdup
421
422
423EXTRA_DIST += strdup.c strdup.h
424
425EXTRA_libgnu_a_SOURCES += strdup.c
426
427## end gnulib module strdup
428
429## begin gnulib module strndup
430
431
432EXTRA_DIST += strndup.c strndup.h
433
434EXTRA_libgnu_a_SOURCES += strndup.c
435
436## end gnulib module strndup
437
438## begin gnulib module strnlen
439
440
441EXTRA_DIST += strnlen.c strnlen.h
442
443EXTRA_libgnu_a_SOURCES += strnlen.c
444
445## end gnulib module strnlen
446
447## begin gnulib module strnlen1
448
449libgnu_a_SOURCES += strnlen1.h strnlen1.c
450
451## end gnulib module strnlen1
452
453## begin gnulib module sys_socket
454
455BUILT_SOURCES += $(SYS_SOCKET_H)
456
457# We need the following in order to create <sys/socket.h> when the system
458# doesn't have one that works with the given compiler.
459sys/socket.h: socket_.h
460 @MKDIR_P@ sys
461 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
462 cat $(srcdir)/socket_.h; \
463 } > $@-t
464 mv -f $@-t $@
465MOSTLYCLEANFILES += sys/socket.h sys/socket.h-t
466MOSTLYCLEANDIRS += sys
467
468EXTRA_DIST += socket_.h
469
470## end gnulib module sys_socket
471
472## begin gnulib module unistd
473
474BUILT_SOURCES += $(UNISTD_H)
475
476# We need the following in order to create an empty placeholder for
477# <unistd.h> when the system doesn't have one.
478unistd.h: unistd_.h
479 rm -f $@-t $@
480 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
481 sed -e 's|@''ABSOLUTE_UNISTD_H''@|$(ABSOLUTE_UNISTD_H)|g' \
482 < $(srcdir)/unistd_.h; \
483 } > $@-t
484 mv $@-t $@
485MOSTLYCLEANFILES += unistd.h unistd.h-t
486
487EXTRA_DIST += unistd_.h
488
489## end gnulib module unistd
490
491## begin gnulib module unistd-safer
492
493
494EXTRA_DIST += dup-safer.c fd-safer.c pipe-safer.c unistd--.h unistd-safer.h
495
496EXTRA_libgnu_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c
497
498## end gnulib module unistd-safer
499
500## begin gnulib module vasnprintf
501
502
503EXTRA_DIST += asnprintf.c printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h
504
505EXTRA_libgnu_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c
506
507## end gnulib module vasnprintf
508
509## begin gnulib module vasprintf
510
511
512EXTRA_DIST += asprintf.c vasprintf.c vasprintf.h
513
514EXTRA_libgnu_a_SOURCES += asprintf.c vasprintf.c
515
516## end gnulib module vasprintf
517
518## begin gnulib module vsnprintf
519
520
521EXTRA_DIST += vsnprintf.c vsnprintf.h
522
523EXTRA_libgnu_a_SOURCES += vsnprintf.c
524
525## end gnulib module vsnprintf
526
527## begin gnulib module wchar
528
529BUILT_SOURCES += $(WCHAR_H)
530
531# We need the following in order to create <wchar.h> when the system
532# version does not work standalone.
533wchar.h: wchar_.h
534 rm -f $@-t $@
535 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
536 sed -e 's|@''ABSOLUTE_WCHAR_H''@|$(ABSOLUTE_WCHAR_H)|g' \
537 < $(srcdir)/wchar_.h; \
538 } > $@-t
539 mv $@-t $@
540MOSTLYCLEANFILES += wchar.h wchar.h-t
541
542EXTRA_DIST += wchar_.h
543
544## end gnulib module wchar
545
546## begin gnulib module wctype
547
548BUILT_SOURCES += $(WCTYPE_H)
549
550# We need the following in order to create <wctype.h> when the system
551# doesn't have one that works with the given compiler.
552wctype.h: wctype_.h
553 rm -f $@-t $@
554 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
555 sed -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \
556 -e 's|@''ABSOLUTE_WCTYPE_H''@|$(ABSOLUTE_WCTYPE_H)|g' \
557 -e 's/@''HAVE_WCTYPE_CTMP_BUG''@/$(HAVE_WCTYPE_CTMP_BUG)/g' \
558 -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \
559 < $(srcdir)/wctype_.h; \
560 } > $@-t
561 mv $@-t $@
562MOSTLYCLEANFILES += wctype.h wctype.h-t
563
564EXTRA_DIST += wctype_.h
565
566## end gnulib module wctype
567
568## begin gnulib module wcwidth
569
570libgnu_a_SOURCES += wcwidth.h
571
572## end gnulib module wcwidth
573
574## begin gnulib module xalloc
575
576
577EXTRA_DIST += xalloc.h xmalloc.c
578
579EXTRA_libgnu_a_SOURCES += xmalloc.c
580
581## end gnulib module xalloc
582
583## begin gnulib module xalloc-die
584
585libgnu_a_SOURCES += xalloc-die.c
586
587## end gnulib module xalloc-die
588
589## begin gnulib module xsize
590
591libgnu_a_SOURCES += xsize.h
592
593## end gnulib module xsize
594
595## begin gnulib module xstrndup
596
597libgnu_a_SOURCES += xstrndup.h xstrndup.c
598
599## end gnulib module xstrndup
600
601
602mostlyclean-local: mostlyclean-generic
603 @for dir in '' $(MOSTLYCLEANDIRS); do \
604 if test -n "$$dir" && test -d $$dir; then \
605 echo "rmdir $$dir"; rmdir $$dir; \
606 fi; \
607 done
diff --git a/gl/alloca.c b/gl/alloca.c
new file mode 100644
index 00000000..3a1f4e27
--- /dev/null
+++ b/gl/alloca.c
@@ -0,0 +1,489 @@
1/* alloca.c -- allocate automatically reclaimed memory
2 (Mostly) portable public-domain implementation -- D A Gwyn
3
4 This implementation of the PWB library alloca function,
5 which is used to allocate space off the run-time stack so
6 that it is automatically reclaimed upon procedure exit,
7 was inspired by discussions with J. Q. Johnson of Cornell.
8 J.Otto Tennant <jot@cray.com> contributed the Cray support.
9
10 There are some preprocessor constants that can
11 be defined when compiling for your specific system, for
12 improved efficiency; however, the defaults should be okay.
13
14 The general concept of this implementation is to keep
15 track of all alloca-allocated blocks, and reclaim any
16 that are found to be deeper in the stack than the current
17 invocation. This heuristic does not reclaim storage as
18 soon as it becomes invalid, but it will do so eventually.
19
20 As a special case, alloca(0) reclaims storage without
21 allocating any. It is a good idea to use alloca(0) in
22 your main control loop, etc. to force garbage collection. */
23
24#include <config.h>
25
26#include <alloca.h>
27
28#include <string.h>
29#include <stdlib.h>
30
31#ifdef emacs
32# include "lisp.h"
33# include "blockinput.h"
34# ifdef EMACS_FREE
35# undef free
36# define free EMACS_FREE
37# endif
38#else
39# define memory_full() abort ()
40#endif
41
42/* If compiling with GCC 2, this file's not needed. */
43#if !defined (__GNUC__) || __GNUC__ < 2
44
45/* If someone has defined alloca as a macro,
46 there must be some other way alloca is supposed to work. */
47# ifndef alloca
48
49# ifdef emacs
50# ifdef static
51/* actually, only want this if static is defined as ""
52 -- this is for usg, in which emacs must undefine static
53 in order to make unexec workable
54 */
55# ifndef STACK_DIRECTION
56you
57lose
58-- must know STACK_DIRECTION at compile-time
59/* Using #error here is not wise since this file should work for
60 old and obscure compilers. */
61# endif /* STACK_DIRECTION undefined */
62# endif /* static */
63# endif /* emacs */
64
65/* If your stack is a linked list of frames, you have to
66 provide an "address metric" ADDRESS_FUNCTION macro. */
67
68# if defined (CRAY) && defined (CRAY_STACKSEG_END)
69long i00afunc ();
70# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
71# else
72# define ADDRESS_FUNCTION(arg) &(arg)
73# endif
74
75/* Define STACK_DIRECTION if you know the direction of stack
76 growth for your system; otherwise it will be automatically
77 deduced at run-time.
78
79 STACK_DIRECTION > 0 => grows toward higher addresses
80 STACK_DIRECTION < 0 => grows toward lower addresses
81 STACK_DIRECTION = 0 => direction of growth unknown */
82
83# ifndef STACK_DIRECTION
84# define STACK_DIRECTION 0 /* Direction unknown. */
85# endif
86
87# if STACK_DIRECTION != 0
88
89# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
90
91# else /* STACK_DIRECTION == 0; need run-time code. */
92
93static int stack_dir; /* 1 or -1 once known. */
94# define STACK_DIR stack_dir
95
96static void
97find_stack_direction (void)
98{
99 static char *addr = NULL; /* Address of first `dummy', once known. */
100 auto char dummy; /* To get stack address. */
101
102 if (addr == NULL)
103 { /* Initial entry. */
104 addr = ADDRESS_FUNCTION (dummy);
105
106 find_stack_direction (); /* Recurse once. */
107 }
108 else
109 {
110 /* Second entry. */
111 if (ADDRESS_FUNCTION (dummy) > addr)
112 stack_dir = 1; /* Stack grew upward. */
113 else
114 stack_dir = -1; /* Stack grew downward. */
115 }
116}
117
118# endif /* STACK_DIRECTION == 0 */
119
120/* An "alloca header" is used to:
121 (a) chain together all alloca'ed blocks;
122 (b) keep track of stack depth.
123
124 It is very important that sizeof(header) agree with malloc
125 alignment chunk size. The following default should work okay. */
126
127# ifndef ALIGN_SIZE
128# define ALIGN_SIZE sizeof(double)
129# endif
130
131typedef union hdr
132{
133 char align[ALIGN_SIZE]; /* To force sizeof(header). */
134 struct
135 {
136 union hdr *next; /* For chaining headers. */
137 char *deep; /* For stack depth measure. */
138 } h;
139} header;
140
141static header *last_alloca_header = NULL; /* -> last alloca header. */
142
143/* Return a pointer to at least SIZE bytes of storage,
144 which will be automatically reclaimed upon exit from
145 the procedure that called alloca. Originally, this space
146 was supposed to be taken from the current stack frame of the
147 caller, but that method cannot be made to work for some
148 implementations of C, for example under Gould's UTX/32. */
149
150void *
151alloca (size_t size)
152{
153 auto char probe; /* Probes stack depth: */
154 register char *depth = ADDRESS_FUNCTION (probe);
155
156# if STACK_DIRECTION == 0
157 if (STACK_DIR == 0) /* Unknown growth direction. */
158 find_stack_direction ();
159# endif
160
161 /* Reclaim garbage, defined as all alloca'd storage that
162 was allocated from deeper in the stack than currently. */
163
164 {
165 register header *hp; /* Traverses linked list. */
166
167# ifdef emacs
168 BLOCK_INPUT;
169# endif
170
171 for (hp = last_alloca_header; hp != NULL;)
172 if ((STACK_DIR > 0 && hp->h.deep > depth)
173 || (STACK_DIR < 0 && hp->h.deep < depth))
174 {
175 register header *np = hp->h.next;
176
177 free (hp); /* Collect garbage. */
178
179 hp = np; /* -> next header. */
180 }
181 else
182 break; /* Rest are not deeper. */
183
184 last_alloca_header = hp; /* -> last valid storage. */
185
186# ifdef emacs
187 UNBLOCK_INPUT;
188# endif
189 }
190
191 if (size == 0)
192 return NULL; /* No allocation required. */
193
194 /* Allocate combined header + user data storage. */
195
196 {
197 /* Address of header. */
198 register header *new;
199
200 size_t combined_size = sizeof (header) + size;
201 if (combined_size < sizeof (header))
202 memory_full ();
203
204 new = malloc (combined_size);
205
206 if (! new)
207 memory_full ();
208
209 new->h.next = last_alloca_header;
210 new->h.deep = depth;
211
212 last_alloca_header = new;
213
214 /* User storage begins just after header. */
215
216 return (void *) (new + 1);
217 }
218}
219
220# if defined (CRAY) && defined (CRAY_STACKSEG_END)
221
222# ifdef DEBUG_I00AFUNC
223# include <stdio.h>
224# endif
225
226# ifndef CRAY_STACK
227# define CRAY_STACK
228# ifndef CRAY2
229/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
230struct stack_control_header
231 {
232 long shgrow:32; /* Number of times stack has grown. */
233 long shaseg:32; /* Size of increments to stack. */
234 long shhwm:32; /* High water mark of stack. */
235 long shsize:32; /* Current size of stack (all segments). */
236 };
237
238/* The stack segment linkage control information occurs at
239 the high-address end of a stack segment. (The stack
240 grows from low addresses to high addresses.) The initial
241 part of the stack segment linkage control information is
242 0200 (octal) words. This provides for register storage
243 for the routine which overflows the stack. */
244
245struct stack_segment_linkage
246 {
247 long ss[0200]; /* 0200 overflow words. */
248 long sssize:32; /* Number of words in this segment. */
249 long ssbase:32; /* Offset to stack base. */
250 long:32;
251 long sspseg:32; /* Offset to linkage control of previous
252 segment of stack. */
253 long:32;
254 long sstcpt:32; /* Pointer to task common address block. */
255 long sscsnm; /* Private control structure number for
256 microtasking. */
257 long ssusr1; /* Reserved for user. */
258 long ssusr2; /* Reserved for user. */
259 long sstpid; /* Process ID for pid based multi-tasking. */
260 long ssgvup; /* Pointer to multitasking thread giveup. */
261 long sscray[7]; /* Reserved for Cray Research. */
262 long ssa0;
263 long ssa1;
264 long ssa2;
265 long ssa3;
266 long ssa4;
267 long ssa5;
268 long ssa6;
269 long ssa7;
270 long sss0;
271 long sss1;
272 long sss2;
273 long sss3;
274 long sss4;
275 long sss5;
276 long sss6;
277 long sss7;
278 };
279
280# else /* CRAY2 */
281/* The following structure defines the vector of words
282 returned by the STKSTAT library routine. */
283struct stk_stat
284 {
285 long now; /* Current total stack size. */
286 long maxc; /* Amount of contiguous space which would
287 be required to satisfy the maximum
288 stack demand to date. */
289 long high_water; /* Stack high-water mark. */
290 long overflows; /* Number of stack overflow ($STKOFEN) calls. */
291 long hits; /* Number of internal buffer hits. */
292 long extends; /* Number of block extensions. */
293 long stko_mallocs; /* Block allocations by $STKOFEN. */
294 long underflows; /* Number of stack underflow calls ($STKRETN). */
295 long stko_free; /* Number of deallocations by $STKRETN. */
296 long stkm_free; /* Number of deallocations by $STKMRET. */
297 long segments; /* Current number of stack segments. */
298 long maxs; /* Maximum number of stack segments so far. */
299 long pad_size; /* Stack pad size. */
300 long current_address; /* Current stack segment address. */
301 long current_size; /* Current stack segment size. This
302 number is actually corrupted by STKSTAT to
303 include the fifteen word trailer area. */
304 long initial_address; /* Address of initial segment. */
305 long initial_size; /* Size of initial segment. */
306 };
307
308/* The following structure describes the data structure which trails
309 any stack segment. I think that the description in 'asdef' is
310 out of date. I only describe the parts that I am sure about. */
311
312struct stk_trailer
313 {
314 long this_address; /* Address of this block. */
315 long this_size; /* Size of this block (does not include
316 this trailer). */
317 long unknown2;
318 long unknown3;
319 long link; /* Address of trailer block of previous
320 segment. */
321 long unknown5;
322 long unknown6;
323 long unknown7;
324 long unknown8;
325 long unknown9;
326 long unknown10;
327 long unknown11;
328 long unknown12;
329 long unknown13;
330 long unknown14;
331 };
332
333# endif /* CRAY2 */
334# endif /* not CRAY_STACK */
335
336# ifdef CRAY2
337/* Determine a "stack measure" for an arbitrary ADDRESS.
338 I doubt that "lint" will like this much. */
339
340static long
341i00afunc (long *address)
342{
343 struct stk_stat status;
344 struct stk_trailer *trailer;
345 long *block, size;
346 long result = 0;
347
348 /* We want to iterate through all of the segments. The first
349 step is to get the stack status structure. We could do this
350 more quickly and more directly, perhaps, by referencing the
351 $LM00 common block, but I know that this works. */
352
353 STKSTAT (&status);
354
355 /* Set up the iteration. */
356
357 trailer = (struct stk_trailer *) (status.current_address
358 + status.current_size
359 - 15);
360
361 /* There must be at least one stack segment. Therefore it is
362 a fatal error if "trailer" is null. */
363
364 if (trailer == 0)
365 abort ();
366
367 /* Discard segments that do not contain our argument address. */
368
369 while (trailer != 0)
370 {
371 block = (long *) trailer->this_address;
372 size = trailer->this_size;
373 if (block == 0 || size == 0)
374 abort ();
375 trailer = (struct stk_trailer *) trailer->link;
376 if ((block <= address) && (address < (block + size)))
377 break;
378 }
379
380 /* Set the result to the offset in this segment and add the sizes
381 of all predecessor segments. */
382
383 result = address - block;
384
385 if (trailer == 0)
386 {
387 return result;
388 }
389
390 do
391 {
392 if (trailer->this_size <= 0)
393 abort ();
394 result += trailer->this_size;
395 trailer = (struct stk_trailer *) trailer->link;
396 }
397 while (trailer != 0);
398
399 /* We are done. Note that if you present a bogus address (one
400 not in any segment), you will get a different number back, formed
401 from subtracting the address of the first block. This is probably
402 not what you want. */
403
404 return (result);
405}
406
407# else /* not CRAY2 */
408/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
409 Determine the number of the cell within the stack,
410 given the address of the cell. The purpose of this
411 routine is to linearize, in some sense, stack addresses
412 for alloca. */
413
414static long
415i00afunc (long address)
416{
417 long stkl = 0;
418
419 long size, pseg, this_segment, stack;
420 long result = 0;
421
422 struct stack_segment_linkage *ssptr;
423
424 /* Register B67 contains the address of the end of the
425 current stack segment. If you (as a subprogram) store
426 your registers on the stack and find that you are past
427 the contents of B67, you have overflowed the segment.
428
429 B67 also points to the stack segment linkage control
430 area, which is what we are really interested in. */
431
432 stkl = CRAY_STACKSEG_END ();
433 ssptr = (struct stack_segment_linkage *) stkl;
434
435 /* If one subtracts 'size' from the end of the segment,
436 one has the address of the first word of the segment.
437
438 If this is not the first segment, 'pseg' will be
439 nonzero. */
440
441 pseg = ssptr->sspseg;
442 size = ssptr->sssize;
443
444 this_segment = stkl - size;
445
446 /* It is possible that calling this routine itself caused
447 a stack overflow. Discard stack segments which do not
448 contain the target address. */
449
450 while (!(this_segment <= address && address <= stkl))
451 {
452# ifdef DEBUG_I00AFUNC
453 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
454# endif
455 if (pseg == 0)
456 break;
457 stkl = stkl - pseg;
458 ssptr = (struct stack_segment_linkage *) stkl;
459 size = ssptr->sssize;
460 pseg = ssptr->sspseg;
461 this_segment = stkl - size;
462 }
463
464 result = address - this_segment;
465
466 /* If you subtract pseg from the current end of the stack,
467 you get the address of the previous stack segment's end.
468 This seems a little convoluted to me, but I'll bet you save
469 a cycle somewhere. */
470
471 while (pseg != 0)
472 {
473# ifdef DEBUG_I00AFUNC
474 fprintf (stderr, "%011o %011o\n", pseg, size);
475# endif
476 stkl = stkl - pseg;
477 ssptr = (struct stack_segment_linkage *) stkl;
478 size = ssptr->sssize;
479 pseg = ssptr->sspseg;
480 result += size;
481 }
482 return (result);
483}
484
485# endif /* not CRAY2 */
486# endif /* CRAY */
487
488# endif /* no alloca */
489#endif /* not GCC version 2 */
diff --git a/gl/alloca_.h b/gl/alloca_.h
new file mode 100644
index 00000000..dd0b3e98
--- /dev/null
+++ b/gl/alloca_.h
@@ -0,0 +1,54 @@
1/* Memory allocation on the stack.
2
3 Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004, 2006 Free Software
4 Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 USA. */
20
21/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
22 means there is a real alloca function. */
23#ifndef _GNULIB_ALLOCA_H
24# define _GNULIB_ALLOCA_H
25
26/* alloca (N) returns a pointer to N bytes of memory
27 allocated on the stack, which will last until the function returns.
28 Use of alloca should be avoided:
29 - inside arguments of function calls - undefined behaviour,
30 - in inline functions - the allocation may actually last until the
31 calling function returns,
32 - for huge N (say, N >= 65536) - you never know how large (or small)
33 the stack is, and when the stack cannot fulfill the memory allocation
34 request, the program just crashes.
35 */
36
37#ifndef alloca
38# ifdef __GNUC__
39# define alloca __builtin_alloca
40# elif defined _AIX
41# define alloca __alloca
42# elif defined _MSC_VER
43# include <malloc.h>
44# define alloca _alloca
45# else
46# include <stddef.h>
47# ifdef __cplusplus
48extern "C"
49# endif
50void *alloca (size_t);
51# endif
52#endif
53
54#endif /* _GNULIB_ALLOCA_H */
diff --git a/gl/asnprintf.c b/gl/asnprintf.c
new file mode 100644
index 00000000..26c3988b
--- /dev/null
+++ b/gl/asnprintf.c
@@ -0,0 +1,35 @@
1/* Formatted output to strings.
2 Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "vasnprintf.h"
22
23#include <stdarg.h>
24
25char *
26asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
27{
28 va_list args;
29 char *result;
30
31 va_start (args, format);
32 result = vasnprintf (resultbuf, lengthp, format, args);
33 va_end (args);
34 return result;
35}
diff --git a/gl/asprintf.c b/gl/asprintf.c
new file mode 100644
index 00000000..29ac6cf2
--- /dev/null
+++ b/gl/asprintf.c
@@ -0,0 +1,35 @@
1/* Formatted output to strings.
2 Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "vasprintf.h"
22
23#include <stdarg.h>
24
25int
26asprintf (char **resultp, const char *format, ...)
27{
28 va_list args;
29 int result;
30
31 va_start (args, format);
32 result = vasprintf (resultp, format, args);
33 va_end (args);
34 return result;
35}
diff --git a/gl/basename.c b/gl/basename.c
new file mode 100644
index 00000000..fbe17ff9
--- /dev/null
+++ b/gl/basename.c
@@ -0,0 +1,129 @@
1/* basename.c -- return the last element in a file name
2
3 Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free
4 Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "dirname.h"
23
24#include <string.h>
25#include "xalloc.h"
26#include "xstrndup.h"
27
28/* Return the address of the last file name component of NAME. If
29 NAME has no relative file name components because it is a file
30 system root, return the empty string. */
31
32char *
33last_component (char const *name)
34{
35 char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
36 char const *p;
37 bool saw_slash = false;
38
39 while (ISSLASH (*base))
40 base++;
41
42 for (p = base; *p; p++)
43 {
44 if (ISSLASH (*p))
45 saw_slash = true;
46 else if (saw_slash)
47 {
48 base = p;
49 saw_slash = false;
50 }
51 }
52
53 return (char *) base;
54}
55
56
57/* In general, we can't use the builtin `basename' function if available,
58 since it has different meanings in different environments.
59 In some environments the builtin `basename' modifies its argument.
60
61 Return the last file name component of NAME, allocated with
62 xmalloc. On systems with drive letters, a leading "./"
63 distinguishes relative names that would otherwise look like a drive
64 letter. Unlike POSIX basename(), NAME cannot be NULL,
65 base_name("") returns "", and the first trailing slash is not
66 stripped.
67
68 If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
69 lstat (base_name (NAME)); } will access the same file. Likewise,
70 if the sequence { chdir (dir_name (NAME));
71 rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
72 to "foo" in the same directory NAME was in. */
73
74char *
75base_name (char const *name)
76{
77 char const *base = last_component (name);
78 size_t length;
79
80 /* If there is no last component, then name is a file system root or the
81 empty string. */
82 if (! *base)
83 return xstrndup (name, base_len (name));
84
85 /* Collapse a sequence of trailing slashes into one. */
86 length = base_len (base);
87 if (ISSLASH (base[length]))
88 length++;
89
90 /* On systems with drive letters, `a/b:c' must return `./b:c' rather
91 than `b:c' to avoid confusion with a drive letter. On systems
92 with pure POSIX semantics, this is not an issue. */
93 if (FILE_SYSTEM_PREFIX_LEN (base))
94 {
95 char *p = xmalloc (length + 3);
96 p[0] = '.';
97 p[1] = '/';
98 memcpy (p + 2, base, length);
99 p[length + 2] = '\0';
100 return p;
101 }
102
103 /* Finally, copy the basename. */
104 return xstrndup (base, length);
105}
106
107/* Return the length of the basename NAME. Typically NAME is the
108 value returned by base_name or last_component. Act like strlen
109 (NAME), except omit all trailing slashes. */
110
111size_t
112base_len (char const *name)
113{
114 size_t len;
115 size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
116
117 for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
118 continue;
119
120 if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
121 && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
122 return 2;
123
124 if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
125 && len == prefix_len && ISSLASH (name[prefix_len]))
126 return prefix_len + 1;
127
128 return len;
129}
diff --git a/gl/c-strtod.c b/gl/c-strtod.c
new file mode 100644
index 00000000..2234ed0f
--- /dev/null
+++ b/gl/c-strtod.c
@@ -0,0 +1,79 @@
1/* Convert string to double, using the C locale.
2
3 Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <config.h>
22
23#include "c-strtod.h"
24
25#include <locale.h>
26#include <stdlib.h>
27
28#include "xalloc.h"
29
30#if LONG
31# define C_STRTOD c_strtold
32# define DOUBLE long double
33# define STRTOD_L strtold_l
34#else
35# define C_STRTOD c_strtod
36# define DOUBLE double
37# define STRTOD_L strtod_l
38#endif
39
40/* c_strtold falls back on strtod if strtold doesn't conform to C99. */
41#if LONG && HAVE_C99_STRTOLD
42# define STRTOD strtold
43#else
44# define STRTOD strtod
45#endif
46
47DOUBLE
48C_STRTOD (char const *nptr, char **endptr)
49{
50 DOUBLE r;
51
52#ifdef LC_ALL_MASK
53
54 locale_t c_locale = newlocale (LC_ALL_MASK, "C", 0);
55 r = STRTOD_L (nptr, endptr, c_locale);
56 freelocale (c_locale);
57
58#else
59
60 char *saved_locale = setlocale (LC_NUMERIC, NULL);
61
62 if (saved_locale)
63 {
64 saved_locale = xstrdup (saved_locale);
65 setlocale (LC_NUMERIC, "C");
66 }
67
68 r = STRTOD (nptr, endptr);
69
70 if (saved_locale)
71 {
72 setlocale (LC_NUMERIC, saved_locale);
73 free (saved_locale);
74 }
75
76#endif
77
78 return r;
79}
diff --git a/gl/c-strtod.h b/gl/c-strtod.h
new file mode 100644
index 00000000..ca9a9e7c
--- /dev/null
+++ b/gl/c-strtod.h
@@ -0,0 +1,2 @@
1double c_strtod (char const *, char **);
2long double c_strtold (char const *, char **);
diff --git a/gl/cloexec.c b/gl/cloexec.c
new file mode 100644
index 00000000..6480006a
--- /dev/null
+++ b/gl/cloexec.c
@@ -0,0 +1,59 @@
1/* closexec.c - set or clear the close-on-exec descriptor flag
2
3 Copyright (C) 1991, 2004, 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 The code is taken from glibc/manual/llio.texi */
20
21#include <config.h>
22
23#include "cloexec.h"
24
25#include <unistd.h>
26#include <fcntl.h>
27
28#ifndef FD_CLOEXEC
29# define FD_CLOEXEC 1
30#endif
31
32/* Set the `FD_CLOEXEC' flag of DESC if VALUE is true,
33 or clear the flag if VALUE is false.
34 Return 0 on success, or -1 on error with `errno' set. */
35
36int
37set_cloexec_flag (int desc, bool value)
38{
39#if defined F_GETFD && defined F_SETFD
40
41 int flags = fcntl (desc, F_GETFD, 0);
42
43 if (0 <= flags)
44 {
45 int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
46
47 if (flags == newflags
48 || fcntl (desc, F_SETFD, newflags) != -1)
49 return 0;
50 }
51
52 return -1;
53
54#else
55
56 return 0;
57
58#endif
59}
diff --git a/gl/cloexec.h b/gl/cloexec.h
new file mode 100644
index 00000000..c25921d6
--- /dev/null
+++ b/gl/cloexec.h
@@ -0,0 +1,2 @@
1#include <stdbool.h>
2int set_cloexec_flag (int desc, bool value);
diff --git a/gl/creat-safer.c b/gl/creat-safer.c
new file mode 100644
index 00000000..f4a2e59d
--- /dev/null
+++ b/gl/creat-safer.c
@@ -0,0 +1,32 @@
1/* Invoke creat, but avoid some glitches.
2
3 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Jim Meyering. */
20
21#include <config.h>
22
23#include "fcntl-safer.h"
24
25#include <fcntl.h>
26#include "unistd-safer.h"
27
28int
29creat_safer (char const *file, mode_t mode)
30{
31 return fd_safer (creat (file, mode));
32}
diff --git a/gl/dirname.c b/gl/dirname.c
new file mode 100644
index 00000000..16552c64
--- /dev/null
+++ b/gl/dirname.c
@@ -0,0 +1,85 @@
1/* dirname.c -- return all but the last element in a file name
2
3 Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
4 Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "dirname.h"
23
24#include <string.h>
25#include "xalloc.h"
26
27/* Return the length of the prefix of FILE that will be used by
28 dir_name. If FILE is in the working directory, this returns zero
29 even though `dir_name (FILE)' will return ".". Works properly even
30 if there are trailing slashes (by effectively ignoring them). */
31
32size_t
33dir_len (char const *file)
34{
35 size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
36 size_t length;
37
38 /* Advance prefix_length beyond important leading slashes. */
39 prefix_length += (prefix_length != 0
40 ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
41 && ISSLASH (file[prefix_length]))
42 : (ISSLASH (file[0])
43 ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
44 && ISSLASH (file[1]) && ! ISSLASH (file[2])
45 ? 2 : 1))
46 : 0));
47
48 /* Strip the basename and any redundant slashes before it. */
49 for (length = last_component (file) - file;
50 prefix_length < length; length--)
51 if (! ISSLASH (file[length - 1]))
52 break;
53 return length;
54}
55
56
57/* In general, we can't use the builtin `dirname' function if available,
58 since it has different meanings in different environments.
59 In some environments the builtin `dirname' modifies its argument.
60
61 Return the leading directories part of FILE, allocated with xmalloc.
62 Works properly even if there are trailing slashes (by effectively
63 ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
64
65 If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
66 lstat (base_name (FILE)); } will access the same file. Likewise,
67 if the sequence { chdir (dir_name (FILE));
68 rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
69 to "foo" in the same directory FILE was in. */
70
71char *
72dir_name (char const *file)
73{
74 size_t length = dir_len (file);
75 bool append_dot = (length == 0
76 || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
77 && length == FILE_SYSTEM_PREFIX_LEN (file)
78 && file[2] != '\0' && ! ISSLASH (file[2])));
79 char *dir = xmalloc (length + append_dot + 1);
80 memcpy (dir, file, length);
81 if (append_dot)
82 dir[length++] = '.';
83 dir[length] = '\0';
84 return dir;
85}
diff --git a/gl/dirname.h b/gl/dirname.h
new file mode 100644
index 00000000..91e7ed33
--- /dev/null
+++ b/gl/dirname.h
@@ -0,0 +1,70 @@
1/* Take file names apart into directory and base names.
2
3 Copyright (C) 1998, 2001, 2003-2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef DIRNAME_H_
20# define DIRNAME_H_ 1
21
22# include <stdbool.h>
23# include <stddef.h>
24
25# ifndef DIRECTORY_SEPARATOR
26# define DIRECTORY_SEPARATOR '/'
27# endif
28
29# ifndef ISSLASH
30# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
31# endif
32
33# ifndef FILE_SYSTEM_PREFIX_LEN
34# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
35 /* This internal macro assumes ASCII, but all hosts that support drive
36 letters use ASCII. */
37# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
38 <= 'z' - 'a')
39# define FILE_SYSTEM_PREFIX_LEN(Filename) \
40 (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
41# else
42# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
43# endif
44# endif
45
46# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
47# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
48# endif
49
50# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
51# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
52# endif
53
54# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
55# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
56# else
57# define IS_ABSOLUTE_FILE_NAME(F) \
58 (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
59# endif
60# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
61
62char *base_name (char const *file);
63char *dir_name (char const *file);
64size_t base_len (char const *file);
65size_t dir_len (char const *file);
66char *last_component (char const *file);
67
68bool strip_trailing_slashes (char *file);
69
70#endif /* not DIRNAME_H_ */
diff --git a/gl/dup-safer.c b/gl/dup-safer.c
new file mode 100644
index 00000000..7b12b615
--- /dev/null
+++ b/gl/dup-safer.c
@@ -0,0 +1,45 @@
1/* Invoke dup, but avoid some glitches.
2
3 Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <config.h>
22
23#include "unistd-safer.h"
24
25#include <fcntl.h>
26
27#include <unistd.h>
28#ifndef STDERR_FILENO
29# define STDERR_FILENO 2
30#endif
31
32/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
33 STDERR_FILENO. */
34
35int
36dup_safer (int fd)
37{
38#if defined F_DUPFD && !defined FCHDIR_REPLACEMENT
39 return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
40#else
41 /* fd_safer calls us back, but eventually the recursion unwinds and
42 does the right thing. */
43 return fd_safer (dup (fd));
44#endif
45}
diff --git a/gl/error.c b/gl/error.c
new file mode 100644
index 00000000..cf863433
--- /dev/null
+++ b/gl/error.c
@@ -0,0 +1,338 @@
1/* Error handler for noninteractive utilities
2 Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
20
21#if !_LIBC
22# include <config.h>
23#endif
24
25#include "error.h"
26
27#include <stdarg.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#if !_LIBC && ENABLE_NLS
33# include "gettext.h"
34#endif
35
36#ifdef _LIBC
37# include <libintl.h>
38# include <stdbool.h>
39# include <stdint.h>
40# include <wchar.h>
41# define mbsrtowcs __mbsrtowcs
42#endif
43
44#if USE_UNLOCKED_IO
45# include "unlocked-io.h"
46#endif
47
48#ifndef _
49# define _(String) String
50#endif
51
52/* If NULL, error will flush stdout, then print on stderr the program
53 name, a colon and a space. Otherwise, error will call this
54 function without parameters instead. */
55void (*error_print_progname) (void);
56
57/* This variable is incremented each time `error' is called. */
58unsigned int error_message_count;
59
60#ifdef _LIBC
61/* In the GNU C library, there is a predefined variable for this. */
62
63# define program_name program_invocation_name
64# include <errno.h>
65# include <limits.h>
66# include <libio/libioP.h>
67
68/* In GNU libc we want do not want to use the common name `error' directly.
69 Instead make it a weak alias. */
70extern void __error (int status, int errnum, const char *message, ...)
71 __attribute__ ((__format__ (__printf__, 3, 4)));
72extern void __error_at_line (int status, int errnum, const char *file_name,
73 unsigned int line_number, const char *message,
74 ...)
75 __attribute__ ((__format__ (__printf__, 5, 6)));;
76# define error __error
77# define error_at_line __error_at_line
78
79# include <libio/iolibio.h>
80# define fflush(s) INTUSE(_IO_fflush) (s)
81# undef putc
82# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
83
84# include <bits/libc-lock.h>
85
86#else /* not _LIBC */
87
88# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
89# ifndef HAVE_DECL_STRERROR_R
90"this configure-time declaration test was not run"
91# endif
92char *strerror_r ();
93# endif
94
95/* The calling program should define program_name and set it to the
96 name of the executing program. */
97extern char *program_name;
98
99# if HAVE_STRERROR_R || defined strerror_r
100# define __strerror_r strerror_r
101# endif /* HAVE_STRERROR_R || defined strerror_r */
102#endif /* not _LIBC */
103
104static void
105print_errno_message (int errnum)
106{
107 char const *s;
108
109#if defined HAVE_STRERROR_R || _LIBC
110 char errbuf[1024];
111# if STRERROR_R_CHAR_P || _LIBC
112 s = __strerror_r (errnum, errbuf, sizeof errbuf);
113# else
114 if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
115 s = errbuf;
116 else
117 s = 0;
118# endif
119#else
120 s = strerror (errnum);
121#endif
122
123#if !_LIBC
124 if (! s)
125 s = _("Unknown system error");
126#endif
127
128#if _LIBC
129 __fxprintf (NULL, ": %s", s);
130#else
131 fprintf (stderr, ": %s", s);
132#endif
133}
134
135static void
136error_tail (int status, int errnum, const char *message, va_list args)
137{
138#if _LIBC
139 if (_IO_fwide (stderr, 0) > 0)
140 {
141# define ALLOCA_LIMIT 2000
142 size_t len = strlen (message) + 1;
143 wchar_t *wmessage = NULL;
144 mbstate_t st;
145 size_t res;
146 const char *tmp;
147 bool use_malloc = false;
148
149 while (1)
150 {
151 if (__libc_use_alloca (len * sizeof (wchar_t)))
152 wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
153 else
154 {
155 if (!use_malloc)
156 wmessage = NULL;
157
158 wchar_t *p = (wchar_t *) realloc (wmessage,
159 len * sizeof (wchar_t));
160 if (p == NULL)
161 {
162 free (wmessage);
163 fputws_unlocked (L"out of memory\n", stderr);
164 return;
165 }
166 wmessage = p;
167 use_malloc = true;
168 }
169
170 memset (&st, '\0', sizeof (st));
171 tmp = message;
172
173 res = mbsrtowcs (wmessage, &tmp, len, &st);
174 if (res != len)
175 break;
176
177 if (__builtin_expect (len >= SIZE_MAX / 2, 0))
178 {
179 /* This really should not happen if everything is fine. */
180 res = (size_t) -1;
181 break;
182 }
183
184 len *= 2;
185 }
186
187 if (res == (size_t) -1)
188 {
189 /* The string cannot be converted. */
190 if (use_malloc)
191 {
192 free (wmessage);
193 use_malloc = false;
194 }
195 wmessage = (wchar_t *) L"???";
196 }
197
198 __vfwprintf (stderr, wmessage, args);
199
200 if (use_malloc)
201 free (wmessage);
202 }
203 else
204#endif
205 vfprintf (stderr, message, args);
206 va_end (args);
207
208 ++error_message_count;
209 if (errnum)
210 print_errno_message (errnum);
211#if _LIBC
212 __fxprintf (NULL, "\n");
213#else
214 putc ('\n', stderr);
215#endif
216 fflush (stderr);
217 if (status)
218 exit (status);
219}
220
221
222/* Print the program name and error message MESSAGE, which is a printf-style
223 format string with optional args.
224 If ERRNUM is nonzero, print its corresponding system error message.
225 Exit with status STATUS if it is nonzero. */
226void
227error (int status, int errnum, const char *message, ...)
228{
229 va_list args;
230
231#if defined _LIBC && defined __libc_ptf_call
232 /* We do not want this call to be cut short by a thread
233 cancellation. Therefore disable cancellation for now. */
234 int state = PTHREAD_CANCEL_ENABLE;
235 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
236 0);
237#endif
238
239 fflush (stdout);
240#ifdef _LIBC
241 _IO_flockfile (stderr);
242#endif
243 if (error_print_progname)
244 (*error_print_progname) ();
245 else
246 {
247#if _LIBC
248 __fxprintf (NULL, "%s: ", program_name);
249#else
250 fprintf (stderr, "%s: ", program_name);
251#endif
252 }
253
254 va_start (args, message);
255 error_tail (status, errnum, message, args);
256
257#ifdef _LIBC
258 _IO_funlockfile (stderr);
259# ifdef __libc_ptf_call
260 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
261# endif
262#endif
263}
264
265/* Sometimes we want to have at most one error per line. This
266 variable controls whether this mode is selected or not. */
267int error_one_per_line;
268
269void
270error_at_line (int status, int errnum, const char *file_name,
271 unsigned int line_number, const char *message, ...)
272{
273 va_list args;
274
275 if (error_one_per_line)
276 {
277 static const char *old_file_name;
278 static unsigned int old_line_number;
279
280 if (old_line_number == line_number
281 && (file_name == old_file_name
282 || strcmp (old_file_name, file_name) == 0))
283 /* Simply return and print nothing. */
284 return;
285
286 old_file_name = file_name;
287 old_line_number = line_number;
288 }
289
290#if defined _LIBC && defined __libc_ptf_call
291 /* We do not want this call to be cut short by a thread
292 cancellation. Therefore disable cancellation for now. */
293 int state = PTHREAD_CANCEL_ENABLE;
294 __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
295 0);
296#endif
297
298 fflush (stdout);
299#ifdef _LIBC
300 _IO_flockfile (stderr);
301#endif
302 if (error_print_progname)
303 (*error_print_progname) ();
304 else
305 {
306#if _LIBC
307 __fxprintf (NULL, "%s:", program_name);
308#else
309 fprintf (stderr, "%s:", program_name);
310#endif
311 }
312
313#if _LIBC
314 __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
315 file_name, line_number);
316#else
317 fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
318 file_name, line_number);
319#endif
320
321 va_start (args, message);
322 error_tail (status, errnum, message, args);
323
324#ifdef _LIBC
325 _IO_funlockfile (stderr);
326# ifdef __libc_ptf_call
327 __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
328# endif
329#endif
330}
331
332#ifdef _LIBC
333/* Make the weak alias. */
334# undef error
335# undef error_at_line
336weak_alias (__error, error)
337weak_alias (__error_at_line, error_at_line)
338#endif
diff --git a/gl/error.h b/gl/error.h
new file mode 100644
index 00000000..5a5f2476
--- /dev/null
+++ b/gl/error.h
@@ -0,0 +1,66 @@
1/* Declaration for error-reporting function
2 Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _ERROR_H
20#define _ERROR_H 1
21
22#ifndef __attribute__
23/* This feature is available in gcc versions 2.5 and later. */
24# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
25# define __attribute__(Spec) /* empty */
26# endif
27/* The __-protected variants of `format' and `printf' attributes
28 are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
29# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
30# define __format__ format
31# define __printf__ printf
32# endif
33#endif
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/* Print a message with `fprintf (stderr, FORMAT, ...)';
40 if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
41 If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
42
43extern void error (int __status, int __errnum, const char *__format, ...)
44 __attribute__ ((__format__ (__printf__, 3, 4)));
45
46extern void error_at_line (int __status, int __errnum, const char *__fname,
47 unsigned int __lineno, const char *__format, ...)
48 __attribute__ ((__format__ (__printf__, 5, 6)));
49
50/* If NULL, error will flush stdout, then print on stderr the program
51 name, a colon and a space. Otherwise, error will call this
52 function without parameters instead. */
53extern void (*error_print_progname) (void);
54
55/* This variable is incremented each time `error' is called. */
56extern unsigned int error_message_count;
57
58/* Sometimes we want to have at most one error per line. This
59 variable controls whether this mode is selected or not. */
60extern int error_one_per_line;
61
62#ifdef __cplusplus
63}
64#endif
65
66#endif /* error.h */
diff --git a/gl/exit.h b/gl/exit.h
new file mode 100644
index 00000000..e8f77388
--- /dev/null
+++ b/gl/exit.h
@@ -0,0 +1,32 @@
1/* exit() function.
2 Copyright (C) 1995, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _EXIT_H
19#define _EXIT_H
20
21/* Get exit() declaration. */
22#include <stdlib.h>
23
24/* Some systems do not define EXIT_*, despite otherwise supporting C89. */
25#ifndef EXIT_SUCCESS
26# define EXIT_SUCCESS 0
27#endif
28#ifndef EXIT_FAILURE
29# define EXIT_FAILURE 1
30#endif
31
32#endif /* _EXIT_H */
diff --git a/gl/exitfail.c b/gl/exitfail.c
new file mode 100644
index 00000000..97abc674
--- /dev/null
+++ b/gl/exitfail.c
@@ -0,0 +1,25 @@
1/* Failure exit status
2
3 Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING.
17 If not, write to the Free Software Foundation,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "exitfail.h"
23#include "exit.h"
24
25int volatile exit_failure = EXIT_FAILURE;
diff --git a/gl/exitfail.h b/gl/exitfail.h
new file mode 100644
index 00000000..e46cf9c1
--- /dev/null
+++ b/gl/exitfail.h
@@ -0,0 +1,20 @@
1/* Failure exit status
2
3 Copyright (C) 2002 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING.
17 If not, write to the Free Software Foundation,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20extern int volatile exit_failure;
diff --git a/gl/fcntl--.h b/gl/fcntl--.h
new file mode 100644
index 00000000..51b869e6
--- /dev/null
+++ b/gl/fcntl--.h
@@ -0,0 +1,28 @@
1/* Like fcntl.h, but redefine some names to avoid glitches.
2
3 Copyright (C) 2005 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <fcntl.h>
22#include "fcntl-safer.h"
23
24#undef open
25#define open open_safer
26
27#undef creat
28#define creat creat_safer
diff --git a/gl/fcntl-safer.h b/gl/fcntl-safer.h
new file mode 100644
index 00000000..cab6aab1
--- /dev/null
+++ b/gl/fcntl-safer.h
@@ -0,0 +1,24 @@
1/* Invoke fcntl-like functions, but avoid some glitches.
2
3 Copyright (C) 2005 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <sys/types.h>
22
23int open_safer (char const *, int, ...);
24int creat_safer (char const *, mode_t);
diff --git a/gl/fd-safer.c b/gl/fd-safer.c
new file mode 100644
index 00000000..256bfa4a
--- /dev/null
+++ b/gl/fd-safer.c
@@ -0,0 +1,57 @@
1/* Return a safer copy of a file descriptor.
2
3 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <config.h>
22
23#include "unistd-safer.h"
24
25#include <errno.h>
26
27#include <unistd.h>
28#ifndef STDIN_FILENO
29# define STDIN_FILENO 0
30#endif
31#ifndef STDERR_FILENO
32# define STDERR_FILENO 2
33#endif
34
35/* Return FD, unless FD would be a copy of standard input, output, or
36 error; in that case, return a duplicate of FD, closing FD. On
37 failure to duplicate, close FD, set errno, and return -1. Preserve
38 errno if FD is negative, so that the caller can always inspect
39 errno when the returned value is negative.
40
41 This function is usefully wrapped around functions that return file
42 descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */
43
44int
45fd_safer (int fd)
46{
47 if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
48 {
49 int f = dup_safer (fd);
50 int e = errno;
51 close (fd);
52 errno = e;
53 fd = f;
54 }
55
56 return fd;
57}
diff --git a/gl/fsusage.c b/gl/fsusage.c
new file mode 100644
index 00000000..337bf531
--- /dev/null
+++ b/gl/fsusage.c
@@ -0,0 +1,264 @@
1/* fsusage.c -- return space usage of mounted file systems
2
3 Copyright (C) 1991, 1992, 1996, 1998, 1999, 2002, 2003, 2004, 2005, 2006
4 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "fsusage.h"
23
24#include <limits.h>
25#include <sys/types.h>
26
27#if STAT_STATVFS /* POSIX 1003.1-2001 (and later) with XSI */
28# include <sys/statvfs.h>
29#else
30/* Don't include backward-compatibility files unless they're needed.
31 Eventually we'd like to remove all this cruft. */
32# include <fcntl.h>
33# include <unistd.h>
34# include <sys/stat.h>
35# if HAVE_SYS_PARAM_H
36# include <sys/param.h>
37# endif
38# if HAVE_SYS_MOUNT_H
39# include <sys/mount.h>
40# endif
41# if HAVE_SYS_VFS_H
42# include <sys/vfs.h>
43# endif
44# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
45# include <sys/fs/s5param.h>
46# endif
47# if defined HAVE_SYS_FILSYS_H && !defined _CRAY
48# include <sys/filsys.h> /* SVR2 */
49# endif
50# if HAVE_SYS_STATFS_H
51# include <sys/statfs.h>
52# endif
53# if HAVE_DUSTAT_H /* AIX PS/2 */
54# include <sys/dustat.h>
55# endif
56# include "full-read.h"
57#endif
58
59/* The results of open() in this file are not used with fchdir,
60 therefore save some unnecessary work in fchdir.c. */
61#undef open
62#undef close
63
64/* Many space usage primitives use all 1 bits to denote a value that is
65 not applicable or unknown. Propagate this information by returning
66 a uintmax_t value that is all 1 bits if X is all 1 bits, even if X
67 is unsigned and narrower than uintmax_t. */
68#define PROPAGATE_ALL_ONES(x) \
69 ((sizeof (x) < sizeof (uintmax_t) \
70 && (~ (x) == (sizeof (x) < sizeof (int) \
71 ? - (1 << (sizeof (x) * CHAR_BIT)) \
72 : 0))) \
73 ? UINTMAX_MAX : (uintmax_t) (x))
74
75/* Extract the top bit of X as an uintmax_t value. */
76#define EXTRACT_TOP_BIT(x) ((x) \
77 & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1)))
78
79/* If a value is negative, many space usage primitives store it into an
80 integer variable by assignment, even if the variable's type is unsigned.
81 So, if a space usage variable X's top bit is set, convert X to the
82 uintmax_t value V such that (- (uintmax_t) V) is the negative of
83 the original value. If X's top bit is clear, just yield X.
84 Use PROPAGATE_TOP_BIT if the original value might be negative;
85 otherwise, use PROPAGATE_ALL_ONES. */
86#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
87
88/* Fill in the fields of FSP with information about space usage for
89 the file system on which FILE resides.
90 DISK is the device on which FILE is mounted, for space-getting
91 methods that need to know it.
92 Return 0 if successful, -1 if not. When returning -1, ensure that
93 ERRNO is either a system error value, or zero if DISK is NULL
94 on a system that requires a non-NULL value. */
95int
96get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
97{
98#if defined STAT_STATVFS /* POSIX */
99
100 struct statvfs fsd;
101
102 if (statvfs (file, &fsd) < 0)
103 return -1;
104
105 /* f_frsize isn't guaranteed to be supported. */
106 fsp->fsu_blocksize = (fsd.f_frsize
107 ? PROPAGATE_ALL_ONES (fsd.f_frsize)
108 : PROPAGATE_ALL_ONES (fsd.f_bsize));
109
110#elif defined STAT_STATFS2_FS_DATA /* Ultrix */
111
112 struct fs_data fsd;
113
114 if (statfs (file, &fsd) != 1)
115 return -1;
116
117 fsp->fsu_blocksize = 1024;
118 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
119 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
120 fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
121 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
122 fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
123 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
124
125#elif defined STAT_READ_FILSYS /* SVR2 */
126# ifndef SUPERBOFF
127# define SUPERBOFF (SUPERB * 512)
128# endif
129
130 struct filsys fsd;
131 int fd;
132
133 if (! disk)
134 {
135 errno = 0;
136 return -1;
137 }
138
139 fd = open (disk, O_RDONLY);
140 if (fd < 0)
141 return -1;
142 lseek (fd, (off_t) SUPERBOFF, 0);
143 if (full_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
144 {
145 close (fd);
146 return -1;
147 }
148 close (fd);
149
150 fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512);
151 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize);
152 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree);
153 fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree);
154 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0;
155 fsp->fsu_files = (fsd.s_isize == -1
156 ? UINTMAX_MAX
157 : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
158 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
159
160#elif defined STAT_STATFS3_OSF1
161
162 struct statfs fsd;
163
164 if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
165 return -1;
166
167 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
168
169#elif defined STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */
170
171 struct statfs fsd;
172
173 if (statfs (file, &fsd) < 0)
174 return -1;
175
176 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
177
178# ifdef STATFS_TRUNCATES_BLOCK_COUNTS
179
180 /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
181 struct statfs are truncated to 2GB. These conditions detect that
182 truncation, presumably without botching the 4.1.1 case, in which
183 the values are not truncated. The correct counts are stored in
184 undocumented spare fields. */
185 if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
186 {
187 fsd.f_blocks = fsd.f_spare[0];
188 fsd.f_bfree = fsd.f_spare[1];
189 fsd.f_bavail = fsd.f_spare[2];
190 }
191# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
192
193#elif defined STAT_STATFS2_FSIZE /* 4.4BSD */
194
195 struct statfs fsd;
196
197 if (statfs (file, &fsd) < 0)
198 return -1;
199
200 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
201
202#elif defined STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */
203
204# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
205# define f_bavail f_bfree
206# endif
207
208 struct statfs fsd;
209
210 if (statfs (file, &fsd, sizeof fsd, 0) < 0)
211 return -1;
212
213 /* Empirically, the block counts on most SVR3 and SVR3-derived
214 systems seem to always be in terms of 512-byte blocks,
215 no matter what value f_bsize has. */
216# if _AIX || defined _CRAY
217 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
218# else
219 fsp->fsu_blocksize = 512;
220# endif
221
222#endif
223
224#if (defined STAT_STATVFS \
225 || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS))
226
227 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
228 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
229 fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
230 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
231 fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
232 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
233
234#endif
235
236 return 0;
237}
238
239#if defined _AIX && defined _I386
240/* AIX PS/2 does not supply statfs. */
241
242int
243statfs (char *file, struct statfs *fsb)
244{
245 struct stat stats;
246 struct dustat fsd;
247
248 if (stat (file, &stats) != 0)
249 return -1;
250 if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
251 return -1;
252 fsb->f_type = 0;
253 fsb->f_bsize = fsd.du_bsize;
254 fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
255 fsb->f_bfree = fsd.du_tfree;
256 fsb->f_bavail = fsd.du_tfree;
257 fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
258 fsb->f_ffree = fsd.du_tinode;
259 fsb->f_fsid.val[0] = fsd.du_site;
260 fsb->f_fsid.val[1] = fsd.du_pckno;
261 return 0;
262}
263
264#endif /* _AIX && _I386 */
diff --git a/gl/fsusage.h b/gl/fsusage.h
new file mode 100644
index 00000000..7fa9f8d6
--- /dev/null
+++ b/gl/fsusage.h
@@ -0,0 +1,41 @@
1/* fsusage.h -- declarations for file system space usage info
2
3 Copyright (C) 1991, 1992, 1997, 2003, 2004, 2005, 2006 Free Software
4 Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20/* Space usage statistics for a file system. Blocks are 512-byte. */
21
22#if !defined FSUSAGE_H_
23# define FSUSAGE_H_
24
25# include <stdint.h>
26# include <stdbool.h>
27
28struct fs_usage
29{
30 uintmax_t fsu_blocksize; /* Size of a block. */
31 uintmax_t fsu_blocks; /* Total blocks. */
32 uintmax_t fsu_bfree; /* Free blocks available to superuser. */
33 uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */
34 bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */
35 uintmax_t fsu_files; /* Total file nodes. */
36 uintmax_t fsu_ffree; /* Free file nodes. */
37};
38
39int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp);
40
41#endif
diff --git a/gl/full-read.c b/gl/full-read.c
new file mode 100644
index 00000000..8c3472a4
--- /dev/null
+++ b/gl/full-read.c
@@ -0,0 +1,19 @@
1/* An interface to read that retries after partial reads and interrupts.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#define FULL_READ
19#include "full-write.c"
diff --git a/gl/full-read.h b/gl/full-read.h
new file mode 100644
index 00000000..05d83a76
--- /dev/null
+++ b/gl/full-read.h
@@ -0,0 +1,24 @@
1/* An interface to read() that reads all it is asked to read.
2
3 Copyright (C) 2002 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, read to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <stddef.h>
20
21/* Read COUNT bytes at BUF to descriptor FD, retrying if interrupted
22 or if partial reads occur. Return the number of bytes successfully
23 read, setting errno if that is less than COUNT. errno = 0 means EOF. */
24extern size_t full_read (int fd, void *buf, size_t count);
diff --git a/gl/full-write.c b/gl/full-write.c
new file mode 100644
index 00000000..cc168720
--- /dev/null
+++ b/gl/full-write.c
@@ -0,0 +1,81 @@
1/* An interface to read and write that retries (if necessary) until complete.
2
3 Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
4 2004, 2005, 2006 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22/* Specification. */
23#ifdef FULL_READ
24# include "full-read.h"
25#else
26# include "full-write.h"
27#endif
28
29#include <errno.h>
30
31#ifdef FULL_READ
32# include "safe-read.h"
33# define safe_rw safe_read
34# define full_rw full_read
35# undef const
36# define const /* empty */
37#else
38# include "safe-write.h"
39# define safe_rw safe_write
40# define full_rw full_write
41#endif
42
43#ifdef FULL_READ
44/* Set errno to zero upon EOF. */
45# define ZERO_BYTE_TRANSFER_ERRNO 0
46#else
47/* Some buggy drivers return 0 when one tries to write beyond
48 a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
49 Set errno to ENOSPC so they get a sensible diagnostic. */
50# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
51#endif
52
53/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
54 interrupted or if a partial write(read) occurs. Return the number
55 of bytes transferred.
56 When writing, set errno if fewer than COUNT bytes are written.
57 When reading, if fewer than COUNT bytes are read, you must examine
58 errno to distinguish failure from EOF (errno == 0). */
59size_t
60full_rw (int fd, const void *buf, size_t count)
61{
62 size_t total = 0;
63 const char *ptr = (const char *) buf;
64
65 while (count > 0)
66 {
67 size_t n_rw = safe_rw (fd, ptr, count);
68 if (n_rw == (size_t) -1)
69 break;
70 if (n_rw == 0)
71 {
72 errno = ZERO_BYTE_TRANSFER_ERRNO;
73 break;
74 }
75 total += n_rw;
76 ptr += n_rw;
77 count -= n_rw;
78 }
79
80 return total;
81}
diff --git a/gl/full-write.h b/gl/full-write.h
new file mode 100644
index 00000000..d20d2fe4
--- /dev/null
+++ b/gl/full-write.h
@@ -0,0 +1,35 @@
1/* An interface to write() that writes all it is asked to write.
2
3 Copyright (C) 2002-2003 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <stddef.h>
20
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26
27/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
28 or if partial writes occur. Return the number of bytes successfully
29 written, setting errno if that is less than COUNT. */
30extern size_t full_write (int fd, const void *buf, size_t count);
31
32
33#ifdef __cplusplus
34}
35#endif
diff --git a/gl/gai_strerror.c b/gl/gai_strerror.c
new file mode 100644
index 00000000..7f0e034e
--- /dev/null
+++ b/gl/gai_strerror.c
@@ -0,0 +1,77 @@
1/* Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _LIBC
20# include <config.h>
21# include "getaddrinfo.h"
22#endif
23
24#include <stdio.h>
25#ifdef HAVE_NETDB_H
26# include <netdb.h>
27#endif
28
29#ifdef _LIBC
30# include <libintl.h>
31#else
32# include "gettext.h"
33# define _(String) gettext (String)
34# define N_(String) String
35#endif
36
37static struct
38 {
39 int code;
40 const char *msg;
41 }
42values[] =
43 {
44 { EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
45 { EAI_AGAIN, N_("Temporary failure in name resolution") },
46 { EAI_BADFLAGS, N_("Bad value for ai_flags") },
47 { EAI_FAIL, N_("Non-recoverable failure in name resolution") },
48 { EAI_FAMILY, N_("ai_family not supported") },
49 { EAI_MEMORY, N_("Memory allocation failure") },
50 { EAI_NODATA, N_("No address associated with hostname") },
51 { EAI_NONAME, N_("Name or service not known") },
52 { EAI_SERVICE, N_("Servname not supported for ai_socktype") },
53 { EAI_SOCKTYPE, N_("ai_socktype not supported") },
54 { EAI_SYSTEM, N_("System error") },
55#ifdef __USE_GNU
56 { EAI_INPROGRESS, N_("Processing request in progress") },
57 { EAI_CANCELED, N_("Request canceled") },
58 { EAI_NOTCANCELED, N_("Request not canceled") },
59 { EAI_ALLDONE, N_("All requests done") },
60 { EAI_INTR, N_("Interrupted by a signal") },
61 { EAI_IDN_ENCODE, N_("Parameter string not correctly encoded") }
62#endif
63 };
64
65const char *
66gai_strerror (int code)
67{
68 size_t i;
69 for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
70 if (values[i].code == code)
71 return _(values[i].msg);
72
73 return _("Unknown error");
74}
75#ifdef _LIBC
76libc_hidden_def (gai_strerror)
77#endif
diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c
new file mode 100644
index 00000000..f523f765
--- /dev/null
+++ b/gl/getaddrinfo.c
@@ -0,0 +1,417 @@
1/* Get address information (partial implementation).
2 Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software
3 Foundation, Inc.
4 Contributed by Simon Josefsson <simon@josefsson.org>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "getaddrinfo.h"
23
24#if HAVE_NETINET_IN_H
25# include <netinet/in.h>
26#endif
27
28/* Get calloc. */
29#include <stdlib.h>
30
31/* Get memcpy. */
32#include <string.h>
33
34#include <stdbool.h>
35
36#include "gettext.h"
37#define _(String) gettext (String)
38#define N_(String) String
39
40#include "inet_ntop.h"
41#include "snprintf.h"
42#include "strdup.h"
43
44/* BeOS has AF_INET, but not PF_INET. */
45#ifndef PF_INET
46# define PF_INET AF_INET
47#endif
48/* BeOS also lacks PF_UNSPEC. */
49#ifndef PF_UNSPEC
50# define PF_UNSPEC 0
51#endif
52
53#if defined _WIN32 || defined __WIN32__
54# define WIN32_NATIVE
55#endif
56
57#ifdef WIN32_NATIVE
58typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
59 const struct addrinfo*,
60 struct addrinfo**);
61typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*);
62typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*,
63 socklen_t, char*, DWORD,
64 char*, DWORD, int);
65
66static getaddrinfo_func getaddrinfo_ptr = NULL;
67static freeaddrinfo_func freeaddrinfo_ptr = NULL;
68static getnameinfo_func getnameinfo_ptr = NULL;
69
70static int
71use_win32_p (void)
72{
73 static int done = 0;
74 HMODULE h;
75
76 if (done)
77 return getaddrinfo_ptr ? 1 : 0;
78
79 done = 1;
80
81 h = GetModuleHandle ("ws2_32.dll");
82
83 if (h)
84 {
85 getaddrinfo_ptr = (getaddrinfo_func) GetProcAddress (h, "getaddrinfo");
86 freeaddrinfo_ptr = (freeaddrinfo_func) GetProcAddress (h, "freeaddrinfo");
87 getnameinfo_ptr = (getnameinfo_func) GetProcAddress (h, "getnameinfo");
88 }
89
90 /* If either is missing, something is odd. */
91 if (!getaddrinfo_ptr || !freeaddrinfo_ptr || !getnameinfo_ptr)
92 {
93 getaddrinfo_ptr = NULL;
94 freeaddrinfo_ptr = NULL;
95 getnameinfo_ptr = NULL;
96 return 0;
97 }
98
99 return 1;
100}
101#endif
102
103static inline bool
104validate_family (int family)
105{
106 /* FIXME: Support more families. */
107#if HAVE_IPV4
108 if (family == PF_INET)
109 return true;
110#endif
111#if HAVE_IPV6
112 if (family == PF_INET6)
113 return true;
114#endif
115 if (family == PF_UNSPEC)
116 return true;
117 return false;
118}
119
120/* Translate name of a service location and/or a service name to set of
121 socket addresses. */
122int
123getaddrinfo (const char *restrict nodename,
124 const char *restrict servname,
125 const struct addrinfo *restrict hints,
126 struct addrinfo **restrict res)
127{
128 struct addrinfo *tmp;
129 int port = 0;
130 struct hostent *he;
131 void *storage;
132 size_t size;
133#if HAVE_IPV6
134 struct v6_pair {
135 struct addrinfo addrinfo;
136 struct sockaddr_in6 sockaddr_in6;
137 };
138#endif
139#if HAVE_IPV4
140 struct v4_pair {
141 struct addrinfo addrinfo;
142 struct sockaddr_in sockaddr_in;
143 };
144#endif
145
146#ifdef WIN32_NATIVE
147 if (use_win32_p ())
148 return getaddrinfo_ptr (nodename, servname, hints, res);
149#endif
150
151 if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
152 /* FIXME: Support more flags. */
153 return EAI_BADFLAGS;
154
155 if (hints && !validate_family (hints->ai_family))
156 return EAI_FAMILY;
157
158 if (hints &&
159 hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
160 /* FIXME: Support other socktype. */
161 return EAI_SOCKTYPE; /* FIXME: Better return code? */
162
163 if (!nodename)
164 {
165 if (!(hints->ai_flags & AI_PASSIVE))
166 return EAI_NONAME;
167
168#ifdef HAVE_IPV6
169 nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
170#else
171 nodename = "0.0.0.0";
172#endif
173 }
174
175 if (servname)
176 {
177 struct servent *se = NULL;
178 const char *proto =
179 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
180
181 if (!(hints->ai_flags & AI_NUMERICSERV))
182 /* FIXME: Use getservbyname_r if available. */
183 se = getservbyname (servname, proto);
184
185 if (!se)
186 {
187 char *c;
188 if (!(*servname >= '0' && *servname <= '9'))
189 return EAI_NONAME;
190 port = strtoul (servname, &c, 10);
191 if (*c || port > 0xffff)
192 return EAI_NONAME;
193 port = htons (port);
194 }
195 else
196 port = se->s_port;
197 }
198
199 /* FIXME: Use gethostbyname_r if available. */
200 he = gethostbyname (nodename);
201 if (!he || he->h_addr_list[0] == NULL)
202 return EAI_NONAME;
203
204 switch (he->h_addrtype)
205 {
206#if HAVE_IPV6
207 case PF_INET6:
208 size = sizeof (struct v6_pair);
209 break;
210#endif
211
212#if HAVE_IPV4
213 case PF_INET:
214 size = sizeof (struct v4_pair);
215 break;
216#endif
217
218 default:
219 return EAI_NODATA;
220 }
221
222 storage = calloc (1, size);
223 if (!storage)
224 return EAI_MEMORY;
225
226 switch (he->h_addrtype)
227 {
228#if HAVE_IPV6
229 case PF_INET6:
230 {
231 struct v6_pair *p = storage;
232 struct sockaddr_in6 *sinp = &p->sockaddr_in6;
233 tmp = &p->addrinfo;
234
235 if (port)
236 sinp->sin6_port = port;
237
238 if (he->h_length != sizeof (sinp->sin6_addr))
239 {
240 free (storage);
241 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
242 }
243
244 memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr);
245
246 tmp->ai_addr = (struct sockaddr *) sinp;
247 tmp->ai_addrlen = sizeof *sinp;
248 }
249 break;
250#endif
251
252#if HAVE_IPV4
253 case PF_INET:
254 {
255 struct v4_pair *p = storage;
256 struct sockaddr_in *sinp = &p->sockaddr_in;
257 tmp = &p->addrinfo;
258
259 if (port)
260 sinp->sin_port = port;
261
262 if (he->h_length != sizeof (sinp->sin_addr))
263 {
264 free (storage);
265 return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
266 }
267
268 memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr);
269
270 tmp->ai_addr = (struct sockaddr *) sinp;
271 tmp->ai_addrlen = sizeof *sinp;
272 }
273 break;
274#endif
275
276 default:
277 free (storage);
278 return EAI_NODATA;
279 }
280
281 if (hints && hints->ai_flags & AI_CANONNAME)
282 {
283 const char *cn;
284 if (he->h_name)
285 cn = he->h_name;
286 else
287 cn = nodename;
288
289 tmp->ai_canonname = strdup (cn);
290 if (!tmp->ai_canonname)
291 {
292 free (storage);
293 return EAI_MEMORY;
294 }
295 }
296
297 tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
298 tmp->ai_socktype = (hints) ? hints->ai_socktype : 0;
299 tmp->ai_addr->sa_family = he->h_addrtype;
300 tmp->ai_family = he->h_addrtype;
301
302 /* FIXME: If more than one address, create linked list of addrinfo's. */
303
304 *res = tmp;
305
306 return 0;
307}
308
309/* Free `addrinfo' structure AI including associated storage. */
310void
311freeaddrinfo (struct addrinfo *ai)
312{
313#ifdef WIN32_NATIVE
314 if (use_win32_p ())
315 {
316 freeaddrinfo_ptr (ai);
317 return;
318 }
319#endif
320
321 while (ai)
322 {
323 struct addrinfo *cur;
324
325 cur = ai;
326 ai = ai->ai_next;
327
328 if (cur->ai_canonname) free (cur->ai_canonname);
329 free (cur);
330 }
331}
332
333int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
334 char *restrict node, socklen_t nodelen,
335 char *restrict service, socklen_t servicelen,
336 int flags)
337{
338#ifdef WIN32_NATIVE
339 if (use_win32_p ())
340 return getnameinfo_ptr (sa, salen, node, nodelen,
341 service, servicelen, flags);
342#endif
343
344 /* FIXME: Support other flags. */
345 if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
346 (service && servicelen > 0 && !(flags & NI_NUMERICHOST)) ||
347 (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV)))
348 return EAI_BADFLAGS;
349
350 if (sa == NULL || salen < sizeof (sa->sa_family))
351 return EAI_FAMILY;
352
353 switch (sa->sa_family)
354 {
355#if HAVE_IPV4
356 case AF_INET:
357 if (salen < sizeof (struct sockaddr_in))
358 return EAI_FAMILY;
359 break;
360#endif
361#if HAVE_IPV6
362 case AF_INET6:
363 if (salen < sizeof (struct sockaddr_in6))
364 return EAI_FAMILY;
365 break;
366#endif
367 default:
368 return EAI_FAMILY;
369 }
370
371 if (node && nodelen > 0 && flags & NI_NUMERICHOST)
372 {
373 switch (sa->sa_family)
374 {
375#if HAVE_IPV4
376 case AF_INET:
377 if (!inet_ntop (AF_INET,
378 &(((const struct sockaddr_in *) sa)->sin_addr),
379 node, nodelen))
380 return EAI_SYSTEM;
381 break;
382#endif
383
384#if HAVE_IPV6
385 case AF_INET6:
386 if (!inet_ntop (AF_INET6,
387 &(((const struct sockaddr_in6 *) sa)->sin6_addr),
388 node, nodelen))
389 return EAI_SYSTEM;
390 break;
391#endif
392
393 default:
394 return EAI_FAMILY;
395 }
396 }
397
398 if (service && servicelen > 0 && flags & NI_NUMERICSERV)
399 switch (sa->sa_family)
400 {
401#if HAVE_IPV4
402 case AF_INET:
403#endif
404#if HAVE_IPV6
405 case AF_INET6:
406#endif
407 {
408 unsigned short int port
409 = ntohs (((const struct sockaddr_in *) sa)->sin_port);
410 if (servicelen <= snprintf (service, servicelen, "%u", port))
411 return EAI_OVERFLOW;
412 }
413 break;
414 }
415
416 return 0;
417}
diff --git a/gl/getaddrinfo.h b/gl/getaddrinfo.h
new file mode 100644
index 00000000..b4ef242c
--- /dev/null
+++ b/gl/getaddrinfo.h
@@ -0,0 +1,155 @@
1/* Get address information.
2 Copyright (C) 1996-2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
4 Contributed by Simon Josefsson <simon@josefsson.org>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef GETADDRINFO_H
21#define GETADDRINFO_H
22
23/* sys/socket.h in i386-unknown-freebsd4.10 and
24 powerpc-apple-darwin5.5 require sys/types.h, so include it first.
25 Then we'll also get 'socklen_t' and 'struct sockaddr' which are
26 used below. */
27#include <sys/types.h>
28/* Get all getaddrinfo related declarations, if available. */
29#include <sys/socket.h>
30#ifdef HAVE_NETDB_H
31# include <netdb.h>
32#endif
33
34#ifndef HAVE_STRUCT_ADDRINFO
35
36/* Structure to contain information about address of a service provider. */
37struct addrinfo
38{
39 int ai_flags; /* Input flags. */
40 int ai_family; /* Protocol family for socket. */
41 int ai_socktype; /* Socket type. */
42 int ai_protocol; /* Protocol for socket. */
43 socklen_t ai_addrlen; /* Length of socket address. */
44 struct sockaddr *ai_addr; /* Socket address for socket. */
45 char *ai_canonname; /* Canonical name for service location. */
46 struct addrinfo *ai_next; /* Pointer to next in list. */
47};
48#endif
49
50/* Possible values for `ai_flags' field in `addrinfo' structure. */
51#ifndef AI_PASSIVE
52# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */
53#endif
54#ifndef AI_CANONNAME
55# define AI_CANONNAME 0x0002 /* Request for canonical name. */
56#endif
57#ifndef AI_NUMERICSERV
58# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */
59#endif
60
61#if 0
62/* The commented out definitions below are not yet implemented in the
63 GNULIB getaddrinfo() replacement, so are not yet needed and may, in fact,
64 cause conflicts on systems with a getaddrinfo() function which does not
65 define them.
66
67 If they are restored, be sure to protect the definitions with #ifndef. */
68#define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */
69#define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
70#define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */
71#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose
72 returned address type.. */
73#endif /* 0 */
74
75/* Error values for `getaddrinfo' function. */
76#ifndef EAI_BADFLAGS
77# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */
78# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */
79# define EAI_AGAIN -3 /* Temporary failure in name resolution. */
80# define EAI_FAIL -4 /* Non-recoverable failure in name res. */
81# define EAI_NODATA -5 /* No address associated with NAME. */
82# define EAI_FAMILY -6 /* `ai_family' not supported. */
83# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */
84# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */
85# define EAI_MEMORY -10 /* Memory allocation failure. */
86#endif
87#ifndef EAI_OVERFLOW
88/* Not defined on mingw32. */
89# define EAI_OVERFLOW -12 /* Argument buffer overflow. */
90#endif
91#ifndef EAI_ADDRFAMILY
92/* Not defined on mingw32. */
93# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */
94#endif
95#ifndef EAI_SYSTEM
96/* Not defined on mingw32. */
97# define EAI_SYSTEM -11 /* System error returned in `errno'. */
98#endif
99
100#ifdef __USE_GNU
101# ifndef EAI_INPROGRESS
102# define EAI_INPROGRESS -100 /* Processing request in progress. */
103# define EAI_CANCELED -101 /* Request canceled. */
104# define EAI_NOTCANCELED -102 /* Request not canceled. */
105# define EAI_ALLDONE -103 /* All requests done. */
106# define EAI_INTR -104 /* Interrupted by a signal. */
107# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */
108# endif
109#endif
110
111#if !HAVE_DECL_GETADDRINFO
112/* Translate name of a service location and/or a service name to set of
113 socket addresses.
114 For more details, see the POSIX:2001 specification
115 <http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */
116extern int getaddrinfo (const char *restrict nodename,
117 const char *restrict servname,
118 const struct addrinfo *restrict hints,
119 struct addrinfo **restrict res);
120#endif
121
122#if !HAVE_DECL_FREEADDRINFO
123/* Free `addrinfo' structure AI including associated storage.
124 For more details, see the POSIX:2001 specification
125 <http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */
126extern void freeaddrinfo (struct addrinfo *ai);
127#endif
128
129#if !HAVE_DECL_GAI_STRERROR
130/* Convert error return from getaddrinfo() to a string.
131 For more details, see the POSIX:2001 specification
132 <http://www.opengroup.org/susv3xsh/gai_strerror.html>. */
133extern const char *gai_strerror (int ecode);
134#endif
135
136#if !HAVE_DECL_GETNAMEINFO
137/* Convert socket address to printable node and service names.
138 For more details, see the POSIX:2001 specification
139 <http://www.opengroup.org/susv3xsh/getnameinfo.html>. */
140extern int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
141 char *restrict node, socklen_t nodelen,
142 char *restrict service, socklen_t servicelen,
143 int flags);
144
145#endif
146
147/* Possible flags for getnameinfo. */
148#ifndef NI_NUMERICHOST
149# define NI_NUMERICHOST 1
150#endif
151#ifndef NI_NUMERICSERV
152# define NI_NUMERICSERV 2
153#endif
154
155#endif /* GETADDRINFO_H */
diff --git a/gl/gethostname.c b/gl/gethostname.c
new file mode 100644
index 00000000..eedc40ec
--- /dev/null
+++ b/gl/gethostname.c
@@ -0,0 +1,52 @@
1/* gethostname emulation for SysV and POSIX.1.
2
3 Copyright (C) 1992, 2003, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* David MacKenzie <djm@gnu.ai.mit.edu> */
20
21#include <config.h>
22
23#ifdef HAVE_UNAME
24# include <sys/utsname.h>
25#endif
26
27/* Put up to LEN chars of the host name into NAME.
28 Null terminate it if the name is shorter than LEN.
29 Return 0 if ok, -1 if error. */
30
31#include <stddef.h>
32
33int
34gethostname (char *name, size_t len)
35{
36#ifdef HAVE_UNAME
37 struct utsname uts;
38
39 if (uname (&uts) == -1)
40 return -1;
41 if (len > sizeof (uts.nodename))
42 {
43 /* More space than we need is available. */
44 name[sizeof (uts.nodename)] = '\0';
45 len = sizeof (uts.nodename);
46 }
47 strncpy (name, uts.nodename, len);
48#else
49 strcpy (name, ""); /* Hardcode your system name if you want. */
50#endif
51 return 0;
52}
diff --git a/gl/getloadavg.c b/gl/getloadavg.c
new file mode 100644
index 00000000..cfa62735
--- /dev/null
+++ b/gl/getloadavg.c
@@ -0,0 +1,1020 @@
1/* Get the system load averages.
2
3 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994,
4 1995, 1997, 1999, 2000, 2003, 2004, 2005, 2006 Free Software
5 Foundation, Inc.
6
7 NOTE: The canonical source of this file is maintained with gnulib.
8 Bugs can be reported to bug-gnulib@gnu.org.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23 USA. */
24
25/* Compile-time symbols that this file uses:
26
27 HAVE_PSTAT_GETDYNAMIC Define this if your system has the
28 pstat_getdynamic function. I think it
29 is unique to HPUX9. The best way to get the
30 definition is through the AC_FUNC_GETLOADAVG
31 macro that comes with autoconf 2.13 or newer.
32 If that isn't an option, then just put
33 AC_CHECK_FUNCS(pstat_getdynamic) in your
34 configure.in file.
35 FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist.
36 KERNEL_FILE Name of the kernel file to nlist.
37 LDAV_CVT() Scale the load average from the kernel.
38 Returns a double.
39 LDAV_SYMBOL Name of kernel symbol giving load average.
40 LOAD_AVE_TYPE Type of the load average array in the kernel.
41 Must be defined unless one of
42 apollo, DGUX, NeXT, or UMAX is defined;
43 or we have libkstat;
44 otherwise, no load average is available.
45 HAVE_NLIST_H nlist.h is available. NLIST_STRUCT defaults
46 to this.
47 NLIST_STRUCT Include nlist.h, not a.out.h, and
48 the nlist n_name element is a pointer,
49 not an array.
50 HAVE_STRUCT_NLIST_N_UN_N_NAME `n_un.n_name' is member of `struct nlist'.
51 LINUX_LDAV_FILE [__linux__, __CYGWIN__]: File containing
52 load averages.
53
54 Specific system predefines this file uses, aside from setting
55 default values if not emacs:
56
57 apollo
58 BSD Real BSD, not just BSD-like.
59 convex
60 DGUX
61 eunice UNIX emulator under VMS.
62 hpux
63 __MSDOS__ No-op for MSDOS.
64 NeXT
65 sgi
66 sequent Sequent Dynix 3.x.x (BSD)
67 _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV)
68 sony_news NEWS-OS (works at least for 4.1C)
69 UMAX
70 UMAX4_3
71 VMS
72 WINDOWS32 No-op for Windows95/NT.
73 __linux__ Linux: assumes /proc file system mounted.
74 Support from Michael K. Johnson.
75 __CYGWIN__ Cygwin emulates linux /proc/loadavg.
76 __NetBSD__ NetBSD: assumes /kern file system mounted.
77
78 In addition, to avoid nesting many #ifdefs, we internally set
79 LDAV_DONE to indicate that the load average has been computed.
80
81 We also #define LDAV_PRIVILEGED if a program will require
82 special installation to be able to call getloadavg. */
83
84/* "configure" defines CONFIGURING_GETLOADAVG to sidestep problems
85 with partially-configured source directories. */
86
87#ifndef CONFIGURING_GETLOADAVG
88# include <config.h>
89# include <stdbool.h>
90#endif
91
92#include <errno.h>
93#include <stdio.h>
94#include <stdlib.h>
95
96/* Exclude all the code except the test program at the end
97 if the system has its own `getloadavg' function. */
98
99#ifndef HAVE_GETLOADAVG
100
101# include <sys/types.h>
102
103/* Both the Emacs and non-Emacs sections want this. Some
104 configuration files' definitions for the LOAD_AVE_CVT macro (like
105 sparc.h's) use macros like FSCALE, defined here. */
106# if defined (unix) || defined (__unix)
107# include <sys/param.h>
108# endif
109
110# include "c-strtod.h"
111# include "cloexec.h"
112# include "intprops.h"
113# include "xalloc.h"
114
115/* The existing Emacs configuration files define a macro called
116 LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
117 returns the load average multiplied by 100. What we actually want
118 is a macro called LDAV_CVT, which returns the load average as an
119 unmultiplied double.
120
121 For backwards compatibility, we'll define LDAV_CVT in terms of
122 LOAD_AVE_CVT, but future machine config files should just define
123 LDAV_CVT directly. */
124
125# if !defined (LDAV_CVT) && defined (LOAD_AVE_CVT)
126# define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
127# endif
128
129# if !defined (BSD) && defined (ultrix)
130/* Ultrix behaves like BSD on Vaxen. */
131# define BSD
132# endif
133
134# ifdef NeXT
135/* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
136 conflicts with the definition understood in this file, that this
137 really is BSD. */
138# undef BSD
139
140/* NeXT defines FSCALE in <sys/param.h>. However, we take FSCALE being
141 defined to mean that the nlist method should be used, which is not true. */
142# undef FSCALE
143# endif
144
145/* Same issues as for NeXT apply to the HURD-based GNU system. */
146# ifdef __GNU__
147# undef BSD
148# undef FSCALE
149# endif /* __GNU__ */
150
151/* Set values that are different from the defaults, which are
152 set a little farther down with #ifndef. */
153
154
155/* Some shorthands. */
156
157# if defined (HPUX) && !defined (hpux)
158# define hpux
159# endif
160
161# if defined (__hpux) && !defined (hpux)
162# define hpux
163# endif
164
165# if defined (__sun) && !defined (sun)
166# define sun
167# endif
168
169# if defined (hp300) && !defined (hpux)
170# define MORE_BSD
171# endif
172
173# if defined (ultrix) && defined (mips)
174# define decstation
175# endif
176
177# if defined (__SVR4) && !defined (SVR4)
178# define SVR4
179# endif
180
181# if (defined (sun) && defined (SVR4)) || defined (SOLARIS2)
182# define SUNOS_5
183# endif
184
185# if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
186# define OSF_ALPHA
187# include <sys/mbuf.h>
188# include <sys/socket.h>
189# include <net/route.h>
190# include <sys/table.h>
191# endif
192
193# if defined (__osf__) && (defined (mips) || defined (__mips__))
194# define OSF_MIPS
195# include <sys/table.h>
196# endif
197
198/* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
199 default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>. Combine
200 that with a couple of other things and we'll have a unique match. */
201# if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
202# define tek4300 /* Define by emacs, but not by other users. */
203# endif
204
205
206/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */
207# ifndef LOAD_AVE_TYPE
208
209# ifdef MORE_BSD
210# define LOAD_AVE_TYPE long
211# endif
212
213# ifdef sun
214# define LOAD_AVE_TYPE long
215# endif
216
217# ifdef decstation
218# define LOAD_AVE_TYPE long
219# endif
220
221# ifdef _SEQUENT_
222# define LOAD_AVE_TYPE long
223# endif
224
225# ifdef sgi
226# define LOAD_AVE_TYPE long
227# endif
228
229# ifdef SVR4
230# define LOAD_AVE_TYPE long
231# endif
232
233# ifdef sony_news
234# define LOAD_AVE_TYPE long
235# endif
236
237# ifdef sequent
238# define LOAD_AVE_TYPE long
239# endif
240
241# ifdef OSF_ALPHA
242# define LOAD_AVE_TYPE long
243# endif
244
245# if defined (ardent) && defined (titan)
246# define LOAD_AVE_TYPE long
247# endif
248
249# ifdef tek4300
250# define LOAD_AVE_TYPE long
251# endif
252
253# if defined (alliant) && defined (i860) /* Alliant FX/2800 */
254# define LOAD_AVE_TYPE long
255# endif
256
257# ifdef _AIX
258# define LOAD_AVE_TYPE long
259# endif
260
261# ifdef convex
262# define LOAD_AVE_TYPE double
263# ifndef LDAV_CVT
264# define LDAV_CVT(n) (n)
265# endif
266# endif
267
268# endif /* No LOAD_AVE_TYPE. */
269
270# ifdef OSF_ALPHA
271/* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
272 according to ghazi@noc.rutgers.edu. */
273# undef FSCALE
274# define FSCALE 1024.0
275# endif
276
277# if defined (alliant) && defined (i860) /* Alliant FX/2800 */
278/* <sys/param.h> defines an incorrect value for FSCALE on an
279 Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */
280# undef FSCALE
281# define FSCALE 100.0
282# endif
283
284
285# ifndef FSCALE
286
287/* SunOS and some others define FSCALE in sys/param.h. */
288
289# ifdef MORE_BSD
290# define FSCALE 2048.0
291# endif
292
293# if defined (MIPS) || defined (SVR4) || defined (decstation)
294# define FSCALE 256
295# endif
296
297# if defined (sgi) || defined (sequent)
298/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
299 above under #ifdef MIPS. But we want the sgi value. */
300# undef FSCALE
301# define FSCALE 1000.0
302# endif
303
304# if defined (ardent) && defined (titan)
305# define FSCALE 65536.0
306# endif
307
308# ifdef tek4300
309# define FSCALE 100.0
310# endif
311
312# ifdef _AIX
313# define FSCALE 65536.0
314# endif
315
316# endif /* Not FSCALE. */
317
318# if !defined (LDAV_CVT) && defined (FSCALE)
319# define LDAV_CVT(n) (((double) (n)) / FSCALE)
320# endif
321
322# ifndef NLIST_STRUCT
323# if HAVE_NLIST_H
324# define NLIST_STRUCT
325# endif
326# endif
327
328# if defined (sgi) || (defined (mips) && !defined (BSD))
329# define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
330# endif
331
332
333# if !defined (KERNEL_FILE) && defined (sequent)
334# define KERNEL_FILE "/dynix"
335# endif
336
337# if !defined (KERNEL_FILE) && defined (hpux)
338# define KERNEL_FILE "/hp-ux"
339# endif
340
341# if !defined (KERNEL_FILE) && (defined (_SEQUENT_) || defined (MIPS) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
342# define KERNEL_FILE "/unix"
343# endif
344
345
346# if !defined (LDAV_SYMBOL) && defined (alliant)
347# define LDAV_SYMBOL "_Loadavg"
348# endif
349
350# if !defined (LDAV_SYMBOL) && ((defined (hpux) && !defined (hp9000s300)) || defined (_SEQUENT_) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (ardent) && defined (titan)) || defined (_AIX))
351# define LDAV_SYMBOL "avenrun"
352# endif
353
354# include <unistd.h>
355
356/* LOAD_AVE_TYPE should only get defined if we're going to use the
357 nlist method. */
358# if !defined (LOAD_AVE_TYPE) && (defined (BSD) || defined (LDAV_CVT) || defined (KERNEL_FILE) || defined (LDAV_SYMBOL))
359# define LOAD_AVE_TYPE double
360# endif
361
362# ifdef LOAD_AVE_TYPE
363
364# ifndef __VMS
365# ifndef __linux__
366# ifndef NLIST_STRUCT
367# include <a.out.h>
368# else /* NLIST_STRUCT */
369# include <nlist.h>
370# endif /* NLIST_STRUCT */
371
372# ifdef SUNOS_5
373# include <fcntl.h>
374# include <kvm.h>
375# include <kstat.h>
376# endif
377
378# if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
379# include <sys/pstat.h>
380# endif
381
382# ifndef KERNEL_FILE
383# define KERNEL_FILE "/vmunix"
384# endif /* KERNEL_FILE */
385
386# ifndef LDAV_SYMBOL
387# define LDAV_SYMBOL "_avenrun"
388# endif /* LDAV_SYMBOL */
389# endif /* __linux__ */
390
391# else /* __VMS */
392
393# ifndef eunice
394# include <iodef.h>
395# include <descrip.h>
396# else /* eunice */
397# include <vms/iodef.h>
398# endif /* eunice */
399# endif /* __VMS */
400
401# ifndef LDAV_CVT
402# define LDAV_CVT(n) ((double) (n))
403# endif /* !LDAV_CVT */
404
405# endif /* LOAD_AVE_TYPE */
406
407# if defined (__GNU__) && !defined (NeXT)
408/* Note that NeXT Openstep defines __GNU__ even though it should not. */
409/* GNU system acts much like NeXT, for load average purposes,
410 but not exactly. */
411# define NeXT
412# define host_self mach_host_self
413# endif
414
415# ifdef NeXT
416# ifdef HAVE_MACH_MACH_H
417# include <mach/mach.h>
418# else
419# include <mach.h>
420# endif
421# endif /* NeXT */
422
423# ifdef sgi
424# include <sys/sysmp.h>
425# endif /* sgi */
426
427# ifdef UMAX
428# include <signal.h>
429# include <sys/time.h>
430# include <sys/wait.h>
431# include <sys/syscall.h>
432
433# ifdef UMAX_43
434# include <machine/cpu.h>
435# include <inq_stats/statistics.h>
436# include <inq_stats/sysstats.h>
437# include <inq_stats/cpustats.h>
438# include <inq_stats/procstats.h>
439# else /* Not UMAX_43. */
440# include <sys/sysdefs.h>
441# include <sys/statistics.h>
442# include <sys/sysstats.h>
443# include <sys/cpudefs.h>
444# include <sys/cpustats.h>
445# include <sys/procstats.h>
446# endif /* Not UMAX_43. */
447# endif /* UMAX */
448
449# ifdef DGUX
450# include <sys/dg_sys_info.h>
451# endif
452
453# include "fcntl--.h"
454
455/* Avoid static vars inside a function since in HPUX they dump as pure. */
456
457# ifdef NeXT
458static processor_set_t default_set;
459static bool getloadavg_initialized;
460# endif /* NeXT */
461
462# ifdef UMAX
463static unsigned int cpus = 0;
464static unsigned int samples;
465# endif /* UMAX */
466
467# ifdef DGUX
468static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */
469# endif /* DGUX */
470
471# if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE)
472/* File descriptor open to /dev/kmem or VMS load ave driver. */
473static int channel;
474/* True iff channel is valid. */
475static bool getloadavg_initialized;
476/* Offset in kmem to seek to read load average, or 0 means invalid. */
477static long offset;
478
479# if ! defined __VMS && ! defined sgi && ! defined __linux__
480static struct nlist nl[2];
481# endif
482
483# ifdef SUNOS_5
484static kvm_t *kd;
485# endif /* SUNOS_5 */
486
487# endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */
488
489/* Put the 1 minute, 5 minute and 15 minute load averages
490 into the first NELEM elements of LOADAVG.
491 Return the number written (never more than 3, but may be less than NELEM),
492 or -1 if an error occurred. */
493
494int
495getloadavg (double loadavg[], int nelem)
496{
497 int elem = 0; /* Return value. */
498
499# ifdef NO_GET_LOAD_AVG
500# define LDAV_DONE
501 /* Set errno to zero to indicate that there was no particular error;
502 this function just can't work at all on this system. */
503 errno = 0;
504 elem = -1;
505# endif
506
507# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
508/* Use libkstat because we don't have to be root. */
509# define LDAV_DONE
510 kstat_ctl_t *kc;
511 kstat_t *ksp;
512 kstat_named_t *kn;
513
514 kc = kstat_open ();
515 if (kc == 0)
516 return -1;
517 ksp = kstat_lookup (kc, "unix", 0, "system_misc");
518 if (ksp == 0)
519 return -1;
520 if (kstat_read (kc, ksp, 0) == -1)
521 return -1;
522
523
524 kn = kstat_data_lookup (ksp, "avenrun_1min");
525 if (kn == 0)
526 {
527 /* Return -1 if no load average information is available. */
528 nelem = 0;
529 elem = -1;
530 }
531
532 if (nelem >= 1)
533 loadavg[elem++] = (double) kn->value.ul / FSCALE;
534
535 if (nelem >= 2)
536 {
537 kn = kstat_data_lookup (ksp, "avenrun_5min");
538 if (kn != 0)
539 {
540 loadavg[elem++] = (double) kn->value.ul / FSCALE;
541
542 if (nelem >= 3)
543 {
544 kn = kstat_data_lookup (ksp, "avenrun_15min");
545 if (kn != 0)
546 loadavg[elem++] = (double) kn->value.ul / FSCALE;
547 }
548 }
549 }
550
551 kstat_close (kc);
552# endif /* HAVE_LIBKSTAT */
553
554# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
555/* Use pstat_getdynamic() because we don't have to be root. */
556# define LDAV_DONE
557# undef LOAD_AVE_TYPE
558
559 struct pst_dynamic dyn_info;
560 if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0)
561 return -1;
562 if (nelem > 0)
563 loadavg[elem++] = dyn_info.psd_avg_1_min;
564 if (nelem > 1)
565 loadavg[elem++] = dyn_info.psd_avg_5_min;
566 if (nelem > 2)
567 loadavg[elem++] = dyn_info.psd_avg_15_min;
568
569# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */
570
571# if !defined (LDAV_DONE) && (defined (__linux__) || defined (__CYGWIN__))
572# define LDAV_DONE
573# undef LOAD_AVE_TYPE
574
575# ifndef LINUX_LDAV_FILE
576# define LINUX_LDAV_FILE "/proc/loadavg"
577# endif
578
579 char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")];
580 char const *ptr = ldavgbuf;
581 int fd, count;
582
583 fd = open (LINUX_LDAV_FILE, O_RDONLY);
584 if (fd == -1)
585 return -1;
586 count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
587 (void) close (fd);
588 if (count <= 0)
589 return -1;
590 ldavgbuf[count] = '\0';
591
592 for (elem = 0; elem < nelem; elem++)
593 {
594 char *endptr;
595 double d = c_strtod (ptr, &endptr);
596 if (ptr == endptr)
597 {
598 if (elem == 0)
599 return -1;
600 break;
601 }
602 loadavg[elem] = d;
603 ptr = endptr;
604 }
605
606 return elem;
607
608# endif /* __linux__ || __CYGWIN__ */
609
610# if !defined (LDAV_DONE) && defined (__NetBSD__)
611# define LDAV_DONE
612# undef LOAD_AVE_TYPE
613
614# ifndef NETBSD_LDAV_FILE
615# define NETBSD_LDAV_FILE "/kern/loadavg"
616# endif
617
618 unsigned long int load_ave[3], scale;
619 int count;
620 FILE *fp;
621
622 fp = fopen (NETBSD_LDAV_FILE, "r");
623 if (fp == NULL)
624 return -1;
625 count = fscanf (fp, "%lu %lu %lu %lu\n",
626 &load_ave[0], &load_ave[1], &load_ave[2],
627 &scale);
628 (void) fclose (fp);
629 if (count != 4)
630 return -1;
631
632 for (elem = 0; elem < nelem; elem++)
633 loadavg[elem] = (double) load_ave[elem] / (double) scale;
634
635 return elem;
636
637# endif /* __NetBSD__ */
638
639# if !defined (LDAV_DONE) && defined (NeXT)
640# define LDAV_DONE
641 /* The NeXT code was adapted from iscreen 3.2. */
642
643 host_t host;
644 struct processor_set_basic_info info;
645 unsigned int info_count;
646
647 /* We only know how to get the 1-minute average for this system,
648 so even if the caller asks for more than 1, we only return 1. */
649
650 if (!getloadavg_initialized)
651 {
652 if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
653 getloadavg_initialized = true;
654 }
655
656 if (getloadavg_initialized)
657 {
658 info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
659 if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
660 (processor_set_info_t) &info, &info_count)
661 != KERN_SUCCESS)
662 getloadavg_initialized = false;
663 else
664 {
665 if (nelem > 0)
666 loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
667 }
668 }
669
670 if (!getloadavg_initialized)
671 return -1;
672# endif /* NeXT */
673
674# if !defined (LDAV_DONE) && defined (UMAX)
675# define LDAV_DONE
676/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
677 have a /dev/kmem. Information about the workings of the running kernel
678 can be gathered with inq_stats system calls.
679 We only know how to get the 1-minute average for this system. */
680
681 struct proc_summary proc_sum_data;
682 struct stat_descr proc_info;
683 double load;
684 register unsigned int i, j;
685
686 if (cpus == 0)
687 {
688 register unsigned int c, i;
689 struct cpu_config conf;
690 struct stat_descr desc;
691
692 desc.sd_next = 0;
693 desc.sd_subsys = SUBSYS_CPU;
694 desc.sd_type = CPUTYPE_CONFIG;
695 desc.sd_addr = (char *) &conf;
696 desc.sd_size = sizeof conf;
697
698 if (inq_stats (1, &desc))
699 return -1;
700
701 c = 0;
702 for (i = 0; i < conf.config_maxclass; ++i)
703 {
704 struct class_stats stats;
705 bzero ((char *) &stats, sizeof stats);
706
707 desc.sd_type = CPUTYPE_CLASS;
708 desc.sd_objid = i;
709 desc.sd_addr = (char *) &stats;
710 desc.sd_size = sizeof stats;
711
712 if (inq_stats (1, &desc))
713 return -1;
714
715 c += stats.class_numcpus;
716 }
717 cpus = c;
718 samples = cpus < 2 ? 3 : (2 * cpus / 3);
719 }
720
721 proc_info.sd_next = 0;
722 proc_info.sd_subsys = SUBSYS_PROC;
723 proc_info.sd_type = PROCTYPE_SUMMARY;
724 proc_info.sd_addr = (char *) &proc_sum_data;
725 proc_info.sd_size = sizeof (struct proc_summary);
726 proc_info.sd_sizeused = 0;
727
728 if (inq_stats (1, &proc_info) != 0)
729 return -1;
730
731 load = proc_sum_data.ps_nrunnable;
732 j = 0;
733 for (i = samples - 1; i > 0; --i)
734 {
735 load += proc_sum_data.ps_nrun[j];
736 if (j++ == PS_NRUNSIZE)
737 j = 0;
738 }
739
740 if (nelem > 0)
741 loadavg[elem++] = load / samples / cpus;
742# endif /* UMAX */
743
744# if !defined (LDAV_DONE) && defined (DGUX)
745# define LDAV_DONE
746 /* This call can return -1 for an error, but with good args
747 it's not supposed to fail. The first argument is for no
748 apparent reason of type `long int *'. */
749 dg_sys_info ((long int *) &load_info,
750 DG_SYS_INFO_LOAD_INFO_TYPE,
751 DG_SYS_INFO_LOAD_VERSION_0);
752
753 if (nelem > 0)
754 loadavg[elem++] = load_info.one_minute;
755 if (nelem > 1)
756 loadavg[elem++] = load_info.five_minute;
757 if (nelem > 2)
758 loadavg[elem++] = load_info.fifteen_minute;
759# endif /* DGUX */
760
761# if !defined (LDAV_DONE) && defined (apollo)
762# define LDAV_DONE
763/* Apollo code from lisch@mentorg.com (Ray Lischner).
764
765 This system call is not documented. The load average is obtained as
766 three long integers, for the load average over the past minute,
767 five minutes, and fifteen minutes. Each value is a scaled integer,
768 with 16 bits of integer part and 16 bits of fraction part.
769
770 I'm not sure which operating system first supported this system call,
771 but I know that SR10.2 supports it. */
772
773 extern void proc1_$get_loadav ();
774 unsigned long load_ave[3];
775
776 proc1_$get_loadav (load_ave);
777
778 if (nelem > 0)
779 loadavg[elem++] = load_ave[0] / 65536.0;
780 if (nelem > 1)
781 loadavg[elem++] = load_ave[1] / 65536.0;
782 if (nelem > 2)
783 loadavg[elem++] = load_ave[2] / 65536.0;
784# endif /* apollo */
785
786# if !defined (LDAV_DONE) && defined (OSF_MIPS)
787# define LDAV_DONE
788
789 struct tbl_loadavg load_ave;
790 table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
791 loadavg[elem++]
792 = (load_ave.tl_lscale == 0
793 ? load_ave.tl_avenrun.d[0]
794 : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
795# endif /* OSF_MIPS */
796
797# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
798# define LDAV_DONE
799
800 /* A faithful emulation is going to have to be saved for a rainy day. */
801 for ( ; elem < nelem; elem++)
802 {
803 loadavg[elem] = 0.0;
804 }
805# endif /* __MSDOS__ || WINDOWS32 */
806
807# if !defined (LDAV_DONE) && defined (OSF_ALPHA)
808# define LDAV_DONE
809
810 struct tbl_loadavg load_ave;
811 table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
812 for (elem = 0; elem < nelem; elem++)
813 loadavg[elem]
814 = (load_ave.tl_lscale == 0
815 ? load_ave.tl_avenrun.d[elem]
816 : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
817# endif /* OSF_ALPHA */
818
819# if ! defined LDAV_DONE && defined __VMS
820 /* VMS specific code -- read from the Load Ave driver. */
821
822 LOAD_AVE_TYPE load_ave[3];
823 static bool getloadavg_initialized;
824# ifdef eunice
825 struct
826 {
827 int dsc$w_length;
828 char *dsc$a_pointer;
829 } descriptor;
830# endif
831
832 /* Ensure that there is a channel open to the load ave device. */
833 if (!getloadavg_initialized)
834 {
835 /* Attempt to open the channel. */
836# ifdef eunice
837 descriptor.dsc$w_length = 18;
838 descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
839# else
840 $DESCRIPTOR (descriptor, "LAV0:");
841# endif
842 if (sys$assign (&descriptor, &channel, 0, 0) & 1)
843 getloadavg_initialized = true;
844 }
845
846 /* Read the load average vector. */
847 if (getloadavg_initialized
848 && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
849 load_ave, 12, 0, 0, 0, 0) & 1))
850 {
851 sys$dassgn (channel);
852 getloadavg_initialized = false;
853 }
854
855 if (!getloadavg_initialized)
856 return -1;
857# endif /* ! defined LDAV_DONE && defined __VMS */
858
859# if ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS
860
861 /* UNIX-specific code -- read the average from /dev/kmem. */
862
863# define LDAV_PRIVILEGED /* This code requires special installation. */
864
865 LOAD_AVE_TYPE load_ave[3];
866
867 /* Get the address of LDAV_SYMBOL. */
868 if (offset == 0)
869 {
870# ifndef sgi
871# ifndef NLIST_STRUCT
872 strcpy (nl[0].n_name, LDAV_SYMBOL);
873 strcpy (nl[1].n_name, "");
874# else /* NLIST_STRUCT */
875# ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
876 nl[0].n_un.n_name = LDAV_SYMBOL;
877 nl[1].n_un.n_name = 0;
878# else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
879 nl[0].n_name = LDAV_SYMBOL;
880 nl[1].n_name = 0;
881# endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
882# endif /* NLIST_STRUCT */
883
884# ifndef SUNOS_5
885 if (
886# if !(defined (_AIX) && !defined (ps2))
887 nlist (KERNEL_FILE, nl)
888# else /* _AIX */
889 knlist (nl, 1, sizeof (nl[0]))
890# endif
891 >= 0)
892 /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */
893 {
894# ifdef FIXUP_KERNEL_SYMBOL_ADDR
895 FIXUP_KERNEL_SYMBOL_ADDR (nl);
896# endif
897 offset = nl[0].n_value;
898 }
899# endif /* !SUNOS_5 */
900# else /* sgi */
901 int ldav_off;
902
903 ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
904 if (ldav_off != -1)
905 offset = (long int) ldav_off & 0x7fffffff;
906# endif /* sgi */
907 }
908
909 /* Make sure we have /dev/kmem open. */
910 if (!getloadavg_initialized)
911 {
912# ifndef SUNOS_5
913 channel = open ("/dev/kmem", O_RDONLY);
914 if (channel >= 0)
915 {
916 /* Set the channel to close on exec, so it does not
917 litter any child's descriptor table. */
918 set_cloexec_flag (channel, true);
919 getloadavg_initialized = true;
920 }
921# else /* SUNOS_5 */
922 /* We pass 0 for the kernel, corefile, and swapfile names
923 to use the currently running kernel. */
924 kd = kvm_open (0, 0, 0, O_RDONLY, 0);
925 if (kd != 0)
926 {
927 /* nlist the currently running kernel. */
928 kvm_nlist (kd, nl);
929 offset = nl[0].n_value;
930 getloadavg_initialized = true;
931 }
932# endif /* SUNOS_5 */
933 }
934
935 /* If we can, get the load average values. */
936 if (offset && getloadavg_initialized)
937 {
938 /* Try to read the load. */
939# ifndef SUNOS_5
940 if (lseek (channel, offset, 0) == -1L
941 || read (channel, (char *) load_ave, sizeof (load_ave))
942 != sizeof (load_ave))
943 {
944 close (channel);
945 getloadavg_initialized = false;
946 }
947# else /* SUNOS_5 */
948 if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
949 != sizeof (load_ave))
950 {
951 kvm_close (kd);
952 getloadavg_initialized = false;
953 }
954# endif /* SUNOS_5 */
955 }
956
957 if (offset == 0 || !getloadavg_initialized)
958 return -1;
959# endif /* ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS */
960
961# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */
962 if (nelem > 0)
963 loadavg[elem++] = LDAV_CVT (load_ave[0]);
964 if (nelem > 1)
965 loadavg[elem++] = LDAV_CVT (load_ave[1]);
966 if (nelem > 2)
967 loadavg[elem++] = LDAV_CVT (load_ave[2]);
968
969# define LDAV_DONE
970# endif /* !LDAV_DONE && LOAD_AVE_TYPE */
971
972# if !defined LDAV_DONE
973 /* Set errno to zero to indicate that there was no particular error;
974 this function just can't work at all on this system. */
975 errno = 0;
976 elem = -1;
977# endif
978 return elem;
979}
980
981#endif /* ! HAVE_GETLOADAVG */
982
983#ifdef TEST
984int
985main (int argc, char **argv)
986{
987 int naptime = 0;
988
989 if (argc > 1)
990 naptime = atoi (argv[1]);
991
992 while (1)
993 {
994 double avg[3];
995 int loads;
996
997 errno = 0; /* Don't be misled if it doesn't set errno. */
998 loads = getloadavg (avg, 3);
999 if (loads == -1)
1000 {
1001 perror ("Error getting load average");
1002 return EXIT_FAILURE;
1003 }
1004 if (loads > 0)
1005 printf ("1-minute: %f ", avg[0]);
1006 if (loads > 1)
1007 printf ("5-minute: %f ", avg[1]);
1008 if (loads > 2)
1009 printf ("15-minute: %f ", avg[2]);
1010 if (loads > 0)
1011 putchar ('\n');
1012
1013 if (naptime == 0)
1014 break;
1015 sleep (naptime);
1016 }
1017
1018 return EXIT_SUCCESS;
1019}
1020#endif /* TEST */
diff --git a/gl/getopt.c b/gl/getopt.c
new file mode 100644
index 00000000..3580ad82
--- /dev/null
+++ b/gl/getopt.c
@@ -0,0 +1,1191 @@
1/* Getopt for GNU.
2 NOTE: getopt is now part of the C library, so if you don't know what
3 "Keep this file name-space clean" means, talk to drepper@gnu.org
4 before changing it!
5 Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
6 Free Software Foundation, Inc.
7 This file is part of the GNU C Library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with this program; if not, write to the Free Software Foundation,
21 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#ifndef _LIBC
24# include <config.h>
25#endif
26
27#include "getopt.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#ifdef __VMS
35# include <unixlib.h>
36#endif
37
38#ifdef _LIBC
39# include <libintl.h>
40#else
41# include "gettext.h"
42# define _(msgid) gettext (msgid)
43#endif
44
45#if defined _LIBC && defined USE_IN_LIBIO
46# include <wchar.h>
47#endif
48
49#ifndef attribute_hidden
50# define attribute_hidden
51#endif
52
53/* Unlike standard Unix `getopt', functions like `getopt_long'
54 let the user intersperse the options with the other arguments.
55
56 As `getopt_long' works, it permutes the elements of ARGV so that,
57 when it is done, all the options precede everything else. Thus
58 all application programs are extended to handle flexible argument order.
59
60 Using `getopt' or setting the environment variable POSIXLY_CORRECT
61 disables permutation.
62 Then the application's behavior is completely standard.
63
64 GNU application programs can use a third alternative mode in which
65 they can distinguish the relative order of options and other arguments. */
66
67#include "getopt_int.h"
68
69/* For communication from `getopt' to the caller.
70 When `getopt' finds an option that takes an argument,
71 the argument value is returned here.
72 Also, when `ordering' is RETURN_IN_ORDER,
73 each non-option ARGV-element is returned here. */
74
75char *optarg;
76
77/* Index in ARGV of the next element to be scanned.
78 This is used for communication to and from the caller
79 and for communication between successive calls to `getopt'.
80
81 On entry to `getopt', zero means this is the first call; initialize.
82
83 When `getopt' returns -1, this is the index of the first of the
84 non-option elements that the caller should itself scan.
85
86 Otherwise, `optind' communicates from one call to the next
87 how much of ARGV has been scanned so far. */
88
89/* 1003.2 says this must be 1 before any call. */
90int optind = 1;
91
92/* Callers store zero here to inhibit the error message
93 for unrecognized options. */
94
95int opterr = 1;
96
97/* Set to an option character which was unrecognized.
98 This must be initialized on some systems to avoid linking in the
99 system's own getopt implementation. */
100
101int optopt = '?';
102
103/* Keep a global copy of all internal members of getopt_data. */
104
105static struct _getopt_data getopt_data;
106
107
108#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
109extern char *getenv ();
110#endif
111
112#ifdef _LIBC
113/* Stored original parameters.
114 XXX This is no good solution. We should rather copy the args so
115 that we can compare them later. But we must not use malloc(3). */
116extern int __libc_argc;
117extern char **__libc_argv;
118
119/* Bash 2.0 gives us an environment variable containing flags
120 indicating ARGV elements that should not be considered arguments. */
121
122# ifdef USE_NONOPTION_FLAGS
123/* Defined in getopt_init.c */
124extern char *__getopt_nonoption_flags;
125# endif
126
127# ifdef USE_NONOPTION_FLAGS
128# define SWAP_FLAGS(ch1, ch2) \
129 if (d->__nonoption_flags_len > 0) \
130 { \
131 char __tmp = __getopt_nonoption_flags[ch1]; \
132 __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
133 __getopt_nonoption_flags[ch2] = __tmp; \
134 }
135# else
136# define SWAP_FLAGS(ch1, ch2)
137# endif
138#else /* !_LIBC */
139# define SWAP_FLAGS(ch1, ch2)
140#endif /* _LIBC */
141
142/* Exchange two adjacent subsequences of ARGV.
143 One subsequence is elements [first_nonopt,last_nonopt)
144 which contains all the non-options that have been skipped so far.
145 The other is elements [last_nonopt,optind), which contains all
146 the options processed since those non-options were skipped.
147
148 `first_nonopt' and `last_nonopt' are relocated so that they describe
149 the new indices of the non-options in ARGV after they are moved. */
150
151static void
152exchange (char **argv, struct _getopt_data *d)
153{
154 int bottom = d->__first_nonopt;
155 int middle = d->__last_nonopt;
156 int top = d->optind;
157 char *tem;
158
159 /* Exchange the shorter segment with the far end of the longer segment.
160 That puts the shorter segment into the right place.
161 It leaves the longer segment in the right place overall,
162 but it consists of two parts that need to be swapped next. */
163
164#if defined _LIBC && defined USE_NONOPTION_FLAGS
165 /* First make sure the handling of the `__getopt_nonoption_flags'
166 string can work normally. Our top argument must be in the range
167 of the string. */
168 if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
169 {
170 /* We must extend the array. The user plays games with us and
171 presents new arguments. */
172 char *new_str = malloc (top + 1);
173 if (new_str == NULL)
174 d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
175 else
176 {
177 memset (__mempcpy (new_str, __getopt_nonoption_flags,
178 d->__nonoption_flags_max_len),
179 '\0', top + 1 - d->__nonoption_flags_max_len);
180 d->__nonoption_flags_max_len = top + 1;
181 __getopt_nonoption_flags = new_str;
182 }
183 }
184#endif
185
186 while (top > middle && middle > bottom)
187 {
188 if (top - middle > middle - bottom)
189 {
190 /* Bottom segment is the short one. */
191 int len = middle - bottom;
192 register int i;
193
194 /* Swap it with the top part of the top segment. */
195 for (i = 0; i < len; i++)
196 {
197 tem = argv[bottom + i];
198 argv[bottom + i] = argv[top - (middle - bottom) + i];
199 argv[top - (middle - bottom) + i] = tem;
200 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
201 }
202 /* Exclude the moved bottom segment from further swapping. */
203 top -= len;
204 }
205 else
206 {
207 /* Top segment is the short one. */
208 int len = top - middle;
209 register int i;
210
211 /* Swap it with the bottom part of the bottom segment. */
212 for (i = 0; i < len; i++)
213 {
214 tem = argv[bottom + i];
215 argv[bottom + i] = argv[middle + i];
216 argv[middle + i] = tem;
217 SWAP_FLAGS (bottom + i, middle + i);
218 }
219 /* Exclude the moved top segment from further swapping. */
220 bottom += len;
221 }
222 }
223
224 /* Update records for the slots the non-options now occupy. */
225
226 d->__first_nonopt += (d->optind - d->__last_nonopt);
227 d->__last_nonopt = d->optind;
228}
229
230/* Initialize the internal data when the first call is made. */
231
232static const char *
233_getopt_initialize (int argc, char **argv, const char *optstring,
234 int posixly_correct, struct _getopt_data *d)
235{
236 /* Start processing options with ARGV-element 1 (since ARGV-element 0
237 is the program name); the sequence of previously skipped
238 non-option ARGV-elements is empty. */
239
240 d->__first_nonopt = d->__last_nonopt = d->optind;
241
242 d->__nextchar = NULL;
243
244 d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
245
246 /* Determine how to handle the ordering of options and nonoptions. */
247
248 if (optstring[0] == '-')
249 {
250 d->__ordering = RETURN_IN_ORDER;
251 ++optstring;
252 }
253 else if (optstring[0] == '+')
254 {
255 d->__ordering = REQUIRE_ORDER;
256 ++optstring;
257 }
258 else if (d->__posixly_correct)
259 d->__ordering = REQUIRE_ORDER;
260 else
261 d->__ordering = PERMUTE;
262
263#if defined _LIBC && defined USE_NONOPTION_FLAGS
264 if (!d->__posixly_correct
265 && argc == __libc_argc && argv == __libc_argv)
266 {
267 if (d->__nonoption_flags_max_len == 0)
268 {
269 if (__getopt_nonoption_flags == NULL
270 || __getopt_nonoption_flags[0] == '\0')
271 d->__nonoption_flags_max_len = -1;
272 else
273 {
274 const char *orig_str = __getopt_nonoption_flags;
275 int len = d->__nonoption_flags_max_len = strlen (orig_str);
276 if (d->__nonoption_flags_max_len < argc)
277 d->__nonoption_flags_max_len = argc;
278 __getopt_nonoption_flags =
279 (char *) malloc (d->__nonoption_flags_max_len);
280 if (__getopt_nonoption_flags == NULL)
281 d->__nonoption_flags_max_len = -1;
282 else
283 memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
284 '\0', d->__nonoption_flags_max_len - len);
285 }
286 }
287 d->__nonoption_flags_len = d->__nonoption_flags_max_len;
288 }
289 else
290 d->__nonoption_flags_len = 0;
291#endif
292
293 return optstring;
294}
295
296/* Scan elements of ARGV (whose length is ARGC) for option characters
297 given in OPTSTRING.
298
299 If an element of ARGV starts with '-', and is not exactly "-" or "--",
300 then it is an option element. The characters of this element
301 (aside from the initial '-') are option characters. If `getopt'
302 is called repeatedly, it returns successively each of the option characters
303 from each of the option elements.
304
305 If `getopt' finds another option character, it returns that character,
306 updating `optind' and `nextchar' so that the next call to `getopt' can
307 resume the scan with the following option character or ARGV-element.
308
309 If there are no more option characters, `getopt' returns -1.
310 Then `optind' is the index in ARGV of the first ARGV-element
311 that is not an option. (The ARGV-elements have been permuted
312 so that those that are not options now come last.)
313
314 OPTSTRING is a string containing the legitimate option characters.
315 If an option character is seen that is not listed in OPTSTRING,
316 return '?' after printing an error message. If you set `opterr' to
317 zero, the error message is suppressed but we still return '?'.
318
319 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
320 so the following text in the same ARGV-element, or the text of the following
321 ARGV-element, is returned in `optarg'. Two colons mean an option that
322 wants an optional arg; if there is text in the current ARGV-element,
323 it is returned in `optarg', otherwise `optarg' is set to zero.
324
325 If OPTSTRING starts with `-' or `+', it requests different methods of
326 handling the non-option ARGV-elements.
327 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
328
329 Long-named options begin with `--' instead of `-'.
330 Their names may be abbreviated as long as the abbreviation is unique
331 or is an exact match for some defined option. If they have an
332 argument, it follows the option name in the same ARGV-element, separated
333 from the option name by a `=', or else the in next ARGV-element.
334 When `getopt' finds a long-named option, it returns 0 if that option's
335 `flag' field is nonzero, the value of the option's `val' field
336 if the `flag' field is zero.
337
338 LONGOPTS is a vector of `struct option' terminated by an
339 element containing a name which is zero.
340
341 LONGIND returns the index in LONGOPT of the long-named option found.
342 It is only valid when a long-named option has been found by the most
343 recent call.
344
345 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
346 long-named options.
347
348 If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
349 environment variable were set. */
350
351int
352_getopt_internal_r (int argc, char **argv, const char *optstring,
353 const struct option *longopts, int *longind,
354 int long_only, int posixly_correct, struct _getopt_data *d)
355{
356 int print_errors = d->opterr;
357 if (optstring[0] == ':')
358 print_errors = 0;
359
360 if (argc < 1)
361 return -1;
362
363 d->optarg = NULL;
364
365 if (d->optind == 0 || !d->__initialized)
366 {
367 if (d->optind == 0)
368 d->optind = 1; /* Don't scan ARGV[0], the program name. */
369 optstring = _getopt_initialize (argc, argv, optstring,
370 posixly_correct, d);
371 d->__initialized = 1;
372 }
373
374 /* Test whether ARGV[optind] points to a non-option argument.
375 Either it does not have option syntax, or there is an environment flag
376 from the shell indicating it is not an option. The later information
377 is only used when the used in the GNU libc. */
378#if defined _LIBC && defined USE_NONOPTION_FLAGS
379# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
380 || (d->optind < d->__nonoption_flags_len \
381 && __getopt_nonoption_flags[d->optind] == '1'))
382#else
383# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
384#endif
385
386 if (d->__nextchar == NULL || *d->__nextchar == '\0')
387 {
388 /* Advance to the next ARGV-element. */
389
390 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
391 moved back by the user (who may also have changed the arguments). */
392 if (d->__last_nonopt > d->optind)
393 d->__last_nonopt = d->optind;
394 if (d->__first_nonopt > d->optind)
395 d->__first_nonopt = d->optind;
396
397 if (d->__ordering == PERMUTE)
398 {
399 /* If we have just processed some options following some non-options,
400 exchange them so that the options come first. */
401
402 if (d->__first_nonopt != d->__last_nonopt
403 && d->__last_nonopt != d->optind)
404 exchange ((char **) argv, d);
405 else if (d->__last_nonopt != d->optind)
406 d->__first_nonopt = d->optind;
407
408 /* Skip any additional non-options
409 and extend the range of non-options previously skipped. */
410
411 while (d->optind < argc && NONOPTION_P)
412 d->optind++;
413 d->__last_nonopt = d->optind;
414 }
415
416 /* The special ARGV-element `--' means premature end of options.
417 Skip it like a null option,
418 then exchange with previous non-options as if it were an option,
419 then skip everything else like a non-option. */
420
421 if (d->optind != argc && !strcmp (argv[d->optind], "--"))
422 {
423 d->optind++;
424
425 if (d->__first_nonopt != d->__last_nonopt
426 && d->__last_nonopt != d->optind)
427 exchange ((char **) argv, d);
428 else if (d->__first_nonopt == d->__last_nonopt)
429 d->__first_nonopt = d->optind;
430 d->__last_nonopt = argc;
431
432 d->optind = argc;
433 }
434
435 /* If we have done all the ARGV-elements, stop the scan
436 and back over any non-options that we skipped and permuted. */
437
438 if (d->optind == argc)
439 {
440 /* Set the next-arg-index to point at the non-options
441 that we previously skipped, so the caller will digest them. */
442 if (d->__first_nonopt != d->__last_nonopt)
443 d->optind = d->__first_nonopt;
444 return -1;
445 }
446
447 /* If we have come to a non-option and did not permute it,
448 either stop the scan or describe it to the caller and pass it by. */
449
450 if (NONOPTION_P)
451 {
452 if (d->__ordering == REQUIRE_ORDER)
453 return -1;
454 d->optarg = argv[d->optind++];
455 return 1;
456 }
457
458 /* We have found another option-ARGV-element.
459 Skip the initial punctuation. */
460
461 d->__nextchar = (argv[d->optind] + 1
462 + (longopts != NULL && argv[d->optind][1] == '-'));
463 }
464
465 /* Decode the current option-ARGV-element. */
466
467 /* Check whether the ARGV-element is a long option.
468
469 If long_only and the ARGV-element has the form "-f", where f is
470 a valid short option, don't consider it an abbreviated form of
471 a long option that starts with f. Otherwise there would be no
472 way to give the -f short option.
473
474 On the other hand, if there's a long option "fubar" and
475 the ARGV-element is "-fu", do consider that an abbreviation of
476 the long option, just like "--fu", and not "-f" with arg "u".
477
478 This distinction seems to be the most useful approach. */
479
480 if (longopts != NULL
481 && (argv[d->optind][1] == '-'
482 || (long_only && (argv[d->optind][2]
483 || !strchr (optstring, argv[d->optind][1])))))
484 {
485 char *nameend;
486 const struct option *p;
487 const struct option *pfound = NULL;
488 int exact = 0;
489 int ambig = 0;
490 int indfound = -1;
491 int option_index;
492
493 for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
494 /* Do nothing. */ ;
495
496 /* Test all long options for either exact match
497 or abbreviated matches. */
498 for (p = longopts, option_index = 0; p->name; p++, option_index++)
499 if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
500 {
501 if ((unsigned int) (nameend - d->__nextchar)
502 == (unsigned int) strlen (p->name))
503 {
504 /* Exact match found. */
505 pfound = p;
506 indfound = option_index;
507 exact = 1;
508 break;
509 }
510 else if (pfound == NULL)
511 {
512 /* First nonexact match found. */
513 pfound = p;
514 indfound = option_index;
515 }
516 else if (long_only
517 || pfound->has_arg != p->has_arg
518 || pfound->flag != p->flag
519 || pfound->val != p->val)
520 /* Second or later nonexact match found. */
521 ambig = 1;
522 }
523
524 if (ambig && !exact)
525 {
526 if (print_errors)
527 {
528#if defined _LIBC && defined USE_IN_LIBIO
529 char *buf;
530
531 if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
532 argv[0], argv[d->optind]) >= 0)
533 {
534 _IO_flockfile (stderr);
535
536 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
537 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
538
539 __fxprintf (NULL, "%s", buf);
540
541 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
542 _IO_funlockfile (stderr);
543
544 free (buf);
545 }
546#else
547 fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
548 argv[0], argv[d->optind]);
549#endif
550 }
551 d->__nextchar += strlen (d->__nextchar);
552 d->optind++;
553 d->optopt = 0;
554 return '?';
555 }
556
557 if (pfound != NULL)
558 {
559 option_index = indfound;
560 d->optind++;
561 if (*nameend)
562 {
563 /* Don't test has_arg with >, because some C compilers don't
564 allow it to be used on enums. */
565 if (pfound->has_arg)
566 d->optarg = nameend + 1;
567 else
568 {
569 if (print_errors)
570 {
571#if defined _LIBC && defined USE_IN_LIBIO
572 char *buf;
573 int n;
574#endif
575
576 if (argv[d->optind - 1][1] == '-')
577 {
578 /* --option */
579#if defined _LIBC && defined USE_IN_LIBIO
580 n = __asprintf (&buf, _("\
581%s: option `--%s' doesn't allow an argument\n"),
582 argv[0], pfound->name);
583#else
584 fprintf (stderr, _("\
585%s: option `--%s' doesn't allow an argument\n"),
586 argv[0], pfound->name);
587#endif
588 }
589 else
590 {
591 /* +option or -option */
592#if defined _LIBC && defined USE_IN_LIBIO
593 n = __asprintf (&buf, _("\
594%s: option `%c%s' doesn't allow an argument\n"),
595 argv[0], argv[d->optind - 1][0],
596 pfound->name);
597#else
598 fprintf (stderr, _("\
599%s: option `%c%s' doesn't allow an argument\n"),
600 argv[0], argv[d->optind - 1][0],
601 pfound->name);
602#endif
603 }
604
605#if defined _LIBC && defined USE_IN_LIBIO
606 if (n >= 0)
607 {
608 _IO_flockfile (stderr);
609
610 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
611 ((_IO_FILE *) stderr)->_flags2
612 |= _IO_FLAGS2_NOTCANCEL;
613
614 __fxprintf (NULL, "%s", buf);
615
616 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
617 _IO_funlockfile (stderr);
618
619 free (buf);
620 }
621#endif
622 }
623
624 d->__nextchar += strlen (d->__nextchar);
625
626 d->optopt = pfound->val;
627 return '?';
628 }
629 }
630 else if (pfound->has_arg == 1)
631 {
632 if (d->optind < argc)
633 d->optarg = argv[d->optind++];
634 else
635 {
636 if (print_errors)
637 {
638#if defined _LIBC && defined USE_IN_LIBIO
639 char *buf;
640
641 if (__asprintf (&buf, _("\
642%s: option `%s' requires an argument\n"),
643 argv[0], argv[d->optind - 1]) >= 0)
644 {
645 _IO_flockfile (stderr);
646
647 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
648 ((_IO_FILE *) stderr)->_flags2
649 |= _IO_FLAGS2_NOTCANCEL;
650
651 __fxprintf (NULL, "%s", buf);
652
653 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
654 _IO_funlockfile (stderr);
655
656 free (buf);
657 }
658#else
659 fprintf (stderr,
660 _("%s: option `%s' requires an argument\n"),
661 argv[0], argv[d->optind - 1]);
662#endif
663 }
664 d->__nextchar += strlen (d->__nextchar);
665 d->optopt = pfound->val;
666 return optstring[0] == ':' ? ':' : '?';
667 }
668 }
669 d->__nextchar += strlen (d->__nextchar);
670 if (longind != NULL)
671 *longind = option_index;
672 if (pfound->flag)
673 {
674 *(pfound->flag) = pfound->val;
675 return 0;
676 }
677 return pfound->val;
678 }
679
680 /* Can't find it as a long option. If this is not getopt_long_only,
681 or the option starts with '--' or is not a valid short
682 option, then it's an error.
683 Otherwise interpret it as a short option. */
684 if (!long_only || argv[d->optind][1] == '-'
685 || strchr (optstring, *d->__nextchar) == NULL)
686 {
687 if (print_errors)
688 {
689#if defined _LIBC && defined USE_IN_LIBIO
690 char *buf;
691 int n;
692#endif
693
694 if (argv[d->optind][1] == '-')
695 {
696 /* --option */
697#if defined _LIBC && defined USE_IN_LIBIO
698 n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
699 argv[0], d->__nextchar);
700#else
701 fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
702 argv[0], d->__nextchar);
703#endif
704 }
705 else
706 {
707 /* +option or -option */
708#if defined _LIBC && defined USE_IN_LIBIO
709 n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
710 argv[0], argv[d->optind][0], d->__nextchar);
711#else
712 fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
713 argv[0], argv[d->optind][0], d->__nextchar);
714#endif
715 }
716
717#if defined _LIBC && defined USE_IN_LIBIO
718 if (n >= 0)
719 {
720 _IO_flockfile (stderr);
721
722 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
723 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
724
725 __fxprintf (NULL, "%s", buf);
726
727 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
728 _IO_funlockfile (stderr);
729
730 free (buf);
731 }
732#endif
733 }
734 d->__nextchar = (char *) "";
735 d->optind++;
736 d->optopt = 0;
737 return '?';
738 }
739 }
740
741 /* Look at and handle the next short option-character. */
742
743 {
744 char c = *d->__nextchar++;
745 char *temp = strchr (optstring, c);
746
747 /* Increment `optind' when we start to process its last character. */
748 if (*d->__nextchar == '\0')
749 ++d->optind;
750
751 if (temp == NULL || c == ':')
752 {
753 if (print_errors)
754 {
755#if defined _LIBC && defined USE_IN_LIBIO
756 char *buf;
757 int n;
758#endif
759
760 if (d->__posixly_correct)
761 {
762 /* 1003.2 specifies the format of this message. */
763#if defined _LIBC && defined USE_IN_LIBIO
764 n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
765 argv[0], c);
766#else
767 fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
768#endif
769 }
770 else
771 {
772#if defined _LIBC && defined USE_IN_LIBIO
773 n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
774 argv[0], c);
775#else
776 fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
777#endif
778 }
779
780#if defined _LIBC && defined USE_IN_LIBIO
781 if (n >= 0)
782 {
783 _IO_flockfile (stderr);
784
785 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
786 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
787
788 __fxprintf (NULL, "%s", buf);
789
790 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
791 _IO_funlockfile (stderr);
792
793 free (buf);
794 }
795#endif
796 }
797 d->optopt = c;
798 return '?';
799 }
800 /* Convenience. Treat POSIX -W foo same as long option --foo */
801 if (temp[0] == 'W' && temp[1] == ';')
802 {
803 char *nameend;
804 const struct option *p;
805 const struct option *pfound = NULL;
806 int exact = 0;
807 int ambig = 0;
808 int indfound = 0;
809 int option_index;
810
811 /* This is an option that requires an argument. */
812 if (*d->__nextchar != '\0')
813 {
814 d->optarg = d->__nextchar;
815 /* If we end this ARGV-element by taking the rest as an arg,
816 we must advance to the next element now. */
817 d->optind++;
818 }
819 else if (d->optind == argc)
820 {
821 if (print_errors)
822 {
823 /* 1003.2 specifies the format of this message. */
824#if defined _LIBC && defined USE_IN_LIBIO
825 char *buf;
826
827 if (__asprintf (&buf,
828 _("%s: option requires an argument -- %c\n"),
829 argv[0], c) >= 0)
830 {
831 _IO_flockfile (stderr);
832
833 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
834 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
835
836 __fxprintf (NULL, "%s", buf);
837
838 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
839 _IO_funlockfile (stderr);
840
841 free (buf);
842 }
843#else
844 fprintf (stderr, _("%s: option requires an argument -- %c\n"),
845 argv[0], c);
846#endif
847 }
848 d->optopt = c;
849 if (optstring[0] == ':')
850 c = ':';
851 else
852 c = '?';
853 return c;
854 }
855 else
856 /* We already incremented `d->optind' once;
857 increment it again when taking next ARGV-elt as argument. */
858 d->optarg = argv[d->optind++];
859
860 /* optarg is now the argument, see if it's in the
861 table of longopts. */
862
863 for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
864 nameend++)
865 /* Do nothing. */ ;
866
867 /* Test all long options for either exact match
868 or abbreviated matches. */
869 for (p = longopts, option_index = 0; p->name; p++, option_index++)
870 if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
871 {
872 if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
873 {
874 /* Exact match found. */
875 pfound = p;
876 indfound = option_index;
877 exact = 1;
878 break;
879 }
880 else if (pfound == NULL)
881 {
882 /* First nonexact match found. */
883 pfound = p;
884 indfound = option_index;
885 }
886 else
887 /* Second or later nonexact match found. */
888 ambig = 1;
889 }
890 if (ambig && !exact)
891 {
892 if (print_errors)
893 {
894#if defined _LIBC && defined USE_IN_LIBIO
895 char *buf;
896
897 if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
898 argv[0], argv[d->optind]) >= 0)
899 {
900 _IO_flockfile (stderr);
901
902 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
903 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
904
905 __fxprintf (NULL, "%s", buf);
906
907 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
908 _IO_funlockfile (stderr);
909
910 free (buf);
911 }
912#else
913 fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
914 argv[0], argv[d->optind]);
915#endif
916 }
917 d->__nextchar += strlen (d->__nextchar);
918 d->optind++;
919 return '?';
920 }
921 if (pfound != NULL)
922 {
923 option_index = indfound;
924 if (*nameend)
925 {
926 /* Don't test has_arg with >, because some C compilers don't
927 allow it to be used on enums. */
928 if (pfound->has_arg)
929 d->optarg = nameend + 1;
930 else
931 {
932 if (print_errors)
933 {
934#if defined _LIBC && defined USE_IN_LIBIO
935 char *buf;
936
937 if (__asprintf (&buf, _("\
938%s: option `-W %s' doesn't allow an argument\n"),
939 argv[0], pfound->name) >= 0)
940 {
941 _IO_flockfile (stderr);
942
943 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
944 ((_IO_FILE *) stderr)->_flags2
945 |= _IO_FLAGS2_NOTCANCEL;
946
947 __fxprintf (NULL, "%s", buf);
948
949 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
950 _IO_funlockfile (stderr);
951
952 free (buf);
953 }
954#else
955 fprintf (stderr, _("\
956%s: option `-W %s' doesn't allow an argument\n"),
957 argv[0], pfound->name);
958#endif
959 }
960
961 d->__nextchar += strlen (d->__nextchar);
962 return '?';
963 }
964 }
965 else if (pfound->has_arg == 1)
966 {
967 if (d->optind < argc)
968 d->optarg = argv[d->optind++];
969 else
970 {
971 if (print_errors)
972 {
973#if defined _LIBC && defined USE_IN_LIBIO
974 char *buf;
975
976 if (__asprintf (&buf, _("\
977%s: option `%s' requires an argument\n"),
978 argv[0], argv[d->optind - 1]) >= 0)
979 {
980 _IO_flockfile (stderr);
981
982 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
983 ((_IO_FILE *) stderr)->_flags2
984 |= _IO_FLAGS2_NOTCANCEL;
985
986 __fxprintf (NULL, "%s", buf);
987
988 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
989 _IO_funlockfile (stderr);
990
991 free (buf);
992 }
993#else
994 fprintf (stderr,
995 _("%s: option `%s' requires an argument\n"),
996 argv[0], argv[d->optind - 1]);
997#endif
998 }
999 d->__nextchar += strlen (d->__nextchar);
1000 return optstring[0] == ':' ? ':' : '?';
1001 }
1002 }
1003 d->__nextchar += strlen (d->__nextchar);
1004 if (longind != NULL)
1005 *longind = option_index;
1006 if (pfound->flag)
1007 {
1008 *(pfound->flag) = pfound->val;
1009 return 0;
1010 }
1011 return pfound->val;
1012 }
1013 d->__nextchar = NULL;
1014 return 'W'; /* Let the application handle it. */
1015 }
1016 if (temp[1] == ':')
1017 {
1018 if (temp[2] == ':')
1019 {
1020 /* This is an option that accepts an argument optionally. */
1021 if (*d->__nextchar != '\0')
1022 {
1023 d->optarg = d->__nextchar;
1024 d->optind++;
1025 }
1026 else
1027 d->optarg = NULL;
1028 d->__nextchar = NULL;
1029 }
1030 else
1031 {
1032 /* This is an option that requires an argument. */
1033 if (*d->__nextchar != '\0')
1034 {
1035 d->optarg = d->__nextchar;
1036 /* If we end this ARGV-element by taking the rest as an arg,
1037 we must advance to the next element now. */
1038 d->optind++;
1039 }
1040 else if (d->optind == argc)
1041 {
1042 if (print_errors)
1043 {
1044 /* 1003.2 specifies the format of this message. */
1045#if defined _LIBC && defined USE_IN_LIBIO
1046 char *buf;
1047
1048 if (__asprintf (&buf, _("\
1049%s: option requires an argument -- %c\n"),
1050 argv[0], c) >= 0)
1051 {
1052 _IO_flockfile (stderr);
1053
1054 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
1055 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
1056
1057 __fxprintf (NULL, "%s", buf);
1058
1059 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
1060 _IO_funlockfile (stderr);
1061
1062 free (buf);
1063 }
1064#else
1065 fprintf (stderr,
1066 _("%s: option requires an argument -- %c\n"),
1067 argv[0], c);
1068#endif
1069 }
1070 d->optopt = c;
1071 if (optstring[0] == ':')
1072 c = ':';
1073 else
1074 c = '?';
1075 }
1076 else
1077 /* We already incremented `optind' once;
1078 increment it again when taking next ARGV-elt as argument. */
1079 d->optarg = argv[d->optind++];
1080 d->__nextchar = NULL;
1081 }
1082 }
1083 return c;
1084 }
1085}
1086
1087int
1088_getopt_internal (int argc, char **argv, const char *optstring,
1089 const struct option *longopts, int *longind,
1090 int long_only, int posixly_correct)
1091{
1092 int result;
1093
1094 getopt_data.optind = optind;
1095 getopt_data.opterr = opterr;
1096
1097 result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
1098 long_only, posixly_correct, &getopt_data);
1099
1100 optind = getopt_data.optind;
1101 optarg = getopt_data.optarg;
1102 optopt = getopt_data.optopt;
1103
1104 return result;
1105}
1106
1107/* glibc gets a LSB-compliant getopt.
1108 Standalone applications get a POSIX-compliant getopt. */
1109#if _LIBC
1110enum { POSIXLY_CORRECT = 0 };
1111#else
1112enum { POSIXLY_CORRECT = 1 };
1113#endif
1114
1115int
1116getopt (int argc, char *const *argv, const char *optstring)
1117{
1118 return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
1119 POSIXLY_CORRECT);
1120}
1121
1122
1123#ifdef TEST
1124
1125/* Compile with -DTEST to make an executable for use in testing
1126 the above definition of `getopt'. */
1127
1128int
1129main (int argc, char **argv)
1130{
1131 int c;
1132 int digit_optind = 0;
1133
1134 while (1)
1135 {
1136 int this_option_optind = optind ? optind : 1;
1137
1138 c = getopt (argc, argv, "abc:d:0123456789");
1139 if (c == -1)
1140 break;
1141
1142 switch (c)
1143 {
1144 case '0':
1145 case '1':
1146 case '2':
1147 case '3':
1148 case '4':
1149 case '5':
1150 case '6':
1151 case '7':
1152 case '8':
1153 case '9':
1154 if (digit_optind != 0 && digit_optind != this_option_optind)
1155 printf ("digits occur in two different argv-elements.\n");
1156 digit_optind = this_option_optind;
1157 printf ("option %c\n", c);
1158 break;
1159
1160 case 'a':
1161 printf ("option a\n");
1162 break;
1163
1164 case 'b':
1165 printf ("option b\n");
1166 break;
1167
1168 case 'c':
1169 printf ("option c with value `%s'\n", optarg);
1170 break;
1171
1172 case '?':
1173 break;
1174
1175 default:
1176 printf ("?? getopt returned character code 0%o ??\n", c);
1177 }
1178 }
1179
1180 if (optind < argc)
1181 {
1182 printf ("non-option ARGV-elements: ");
1183 while (optind < argc)
1184 printf ("%s ", argv[optind++]);
1185 printf ("\n");
1186 }
1187
1188 exit (0);
1189}
1190
1191#endif /* TEST */
diff --git a/gl/getopt1.c b/gl/getopt1.c
new file mode 100644
index 00000000..cc0746ea
--- /dev/null
+++ b/gl/getopt1.c
@@ -0,0 +1,171 @@
1/* getopt_long and getopt_long_only entry points for GNU getopt.
2 Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifdef _LIBC
21# include <getopt.h>
22#else
23# include <config.h>
24# include "getopt.h"
25#endif
26#include "getopt_int.h"
27
28#include <stdio.h>
29
30/* This needs to come after some library #include
31 to get __GNU_LIBRARY__ defined. */
32#ifdef __GNU_LIBRARY__
33#include <stdlib.h>
34#endif
35
36#ifndef NULL
37#define NULL 0
38#endif
39
40int
41getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
42 const struct option *long_options, int *opt_index)
43{
44 return _getopt_internal (argc, (char **) argv, options, long_options,
45 opt_index, 0, 0);
46}
47
48int
49_getopt_long_r (int argc, char **argv, const char *options,
50 const struct option *long_options, int *opt_index,
51 struct _getopt_data *d)
52{
53 return _getopt_internal_r (argc, argv, options, long_options, opt_index,
54 0, 0, d);
55}
56
57/* Like getopt_long, but '-' as well as '--' can indicate a long option.
58 If an option that starts with '-' (not '--') doesn't match a long option,
59 but does match a short option, it is parsed as a short option
60 instead. */
61
62int
63getopt_long_only (int argc, char *__getopt_argv_const *argv,
64 const char *options,
65 const struct option *long_options, int *opt_index)
66{
67 return _getopt_internal (argc, (char **) argv, options, long_options,
68 opt_index, 1, 0);
69}
70
71int
72_getopt_long_only_r (int argc, char **argv, const char *options,
73 const struct option *long_options, int *opt_index,
74 struct _getopt_data *d)
75{
76 return _getopt_internal_r (argc, argv, options, long_options, opt_index,
77 1, 0, d);
78}
79
80
81#ifdef TEST
82
83#include <stdio.h>
84
85int
86main (int argc, char **argv)
87{
88 int c;
89 int digit_optind = 0;
90
91 while (1)
92 {
93 int this_option_optind = optind ? optind : 1;
94 int option_index = 0;
95 static struct option long_options[] =
96 {
97 {"add", 1, 0, 0},
98 {"append", 0, 0, 0},
99 {"delete", 1, 0, 0},
100 {"verbose", 0, 0, 0},
101 {"create", 0, 0, 0},
102 {"file", 1, 0, 0},
103 {0, 0, 0, 0}
104 };
105
106 c = getopt_long (argc, argv, "abc:d:0123456789",
107 long_options, &option_index);
108 if (c == -1)
109 break;
110
111 switch (c)
112 {
113 case 0:
114 printf ("option %s", long_options[option_index].name);
115 if (optarg)
116 printf (" with arg %s", optarg);
117 printf ("\n");
118 break;
119
120 case '0':
121 case '1':
122 case '2':
123 case '3':
124 case '4':
125 case '5':
126 case '6':
127 case '7':
128 case '8':
129 case '9':
130 if (digit_optind != 0 && digit_optind != this_option_optind)
131 printf ("digits occur in two different argv-elements.\n");
132 digit_optind = this_option_optind;
133 printf ("option %c\n", c);
134 break;
135
136 case 'a':
137 printf ("option a\n");
138 break;
139
140 case 'b':
141 printf ("option b\n");
142 break;
143
144 case 'c':
145 printf ("option c with value `%s'\n", optarg);
146 break;
147
148 case 'd':
149 printf ("option d with value `%s'\n", optarg);
150 break;
151
152 case '?':
153 break;
154
155 default:
156 printf ("?? getopt returned character code 0%o ??\n", c);
157 }
158 }
159
160 if (optind < argc)
161 {
162 printf ("non-option ARGV-elements: ");
163 while (optind < argc)
164 printf ("%s ", argv[optind++]);
165 printf ("\n");
166 }
167
168 exit (0);
169}
170
171#endif /* TEST */
diff --git a/gl/getopt_.h b/gl/getopt_.h
new file mode 100644
index 00000000..27fce3dc
--- /dev/null
+++ b/gl/getopt_.h
@@ -0,0 +1,226 @@
1/* Declarations for getopt.
2 Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef _GETOPT_H
21
22#ifndef __need_getopt
23# define _GETOPT_H 1
24#endif
25
26/* Standalone applications should #define __GETOPT_PREFIX to an
27 identifier that prefixes the external functions and variables
28 defined in this header. When this happens, include the
29 headers that might declare getopt so that they will not cause
30 confusion if included after this file. Then systematically rename
31 identifiers so that they do not collide with the system functions
32 and variables. Renaming avoids problems with some compilers and
33 linkers. */
34#if defined __GETOPT_PREFIX && !defined __need_getopt
35# include <stdlib.h>
36# include <stdio.h>
37# include <unistd.h>
38# undef __need_getopt
39# undef getopt
40# undef getopt_long
41# undef getopt_long_only
42# undef optarg
43# undef opterr
44# undef optind
45# undef optopt
46# define __GETOPT_CONCAT(x, y) x ## y
47# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
48# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
49# define getopt __GETOPT_ID (getopt)
50# define getopt_long __GETOPT_ID (getopt_long)
51# define getopt_long_only __GETOPT_ID (getopt_long_only)
52# define optarg __GETOPT_ID (optarg)
53# define opterr __GETOPT_ID (opterr)
54# define optind __GETOPT_ID (optind)
55# define optopt __GETOPT_ID (optopt)
56#endif
57
58/* Standalone applications get correct prototypes for getopt_long and
59 getopt_long_only; they declare "char **argv". libc uses prototypes
60 with "char *const *argv" that are incorrect because getopt_long and
61 getopt_long_only can permute argv; this is required for backward
62 compatibility (e.g., for LSB 2.0.1).
63
64 This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
65 but it caused redefinition warnings if both unistd.h and getopt.h were
66 included, since unistd.h includes getopt.h having previously defined
67 __need_getopt.
68
69 The only place where __getopt_argv_const is used is in definitions
70 of getopt_long and getopt_long_only below, but these are visible
71 only if __need_getopt is not defined, so it is quite safe to rewrite
72 the conditional as follows:
73*/
74#if !defined __need_getopt
75# if defined __GETOPT_PREFIX
76# define __getopt_argv_const /* empty */
77# else
78# define __getopt_argv_const const
79# endif
80#endif
81
82/* If __GNU_LIBRARY__ is not already defined, either we are being used
83 standalone, or this is the first header included in the source file.
84 If we are being used with glibc, we need to include <features.h>, but
85 that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
86 not defined, include <ctype.h>, which will pull in <features.h> for us
87 if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
88 doesn't flood the namespace with stuff the way some other headers do.) */
89#if !defined __GNU_LIBRARY__
90# include <ctype.h>
91#endif
92
93#ifndef __THROW
94# ifndef __GNUC_PREREQ
95# define __GNUC_PREREQ(maj, min) (0)
96# endif
97# if defined __cplusplus && __GNUC_PREREQ (2,8)
98# define __THROW throw ()
99# else
100# define __THROW
101# endif
102#endif
103
104#ifdef __cplusplus
105extern "C" {
106#endif
107
108/* For communication from `getopt' to the caller.
109 When `getopt' finds an option that takes an argument,
110 the argument value is returned here.
111 Also, when `ordering' is RETURN_IN_ORDER,
112 each non-option ARGV-element is returned here. */
113
114extern char *optarg;
115
116/* Index in ARGV of the next element to be scanned.
117 This is used for communication to and from the caller
118 and for communication between successive calls to `getopt'.
119
120 On entry to `getopt', zero means this is the first call; initialize.
121
122 When `getopt' returns -1, this is the index of the first of the
123 non-option elements that the caller should itself scan.
124
125 Otherwise, `optind' communicates from one call to the next
126 how much of ARGV has been scanned so far. */
127
128extern int optind;
129
130/* Callers store zero here to inhibit the error message `getopt' prints
131 for unrecognized options. */
132
133extern int opterr;
134
135/* Set to an option character which was unrecognized. */
136
137extern int optopt;
138
139#ifndef __need_getopt
140/* Describe the long-named options requested by the application.
141 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
142 of `struct option' terminated by an element containing a name which is
143 zero.
144
145 The field `has_arg' is:
146 no_argument (or 0) if the option does not take an argument,
147 required_argument (or 1) if the option requires an argument,
148 optional_argument (or 2) if the option takes an optional argument.
149
150 If the field `flag' is not NULL, it points to a variable that is set
151 to the value given in the field `val' when the option is found, but
152 left unchanged if the option is not found.
153
154 To have a long-named option do something other than set an `int' to
155 a compiled-in constant, such as set a value from `optarg', set the
156 option's `flag' field to zero and its `val' field to a nonzero
157 value (the equivalent single-letter option character, if there is
158 one). For long options that have a zero `flag' field, `getopt'
159 returns the contents of the `val' field. */
160
161struct option
162{
163 const char *name;
164 /* has_arg can't be an enum because some compilers complain about
165 type mismatches in all the code that assumes it is an int. */
166 int has_arg;
167 int *flag;
168 int val;
169};
170
171/* Names for the values of the `has_arg' field of `struct option'. */
172
173# define no_argument 0
174# define required_argument 1
175# define optional_argument 2
176#endif /* need getopt */
177
178
179/* Get definitions and prototypes for functions to process the
180 arguments in ARGV (ARGC of them, minus the program name) for
181 options given in OPTS.
182
183 Return the option character from OPTS just read. Return -1 when
184 there are no more options. For unrecognized options, or options
185 missing arguments, `optopt' is set to the option letter, and '?' is
186 returned.
187
188 The OPTS string is a list of characters which are recognized option
189 letters, optionally followed by colons, specifying that that letter
190 takes an argument, to be placed in `optarg'.
191
192 If a letter in OPTS is followed by two colons, its argument is
193 optional. This behavior is specific to the GNU `getopt'.
194
195 The argument `--' causes premature termination of argument
196 scanning, explicitly telling `getopt' that there are no more
197 options.
198
199 If OPTS begins with `-', then non-option arguments are treated as
200 arguments to the option '\1'. This behavior is specific to the GNU
201 `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
202 the environment, then do not permute arguments. */
203
204extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
205 __THROW;
206
207#ifndef __need_getopt
208extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
209 const char *__shortopts,
210 const struct option *__longopts, int *__longind)
211 __THROW;
212extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
213 const char *__shortopts,
214 const struct option *__longopts, int *__longind)
215 __THROW;
216
217#endif
218
219#ifdef __cplusplus
220}
221#endif
222
223/* Make sure we later can get all the definitions and declarations. */
224#undef __need_getopt
225
226#endif /* getopt.h */
diff --git a/gl/getopt_int.h b/gl/getopt_int.h
new file mode 100644
index 00000000..401579fd
--- /dev/null
+++ b/gl/getopt_int.h
@@ -0,0 +1,131 @@
1/* Internal declarations for getopt.
2 Copyright (C) 1989-1994,1996-1999,2001,2003,2004
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef _GETOPT_INT_H
21#define _GETOPT_INT_H 1
22
23extern int _getopt_internal (int ___argc, char **___argv,
24 const char *__shortopts,
25 const struct option *__longopts, int *__longind,
26 int __long_only, int __posixly_correct);
27
28
29/* Reentrant versions which can handle parsing multiple argument
30 vectors at the same time. */
31
32/* Data type for reentrant functions. */
33struct _getopt_data
34{
35 /* These have exactly the same meaning as the corresponding global
36 variables, except that they are used for the reentrant
37 versions of getopt. */
38 int optind;
39 int opterr;
40 int optopt;
41 char *optarg;
42
43 /* Internal members. */
44
45 /* True if the internal members have been initialized. */
46 int __initialized;
47
48 /* The next char to be scanned in the option-element
49 in which the last option character we returned was found.
50 This allows us to pick up the scan where we left off.
51
52 If this is zero, or a null string, it means resume the scan
53 by advancing to the next ARGV-element. */
54 char *__nextchar;
55
56 /* Describe how to deal with options that follow non-option ARGV-elements.
57
58 If the caller did not specify anything,
59 the default is REQUIRE_ORDER if the environment variable
60 POSIXLY_CORRECT is defined, PERMUTE otherwise.
61
62 REQUIRE_ORDER means don't recognize them as options;
63 stop option processing when the first non-option is seen.
64 This is what Unix does.
65 This mode of operation is selected by either setting the environment
66 variable POSIXLY_CORRECT, or using `+' as the first character
67 of the list of option characters, or by calling getopt.
68
69 PERMUTE is the default. We permute the contents of ARGV as we
70 scan, so that eventually all the non-options are at the end.
71 This allows options to be given in any order, even with programs
72 that were not written to expect this.
73
74 RETURN_IN_ORDER is an option available to programs that were
75 written to expect options and other ARGV-elements in any order
76 and that care about the ordering of the two. We describe each
77 non-option ARGV-element as if it were the argument of an option
78 with character code 1. Using `-' as the first character of the
79 list of option characters selects this mode of operation.
80
81 The special argument `--' forces an end of option-scanning regardless
82 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
83 `--' can cause `getopt' to return -1 with `optind' != ARGC. */
84
85 enum
86 {
87 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
88 } __ordering;
89
90 /* If the POSIXLY_CORRECT environment variable is set
91 or getopt was called. */
92 int __posixly_correct;
93
94
95 /* Handle permutation of arguments. */
96
97 /* Describe the part of ARGV that contains non-options that have
98 been skipped. `first_nonopt' is the index in ARGV of the first
99 of them; `last_nonopt' is the index after the last of them. */
100
101 int __first_nonopt;
102 int __last_nonopt;
103
104#if defined _LIBC && defined USE_NONOPTION_FLAGS
105 int __nonoption_flags_max_len;
106 int __nonoption_flags_len;
107# endif
108};
109
110/* The initializer is necessary to set OPTIND and OPTERR to their
111 default values and to clear the initialization flag. */
112#define _GETOPT_DATA_INITIALIZER { 1, 1 }
113
114extern int _getopt_internal_r (int ___argc, char **___argv,
115 const char *__shortopts,
116 const struct option *__longopts, int *__longind,
117 int __long_only, int __posixly_correct,
118 struct _getopt_data *__data);
119
120extern int _getopt_long_r (int ___argc, char **___argv,
121 const char *__shortopts,
122 const struct option *__longopts, int *__longind,
123 struct _getopt_data *__data);
124
125extern int _getopt_long_only_r (int ___argc, char **___argv,
126 const char *__shortopts,
127 const struct option *__longopts,
128 int *__longind,
129 struct _getopt_data *__data);
130
131#endif /* getopt_int.h */
diff --git a/gl/gettext.h b/gl/gettext.h
new file mode 100644
index 00000000..9d76ec9a
--- /dev/null
+++ b/gl/gettext.h
@@ -0,0 +1,270 @@
1/* Convenience header for conditional use of GNU <libintl.h>.
2 Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _LIBGETTEXT_H
19#define _LIBGETTEXT_H 1
20
21/* NLS can be disabled through the configure --disable-nls option. */
22#if ENABLE_NLS
23
24/* Get declarations of GNU message catalog functions. */
25# include <libintl.h>
26
27/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
28 the gettext() and ngettext() macros. This is an alternative to calling
29 textdomain(), and is useful for libraries. */
30# ifdef DEFAULT_TEXT_DOMAIN
31# undef gettext
32# define gettext(Msgid) \
33 dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
34# undef ngettext
35# define ngettext(Msgid1, Msgid2, N) \
36 dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
37# endif
38
39#else
40
41/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
42 chokes if dcgettext is defined as a macro. So include it now, to make
43 later inclusions of <locale.h> a NOP. We don't include <libintl.h>
44 as well because people using "gettext.h" will not include <libintl.h>,
45 and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
46 is OK. */
47#if defined(__sun)
48# include <locale.h>
49#endif
50
51/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
52 <libintl.h>, which chokes if dcgettext is defined as a macro. So include
53 it now, to make later inclusions of <libintl.h> a NOP. */
54#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
55# include <cstdlib>
56# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
57# include <libintl.h>
58# endif
59#endif
60
61/* Disabled NLS.
62 The casts to 'const char *' serve the purpose of producing warnings
63 for invalid uses of the value returned from these functions.
64 On pre-ANSI systems without 'const', the config.h file is supposed to
65 contain "#define const". */
66# define gettext(Msgid) ((const char *) (Msgid))
67# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
68# define dcgettext(Domainname, Msgid, Category) \
69 ((void) (Category), dgettext (Domainname, Msgid))
70# define ngettext(Msgid1, Msgid2, N) \
71 ((N) == 1 \
72 ? ((void) (Msgid2), (const char *) (Msgid1)) \
73 : ((void) (Msgid1), (const char *) (Msgid2)))
74# define dngettext(Domainname, Msgid1, Msgid2, N) \
75 ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
76# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
77 ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
78# define textdomain(Domainname) ((const char *) (Domainname))
79# define bindtextdomain(Domainname, Dirname) \
80 ((void) (Domainname), (const char *) (Dirname))
81# define bind_textdomain_codeset(Domainname, Codeset) \
82 ((void) (Domainname), (const char *) (Codeset))
83
84#endif
85
86/* A pseudo function call that serves as a marker for the automated
87 extraction of messages, but does not call gettext(). The run-time
88 translation is done at a different place in the code.
89 The argument, String, should be a literal string. Concatenated strings
90 and other string expressions won't work.
91 The macro's expansion is not parenthesized, so that it is suitable as
92 initializer for static 'char[]' or 'const char[]' variables. */
93#define gettext_noop(String) String
94
95/* The separator between msgctxt and msgid in a .mo file. */
96#define GETTEXT_CONTEXT_GLUE "\004"
97
98/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
99 MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
100 short and rarely need to change.
101 The letter 'p' stands for 'particular' or 'special'. */
102#ifdef DEFAULT_TEXT_DOMAIN
103# define pgettext(Msgctxt, Msgid) \
104 pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
105#else
106# define pgettext(Msgctxt, Msgid) \
107 pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
108#endif
109#define dpgettext(Domainname, Msgctxt, Msgid) \
110 pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
111#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
112 pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
113#ifdef DEFAULT_TEXT_DOMAIN
114# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
115 npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
116#else
117# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
118 npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
119#endif
120#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
121 npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
122#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
123 npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
124
125#ifdef __GNUC__
126__inline
127#else
128#ifdef __cplusplus
129inline
130#endif
131#endif
132static const char *
133pgettext_aux (const char *domain,
134 const char *msg_ctxt_id, const char *msgid,
135 int category)
136{
137 const char *translation = dcgettext (domain, msg_ctxt_id, category);
138 if (translation == msg_ctxt_id)
139 return msgid;
140 else
141 return translation;
142}
143
144#ifdef __GNUC__
145__inline
146#else
147#ifdef __cplusplus
148inline
149#endif
150#endif
151static const char *
152npgettext_aux (const char *domain,
153 const char *msg_ctxt_id, const char *msgid,
154 const char *msgid_plural, unsigned long int n,
155 int category)
156{
157 const char *translation =
158 dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
159 if (translation == msg_ctxt_id || translation == msgid_plural)
160 return (n == 1 ? msgid : msgid_plural);
161 else
162 return translation;
163}
164
165/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
166 can be arbitrary expressions. But for string literals these macros are
167 less efficient than those above. */
168
169#include <string.h>
170
171#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
172 (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
173 /* || __STDC_VERSION__ >= 199901L */ )
174
175#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
176#include <stdlib.h>
177#endif
178
179#define pgettext_expr(Msgctxt, Msgid) \
180 dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
181#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
182 dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
183
184#ifdef __GNUC__
185__inline
186#else
187#ifdef __cplusplus
188inline
189#endif
190#endif
191static const char *
192dcpgettext_expr (const char *domain,
193 const char *msgctxt, const char *msgid,
194 int category)
195{
196 size_t msgctxt_len = strlen (msgctxt) + 1;
197 size_t msgid_len = strlen (msgid) + 1;
198 const char *translation;
199#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
200 char msg_ctxt_id[msgctxt_len + msgid_len];
201#else
202 char buf[1024];
203 char *msg_ctxt_id =
204 (msgctxt_len + msgid_len <= sizeof (buf)
205 ? buf
206 : (char *) malloc (msgctxt_len + msgid_len));
207 if (msg_ctxt_id != NULL)
208#endif
209 {
210 memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
211 msg_ctxt_id[msgctxt_len - 1] = '\004';
212 memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
213 translation = dcgettext (domain, msg_ctxt_id, category);
214#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
215 if (msg_ctxt_id != buf)
216 free (msg_ctxt_id);
217#endif
218 if (translation != msg_ctxt_id)
219 return translation;
220 }
221 return msgid;
222}
223
224#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
225 dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
226#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
227 dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
228
229#ifdef __GNUC__
230__inline
231#else
232#ifdef __cplusplus
233inline
234#endif
235#endif
236static const char *
237dcnpgettext_expr (const char *domain,
238 const char *msgctxt, const char *msgid,
239 const char *msgid_plural, unsigned long int n,
240 int category)
241{
242 size_t msgctxt_len = strlen (msgctxt) + 1;
243 size_t msgid_len = strlen (msgid) + 1;
244 const char *translation;
245#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
246 char msg_ctxt_id[msgctxt_len + msgid_len];
247#else
248 char buf[1024];
249 char *msg_ctxt_id =
250 (msgctxt_len + msgid_len <= sizeof (buf)
251 ? buf
252 : (char *) malloc (msgctxt_len + msgid_len));
253 if (msg_ctxt_id != NULL)
254#endif
255 {
256 memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
257 msg_ctxt_id[msgctxt_len - 1] = '\004';
258 memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
259 translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
260#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
261 if (msg_ctxt_id != buf)
262 free (msg_ctxt_id);
263#endif
264 if (!(translation == msg_ctxt_id || translation == msgid_plural))
265 return translation;
266 }
267 return (n == 1 ? msgid : msgid_plural);
268}
269
270#endif /* _LIBGETTEXT_H */
diff --git a/gl/inet_ntop.c b/gl/inet_ntop.c
new file mode 100644
index 00000000..537b59fa
--- /dev/null
+++ b/gl/inet_ntop.c
@@ -0,0 +1,238 @@
1/* inet_ntop.c -- convert IPv4 and IPv6 addresses from binary to text form
2
3 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/*
20 * Copyright (c) 1996-1999 by Internet Software Consortium.
21 *
22 * Permission to use, copy, modify, and distribute this software for any
23 * purpose with or without fee is hereby granted, provided that the above
24 * copyright notice and this permission notice appear in all copies.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
27 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
29 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
30 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
31 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
32 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
33 * SOFTWARE.
34 */
35
36#include <config.h>
37
38/* Specification. */
39#include "inet_ntop.h"
40
41#include <stdio.h>
42#include <string.h>
43#include <errno.h>
44
45#ifndef EAFNOSUPPORT
46# define EAFNOSUPPORT EINVAL
47#endif
48
49#define NS_IN6ADDRSZ 16
50#define NS_INT16SZ 2
51
52/*
53 * WARNING: Don't even consider trying to compile this on a system where
54 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
55 */
56typedef int verify_int_size[2 * sizeof (int) - 7];
57
58static const char *inet_ntop4 (const unsigned char *src, char *dst, socklen_t size);
59#if HAVE_IPV6
60static const char *inet_ntop6 (const unsigned char *src, char *dst, socklen_t size);
61#endif
62
63
64/* char *
65 * inet_ntop(af, src, dst, size)
66 * convert a network format address to presentation format.
67 * return:
68 * pointer to presentation format address (`dst'), or NULL (see errno).
69 * author:
70 * Paul Vixie, 1996.
71 */
72const char *
73inet_ntop (int af, const void *restrict src,
74 char *restrict dst, socklen_t cnt)
75{
76 switch (af)
77 {
78#if HAVE_IPV4
79 case AF_INET:
80 return (inet_ntop4 (src, dst, cnt));
81#endif
82
83#if HAVE_IPV6
84 case AF_INET6:
85 return (inet_ntop6 (src, dst, cnt));
86#endif
87
88 default:
89 errno = EAFNOSUPPORT;
90 return (NULL);
91 }
92 /* NOTREACHED */
93}
94
95/* const char *
96 * inet_ntop4(src, dst, size)
97 * format an IPv4 address
98 * return:
99 * `dst' (as a const)
100 * notes:
101 * (1) uses no statics
102 * (2) takes a u_char* not an in_addr as input
103 * author:
104 * Paul Vixie, 1996.
105 */
106static const char *
107inet_ntop4 (const unsigned char *src, char *dst, socklen_t size)
108{
109 char tmp[sizeof "255.255.255.255"];
110 int len;
111
112 len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
113 if (len < 0)
114 return NULL;
115
116 if (len > size)
117 {
118 errno = ENOSPC;
119 return NULL;
120 }
121
122 return strcpy (dst, tmp);
123}
124
125#if HAVE_IPV6
126
127/* const char *
128 * inet_ntop6(src, dst, size)
129 * convert IPv6 binary address into presentation (printable) format
130 * author:
131 * Paul Vixie, 1996.
132 */
133static const char *
134inet_ntop6 (const unsigned char *src, char *dst, socklen_t size)
135{
136 /*
137 * Note that int32_t and int16_t need only be "at least" large enough
138 * to contain a value of the specified size. On some systems, like
139 * Crays, there is no such thing as an integer variable with 16 bits.
140 * Keep this in mind if you think this function should have been coded
141 * to use pointer overlays. All the world's not a VAX.
142 */
143 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
144 struct
145 {
146 int base, len;
147 } best, cur;
148 unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
149 int i;
150
151 /*
152 * Preprocess:
153 * Copy the input (bytewise) array into a wordwise array.
154 * Find the longest run of 0x00's in src[] for :: shorthanding.
155 */
156 memset (words, '\0', sizeof words);
157 for (i = 0; i < NS_IN6ADDRSZ; i += 2)
158 words[i / 2] = (src[i] << 8) | src[i + 1];
159 best.base = -1;
160 cur.base = -1;
161 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
162 {
163 if (words[i] == 0)
164 {
165 if (cur.base == -1)
166 cur.base = i, cur.len = 1;
167 else
168 cur.len++;
169 }
170 else
171 {
172 if (cur.base != -1)
173 {
174 if (best.base == -1 || cur.len > best.len)
175 best = cur;
176 cur.base = -1;
177 }
178 }
179 }
180 if (cur.base != -1)
181 {
182 if (best.base == -1 || cur.len > best.len)
183 best = cur;
184 }
185 if (best.base != -1 && best.len < 2)
186 best.base = -1;
187
188 /*
189 * Format the result.
190 */
191 tp = tmp;
192 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
193 {
194 /* Are we inside the best run of 0x00's? */
195 if (best.base != -1 && i >= best.base && i < (best.base + best.len))
196 {
197 if (i == best.base)
198 *tp++ = ':';
199 continue;
200 }
201 /* Are we following an initial run of 0x00s or any real hex? */
202 if (i != 0)
203 *tp++ = ':';
204 /* Is this address an encapsulated IPv4? */
205 if (i == 6 && best.base == 0 &&
206 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
207 {
208 if (!inet_ntop4 (src + 12, tp, sizeof tmp - (tp - tmp)))
209 return (NULL);
210 tp += strlen (tp);
211 break;
212 }
213 {
214 int len = sprintf (tp, "%x", words[i]);
215 if (len < 0)
216 return NULL;
217 tp += len;
218 }
219 }
220 /* Was it a trailing run of 0x00's? */
221 if (best.base != -1 && (best.base + best.len) ==
222 (NS_IN6ADDRSZ / NS_INT16SZ))
223 *tp++ = ':';
224 *tp++ = '\0';
225
226 /*
227 * Check for overflow, copy, and we're done.
228 */
229 if ((socklen_t) (tp - tmp) > size)
230 {
231 errno = ENOSPC;
232 return NULL;
233 }
234
235 return strcpy (dst, tmp);
236}
237
238#endif
diff --git a/gl/inet_ntop.h b/gl/inet_ntop.h
new file mode 100644
index 00000000..bd1e085a
--- /dev/null
+++ b/gl/inet_ntop.h
@@ -0,0 +1,42 @@
1/* Convert internet address from internal to printable, presentable format.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22
23/* Converts an internet address from internal format to a printable,
24 presentable format.
25 AF is an internet address family, such as AF_INET or AF_INET6.
26 SRC points to a 'struct in_addr' (for AF_INET) or 'struct in6_addr'
27 (for AF_INET6).
28 DST points to a buffer having room for CNT bytes.
29 The printable representation of the address (in numeric form, not
30 surrounded by [...], no reverse DNS is done) is placed in DST, and
31 DST is returned. If an error occurs, the return value is NULL and
32 errno is set. If CNT bytes are not sufficient to hold the result,
33 the return value is NULL and errno is set to ENOSPC. A good value
34 for CNT is 46.
35
36 For more details, see the POSIX:2001 specification
37 <http://www.opengroup.org/susv3xsh/inet_ntop.html>. */
38
39#if !HAVE_DECL_INET_NTOP
40extern const char *inet_ntop (int af, const void *restrict src,
41 char *restrict dst, socklen_t cnt);
42#endif
diff --git a/gl/intprops.h b/gl/intprops.h
new file mode 100644
index 00000000..34f971cb
--- /dev/null
+++ b/gl/intprops.h
@@ -0,0 +1,78 @@
1/* intprops.h -- properties of integer types
2
3 Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <limits.h>
22
23/* The extra casts in the following macros work around compiler bugs,
24 e.g., in Cray C 5.0.3.0. */
25
26/* True if the arithmetic type T is an integer type. bool counts as
27 an integer. */
28#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
29
30/* True if negative values of the signed integer type T use two's
31 complement, ones' complement, or signed magnitude representation,
32 respectively. Much GNU code assumes two's complement, but some
33 people like to be portable to all possible C hosts. */
34#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
35#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
36#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
37
38/* True if the arithmetic type T is signed. */
39#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
40
41/* The maximum and minimum values for the integer type T. These
42 macros have undefined behavior if T is signed and has padding bits.
43 If this is a problem for you, please let us know how to fix it for
44 your host. */
45#define TYPE_MINIMUM(t) \
46 ((t) (! TYPE_SIGNED (t) \
47 ? (t) 0 \
48 : TYPE_SIGNED_MAGNITUDE (t) \
49 ? ~ (t) 0 \
50 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
51#define TYPE_MAXIMUM(t) \
52 ((t) (! TYPE_SIGNED (t) \
53 ? (t) -1 \
54 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
55
56/* Return zero if T can be determined to be an unsigned type.
57 Otherwise, return 1.
58 When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
59 tighter bound. Otherwise, it overestimates the true bound by one byte
60 when applied to unsigned types of size 2, 4, 16, ... bytes.
61 The symbol signed_type_or_expr__ is private to this header file. */
62#if __GNUC__ >= 2
63# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
64#else
65# define signed_type_or_expr__(t) 1
66#endif
67
68/* Bound on length of the string representing an integer type or expression T.
69 Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
70 add 1 for integer division truncation; add 1 more for a minus sign
71 if needed. */
72#define INT_STRLEN_BOUND(t) \
73 ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
74 + signed_type_or_expr__ (t) + 1)
75
76/* Bound on buffer size needed to represent an integer type or expression T,
77 including the terminating null. */
78#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
diff --git a/gl/m4/absolute-header.m4 b/gl/m4/absolute-header.m4
new file mode 100644
index 00000000..c649df08
--- /dev/null
+++ b/gl/m4/absolute-header.m4
@@ -0,0 +1,44 @@
1# absolute-header.m4 serial 6
2dnl Copyright (C) 2006 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
7dnl From Derek Price.
8
9# gl_ABSOLUTE_HEADER(HEADER1 HEADER2 ...)
10# ---------------------------------------
11# Find the absolute name of a header file, assuming the header exists.
12# If the header were sys/inttypes.h, this macro would define
13# ABSOLUTE_SYS_INTTYPES_H to the `""' quoted absolute name of sys/inttypes.h
14# in config.h
15# (e.g. `#define ABSOLUTE_SYS_INTTYPES_H "///usr/include/sys/inttypes.h"').
16# The three "///" are to pacify Sun C 5.8, which otherwise would say
17# "warning: #include of /usr/include/... may be non-portable".
18# Use `""', not `<>', so that the /// cannot be confused with a C99 comment.
19AC_DEFUN([gl_ABSOLUTE_HEADER],
20[AC_LANG_PREPROC_REQUIRE()dnl
21AC_FOREACH([gl_HEADER_NAME], [$1],
22 [AS_VAR_PUSHDEF([gl_absolute_header],
23 [gl_cv_absolute_]m4_quote(m4_defn([gl_HEADER_NAME])))dnl
24 AC_CACHE_CHECK([absolute name of <]m4_quote(m4_defn([gl_HEADER_NAME]))[>],
25 m4_quote(m4_defn([gl_absolute_header])),
26 [AS_VAR_PUSHDEF([ac_header_exists],
27 [ac_cv_header_]m4_quote(m4_defn([gl_HEADER_NAME])))dnl
28 AC_CHECK_HEADERS_ONCE(m4_quote(m4_defn([gl_HEADER_NAME])))dnl
29 if test AS_VAR_GET(ac_header_exists) = yes; then
30 AC_LANG_CONFTEST([AC_LANG_SOURCE([[#include <]]m4_dquote(m4_defn([gl_HEADER_NAME]))[[>]])])
31dnl eval is necessary to expand ac_cpp.
32dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell.
33 AS_VAR_SET(gl_absolute_header,
34[`(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
35sed -n '\#/]m4_quote(m4_defn([gl_HEADER_NAME]))[#{s#.*"\(.*/]m4_quote(m4_defn([gl_HEADER_NAME]))[\)".*#\1#;s#^/[^/]#//&#;p;q;}'`])
36 fi
37 AS_VAR_POPDEF([ac_header_exists])dnl
38 ])dnl
39 AC_DEFINE_UNQUOTED(AS_TR_CPP([ABSOLUTE_]m4_quote(m4_defn([gl_HEADER_NAME]))),
40 ["AS_VAR_GET(gl_absolute_header)"],
41 [Define this to an absolute name of <]m4_quote(m4_defn([gl_HEADER_NAME]))[>.])
42 AS_VAR_POPDEF([gl_absolute_header])dnl
43])dnl
44])# gl_ABSOLUTE_HEADER
diff --git a/gl/m4/alloca.m4 b/gl/m4/alloca.m4
new file mode 100644
index 00000000..eb62e0e7
--- /dev/null
+++ b/gl/m4/alloca.m4
@@ -0,0 +1,50 @@
1# alloca.m4 serial 7
2dnl Copyright (C) 2002-2004, 2006 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_FUNC_ALLOCA],
8[
9 dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57.
10 AC_REQUIRE([AC_PROG_CPP])
11 AC_REQUIRE([AC_PROG_EGREP])
12
13 AC_REQUIRE([AC_FUNC_ALLOCA])
14 if test $ac_cv_func_alloca_works = no; then
15 gl_PREREQ_ALLOCA
16 fi
17
18 # Define an additional variable used in the Makefile substitution.
19 if test $ac_cv_working_alloca_h = yes; then
20 AC_CACHE_CHECK([for alloca as a compiler built-in], [gl_cv_rpl_alloca], [
21 AC_EGREP_CPP([Need own alloca], [
22#if defined __GNUC__ || defined _AIX || defined _MSC_VER
23 Need own alloca
24#endif
25 ], [gl_cv_rpl_alloca=yes], [gl_cv_rpl_alloca=no])
26 ])
27 if test $gl_cv_rpl_alloca = yes; then
28 dnl OK, alloca can be implemented through a compiler built-in.
29 AC_DEFINE([HAVE_ALLOCA], 1,
30 [Define to 1 if you have 'alloca' after including <alloca.h>,
31 a header that may be supplied by this distribution.])
32 ALLOCA_H=alloca.h
33 else
34 dnl alloca exists as a library function, i.e. it is slow and probably
35 dnl a memory leak. Don't define HAVE_ALLOCA in this case.
36 ALLOCA_H=
37 fi
38 else
39 ALLOCA_H=alloca.h
40 fi
41 AC_SUBST([ALLOCA_H])
42
43 AC_DEFINE(HAVE_ALLOCA_H, 1,
44 [Define HAVE_ALLOCA_H for backward compatibility with older code
45 that includes <alloca.h> only if HAVE_ALLOCA_H is defined.])
46])
47
48# Prerequisites of lib/alloca.c.
49# STACK_DIRECTION is already handled by AC_FUNC_ALLOCA.
50AC_DEFUN([gl_PREREQ_ALLOCA], [:])
diff --git a/gl/m4/arpa_inet_h.m4 b/gl/m4/arpa_inet_h.m4
new file mode 100644
index 00000000..d01d0984
--- /dev/null
+++ b/gl/m4/arpa_inet_h.m4
@@ -0,0 +1,18 @@
1# arpa_inet_h.m4 serial 1
2dnl Copyright (C) 2006 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
7dnl Written by Simon Josefsson
8
9AC_DEFUN([gl_HEADER_ARPA_INET],
10[
11 AC_CHECK_HEADERS_ONCE([arpa/inet.h])
12 if test $ac_cv_header_arpa_inet_h = yes; then
13 ARPA_INET_H=''
14 else
15 ARPA_INET_H='arpa/inet.h'
16 fi
17 AC_SUBST(ARPA_INET_H)
18])
diff --git a/gl/m4/c-strtod.m4 b/gl/m4/c-strtod.m4
new file mode 100644
index 00000000..7f206c71
--- /dev/null
+++ b/gl/m4/c-strtod.m4
@@ -0,0 +1,53 @@
1# c-strtod.m4 serial 9
2
3# Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4# This file is free software; the Free Software Foundation
5# gives unlimited permission to copy and/or distribute it,
6# with or without modifications, as long as this notice is preserved.
7
8# Written by Paul Eggert.
9
10AC_DEFUN([gl_C99_STRTOLD],
11[
12 AC_CACHE_CHECK([whether strtold conforms to C99],
13 [gl_cv_func_c99_strtold],
14 [AC_LINK_IFELSE(
15 [AC_LANG_PROGRAM(
16 [[/* On HP-UX before 11.23, strtold returns a struct instead of
17 long double. Reject implementations like that, by requiring
18 compatibility with the C99 prototype. */
19 #include <stdlib.h>
20 static long double (*p) (char const *, char **) = strtold;
21 static long double
22 test (char const *nptr, char **endptr)
23 {
24 long double r;
25 r = strtold (nptr, endptr);
26 return r;
27 }]],
28 [[return test ("1.0", NULL) != 1 || p ("1.0", NULL) != 1;]])],
29 [gl_cv_func_c99_strtold=yes],
30 [gl_cv_func_c99_strtold=no])])
31 if test $gl_cv_func_c99_strtold = yes; then
32 AC_DEFINE([HAVE_C99_STRTOLD], 1, [Define to 1 if strtold conforms to C99.])
33 fi
34])
35
36AC_DEFUN([gl_C_STRTOD],
37[
38 AC_LIBOBJ([c-strtod])
39
40 dnl Prerequisites of lib/c-strtod.c.
41 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
42 :
43])
44
45AC_DEFUN([gl_C_STRTOLD],
46[
47 AC_LIBOBJ([c-strtold])
48
49 dnl Prerequisites of lib/c-strtold.c.
50 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
51 AC_REQUIRE([gl_C99_STRTOLD])
52 :
53])
diff --git a/gl/m4/cloexec.m4 b/gl/m4/cloexec.m4
new file mode 100644
index 00000000..4c4e26a1
--- /dev/null
+++ b/gl/m4/cloexec.m4
@@ -0,0 +1,10 @@
1#serial 6
2dnl Copyright (C) 2004, 2005, 2006 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_CLOEXEC],
8[
9 AC_LIBOBJ([cloexec])
10])
diff --git a/gl/m4/codeset.m4 b/gl/m4/codeset.m4
new file mode 100644
index 00000000..223955b4
--- /dev/null
+++ b/gl/m4/codeset.m4
@@ -0,0 +1,21 @@
1# codeset.m4 serial 2 (gettext-0.16)
2dnl Copyright (C) 2000-2002, 2006 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
7dnl From Bruno Haible.
8
9AC_DEFUN([AM_LANGINFO_CODESET],
10[
11 AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
12 [AC_TRY_LINK([#include <langinfo.h>],
13 [char* cs = nl_langinfo(CODESET); return !cs;],
14 am_cv_langinfo_codeset=yes,
15 am_cv_langinfo_codeset=no)
16 ])
17 if test $am_cv_langinfo_codeset = yes; then
18 AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
19 [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
20 fi
21])
diff --git a/gl/m4/dirname.m4 b/gl/m4/dirname.m4
new file mode 100644
index 00000000..e35da965
--- /dev/null
+++ b/gl/m4/dirname.m4
@@ -0,0 +1,18 @@
1#serial 7 -*- autoconf -*-
2dnl Copyright (C) 2002-2006 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_DIRNAME],
8[
9 AC_LIBOBJ([basename])
10 AC_LIBOBJ([dirname])
11 AC_LIBOBJ([stripslash])
12
13 dnl Prerequisites of lib/dirname.h.
14 AC_REQUIRE([gl_AC_DOS])
15 AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
16
17 dnl No prerequisites of lib/basename.c, lib/dirname.c, lib/stripslash.c.
18])
diff --git a/gl/m4/dos.m4 b/gl/m4/dos.m4
new file mode 100644
index 00000000..dd59571c
--- /dev/null
+++ b/gl/m4/dos.m4
@@ -0,0 +1,71 @@
1#serial 10 -*- autoconf -*-
2
3# Define some macros required for proper operation of code in lib/*.c
4# on MSDOS/Windows systems.
5
6# Copyright (C) 2000, 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
7# This file is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# From Jim Meyering.
12
13AC_DEFUN([gl_AC_DOS],
14 [
15 AC_CACHE_CHECK([whether system is Windows or MSDOS], [ac_cv_win_or_dos],
16 [
17 AC_TRY_COMPILE([],
18 [#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __CYGWIN__
19neither MSDOS nor Windows
20#endif],
21 [ac_cv_win_or_dos=yes],
22 [ac_cv_win_or_dos=no])
23 ])
24
25 if test x"$ac_cv_win_or_dos" = xyes; then
26 ac_fs_accepts_drive_letter_prefix=1
27 ac_fs_backslash_is_file_name_separator=1
28 AC_CACHE_CHECK([whether drive letter can start relative path],
29 [ac_cv_drive_letter_can_be_relative],
30 [
31 AC_TRY_COMPILE([],
32 [#if defined __CYGWIN__
33drive letters are always absolute
34#endif],
35 [ac_cv_drive_letter_can_be_relative=yes],
36 [ac_cv_drive_letter_can_be_relative=no])
37 ])
38 if test x"$ac_cv_drive_letter_can_be_relative" = xyes; then
39 ac_fs_drive_letter_can_be_relative=1
40 else
41 ac_fs_drive_letter_can_be_relative=0
42 fi
43 else
44 ac_fs_accepts_drive_letter_prefix=0
45 ac_fs_backslash_is_file_name_separator=0
46 ac_fs_drive_letter_can_be_relative=0
47 fi
48
49 AC_DEFINE_UNQUOTED([FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX],
50 $ac_fs_accepts_drive_letter_prefix,
51 [Define on systems for which file names may have a so-called
52 `drive letter' prefix, define this to compute the length of that
53 prefix, including the colon.])
54
55 AH_VERBATIM(ISSLASH,
56 [#if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR
57# define ISSLASH(C) ((C) == '/' || (C) == '\\')
58#else
59# define ISSLASH(C) ((C) == '/')
60#endif])
61
62 AC_DEFINE_UNQUOTED([FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR],
63 $ac_fs_backslash_is_file_name_separator,
64 [Define if the backslash character may also serve as a file name
65 component separator.])
66
67 AC_DEFINE_UNQUOTED([FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE],
68 $ac_fs_drive_letter_can_be_relative,
69 [Define if a drive letter prefix denotes a relative path if it is
70 not followed by a file name component separator.])
71 ])
diff --git a/gl/m4/double-slash-root.m4 b/gl/m4/double-slash-root.m4
new file mode 100644
index 00000000..69d60d01
--- /dev/null
+++ b/gl/m4/double-slash-root.m4
@@ -0,0 +1,38 @@
1# double-slash-root.m4 serial 2 -*- Autoconf -*-
2dnl Copyright (C) 2006 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_DOUBLE_SLASH_ROOT],
8[
9 AC_REQUIRE([AC_CANONICAL_HOST])
10 AC_CACHE_CHECK([whether // is distinct from /], [gl_cv_double_slash_root],
11 [ if test x"$cross_compiling" = xyes ; then
12 # When cross-compiling, there is no way to tell whether // is special
13 # short of a list of hosts. However, the only known hosts to date
14 # that have a distinct // are Apollo DomainOS (too old to port to),
15 # Cygwin, and z/OS. If anyone knows of another system for which // has
16 # special semantics and is distinct from /, please report it to
17 # <bug-gnulib@gnu.org>.
18 case $host in
19 *-cygwin | i370-ibm-openedition)
20 gl_cv_double_slash_root=yes ;;
21 *)
22 # Be optimistic and assume that / and // are the same when we
23 # don't know.
24 gl_cv_double_slash_root='unknown, assuming no' ;;
25 esac
26 else
27 set x `ls -di / //`
28 if test $[2] = $[4] && wc //dev/null >/dev/null 2>&1; then
29 gl_cv_double_slash_root=no
30 else
31 gl_cv_double_slash_root=yes
32 fi
33 fi])
34 if test "$gl_cv_double_slash_root" = yes; then
35 AC_DEFINE([DOUBLE_SLASH_IS_DISTINCT_ROOT], 1,
36 [Define to 1 if // is a file system root distinct from /.])
37 fi
38])
diff --git a/gl/m4/eoverflow.m4 b/gl/m4/eoverflow.m4
new file mode 100644
index 00000000..3bffd10e
--- /dev/null
+++ b/gl/m4/eoverflow.m4
@@ -0,0 +1,70 @@
1# eoverflow.m4 serial 2
2dnl Copyright (C) 2004, 2006 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
7dnl From Bruno Haible.
8
9# The EOVERFLOW errno value ought to be defined in <errno.h>, according to
10# POSIX. But some systems (like AIX 3) don't define it, and some systems
11# (like OSF/1) define it when _XOPEN_SOURCE_EXTENDED is defined.
12
13# Define EOVERFLOW as a C macro and as a substituted macro in such a way that
14# 1. on all systems, after inclusion of <errno.h>, EOVERFLOW is usable,
15# 2. on systems where EOVERFLOW is defined elsewhere, we use the same numeric
16# value.
17
18AC_DEFUN([gl_EOVERFLOW],
19[
20 AC_REQUIRE([AC_PROG_CC])dnl
21
22 AC_CACHE_CHECK([for EOVERFLOW], ac_cv_decl_EOVERFLOW, [
23 AC_EGREP_CPP(yes,[
24#include <errno.h>
25#ifdef EOVERFLOW
26yes
27#endif
28 ], have_eoverflow=1)
29 if test -n "$have_eoverflow"; then
30 dnl EOVERFLOW exists in <errno.h>. Don't need to define EOVERFLOW ourselves.
31 ac_cv_decl_EOVERFLOW=yes
32 else
33 AC_EGREP_CPP(yes,[
34#define _XOPEN_SOURCE_EXTENDED 1
35#include <errno.h>
36#ifdef EOVERFLOW
37yes
38#endif
39 ], have_eoverflow=1)
40 if test -n "$have_eoverflow"; then
41 dnl EOVERFLOW exists but is hidden.
42 dnl Define it to the same value.
43 AC_COMPUTE_INT([ac_cv_decl_EOVERFLOW], [EOVERFLOW], [
44#define _XOPEN_SOURCE_EXTENDED 1
45#include <errno.h>
46/* The following two lines are a workaround against an autoconf-2.52 bug. */
47#include <stdio.h>
48#include <stdlib.h>
49])
50 else
51 dnl EOVERFLOW isn't defined by the system. Define EOVERFLOW ourselves, but
52 dnl don't define it as EINVAL, because snprintf() callers want to
53 dnl distinguish EINVAL and EOVERFLOW.
54 ac_cv_decl_EOVERFLOW=E2BIG
55 fi
56 fi
57 ])
58 if test "$ac_cv_decl_EOVERFLOW" != yes; then
59 AC_DEFINE_UNQUOTED([EOVERFLOW], [$ac_cv_decl_EOVERFLOW],
60 [Define as good substitute value for EOVERFLOW.])
61 EOVERFLOW="$ac_cv_decl_EOVERFLOW"
62 AC_SUBST(EOVERFLOW)
63 fi
64])
65
66dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
67dnl Remove this when we can assume autoconf >= 2.61.
68m4_ifdef([AC_COMPUTE_INT], [], [
69 AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
70])
diff --git a/gl/m4/error.m4 b/gl/m4/error.m4
new file mode 100644
index 00000000..7c7746e2
--- /dev/null
+++ b/gl/m4/error.m4
@@ -0,0 +1,22 @@
1#serial 11
2
3# Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004 Free Software
4# Foundation, Inc.
5#
6# This file is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10AC_DEFUN([gl_ERROR],
11[
12 AC_FUNC_ERROR_AT_LINE
13 dnl Note: AC_FUNC_ERROR_AT_LINE does AC_LIBSOURCES([error.h, error.c]).
14 gl_PREREQ_ERROR
15])
16
17# Prerequisites of lib/error.c.
18AC_DEFUN([gl_PREREQ_ERROR],
19[
20 AC_REQUIRE([AC_FUNC_STRERROR_R])
21 :
22])
diff --git a/gl/m4/exitfail.m4 b/gl/m4/exitfail.m4
new file mode 100644
index 00000000..b7a691e5
--- /dev/null
+++ b/gl/m4/exitfail.m4
@@ -0,0 +1,13 @@
1# exitfail.m4 serial 6
2dnl Copyright (C) 2002, 2003, 2005, 2006 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_EXITFAIL],
8[
9 AC_LIBOBJ([exitfail])
10
11 dnl No prerequisites of lib/exitfail.c.
12 :
13])
diff --git a/gl/m4/extensions.m4 b/gl/m4/extensions.m4
new file mode 100644
index 00000000..143a9e54
--- /dev/null
+++ b/gl/m4/extensions.m4
@@ -0,0 +1,58 @@
1# serial 4 -*- Autoconf -*-
2# Enable extensions on systems that normally disable them.
3
4# Copyright (C) 2003, 2006 Free Software Foundation, Inc.
5# This file is free software; the Free Software Foundation
6# gives unlimited permission to copy and/or distribute it,
7# with or without modifications, as long as this notice is preserved.
8
9# This definition of AC_USE_SYSTEM_EXTENSIONS is stolen from CVS
10# Autoconf. Perhaps we can remove this once we can assume Autoconf
11# 2.61 or later everywhere, but since CVS Autoconf mutates rapidly
12# enough in this area it's likely we'll need to redefine
13# AC_USE_SYSTEM_EXTENSIONS for quite some time.
14
15# AC_USE_SYSTEM_EXTENSIONS
16# ------------------------
17# Enable extensions on systems that normally disable them,
18# typically due to standards-conformance issues.
19AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS],
20[
21 AC_BEFORE([$0], [AC_COMPILE_IFELSE])
22 AC_BEFORE([$0], [AC_RUN_IFELSE])
23
24 AC_REQUIRE([AC_GNU_SOURCE])
25 AC_REQUIRE([AC_AIX])
26 AC_REQUIRE([AC_MINIX])
27
28 AH_VERBATIM([__EXTENSIONS__],
29[/* Enable extensions on Solaris. */
30#ifndef __EXTENSIONS__
31# undef __EXTENSIONS__
32#endif
33#ifndef _POSIX_PTHREAD_SEMANTICS
34# undef _POSIX_PTHREAD_SEMANTICS
35#endif
36#ifndef _TANDEM_SOURCE
37# undef _TANDEM_SOURCE
38#endif])
39 AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
40 [ac_cv_safe_to_define___extensions__],
41 [AC_COMPILE_IFELSE(
42 [AC_LANG_PROGRAM([
43# define __EXTENSIONS__ 1
44 AC_INCLUDES_DEFAULT])],
45 [ac_cv_safe_to_define___extensions__=yes],
46 [ac_cv_safe_to_define___extensions__=no])])
47 test $ac_cv_safe_to_define___extensions__ = yes &&
48 AC_DEFINE([__EXTENSIONS__])
49 AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
50 AC_DEFINE([_TANDEM_SOURCE])
51])
52
53# gl_USE_SYSTEM_EXTENSIONS
54# ------------------------
55# Enable extensions on systems that normally disable them,
56# typically due to standards-conformance issues.
57AC_DEFUN([gl_USE_SYSTEM_EXTENSIONS],
58 [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])])
diff --git a/gl/m4/fcntl-safer.m4 b/gl/m4/fcntl-safer.m4
new file mode 100644
index 00000000..3475b0a7
--- /dev/null
+++ b/gl/m4/fcntl-safer.m4
@@ -0,0 +1,11 @@
1#serial 5
2dnl Copyright (C) 2005-2007 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_FCNTL_SAFER],
8[
9 AC_LIBOBJ([open-safer])
10 AC_LIBOBJ([creat-safer])
11])
diff --git a/gl/m4/fstypename.m4 b/gl/m4/fstypename.m4
new file mode 100644
index 00000000..aa676f3a
--- /dev/null
+++ b/gl/m4/fstypename.m4
@@ -0,0 +1,22 @@
1#serial 6
2
3dnl From Jim Meyering.
4dnl
5dnl See if struct statfs has the f_fstypename member.
6dnl If so, define HAVE_STRUCT_STATFS_F_FSTYPENAME.
7dnl
8
9# Copyright (C) 1998, 1999, 2001, 2004, 2006 Free Software Foundation, Inc.
10# This file is free software; the Free Software Foundation
11# gives unlimited permission to copy and/or distribute it,
12# with or without modifications, as long as this notice is preserved.
13
14AC_DEFUN([gl_FSTYPENAME],
15[
16 AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,
17 [
18 #include <sys/types.h>
19 #include <sys/param.h>
20 #include <sys/mount.h>
21 ])
22])
diff --git a/gl/m4/fsusage.m4 b/gl/m4/fsusage.m4
new file mode 100644
index 00000000..08bf06c9
--- /dev/null
+++ b/gl/m4/fsusage.m4
@@ -0,0 +1,265 @@
1#serial 22
2# Obtaining file system usage information.
3
4# Copyright (C) 1997, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
5# Foundation, Inc.
6#
7# This file is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# Written by Jim Meyering.
12
13AC_DEFUN([gl_FSUSAGE],
14[
15 AC_CHECK_HEADERS_ONCE(sys/param.h)
16 AC_CHECK_HEADERS_ONCE(sys/vfs.h sys/fs_types.h)
17 AC_CHECK_HEADERS(sys/mount.h, [], [],
18 [AC_INCLUDES_DEFAULT
19 [#if HAVE_SYS_PARAM_H
20 #include <sys/param.h>
21 #endif]])
22 gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no])
23 if test $gl_cv_fs_space = yes; then
24 AC_LIBOBJ(fsusage)
25 gl_PREREQ_FSUSAGE_EXTRA
26 fi
27])
28
29# Try to determine how a program can obtain file system usage information.
30# If successful, define the appropriate symbol (see fsusage.c) and
31# execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND.
32#
33# gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
34
35AC_DEFUN([gl_FILE_SYSTEM_USAGE],
36[
37
38AC_MSG_NOTICE([checking how to get file system space usage])
39ac_fsusage_space=no
40
41# Perform only the link test since it seems there are no variants of the
42# statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs)
43# because that got a false positive on SCO OSR5. Adding the declaration
44# of a `struct statvfs' causes this test to fail (as it should) on such
45# systems. That system is reported to work fine with STAT_STATFS4 which
46# is what it gets when this test fails.
47if test $ac_fsusage_space = no; then
48 # SVR4
49 AC_CACHE_CHECK([for statvfs function (SVR4)], fu_cv_sys_stat_statvfs,
50 [AC_TRY_LINK([#include <sys/types.h>
51#if defined __GLIBC__ && !defined __BEOS__
52Do not use statvfs on systems with GNU libc, because that function stats
53all preceding entries in /proc/mounts, and that makes df hang if even
54one of the corresponding file systems is hard-mounted, but not available.
55statvfs in GNU libc on BeOS operates differently: it only makes a system
56call.
57#endif
58#include <sys/statvfs.h>],
59 [struct statvfs fsd; statvfs (0, &fsd);],
60 fu_cv_sys_stat_statvfs=yes,
61 fu_cv_sys_stat_statvfs=no)])
62 if test $fu_cv_sys_stat_statvfs = yes; then
63 ac_fsusage_space=yes
64 AC_DEFINE(STAT_STATVFS, 1,
65 [ Define if there is a function named statvfs. (SVR4)])
66 fi
67fi
68
69if test $ac_fsusage_space = no; then
70 # DEC Alpha running OSF/1
71 AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])
72 AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1,
73 [AC_TRY_RUN([
74#include <sys/param.h>
75#include <sys/types.h>
76#include <sys/mount.h>
77 int
78 main ()
79 {
80 struct statfs fsd;
81 fsd.f_fsize = 0;
82 return statfs (".", &fsd, sizeof (struct statfs)) != 0;
83 }],
84 fu_cv_sys_stat_statfs3_osf1=yes,
85 fu_cv_sys_stat_statfs3_osf1=no,
86 fu_cv_sys_stat_statfs3_osf1=no)])
87 AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1)
88 if test $fu_cv_sys_stat_statfs3_osf1 = yes; then
89 ac_fsusage_space=yes
90 AC_DEFINE(STAT_STATFS3_OSF1, 1,
91 [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)])
92 fi
93fi
94
95if test $ac_fsusage_space = no; then
96# AIX
97 AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl
98member (AIX, 4.3BSD)])
99 AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize,
100 [AC_TRY_RUN([
101#ifdef HAVE_SYS_PARAM_H
102#include <sys/param.h>
103#endif
104#ifdef HAVE_SYS_MOUNT_H
105#include <sys/mount.h>
106#endif
107#ifdef HAVE_SYS_VFS_H
108#include <sys/vfs.h>
109#endif
110 int
111 main ()
112 {
113 struct statfs fsd;
114 fsd.f_bsize = 0;
115 return statfs (".", &fsd) != 0;
116 }],
117 fu_cv_sys_stat_statfs2_bsize=yes,
118 fu_cv_sys_stat_statfs2_bsize=no,
119 fu_cv_sys_stat_statfs2_bsize=no)])
120 AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize)
121 if test $fu_cv_sys_stat_statfs2_bsize = yes; then
122 ac_fsusage_space=yes
123 AC_DEFINE(STAT_STATFS2_BSIZE, 1,
124[ Define if statfs takes 2 args and struct statfs has a field named f_bsize.
125 (4.3BSD, SunOS 4, HP-UX, AIX PS/2)])
126 fi
127fi
128
129if test $ac_fsusage_space = no; then
130# SVR3
131 AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)])
132 AC_CACHE_VAL(fu_cv_sys_stat_statfs4,
133 [AC_TRY_RUN([#include <sys/types.h>
134#include <sys/statfs.h>
135 int
136 main ()
137 {
138 struct statfs fsd;
139 return statfs (".", &fsd, sizeof fsd, 0) != 0;
140 }],
141 fu_cv_sys_stat_statfs4=yes,
142 fu_cv_sys_stat_statfs4=no,
143 fu_cv_sys_stat_statfs4=no)])
144 AC_MSG_RESULT($fu_cv_sys_stat_statfs4)
145 if test $fu_cv_sys_stat_statfs4 = yes; then
146 ac_fsusage_space=yes
147 AC_DEFINE(STAT_STATFS4, 1,
148 [ Define if statfs takes 4 args. (SVR3, Dynix, Irix, Dolphin)])
149 fi
150fi
151
152if test $ac_fsusage_space = no; then
153# 4.4BSD and NetBSD
154 AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl
155member (4.4BSD and NetBSD)])
156 AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize,
157 [AC_TRY_RUN([#include <sys/types.h>
158#ifdef HAVE_SYS_PARAM_H
159#include <sys/param.h>
160#endif
161#ifdef HAVE_SYS_MOUNT_H
162#include <sys/mount.h>
163#endif
164 int
165 main ()
166 {
167 struct statfs fsd;
168 fsd.f_fsize = 0;
169 return statfs (".", &fsd) != 0;
170 }],
171 fu_cv_sys_stat_statfs2_fsize=yes,
172 fu_cv_sys_stat_statfs2_fsize=no,
173 fu_cv_sys_stat_statfs2_fsize=no)])
174 AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize)
175 if test $fu_cv_sys_stat_statfs2_fsize = yes; then
176 ac_fsusage_space=yes
177 AC_DEFINE(STAT_STATFS2_FSIZE, 1,
178[ Define if statfs takes 2 args and struct statfs has a field named f_fsize.
179 (4.4BSD, NetBSD)])
180 fi
181fi
182
183if test $ac_fsusage_space = no; then
184 # Ultrix
185 AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)])
186 AC_CACHE_VAL(fu_cv_sys_stat_fs_data,
187 [AC_TRY_RUN([#include <sys/types.h>
188#ifdef HAVE_SYS_PARAM_H
189#include <sys/param.h>
190#endif
191#ifdef HAVE_SYS_MOUNT_H
192#include <sys/mount.h>
193#endif
194#ifdef HAVE_SYS_FS_TYPES_H
195#include <sys/fs_types.h>
196#endif
197 int
198 main ()
199 {
200 struct fs_data fsd;
201 /* Ultrix's statfs returns 1 for success,
202 0 for not mounted, -1 for failure. */
203 return statfs (".", &fsd) != 1;
204 }],
205 fu_cv_sys_stat_fs_data=yes,
206 fu_cv_sys_stat_fs_data=no,
207 fu_cv_sys_stat_fs_data=no)])
208 AC_MSG_RESULT($fu_cv_sys_stat_fs_data)
209 if test $fu_cv_sys_stat_fs_data = yes; then
210 ac_fsusage_space=yes
211 AC_DEFINE(STAT_STATFS2_FS_DATA, 1,
212[ Define if statfs takes 2 args and the second argument has
213 type struct fs_data. (Ultrix)])
214 fi
215fi
216
217if test $ac_fsusage_space = no; then
218 # SVR2
219 AC_TRY_CPP([#include <sys/filsys.h>
220 ],
221 AC_DEFINE(STAT_READ_FILSYS, 1,
222 [Define if there is no specific function for reading file systems usage
223 information and you have the <sys/filsys.h> header file. (SVR2)])
224 ac_fsusage_space=yes)
225fi
226
227AS_IF([test $ac_fsusage_space = yes], [$1], [$2])
228
229])
230
231
232# Check for SunOS statfs brokenness wrt partitions 2GB and larger.
233# If <sys/vfs.h> exists and struct statfs has a member named f_spare,
234# enable the work-around code in fsusage.c.
235AC_DEFUN([gl_STATFS_TRUNCATES],
236[
237 AC_MSG_CHECKING([for statfs that truncates block counts])
238 AC_CACHE_VAL(fu_cv_sys_truncating_statfs,
239 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
240#if !defined(sun) && !defined(__sun)
241choke -- this is a workaround for a Sun-specific problem
242#endif
243#include <sys/types.h>
244#include <sys/vfs.h>]],
245 [[struct statfs t; long c = *(t.f_spare);
246 if (c) return 0;]])],
247 [fu_cv_sys_truncating_statfs=yes],
248 [fu_cv_sys_truncating_statfs=no])])
249 if test $fu_cv_sys_truncating_statfs = yes; then
250 AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1,
251 [Define if the block counts reported by statfs may be truncated to 2GB
252 and the correct values may be stored in the f_spare array.
253 (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem.
254 SunOS 4.1.1 seems not to be affected.)])
255 fi
256 AC_MSG_RESULT($fu_cv_sys_truncating_statfs)
257])
258
259
260# Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE.
261AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA],
262[
263 AC_CHECK_HEADERS(dustat.h sys/fs/s5param.h sys/filsys.h sys/statfs.h)
264 gl_STATFS_TRUNCATES
265])
diff --git a/gl/m4/getaddrinfo.m4 b/gl/m4/getaddrinfo.m4
new file mode 100644
index 00000000..db285d94
--- /dev/null
+++ b/gl/m4/getaddrinfo.m4
@@ -0,0 +1,88 @@
1# getaddrinfo.m4 serial 11
2dnl Copyright (C) 2004, 2005, 2006 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_GETADDRINFO],
8[
9 AC_MSG_NOTICE([checking how to do getaddrinfo, freeaddrinfo and getnameinfo])
10
11 AC_SEARCH_LIBS(getaddrinfo, [nsl socket])
12 AC_CHECK_FUNCS(getaddrinfo,, [
13 AC_CACHE_CHECK(for getaddrinfo in ws2tcpip.h and -lws2_32,
14 gl_cv_w32_getaddrinfo, [
15 gl_cv_w32_getaddrinfo=no
16 am_save_LIBS="$LIBS"
17 LIBS="$LIBS -lws2_32"
18 AC_TRY_LINK([
19#ifdef HAVE_WS2TCPIP_H
20#include <ws2tcpip.h>
21#endif
22], [getaddrinfo(0, 0, 0, 0);], gl_cv_w32_getaddrinfo=yes)
23 LIBS="$am_save_LIBS"])
24 if test "$gl_cv_w32_getaddrinfo" = "yes"; then
25 LIBS="$LIBS -lws2_32"
26 else
27 AC_LIBOBJ(getaddrinfo)
28 fi
29 ])
30
31 AC_REPLACE_FUNCS(gai_strerror)
32 gl_PREREQ_GETADDRINFO
33])
34
35# Prerequisites of lib/getaddrinfo.h and lib/getaddrinfo.c.
36AC_DEFUN([gl_PREREQ_GETADDRINFO], [
37 AC_SEARCH_LIBS(gethostbyname, [inet nsl])
38 AC_SEARCH_LIBS(getservbyname, [inet nsl socket xnet])
39 AC_CHECK_FUNCS(gethostbyname,, [
40 AC_CACHE_CHECK(for gethostbyname in winsock2.h and -lws2_32,
41 gl_cv_w32_gethostbyname, [
42 gl_cv_w32_gethostbyname=no
43 am_save_LIBS="$LIBS"
44 LIBS="$LIBS -lws2_32"
45 AC_TRY_LINK([
46#ifdef HAVE_WINSOCK2_H
47#include <winsock2.h>
48#endif
49], [gethostbyname(0);], gl_cv_w32_gethostbyname=yes)
50 LIBS="$am_save_LIBS"])
51 if test "$gl_cv_w32_gethostbyname" = "yes"; then
52 LIBS="$LIBS -lws2_32"
53 fi
54 ])
55 AC_REQUIRE([AC_C_RESTRICT])
56 AC_REQUIRE([gl_SOCKET_FAMILIES])
57 AC_REQUIRE([gl_HEADER_SYS_SOCKET])
58 AC_REQUIRE([AC_C_INLINE])
59 AC_REQUIRE([AC_GNU_SOURCE])
60 AC_CHECK_HEADERS_ONCE(netinet/in.h netdb.h)
61 AC_CHECK_DECLS([getaddrinfo, freeaddrinfo, gai_strerror, getnameinfo],,,[
62 /* sys/types.h is not needed according to POSIX, but the
63 sys/socket.h in i386-unknown-freebsd4.10 and
64 powerpc-apple-darwin5.5 required it. */
65#include <sys/types.h>
66#ifdef HAVE_SYS_SOCKET_H
67#include <sys/socket.h>
68#endif
69#ifdef HAVE_NETDB_H
70#include <netdb.h>
71#endif
72#ifdef HAVE_WS2TCPIP_H
73#include <ws2tcpip.h>
74#endif
75])
76 AC_CHECK_TYPES([struct addrinfo],,,[
77#include <sys/types.h>
78#ifdef HAVE_SYS_SOCKET_H
79#include <sys/socket.h>
80#endif
81#ifdef HAVE_NETDB_H
82#include <netdb.h>
83#endif
84#ifdef HAVE_WS2TCPIP_H
85#include <ws2tcpip.h>
86#endif
87])
88])
diff --git a/gl/m4/gethostname.m4 b/gl/m4/gethostname.m4
new file mode 100644
index 00000000..1e9749d3
--- /dev/null
+++ b/gl/m4/gethostname.m4
@@ -0,0 +1,18 @@
1# gethostname.m4 serial 2
2dnl Copyright (C) 2002 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_FUNC_GETHOSTNAME],
8[
9 AC_REPLACE_FUNCS(gethostname)
10 if test $ac_cv_func_gethostname = no; then
11 gl_PREREQ_GETHOSTNAME
12 fi
13])
14
15# Prerequisites of lib/gethostname.c.
16AC_DEFUN([gl_PREREQ_GETHOSTNAME], [
17 AC_CHECK_FUNCS(uname)
18])
diff --git a/gl/m4/getloadavg.m4 b/gl/m4/getloadavg.m4
new file mode 100644
index 00000000..82437291
--- /dev/null
+++ b/gl/m4/getloadavg.m4
@@ -0,0 +1,155 @@
1# Check for getloadavg.
2
3# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2002, 2003,
4# 2006 Free Software Foundation, Inc.
5
6# This file is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10# Autoconf defines AC_FUNC_GETLOADAVG, but that is obsolescent.
11# New applications should use gl_GETLOADAVG instead.
12
13# gl_GETLOADAVG(LIBOBJDIR)
14# ------------------------
15AC_DEFUN([gl_GETLOADAVG],
16[gl_have_func=no # yes means we've found a way to get the load average.
17
18# Make sure getloadavg.c is where it belongs, at configure-time.
19test -f "$srcdir/$1/getloadavg.c" ||
20 AC_MSG_ERROR([$srcdir/$1/getloadavg.c is missing])
21
22gl_save_LIBS=$LIBS
23
24# Check for getloadavg, but be sure not to touch the cache variable.
25(AC_CHECK_FUNC(getloadavg, exit 0, exit 1)) && gl_have_func=yes
26
27# On HPUX9, an unprivileged user can get load averages through this function.
28AC_CHECK_FUNCS(pstat_getdynamic)
29
30# Solaris has libkstat which does not require root.
31AC_CHECK_LIB(kstat, kstat_open)
32test $ac_cv_lib_kstat_kstat_open = yes && gl_have_func=yes
33
34# Some systems with -lutil have (and need) -lkvm as well, some do not.
35# On Solaris, -lkvm requires nlist from -lelf, so check that first
36# to get the right answer into the cache.
37# For kstat on solaris, we need libelf to force the definition of SVR4 below.
38if test $gl_have_func = no; then
39 AC_CHECK_LIB(elf, elf_begin, LIBS="-lelf $LIBS")
40fi
41if test $gl_have_func = no; then
42 AC_CHECK_LIB(kvm, kvm_open, LIBS="-lkvm $LIBS")
43 # Check for the 4.4BSD definition of getloadavg.
44 AC_CHECK_LIB(util, getloadavg,
45 [LIBS="-lutil $LIBS" gl_have_func=yes gl_cv_func_getloadavg_setgid=yes])
46fi
47
48if test $gl_have_func = no; then
49 # There is a commonly available library for RS/6000 AIX.
50 # Since it is not a standard part of AIX, it might be installed locally.
51 gl_getloadavg_LIBS=$LIBS
52 LIBS="-L/usr/local/lib $LIBS"
53 AC_CHECK_LIB(getloadavg, getloadavg,
54 [LIBS="-lgetloadavg $LIBS"], [LIBS=$gl_getloadavg_LIBS])
55fi
56
57# Make sure it is really in the library, if we think we found it,
58# otherwise set up the replacement function.
59AC_CHECK_FUNCS(getloadavg, [],
60 [gl_PREREQ_GETLOADAVG])
61
62# Some definitions of getloadavg require that the program be installed setgid.
63AC_CACHE_CHECK(whether getloadavg requires setgid,
64 gl_cv_func_getloadavg_setgid,
65[AC_EGREP_CPP([Yowza Am I SETGID yet],
66[#define CONFIGURING_GETLOADAVG
67#include "$srcdir/$1/getloadavg.c"
68#ifdef LDAV_PRIVILEGED
69Yowza Am I SETGID yet
70#endif
71],
72 gl_cv_func_getloadavg_setgid=yes,
73 gl_cv_func_getloadavg_setgid=no)])
74if test $gl_cv_func_getloadavg_setgid = yes; then
75 NEED_SETGID=true
76 AC_DEFINE(GETLOADAVG_PRIVILEGED, 1,
77 [Define to 1 if the `getloadavg' function needs to be run setuid
78 or setgid.])
79else
80 NEED_SETGID=false
81fi
82AC_SUBST(NEED_SETGID)dnl
83
84if test $gl_cv_func_getloadavg_setgid = yes; then
85 AC_CACHE_CHECK(group of /dev/kmem, gl_cv_group_kmem,
86[ # On Solaris, /dev/kmem is a symlink. Get info on the real file.
87 ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null`
88 # If we got an error (system does not support symlinks), try without -L.
89 test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem`
90 gl_cv_group_kmem=`echo $ac_ls_output \
91 | sed -ne ['s/[ ][ ]*/ /g
92 s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\) *.*/\1/
93 / /s/.* //;p']`
94])
95 AC_SUBST(KMEM_GROUP, $gl_cv_group_kmem)dnl
96fi
97if test "x$gl_save_LIBS" = x; then
98 GETLOADAVG_LIBS=$LIBS
99else
100 GETLOADAVG_LIBS=`echo "$LIBS" | sed "s!$gl_save_LIBS!!"`
101fi
102LIBS=$gl_save_LIBS
103
104AC_SUBST(GETLOADAVG_LIBS)dnl
105])# gl_GETLOADAVG
106
107
108# gl_PREREQ_GETLOADAVG
109# --------------------
110# Set up the AC_LIBOBJ replacement of `getloadavg'.
111AC_DEFUN([gl_PREREQ_GETLOADAVG],
112[AC_LIBOBJ(getloadavg)
113AC_DEFINE(C_GETLOADAVG, 1, [Define to 1 if using `getloadavg.c'.])
114# Figure out what our getloadavg.c needs.
115gl_have_func=no
116AC_CHECK_HEADER(sys/dg_sys_info.h,
117[gl_have_func=yes
118 AC_DEFINE(DGUX, 1, [Define to 1 for DGUX with <sys/dg_sys_info.h>.])
119 AC_CHECK_LIB(dgc, dg_sys_info)])
120
121# We cannot check for <dwarf.h>, because Solaris 2 does not use dwarf (it
122# uses stabs), but it is still SVR4. We cannot check for <elf.h> because
123# Irix 4.0.5F has the header but not the library.
124if test $gl_have_func = no && test "$ac_cv_lib_elf_elf_begin" = yes; then
125 gl_have_func=yes
126 AC_DEFINE(SVR4, 1, [Define to 1 on System V Release 4.])
127fi
128
129if test $gl_have_func = no; then
130 AC_CHECK_HEADER(inq_stats/cpustats.h,
131 [gl_have_func=yes
132 AC_DEFINE(UMAX, 1, [Define to 1 for Encore UMAX.])
133 AC_DEFINE(UMAX4_3, 1,
134 [Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h>
135 instead of <sys/cpustats.h>.])])
136fi
137
138if test $gl_have_func = no; then
139 AC_CHECK_HEADER(sys/cpustats.h,
140 [gl_have_func=yes; AC_DEFINE(UMAX)])
141fi
142
143if test $gl_have_func = no; then
144 AC_CHECK_HEADERS(mach/mach.h)
145fi
146
147AC_CHECK_HEADERS(nlist.h,
148[AC_CHECK_MEMBERS([struct nlist.n_un.n_name],
149 [AC_DEFINE(NLIST_NAME_UNION, 1,
150 [Define to 1 if your `struct nlist' has an
151 `n_un' member. Obsolete, depend on
152 `HAVE_STRUCT_NLIST_N_UN_N_NAME])], [],
153 [@%:@include <nlist.h>])
154])dnl
155])# gl_PREREQ_GETLOADAVG
diff --git a/gl/m4/getopt.m4 b/gl/m4/getopt.m4
new file mode 100644
index 00000000..c0a73b2c
--- /dev/null
+++ b/gl/m4/getopt.m4
@@ -0,0 +1,83 @@
1# getopt.m4 serial 13
2dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 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
7# The getopt module assume you want GNU getopt, with getopt_long etc,
8# rather than vanilla POSIX getopt. This means your code should
9# always include <getopt.h> for the getopt prototypes.
10
11AC_DEFUN([gl_GETOPT_SUBSTITUTE],
12[
13 AC_LIBOBJ([getopt])
14 AC_LIBOBJ([getopt1])
15 gl_GETOPT_SUBSTITUTE_HEADER
16 gl_PREREQ_GETOPT
17])
18
19AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER],
20[
21 GETOPT_H=getopt.h
22 AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
23 [Define to rpl_ if the getopt replacement functions and variables
24 should be used.])
25 AC_SUBST([GETOPT_H])
26])
27
28AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
29[
30 if test -z "$GETOPT_H"; then
31 AC_CHECK_HEADERS([getopt.h], [], [GETOPT_H=getopt.h])
32 fi
33
34 if test -z "$GETOPT_H"; then
35 AC_CHECK_FUNCS([getopt_long_only], [], [GETOPT_H=getopt.h])
36 fi
37
38 dnl BSD getopt_long uses an incompatible method to reset option processing,
39 dnl and (as of 2004-10-15) mishandles optional option-arguments.
40 if test -z "$GETOPT_H"; then
41 AC_CHECK_DECL([optreset], [GETOPT_H=getopt.h], [], [#include <getopt.h>])
42 fi
43
44 dnl Solaris 10 getopt doesn't handle `+' as a leading character in an
45 dnl option string (as of 2005-05-05).
46 if test -z "$GETOPT_H"; then
47 AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_gnu_getopt],
48 [AC_RUN_IFELSE(
49 [AC_LANG_PROGRAM([#include <getopt.h>],
50 [[
51 char *myargv[3];
52 myargv[0] = "conftest";
53 myargv[1] = "-+";
54 myargv[2] = 0;
55 return getopt (2, myargv, "+a") != '?';
56 ]])],
57 [gl_cv_func_gnu_getopt=yes],
58 [gl_cv_func_gnu_getopt=no],
59 [dnl cross compiling - pessimistically guess based on decls
60 dnl Solaris 10 getopt doesn't handle `+' as a leading character in an
61 dnl option string (as of 2005-05-05).
62 AC_CHECK_DECL([getopt_clip],
63 [gl_cv_func_gnu_getopt=no], [gl_cv_func_gnu_getopt=yes],
64 [#include <getopt.h>])])])
65 if test "$gl_cv_func_gnu_getopt" = "no"; then
66 GETOPT_H=getopt.h
67 fi
68 fi
69])
70
71AC_DEFUN([gl_GETOPT_IFELSE],
72[
73 AC_REQUIRE([gl_GETOPT_CHECK_HEADERS])
74 AS_IF([test -n "$GETOPT_H"], [$1], [$2])
75])
76
77AC_DEFUN([gl_GETOPT], [gl_GETOPT_IFELSE([gl_GETOPT_SUBSTITUTE])])
78
79# Prerequisites of lib/getopt*.
80AC_DEFUN([gl_PREREQ_GETOPT],
81[
82 AC_CHECK_DECLS_ONCE([getenv])
83])
diff --git a/gl/m4/gettext.m4 b/gl/m4/gettext.m4
new file mode 100644
index 00000000..91c345e9
--- /dev/null
+++ b/gl/m4/gettext.m4
@@ -0,0 +1,419 @@
1# gettext.m4 serial 59 (gettext-0.16.1)
2dnl Copyright (C) 1995-2006 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
18dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006.
19
20dnl Macro to add for using GNU gettext.
21
22dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
23dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The
24dnl default (if it is not specified or empty) is 'no-libtool'.
25dnl INTLSYMBOL should be 'external' for packages with no intl directory,
26dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory.
27dnl If INTLSYMBOL is 'use-libtool', then a libtool library
28dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static,
29dnl depending on --{enable,disable}-{shared,static} and on the presence of
30dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library
31dnl $(top_builddir)/intl/libintl.a will be created.
32dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
33dnl implementations (in libc or libintl) without the ngettext() function
34dnl will be ignored. If NEEDSYMBOL is specified and is
35dnl 'need-formatstring-macros', then GNU gettext implementations that don't
36dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored.
37dnl INTLDIR is used to find the intl libraries. If empty,
38dnl the value `$(top_builddir)/intl/' is used.
39dnl
40dnl The result of the configuration is one of three cases:
41dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
42dnl and used.
43dnl Catalog format: GNU --> install in $(datadir)
44dnl Catalog extension: .mo after installation, .gmo in source tree
45dnl 2) GNU gettext has been found in the system's C library.
46dnl Catalog format: GNU --> install in $(datadir)
47dnl Catalog extension: .mo after installation, .gmo in source tree
48dnl 3) No internationalization, always use English msgid.
49dnl Catalog format: none
50dnl Catalog extension: none
51dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
52dnl The use of .gmo is historical (it was needed to avoid overwriting the
53dnl GNU format catalogs when building on a platform with an X/Open gettext),
54dnl but we keep it in order not to force irrelevant filename changes on the
55dnl maintainers.
56dnl
57AC_DEFUN([AM_GNU_GETTEXT],
58[
59 dnl Argument checking.
60 ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], ,
61 [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
62])])])])])
63 ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], ,
64 [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
65])])])])
66 define([gt_included_intl],
67 ifelse([$1], [external],
68 ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]),
69 [yes]))
70 define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], []))
71 gt_NEEDS_INIT
72 AM_GNU_GETTEXT_NEED([$2])
73
74 AC_REQUIRE([AM_PO_SUBDIRS])dnl
75 ifelse(gt_included_intl, yes, [
76 AC_REQUIRE([AM_INTL_SUBDIR])dnl
77 ])
78
79 dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
80 AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
81 AC_REQUIRE([AC_LIB_RPATH])
82
83 dnl Sometimes libintl requires libiconv, so first search for libiconv.
84 dnl Ideally we would do this search only after the
85 dnl if test "$USE_NLS" = "yes"; then
86 dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
87 dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT
88 dnl the configure script would need to contain the same shell code
89 dnl again, outside any 'if'. There are two solutions:
90 dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'.
91 dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE.
92 dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not
93 dnl documented, we avoid it.
94 ifelse(gt_included_intl, yes, , [
95 AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
96 ])
97
98 dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation.
99 gt_INTL_MACOSX
100
101 dnl Set USE_NLS.
102 AC_REQUIRE([AM_NLS])
103
104 ifelse(gt_included_intl, yes, [
105 BUILD_INCLUDED_LIBINTL=no
106 USE_INCLUDED_LIBINTL=no
107 ])
108 LIBINTL=
109 LTLIBINTL=
110 POSUB=
111
112 dnl Add a version number to the cache macros.
113 case " $gt_needs " in
114 *" need-formatstring-macros "*) gt_api_version=3 ;;
115 *" need-ngettext "*) gt_api_version=2 ;;
116 *) gt_api_version=1 ;;
117 esac
118 gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc"
119 gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl"
120
121 dnl If we use NLS figure out what method
122 if test "$USE_NLS" = "yes"; then
123 gt_use_preinstalled_gnugettext=no
124 ifelse(gt_included_intl, yes, [
125 AC_MSG_CHECKING([whether included gettext is requested])
126 AC_ARG_WITH(included-gettext,
127 [ --with-included-gettext use the GNU gettext library included here],
128 nls_cv_force_use_gnu_gettext=$withval,
129 nls_cv_force_use_gnu_gettext=no)
130 AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
131
132 nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
133 if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
134 ])
135 dnl User does not insist on using GNU NLS library. Figure out what
136 dnl to use. If GNU gettext is available we use this. Else we have
137 dnl to fall back to GNU NLS library.
138
139 if test $gt_api_version -ge 3; then
140 gt_revision_test_code='
141#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
142#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
143#endif
144changequote(,)dnl
145typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
146changequote([,])dnl
147'
148 else
149 gt_revision_test_code=
150 fi
151 if test $gt_api_version -ge 2; then
152 gt_expression_test_code=' + * ngettext ("", "", 0)'
153 else
154 gt_expression_test_code=
155 fi
156
157 AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc],
158 [AC_TRY_LINK([#include <libintl.h>
159$gt_revision_test_code
160extern int _nl_msg_cat_cntr;
161extern int *_nl_domain_bindings;],
162 [bindtextdomain ("", "");
163return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings],
164 [eval "$gt_func_gnugettext_libc=yes"],
165 [eval "$gt_func_gnugettext_libc=no"])])
166
167 if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
168 dnl Sometimes libintl requires libiconv, so first search for libiconv.
169 ifelse(gt_included_intl, yes, , [
170 AM_ICONV_LINK
171 ])
172 dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
173 dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
174 dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
175 dnl even if libiconv doesn't exist.
176 AC_LIB_LINKFLAGS_BODY([intl])
177 AC_CACHE_CHECK([for GNU gettext in libintl],
178 [$gt_func_gnugettext_libintl],
179 [gt_save_CPPFLAGS="$CPPFLAGS"
180 CPPFLAGS="$CPPFLAGS $INCINTL"
181 gt_save_LIBS="$LIBS"
182 LIBS="$LIBS $LIBINTL"
183 dnl Now see whether libintl exists and does not depend on libiconv.
184 AC_TRY_LINK([#include <libintl.h>
185$gt_revision_test_code
186extern int _nl_msg_cat_cntr;
187extern
188#ifdef __cplusplus
189"C"
190#endif
191const char *_nl_expand_alias (const char *);],
192 [bindtextdomain ("", "");
193return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")],
194 [eval "$gt_func_gnugettext_libintl=yes"],
195 [eval "$gt_func_gnugettext_libintl=no"])
196 dnl Now see whether libintl exists and depends on libiconv.
197 if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then
198 LIBS="$LIBS $LIBICONV"
199 AC_TRY_LINK([#include <libintl.h>
200$gt_revision_test_code
201extern int _nl_msg_cat_cntr;
202extern
203#ifdef __cplusplus
204"C"
205#endif
206const char *_nl_expand_alias (const char *);],
207 [bindtextdomain ("", "");
208return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")],
209 [LIBINTL="$LIBINTL $LIBICONV"
210 LTLIBINTL="$LTLIBINTL $LTLIBICONV"
211 eval "$gt_func_gnugettext_libintl=yes"
212 ])
213 fi
214 CPPFLAGS="$gt_save_CPPFLAGS"
215 LIBS="$gt_save_LIBS"])
216 fi
217
218 dnl If an already present or preinstalled GNU gettext() is found,
219 dnl use it. But if this macro is used in GNU gettext, and GNU
220 dnl gettext is already preinstalled in libintl, we update this
221 dnl libintl. (Cf. the install rule in intl/Makefile.in.)
222 if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \
223 || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \
224 && test "$PACKAGE" != gettext-runtime \
225 && test "$PACKAGE" != gettext-tools; }; then
226 gt_use_preinstalled_gnugettext=yes
227 else
228 dnl Reset the values set by searching for libintl.
229 LIBINTL=
230 LTLIBINTL=
231 INCINTL=
232 fi
233
234 ifelse(gt_included_intl, yes, [
235 if test "$gt_use_preinstalled_gnugettext" != "yes"; then
236 dnl GNU gettext is not found in the C library.
237 dnl Fall back on included GNU gettext library.
238 nls_cv_use_gnu_gettext=yes
239 fi
240 fi
241
242 if test "$nls_cv_use_gnu_gettext" = "yes"; then
243 dnl Mark actions used to generate GNU NLS library.
244 BUILD_INCLUDED_LIBINTL=yes
245 USE_INCLUDED_LIBINTL=yes
246 LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD"
247 LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD"
248 LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
249 fi
250
251 CATOBJEXT=
252 if test "$gt_use_preinstalled_gnugettext" = "yes" \
253 || test "$nls_cv_use_gnu_gettext" = "yes"; then
254 dnl Mark actions to use GNU gettext tools.
255 CATOBJEXT=.gmo
256 fi
257 ])
258
259 if test -n "$INTL_MACOSX_LIBS"; then
260 if test "$gt_use_preinstalled_gnugettext" = "yes" \
261 || test "$nls_cv_use_gnu_gettext" = "yes"; then
262 dnl Some extra flags are needed during linking.
263 LIBINTL="$LIBINTL $INTL_MACOSX_LIBS"
264 LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS"
265 fi
266 fi
267
268 if test "$gt_use_preinstalled_gnugettext" = "yes" \
269 || test "$nls_cv_use_gnu_gettext" = "yes"; then
270 AC_DEFINE(ENABLE_NLS, 1,
271 [Define to 1 if translation of program messages to the user's native language
272 is requested.])
273 else
274 USE_NLS=no
275 fi
276 fi
277
278 AC_MSG_CHECKING([whether to use NLS])
279 AC_MSG_RESULT([$USE_NLS])
280 if test "$USE_NLS" = "yes"; then
281 AC_MSG_CHECKING([where the gettext function comes from])
282 if test "$gt_use_preinstalled_gnugettext" = "yes"; then
283 if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
284 gt_source="external libintl"
285 else
286 gt_source="libc"
287 fi
288 else
289 gt_source="included intl directory"
290 fi
291 AC_MSG_RESULT([$gt_source])
292 fi
293
294 if test "$USE_NLS" = "yes"; then
295
296 if test "$gt_use_preinstalled_gnugettext" = "yes"; then
297 if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
298 AC_MSG_CHECKING([how to link with libintl])
299 AC_MSG_RESULT([$LIBINTL])
300 AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
301 fi
302
303 dnl For backward compatibility. Some packages may be using this.
304 AC_DEFINE(HAVE_GETTEXT, 1,
305 [Define if the GNU gettext() function is already present or preinstalled.])
306 AC_DEFINE(HAVE_DCGETTEXT, 1,
307 [Define if the GNU dcgettext() function is already present or preinstalled.])
308 fi
309
310 dnl We need to process the po/ directory.
311 POSUB=po
312 fi
313
314 ifelse(gt_included_intl, yes, [
315 dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
316 dnl to 'yes' because some of the testsuite requires it.
317 if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then
318 BUILD_INCLUDED_LIBINTL=yes
319 fi
320
321 dnl Make all variables we use known to autoconf.
322 AC_SUBST(BUILD_INCLUDED_LIBINTL)
323 AC_SUBST(USE_INCLUDED_LIBINTL)
324 AC_SUBST(CATOBJEXT)
325
326 dnl For backward compatibility. Some configure.ins may be using this.
327 nls_cv_header_intl=
328 nls_cv_header_libgt=
329
330 dnl For backward compatibility. Some Makefiles may be using this.
331 DATADIRNAME=share
332 AC_SUBST(DATADIRNAME)
333
334 dnl For backward compatibility. Some Makefiles may be using this.
335 INSTOBJEXT=.mo
336 AC_SUBST(INSTOBJEXT)
337
338 dnl For backward compatibility. Some Makefiles may be using this.
339 GENCAT=gencat
340 AC_SUBST(GENCAT)
341
342 dnl For backward compatibility. Some Makefiles may be using this.
343 INTLOBJS=
344 if test "$USE_INCLUDED_LIBINTL" = yes; then
345 INTLOBJS="\$(GETTOBJS)"
346 fi
347 AC_SUBST(INTLOBJS)
348
349 dnl Enable libtool support if the surrounding package wishes it.
350 INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
351 AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
352 ])
353
354 dnl For backward compatibility. Some Makefiles may be using this.
355 INTLLIBS="$LIBINTL"
356 AC_SUBST(INTLLIBS)
357
358 dnl Make all documented variables known to autoconf.
359 AC_SUBST(LIBINTL)
360 AC_SUBST(LTLIBINTL)
361 AC_SUBST(POSUB)
362])
363
364
365dnl Checks for special options needed on MacOS X.
366dnl Defines INTL_MACOSX_LIBS.
367AC_DEFUN([gt_INTL_MACOSX],
368[
369 dnl Check for API introduced in MacOS X 10.2.
370 AC_CACHE_CHECK([for CFPreferencesCopyAppValue],
371 gt_cv_func_CFPreferencesCopyAppValue,
372 [gt_save_LIBS="$LIBS"
373 LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
374 AC_TRY_LINK([#include <CoreFoundation/CFPreferences.h>],
375 [CFPreferencesCopyAppValue(NULL, NULL)],
376 [gt_cv_func_CFPreferencesCopyAppValue=yes],
377 [gt_cv_func_CFPreferencesCopyAppValue=no])
378 LIBS="$gt_save_LIBS"])
379 if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then
380 AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1,
381 [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.])
382 fi
383 dnl Check for API introduced in MacOS X 10.3.
384 AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent,
385 [gt_save_LIBS="$LIBS"
386 LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
387 AC_TRY_LINK([#include <CoreFoundation/CFLocale.h>], [CFLocaleCopyCurrent();],
388 [gt_cv_func_CFLocaleCopyCurrent=yes],
389 [gt_cv_func_CFLocaleCopyCurrent=no])
390 LIBS="$gt_save_LIBS"])
391 if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
392 AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1,
393 [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.])
394 fi
395 INTL_MACOSX_LIBS=
396 if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then
397 INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
398 fi
399 AC_SUBST([INTL_MACOSX_LIBS])
400])
401
402
403dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized.
404m4_define([gt_NEEDS_INIT],
405[
406 m4_divert_text([DEFAULTS], [gt_needs=])
407 m4_define([gt_NEEDS_INIT], [])
408])
409
410
411dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL])
412AC_DEFUN([AM_GNU_GETTEXT_NEED],
413[
414 m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"])
415])
416
417
418dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version])
419AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
diff --git a/gl/m4/glibc2.m4 b/gl/m4/glibc2.m4
new file mode 100644
index 00000000..e8f5bfe6
--- /dev/null
+++ b/gl/m4/glibc2.m4
@@ -0,0 +1,30 @@
1# glibc2.m4 serial 1
2dnl Copyright (C) 2000-2002, 2004 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
7# Test for the GNU C Library, version 2.0 or newer.
8# From Bruno Haible.
9
10AC_DEFUN([gt_GLIBC2],
11 [
12 AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer,
13 ac_cv_gnu_library_2,
14 [AC_EGREP_CPP([Lucky GNU user],
15 [
16#include <features.h>
17#ifdef __GNU_LIBRARY__
18 #if (__GLIBC__ >= 2)
19 Lucky GNU user
20 #endif
21#endif
22 ],
23 ac_cv_gnu_library_2=yes,
24 ac_cv_gnu_library_2=no)
25 ]
26 )
27 AC_SUBST(GLIBC2)
28 GLIBC2="$ac_cv_gnu_library_2"
29 ]
30)
diff --git a/gl/m4/glibc21.m4 b/gl/m4/glibc21.m4
new file mode 100644
index 00000000..d95fd986
--- /dev/null
+++ b/gl/m4/glibc21.m4
@@ -0,0 +1,30 @@
1# glibc21.m4 serial 3
2dnl Copyright (C) 2000-2002, 2004 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
7# Test for the GNU C Library, version 2.1 or newer.
8# From Bruno Haible.
9
10AC_DEFUN([gl_GLIBC21],
11 [
12 AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
13 ac_cv_gnu_library_2_1,
14 [AC_EGREP_CPP([Lucky GNU user],
15 [
16#include <features.h>
17#ifdef __GNU_LIBRARY__
18 #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
19 Lucky GNU user
20 #endif
21#endif
22 ],
23 ac_cv_gnu_library_2_1=yes,
24 ac_cv_gnu_library_2_1=no)
25 ]
26 )
27 AC_SUBST(GLIBC21)
28 GLIBC21="$ac_cv_gnu_library_2_1"
29 ]
30)
diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4
new file mode 100644
index 00000000..e78c8604
--- /dev/null
+++ b/gl/m4/gnulib-cache.m4
@@ -0,0 +1,30 @@
1# Copyright (C) 2004-2007 Free Software Foundation, Inc.
2#
3# This file is free software, distributed under the terms of the GNU
4# General Public License. As a special exception to the GNU General
5# Public License, this file may be distributed as part of a program
6# that contains a configuration script generated by Autoconf, under
7# the same distribution terms as the rest of that program.
8#
9# Generated by gnulib-tool.
10#
11# This file represents the specification of how gnulib-tool is used.
12# It acts as a cache: It is written and read by gnulib-tool.
13# In projects using CVS, this file is meant to be stored in CVS,
14# like the configure.ac and various Makefile.am files.
15
16
17# Specification in the form of a command-line invocation:
18# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --aux-dir=. --no-libtool --macro-prefix=gl dirname fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex vasprintf vsnprintf
19
20# Specification in the form of a few gnulib-tool.m4 macro invocations:
21gl_LOCAL_DIR([])
22gl_MODULES([dirname fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex vasprintf vsnprintf])
23gl_AVOID([])
24gl_SOURCE_BASE([gl])
25gl_M4_BASE([gl/m4])
26gl_DOC_BASE([doc])
27gl_TESTS_BASE([tests])
28gl_LIB([libgnu])
29gl_MAKEFILE_NAME([])
30gl_MACRO_PREFIX([gl])
diff --git a/gl/m4/gnulib-common.m4 b/gl/m4/gnulib-common.m4
new file mode 100644
index 00000000..53980108
--- /dev/null
+++ b/gl/m4/gnulib-common.m4
@@ -0,0 +1,22 @@
1# gnulib-common.m4 serial 2
2dnl Copyright (C) 2007 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
7# gl_MODULE_INDICATOR([modulename])
8# defines a C macro indicating the presence of the given module.
9AC_DEFUN([gl_MODULE_INDICATOR],
10[
11 AC_DEFINE([GNULIB_]translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___]), [1],
12 [Define to 1 when using the gnulib module ]$1[.])
13])
14
15# AC_PROG_MKDIR_P
16# is a backport of autoconf-2.60's AC_PROG_MKDIR_P.
17# Remove this macro when we can assume autoconf >= 2.60.
18m4_ifdef([AC_PROG_MKDIR_P], [], [
19 AC_DEFUN([AC_PROG_MKDIR_P],
20 [AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
21 MKDIR_P='$(mkdir_p)'
22 AC_SUBST([MKDIR_P])])])
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4
new file mode 100644
index 00000000..ed4da7d9
--- /dev/null
+++ b/gl/m4/gnulib-comp.m4
@@ -0,0 +1,326 @@
1# DO NOT EDIT! GENERATED AUTOMATICALLY!
2# Copyright (C) 2004-2007 Free Software Foundation, Inc.
3#
4# This file is free software, distributed under the terms of the GNU
5# General Public License. As a special exception to the GNU General
6# Public License, this file may be distributed as part of a program
7# that contains a configuration script generated by Autoconf, under
8# the same distribution terms as the rest of that program.
9#
10# Generated by gnulib-tool.
11#
12# This file represents the compiled summary of the specification in
13# gnulib-cache.m4. It lists the computed macro invocations that need
14# to be invoked from configure.ac.
15# In projects using CVS, this file can be treated like other built files.
16
17
18# This macro should be invoked from ./configure.in, in the section
19# "Checks for programs", right after AC_PROG_CC, and certainly before
20# any checks for libraries, header files, types and library functions.
21AC_DEFUN([gl_EARLY],
22[
23 m4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace
24 m4_pattern_allow([^gl_ES$])dnl a valid locale name
25 m4_pattern_allow([^gl_LIBOBJS$])dnl a variable
26 m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable
27 AC_REQUIRE([AC_PROG_RANLIB])
28 AC_REQUIRE([AC_GNU_SOURCE])
29 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
30 AC_REQUIRE([gl_LOCK_EARLY])
31])
32
33# This macro should be invoked from ./configure.in, in the section
34# "Check for header files, types and library functions".
35AC_DEFUN([gl_INIT],
36[
37 m4_pushdef([AC_LIBOBJ], m4_defn([gl_LIBOBJ]))
38 m4_pushdef([AC_REPLACE_FUNCS], m4_defn([gl_REPLACE_FUNCS]))
39 m4_pushdef([AC_LIBSOURCES], m4_defn([gl_LIBSOURCES]))
40 AM_CONDITIONAL([GL_COND_LIBTOOL], [false])
41 gl_cond_libtool=false
42 gl_libdeps=
43 gl_ltlibdeps=
44 gl_source_base='gl'
45 gl_FUNC_ALLOCA
46 gl_HEADER_ARPA_INET
47 gl_C_STRTOD
48 gl_CLOEXEC
49 gl_DIRNAME
50 gl_DOUBLE_SLASH_ROOT
51 gl_ERROR
52 gl_EXITFAIL
53 dnl gl_USE_SYSTEM_EXTENSIONS must be added quite early to configure.ac.
54 gl_FCNTL_SAFER
55 gl_MODULE_INDICATOR([fcntl-safer])
56 gl_FSUSAGE
57 gl_GETADDRINFO
58 gl_FUNC_GETHOSTNAME
59 gl_GETLOADAVG([$gl_source_base])
60 gl_GETOPT
61 dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac.
62 AM_GNU_GETTEXT_VERSION([0.15])
63 gl_INET_NTOP
64 gl_INLINE
65 AC_FUNC_MALLOC
66 gl_MBCHAR
67 gl_MBITER
68 gl_FUNC_MEMCHR
69 gl_MINMAX
70 gl_MOUNTLIST
71 gl_HEADER_NETINET_IN
72 gl_REGEX
73 gl_SAFE_READ
74 gl_SAFE_WRITE
75 gl_SIZE_MAX
76 gl_FUNC_SNPRINTF
77 gl_TYPE_SOCKLEN_T
78 gt_TYPE_SSIZE_T
79 AM_STDBOOL_H
80 gl_STDINT_H
81 gl_STRCASE
82 gl_FUNC_STRDUP
83 gl_FUNC_STRNDUP
84 gl_FUNC_STRNLEN
85 gl_HEADER_SYS_SOCKET
86 AC_PROG_MKDIR_P
87 gl_HEADER_UNISTD
88 gl_UNISTD_SAFER
89 gl_FUNC_VASNPRINTF
90 gl_FUNC_VASPRINTF
91 gl_FUNC_VSNPRINTF
92 gl_WCHAR_H
93 gl_WCTYPE_H
94 gl_FUNC_WCWIDTH
95 gl_XALLOC
96 gl_XSIZE
97 gl_XSTRNDUP
98 LIBGNU_LIBDEPS="$gl_libdeps"
99 AC_SUBST([LIBGNU_LIBDEPS])
100 LIBGNU_LTLIBDEPS="$gl_ltlibdeps"
101 AC_SUBST([LIBGNU_LTLIBDEPS])
102 m4_popdef([AC_LIBSOURCES])
103 m4_popdef([AC_REPLACE_FUNCS])
104 m4_popdef([AC_LIBOBJ])
105 AC_CONFIG_COMMANDS_PRE([
106 gl_libobjs=
107 gl_ltlibobjs=
108 if test -n "$gl_LIBOBJS"; then
109 # Remove the extension.
110 sed_drop_objext='s/\.o$//;s/\.obj$//'
111 for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed "$sed_drop_objext" | sort | uniq`; do
112 gl_libobjs="$gl_libobjs $i.$ac_objext"
113 gl_ltlibobjs="$gl_ltlibobjs $i.lo"
114 done
115 fi
116 AC_SUBST([gl_LIBOBJS], [$gl_libobjs])
117 AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs])
118 ])
119])
120
121# Like AC_LIBOBJ, except that the module name goes
122# into gl_LIBOBJS instead of into LIBOBJS.
123AC_DEFUN([gl_LIBOBJ],
124 [gl_LIBOBJS="$gl_LIBOBJS $1.$ac_objext"])
125
126# Like AC_REPLACE_FUNCS, except that the module name goes
127# into gl_LIBOBJS instead of into LIBOBJS.
128AC_DEFUN([gl_REPLACE_FUNCS],
129 [AC_CHECK_FUNCS([$1], , [gl_LIBOBJ($ac_func)])])
130
131# Like AC_LIBSOURCES, except that it does nothing.
132# We rely on EXTRA_lib..._SOURCES instead.
133AC_DEFUN([gl_LIBSOURCES],
134 [])
135
136# This macro records the list of files which have been installed by
137# gnulib-tool and may be removed by future gnulib-tool invocations.
138AC_DEFUN([gl_FILE_LIST], [
139 build-aux/config.rpath
140 lib/alloca.c
141 lib/alloca_.h
142 lib/asnprintf.c
143 lib/asprintf.c
144 lib/basename.c
145 lib/c-strtod.c
146 lib/c-strtod.h
147 lib/cloexec.c
148 lib/cloexec.h
149 lib/creat-safer.c
150 lib/dirname.c
151 lib/dirname.h
152 lib/dup-safer.c
153 lib/error.c
154 lib/error.h
155 lib/exit.h
156 lib/exitfail.c
157 lib/exitfail.h
158 lib/fcntl--.h
159 lib/fcntl-safer.h
160 lib/fd-safer.c
161 lib/fsusage.c
162 lib/fsusage.h
163 lib/full-read.c
164 lib/full-read.h
165 lib/full-write.c
166 lib/full-write.h
167 lib/gai_strerror.c
168 lib/getaddrinfo.c
169 lib/getaddrinfo.h
170 lib/gethostname.c
171 lib/getloadavg.c
172 lib/getopt.c
173 lib/getopt1.c
174 lib/getopt_.h
175 lib/getopt_int.h
176 lib/gettext.h
177 lib/inet_ntop.c
178 lib/inet_ntop.h
179 lib/intprops.h
180 lib/malloc.c
181 lib/mbchar.c
182 lib/mbchar.h
183 lib/mbuiter.h
184 lib/memchr.c
185 lib/minmax.h
186 lib/mountlist.c
187 lib/mountlist.h
188 lib/open-safer.c
189 lib/pipe-safer.c
190 lib/printf-args.c
191 lib/printf-args.h
192 lib/printf-parse.c
193 lib/printf-parse.h
194 lib/regcomp.c
195 lib/regex.c
196 lib/regex.h
197 lib/regex_internal.c
198 lib/regex_internal.h
199 lib/regexec.c
200 lib/safe-read.c
201 lib/safe-read.h
202 lib/safe-write.c
203 lib/safe-write.h
204 lib/size_max.h
205 lib/snprintf.c
206 lib/snprintf.h
207 lib/socket_.h
208 lib/stdbool_.h
209 lib/stdint_.h
210 lib/strcase.h
211 lib/strcasecmp.c
212 lib/strdup.c
213 lib/strdup.h
214 lib/stripslash.c
215 lib/strncasecmp.c
216 lib/strndup.c
217 lib/strndup.h
218 lib/strnlen.c
219 lib/strnlen.h
220 lib/strnlen1.c
221 lib/strnlen1.h
222 lib/unistd--.h
223 lib/unistd-safer.h
224 lib/unistd_.h
225 lib/vasnprintf.c
226 lib/vasnprintf.h
227 lib/vasprintf.c
228 lib/vasprintf.h
229 lib/vsnprintf.c
230 lib/vsnprintf.h
231 lib/wchar_.h
232 lib/wctype_.h
233 lib/wcwidth.h
234 lib/xalloc-die.c
235 lib/xalloc.h
236 lib/xmalloc.c
237 lib/xsize.h
238 lib/xstrndup.c
239 lib/xstrndup.h
240 m4/absolute-header.m4
241 m4/alloca.m4
242 m4/arpa_inet_h.m4
243 m4/c-strtod.m4
244 m4/cloexec.m4
245 m4/codeset.m4
246 m4/dirname.m4
247 m4/dos.m4
248 m4/double-slash-root.m4
249 m4/eoverflow.m4
250 m4/error.m4
251 m4/exitfail.m4
252 m4/extensions.m4
253 m4/fcntl-safer.m4
254 m4/fstypename.m4
255 m4/fsusage.m4
256 m4/getaddrinfo.m4
257 m4/gethostname.m4
258 m4/getloadavg.m4
259 m4/getopt.m4
260 m4/gettext.m4
261 m4/glibc2.m4
262 m4/glibc21.m4
263 m4/gnulib-common.m4
264 m4/iconv.m4
265 m4/inet_ntop.m4
266 m4/inline.m4
267 m4/intdiv0.m4
268 m4/intl.m4
269 m4/intldir.m4
270 m4/intmax.m4
271 m4/intmax_t.m4
272 m4/inttypes-pri.m4
273 m4/inttypes_h.m4
274 m4/lcmessage.m4
275 m4/lib-ld.m4
276 m4/lib-link.m4
277 m4/lib-prefix.m4
278 m4/lock.m4
279 m4/longdouble.m4
280 m4/longlong.m4
281 m4/ls-mntd-fs.m4
282 m4/mbchar.m4
283 m4/mbiter.m4
284 m4/mbrtowc.m4
285 m4/memchr.m4
286 m4/minmax.m4
287 m4/mountlist.m4
288 m4/netinet_in_h.m4
289 m4/nls.m4
290 m4/onceonly_2_57.m4
291 m4/po.m4
292 m4/printf-posix.m4
293 m4/progtest.m4
294 m4/regex.m4
295 m4/safe-read.m4
296 m4/safe-write.m4
297 m4/size_max.m4
298 m4/snprintf.m4
299 m4/socklen.m4
300 m4/sockpfaf.m4
301 m4/ssize_t.m4
302 m4/stdbool.m4
303 m4/stdint.m4
304 m4/stdint_h.m4
305 m4/strcase.m4
306 m4/strdup.m4
307 m4/strndup.m4
308 m4/strnlen.m4
309 m4/sys_socket_h.m4
310 m4/uintmax_t.m4
311 m4/ulonglong.m4
312 m4/unistd-safer.m4
313 m4/unistd_h.m4
314 m4/vasnprintf.m4
315 m4/vasprintf.m4
316 m4/visibility.m4
317 m4/vsnprintf.m4
318 m4/wchar.m4
319 m4/wchar_t.m4
320 m4/wctype.m4
321 m4/wcwidth.m4
322 m4/wint_t.m4
323 m4/xalloc.m4
324 m4/xsize.m4
325 m4/xstrndup.m4
326])
diff --git a/gl/m4/gnulib-tool.m4 b/gl/m4/gnulib-tool.m4
new file mode 100644
index 00000000..ef593203
--- /dev/null
+++ b/gl/m4/gnulib-tool.m4
@@ -0,0 +1,33 @@
1# gnulib-tool.m4 serial 1
2dnl Copyright (C) 2004-2005 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
7dnl The following macros need not be invoked explicitly.
8dnl Invoking them does nothing except to declare default arguments
9dnl for "gnulib-tool --import".
10
11dnl Usage: gl_MODULES([module1 module2 ...])
12AC_DEFUN([gl_MODULES], [])
13
14dnl Usage: gl_AVOID([module1 module2 ...])
15AC_DEFUN([gl_AVOID], [])
16
17dnl Usage: gl_SOURCE_BASE([DIR])
18AC_DEFUN([gl_SOURCE_BASE], [])
19
20dnl Usage: gl_M4_BASE([DIR])
21AC_DEFUN([gl_M4_BASE], [])
22
23dnl Usage: gl_LIB([LIBNAME])
24AC_DEFUN([gl_LIB], [])
25
26dnl Usage: gl_LGPL
27AC_DEFUN([gl_LGPL], [])
28
29dnl Usage: gl_LIBTOOL
30AC_DEFUN([gl_LIBTOOL], [])
31
32dnl Usage: gl_MACRO_PREFIX([PREFIX])
33AC_DEFUN([gl_MACRO_PREFIX], [])
diff --git a/gl/m4/iconv.m4 b/gl/m4/iconv.m4
new file mode 100644
index 00000000..654c4158
--- /dev/null
+++ b/gl/m4/iconv.m4
@@ -0,0 +1,101 @@
1# iconv.m4 serial AM4 (gettext-0.11.3)
2dnl Copyright (C) 2000-2002 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
7dnl From Bruno Haible.
8
9AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
10[
11 dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
12 AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
13 AC_REQUIRE([AC_LIB_RPATH])
14
15 dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
16 dnl accordingly.
17 AC_LIB_LINKFLAGS_BODY([iconv])
18])
19
20AC_DEFUN([AM_ICONV_LINK],
21[
22 dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
23 dnl those with the standalone portable GNU libiconv installed).
24
25 dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
26 dnl accordingly.
27 AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
28
29 dnl Add $INCICONV to CPPFLAGS before performing the following checks,
30 dnl because if the user has installed libiconv and not disabled its use
31 dnl via --without-libiconv-prefix, he wants to use it. The first
32 dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
33 am_save_CPPFLAGS="$CPPFLAGS"
34 AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
35
36 AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
37 am_cv_func_iconv="no, consider installing GNU libiconv"
38 am_cv_lib_iconv=no
39 AC_TRY_LINK([#include <stdlib.h>
40#include <iconv.h>],
41 [iconv_t cd = iconv_open("","");
42 iconv(cd,NULL,NULL,NULL,NULL);
43 iconv_close(cd);],
44 am_cv_func_iconv=yes)
45 if test "$am_cv_func_iconv" != yes; then
46 am_save_LIBS="$LIBS"
47 LIBS="$LIBS $LIBICONV"
48 AC_TRY_LINK([#include <stdlib.h>
49#include <iconv.h>],
50 [iconv_t cd = iconv_open("","");
51 iconv(cd,NULL,NULL,NULL,NULL);
52 iconv_close(cd);],
53 am_cv_lib_iconv=yes
54 am_cv_func_iconv=yes)
55 LIBS="$am_save_LIBS"
56 fi
57 ])
58 if test "$am_cv_func_iconv" = yes; then
59 AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
60 fi
61 if test "$am_cv_lib_iconv" = yes; then
62 AC_MSG_CHECKING([how to link with libiconv])
63 AC_MSG_RESULT([$LIBICONV])
64 else
65 dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
66 dnl either.
67 CPPFLAGS="$am_save_CPPFLAGS"
68 LIBICONV=
69 LTLIBICONV=
70 fi
71 AC_SUBST(LIBICONV)
72 AC_SUBST(LTLIBICONV)
73])
74
75AC_DEFUN([AM_ICONV],
76[
77 AM_ICONV_LINK
78 if test "$am_cv_func_iconv" = yes; then
79 AC_MSG_CHECKING([for iconv declaration])
80 AC_CACHE_VAL(am_cv_proto_iconv, [
81 AC_TRY_COMPILE([
82#include <stdlib.h>
83#include <iconv.h>
84extern
85#ifdef __cplusplus
86"C"
87#endif
88#if defined(__STDC__) || defined(__cplusplus)
89size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
90#else
91size_t iconv();
92#endif
93], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
94 am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
95 am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
96 AC_MSG_RESULT([$]{ac_t:-
97 }[$]am_cv_proto_iconv)
98 AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
99 [Define as const if the declaration of iconv() needs const.])
100 fi
101])
diff --git a/gl/m4/inet_ntop.m4 b/gl/m4/inet_ntop.m4
new file mode 100644
index 00000000..bb02d229
--- /dev/null
+++ b/gl/m4/inet_ntop.m4
@@ -0,0 +1,19 @@
1# inet_ntop.m4 serial 3
2dnl Copyright (C) 2005, 2006 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_INET_NTOP],
8[
9 AC_REPLACE_FUNCS(inet_ntop)
10 gl_PREREQ_INET_NTOP
11])
12
13# Prerequisites of lib/inet_ntop.h and lib/inet_ntop.c.
14AC_DEFUN([gl_PREREQ_INET_NTOP], [
15 AC_CHECK_HEADERS_ONCE([netinet/in.h arpa/inet.h])
16 AC_CHECK_DECLS([inet_ntop],,,[#include <arpa/inet.h>])
17 AC_REQUIRE([gl_SOCKET_FAMILIES])
18 AC_REQUIRE([AC_C_RESTRICT])
19])
diff --git a/gl/m4/inline.m4 b/gl/m4/inline.m4
new file mode 100644
index 00000000..a07076cd
--- /dev/null
+++ b/gl/m4/inline.m4
@@ -0,0 +1,40 @@
1# inline.m4 serial 3
2dnl Copyright (C) 2006 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
7dnl Test for the 'inline' keyword or equivalent.
8dnl Define 'inline' to a supported equivalent, or to nothing if not supported,
9dnl like AC_C_INLINE does. Also, define HAVE_INLINE if 'inline' or an
10dnl equivalent is effectively supported, i.e. if the compiler is likely to
11dnl drop unused 'static inline' functions.
12AC_DEFUN([gl_INLINE],
13[
14 AC_REQUIRE([AC_C_INLINE])
15 AC_CACHE_CHECK([whether the compiler generally respects inline],
16 [gl_cv_c_inline_effective],
17 [if test $ac_cv_c_inline = no; then
18 gl_cv_c_inline_effective=no
19 else
20 dnl GCC defines __NO_INLINE__ if not optimizing or if -fno-inline is
21 dnl specified.
22 dnl Use AC_COMPILE_IFELSE here, not AC_EGREP_CPP, because the result
23 dnl depends on optimization flags, which can be in CFLAGS.
24 dnl (AC_EGREP_CPP looks only at the CPPFLAGS.)
25 AC_COMPILE_IFELSE(
26 [AC_LANG_PROGRAM([[]],
27 [[#ifdef __NO_INLINE__
28 #error "inline is not effective"
29 #endif]])],
30 [gl_cv_c_inline_effective=yes],
31 [gl_cv_c_inline_effective=no])
32 fi
33 ])
34 if test $gl_cv_c_inline_effective = yes; then
35 AC_DEFINE([HAVE_INLINE], 1,
36 [Define to 1 if the compiler supports one of the keywords
37 'inline', '__inline__', '__inline' and effectively inlines
38 functions marked as such.])
39 fi
40])
diff --git a/gl/m4/intdiv0.m4 b/gl/m4/intdiv0.m4
new file mode 100644
index 00000000..b8d78176
--- /dev/null
+++ b/gl/m4/intdiv0.m4
@@ -0,0 +1,70 @@
1# intdiv0.m4 serial 1 (gettext-0.11.3)
2dnl Copyright (C) 2002 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
7dnl From Bruno Haible.
8
9AC_DEFUN([gt_INTDIV0],
10[
11 AC_REQUIRE([AC_PROG_CC])dnl
12 AC_REQUIRE([AC_CANONICAL_HOST])dnl
13
14 AC_CACHE_CHECK([whether integer division by zero raises SIGFPE],
15 gt_cv_int_divbyzero_sigfpe,
16 [
17 AC_TRY_RUN([
18#include <stdlib.h>
19#include <signal.h>
20
21static void
22#ifdef __cplusplus
23sigfpe_handler (int sig)
24#else
25sigfpe_handler (sig) int sig;
26#endif
27{
28 /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */
29 exit (sig != SIGFPE);
30}
31
32int x = 1;
33int y = 0;
34int z;
35int nan;
36
37int main ()
38{
39 signal (SIGFPE, sigfpe_handler);
40/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */
41#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP)
42 signal (SIGTRAP, sigfpe_handler);
43#endif
44/* Linux/SPARC yields signal SIGILL. */
45#if defined (__sparc__) && defined (__linux__)
46 signal (SIGILL, sigfpe_handler);
47#endif
48
49 z = x / y;
50 nan = y / y;
51 exit (1);
52}
53], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no,
54 [
55 # Guess based on the CPU.
56 case "$host_cpu" in
57 alpha* | i[34567]86 | m68k | s390*)
58 gt_cv_int_divbyzero_sigfpe="guessing yes";;
59 *)
60 gt_cv_int_divbyzero_sigfpe="guessing no";;
61 esac
62 ])
63 ])
64 case "$gt_cv_int_divbyzero_sigfpe" in
65 *yes) value=1;;
66 *) value=0;;
67 esac
68 AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value,
69 [Define if integer division by zero raises signal SIGFPE.])
70])
diff --git a/gl/m4/intl.m4 b/gl/m4/intl.m4
new file mode 100644
index 00000000..dcefb118
--- /dev/null
+++ b/gl/m4/intl.m4
@@ -0,0 +1,259 @@
1# intl.m4 serial 3 (gettext-0.16)
2dnl Copyright (C) 1995-2006 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
18dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006.
19
20AC_PREREQ(2.52)
21
22dnl Checks for all prerequisites of the intl subdirectory,
23dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS,
24dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL.
25AC_DEFUN([AM_INTL_SUBDIR],
26[
27 AC_REQUIRE([AC_PROG_INSTALL])dnl
28 AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
29 AC_REQUIRE([AC_PROG_CC])dnl
30 AC_REQUIRE([AC_CANONICAL_HOST])dnl
31 AC_REQUIRE([gt_GLIBC2])dnl
32 AC_REQUIRE([AC_PROG_RANLIB])dnl
33 AC_REQUIRE([gl_VISIBILITY])dnl
34 AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl
35 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl
36 AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl
37 AC_REQUIRE([gt_TYPE_WCHAR_T])dnl
38 AC_REQUIRE([gt_TYPE_WINT_T])dnl
39 AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
40 AC_REQUIRE([gt_TYPE_INTMAX_T])
41 AC_REQUIRE([gt_PRINTF_POSIX])
42 AC_REQUIRE([gl_GLIBC21])dnl
43 AC_REQUIRE([gl_XSIZE])dnl
44 AC_REQUIRE([gt_INTL_MACOSX])dnl
45
46 AC_CHECK_TYPE([ptrdiff_t], ,
47 [AC_DEFINE([ptrdiff_t], [long],
48 [Define as the type of the result of subtracting two pointers, if the system doesn't define it.])
49 ])
50 AC_CHECK_HEADERS([stddef.h stdlib.h string.h])
51 AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen])
52
53 dnl Use the _snprintf function only if it is declared (because on NetBSD it
54 dnl is defined as a weak alias of snprintf; we prefer to use the latter).
55 gt_CHECK_DECL(_snprintf, [#include <stdio.h>])
56 gt_CHECK_DECL(_snwprintf, [#include <stdio.h>])
57
58 dnl Use the *_unlocked functions only if they are declared.
59 dnl (because some of them were defined without being declared in Solaris
60 dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built
61 dnl on Solaris 2.5.1 to run on Solaris 2.6).
62 dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13.
63 gt_CHECK_DECL(getc_unlocked, [#include <stdio.h>])
64
65 case $gt_cv_func_printf_posix in
66 *yes) HAVE_POSIX_PRINTF=1 ;;
67 *) HAVE_POSIX_PRINTF=0 ;;
68 esac
69 AC_SUBST([HAVE_POSIX_PRINTF])
70 if test "$ac_cv_func_asprintf" = yes; then
71 HAVE_ASPRINTF=1
72 else
73 HAVE_ASPRINTF=0
74 fi
75 AC_SUBST([HAVE_ASPRINTF])
76 if test "$ac_cv_func_snprintf" = yes; then
77 HAVE_SNPRINTF=1
78 else
79 HAVE_SNPRINTF=0
80 fi
81 AC_SUBST([HAVE_SNPRINTF])
82 if test "$ac_cv_func_wprintf" = yes; then
83 HAVE_WPRINTF=1
84 else
85 HAVE_WPRINTF=0
86 fi
87 AC_SUBST([HAVE_WPRINTF])
88
89 AM_LANGINFO_CODESET
90 gt_LC_MESSAGES
91
92 dnl Compilation on mingw and Cygwin needs special Makefile rules, because
93 dnl 1. when we install a shared library, we must arrange to export
94 dnl auxiliary pointer variables for every exported variable,
95 dnl 2. when we install a shared library and a static library simultaneously,
96 dnl the include file specifies __declspec(dllimport) and therefore we
97 dnl must arrange to define the auxiliary pointer variables for the
98 dnl exported variables _also_ in the static library.
99 if test "$enable_shared" = yes; then
100 case "$host_os" in
101 cygwin*) is_woe32dll=yes ;;
102 *) is_woe32dll=no ;;
103 esac
104 else
105 is_woe32dll=no
106 fi
107 WOE32DLL=$is_woe32dll
108 AC_SUBST([WOE32DLL])
109
110 dnl Rename some macros and functions used for locking.
111 AH_BOTTOM([
112#define __libc_lock_t gl_lock_t
113#define __libc_lock_define gl_lock_define
114#define __libc_lock_define_initialized gl_lock_define_initialized
115#define __libc_lock_init gl_lock_init
116#define __libc_lock_lock gl_lock_lock
117#define __libc_lock_unlock gl_lock_unlock
118#define __libc_lock_recursive_t gl_recursive_lock_t
119#define __libc_lock_define_recursive gl_recursive_lock_define
120#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized
121#define __libc_lock_init_recursive gl_recursive_lock_init
122#define __libc_lock_lock_recursive gl_recursive_lock_lock
123#define __libc_lock_unlock_recursive gl_recursive_lock_unlock
124#define glthread_in_use libintl_thread_in_use
125#define glthread_lock_init libintl_lock_init
126#define glthread_lock_lock libintl_lock_lock
127#define glthread_lock_unlock libintl_lock_unlock
128#define glthread_lock_destroy libintl_lock_destroy
129#define glthread_rwlock_init libintl_rwlock_init
130#define glthread_rwlock_rdlock libintl_rwlock_rdlock
131#define glthread_rwlock_wrlock libintl_rwlock_wrlock
132#define glthread_rwlock_unlock libintl_rwlock_unlock
133#define glthread_rwlock_destroy libintl_rwlock_destroy
134#define glthread_recursive_lock_init libintl_recursive_lock_init
135#define glthread_recursive_lock_lock libintl_recursive_lock_lock
136#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock
137#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy
138#define glthread_once libintl_once
139#define glthread_once_call libintl_once_call
140#define glthread_once_singlethreaded libintl_once_singlethreaded
141])
142])
143
144
145dnl Checks for the core files of the intl subdirectory:
146dnl dcigettext.c
147dnl eval-plural.h
148dnl explodename.c
149dnl finddomain.c
150dnl gettextP.h
151dnl gmo.h
152dnl hash-string.h hash-string.c
153dnl l10nflist.c
154dnl libgnuintl.h.in (except the *printf stuff)
155dnl loadinfo.h
156dnl loadmsgcat.c
157dnl localealias.c
158dnl log.c
159dnl plural-exp.h plural-exp.c
160dnl plural.y
161dnl Used by libglocale.
162AC_DEFUN([gt_INTL_SUBDIR_CORE],
163[
164 AC_REQUIRE([AC_C_INLINE])dnl
165 AC_REQUIRE([AC_TYPE_SIZE_T])dnl
166 AC_REQUIRE([gl_AC_HEADER_STDINT_H])
167 AC_REQUIRE([AC_FUNC_ALLOCA])dnl
168 AC_REQUIRE([AC_FUNC_MMAP])dnl
169 AC_REQUIRE([gt_INTDIV0])dnl
170 AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl
171 AC_REQUIRE([gt_INTTYPES_PRI])dnl
172 AC_REQUIRE([gl_LOCK])dnl
173
174 AC_TRY_LINK(
175 [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }],
176 [],
177 [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1,
178 [Define to 1 if the compiler understands __builtin_expect.])])
179
180 AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h])
181 AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \
182 stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \
183 argz_next __fsetlocking])
184
185 dnl Use the *_unlocked functions only if they are declared.
186 dnl (because some of them were defined without being declared in Solaris
187 dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built
188 dnl on Solaris 2.5.1 to run on Solaris 2.6).
189 dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13.
190 gt_CHECK_DECL(feof_unlocked, [#include <stdio.h>])
191 gt_CHECK_DECL(fgets_unlocked, [#include <stdio.h>])
192
193 AM_ICONV
194
195 dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined,
196 dnl and a _NL_LOCALE_NAME macro always.
197 AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name,
198 [AC_TRY_LINK([#include <langinfo.h>
199#include <locale.h>],
200 [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES));],
201 gt_cv_nl_locale_name=yes,
202 gt_cv_nl_locale_name=no)
203 ])
204 if test $gt_cv_nl_locale_name = yes; then
205 AC_DEFINE(HAVE_NL_LOCALE_NAME, 1,
206 [Define if you have <langinfo.h> and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.])
207 fi
208
209 dnl intl/plural.c is generated from intl/plural.y. It requires bison,
210 dnl because plural.y uses bison specific features. It requires at least
211 dnl bison-1.26 because earlier versions generate a plural.c that doesn't
212 dnl compile.
213 dnl bison is only needed for the maintainer (who touches plural.y). But in
214 dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put
215 dnl the rule in general Makefile. Now, some people carelessly touch the
216 dnl files or have a broken "make" program, hence the plural.c rule will
217 dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not
218 dnl present or too old.
219 AC_CHECK_PROGS([INTLBISON], [bison])
220 if test -z "$INTLBISON"; then
221 ac_verc_fail=yes
222 else
223 dnl Found it, now check the version.
224 AC_MSG_CHECKING([version of bison])
225changequote(<<,>>)dnl
226 ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
227 case $ac_prog_version in
228 '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
229 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*)
230changequote([,])dnl
231 ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
232 *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
233 esac
234 AC_MSG_RESULT([$ac_prog_version])
235 fi
236 if test $ac_verc_fail = yes; then
237 INTLBISON=:
238 fi
239])
240
241
242dnl gt_CHECK_DECL(FUNC, INCLUDES)
243dnl Check whether a function is declared.
244AC_DEFUN([gt_CHECK_DECL],
245[
246 AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1,
247 [AC_TRY_COMPILE([$2], [
248#ifndef $1
249 char *p = (char *) $1;
250#endif
251], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)])
252 if test $ac_cv_have_decl_$1 = yes; then
253 gt_value=1
254 else
255 gt_value=0
256 fi
257 AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value],
258 [Define to 1 if you have the declaration of `$1', and to 0 if you don't.])
259])
diff --git a/gl/m4/intldir.m4 b/gl/m4/intldir.m4
new file mode 100644
index 00000000..7a28843f
--- /dev/null
+++ b/gl/m4/intldir.m4
@@ -0,0 +1,19 @@
1# intldir.m4 serial 1 (gettext-0.16)
2dnl Copyright (C) 2006 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16AC_PREREQ(2.52)
17
18dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory.
19AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], [])
diff --git a/gl/m4/intmax.m4 b/gl/m4/intmax.m4
new file mode 100644
index 00000000..ce7a8a49
--- /dev/null
+++ b/gl/m4/intmax.m4
@@ -0,0 +1,33 @@
1# intmax.m4 serial 3 (gettext-0.16)
2dnl Copyright (C) 2002-2005 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
7dnl From Bruno Haible.
8dnl Test whether the system has the 'intmax_t' type, but don't attempt to
9dnl find a replacement if it is lacking.
10
11AC_DEFUN([gt_TYPE_INTMAX_T],
12[
13 AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
14 AC_REQUIRE([gl_AC_HEADER_STDINT_H])
15 AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t,
16 [AC_TRY_COMPILE([
17#include <stddef.h>
18#include <stdlib.h>
19#if HAVE_STDINT_H_WITH_UINTMAX
20#include <stdint.h>
21#endif
22#if HAVE_INTTYPES_H_WITH_UINTMAX
23#include <inttypes.h>
24#endif
25], [intmax_t x = -1;
26 return !x;],
27 gt_cv_c_intmax_t=yes,
28 gt_cv_c_intmax_t=no)])
29 if test $gt_cv_c_intmax_t = yes; then
30 AC_DEFINE(HAVE_INTMAX_T, 1,
31 [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
32 fi
33])
diff --git a/gl/m4/intmax_t.m4 b/gl/m4/intmax_t.m4
new file mode 100644
index 00000000..17c7b0ae
--- /dev/null
+++ b/gl/m4/intmax_t.m4
@@ -0,0 +1,61 @@
1# intmax_t.m4 serial 5
2dnl Copyright (C) 1997-2004, 2006 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
7dnl From Paul Eggert.
8
9AC_PREREQ(2.13)
10
11# Define intmax_t to 'long' or 'long long'
12# if it is not already defined in <stdint.h> or <inttypes.h>.
13
14AC_DEFUN([gl_AC_TYPE_INTMAX_T],
15[
16 dnl For simplicity, we assume that a header file defines 'intmax_t' if and
17 dnl only if it defines 'uintmax_t'.
18 AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
19 AC_REQUIRE([gl_AC_HEADER_STDINT_H])
20 if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then
21 AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
22 test $ac_cv_type_long_long = yes \
23 && ac_type='long long' \
24 || ac_type='long'
25 AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
26 [Define to long or long long if <inttypes.h> and <stdint.h> don't define.])
27 else
28 AC_DEFINE(HAVE_INTMAX_T, 1,
29 [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
30 fi
31])
32
33dnl An alternative would be to explicitly test for 'intmax_t'.
34
35AC_DEFUN([gt_AC_TYPE_INTMAX_T],
36[
37 AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
38 AC_REQUIRE([gl_AC_HEADER_STDINT_H])
39 AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t,
40 [AC_TRY_COMPILE([
41#include <stddef.h>
42#include <stdlib.h>
43#if HAVE_STDINT_H_WITH_UINTMAX
44#include <stdint.h>
45#endif
46#if HAVE_INTTYPES_H_WITH_UINTMAX
47#include <inttypes.h>
48#endif
49], [intmax_t x = -1; return !x;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)])
50 if test $gt_cv_c_intmax_t = yes; then
51 AC_DEFINE(HAVE_INTMAX_T, 1,
52 [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
53 else
54 AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
55 test $ac_cv_type_long_long = yes \
56 && ac_type='long long' \
57 || ac_type='long'
58 AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
59 [Define to long or long long if <stdint.h> and <inttypes.h> don't define.])
60 fi
61])
diff --git a/gl/m4/inttypes-pri.m4 b/gl/m4/inttypes-pri.m4
new file mode 100644
index 00000000..7c7f8940
--- /dev/null
+++ b/gl/m4/inttypes-pri.m4
@@ -0,0 +1,36 @@
1# inttypes-pri.m4 serial 4 (gettext-0.16)
2dnl Copyright (C) 1997-2002, 2006 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
7dnl From Bruno Haible.
8
9AC_PREREQ(2.52)
10
11# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI*
12# macros to non-string values. This is the case on AIX 4.3.3.
13
14AC_DEFUN([gt_INTTYPES_PRI],
15[
16 AC_CHECK_HEADERS([inttypes.h])
17 if test $ac_cv_header_inttypes_h = yes; then
18 AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken],
19 gt_cv_inttypes_pri_broken,
20 [
21 AC_TRY_COMPILE([#include <inttypes.h>
22#ifdef PRId32
23char *p = PRId32;
24#endif
25], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes)
26 ])
27 fi
28 if test "$gt_cv_inttypes_pri_broken" = yes; then
29 AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1,
30 [Define if <inttypes.h> exists and defines unusable PRI* macros.])
31 PRI_MACROS_BROKEN=1
32 else
33 PRI_MACROS_BROKEN=0
34 fi
35 AC_SUBST([PRI_MACROS_BROKEN])
36])
diff --git a/gl/m4/inttypes_h.m4 b/gl/m4/inttypes_h.m4
new file mode 100644
index 00000000..edc8ecb2
--- /dev/null
+++ b/gl/m4/inttypes_h.m4
@@ -0,0 +1,26 @@
1# inttypes_h.m4 serial 7
2dnl Copyright (C) 1997-2004, 2006 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
7dnl From Paul Eggert.
8
9# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
10# doesn't clash with <sys/types.h>, and declares uintmax_t.
11
12AC_DEFUN([gl_AC_HEADER_INTTYPES_H],
13[
14 AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h,
15 [AC_TRY_COMPILE(
16 [#include <sys/types.h>
17#include <inttypes.h>],
18 [uintmax_t i = (uintmax_t) -1; return !i;],
19 gl_cv_header_inttypes_h=yes,
20 gl_cv_header_inttypes_h=no)])
21 if test $gl_cv_header_inttypes_h = yes; then
22 AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1,
23 [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
24 and declares uintmax_t. ])
25 fi
26])
diff --git a/gl/m4/lcmessage.m4 b/gl/m4/lcmessage.m4
new file mode 100644
index 00000000..19aa77e4
--- /dev/null
+++ b/gl/m4/lcmessage.m4
@@ -0,0 +1,30 @@
1# lcmessage.m4 serial 4 (gettext-0.14.2)
2dnl Copyright (C) 1995-2002, 2004-2005 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1995.
18
19# Check whether LC_MESSAGES is available in <locale.h>.
20
21AC_DEFUN([gt_LC_MESSAGES],
22[
23 AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES,
24 [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
25 gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)])
26 if test $gt_cv_val_LC_MESSAGES = yes; then
27 AC_DEFINE(HAVE_LC_MESSAGES, 1,
28 [Define if your <locale.h> file defines LC_MESSAGES.])
29 fi
30])
diff --git a/gl/m4/lib-ld.m4 b/gl/m4/lib-ld.m4
new file mode 100644
index 00000000..96c4e2c3
--- /dev/null
+++ b/gl/m4/lib-ld.m4
@@ -0,0 +1,110 @@
1# lib-ld.m4 serial 3 (gettext-0.13)
2dnl Copyright (C) 1996-2003 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
7dnl Subroutines of libtool.m4,
8dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
9dnl with libtool.m4.
10
11dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
12AC_DEFUN([AC_LIB_PROG_LD_GNU],
13[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
14[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
15case `$LD -v 2>&1 </dev/null` in
16*GNU* | *'with BFD'*)
17 acl_cv_prog_gnu_ld=yes ;;
18*)
19 acl_cv_prog_gnu_ld=no ;;
20esac])
21with_gnu_ld=$acl_cv_prog_gnu_ld
22])
23
24dnl From libtool-1.4. Sets the variable LD.
25AC_DEFUN([AC_LIB_PROG_LD],
26[AC_ARG_WITH(gnu-ld,
27[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
28test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
29AC_REQUIRE([AC_PROG_CC])dnl
30AC_REQUIRE([AC_CANONICAL_HOST])dnl
31# Prepare PATH_SEPARATOR.
32# The user is always right.
33if test "${PATH_SEPARATOR+set}" != set; then
34 echo "#! /bin/sh" >conf$$.sh
35 echo "exit 0" >>conf$$.sh
36 chmod +x conf$$.sh
37 if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
38 PATH_SEPARATOR=';'
39 else
40 PATH_SEPARATOR=:
41 fi
42 rm -f conf$$.sh
43fi
44ac_prog=ld
45if test "$GCC" = yes; then
46 # Check if gcc -print-prog-name=ld gives a path.
47 AC_MSG_CHECKING([for ld used by GCC])
48 case $host in
49 *-*-mingw*)
50 # gcc leaves a trailing carriage return which upsets mingw
51 ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
52 *)
53 ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
54 esac
55 case $ac_prog in
56 # Accept absolute paths.
57 [[\\/]* | [A-Za-z]:[\\/]*)]
58 [re_direlt='/[^/][^/]*/\.\./']
59 # Canonicalize the path of ld
60 ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
61 while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
62 ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
63 done
64 test -z "$LD" && LD="$ac_prog"
65 ;;
66 "")
67 # If it fails, then pretend we aren't using GCC.
68 ac_prog=ld
69 ;;
70 *)
71 # If it is relative, then search for the first ld in PATH.
72 with_gnu_ld=unknown
73 ;;
74 esac
75elif test "$with_gnu_ld" = yes; then
76 AC_MSG_CHECKING([for GNU ld])
77else
78 AC_MSG_CHECKING([for non-GNU ld])
79fi
80AC_CACHE_VAL(acl_cv_path_LD,
81[if test -z "$LD"; then
82 IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
83 for ac_dir in $PATH; do
84 test -z "$ac_dir" && ac_dir=.
85 if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
86 acl_cv_path_LD="$ac_dir/$ac_prog"
87 # Check to see if the program is GNU ld. I'd rather use --version,
88 # but apparently some GNU ld's only accept -v.
89 # Break only if it was the GNU/non-GNU ld that we prefer.
90 case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
91 *GNU* | *'with BFD'*)
92 test "$with_gnu_ld" != no && break ;;
93 *)
94 test "$with_gnu_ld" != yes && break ;;
95 esac
96 fi
97 done
98 IFS="$ac_save_ifs"
99else
100 acl_cv_path_LD="$LD" # Let the user override the test with a path.
101fi])
102LD="$acl_cv_path_LD"
103if test -n "$LD"; then
104 AC_MSG_RESULT($LD)
105else
106 AC_MSG_RESULT(no)
107fi
108test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
109AC_LIB_PROG_LD_GNU
110])
diff --git a/gl/m4/lib-link.m4 b/gl/m4/lib-link.m4
new file mode 100644
index 00000000..f157d983
--- /dev/null
+++ b/gl/m4/lib-link.m4
@@ -0,0 +1,709 @@
1# lib-link.m4 serial 13 (gettext-0.16.2)
2dnl Copyright (C) 2001-2007 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
7dnl From Bruno Haible.
8
9AC_PREREQ(2.54)
10
11dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
12dnl the libraries corresponding to explicit and implicit dependencies.
13dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
14dnl augments the CPPFLAGS variable.
15dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
16dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
17AC_DEFUN([AC_LIB_LINKFLAGS],
18[
19 AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
20 AC_REQUIRE([AC_LIB_RPATH])
21 define([Name],[translit([$1],[./-], [___])])
22 define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
23 [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
24 AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
25 AC_LIB_LINKFLAGS_BODY([$1], [$2])
26 ac_cv_lib[]Name[]_libs="$LIB[]NAME"
27 ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
28 ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
29 ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
30 ])
31 LIB[]NAME="$ac_cv_lib[]Name[]_libs"
32 LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
33 INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
34 LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
35 AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
36 AC_SUBST([LIB]NAME)
37 AC_SUBST([LTLIB]NAME)
38 AC_SUBST([LIB]NAME[_PREFIX])
39 dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
40 dnl results of this search when this library appears as a dependency.
41 HAVE_LIB[]NAME=yes
42 undefine([Name])
43 undefine([NAME])
44])
45
46dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
47dnl searches for libname and the libraries corresponding to explicit and
48dnl implicit dependencies, together with the specified include files and
49dnl the ability to compile and link the specified testcode. If found, it
50dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
51dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
52dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
53dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
54dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
55dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
56AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
57[
58 AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
59 AC_REQUIRE([AC_LIB_RPATH])
60 define([Name],[translit([$1],[./-], [___])])
61 define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
62 [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
63
64 dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
65 dnl accordingly.
66 AC_LIB_LINKFLAGS_BODY([$1], [$2])
67
68 dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
69 dnl because if the user has installed lib[]Name and not disabled its use
70 dnl via --without-lib[]Name-prefix, he wants to use it.
71 ac_save_CPPFLAGS="$CPPFLAGS"
72 AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
73
74 AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
75 ac_save_LIBS="$LIBS"
76 LIBS="$LIBS $LIB[]NAME"
77 AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
78 LIBS="$ac_save_LIBS"
79 ])
80 if test "$ac_cv_lib[]Name" = yes; then
81 HAVE_LIB[]NAME=yes
82 AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
83 AC_MSG_CHECKING([how to link with lib[]$1])
84 AC_MSG_RESULT([$LIB[]NAME])
85 else
86 HAVE_LIB[]NAME=no
87 dnl If $LIB[]NAME didn't lead to a usable library, we don't need
88 dnl $INC[]NAME either.
89 CPPFLAGS="$ac_save_CPPFLAGS"
90 LIB[]NAME=
91 LTLIB[]NAME=
92 LIB[]NAME[]_PREFIX=
93 fi
94 AC_SUBST([HAVE_LIB]NAME)
95 AC_SUBST([LIB]NAME)
96 AC_SUBST([LTLIB]NAME)
97 AC_SUBST([LIB]NAME[_PREFIX])
98 undefine([Name])
99 undefine([NAME])
100])
101
102dnl Determine the platform dependent parameters needed to use rpath:
103dnl acl_libext,
104dnl acl_shlibext,
105dnl acl_hardcode_libdir_flag_spec,
106dnl acl_hardcode_libdir_separator,
107dnl acl_hardcode_direct,
108dnl acl_hardcode_minus_L.
109AC_DEFUN([AC_LIB_RPATH],
110[
111 dnl Tell automake >= 1.10 to complain if config.rpath is missing.
112 m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
113 AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
114 AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
115 AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
116 AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
117 AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
118 CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
119 ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
120 . ./conftest.sh
121 rm -f ./conftest.sh
122 acl_cv_rpath=done
123 ])
124 wl="$acl_cv_wl"
125 acl_libext="$acl_cv_libext"
126 acl_shlibext="$acl_cv_shlibext"
127 acl_libname_spec="$acl_cv_libname_spec"
128 acl_library_names_spec="$acl_cv_library_names_spec"
129 acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
130 acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
131 acl_hardcode_direct="$acl_cv_hardcode_direct"
132 acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
133 dnl Determine whether the user wants rpath handling at all.
134 AC_ARG_ENABLE(rpath,
135 [ --disable-rpath do not hardcode runtime library paths],
136 :, enable_rpath=yes)
137])
138
139dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
140dnl the libraries corresponding to explicit and implicit dependencies.
141dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
142dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
143dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
144AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
145[
146 AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
147 define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
148 [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
149 dnl Autoconf >= 2.61 supports dots in --with options.
150 define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])])
151 dnl By default, look in $includedir and $libdir.
152 use_additional=yes
153 AC_LIB_WITH_FINAL_PREFIX([
154 eval additional_includedir=\"$includedir\"
155 eval additional_libdir=\"$libdir\"
156 ])
157 AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix],
158[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
159 --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir],
160[
161 if test "X$withval" = "Xno"; then
162 use_additional=no
163 else
164 if test "X$withval" = "X"; then
165 AC_LIB_WITH_FINAL_PREFIX([
166 eval additional_includedir=\"$includedir\"
167 eval additional_libdir=\"$libdir\"
168 ])
169 else
170 additional_includedir="$withval/include"
171 additional_libdir="$withval/$acl_libdirstem"
172 fi
173 fi
174])
175 dnl Search the library and its dependencies in $additional_libdir and
176 dnl $LDFLAGS. Using breadth-first-seach.
177 LIB[]NAME=
178 LTLIB[]NAME=
179 INC[]NAME=
180 LIB[]NAME[]_PREFIX=
181 rpathdirs=
182 ltrpathdirs=
183 names_already_handled=
184 names_next_round='$1 $2'
185 while test -n "$names_next_round"; do
186 names_this_round="$names_next_round"
187 names_next_round=
188 for name in $names_this_round; do
189 already_handled=
190 for n in $names_already_handled; do
191 if test "$n" = "$name"; then
192 already_handled=yes
193 break
194 fi
195 done
196 if test -z "$already_handled"; then
197 names_already_handled="$names_already_handled $name"
198 dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
199 dnl or AC_LIB_HAVE_LINKFLAGS call.
200 uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
201 eval value=\"\$HAVE_LIB$uppername\"
202 if test -n "$value"; then
203 if test "$value" = yes; then
204 eval value=\"\$LIB$uppername\"
205 test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
206 eval value=\"\$LTLIB$uppername\"
207 test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
208 else
209 dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
210 dnl that this library doesn't exist. So just drop it.
211 :
212 fi
213 else
214 dnl Search the library lib$name in $additional_libdir and $LDFLAGS
215 dnl and the already constructed $LIBNAME/$LTLIBNAME.
216 found_dir=
217 found_la=
218 found_so=
219 found_a=
220 eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
221 if test -n "$acl_shlibext"; then
222 shrext=".$acl_shlibext" # typically: shrext=.so
223 else
224 shrext=
225 fi
226 if test $use_additional = yes; then
227 dir="$additional_libdir"
228 dnl The same code as in the loop below:
229 dnl First look for a shared library.
230 if test -n "$acl_shlibext"; then
231 if test -f "$dir/$libname$shrext"; then
232 found_dir="$dir"
233 found_so="$dir/$libname$shrext"
234 else
235 if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
236 ver=`(cd "$dir" && \
237 for f in "$libname$shrext".*; do echo "$f"; done \
238 | sed -e "s,^$libname$shrext\\\\.,," \
239 | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
240 | sed 1q ) 2>/dev/null`
241 if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
242 found_dir="$dir"
243 found_so="$dir/$libname$shrext.$ver"
244 fi
245 else
246 eval library_names=\"$acl_library_names_spec\"
247 for f in $library_names; do
248 if test -f "$dir/$f"; then
249 found_dir="$dir"
250 found_so="$dir/$f"
251 break
252 fi
253 done
254 fi
255 fi
256 fi
257 dnl Then look for a static library.
258 if test "X$found_dir" = "X"; then
259 if test -f "$dir/$libname.$acl_libext"; then
260 found_dir="$dir"
261 found_a="$dir/$libname.$acl_libext"
262 fi
263 fi
264 if test "X$found_dir" != "X"; then
265 if test -f "$dir/$libname.la"; then
266 found_la="$dir/$libname.la"
267 fi
268 fi
269 fi
270 if test "X$found_dir" = "X"; then
271 for x in $LDFLAGS $LTLIB[]NAME; do
272 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
273 case "$x" in
274 -L*)
275 dir=`echo "X$x" | sed -e 's/^X-L//'`
276 dnl First look for a shared library.
277 if test -n "$acl_shlibext"; then
278 if test -f "$dir/$libname$shrext"; then
279 found_dir="$dir"
280 found_so="$dir/$libname$shrext"
281 else
282 if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
283 ver=`(cd "$dir" && \
284 for f in "$libname$shrext".*; do echo "$f"; done \
285 | sed -e "s,^$libname$shrext\\\\.,," \
286 | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
287 | sed 1q ) 2>/dev/null`
288 if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
289 found_dir="$dir"
290 found_so="$dir/$libname$shrext.$ver"
291 fi
292 else
293 eval library_names=\"$acl_library_names_spec\"
294 for f in $library_names; do
295 if test -f "$dir/$f"; then
296 found_dir="$dir"
297 found_so="$dir/$f"
298 break
299 fi
300 done
301 fi
302 fi
303 fi
304 dnl Then look for a static library.
305 if test "X$found_dir" = "X"; then
306 if test -f "$dir/$libname.$acl_libext"; then
307 found_dir="$dir"
308 found_a="$dir/$libname.$acl_libext"
309 fi
310 fi
311 if test "X$found_dir" != "X"; then
312 if test -f "$dir/$libname.la"; then
313 found_la="$dir/$libname.la"
314 fi
315 fi
316 ;;
317 esac
318 if test "X$found_dir" != "X"; then
319 break
320 fi
321 done
322 fi
323 if test "X$found_dir" != "X"; then
324 dnl Found the library.
325 LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
326 if test "X$found_so" != "X"; then
327 dnl Linking with a shared library. We attempt to hardcode its
328 dnl directory into the executable's runpath, unless it's the
329 dnl standard /usr/lib.
330 if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
331 dnl No hardcoding is needed.
332 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
333 else
334 dnl Use an explicit option to hardcode DIR into the resulting
335 dnl binary.
336 dnl Potentially add DIR to ltrpathdirs.
337 dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
338 haveit=
339 for x in $ltrpathdirs; do
340 if test "X$x" = "X$found_dir"; then
341 haveit=yes
342 break
343 fi
344 done
345 if test -z "$haveit"; then
346 ltrpathdirs="$ltrpathdirs $found_dir"
347 fi
348 dnl The hardcoding into $LIBNAME is system dependent.
349 if test "$acl_hardcode_direct" = yes; then
350 dnl Using DIR/libNAME.so during linking hardcodes DIR into the
351 dnl resulting binary.
352 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
353 else
354 if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
355 dnl Use an explicit option to hardcode DIR into the resulting
356 dnl binary.
357 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
358 dnl Potentially add DIR to rpathdirs.
359 dnl The rpathdirs will be appended to $LIBNAME at the end.
360 haveit=
361 for x in $rpathdirs; do
362 if test "X$x" = "X$found_dir"; then
363 haveit=yes
364 break
365 fi
366 done
367 if test -z "$haveit"; then
368 rpathdirs="$rpathdirs $found_dir"
369 fi
370 else
371 dnl Rely on "-L$found_dir".
372 dnl But don't add it if it's already contained in the LDFLAGS
373 dnl or the already constructed $LIBNAME
374 haveit=
375 for x in $LDFLAGS $LIB[]NAME; do
376 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
377 if test "X$x" = "X-L$found_dir"; then
378 haveit=yes
379 break
380 fi
381 done
382 if test -z "$haveit"; then
383 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
384 fi
385 if test "$acl_hardcode_minus_L" != no; then
386 dnl FIXME: Not sure whether we should use
387 dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
388 dnl here.
389 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
390 else
391 dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
392 dnl here, because this doesn't fit in flags passed to the
393 dnl compiler. So give up. No hardcoding. This affects only
394 dnl very old systems.
395 dnl FIXME: Not sure whether we should use
396 dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
397 dnl here.
398 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
399 fi
400 fi
401 fi
402 fi
403 else
404 if test "X$found_a" != "X"; then
405 dnl Linking with a static library.
406 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
407 else
408 dnl We shouldn't come here, but anyway it's good to have a
409 dnl fallback.
410 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
411 fi
412 fi
413 dnl Assume the include files are nearby.
414 additional_includedir=
415 case "$found_dir" in
416 */$acl_libdirstem | */$acl_libdirstem/)
417 basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
418 LIB[]NAME[]_PREFIX="$basedir"
419 additional_includedir="$basedir/include"
420 ;;
421 esac
422 if test "X$additional_includedir" != "X"; then
423 dnl Potentially add $additional_includedir to $INCNAME.
424 dnl But don't add it
425 dnl 1. if it's the standard /usr/include,
426 dnl 2. if it's /usr/local/include and we are using GCC on Linux,
427 dnl 3. if it's already present in $CPPFLAGS or the already
428 dnl constructed $INCNAME,
429 dnl 4. if it doesn't exist as a directory.
430 if test "X$additional_includedir" != "X/usr/include"; then
431 haveit=
432 if test "X$additional_includedir" = "X/usr/local/include"; then
433 if test -n "$GCC"; then
434 case $host_os in
435 linux* | gnu* | k*bsd*-gnu) haveit=yes;;
436 esac
437 fi
438 fi
439 if test -z "$haveit"; then
440 for x in $CPPFLAGS $INC[]NAME; do
441 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
442 if test "X$x" = "X-I$additional_includedir"; then
443 haveit=yes
444 break
445 fi
446 done
447 if test -z "$haveit"; then
448 if test -d "$additional_includedir"; then
449 dnl Really add $additional_includedir to $INCNAME.
450 INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
451 fi
452 fi
453 fi
454 fi
455 fi
456 dnl Look for dependencies.
457 if test -n "$found_la"; then
458 dnl Read the .la file. It defines the variables
459 dnl dlname, library_names, old_library, dependency_libs, current,
460 dnl age, revision, installed, dlopen, dlpreopen, libdir.
461 save_libdir="$libdir"
462 case "$found_la" in
463 */* | *\\*) . "$found_la" ;;
464 *) . "./$found_la" ;;
465 esac
466 libdir="$save_libdir"
467 dnl We use only dependency_libs.
468 for dep in $dependency_libs; do
469 case "$dep" in
470 -L*)
471 additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
472 dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
473 dnl But don't add it
474 dnl 1. if it's the standard /usr/lib,
475 dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
476 dnl 3. if it's already present in $LDFLAGS or the already
477 dnl constructed $LIBNAME,
478 dnl 4. if it doesn't exist as a directory.
479 if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
480 haveit=
481 if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
482 if test -n "$GCC"; then
483 case $host_os in
484 linux* | gnu* | k*bsd*-gnu) haveit=yes;;
485 esac
486 fi
487 fi
488 if test -z "$haveit"; then
489 haveit=
490 for x in $LDFLAGS $LIB[]NAME; do
491 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
492 if test "X$x" = "X-L$additional_libdir"; then
493 haveit=yes
494 break
495 fi
496 done
497 if test -z "$haveit"; then
498 if test -d "$additional_libdir"; then
499 dnl Really add $additional_libdir to $LIBNAME.
500 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
501 fi
502 fi
503 haveit=
504 for x in $LDFLAGS $LTLIB[]NAME; do
505 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
506 if test "X$x" = "X-L$additional_libdir"; then
507 haveit=yes
508 break
509 fi
510 done
511 if test -z "$haveit"; then
512 if test -d "$additional_libdir"; then
513 dnl Really add $additional_libdir to $LTLIBNAME.
514 LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
515 fi
516 fi
517 fi
518 fi
519 ;;
520 -R*)
521 dir=`echo "X$dep" | sed -e 's/^X-R//'`
522 if test "$enable_rpath" != no; then
523 dnl Potentially add DIR to rpathdirs.
524 dnl The rpathdirs will be appended to $LIBNAME at the end.
525 haveit=
526 for x in $rpathdirs; do
527 if test "X$x" = "X$dir"; then
528 haveit=yes
529 break
530 fi
531 done
532 if test -z "$haveit"; then
533 rpathdirs="$rpathdirs $dir"
534 fi
535 dnl Potentially add DIR to ltrpathdirs.
536 dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
537 haveit=
538 for x in $ltrpathdirs; do
539 if test "X$x" = "X$dir"; then
540 haveit=yes
541 break
542 fi
543 done
544 if test -z "$haveit"; then
545 ltrpathdirs="$ltrpathdirs $dir"
546 fi
547 fi
548 ;;
549 -l*)
550 dnl Handle this in the next round.
551 names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
552 ;;
553 *.la)
554 dnl Handle this in the next round. Throw away the .la's
555 dnl directory; it is already contained in a preceding -L
556 dnl option.
557 names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
558 ;;
559 *)
560 dnl Most likely an immediate library name.
561 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
562 LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
563 ;;
564 esac
565 done
566 fi
567 else
568 dnl Didn't find the library; assume it is in the system directories
569 dnl known to the linker and runtime loader. (All the system
570 dnl directories known to the linker should also be known to the
571 dnl runtime loader, otherwise the system is severely misconfigured.)
572 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
573 LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
574 fi
575 fi
576 fi
577 done
578 done
579 if test "X$rpathdirs" != "X"; then
580 if test -n "$acl_hardcode_libdir_separator"; then
581 dnl Weird platform: only the last -rpath option counts, the user must
582 dnl pass all path elements in one option. We can arrange that for a
583 dnl single library, but not when more than one $LIBNAMEs are used.
584 alldirs=
585 for found_dir in $rpathdirs; do
586 alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
587 done
588 dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
589 acl_save_libdir="$libdir"
590 libdir="$alldirs"
591 eval flag=\"$acl_hardcode_libdir_flag_spec\"
592 libdir="$acl_save_libdir"
593 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
594 else
595 dnl The -rpath options are cumulative.
596 for found_dir in $rpathdirs; do
597 acl_save_libdir="$libdir"
598 libdir="$found_dir"
599 eval flag=\"$acl_hardcode_libdir_flag_spec\"
600 libdir="$acl_save_libdir"
601 LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
602 done
603 fi
604 fi
605 if test "X$ltrpathdirs" != "X"; then
606 dnl When using libtool, the option that works for both libraries and
607 dnl executables is -R. The -R options are cumulative.
608 for found_dir in $ltrpathdirs; do
609 LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
610 done
611 fi
612])
613
614dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
615dnl unless already present in VAR.
616dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
617dnl contains two or three consecutive elements that belong together.
618AC_DEFUN([AC_LIB_APPENDTOVAR],
619[
620 for element in [$2]; do
621 haveit=
622 for x in $[$1]; do
623 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
624 if test "X$x" = "X$element"; then
625 haveit=yes
626 break
627 fi
628 done
629 if test -z "$haveit"; then
630 [$1]="${[$1]}${[$1]:+ }$element"
631 fi
632 done
633])
634
635dnl For those cases where a variable contains several -L and -l options
636dnl referring to unknown libraries and directories, this macro determines the
637dnl necessary additional linker options for the runtime path.
638dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
639dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
640dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
641dnl otherwise linking without libtool is assumed.
642AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
643[
644 AC_REQUIRE([AC_LIB_RPATH])
645 AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
646 $1=
647 if test "$enable_rpath" != no; then
648 if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
649 dnl Use an explicit option to hardcode directories into the resulting
650 dnl binary.
651 rpathdirs=
652 next=
653 for opt in $2; do
654 if test -n "$next"; then
655 dir="$next"
656 dnl No need to hardcode the standard /usr/lib.
657 if test "X$dir" != "X/usr/$acl_libdirstem"; then
658 rpathdirs="$rpathdirs $dir"
659 fi
660 next=
661 else
662 case $opt in
663 -L) next=yes ;;
664 -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
665 dnl No need to hardcode the standard /usr/lib.
666 if test "X$dir" != "X/usr/$acl_libdirstem"; then
667 rpathdirs="$rpathdirs $dir"
668 fi
669 next= ;;
670 *) next= ;;
671 esac
672 fi
673 done
674 if test "X$rpathdirs" != "X"; then
675 if test -n ""$3""; then
676 dnl libtool is used for linking. Use -R options.
677 for dir in $rpathdirs; do
678 $1="${$1}${$1:+ }-R$dir"
679 done
680 else
681 dnl The linker is used for linking directly.
682 if test -n "$acl_hardcode_libdir_separator"; then
683 dnl Weird platform: only the last -rpath option counts, the user
684 dnl must pass all path elements in one option.
685 alldirs=
686 for dir in $rpathdirs; do
687 alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
688 done
689 acl_save_libdir="$libdir"
690 libdir="$alldirs"
691 eval flag=\"$acl_hardcode_libdir_flag_spec\"
692 libdir="$acl_save_libdir"
693 $1="$flag"
694 else
695 dnl The -rpath options are cumulative.
696 for dir in $rpathdirs; do
697 acl_save_libdir="$libdir"
698 libdir="$dir"
699 eval flag=\"$acl_hardcode_libdir_flag_spec\"
700 libdir="$acl_save_libdir"
701 $1="${$1}${$1:+ }$flag"
702 done
703 fi
704 fi
705 fi
706 fi
707 fi
708 AC_SUBST([$1])
709])
diff --git a/gl/m4/lib-prefix.m4 b/gl/m4/lib-prefix.m4
new file mode 100644
index 00000000..a8684e17
--- /dev/null
+++ b/gl/m4/lib-prefix.m4
@@ -0,0 +1,185 @@
1# lib-prefix.m4 serial 5 (gettext-0.15)
2dnl Copyright (C) 2001-2005 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
7dnl From Bruno Haible.
8
9dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
10dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
11dnl require excessive bracketing.
12ifdef([AC_HELP_STRING],
13[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
14[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
15
16dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
17dnl to access previously installed libraries. The basic assumption is that
18dnl a user will want packages to use other packages he previously installed
19dnl with the same --prefix option.
20dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
21dnl libraries, but is otherwise very convenient.
22AC_DEFUN([AC_LIB_PREFIX],
23[
24 AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
25 AC_REQUIRE([AC_PROG_CC])
26 AC_REQUIRE([AC_CANONICAL_HOST])
27 AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
28 AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
29 dnl By default, look in $includedir and $libdir.
30 use_additional=yes
31 AC_LIB_WITH_FINAL_PREFIX([
32 eval additional_includedir=\"$includedir\"
33 eval additional_libdir=\"$libdir\"
34 ])
35 AC_LIB_ARG_WITH([lib-prefix],
36[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
37 --without-lib-prefix don't search for libraries in includedir and libdir],
38[
39 if test "X$withval" = "Xno"; then
40 use_additional=no
41 else
42 if test "X$withval" = "X"; then
43 AC_LIB_WITH_FINAL_PREFIX([
44 eval additional_includedir=\"$includedir\"
45 eval additional_libdir=\"$libdir\"
46 ])
47 else
48 additional_includedir="$withval/include"
49 additional_libdir="$withval/$acl_libdirstem"
50 fi
51 fi
52])
53 if test $use_additional = yes; then
54 dnl Potentially add $additional_includedir to $CPPFLAGS.
55 dnl But don't add it
56 dnl 1. if it's the standard /usr/include,
57 dnl 2. if it's already present in $CPPFLAGS,
58 dnl 3. if it's /usr/local/include and we are using GCC on Linux,
59 dnl 4. if it doesn't exist as a directory.
60 if test "X$additional_includedir" != "X/usr/include"; then
61 haveit=
62 for x in $CPPFLAGS; do
63 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
64 if test "X$x" = "X-I$additional_includedir"; then
65 haveit=yes
66 break
67 fi
68 done
69 if test -z "$haveit"; then
70 if test "X$additional_includedir" = "X/usr/local/include"; then
71 if test -n "$GCC"; then
72 case $host_os in
73 linux* | gnu* | k*bsd*-gnu) haveit=yes;;
74 esac
75 fi
76 fi
77 if test -z "$haveit"; then
78 if test -d "$additional_includedir"; then
79 dnl Really add $additional_includedir to $CPPFLAGS.
80 CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
81 fi
82 fi
83 fi
84 fi
85 dnl Potentially add $additional_libdir to $LDFLAGS.
86 dnl But don't add it
87 dnl 1. if it's the standard /usr/lib,
88 dnl 2. if it's already present in $LDFLAGS,
89 dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
90 dnl 4. if it doesn't exist as a directory.
91 if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
92 haveit=
93 for x in $LDFLAGS; do
94 AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
95 if test "X$x" = "X-L$additional_libdir"; then
96 haveit=yes
97 break
98 fi
99 done
100 if test -z "$haveit"; then
101 if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
102 if test -n "$GCC"; then
103 case $host_os in
104 linux*) haveit=yes;;
105 esac
106 fi
107 fi
108 if test -z "$haveit"; then
109 if test -d "$additional_libdir"; then
110 dnl Really add $additional_libdir to $LDFLAGS.
111 LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
112 fi
113 fi
114 fi
115 fi
116 fi
117])
118
119dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
120dnl acl_final_exec_prefix, containing the values to which $prefix and
121dnl $exec_prefix will expand at the end of the configure script.
122AC_DEFUN([AC_LIB_PREPARE_PREFIX],
123[
124 dnl Unfortunately, prefix and exec_prefix get only finally determined
125 dnl at the end of configure.
126 if test "X$prefix" = "XNONE"; then
127 acl_final_prefix="$ac_default_prefix"
128 else
129 acl_final_prefix="$prefix"
130 fi
131 if test "X$exec_prefix" = "XNONE"; then
132 acl_final_exec_prefix='${prefix}'
133 else
134 acl_final_exec_prefix="$exec_prefix"
135 fi
136 acl_save_prefix="$prefix"
137 prefix="$acl_final_prefix"
138 eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
139 prefix="$acl_save_prefix"
140])
141
142dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
143dnl variables prefix and exec_prefix bound to the values they will have
144dnl at the end of the configure script.
145AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
146[
147 acl_save_prefix="$prefix"
148 prefix="$acl_final_prefix"
149 acl_save_exec_prefix="$exec_prefix"
150 exec_prefix="$acl_final_exec_prefix"
151 $1
152 exec_prefix="$acl_save_exec_prefix"
153 prefix="$acl_save_prefix"
154])
155
156dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing
157dnl the basename of the libdir, either "lib" or "lib64".
158AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
159[
160 dnl There is no formal standard regarding lib and lib64. The current
161 dnl practice is that on a system supporting 32-bit and 64-bit instruction
162 dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit
163 dnl libraries go under $prefix/lib. We determine the compiler's default
164 dnl mode by looking at the compiler's library search path. If at least
165 dnl of its elements ends in /lib64 or points to a directory whose absolute
166 dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the
167 dnl default, namely "lib".
168 acl_libdirstem=lib
169 searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
170 if test -n "$searchpath"; then
171 acl_save_IFS="${IFS= }"; IFS=":"
172 for searchdir in $searchpath; do
173 if test -d "$searchdir"; then
174 case "$searchdir" in
175 */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
176 *) searchdir=`cd "$searchdir" && pwd`
177 case "$searchdir" in
178 */lib64 ) acl_libdirstem=lib64 ;;
179 esac ;;
180 esac
181 fi
182 done
183 IFS="$acl_save_IFS"
184 fi
185])
diff --git a/gl/m4/lock.m4 b/gl/m4/lock.m4
new file mode 100644
index 00000000..0224f2ff
--- /dev/null
+++ b/gl/m4/lock.m4
@@ -0,0 +1,311 @@
1# lock.m4 serial 6 (gettext-0.16)
2dnl Copyright (C) 2005-2006 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
7dnl From Bruno Haible.
8
9dnl Tests for a multithreading library to be used.
10dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS,
11dnl USE_PTH_THREADS, USE_WIN32_THREADS
12dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use
13dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with
14dnl libtool).
15dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for
16dnl programs that really need multithread functionality. The difference
17dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak
18dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread".
19dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for
20dnl multithread-safe programs.
21
22AC_DEFUN([gl_LOCK_EARLY],
23[
24 AC_REQUIRE([gl_LOCK_EARLY_BODY])
25])
26
27dnl The guts of gl_LOCK_EARLY. Needs to be expanded only once.
28
29AC_DEFUN([gl_LOCK_EARLY_BODY],
30[
31 dnl Ordering constraints: This macro modifies CPPFLAGS in a way that
32 dnl influences the result of the autoconf tests that test for *_unlocked
33 dnl declarations, on AIX 5 at least. Therefore it must come early.
34 AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl
35 AC_BEFORE([$0], [gl_ARGP])dnl
36
37 AC_REQUIRE([AC_CANONICAL_HOST])
38 AC_REQUIRE([AC_GNU_SOURCE]) dnl needed for pthread_rwlock_t on glibc systems
39 dnl Check for multithreading.
40 AC_ARG_ENABLE(threads,
41AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API])
42AC_HELP_STRING([--disable-threads], [build without multithread safety]),
43 [gl_use_threads=$enableval],
44 [case "$host_os" in
45 dnl Disable multithreading by default on OSF/1, because it interferes
46 dnl with fork()/exec(): When msgexec is linked with -lpthread, its child
47 dnl process gets an endless segmentation fault inside execvp().
48 osf*) gl_use_threads=no ;;
49 *) gl_use_threads=yes ;;
50 esac
51 ])
52 if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
53 # For using <pthread.h>:
54 case "$host_os" in
55 osf*)
56 # On OSF/1, the compiler needs the flag -D_REENTRANT so that it
57 # groks <pthread.h>. cc also understands the flag -pthread, but
58 # we don't use it because 1. gcc-2.95 doesn't understand -pthread,
59 # 2. putting a flag into CPPFLAGS that has an effect on the linker
60 # causes the AC_TRY_LINK test below to succeed unexpectedly,
61 # leading to wrong values of LIBTHREAD and LTLIBTHREAD.
62 CPPFLAGS="$CPPFLAGS -D_REENTRANT"
63 ;;
64 esac
65 # Some systems optimize for single-threaded programs by default, and
66 # need special flags to disable these optimizations. For example, the
67 # definition of 'errno' in <errno.h>.
68 case "$host_os" in
69 aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
70 solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
71 esac
72 fi
73])
74
75dnl The guts of gl_LOCK. Needs to be expanded only once.
76
77AC_DEFUN([gl_LOCK_BODY],
78[
79 AC_REQUIRE([gl_LOCK_EARLY_BODY])
80 gl_threads_api=none
81 LIBTHREAD=
82 LTLIBTHREAD=
83 LIBMULTITHREAD=
84 LTLIBMULTITHREAD=
85 if test "$gl_use_threads" != no; then
86 dnl Check whether the compiler and linker support weak declarations.
87 AC_MSG_CHECKING([whether imported symbols can be declared weak])
88 gl_have_weak=no
89 AC_TRY_LINK([extern void xyzzy ();
90#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes])
91 AC_MSG_RESULT([$gl_have_weak])
92 if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
93 # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that
94 # it groks <pthread.h>. It's added above, in gl_LOCK_EARLY_BODY.
95 AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no)
96 if test "$gl_have_pthread_h" = yes; then
97 # Other possible tests:
98 # -lpthreads (FSU threads, PCthreads)
99 # -lgthreads
100 gl_have_pthread=
101 # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist
102 # in libc. IRIX 6.5 has the first one in both libc and libpthread, but
103 # the second one only in libpthread, and lock.c needs it.
104 AC_TRY_LINK([#include <pthread.h>],
105 [pthread_mutex_lock((pthread_mutex_t*)0);
106 pthread_mutexattr_init((pthread_mutexattr_t*)0);],
107 [gl_have_pthread=yes])
108 # Test for libpthread by looking for pthread_kill. (Not pthread_self,
109 # since it is defined as a macro on OSF/1.)
110 if test -n "$gl_have_pthread"; then
111 # The program links fine without libpthread. But it may actually
112 # need to link with libpthread in order to create multiple threads.
113 AC_CHECK_LIB(pthread, pthread_kill,
114 [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread
115 # On Solaris and HP-UX, most pthread functions exist also in libc.
116 # Therefore pthread_in_use() needs to actually try to create a
117 # thread: pthread_create from libc will fail, whereas
118 # pthread_create will actually create a thread.
119 case "$host_os" in
120 solaris* | hpux*)
121 AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1,
122 [Define if the pthread_in_use() detection is hard.])
123 esac
124 ])
125 else
126 # Some library is needed. Try libpthread and libc_r.
127 AC_CHECK_LIB(pthread, pthread_kill,
128 [gl_have_pthread=yes
129 LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread
130 LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread])
131 if test -z "$gl_have_pthread"; then
132 # For FreeBSD 4.
133 AC_CHECK_LIB(c_r, pthread_kill,
134 [gl_have_pthread=yes
135 LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r
136 LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r])
137 fi
138 fi
139 if test -n "$gl_have_pthread"; then
140 gl_threads_api=posix
141 AC_DEFINE([USE_POSIX_THREADS], 1,
142 [Define if the POSIX multithreading library can be used.])
143 if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
144 if test $gl_have_weak = yes; then
145 AC_DEFINE([USE_POSIX_THREADS_WEAK], 1,
146 [Define if references to the POSIX multithreading library should be made weak.])
147 LIBTHREAD=
148 LTLIBTHREAD=
149 fi
150 fi
151 # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the
152 # pthread_rwlock_* functions.
153 AC_CHECK_TYPE([pthread_rwlock_t],
154 [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1,
155 [Define if the POSIX multithreading library has read/write locks.])],
156 [],
157 [#include <pthread.h>])
158 # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro.
159 AC_TRY_COMPILE([#include <pthread.h>],
160 [#if __FreeBSD__ == 4
161error "No, in FreeBSD 4.0 recursive mutexes actually don't work."
162#else
163int x = (int)PTHREAD_MUTEX_RECURSIVE;
164return !x;
165#endif],
166 [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1,
167 [Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE.])])
168 fi
169 fi
170 fi
171 if test -z "$gl_have_pthread"; then
172 if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then
173 gl_have_solaristhread=
174 gl_save_LIBS="$LIBS"
175 LIBS="$LIBS -lthread"
176 AC_TRY_LINK([#include <thread.h>
177#include <synch.h>],
178 [thr_self();],
179 [gl_have_solaristhread=yes])
180 LIBS="$gl_save_LIBS"
181 if test -n "$gl_have_solaristhread"; then
182 gl_threads_api=solaris
183 LIBTHREAD=-lthread
184 LTLIBTHREAD=-lthread
185 LIBMULTITHREAD="$LIBTHREAD"
186 LTLIBMULTITHREAD="$LTLIBTHREAD"
187 AC_DEFINE([USE_SOLARIS_THREADS], 1,
188 [Define if the old Solaris multithreading library can be used.])
189 if test $gl_have_weak = yes; then
190 AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1,
191 [Define if references to the old Solaris multithreading library should be made weak.])
192 LIBTHREAD=
193 LTLIBTHREAD=
194 fi
195 fi
196 fi
197 fi
198 if test "$gl_use_threads" = pth; then
199 gl_save_CPPFLAGS="$CPPFLAGS"
200 AC_LIB_LINKFLAGS(pth)
201 gl_have_pth=
202 gl_save_LIBS="$LIBS"
203 LIBS="$LIBS -lpth"
204 AC_TRY_LINK([#include <pth.h>], [pth_self();], gl_have_pth=yes)
205 LIBS="$gl_save_LIBS"
206 if test -n "$gl_have_pth"; then
207 gl_threads_api=pth
208 LIBTHREAD="$LIBPTH"
209 LTLIBTHREAD="$LTLIBPTH"
210 LIBMULTITHREAD="$LIBTHREAD"
211 LTLIBMULTITHREAD="$LTLIBTHREAD"
212 AC_DEFINE([USE_PTH_THREADS], 1,
213 [Define if the GNU Pth multithreading library can be used.])
214 if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
215 if test $gl_have_weak = yes; then
216 AC_DEFINE([USE_PTH_THREADS_WEAK], 1,
217 [Define if references to the GNU Pth multithreading library should be made weak.])
218 LIBTHREAD=
219 LTLIBTHREAD=
220 fi
221 fi
222 else
223 CPPFLAGS="$gl_save_CPPFLAGS"
224 fi
225 fi
226 if test -z "$gl_have_pthread"; then
227 if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then
228 if { case "$host_os" in
229 mingw*) true;;
230 *) false;;
231 esac
232 }; then
233 gl_threads_api=win32
234 AC_DEFINE([USE_WIN32_THREADS], 1,
235 [Define if the Win32 multithreading API can be used.])
236 fi
237 fi
238 fi
239 fi
240 AC_MSG_CHECKING([for multithread API to use])
241 AC_MSG_RESULT([$gl_threads_api])
242 AC_SUBST(LIBTHREAD)
243 AC_SUBST(LTLIBTHREAD)
244 AC_SUBST(LIBMULTITHREAD)
245 AC_SUBST(LTLIBMULTITHREAD)
246])
247
248AC_DEFUN([gl_LOCK],
249[
250 AC_REQUIRE([gl_LOCK_EARLY])
251 AC_REQUIRE([gl_LOCK_BODY])
252 gl_PREREQ_LOCK
253])
254
255# Prerequisites of lib/lock.c.
256AC_DEFUN([gl_PREREQ_LOCK], [
257 AC_REQUIRE([AC_C_INLINE])
258])
259
260dnl Survey of platforms:
261dnl
262dnl Platform Available Compiler Supports test-lock
263dnl flavours option weak result
264dnl --------------- --------- --------- -------- ---------
265dnl Linux 2.4/glibc posix -lpthread Y OK
266dnl
267dnl GNU Hurd/glibc posix
268dnl
269dnl FreeBSD 5.3 posix -lc_r Y
270dnl posix -lkse ? Y
271dnl posix -lpthread ? Y
272dnl posix -lthr Y
273dnl
274dnl FreeBSD 5.2 posix -lc_r Y
275dnl posix -lkse Y
276dnl posix -lthr Y
277dnl
278dnl FreeBSD 4.0,4.10 posix -lc_r Y OK
279dnl
280dnl NetBSD 1.6 --
281dnl
282dnl OpenBSD 3.4 posix -lpthread Y OK
283dnl
284dnl MacOS X 10.[123] posix -lpthread Y OK
285dnl
286dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK
287dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK
288dnl
289dnl HP-UX 11 posix -lpthread N (cc) OK
290dnl Y (gcc)
291dnl
292dnl IRIX 6.5 posix -lpthread Y 0.5
293dnl
294dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK
295dnl
296dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK
297dnl -lpthread (gcc) Y
298dnl
299dnl Cygwin posix -lpthread Y OK
300dnl
301dnl Any of the above pth -lpth 0.0
302dnl
303dnl Mingw win32 N OK
304dnl
305dnl BeOS 5 --
306dnl
307dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is
308dnl turned off:
309dnl OK if all three tests terminate OK,
310dnl 0.5 if the first test terminates OK but the second one loops endlessly,
311dnl 0.0 if the first test already loops endlessly.
diff --git a/gl/m4/longdouble.m4 b/gl/m4/longdouble.m4
new file mode 100644
index 00000000..25590f47
--- /dev/null
+++ b/gl/m4/longdouble.m4
@@ -0,0 +1,31 @@
1# longdouble.m4 serial 2 (gettext-0.15)
2dnl Copyright (C) 2002-2003, 2006 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
7dnl From Bruno Haible.
8dnl Test whether the compiler supports the 'long double' type.
9dnl Prerequisite: AC_PROG_CC
10
11dnl This file is only needed in autoconf <= 2.59. Newer versions of autoconf
12dnl have a macro AC_TYPE_LONG_DOUBLE with identical semantics.
13
14AC_DEFUN([gt_TYPE_LONGDOUBLE],
15[
16 AC_CACHE_CHECK([for long double], gt_cv_c_long_double,
17 [if test "$GCC" = yes; then
18 gt_cv_c_long_double=yes
19 else
20 AC_TRY_COMPILE([
21 /* The Stardent Vistra knows sizeof(long double), but does not support it. */
22 long double foo = 0.0;
23 /* On Ultrix 4.3 cc, long double is 4 and double is 8. */
24 int array [2*(sizeof(long double) >= sizeof(double)) - 1];
25 ], ,
26 gt_cv_c_long_double=yes, gt_cv_c_long_double=no)
27 fi])
28 if test $gt_cv_c_long_double = yes; then
29 AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.])
30 fi
31])
diff --git a/gl/m4/longlong.m4 b/gl/m4/longlong.m4
new file mode 100644
index 00000000..1f9e862e
--- /dev/null
+++ b/gl/m4/longlong.m4
@@ -0,0 +1,72 @@
1# longlong.m4 serial 10
2dnl Copyright (C) 1999-2006 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
7dnl From Paul Eggert.
8
9# Define HAVE_LONG_LONG_INT if 'long long int' works.
10# This fixes a bug in Autoconf 2.60, but can be removed once we
11# assume 2.61 everywhere.
12
13# Note: If the type 'long long int' exists but is only 32 bits large
14# (as on some very old compilers), HAVE_LONG_LONG_INT will not be
15# defined. In this case you can treat 'long long int' like 'long int'.
16
17AC_DEFUN([AC_TYPE_LONG_LONG_INT],
18[
19 AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int],
20 [AC_LINK_IFELSE(
21 [AC_LANG_PROGRAM(
22 [[long long int ll = 9223372036854775807ll;
23 long long int nll = -9223372036854775807LL;
24 typedef int a[((-9223372036854775807LL < 0
25 && 0 < 9223372036854775807ll)
26 ? 1 : -1)];
27 int i = 63;]],
28 [[long long int llmax = 9223372036854775807ll;
29 return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
30 | (llmax / ll) | (llmax % ll));]])],
31 [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004.
32 dnl If cross compiling, assume the bug isn't important, since
33 dnl nobody cross compiles for this platform as far as we know.
34 AC_RUN_IFELSE(
35 [AC_LANG_PROGRAM(
36 [[@%:@include <limits.h>
37 @%:@ifndef LLONG_MAX
38 @%:@ define HALF \
39 (1LL << (sizeof (long long int) * CHAR_BIT - 2))
40 @%:@ define LLONG_MAX (HALF - 1 + HALF)
41 @%:@endif]],
42 [[long long int n = 1;
43 int i;
44 for (i = 0; ; i++)
45 {
46 long long int m = n << i;
47 if (m >> i != n)
48 return 1;
49 if (LLONG_MAX / 2 < m)
50 break;
51 }
52 return 0;]])],
53 [ac_cv_type_long_long_int=yes],
54 [ac_cv_type_long_long_int=no],
55 [ac_cv_type_long_long_int=yes])],
56 [ac_cv_type_long_long_int=no])])
57 if test $ac_cv_type_long_long_int = yes; then
58 AC_DEFINE([HAVE_LONG_LONG_INT], 1,
59 [Define to 1 if the system has the type `long long int'.])
60 fi
61])
62
63# This macro is obsolescent and should go away soon.
64AC_DEFUN([gl_AC_TYPE_LONG_LONG],
65[
66 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
67 ac_cv_type_long_long=$ac_cv_type_long_long_int
68 if test $ac_cv_type_long_long = yes; then
69 AC_DEFINE(HAVE_LONG_LONG, 1,
70 [Define if you have the 'long long' type.])
71 fi
72])
diff --git a/gl/m4/ls-mntd-fs.m4 b/gl/m4/ls-mntd-fs.m4
new file mode 100644
index 00000000..21ac4e74
--- /dev/null
+++ b/gl/m4/ls-mntd-fs.m4
@@ -0,0 +1,337 @@
1#serial 26
2# How to list mounted file systems.
3
4# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software
5# Foundation, Inc.
6#
7# This file is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11dnl From Jim Meyering.
12dnl
13dnl This is not pretty. I've just taken the autoconf code and wrapped
14dnl it in an AC_DEFUN and made some other fixes.
15dnl
16
17# Replace Autoconf's AC_FUNC_GETMNTENT to work around a bug in Autoconf
18# through Autoconf 2.59. We can remove this once we assume Autoconf 2.60
19# or later.
20AC_DEFUN([AC_FUNC_GETMNTENT],
21[# getmntent is in the standard C library on UNICOS, in -lsun on Irix 4,
22# -lseq on Dynix/PTX, -lgen on Unixware.
23AC_SEARCH_LIBS(getmntent, [sun seq gen])
24AC_CHECK_FUNCS(getmntent)
25])
26
27# gl_LIST_MOUNTED_FILE_SYSTEMS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
28AC_DEFUN([gl_LIST_MOUNTED_FILE_SYSTEMS],
29 [
30AC_CHECK_FUNCS(listmntent getmntinfo)
31AC_CHECK_HEADERS_ONCE(sys/param.h sys/statvfs.h)
32
33# We must include grp.h before ucred.h on OSF V4.0, since ucred.h uses
34# NGROUPS (as the array dimension for a struct member) without a definition.
35AC_CHECK_HEADERS(sys/ucred.h, [], [], [#include <grp.h>])
36
37AC_CHECK_HEADERS(sys/mount.h, [], [],
38 [AC_INCLUDES_DEFAULT
39 [#if HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif]])
42
43AC_CHECK_HEADERS(mntent.h sys/fs_types.h)
44 getfsstat_includes="\
45$ac_includes_default
46#if HAVE_SYS_PARAM_H
47# include <sys/param.h> /* needed by powerpc-apple-darwin1.3.7 */
48#endif
49#if HAVE_SYS_UCRED_H
50# include <grp.h> /* needed for definition of NGROUPS */
51# include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
52#endif
53#if HAVE_SYS_MOUNT_H
54# include <sys/mount.h>
55#endif
56#if HAVE_SYS_FS_TYPES_H
57# include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
58#endif
59"
60AC_CHECK_MEMBERS([struct fsstat.f_fstypename],,,[$getfsstat_includes])
61
62# Determine how to get the list of mounted file systems.
63ac_list_mounted_fs=
64
65# If the getmntent function is available but not in the standard library,
66# make sure LIBS contains the appropriate -l option.
67AC_FUNC_GETMNTENT
68
69# This test must precede the ones for getmntent because Unicos-9 is
70# reported to have the getmntent function, but its support is incompatible
71# with other getmntent implementations.
72
73# NOTE: Normally, I wouldn't use a check for system type as I've done for
74# `CRAY' below since that goes against the whole autoconf philosophy. But
75# I think there is too great a chance that some non-Cray system has a
76# function named listmntent to risk the false positive.
77
78if test -z "$ac_list_mounted_fs"; then
79 # Cray UNICOS 9
80 AC_MSG_CHECKING([for listmntent of Cray/Unicos-9])
81 AC_CACHE_VAL(fu_cv_sys_mounted_cray_listmntent,
82 [fu_cv_sys_mounted_cray_listmntent=no
83 AC_EGREP_CPP(yes,
84 [#ifdef _CRAY
85yes
86#endif
87 ], [test $ac_cv_func_listmntent = yes \
88 && fu_cv_sys_mounted_cray_listmntent=yes]
89 )
90 ]
91 )
92 AC_MSG_RESULT($fu_cv_sys_mounted_cray_listmntent)
93 if test $fu_cv_sys_mounted_cray_listmntent = yes; then
94 ac_list_mounted_fs=found
95 AC_DEFINE(MOUNTED_LISTMNTENT, 1,
96 [Define if there is a function named listmntent that can be used to
97 list all mounted file systems. (UNICOS)])
98 fi
99fi
100
101if test -z "$ac_list_mounted_fs"; then
102 # AIX.
103 AC_MSG_CHECKING([for mntctl function and struct vmount])
104 AC_CACHE_VAL(fu_cv_sys_mounted_vmount,
105 [AC_TRY_CPP([#include <fshelp.h>],
106 fu_cv_sys_mounted_vmount=yes,
107 fu_cv_sys_mounted_vmount=no)])
108 AC_MSG_RESULT($fu_cv_sys_mounted_vmount)
109 if test $fu_cv_sys_mounted_vmount = yes; then
110 ac_list_mounted_fs=found
111 AC_DEFINE(MOUNTED_VMOUNT, 1,
112 [Define if there is a function named mntctl that can be used to read
113 the list of mounted file systems, and there is a system header file
114 that declares `struct vmount.' (AIX)])
115 fi
116fi
117
118if test $ac_cv_func_getmntent = yes; then
119
120 # This system has the getmntent function.
121 # Determine whether it's the one-argument variant or the two-argument one.
122
123 if test -z "$ac_list_mounted_fs"; then
124 # 4.3BSD, SunOS, HP-UX, Dynix, Irix
125 AC_MSG_CHECKING([for one-argument getmntent function])
126 AC_CACHE_VAL(fu_cv_sys_mounted_getmntent1,
127 [AC_TRY_COMPILE([
128/* SunOS 4.1.x /usr/include/mntent.h needs this for FILE */
129#include <stdio.h>
130
131#include <mntent.h>
132#if !defined MOUNTED
133# if defined _PATH_MOUNTED /* GNU libc */
134# define MOUNTED _PATH_MOUNTED
135# endif
136# if defined MNT_MNTTAB /* HP-UX. */
137# define MOUNTED MNT_MNTTAB
138# endif
139# if defined MNTTABNAME /* Dynix. */
140# define MOUNTED MNTTABNAME
141# endif
142#endif
143],
144 [ struct mntent *mnt = 0; char *table = MOUNTED;
145 if (sizeof mnt && sizeof table) return 0;],
146 fu_cv_sys_mounted_getmntent1=yes,
147 fu_cv_sys_mounted_getmntent1=no)])
148 AC_MSG_RESULT($fu_cv_sys_mounted_getmntent1)
149 if test $fu_cv_sys_mounted_getmntent1 = yes; then
150 ac_list_mounted_fs=found
151 AC_DEFINE(MOUNTED_GETMNTENT1, 1,
152 [Define if there is a function named getmntent for reading the list
153 of mounted file systems, and that function takes a single argument.
154 (4.3BSD, SunOS, HP-UX, Dynix, Irix)])
155 fi
156 fi
157
158 if test -z "$ac_list_mounted_fs"; then
159 # SVR4
160 AC_MSG_CHECKING([for two-argument getmntent function])
161 AC_CACHE_VAL(fu_cv_sys_mounted_getmntent2,
162 [AC_EGREP_HEADER(getmntent, sys/mnttab.h,
163 fu_cv_sys_mounted_getmntent2=yes,
164 fu_cv_sys_mounted_getmntent2=no)])
165 AC_MSG_RESULT($fu_cv_sys_mounted_getmntent2)
166 if test $fu_cv_sys_mounted_getmntent2 = yes; then
167 ac_list_mounted_fs=found
168 AC_DEFINE(MOUNTED_GETMNTENT2, 1,
169 [Define if there is a function named getmntent for reading the list of
170 mounted file systems, and that function takes two arguments. (SVR4)])
171 AC_CHECK_FUNCS(hasmntopt)
172 fi
173 fi
174
175fi
176
177if test -z "$ac_list_mounted_fs"; then
178 # DEC Alpha running OSF/1, and Apple Darwin 1.3.
179 # powerpc-apple-darwin1.3.7 needs sys/param.h sys/ucred.h sys/fs_types.h
180
181 AC_MSG_CHECKING([for getfsstat function])
182 AC_CACHE_VAL(fu_cv_sys_mounted_getfsstat,
183 [AC_TRY_LINK([
184#include <sys/types.h>
185#if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
186# define FS_TYPE(Ent) ((Ent).f_fstypename)
187#else
188# define FS_TYPE(Ent) mnt_names[(Ent).f_type]
189#endif
190]$getfsstat_includes
191,
192 [struct statfs *stats;
193 int numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
194 char *t = FS_TYPE (*stats); ],
195 fu_cv_sys_mounted_getfsstat=yes,
196 fu_cv_sys_mounted_getfsstat=no)])
197 AC_MSG_RESULT($fu_cv_sys_mounted_getfsstat)
198 if test $fu_cv_sys_mounted_getfsstat = yes; then
199 ac_list_mounted_fs=found
200 AC_DEFINE(MOUNTED_GETFSSTAT, 1,
201 [Define if there is a function named getfsstat for reading the
202 list of mounted file systems. (DEC Alpha running OSF/1)])
203 fi
204fi
205
206if test -z "$ac_list_mounted_fs"; then
207 # SVR3
208 AC_MSG_CHECKING([for FIXME existence of three headers])
209 AC_CACHE_VAL(fu_cv_sys_mounted_fread_fstyp,
210 [AC_TRY_CPP([
211#include <sys/statfs.h>
212#include <sys/fstyp.h>
213#include <mnttab.h>],
214 fu_cv_sys_mounted_fread_fstyp=yes,
215 fu_cv_sys_mounted_fread_fstyp=no)])
216 AC_MSG_RESULT($fu_cv_sys_mounted_fread_fstyp)
217 if test $fu_cv_sys_mounted_fread_fstyp = yes; then
218 ac_list_mounted_fs=found
219 AC_DEFINE(MOUNTED_FREAD_FSTYP, 1,
220 [Define if (like SVR2) there is no specific function for reading the
221 list of mounted file systems, and your system has these header files:
222 <sys/fstyp.h> and <sys/statfs.h>. (SVR3)])
223 fi
224fi
225
226if test -z "$ac_list_mounted_fs"; then
227 # 4.4BSD and DEC OSF/1.
228 AC_MSG_CHECKING([for getmntinfo function])
229 AC_CACHE_VAL(fu_cv_sys_mounted_getmntinfo,
230 [
231 test "$ac_cv_func_getmntinfo" = yes \
232 && fu_cv_sys_mounted_getmntinfo=yes \
233 || fu_cv_sys_mounted_getmntinfo=no
234 ])
235 AC_MSG_RESULT($fu_cv_sys_mounted_getmntinfo)
236 if test $fu_cv_sys_mounted_getmntinfo = yes; then
237 AC_MSG_CHECKING([whether getmntinfo returns statvfs structures])
238 AC_CACHE_VAL(fu_cv_sys_mounted_getmntinfo2,
239 [
240 AC_TRY_COMPILE([
241#if HAVE_SYS_PARAM_H
242# include <sys/param.h>
243#endif
244#include <sys/types.h>
245#if HAVE_SYS_MOUNT_H
246# include <sys/mount.h>
247#endif
248#if HAVE_SYS_STATVFS_H
249# include <sys/statvfs.h>
250#endif
251extern int getmntinfo (struct statfs **, int);
252 ], [],
253 [fu_cv_sys_mounted_getmntinfo2=no],
254 [fu_cv_sys_mounted_getmntinfo2=yes])
255 ])
256 AC_MSG_RESULT([$fu_cv_sys_mounted_getmntinfo2])
257 if test $fu_cv_sys_mounted_getmntinfo2 = no; then
258 ac_list_mounted_fs=found
259 AC_DEFINE(MOUNTED_GETMNTINFO, 1,
260 [Define if there is a function named getmntinfo for reading the
261 list of mounted file systems and it returns an array of
262 'struct statfs'. (4.4BSD, Darwin)])
263 else
264 ac_list_mounted_fs=found
265 AC_DEFINE(MOUNTED_GETMNTINFO2, 1,
266 [Define if there is a function named getmntinfo for reading the
267 list of mounted file systems and it returns an array of
268 'struct statvfs'. (NetBSD 3.0)])
269 fi
270 fi
271fi
272
273if test -z "$ac_list_mounted_fs"; then
274 # Ultrix
275 AC_MSG_CHECKING([for getmnt function])
276 AC_CACHE_VAL(fu_cv_sys_mounted_getmnt,
277 [AC_TRY_CPP([
278#include <sys/fs_types.h>
279#include <sys/mount.h>],
280 fu_cv_sys_mounted_getmnt=yes,
281 fu_cv_sys_mounted_getmnt=no)])
282 AC_MSG_RESULT($fu_cv_sys_mounted_getmnt)
283 if test $fu_cv_sys_mounted_getmnt = yes; then
284 ac_list_mounted_fs=found
285 AC_DEFINE(MOUNTED_GETMNT, 1,
286 [Define if there is a function named getmnt for reading the list of
287 mounted file systems. (Ultrix)])
288 fi
289fi
290
291if test -z "$ac_list_mounted_fs"; then
292 # BeOS
293 AC_CHECK_FUNCS(next_dev fs_stat_dev)
294 AC_CHECK_HEADERS(fs_info.h)
295 AC_MSG_CHECKING([for BEOS mounted file system support functions])
296 if test $ac_cv_header_fs_info_h = yes \
297 && test $ac_cv_func_next_dev = yes \
298 && test $ac_cv_func_fs_stat_dev = yes; then
299 fu_result=yes
300 else
301 fu_result=no
302 fi
303 AC_MSG_RESULT($fu_result)
304 if test $fu_result = yes; then
305 ac_list_mounted_fs=found
306 AC_DEFINE(MOUNTED_FS_STAT_DEV, 1,
307 [Define if there are functions named next_dev and fs_stat_dev for
308 reading the list of mounted file systems. (BeOS)])
309 fi
310fi
311
312if test -z "$ac_list_mounted_fs"; then
313 # SVR2
314 AC_MSG_CHECKING([whether it is possible to resort to fread on /etc/mnttab])
315 AC_CACHE_VAL(fu_cv_sys_mounted_fread,
316 [AC_TRY_CPP([#include <mnttab.h>],
317 fu_cv_sys_mounted_fread=yes,
318 fu_cv_sys_mounted_fread=no)])
319 AC_MSG_RESULT($fu_cv_sys_mounted_fread)
320 if test $fu_cv_sys_mounted_fread = yes; then
321 ac_list_mounted_fs=found
322 AC_DEFINE(MOUNTED_FREAD, 1,
323 [Define if there is no specific function for reading the list of
324 mounted file systems. fread will be used to read /etc/mnttab.
325 (SVR2) ])
326 fi
327fi
328
329if test -z "$ac_list_mounted_fs"; then
330 AC_MSG_ERROR([could not determine how to read list of mounted file systems])
331 # FIXME -- no need to abort building the whole package
332 # Can't build mountlist.c or anything that needs its functions
333fi
334
335AS_IF([test $ac_list_mounted_fs = found], [$1], [$2])
336
337 ])
diff --git a/gl/m4/mbchar.m4 b/gl/m4/mbchar.m4
new file mode 100644
index 00000000..5380941b
--- /dev/null
+++ b/gl/m4/mbchar.m4
@@ -0,0 +1,14 @@
1# mbchar.m4 serial 5
2dnl Copyright (C) 2005-2007 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
7dnl autoconf tests required for use of mbchar.m4
8dnl From Bruno Haible.
9
10AC_DEFUN([gl_MBCHAR],
11[
12 AC_REQUIRE([AC_GNU_SOURCE])
13 AC_LIBOBJ([mbchar])
14])
diff --git a/gl/m4/mbiter.m4 b/gl/m4/mbiter.m4
new file mode 100644
index 00000000..7d51af10
--- /dev/null
+++ b/gl/m4/mbiter.m4
@@ -0,0 +1,17 @@
1# mbiter.m4 serial 2
2dnl Copyright (C) 2005 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
7dnl autoconf tests required for use of mbiter.h
8dnl From Bruno Haible.
9
10AC_DEFUN([gl_MBITER],
11[
12 AC_REQUIRE([AC_TYPE_MBSTATE_T])
13 dnl The following line is that so the user can test HAVE_MBRTOWC before
14 dnl #include "mbiter.h" or "mbuiter.h".
15 AC_REQUIRE([gl_FUNC_MBRTOWC])
16 :
17])
diff --git a/gl/m4/mbrtowc.m4 b/gl/m4/mbrtowc.m4
new file mode 100644
index 00000000..a3bd9114
--- /dev/null
+++ b/gl/m4/mbrtowc.m4
@@ -0,0 +1,31 @@
1# mbrtowc.m4 serial 8
2dnl Copyright (C) 2001-2002, 2004-2005 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
7dnl From Paul Eggert
8
9dnl This file can be removed, and gl_FUNC_MBRTOWC replaced with
10dnl AC_FUNC_MBRTOWC, when autoconf 2.60 can be assumed everywhere.
11
12AC_DEFUN([gl_FUNC_MBRTOWC],
13[
14 dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
15 AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
16 gl_cv_func_mbrtowc,
17 [AC_LINK_IFELSE(
18 [AC_LANG_PROGRAM(
19 [[#include <wchar.h>]],
20 [[wchar_t wc;
21 char const s[] = "";
22 size_t n = 1;
23 mbstate_t state;
24 return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
25 gl_cv_func_mbrtowc=yes,
26 gl_cv_func_mbrtowc=no)])
27 if test $gl_cv_func_mbrtowc = yes; then
28 AC_DEFINE([HAVE_MBRTOWC], 1,
29 [Define to 1 if mbrtowc and mbstate_t are properly declared.])
30 fi
31])
diff --git a/gl/m4/memchr.m4 b/gl/m4/memchr.m4
new file mode 100644
index 00000000..91b8636e
--- /dev/null
+++ b/gl/m4/memchr.m4
@@ -0,0 +1,18 @@
1# memchr.m4 serial 4
2dnl Copyright (C) 2002, 2003, 2004 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_FUNC_MEMCHR],
8[
9 AC_REPLACE_FUNCS(memchr)
10 if test $ac_cv_func_memchr = no; then
11 gl_PREREQ_MEMCHR
12 fi
13])
14
15# Prerequisites of lib/memchr.c.
16AC_DEFUN([gl_PREREQ_MEMCHR], [
17 AC_CHECK_HEADERS(bp-sym.h)
18])
diff --git a/gl/m4/minmax.m4 b/gl/m4/minmax.m4
new file mode 100644
index 00000000..bbd1ba0b
--- /dev/null
+++ b/gl/m4/minmax.m4
@@ -0,0 +1,41 @@
1# minmax.m4 serial 2
2dnl Copyright (C) 2005 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_PREREQ(2.52)
8
9AC_DEFUN([gl_MINMAX],
10[
11 AC_REQUIRE([gl_PREREQ_MINMAX])
12])
13
14# Prerequisites of lib/minmax.h.
15AC_DEFUN([gl_PREREQ_MINMAX],
16[
17 gl_MINMAX_IN_HEADER([limits.h])
18 gl_MINMAX_IN_HEADER([sys/param.h])
19])
20
21dnl gl_MINMAX_IN_HEADER(HEADER)
22dnl The parameter has to be a literal header name; it cannot be macro,
23dnl nor a shell variable. (Because autoheader collects only AC_DEFINE
24dnl invocations with a literal macro name.)
25AC_DEFUN([gl_MINMAX_IN_HEADER],
26[
27 m4_pushdef([header], AS_TR_SH([$1]))
28 m4_pushdef([HEADER], AS_TR_CPP([$1]))
29 AC_CACHE_CHECK([whether <$1> defines MIN and MAX],
30 [gl_cv_minmax_in_]header,
31 [AC_TRY_COMPILE([#include <$1>
32int x = MIN (42, 17);], [],
33 [gl_cv_minmax_in_]header[=yes],
34 [gl_cv_minmax_in_]header[=no])])
35 if test $gl_cv_minmax_in_[]header = yes; then
36 AC_DEFINE([HAVE_MINMAX_IN_]HEADER, 1,
37 [Define to 1 if <$1> defines the MIN and MAX macros.])
38 fi
39 m4_popdef([HEADER])
40 m4_popdef([header])
41])
diff --git a/gl/m4/mountlist.m4 b/gl/m4/mountlist.m4
new file mode 100644
index 00000000..c25f44e7
--- /dev/null
+++ b/gl/m4/mountlist.m4
@@ -0,0 +1,23 @@
1#serial 9
2dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 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_MOUNTLIST],
8[
9 gl_LIST_MOUNTED_FILE_SYSTEMS([gl_cv_list_mounted_fs=yes],
10 [gl_cv_list_mounted_fs=no])
11 if test $gl_cv_list_mounted_fs = yes; then
12 AC_LIBOBJ(mountlist)
13 gl_PREREQ_MOUNTLIST_EXTRA
14 fi
15])
16
17# Prerequisites of lib/mountlist.c not done by gl_LIST_MOUNTED_FILE_SYSTEMS.
18AC_DEFUN([gl_PREREQ_MOUNTLIST_EXTRA],
19[
20 dnl Note gl_LIST_MOUNTED_FILE_SYSTEMS checks for mntent.h, not sys/mntent.h.
21 AC_CHECK_HEADERS(sys/mntent.h)
22 gl_FSTYPENAME
23])
diff --git a/gl/m4/netinet_in_h.m4 b/gl/m4/netinet_in_h.m4
new file mode 100644
index 00000000..d73531a0
--- /dev/null
+++ b/gl/m4/netinet_in_h.m4
@@ -0,0 +1,18 @@
1# netinet_in_h.m4 serial 1
2dnl Copyright (C) 2006 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
7dnl Written by Simon Josefsson
8
9AC_DEFUN([gl_HEADER_NETINET_IN],
10[
11 AC_CHECK_HEADERS_ONCE([netinet/in.h])
12 if test $ac_cv_header_netinet_in_h = yes; then
13 NETINET_IN_H=''
14 else
15 NETINET_IN_H='netinet/in.h'
16 fi
17 AC_SUBST(NETINET_IN_H)
18])
diff --git a/gl/m4/nls.m4 b/gl/m4/nls.m4
new file mode 100644
index 00000000..7967cc2f
--- /dev/null
+++ b/gl/m4/nls.m4
@@ -0,0 +1,31 @@
1# nls.m4 serial 3 (gettext-0.15)
2dnl Copyright (C) 1995-2003, 2005-2006 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
18dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
19
20AC_PREREQ(2.50)
21
22AC_DEFUN([AM_NLS],
23[
24 AC_MSG_CHECKING([whether NLS is requested])
25 dnl Default is enabled NLS
26 AC_ARG_ENABLE(nls,
27 [ --disable-nls do not use Native Language Support],
28 USE_NLS=$enableval, USE_NLS=yes)
29 AC_MSG_RESULT($USE_NLS)
30 AC_SUBST(USE_NLS)
31])
diff --git a/gl/m4/onceonly_2_57.m4 b/gl/m4/onceonly_2_57.m4
new file mode 100644
index 00000000..15884b3e
--- /dev/null
+++ b/gl/m4/onceonly_2_57.m4
@@ -0,0 +1,86 @@
1# onceonly_2_57.m4 serial 4
2dnl Copyright (C) 2002-2003, 2005-2006 Free Software Foundation, Inc.
3dnl This file is free software, distributed under the terms of the GNU
4dnl General Public License. As a special exception to the GNU General
5dnl Public License, this file may be distributed as part of a program
6dnl that contains a configuration script generated by Autoconf, under
7dnl the same distribution terms as the rest of that program.
8
9dnl This file defines some "once only" variants of standard autoconf macros.
10dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS
11dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS
12dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS
13dnl AC_REQUIRE([AC_FUNC_STRCOLL]) like AC_FUNC_STRCOLL
14dnl The advantage is that the check for each of the headers/functions/decls
15dnl will be put only once into the 'configure' file. It keeps the size of
16dnl the 'configure' file down, and avoids redundant output when 'configure'
17dnl is run.
18dnl The drawback is that the checks cannot be conditionalized. If you write
19dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
20dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
21dnl empty, and the check will be inserted before the body of the AC_DEFUNed
22dnl function.
23
24dnl This is like onceonly.m4, except that it uses diversions to named sections
25dnl DEFAULTS and INIT_PREPARE in order to check all requested headers at once,
26dnl thus reducing the size of 'configure'. Works with autoconf-2.57. The
27dnl size reduction is ca. 9%.
28
29dnl Autoconf version 2.57 or newer is recommended.
30AC_PREREQ(2.57)
31
32# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
33# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
34AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
35 :
36 AC_FOREACH([gl_HEADER_NAME], [$1], [
37 AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
38 [./-], [___])), [
39 m4_divert_text([INIT_PREPARE],
40 [gl_header_list="$gl_header_list gl_HEADER_NAME"])
41 gl_HEADERS_EXPANSION
42 AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_HEADER_NAME])),
43 [Define to 1 if you have the <]m4_defn([gl_HEADER_NAME])[> header file.])
44 ])
45 AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
46 [./-], [___])))
47 ])
48])
49m4_define([gl_HEADERS_EXPANSION], [
50 m4_divert_text([DEFAULTS], [gl_header_list=])
51 AC_CHECK_HEADERS([$gl_header_list])
52 m4_define([gl_HEADERS_EXPANSION], [])
53])
54
55# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
56# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
57AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
58 :
59 AC_FOREACH([gl_FUNC_NAME], [$1], [
60 AC_DEFUN([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]), [
61 m4_divert_text([INIT_PREPARE],
62 [gl_func_list="$gl_func_list gl_FUNC_NAME"])
63 gl_FUNCS_EXPANSION
64 AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_FUNC_NAME])),
65 [Define to 1 if you have the `]m4_defn([gl_FUNC_NAME])[' function.])
66 ])
67 AC_REQUIRE([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]))
68 ])
69])
70m4_define([gl_FUNCS_EXPANSION], [
71 m4_divert_text([DEFAULTS], [gl_func_list=])
72 AC_CHECK_FUNCS([$gl_func_list])
73 m4_define([gl_FUNCS_EXPANSION], [])
74])
75
76# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
77# AC_CHECK_DECLS(DECL1, DECL2, ...).
78AC_DEFUN([AC_CHECK_DECLS_ONCE], [
79 :
80 AC_FOREACH([gl_DECL_NAME], [$1], [
81 AC_DEFUN([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]), [
82 AC_CHECK_DECLS(m4_defn([gl_DECL_NAME]))
83 ])
84 AC_REQUIRE([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]))
85 ])
86])
diff --git a/gl/m4/po.m4 b/gl/m4/po.m4
new file mode 100644
index 00000000..00133ef3
--- /dev/null
+++ b/gl/m4/po.m4
@@ -0,0 +1,428 @@
1# po.m4 serial 13 (gettext-0.15)
2dnl Copyright (C) 1995-2006 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
18dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
19
20AC_PREREQ(2.50)
21
22dnl Checks for all prerequisites of the po subdirectory.
23AC_DEFUN([AM_PO_SUBDIRS],
24[
25 AC_REQUIRE([AC_PROG_MAKE_SET])dnl
26 AC_REQUIRE([AC_PROG_INSTALL])dnl
27 AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
28 AC_REQUIRE([AM_NLS])dnl
29
30 dnl Perform the following tests also if --disable-nls has been given,
31 dnl because they are needed for "make dist" to work.
32
33 dnl Search for GNU msgfmt in the PATH.
34 dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
35 dnl The second test excludes FreeBSD msgfmt.
36 AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
37 [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
38 (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
39 :)
40 AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
41
42 dnl Test whether it is GNU msgfmt >= 0.15.
43changequote(,)dnl
44 case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
45 '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;;
46 *) MSGFMT_015=$MSGFMT ;;
47 esac
48changequote([,])dnl
49 AC_SUBST([MSGFMT_015])
50changequote(,)dnl
51 case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
52 '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;;
53 *) GMSGFMT_015=$GMSGFMT ;;
54 esac
55changequote([,])dnl
56 AC_SUBST([GMSGFMT_015])
57
58 dnl Search for GNU xgettext 0.12 or newer in the PATH.
59 dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
60 dnl The second test excludes FreeBSD xgettext.
61 AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
62 [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
63 (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
64 :)
65 dnl Remove leftover from FreeBSD xgettext call.
66 rm -f messages.po
67
68 dnl Test whether it is GNU xgettext >= 0.15.
69changequote(,)dnl
70 case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
71 '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;;
72 *) XGETTEXT_015=$XGETTEXT ;;
73 esac
74changequote([,])dnl
75 AC_SUBST([XGETTEXT_015])
76
77 dnl Search for GNU msgmerge 0.11 or newer in the PATH.
78 AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
79 [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :)
80
81 dnl Installation directories.
82 dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we
83 dnl have to define it here, so that it can be used in po/Makefile.
84 test -n "$localedir" || localedir='${datadir}/locale'
85 AC_SUBST([localedir])
86
87 AC_CONFIG_COMMANDS([po-directories], [[
88 for ac_file in $CONFIG_FILES; do
89 # Support "outfile[:infile[:infile...]]"
90 case "$ac_file" in
91 *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
92 esac
93 # PO directories have a Makefile.in generated from Makefile.in.in.
94 case "$ac_file" in */Makefile.in)
95 # Adjust a relative srcdir.
96 ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
97 ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
98 ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
99 # In autoconf-2.13 it is called $ac_given_srcdir.
100 # In autoconf-2.50 it is called $srcdir.
101 test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
102 case "$ac_given_srcdir" in
103 .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
104 /*) top_srcdir="$ac_given_srcdir" ;;
105 *) top_srcdir="$ac_dots$ac_given_srcdir" ;;
106 esac
107 # Treat a directory as a PO directory if and only if it has a
108 # POTFILES.in file. This allows packages to have multiple PO
109 # directories under different names or in different locations.
110 if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
111 rm -f "$ac_dir/POTFILES"
112 test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
113 cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
114 POMAKEFILEDEPS="POTFILES.in"
115 # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend
116 # on $ac_dir but don't depend on user-specified configuration
117 # parameters.
118 if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
119 # The LINGUAS file contains the set of available languages.
120 if test -n "$OBSOLETE_ALL_LINGUAS"; then
121 test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
122 fi
123 ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
124 # Hide the ALL_LINGUAS assigment from automake < 1.5.
125 eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
126 POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
127 else
128 # The set of available languages was given in configure.in.
129 # Hide the ALL_LINGUAS assigment from automake < 1.5.
130 eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS'
131 fi
132 # Compute POFILES
133 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
134 # Compute UPDATEPOFILES
135 # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
136 # Compute DUMMYPOFILES
137 # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
138 # Compute GMOFILES
139 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
140 case "$ac_given_srcdir" in
141 .) srcdirpre= ;;
142 *) srcdirpre='$(srcdir)/' ;;
143 esac
144 POFILES=
145 UPDATEPOFILES=
146 DUMMYPOFILES=
147 GMOFILES=
148 for lang in $ALL_LINGUAS; do
149 POFILES="$POFILES $srcdirpre$lang.po"
150 UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
151 DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
152 GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
153 done
154 # CATALOGS depends on both $ac_dir and the user's LINGUAS
155 # environment variable.
156 INST_LINGUAS=
157 if test -n "$ALL_LINGUAS"; then
158 for presentlang in $ALL_LINGUAS; do
159 useit=no
160 if test "%UNSET%" != "$LINGUAS"; then
161 desiredlanguages="$LINGUAS"
162 else
163 desiredlanguages="$ALL_LINGUAS"
164 fi
165 for desiredlang in $desiredlanguages; do
166 # Use the presentlang catalog if desiredlang is
167 # a. equal to presentlang, or
168 # b. a variant of presentlang (because in this case,
169 # presentlang can be used as a fallback for messages
170 # which are not translated in the desiredlang catalog).
171 case "$desiredlang" in
172 "$presentlang"*) useit=yes;;
173 esac
174 done
175 if test $useit = yes; then
176 INST_LINGUAS="$INST_LINGUAS $presentlang"
177 fi
178 done
179 fi
180 CATALOGS=
181 if test -n "$INST_LINGUAS"; then
182 for lang in $INST_LINGUAS; do
183 CATALOGS="$CATALOGS $lang.gmo"
184 done
185 fi
186 test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
187 sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
188 for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
189 if test -f "$f"; then
190 case "$f" in
191 *.orig | *.bak | *~) ;;
192 *) cat "$f" >> "$ac_dir/Makefile" ;;
193 esac
194 fi
195 done
196 fi
197 ;;
198 esac
199 done]],
200 [# Capture the value of obsolete ALL_LINGUAS because we need it to compute
201 # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it
202 # from automake < 1.5.
203 eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"'
204 # Capture the value of LINGUAS because we need it to compute CATALOGS.
205 LINGUAS="${LINGUAS-%UNSET%}"
206 ])
207])
208
209dnl Postprocesses a Makefile in a directory containing PO files.
210AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE],
211[
212 # When this code is run, in config.status, two variables have already been
213 # set:
214 # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in,
215 # - LINGUAS is the value of the environment variable LINGUAS at configure
216 # time.
217
218changequote(,)dnl
219 # Adjust a relative srcdir.
220 ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
221 ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
222 ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
223 # In autoconf-2.13 it is called $ac_given_srcdir.
224 # In autoconf-2.50 it is called $srcdir.
225 test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
226 case "$ac_given_srcdir" in
227 .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
228 /*) top_srcdir="$ac_given_srcdir" ;;
229 *) top_srcdir="$ac_dots$ac_given_srcdir" ;;
230 esac
231
232 # Find a way to echo strings without interpreting backslash.
233 if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then
234 gt_echo='echo'
235 else
236 if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then
237 gt_echo='printf %s\n'
238 else
239 echo_func () {
240 cat <<EOT
241$*
242EOT
243 }
244 gt_echo='echo_func'
245 fi
246 fi
247
248 # A sed script that extracts the value of VARIABLE from a Makefile.
249 sed_x_variable='
250# Test if the hold space is empty.
251x
252s/P/P/
253x
254ta
255# Yes it was empty. Look if we have the expected variable definition.
256/^[ ]*VARIABLE[ ]*=/{
257 # Seen the first line of the variable definition.
258 s/^[ ]*VARIABLE[ ]*=//
259 ba
260}
261bd
262:a
263# Here we are processing a line from the variable definition.
264# Remove comment, more precisely replace it with a space.
265s/#.*$/ /
266# See if the line ends in a backslash.
267tb
268:b
269s/\\$//
270# Print the line, without the trailing backslash.
271p
272tc
273# There was no trailing backslash. The end of the variable definition is
274# reached. Clear the hold space.
275s/^.*$//
276x
277bd
278:c
279# A trailing backslash means that the variable definition continues in the
280# next line. Put a nonempty string into the hold space to indicate this.
281s/^.*$/P/
282x
283:d
284'
285changequote([,])dnl
286
287 # Set POTFILES to the value of the Makefile variable POTFILES.
288 sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
289 POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
290 # Compute POTFILES_DEPS as
291 # $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
292 POTFILES_DEPS=
293 for file in $POTFILES; do
294 POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
295 done
296 POMAKEFILEDEPS=""
297
298 if test -n "$OBSOLETE_ALL_LINGUAS"; then
299 test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
300 fi
301 if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
302 # The LINGUAS file contains the set of available languages.
303 ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
304 POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
305 else
306 # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
307 sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
308 ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
309 fi
310 # Hide the ALL_LINGUAS assigment from automake < 1.5.
311 eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
312 # Compute POFILES
313 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
314 # Compute UPDATEPOFILES
315 # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
316 # Compute DUMMYPOFILES
317 # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
318 # Compute GMOFILES
319 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
320 # Compute PROPERTIESFILES
321 # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties)
322 # Compute CLASSFILES
323 # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class)
324 # Compute QMFILES
325 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
326 # Compute MSGFILES
327 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
328 # Compute RESOURCESDLLFILES
329 # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
330 case "$ac_given_srcdir" in
331 .) srcdirpre= ;;
332 *) srcdirpre='$(srcdir)/' ;;
333 esac
334 POFILES=
335 UPDATEPOFILES=
336 DUMMYPOFILES=
337 GMOFILES=
338 PROPERTIESFILES=
339 CLASSFILES=
340 QMFILES=
341 MSGFILES=
342 RESOURCESDLLFILES=
343 for lang in $ALL_LINGUAS; do
344 POFILES="$POFILES $srcdirpre$lang.po"
345 UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
346 DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
347 GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
348 PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties"
349 CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class"
350 QMFILES="$QMFILES $srcdirpre$lang.qm"
351 frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
352 MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
353 frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
354 RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
355 done
356 # CATALOGS depends on both $ac_dir and the user's LINGUAS
357 # environment variable.
358 INST_LINGUAS=
359 if test -n "$ALL_LINGUAS"; then
360 for presentlang in $ALL_LINGUAS; do
361 useit=no
362 if test "%UNSET%" != "$LINGUAS"; then
363 desiredlanguages="$LINGUAS"
364 else
365 desiredlanguages="$ALL_LINGUAS"
366 fi
367 for desiredlang in $desiredlanguages; do
368 # Use the presentlang catalog if desiredlang is
369 # a. equal to presentlang, or
370 # b. a variant of presentlang (because in this case,
371 # presentlang can be used as a fallback for messages
372 # which are not translated in the desiredlang catalog).
373 case "$desiredlang" in
374 "$presentlang"*) useit=yes;;
375 esac
376 done
377 if test $useit = yes; then
378 INST_LINGUAS="$INST_LINGUAS $presentlang"
379 fi
380 done
381 fi
382 CATALOGS=
383 JAVACATALOGS=
384 QTCATALOGS=
385 TCLCATALOGS=
386 CSHARPCATALOGS=
387 if test -n "$INST_LINGUAS"; then
388 for lang in $INST_LINGUAS; do
389 CATALOGS="$CATALOGS $lang.gmo"
390 JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
391 QTCATALOGS="$QTCATALOGS $lang.qm"
392 frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
393 TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
394 frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
395 CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
396 done
397 fi
398
399 sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp"
400 if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then
401 # Add dependencies that cannot be formulated as a simple suffix rule.
402 for lang in $ALL_LINGUAS; do
403 frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
404 cat >> "$ac_file.tmp" <<EOF
405$frobbedlang.msg: $lang.po
406 @echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
407 \$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
408EOF
409 done
410 fi
411 if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then
412 # Add dependencies that cannot be formulated as a simple suffix rule.
413 for lang in $ALL_LINGUAS; do
414 frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
415 cat >> "$ac_file.tmp" <<EOF
416$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
417 @echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
418 \$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
419EOF
420 done
421 fi
422 if test -n "$POMAKEFILEDEPS"; then
423 cat >> "$ac_file.tmp" <<EOF
424Makefile: $POMAKEFILEDEPS
425EOF
426 fi
427 mv "$ac_file.tmp" "$ac_file"
428])
diff --git a/gl/m4/printf-posix.m4 b/gl/m4/printf-posix.m4
new file mode 100644
index 00000000..af10170a
--- /dev/null
+++ b/gl/m4/printf-posix.m4
@@ -0,0 +1,44 @@
1# printf-posix.m4 serial 2 (gettext-0.13.1)
2dnl Copyright (C) 2003 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
7dnl From Bruno Haible.
8dnl Test whether the printf() function supports POSIX/XSI format strings with
9dnl positions.
10
11AC_DEFUN([gt_PRINTF_POSIX],
12[
13 AC_REQUIRE([AC_PROG_CC])
14 AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings],
15 gt_cv_func_printf_posix,
16 [
17 AC_TRY_RUN([
18#include <stdio.h>
19#include <string.h>
20/* The string "%2$d %1$d", with dollar characters protected from the shell's
21 dollar expansion (possibly an autoconf bug). */
22static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' };
23static char buf[100];
24int main ()
25{
26 sprintf (buf, format, 33, 55);
27 return (strcmp (buf, "55 33") != 0);
28}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no,
29 [
30 AC_EGREP_CPP(notposix, [
31#if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__
32 notposix
33#endif
34 ], gt_cv_func_printf_posix="guessing no",
35 gt_cv_func_printf_posix="guessing yes")
36 ])
37 ])
38 case $gt_cv_func_printf_posix in
39 *yes)
40 AC_DEFINE(HAVE_POSIX_PRINTF, 1,
41 [Define if your printf() function supports format strings with positions.])
42 ;;
43 esac
44])
diff --git a/gl/m4/progtest.m4 b/gl/m4/progtest.m4
new file mode 100644
index 00000000..a56365cd
--- /dev/null
+++ b/gl/m4/progtest.m4
@@ -0,0 +1,92 @@
1# progtest.m4 serial 4 (gettext-0.14.2)
2dnl Copyright (C) 1996-2003, 2005 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.
6dnl
7dnl This file can can be used in projects which are not available under
8dnl the GNU General Public License or the GNU Library General Public
9dnl License but which still want to provide support for the GNU gettext
10dnl functionality.
11dnl Please note that the actual code of the GNU gettext library is covered
12dnl by the GNU Library General Public License, and the rest of the GNU
13dnl gettext package package is covered by the GNU General Public License.
14dnl They are *not* in the public domain.
15
16dnl Authors:
17dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
18
19AC_PREREQ(2.50)
20
21# Search path for a program which passes the given test.
22
23dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
24dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
25AC_DEFUN([AM_PATH_PROG_WITH_TEST],
26[
27# Prepare PATH_SEPARATOR.
28# The user is always right.
29if test "${PATH_SEPARATOR+set}" != set; then
30 echo "#! /bin/sh" >conf$$.sh
31 echo "exit 0" >>conf$$.sh
32 chmod +x conf$$.sh
33 if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
34 PATH_SEPARATOR=';'
35 else
36 PATH_SEPARATOR=:
37 fi
38 rm -f conf$$.sh
39fi
40
41# Find out how to test for executable files. Don't use a zero-byte file,
42# as systems may use methods other than mode bits to determine executability.
43cat >conf$$.file <<_ASEOF
44#! /bin/sh
45exit 0
46_ASEOF
47chmod +x conf$$.file
48if test -x conf$$.file >/dev/null 2>&1; then
49 ac_executable_p="test -x"
50else
51 ac_executable_p="test -f"
52fi
53rm -f conf$$.file
54
55# Extract the first word of "$2", so it can be a program name with args.
56set dummy $2; ac_word=[$]2
57AC_MSG_CHECKING([for $ac_word])
58AC_CACHE_VAL(ac_cv_path_$1,
59[case "[$]$1" in
60 [[\\/]]* | ?:[[\\/]]*)
61 ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
62 ;;
63 *)
64 ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
65 for ac_dir in ifelse([$5], , $PATH, [$5]); do
66 IFS="$ac_save_IFS"
67 test -z "$ac_dir" && ac_dir=.
68 for ac_exec_ext in '' $ac_executable_extensions; do
69 if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
70 echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
71 if [$3]; then
72 ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
73 break 2
74 fi
75 fi
76 done
77 done
78 IFS="$ac_save_IFS"
79dnl If no 4th arg is given, leave the cache variable unset,
80dnl so AC_PATH_PROGS will keep looking.
81ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
82])dnl
83 ;;
84esac])dnl
85$1="$ac_cv_path_$1"
86if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
87 AC_MSG_RESULT([$]$1)
88else
89 AC_MSG_RESULT(no)
90fi
91AC_SUBST($1)dnl
92])
diff --git a/gl/m4/regex.m4 b/gl/m4/regex.m4
new file mode 100644
index 00000000..25da645e
--- /dev/null
+++ b/gl/m4/regex.m4
@@ -0,0 +1,198 @@
1#serial 42
2
3# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
4# 2006, 2007 Free Software Foundation, Inc.
5#
6# This file is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10dnl Initially derived from code in GNU grep.
11dnl Mostly written by Jim Meyering.
12
13AC_PREREQ([2.50])
14
15AC_DEFUN([gl_REGEX],
16[
17 AC_CHECK_HEADERS_ONCE([locale.h])
18
19 AC_ARG_WITH([included-regex],
20 [AC_HELP_STRING([--without-included-regex],
21 [don't compile regex; this is the default on
22 systems with recent-enough versions of the GNU C
23 Library (use with caution on other systems)])])
24
25 case $with_included_regex in #(
26 yes|no) ac_use_included_regex=$with_included_regex
27 ;;
28 '')
29 # If the system regex support is good enough that it passes the
30 # following run test, then default to *not* using the included regex.c.
31 # If cross compiling, assume the test would fail and use the included
32 # regex.c. The first failing regular expression is from `Spencer ere
33 # test #75' in grep-2.3.
34 AC_CACHE_CHECK([for working re_compile_pattern],
35 [gl_cv_func_re_compile_pattern_working],
36 [AC_RUN_IFELSE(
37 [AC_LANG_PROGRAM(
38 [AC_INCLUDES_DEFAULT
39 #if HAVE_LOCALE_H
40 #include <locale.h>
41 #endif
42 #include <limits.h>
43 #include <regex.h>
44 ],
45 [[static struct re_pattern_buffer regex;
46 unsigned char folded_chars[UCHAR_MAX + 1];
47 int i;
48 const char *s;
49 struct re_registers regs;
50
51 #if HAVE_LOCALE_H
52 /* http://sourceware.org/ml/libc-hacker/2006-09/msg00008.html
53 This test needs valgrind to catch the bug on Debian
54 GNU/Linux 3.1 x86, but it might catch the bug better
55 on other platforms and it shouldn't hurt to try the
56 test here. */
57 if (setlocale (LC_ALL, "en_US.UTF-8"))
58 {
59 static char const pat[] = "insert into";
60 static char const data[] =
61 "\xFF\0\x12\xA2\xAA\xC4\xB1,K\x12\xC4\xB1*\xACK";
62 re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE
63 | RE_ICASE);
64 memset (&regex, 0, sizeof regex);
65 s = re_compile_pattern (pat, sizeof pat - 1, &regex);
66 if (s)
67 return 1;
68 if (re_search (&regex, data, sizeof data - 1,
69 0, sizeof data - 1, &regs)
70 != -1)
71 return 1;
72 if (! setlocale (LC_ALL, "C"))
73 return 1;
74 }
75 #endif
76
77 re_set_syntax (RE_SYNTAX_POSIX_EGREP);
78 memset (&regex, 0, sizeof (regex));
79 for (i = 0; i <= UCHAR_MAX; i++)
80 folded_chars[i] = i;
81 regex.translate = folded_chars;
82 s = re_compile_pattern ("a[[:@:>@:]]b\n", 11, &regex);
83 /* This should fail with _Invalid character class name_ error. */
84 if (!s)
85 exit (1);
86
87 /* This should succeed, but does not for e.g. glibc-2.1.3. */
88 memset (&regex, 0, sizeof (regex));
89 s = re_compile_pattern ("{1", 2, &regex);
90
91 if (s)
92 exit (1);
93
94 /* The following example is derived from a problem report
95 against gawk from Jorge Stolfi <stolfi@ic.unicamp.br>. */
96 memset (&regex, 0, sizeof (regex));
97 s = re_compile_pattern ("[an\371]*n", 7, &regex);
98 if (s)
99 exit (1);
100
101 /* This should match, but does not for e.g. glibc-2.2.1. */
102 if (re_match (&regex, "an", 2, 0, &regs) != 2)
103 exit (1);
104
105 memset (&regex, 0, sizeof (regex));
106 s = re_compile_pattern ("x", 1, &regex);
107 if (s)
108 exit (1);
109
110 /* The version of regex.c in e.g. GNU libc-2.2.93 did not
111 work with a negative RANGE argument. */
112 if (re_search (&regex, "wxy", 3, 2, -2, &regs) != 1)
113 exit (1);
114
115 /* The version of regex.c in older versions of gnulib
116 ignored RE_ICASE. Detect that problem too. */
117 memset (&regex, 0, sizeof (regex));
118 re_set_syntax (RE_SYNTAX_EMACS | RE_ICASE);
119 s = re_compile_pattern ("x", 1, &regex);
120 if (s)
121 exit (1);
122
123 if (re_search (&regex, "WXY", 3, 0, 3, &regs) < 0)
124 exit (1);
125
126 /* REG_STARTEND was added to glibc on 2004-01-15.
127 Reject older versions. */
128 if (! REG_STARTEND)
129 exit (1);
130
131 /* Reject hosts whose regoff_t values are too narrow.
132 These include glibc 2.3.5 on hosts with 64-bit ptrdiff_t
133 and 32-bit int. */
134 if (sizeof (regoff_t) < sizeof (ptrdiff_t)
135 || sizeof (regoff_t) < sizeof (ssize_t))
136 exit (1);
137
138 exit (0);]])],
139 [gl_cv_func_re_compile_pattern_working=yes],
140 [gl_cv_func_re_compile_pattern_working=no],
141 dnl When crosscompiling, assume it is not working.
142 [gl_cv_func_re_compile_pattern_working=no])])
143 case $gl_cv_func_re_compile_pattern_working in #(
144 yes) ac_use_included_regex=no;; #(
145 no) ac_use_included_regex=yes;;
146 esac
147 ;;
148 *) AC_MSG_ERROR([Invalid value for --with-included-regex: $with_included_regex])
149 ;;
150 esac
151
152 if test $ac_use_included_regex = yes; then
153 AC_DEFINE([_REGEX_LARGE_OFFSETS], 1,
154 [Define if you want regoff_t to be at least as wide POSIX requires.])
155 AC_DEFINE([re_syntax_options], [rpl_re_syntax_options],
156 [Define to rpl_re_syntax_options if the replacement should be used.])
157 AC_DEFINE([re_set_syntax], [rpl_re_set_syntax],
158 [Define to rpl_re_set_syntax if the replacement should be used.])
159 AC_DEFINE([re_compile_pattern], [rpl_re_compile_pattern],
160 [Define to rpl_re_compile_pattern if the replacement should be used.])
161 AC_DEFINE([re_compile_fastmap], [rpl_re_compile_fastmap],
162 [Define to rpl_re_compile_fastmap if the replacement should be used.])
163 AC_DEFINE([re_search], [rpl_re_search],
164 [Define to rpl_re_search if the replacement should be used.])
165 AC_DEFINE([re_search_2], [rpl_re_search_2],
166 [Define to rpl_re_search_2 if the replacement should be used.])
167 AC_DEFINE([re_match], [rpl_re_match],
168 [Define to rpl_re_match if the replacement should be used.])
169 AC_DEFINE([re_match_2], [rpl_re_match_2],
170 [Define to rpl_re_match_2 if the replacement should be used.])
171 AC_DEFINE([re_set_registers], [rpl_re_set_registers],
172 [Define to rpl_re_set_registers if the replacement should be used.])
173 AC_DEFINE([re_comp], [rpl_re_comp],
174 [Define to rpl_re_comp if the replacement should be used.])
175 AC_DEFINE([re_exec], [rpl_re_exec],
176 [Define to rpl_re_exec if the replacement should be used.])
177 AC_DEFINE([regcomp], [rpl_regcomp],
178 [Define to rpl_regcomp if the replacement should be used.])
179 AC_DEFINE([regexec], [rpl_regexec],
180 [Define to rpl_regexec if the replacement should be used.])
181 AC_DEFINE([regerror], [rpl_regerror],
182 [Define to rpl_regerror if the replacement should be used.])
183 AC_DEFINE([regfree], [rpl_regfree],
184 [Define to rpl_regfree if the replacement should be used.])
185 AC_LIBOBJ([regex])
186 gl_PREREQ_REGEX
187 fi
188])
189
190# Prerequisites of lib/regex.c and lib/regex_internal.c.
191AC_DEFUN([gl_PREREQ_REGEX],
192[
193 AC_REQUIRE([AC_GNU_SOURCE])
194 AC_REQUIRE([AC_C_RESTRICT])
195 AC_REQUIRE([AM_LANGINFO_CODESET])
196 AC_CHECK_FUNCS_ONCE([iswctype mbrtowc mempcpy wcrtomb wcscoll])
197 AC_CHECK_DECLS([isblank], [], [], [#include <ctype.h>])
198])
diff --git a/gl/m4/safe-read.m4 b/gl/m4/safe-read.m4
new file mode 100644
index 00000000..7a89d0a6
--- /dev/null
+++ b/gl/m4/safe-read.m4
@@ -0,0 +1,18 @@
1# safe-read.m4 serial 5
2dnl Copyright (C) 2002, 2003, 2005, 2006 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_SAFE_READ],
8[
9 AC_LIBOBJ([safe-read])
10
11 gl_PREREQ_SAFE_READ
12])
13
14# Prerequisites of lib/safe-read.c.
15AC_DEFUN([gl_PREREQ_SAFE_READ],
16[
17 AC_REQUIRE([gt_TYPE_SSIZE_T])
18])
diff --git a/gl/m4/safe-write.m4 b/gl/m4/safe-write.m4
new file mode 100644
index 00000000..db119ffa
--- /dev/null
+++ b/gl/m4/safe-write.m4
@@ -0,0 +1,18 @@
1# safe-write.m4 serial 3
2dnl Copyright (C) 2002, 2005, 2006 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_SAFE_WRITE],
8[
9 AC_LIBOBJ([safe-write])
10
11 gl_PREREQ_SAFE_WRITE
12])
13
14# Prerequisites of lib/safe-write.c.
15AC_DEFUN([gl_PREREQ_SAFE_WRITE],
16[
17 gl_PREREQ_SAFE_READ
18])
diff --git a/gl/m4/size_max.m4 b/gl/m4/size_max.m4
new file mode 100644
index 00000000..6cb48689
--- /dev/null
+++ b/gl/m4/size_max.m4
@@ -0,0 +1,68 @@
1# size_max.m4 serial 6
2dnl Copyright (C) 2003, 2005-2006 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
7dnl From Bruno Haible.
8
9AC_DEFUN([gl_SIZE_MAX],
10[
11 AC_CHECK_HEADERS(stdint.h)
12 dnl First test whether the system already has SIZE_MAX.
13 AC_MSG_CHECKING([for SIZE_MAX])
14 AC_CACHE_VAL([gl_cv_size_max], [
15 gl_cv_size_max=
16 AC_EGREP_CPP([Found it], [
17#include <limits.h>
18#if HAVE_STDINT_H
19#include <stdint.h>
20#endif
21#ifdef SIZE_MAX
22Found it
23#endif
24], gl_cv_size_max=yes)
25 if test -z "$gl_cv_size_max"; then
26 dnl Define it ourselves. Here we assume that the type 'size_t' is not wider
27 dnl than the type 'unsigned long'. Try hard to find a definition that can
28 dnl be used in a preprocessor #if, i.e. doesn't contain a cast.
29 AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1],
30 [#include <stddef.h>
31#include <limits.h>], size_t_bits_minus_1=)
32 AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)],
33 [#include <stddef.h>], fits_in_uint=)
34 if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then
35 if test $fits_in_uint = 1; then
36 dnl Even though SIZE_MAX fits in an unsigned int, it must be of type
37 dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'.
38 AC_TRY_COMPILE([#include <stddef.h>
39 extern size_t foo;
40 extern unsigned long foo;
41 ], [], fits_in_uint=0)
42 fi
43 dnl We cannot use 'expr' to simplify this expression, because 'expr'
44 dnl works only with 'long' integers in the host environment, while we
45 dnl might be cross-compiling from a 32-bit platform to a 64-bit platform.
46 if test $fits_in_uint = 1; then
47 gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)"
48 else
49 gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)"
50 fi
51 else
52 dnl Shouldn't happen, but who knows...
53 gl_cv_size_max='((size_t)~(size_t)0)'
54 fi
55 fi
56 ])
57 AC_MSG_RESULT([$gl_cv_size_max])
58 if test "$gl_cv_size_max" != yes; then
59 AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max],
60 [Define as the maximum value of type 'size_t', if the system doesn't define it.])
61 fi
62])
63
64dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
65dnl Remove this when we can assume autoconf >= 2.61.
66m4_ifdef([AC_COMPUTE_INT], [], [
67 AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
68])
diff --git a/gl/m4/snprintf.m4 b/gl/m4/snprintf.m4
new file mode 100644
index 00000000..432e0375
--- /dev/null
+++ b/gl/m4/snprintf.m4
@@ -0,0 +1,15 @@
1# snprintf.m4 serial 2
2dnl Copyright (C) 2002, 2003, 2004 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_FUNC_SNPRINTF],
8[
9 AC_REPLACE_FUNCS(snprintf)
10 AC_CHECK_DECLS_ONCE(snprintf)
11 gl_PREREQ_SNPRINTF
12])
13
14# Prerequisites of lib/snprintf.c.
15AC_DEFUN([gl_PREREQ_SNPRINTF], [:])
diff --git a/gl/m4/socklen.m4 b/gl/m4/socklen.m4
new file mode 100644
index 00000000..5e3765a6
--- /dev/null
+++ b/gl/m4/socklen.m4
@@ -0,0 +1,52 @@
1# socklen.m4 serial 4
2dnl Copyright (C) 2005, 2006 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
7dnl From Albert Chin, Windows fixes from Simon Josefsson.
8
9dnl Check for socklen_t: historically on BSD it is an int, and in
10dnl POSIX 1g it is a type of its own, but some platforms use different
11dnl types for the argument to getsockopt, getpeername, etc. So we
12dnl have to test to find something that will work.
13
14dnl On mingw32, socklen_t is in ws2tcpip.h ('int'), so we try to find
15dnl it there first. That file is included by gnulib's socket_.h, which
16dnl all users of this module should include. Cygwin must not include
17dnl ws2tcpip.h.
18AC_DEFUN([gl_TYPE_SOCKLEN_T],
19 [AC_REQUIRE([gl_HEADER_SYS_SOCKET])dnl
20 AC_CHECK_TYPE([socklen_t], ,
21 [AC_MSG_CHECKING([for socklen_t equivalent])
22 AC_CACHE_VAL([gl_cv_gl_cv_socklen_t_equiv],
23 [# Systems have either "struct sockaddr *" or
24 # "void *" as the second argument to getpeername
25 gl_cv_socklen_t_equiv=
26 for arg2 in "struct sockaddr" void; do
27 for t in int size_t "unsigned int" "long int" "unsigned long int"; do
28 AC_TRY_COMPILE(
29 [#include <sys/types.h>
30 #include <sys/socket.h>
31
32 int getpeername (int, $arg2 *, $t *);],
33 [$t len;
34 getpeername (0, 0, &len);],
35 [gl_cv_socklen_t_equiv="$t"])
36 test "$gl_cv_socklen_t_equiv" != "" && break
37 done
38 test "$gl_cv_socklen_t_equiv" != "" && break
39 done
40 ])
41 if test "$gl_cv_socklen_t_equiv" = ""; then
42 AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
43 fi
44 AC_MSG_RESULT([$gl_cv_socklen_t_equiv])
45 AC_DEFINE_UNQUOTED([socklen_t], [$gl_cv_socklen_t_equiv],
46 [type to use in place of socklen_t if not defined])],
47 [#include <sys/types.h>
48 #if HAVE_SYS_SOCKET_H
49 # include <sys/socket.h>
50 #elif HAVE_WS2TCPIP_H
51 # include <ws2tcpip.h>
52 #endif])])
diff --git a/gl/m4/sockpfaf.m4 b/gl/m4/sockpfaf.m4
new file mode 100644
index 00000000..25d9755c
--- /dev/null
+++ b/gl/m4/sockpfaf.m4
@@ -0,0 +1,58 @@
1# sockpfaf.m4 serial 5
2dnl Copyright (C) 2004, 2006 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
7dnl Test for some common socket protocol families (PF_INET, PF_INET6, ...)
8dnl and some common address families (AF_INET, AF_INET6, ...).
9dnl This test assumes that a system supports an address family if and only if
10dnl it supports the corresponding protocol family.
11
12dnl From Bruno Haible.
13
14AC_DEFUN([gl_SOCKET_FAMILIES],
15[
16 AC_REQUIRE([gl_HEADER_SYS_SOCKET])
17 AC_CHECK_HEADERS_ONCE([netinet/in.h])
18
19 AC_MSG_CHECKING(for IPv4 sockets)
20 AC_CACHE_VAL(gl_cv_socket_ipv4,
21 [AC_TRY_COMPILE([#include <sys/types.h>
22#ifdef HAVE_SYS_SOCKET_H
23#include <sys/socket.h>
24#endif
25#ifdef HAVE_NETINET_IN_H
26#include <netinet/in.h>
27#endif
28#ifdef HAVE_WINSOCK2_H
29#include <winsock2.h>
30#endif],
31[int x = AF_INET; struct in_addr y; struct sockaddr_in z;
32 if (&x && &y && &z) return 0;],
33 gl_cv_socket_ipv4=yes, gl_cv_socket_ipv4=no)])
34 AC_MSG_RESULT($gl_cv_socket_ipv4)
35 if test $gl_cv_socket_ipv4 = yes; then
36 AC_DEFINE(HAVE_IPV4, 1, [Define to 1 if <sys/socket.h> defines AF_INET.])
37 fi
38
39 AC_MSG_CHECKING(for IPv6 sockets)
40 AC_CACHE_VAL(gl_cv_socket_ipv6,
41 [AC_TRY_COMPILE([#include <sys/types.h>
42#ifdef HAVE_SYS_SOCKET_H
43#include <sys/socket.h>
44#endif
45#ifdef HAVE_NETINET_IN_H
46#include <netinet/in.h>
47#endif
48#ifdef HAVE_WINSOCK2_H
49#include <winsock2.h>
50#endif],
51[int x = AF_INET6; struct in6_addr y; struct sockaddr_in6 z;
52 if (&x && &y && &z) return 0;],
53 gl_cv_socket_ipv6=yes, gl_cv_socket_ipv6=no)])
54 AC_MSG_RESULT($gl_cv_socket_ipv6)
55 if test $gl_cv_socket_ipv6 = yes; then
56 AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if <sys/socket.h> defines AF_INET6.])
57 fi
58])
diff --git a/gl/m4/ssize_t.m4 b/gl/m4/ssize_t.m4
new file mode 100644
index 00000000..4eaef93c
--- /dev/null
+++ b/gl/m4/ssize_t.m4
@@ -0,0 +1,21 @@
1# ssize_t.m4 serial 4 (gettext-0.15)
2dnl Copyright (C) 2001-2003, 2006 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
7dnl From Bruno Haible.
8dnl Test whether ssize_t is defined.
9
10AC_DEFUN([gt_TYPE_SSIZE_T],
11[
12 AC_CACHE_CHECK([for ssize_t], [gt_cv_ssize_t],
13 [AC_TRY_COMPILE([#include <sys/types.h>],
14 [int x = sizeof (ssize_t *) + sizeof (ssize_t);
15 return !x;],
16 [gt_cv_ssize_t=yes], [gt_cv_ssize_t=no])])
17 if test $gt_cv_ssize_t = no; then
18 AC_DEFINE([ssize_t], [int],
19 [Define as a signed type of the same size as size_t.])
20 fi
21])
diff --git a/gl/m4/stdbool.m4 b/gl/m4/stdbool.m4
new file mode 100644
index 00000000..2204ecd9
--- /dev/null
+++ b/gl/m4/stdbool.m4
@@ -0,0 +1,115 @@
1# Check for stdbool.h that conforms to C99.
2
3dnl Copyright (C) 2002-2006 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8# Prepare for substituting <stdbool.h> if it is not supported.
9
10AC_DEFUN([AM_STDBOOL_H],
11[
12 AC_REQUIRE([AC_HEADER_STDBOOL])
13
14 # Define two additional variables used in the Makefile substitution.
15
16 if test "$ac_cv_header_stdbool_h" = yes; then
17 STDBOOL_H=''
18 else
19 STDBOOL_H='stdbool.h'
20 fi
21 AC_SUBST([STDBOOL_H])
22
23 if test "$ac_cv_type__Bool" = yes; then
24 HAVE__BOOL=1
25 else
26 HAVE__BOOL=0
27 fi
28 AC_SUBST([HAVE__BOOL])
29])
30
31# AM_STDBOOL_H will be renamed to gl_STDBOOL_H in the future.
32AC_DEFUN([gl_STDBOOL_H], [AM_STDBOOL_H])
33
34# This macro is only needed in autoconf <= 2.59. Newer versions of autoconf
35# have this macro built-in.
36
37AC_DEFUN([AC_HEADER_STDBOOL],
38 [AC_CACHE_CHECK([for stdbool.h that conforms to C99],
39 [ac_cv_header_stdbool_h],
40 [AC_TRY_COMPILE(
41 [
42 #include <stdbool.h>
43 #ifndef bool
44 "error: bool is not defined"
45 #endif
46 #ifndef false
47 "error: false is not defined"
48 #endif
49 #if false
50 "error: false is not 0"
51 #endif
52 #ifndef true
53 "error: true is not defined"
54 #endif
55 #if true != 1
56 "error: true is not 1"
57 #endif
58 #ifndef __bool_true_false_are_defined
59 "error: __bool_true_false_are_defined is not defined"
60 #endif
61
62 struct s { _Bool s: 1; _Bool t; } s;
63
64 char a[true == 1 ? 1 : -1];
65 char b[false == 0 ? 1 : -1];
66 char c[__bool_true_false_are_defined == 1 ? 1 : -1];
67 char d[(bool) 0.5 == true ? 1 : -1];
68 bool e = &s;
69 char f[(_Bool) 0.0 == false ? 1 : -1];
70 char g[true];
71 char h[sizeof (_Bool)];
72 char i[sizeof s.t];
73 enum { j = false, k = true, l = false * true, m = true * 256 };
74 _Bool n[m];
75 char o[sizeof n == m * sizeof n[0] ? 1 : -1];
76 char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
77 #if defined __xlc__ || defined __GNUC__
78 /* Catch a bug in IBM AIX xlc compiler version 6.0.0.0
79 reported by James Lemley on 2005-10-05; see
80 http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
81 This test is not quite right, since xlc is allowed to
82 reject this program, as the initializer for xlcbug is
83 not one of the forms that C requires support for.
84 However, doing the test right would require a run-time
85 test, and that would make cross-compilation harder.
86 Let us hope that IBM fixes the xlc bug, and also adds
87 support for this kind of constant expression. In the
88 meantime, this test will reject xlc, which is OK, since
89 our stdbool.h substitute should suffice. We also test
90 this with GCC, where it should work, to detect more
91 quickly whether someone messes up the test in the
92 future. */
93 char digs[] = "0123456789";
94 int xlcbug = 1 / (&(digs + 5)[-2 + (bool) 1] == &digs[4] ? 1 : -1);
95 #endif
96 /* Catch a bug in an HP-UX C compiler. See
97 http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
98 http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
99 */
100 _Bool q = true;
101 _Bool *pq = &q;
102 ],
103 [
104 *pq |= q;
105 *pq |= ! q;
106 /* Refer to every declared value, to avoid compiler optimizations. */
107 return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
108 + !m + !n + !o + !p + !q + !pq);
109 ],
110 [ac_cv_header_stdbool_h=yes],
111 [ac_cv_header_stdbool_h=no])])
112 AC_CHECK_TYPES([_Bool])
113 if test $ac_cv_header_stdbool_h = yes; then
114 AC_DEFINE(HAVE_STDBOOL_H, 1, [Define to 1 if stdbool.h conforms to C99.])
115 fi])
diff --git a/gl/m4/stdint.m4 b/gl/m4/stdint.m4
new file mode 100644
index 00000000..1a4b4a6a
--- /dev/null
+++ b/gl/m4/stdint.m4
@@ -0,0 +1,369 @@
1# stdint.m4 serial 22
2dnl Copyright (C) 2001-2002, 2004-2007 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
7dnl From Paul Eggert and Bruno Haible.
8dnl Test whether <stdint.h> is supported or must be substituted.
9
10AC_DEFUN([gl_STDINT_H],
11[
12 AC_PREREQ(2.59)dnl
13
14 dnl Check for long long int and unsigned long long int.
15 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
16 if test $ac_cv_type_long_long_int = yes; then
17 HAVE_LONG_LONG_INT=1
18 else
19 HAVE_LONG_LONG_INT=0
20 fi
21 AC_SUBST([HAVE_LONG_LONG_INT])
22 AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
23 if test $ac_cv_type_unsigned_long_long_int = yes; then
24 HAVE_UNSIGNED_LONG_LONG_INT=1
25 else
26 HAVE_UNSIGNED_LONG_LONG_INT=0
27 fi
28 AC_SUBST([HAVE_UNSIGNED_LONG_LONG_INT])
29
30 dnl Check for <inttypes.h>.
31 dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_inttypes_h.
32 if test $ac_cv_header_inttypes_h = yes; then
33 HAVE_INTTYPES_H=1
34 else
35 HAVE_INTTYPES_H=0
36 fi
37 AC_SUBST([HAVE_INTTYPES_H])
38
39 dnl Check for <sys/types.h>.
40 dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_sys_types_h.
41 if test $ac_cv_header_sys_types_h = yes; then
42 HAVE_SYS_TYPES_H=1
43 else
44 HAVE_SYS_TYPES_H=0
45 fi
46 AC_SUBST([HAVE_SYS_TYPES_H])
47
48 dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_stdint_h.
49 if test $ac_cv_header_stdint_h = yes; then
50 gl_ABSOLUTE_HEADER([stdint.h])
51 ABSOLUTE_STDINT_H=\"$gl_cv_absolute_stdint_h\"
52 HAVE_STDINT_H=1
53 else
54 ABSOLUTE_STDINT_H=\"no/such/file/stdint.h\"
55 HAVE_STDINT_H=0
56 fi
57 AC_SUBST([ABSOLUTE_STDINT_H])
58 AC_SUBST([HAVE_STDINT_H])
59
60 dnl Now see whether we need a substitute <stdint.h>. Use
61 dnl ABSOLUTE_STDINT_H, not <stdint.h>, so that it also works during
62 dnl a "config.status --recheck" if a stdint.h has been
63 dnl created in the build directory.
64 if test $ac_cv_header_stdint_h = yes; then
65 AC_CACHE_CHECK([whether stdint.h conforms to C99],
66 [gl_cv_header_working_stdint_h],
67 [gl_cv_header_working_stdint_h=no
68 AC_COMPILE_IFELSE([
69 AC_LANG_PROGRAM([[
70#include <stddef.h>
71#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
72#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
73#include ABSOLUTE_STDINT_H
74#ifdef INT8_MAX
75int8_t a1 = INT8_MAX;
76int8_t a1min = INT8_MIN;
77#endif
78#ifdef INT16_MAX
79int16_t a2 = INT16_MAX;
80int16_t a2min = INT16_MIN;
81#endif
82#ifdef INT32_MAX
83int32_t a3 = INT32_MAX;
84int32_t a3min = INT32_MIN;
85#endif
86#ifdef INT64_MAX
87int64_t a4 = INT64_MAX;
88int64_t a4min = INT64_MIN;
89#endif
90#ifdef UINT8_MAX
91uint8_t b1 = UINT8_MAX;
92#else
93typedef int b1[(unsigned char) -1 != 255 ? 1 : -1];
94#endif
95#ifdef UINT16_MAX
96uint16_t b2 = UINT16_MAX;
97#endif
98#ifdef UINT32_MAX
99uint32_t b3 = UINT32_MAX;
100#endif
101#ifdef UINT64_MAX
102uint64_t b4 = UINT64_MAX;
103#endif
104int_least8_t c1 = INT8_C (0x7f);
105int_least8_t c1max = INT_LEAST8_MAX;
106int_least8_t c1min = INT_LEAST8_MIN;
107int_least16_t c2 = INT16_C (0x7fff);
108int_least16_t c2max = INT_LEAST16_MAX;
109int_least16_t c2min = INT_LEAST16_MIN;
110int_least32_t c3 = INT32_C (0x7fffffff);
111int_least32_t c3max = INT_LEAST32_MAX;
112int_least32_t c3min = INT_LEAST32_MIN;
113int_least64_t c4 = INT64_C (0x7fffffffffffffff);
114int_least64_t c4max = INT_LEAST64_MAX;
115int_least64_t c4min = INT_LEAST64_MIN;
116uint_least8_t d1 = UINT8_C (0xff);
117uint_least8_t d1max = UINT_LEAST8_MAX;
118uint_least16_t d2 = UINT16_C (0xffff);
119uint_least16_t d2max = UINT_LEAST16_MAX;
120uint_least32_t d3 = UINT32_C (0xffffffff);
121uint_least32_t d3max = UINT_LEAST32_MAX;
122uint_least64_t d4 = UINT64_C (0xffffffffffffffff);
123uint_least64_t d4max = UINT_LEAST64_MAX;
124int_fast8_t e1 = INT_FAST8_MAX;
125int_fast8_t e1min = INT_FAST8_MIN;
126int_fast16_t e2 = INT_FAST16_MAX;
127int_fast16_t e2min = INT_FAST16_MIN;
128int_fast32_t e3 = INT_FAST32_MAX;
129int_fast32_t e3min = INT_FAST32_MIN;
130int_fast64_t e4 = INT_FAST64_MAX;
131int_fast64_t e4min = INT_FAST64_MIN;
132uint_fast8_t f1 = UINT_FAST8_MAX;
133uint_fast16_t f2 = UINT_FAST16_MAX;
134uint_fast32_t f3 = UINT_FAST32_MAX;
135uint_fast64_t f4 = UINT_FAST64_MAX;
136#ifdef INTPTR_MAX
137intptr_t g = INTPTR_MAX;
138intptr_t gmin = INTPTR_MIN;
139#endif
140#ifdef UINTPTR_MAX
141uintptr_t h = UINTPTR_MAX;
142#endif
143intmax_t i = INTMAX_MAX;
144uintmax_t j = UINTMAX_MAX;
145struct s {
146 int check_PTRDIFF: PTRDIFF_MIN < 0 && 0 < PTRDIFF_MAX ? 1 : -1;
147 int check_SIG_ATOMIC: SIG_ATOMIC_MIN <= 0 && 0 < SIG_ATOMIC_MAX ? 1 : -1;
148 int check_SIZE: 0 < SIZE_MAX ? 1 : -1;
149 int check_WCHAR: WCHAR_MIN <= 0 && 0 < WCHAR_MAX ? 1 : -1;
150 int check_WINT: WINT_MIN <= 0 && 0 < WINT_MAX ? 1 : -1;
151
152 /* Detect bugs in glibc 2.4 and Solaris 10 stdint.h, among others. */
153 int check_UINT8_C:
154 (-1 < UINT8_C (0)) == (-1 < (uint_least8_t) 0) ? 1 : -1;
155 int check_UINT16_C:
156 (-1 < UINT16_C (0)) == (-1 < (uint_least16_t) 0) ? 1 : -1;
157
158 /* Detect bugs in OpenBSD 3.9 stdint.h. */
159#ifdef UINT8_MAX
160 int check_uint8: (uint8_t) -1 == UINT8_MAX ? 1 : -1;
161#endif
162#ifdef UINT16_MAX
163 int check_uint16: (uint16_t) -1 == UINT16_MAX ? 1 : -1;
164#endif
165#ifdef UINT32_MAX
166 int check_uint32: (uint32_t) -1 == UINT32_MAX ? 1 : -1;
167#endif
168#ifdef UINT64_MAX
169 int check_uint64: (uint64_t) -1 == UINT64_MAX ? 1 : -1;
170#endif
171 int check_uint_least8: (uint_least8_t) -1 == UINT_LEAST8_MAX ? 1 : -1;
172 int check_uint_least16: (uint_least16_t) -1 == UINT_LEAST16_MAX ? 1 : -1;
173 int check_uint_least32: (uint_least32_t) -1 == UINT_LEAST32_MAX ? 1 : -1;
174 int check_uint_least64: (uint_least64_t) -1 == UINT_LEAST64_MAX ? 1 : -1;
175 int check_uint_fast8: (uint_fast8_t) -1 == UINT_FAST8_MAX ? 1 : -1;
176 int check_uint_fast16: (uint_fast16_t) -1 == UINT_FAST16_MAX ? 1 : -1;
177 int check_uint_fast32: (uint_fast32_t) -1 == UINT_FAST32_MAX ? 1 : -1;
178 int check_uint_fast64: (uint_fast64_t) -1 == UINT_FAST64_MAX ? 1 : -1;
179 int check_uintptr: (uintptr_t) -1 == UINTPTR_MAX ? 1 : -1;
180 int check_uintmax: (uintmax_t) -1 == UINTMAX_MAX ? 1 : -1;
181 int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1;
182};
183 ]])],
184 [gl_cv_header_working_stdint_h=yes])])
185 fi
186 if test "$gl_cv_header_working_stdint_h" = yes; then
187 STDINT_H=
188 else
189 dnl Check for <sys/inttypes.h>, and for
190 dnl <sys/bitypes.h> (used in Linux libc4 >= 4.6.7 and libc5).
191 AC_CHECK_HEADERS([sys/inttypes.h sys/bitypes.h])
192 if test $ac_cv_header_sys_inttypes_h = yes; then
193 HAVE_SYS_INTTYPES_H=1
194 else
195 HAVE_SYS_INTTYPES_H=0
196 fi
197 AC_SUBST([HAVE_SYS_INTTYPES_H])
198 if test $ac_cv_header_sys_bitypes_h = yes; then
199 HAVE_SYS_BITYPES_H=1
200 else
201 HAVE_SYS_BITYPES_H=0
202 fi
203 AC_SUBST([HAVE_SYS_BITYPES_H])
204
205 gl_STDINT_TYPE_PROPERTIES
206 STDINT_H=stdint.h
207 fi
208 AC_SUBST(STDINT_H)
209])
210
211dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES)
212dnl Determine the size of each of the given types in bits.
213AC_DEFUN([gl_STDINT_BITSIZEOF],
214[
215 dnl Use a shell loop, to avoid bloating configure, and
216 dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
217 dnl config.h.in,
218 dnl - extra AC_SUBST calls, so that the right substitutions are made.
219 AC_FOREACH([gltype], [$1],
220 [AH_TEMPLATE([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]),
221 [Define to the number of bits in type ']gltype['.])])
222 for gltype in $1 ; do
223 AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}],
224 [AC_COMPUTE_INT([result], [sizeof ($gltype) * CHAR_BIT],
225 [$2
226#include <limits.h>], [result=unknown])
227 eval gl_cv_bitsizeof_${gltype}=\$result
228 ])
229 eval result=\$gl_cv_bitsizeof_${gltype}
230 if test $result = unknown; then
231 dnl Use a nonempty default, because some compilers, such as IRIX 5 cc,
232 dnl do a syntax check even on unused #if conditions and give an error
233 dnl on valid C code like this:
234 dnl #if 0
235 dnl # if > 32
236 dnl # endif
237 dnl #endif
238 result=0
239 fi
240 GLTYPE=`echo "$gltype" | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
241 AC_DEFINE_UNQUOTED([BITSIZEOF_${GLTYPE}], [$result])
242 eval BITSIZEOF_${GLTYPE}=\$result
243 done
244 AC_FOREACH([gltype], [$1],
245 [AC_SUBST([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))])
246])
247
248dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES)
249dnl Determine the signedness of each of the given types.
250dnl Define HAVE_SIGNED_TYPE if type is signed.
251AC_DEFUN([gl_CHECK_TYPES_SIGNED],
252[
253 dnl Use a shell loop, to avoid bloating configure, and
254 dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
255 dnl config.h.in,
256 dnl - extra AC_SUBST calls, so that the right substitutions are made.
257 AC_FOREACH([gltype], [$1],
258 [AH_TEMPLATE([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]),
259 [Define to 1 if ']gltype[' is a signed integer type.])])
260 for gltype in $1 ; do
261 AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed],
262 [AC_COMPILE_IFELSE(
263 [AC_LANG_PROGRAM([$2[
264 int verify[2 * (($gltype) -1 < ($gltype) 0) - 1];]])],
265 result=yes, result=no)
266 eval gl_cv_type_${gltype}_signed=\$result
267 ])
268 eval result=\$gl_cv_type_${gltype}_signed
269 GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
270 if test "$result" = yes; then
271 AC_DEFINE_UNQUOTED([HAVE_SIGNED_${GLTYPE}], 1)
272 eval HAVE_SIGNED_${GLTYPE}=1
273 else
274 eval HAVE_SIGNED_${GLTYPE}=0
275 fi
276 done
277 AC_FOREACH([gltype], [$1],
278 [AC_SUBST([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))])
279])
280
281dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES)
282dnl Determine the suffix to use for integer constants of the given types.
283dnl Define t_SUFFIX for each such type.
284AC_DEFUN([gl_INTEGER_TYPE_SUFFIX],
285[
286 dnl Use a shell loop, to avoid bloating configure, and
287 dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
288 dnl config.h.in,
289 dnl - extra AC_SUBST calls, so that the right substitutions are made.
290 AC_FOREACH([gltype], [$1],
291 [AH_TEMPLATE(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX],
292 [Define to l, ll, u, ul, ull, etc., as suitable for
293 constants of type ']gltype['.])])
294 for gltype in $1 ; do
295 AC_CACHE_CHECK([for $gltype integer literal suffix],
296 [gl_cv_type_${gltype}_suffix],
297 [eval gl_cv_type_${gltype}_suffix=no
298 eval result=\$gl_cv_type_${gltype}_signed
299 if test "$result" = yes; then
300 glsufu=
301 else
302 glsufu=u
303 fi
304 for glsuf in "$glsufu" ${glsufu}l ${glsufu}ll ${glsufu}i64; do
305 case $glsuf in
306 '') gltype1='int';;
307 l) gltype1='long int';;
308 ll) gltype1='long long int';;
309 i64) gltype1='__int64';;
310 u) gltype1='unsigned int';;
311 ul) gltype1='unsigned long int';;
312 ull) gltype1='unsigned long long int';;
313 ui64)gltype1='unsigned __int64';;
314 esac
315 AC_COMPILE_IFELSE(
316 [AC_LANG_PROGRAM([$2
317 extern $gltype foo;
318 extern $gltype1 foo;])],
319 [eval gl_cv_type_${gltype}_suffix=\$glsuf])
320 eval result=\$gl_cv_type_${gltype}_suffix
321 test "$result" != no && break
322 done])
323 GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
324 eval result=\$gl_cv_type_${gltype}_suffix
325 test "$result" = no && result=
326 eval ${GLTYPE}_SUFFIX=\$result
327 AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], $result)
328 done
329 AC_FOREACH([gltype], [$1],
330 [AC_SUBST(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])])
331])
332
333dnl gl_STDINT_INCLUDES
334AC_DEFUN([gl_STDINT_INCLUDES],
335[[
336 /* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
337 included before <wchar.h>. */
338 #include <stddef.h>
339 #include <signal.h>
340 #include <stdio.h>
341 #include <time.h>
342 #include <wchar.h>
343]])
344
345dnl gl_STDINT_TYPE_PROPERTIES
346dnl Compute HAVE_SIGNED_t, BITSIZEOF_t and t_SUFFIX, for all the types t
347dnl of interest to stdint_.h.
348AC_DEFUN([gl_STDINT_TYPE_PROPERTIES],
349[
350 gl_STDINT_BITSIZEOF([ptrdiff_t sig_atomic_t size_t wchar_t wint_t],
351 [gl_STDINT_INCLUDES])
352 gl_CHECK_TYPES_SIGNED([sig_atomic_t wchar_t wint_t],
353 [gl_STDINT_INCLUDES])
354 gl_cv_type_ptrdiff_t_signed=yes
355 gl_cv_type_size_t_signed=no
356 gl_INTEGER_TYPE_SUFFIX([ptrdiff_t sig_atomic_t size_t wchar_t wint_t],
357 [gl_STDINT_INCLUDES])
358])
359
360dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
361dnl Remove this when we can assume autoconf >= 2.61.
362m4_ifdef([AC_COMPUTE_INT], [], [
363 AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
364])
365
366# Hey Emacs!
367# Local Variables:
368# indent-tabs-mode: nil
369# End:
diff --git a/gl/m4/stdint_h.m4 b/gl/m4/stdint_h.m4
new file mode 100644
index 00000000..db9a8ac4
--- /dev/null
+++ b/gl/m4/stdint_h.m4
@@ -0,0 +1,26 @@
1# stdint_h.m4 serial 6
2dnl Copyright (C) 1997-2004, 2006 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
7dnl From Paul Eggert.
8
9# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
10# doesn't clash with <sys/types.h>, and declares uintmax_t.
11
12AC_DEFUN([gl_AC_HEADER_STDINT_H],
13[
14 AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h,
15 [AC_TRY_COMPILE(
16 [#include <sys/types.h>
17#include <stdint.h>],
18 [uintmax_t i = (uintmax_t) -1; return !i;],
19 gl_cv_header_stdint_h=yes,
20 gl_cv_header_stdint_h=no)])
21 if test $gl_cv_header_stdint_h = yes; then
22 AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1,
23 [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
24 and declares uintmax_t. ])
25 fi
26])
diff --git a/gl/m4/strcase.m4 b/gl/m4/strcase.m4
new file mode 100644
index 00000000..ae827907
--- /dev/null
+++ b/gl/m4/strcase.m4
@@ -0,0 +1,39 @@
1# strcase.m4 serial 4
2dnl Copyright (C) 2002, 2005-2006 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_STRCASE],
8[
9 gl_FUNC_STRCASECMP
10 gl_FUNC_STRNCASECMP
11])
12
13AC_DEFUN([gl_FUNC_STRCASECMP],
14[
15 dnl No known system has a strcasecmp() function that works correctly in
16 dnl multibyte locales. Therefore we use our version always.
17 AC_LIBOBJ(strcasecmp)
18 gl_PREREQ_STRCASECMP
19])
20
21AC_DEFUN([gl_FUNC_STRNCASECMP],
22[
23 AC_REPLACE_FUNCS(strncasecmp)
24 AC_CHECK_DECLS(strncasecmp)
25 if test $ac_cv_func_strncasecmp = no; then
26 gl_PREREQ_STRNCASECMP
27 fi
28])
29
30# Prerequisites of lib/strcasecmp.c.
31AC_DEFUN([gl_PREREQ_STRCASECMP], [
32 AC_REQUIRE([gl_FUNC_MBRTOWC])
33 :
34])
35
36# Prerequisites of lib/strncasecmp.c.
37AC_DEFUN([gl_PREREQ_STRNCASECMP], [
38 :
39])
diff --git a/gl/m4/strdup.m4 b/gl/m4/strdup.m4
new file mode 100644
index 00000000..f7786e94
--- /dev/null
+++ b/gl/m4/strdup.m4
@@ -0,0 +1,15 @@
1# strdup.m4 serial 7
2dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 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_FUNC_STRDUP],
8[
9 AC_REPLACE_FUNCS(strdup)
10 AC_CHECK_DECLS_ONCE(strdup)
11 gl_PREREQ_STRDUP
12])
13
14# Prerequisites of lib/strdup.c.
15AC_DEFUN([gl_PREREQ_STRDUP], [:])
diff --git a/gl/m4/strndup.m4 b/gl/m4/strndup.m4
new file mode 100644
index 00000000..dd5780b6
--- /dev/null
+++ b/gl/m4/strndup.m4
@@ -0,0 +1,48 @@
1# strndup.m4 serial 11
2dnl Copyright (C) 2002-2003, 2005-2006 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_FUNC_STRNDUP],
8[
9 dnl Persuade glibc <string.h> to declare strndup().
10 AC_REQUIRE([AC_GNU_SOURCE])
11
12 AC_CHECK_DECLS_ONCE([strndup])
13
14 # AIX 4.3.3, AIX 5.1 have a function that fails to add the terminating '\0'.
15 AC_CACHE_CHECK([for working strndup], gl_cv_func_strndup,
16 [AC_RUN_IFELSE([
17 AC_LANG_PROGRAM([#include <string.h>
18 #include <stdlib.h>], [[
19#ifndef HAVE_DECL_STRNDUP
20 extern char *strndup (const char *, size_t);
21#endif
22 char *s;
23 s = strndup ("some longer string", 15);
24 free (s);
25 s = strndup ("shorter string", 13);
26 return s[13] != '\0';]])],
27 [gl_cv_func_strndup=yes],
28 [gl_cv_func_strndup=no],
29 [AC_CHECK_FUNC([strndup],
30 [AC_EGREP_CPP([too risky], [
31#ifdef _AIX
32 too risky
33#endif
34 ],
35 [gl_cv_func_strndup=no],
36 [gl_cv_func_strndup=yes])],
37 [gl_cv_func_strndup=no])])])
38 if test $gl_cv_func_strndup = yes; then
39 AC_DEFINE([HAVE_STRNDUP], 1,
40 [Define if you have the strndup() function and it works.])
41 else
42 AC_LIBOBJ([strndup])
43 gl_PREREQ_STRNDUP
44 fi
45])
46
47# Prerequisites of lib/strndup.c.
48AC_DEFUN([gl_PREREQ_STRNDUP], [:])
diff --git a/gl/m4/strnlen.m4 b/gl/m4/strnlen.m4
new file mode 100644
index 00000000..0213a8ae
--- /dev/null
+++ b/gl/m4/strnlen.m4
@@ -0,0 +1,27 @@
1# strnlen.m4 serial 6
2dnl Copyright (C) 2002-2003, 2005, 2006 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_FUNC_STRNLEN],
8[
9 dnl Persuade glibc <string.h> to declare strnlen().
10 AC_REQUIRE([AC_GNU_SOURCE])
11
12 AC_FUNC_STRNLEN
13 if test $ac_cv_func_strnlen_working = no; then
14 # This is necessary because automake-1.6.1 doens't understand
15 # that the above use of AC_FUNC_STRNLEN means we may have to use
16 # lib/strnlen.c.
17 #AC_LIBOBJ(strnlen)
18 AC_DEFINE(strnlen, rpl_strnlen,
19 [Define to rpl_strnlen if the replacement function should be used.])
20 gl_PREREQ_STRNLEN
21 fi
22])
23
24# Prerequisites of lib/strnlen.c.
25AC_DEFUN([gl_PREREQ_STRNLEN], [
26 AC_CHECK_DECLS_ONCE(strnlen)
27])
diff --git a/gl/m4/sys_socket_h.m4 b/gl/m4/sys_socket_h.m4
new file mode 100644
index 00000000..d3e45b48
--- /dev/null
+++ b/gl/m4/sys_socket_h.m4
@@ -0,0 +1,23 @@
1# sys_socket_h.m4 serial 2
2dnl Copyright (C) 2005, 2006 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
7dnl From Simon Josefsson.
8
9AC_DEFUN([gl_HEADER_SYS_SOCKET],
10[
11 AC_CHECK_HEADERS_ONCE([sys/socket.h])
12 if test $ac_cv_header_sys_socket_h = yes; then
13 SYS_SOCKET_H=''
14 else
15 dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make
16 dnl the check for those headers unconditional; yet cygwin reports
17 dnl that the headers are present but cannot be compiled (since on
18 dnl cygwin, all socket information should come from sys/socket.h).
19 AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
20 SYS_SOCKET_H='sys/socket.h'
21 fi
22 AC_SUBST(SYS_SOCKET_H)
23])
diff --git a/gl/m4/uintmax_t.m4 b/gl/m4/uintmax_t.m4
new file mode 100644
index 00000000..bf83ed74
--- /dev/null
+++ b/gl/m4/uintmax_t.m4
@@ -0,0 +1,30 @@
1# uintmax_t.m4 serial 9
2dnl Copyright (C) 1997-2004 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
7dnl From Paul Eggert.
8
9AC_PREREQ(2.13)
10
11# Define uintmax_t to 'unsigned long' or 'unsigned long long'
12# if it is not already defined in <stdint.h> or <inttypes.h>.
13
14AC_DEFUN([gl_AC_TYPE_UINTMAX_T],
15[
16 AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
17 AC_REQUIRE([gl_AC_HEADER_STDINT_H])
18 if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then
19 AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG])
20 test $ac_cv_type_unsigned_long_long = yes \
21 && ac_type='unsigned long long' \
22 || ac_type='unsigned long'
23 AC_DEFINE_UNQUOTED(uintmax_t, $ac_type,
24 [Define to unsigned long or unsigned long long
25 if <stdint.h> and <inttypes.h> don't define.])
26 else
27 AC_DEFINE(HAVE_UINTMAX_T, 1,
28 [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.])
29 fi
30])
diff --git a/gl/m4/ulonglong.m4 b/gl/m4/ulonglong.m4
new file mode 100644
index 00000000..9fae98e3
--- /dev/null
+++ b/gl/m4/ulonglong.m4
@@ -0,0 +1,48 @@
1# ulonglong.m4 serial 6
2dnl Copyright (C) 1999-2006 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
7dnl From Paul Eggert.
8
9# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works.
10# This fixes a bug in Autoconf 2.60, but can be removed once we
11# assume 2.61 everywhere.
12
13# Note: If the type 'unsigned long long int' exists but is only 32 bits
14# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT
15# will not be defined. In this case you can treat 'unsigned long long int'
16# like 'unsigned long int'.
17
18AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
19[
20 AC_CACHE_CHECK([for unsigned long long int],
21 [ac_cv_type_unsigned_long_long_int],
22 [AC_LINK_IFELSE(
23 [AC_LANG_PROGRAM(
24 [[unsigned long long int ull = 18446744073709551615ULL;
25 typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1
26 ? 1 : -1)];
27 int i = 63;]],
28 [[unsigned long long int ullmax = 18446744073709551615ull;
29 return (ull << 63 | ull >> 63 | ull << i | ull >> i
30 | ullmax / ull | ullmax % ull);]])],
31 [ac_cv_type_unsigned_long_long_int=yes],
32 [ac_cv_type_unsigned_long_long_int=no])])
33 if test $ac_cv_type_unsigned_long_long_int = yes; then
34 AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1,
35 [Define to 1 if the system has the type `unsigned long long int'.])
36 fi
37])
38
39# This macro is obsolescent and should go away soon.
40AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG],
41[
42 AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
43 ac_cv_type_unsigned_long_long=$ac_cv_type_unsigned_long_long_int
44 if test $ac_cv_type_unsigned_long_long = yes; then
45 AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1,
46 [Define if you have the 'unsigned long long' type.])
47 fi
48])
diff --git a/gl/m4/unistd-safer.m4 b/gl/m4/unistd-safer.m4
new file mode 100644
index 00000000..09adf931
--- /dev/null
+++ b/gl/m4/unistd-safer.m4
@@ -0,0 +1,13 @@
1#serial 8
2dnl Copyright (C) 2002, 2005, 2006 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_UNISTD_SAFER],
8[
9 AC_CHECK_FUNCS_ONCE([pipe])
10 AC_LIBOBJ([dup-safer])
11 AC_LIBOBJ([fd-safer])
12 AC_LIBOBJ([pipe-safer])
13])
diff --git a/gl/m4/unistd_h.m4 b/gl/m4/unistd_h.m4
new file mode 100644
index 00000000..9d499dfe
--- /dev/null
+++ b/gl/m4/unistd_h.m4
@@ -0,0 +1,32 @@
1# unistd_h.m4 serial 3
2dnl Copyright (C) 2006 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
7dnl Written by Simon Josefsson
8
9AC_DEFUN([gl_HEADER_UNISTD],
10[
11 AC_CHECK_HEADERS([unistd.h], [
12 UNISTD_H=''
13 ], [
14 UNISTD_H='unistd.h'
15 ])
16 AC_SUBST(UNISTD_H)
17 dnl This module decides to build unistd.h if it is missing.
18 dnl The fchdir module decides to build unistd.h if fchdir() is missing.
19 dnl Therefore check for the prerequisites of lib/unistd.h always.
20 gl_PREREQ_UNISTD
21])
22
23dnl Prerequisites of lib/unistd.h.
24AC_DEFUN([gl_PREREQ_UNISTD],
25[
26 AC_CHECK_HEADERS_ONCE([unistd.h])
27 if test $ac_cv_header_unistd_h = yes; then
28 gl_ABSOLUTE_HEADER([unistd.h])
29 ABSOLUTE_UNISTD_H=\"$gl_cv_absolute_unistd_h\"
30 fi
31 AC_SUBST([ABSOLUTE_UNISTD_H])
32])
diff --git a/gl/m4/vasnprintf.m4 b/gl/m4/vasnprintf.m4
new file mode 100644
index 00000000..72c9a13e
--- /dev/null
+++ b/gl/m4/vasnprintf.m4
@@ -0,0 +1,57 @@
1# vasnprintf.m4 serial 7
2dnl Copyright (C) 2002-2004, 2006 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_FUNC_VASNPRINTF],
8[
9 AC_REQUIRE([gl_EOVERFLOW])
10 AC_REPLACE_FUNCS(vasnprintf)
11 if test $ac_cv_func_vasnprintf = no; then
12 AC_LIBOBJ(printf-args)
13 AC_LIBOBJ(printf-parse)
14 AC_LIBOBJ(asnprintf)
15 gl_PREREQ_PRINTF_ARGS
16 gl_PREREQ_PRINTF_PARSE
17 gl_PREREQ_VASNPRINTF
18 gl_PREREQ_ASNPRINTF
19 fi
20])
21
22# Prequisites of lib/printf-args.h, lib/printf-args.c.
23AC_DEFUN([gl_PREREQ_PRINTF_ARGS],
24[
25 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
26 AC_REQUIRE([gt_TYPE_LONGDOUBLE])
27 AC_REQUIRE([gt_TYPE_WCHAR_T])
28 AC_REQUIRE([gt_TYPE_WINT_T])
29])
30
31# Prequisites of lib/printf-parse.h, lib/printf-parse.c.
32AC_DEFUN([gl_PREREQ_PRINTF_PARSE],
33[
34 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
35 AC_REQUIRE([gt_TYPE_LONGDOUBLE])
36 AC_REQUIRE([gt_TYPE_WCHAR_T])
37 AC_REQUIRE([gt_TYPE_WINT_T])
38 AC_REQUIRE([AC_TYPE_SIZE_T])
39 AC_CHECK_TYPES(ptrdiff_t)
40 AC_REQUIRE([gt_AC_TYPE_INTMAX_T])
41])
42
43# Prerequisites of lib/vasnprintf.c.
44AC_DEFUN([gl_PREREQ_VASNPRINTF],
45[
46 AC_REQUIRE([AC_FUNC_ALLOCA])
47 AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
48 AC_REQUIRE([gt_TYPE_LONGDOUBLE])
49 AC_REQUIRE([gt_TYPE_WCHAR_T])
50 AC_REQUIRE([gt_TYPE_WINT_T])
51 AC_CHECK_FUNCS(snprintf wcslen)
52])
53
54# Prerequisites of lib/asnprintf.c.
55AC_DEFUN([gl_PREREQ_ASNPRINTF],
56[
57])
diff --git a/gl/m4/vasprintf.m4 b/gl/m4/vasprintf.m4
new file mode 100644
index 00000000..18ca6327
--- /dev/null
+++ b/gl/m4/vasprintf.m4
@@ -0,0 +1,33 @@
1# vasprintf.m4 serial 2
2dnl Copyright (C) 2002-2003, 2006 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_FUNC_VASPRINTF],
8[
9 AC_REPLACE_FUNCS(vasprintf)
10 if test $ac_cv_func_vasprintf = no; then
11 AC_LIBOBJ(asprintf)
12 gl_PREREQ_VASPRINTF_H
13 gl_PREREQ_VASPRINTF
14 gl_PREREQ_ASPRINTF
15 fi
16])
17
18# Prerequisites of lib/vasprintf.h.
19AC_DEFUN([gl_PREREQ_VASPRINTF_H],
20[
21 dnl Persuade glibc <stdio.h> to declare asprintf() and vasprintf().
22 AC_REQUIRE([AC_GNU_SOURCE])
23])
24
25# Prerequisites of lib/vasprintf.c.
26AC_DEFUN([gl_PREREQ_VASPRINTF],
27[
28])
29
30# Prerequisites of lib/asprintf.c.
31AC_DEFUN([gl_PREREQ_ASPRINTF],
32[
33])
diff --git a/gl/m4/visibility.m4 b/gl/m4/visibility.m4
new file mode 100644
index 00000000..2ff6330a
--- /dev/null
+++ b/gl/m4/visibility.m4
@@ -0,0 +1,52 @@
1# visibility.m4 serial 1 (gettext-0.15)
2dnl Copyright (C) 2005 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
7dnl From Bruno Haible.
8
9dnl Tests whether the compiler supports the command-line option
10dnl -fvisibility=hidden and the function and variable attributes
11dnl __attribute__((__visibility__("hidden"))) and
12dnl __attribute__((__visibility__("default"))).
13dnl Does *not* test for __visibility__("protected") - which has tricky
14dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
15dnl MacOS X.
16dnl Does *not* test for __visibility__("internal") - which has processor
17dnl dependent semantics.
18dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
19dnl "really only recommended for legacy code".
20dnl Set the variable CFLAG_VISIBILITY.
21dnl Defines and sets the variable HAVE_VISIBILITY.
22
23AC_DEFUN([gl_VISIBILITY],
24[
25 AC_REQUIRE([AC_PROG_CC])
26 CFLAG_VISIBILITY=
27 HAVE_VISIBILITY=0
28 if test -n "$GCC"; then
29 AC_MSG_CHECKING([for simple visibility declarations])
30 AC_CACHE_VAL(gl_cv_cc_visibility, [
31 gl_save_CFLAGS="$CFLAGS"
32 CFLAGS="$CFLAGS -fvisibility=hidden"
33 AC_TRY_COMPILE(
34 [extern __attribute__((__visibility__("hidden"))) int hiddenvar;
35 extern __attribute__((__visibility__("default"))) int exportedvar;
36 extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
37 extern __attribute__((__visibility__("default"))) int exportedfunc (void);],
38 [],
39 gl_cv_cc_visibility=yes,
40 gl_cv_cc_visibility=no)
41 CFLAGS="$gl_save_CFLAGS"])
42 AC_MSG_RESULT([$gl_cv_cc_visibility])
43 if test $gl_cv_cc_visibility = yes; then
44 CFLAG_VISIBILITY="-fvisibility=hidden"
45 HAVE_VISIBILITY=1
46 fi
47 fi
48 AC_SUBST([CFLAG_VISIBILITY])
49 AC_SUBST([HAVE_VISIBILITY])
50 AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
51 [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
52])
diff --git a/gl/m4/vsnprintf.m4 b/gl/m4/vsnprintf.m4
new file mode 100644
index 00000000..cb8a9b18
--- /dev/null
+++ b/gl/m4/vsnprintf.m4
@@ -0,0 +1,15 @@
1# vsnprintf.m4 serial 2
2dnl Copyright (C) 2002, 2003, 2004 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_FUNC_VSNPRINTF],
8[
9 AC_REPLACE_FUNCS(vsnprintf)
10 AC_CHECK_DECLS_ONCE(vsnprintf)
11 gl_PREREQ_VSNPRINTF
12])
13
14# Prerequisites of lib/vsnprintf.c.
15AC_DEFUN([gl_PREREQ_VSNPRINTF], [:])
diff --git a/gl/m4/wchar.m4 b/gl/m4/wchar.m4
new file mode 100644
index 00000000..068f22d3
--- /dev/null
+++ b/gl/m4/wchar.m4
@@ -0,0 +1,29 @@
1dnl A placeholder for ISO C99 <wchar.h>, for platforms that have issues.
2
3dnl Copyright (C) 2007 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8dnl Written by Eric Blake.
9
10# wchar.m4 serial 1
11
12AC_DEFUN([gl_WCHAR_H],
13[
14 AC_CACHE_CHECK([whether <wchar.h> is standalone],
15 [gl_cv_header_wchar_h_standalone],
16 [AC_COMPILE_IFELSE([[#include <wchar.h>
17wchar_t w;]],
18 [gl_cv_header_wchar_h_standalone=yes],
19 [gl_cv_header_wchar_h_standalone=no])])
20 if test $gl_cv_header_wchar_h_standalone = yes; then
21 WCHAR_H=
22 else
23 gl_ABSOLUTE_HEADER([wchar.h])
24 ABSOLUTE_WCHAR_H=\"$gl_cv_absolute_wchar_h\"
25 WCHAR_H=wchar.h
26 fi
27 AC_SUBST([ABSOLUTE_WCHAR_H])
28 AC_SUBST([WCHAR_H])
29])
diff --git a/gl/m4/wchar_t.m4 b/gl/m4/wchar_t.m4
new file mode 100644
index 00000000..cde2129a
--- /dev/null
+++ b/gl/m4/wchar_t.m4
@@ -0,0 +1,20 @@
1# wchar_t.m4 serial 1 (gettext-0.12)
2dnl Copyright (C) 2002-2003 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
7dnl From Bruno Haible.
8dnl Test whether <stddef.h> has the 'wchar_t' type.
9dnl Prerequisite: AC_PROG_CC
10
11AC_DEFUN([gt_TYPE_WCHAR_T],
12[
13 AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t,
14 [AC_TRY_COMPILE([#include <stddef.h>
15 wchar_t foo = (wchar_t)'\0';], ,
16 gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)])
17 if test $gt_cv_c_wchar_t = yes; then
18 AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.])
19 fi
20])
diff --git a/gl/m4/wctype.m4 b/gl/m4/wctype.m4
new file mode 100644
index 00000000..62994c62
--- /dev/null
+++ b/gl/m4/wctype.m4
@@ -0,0 +1,41 @@
1dnl A placeholder for ISO C99 <wctype.h>, for platforms that lack it.
2
3dnl Copyright (C) 2006, 2007 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8dnl Written by Paul Eggert.
9
10AC_DEFUN([gl_WCTYPE_H],
11[
12 AC_CHECK_FUNCS_ONCE([iswcntrl])
13 AC_CHECK_HEADERS_ONCE([wctype.h])
14 AC_REQUIRE([AC_C_INLINE])
15
16 AC_REQUIRE([gt_TYPE_WINT_T])
17 if test $gt_cv_c_wint_t = yes; then
18 HAVE_WINT_T=1
19 else
20 HAVE_WINT_T=0
21 fi
22 AC_SUBST([HAVE_WINT_T])
23
24 WCTYPE_H=wctype.h
25 if test $ac_cv_header_wctype_h = yes; then
26 if test "$ac_cv_func_iswcntrl" = yes; then
27 WCTYPE_H=
28 fi
29 dnl Compute ABSOLUTE_WCTYPE_H even if WCTYPE_H is empty,
30 dnl for the benefit of builds from non-distclean directories.
31 gl_ABSOLUTE_HEADER([wctype.h])
32 ABSOLUTE_WCTYPE_H=\"$gl_cv_absolute_wctype_h\"
33 HAVE_WCTYPE_H=1
34 else
35 ABSOLUTE_WCTYPE_H=\"no/such/file/wctype.h\"
36 HAVE_WCTYPE_H=0
37 fi
38 AC_SUBST([ABSOLUTE_WCTYPE_H])
39 AC_SUBST([HAVE_WCTYPE_H])
40 AC_SUBST([WCTYPE_H])
41])
diff --git a/gl/m4/wcwidth.m4 b/gl/m4/wcwidth.m4
new file mode 100644
index 00000000..b4834991
--- /dev/null
+++ b/gl/m4/wcwidth.m4
@@ -0,0 +1,30 @@
1# wcwidth.m4 serial 8
2dnl Copyright (C) 2006, 2007 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_FUNC_WCWIDTH],
8[
9 dnl Persuade glibc <wchar.h> to declare wcwidth().
10 AC_REQUIRE([AC_GNU_SOURCE])
11
12 AC_REQUIRE([AC_C_INLINE])
13 AC_REQUIRE([gt_TYPE_WCHAR_T])
14 AC_REQUIRE([gt_TYPE_WINT_T])
15
16 AC_CHECK_HEADERS_ONCE([wchar.h])
17 AC_CHECK_FUNCS_ONCE([wcwidth])
18
19 AC_CHECK_DECLS([wcwidth], [], [], [
20/* AIX 3.2.5 declares wcwidth in <string.h>. */
21#include <string.h>
22/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
23 <wchar.h>.
24 BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included
25 before <wchar.h>. */
26#include <stddef.h>
27#include <stdio.h>
28#include <time.h>
29#include <wchar.h>
30])])
diff --git a/gl/m4/wint_t.m4 b/gl/m4/wint_t.m4
new file mode 100644
index 00000000..3706c047
--- /dev/null
+++ b/gl/m4/wint_t.m4
@@ -0,0 +1,28 @@
1# wint_t.m4 serial 2 (gettext-0.12)
2dnl Copyright (C) 2003, 2007 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
7dnl From Bruno Haible.
8dnl Test whether <wchar.h> has the 'wint_t' type.
9dnl Prerequisite: AC_PROG_CC
10
11AC_DEFUN([gt_TYPE_WINT_T],
12[
13 AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t,
14 [AC_TRY_COMPILE([
15/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
16 <wchar.h>.
17 BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included
18 before <wchar.h>. */
19#include <stddef.h>
20#include <stdio.h>
21#include <time.h>
22#include <wchar.h>
23 wint_t foo = (wchar_t)'\0';], ,
24 gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)])
25 if test $gt_cv_c_wint_t = yes; then
26 AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.])
27 fi
28])
diff --git a/gl/m4/xalloc.m4 b/gl/m4/xalloc.m4
new file mode 100644
index 00000000..837a948c
--- /dev/null
+++ b/gl/m4/xalloc.m4
@@ -0,0 +1,24 @@
1# xalloc.m4 serial 16
2dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 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_XALLOC],
8[
9 AC_LIBOBJ([xmalloc])
10
11 gl_PREREQ_XALLOC
12 gl_PREREQ_XMALLOC
13])
14
15# Prerequisites of lib/xalloc.h.
16AC_DEFUN([gl_PREREQ_XALLOC], [
17 AC_REQUIRE([gl_INLINE])
18 :
19])
20
21# Prerequisites of lib/xmalloc.c.
22AC_DEFUN([gl_PREREQ_XMALLOC], [
23 :
24])
diff --git a/gl/m4/xsize.m4 b/gl/m4/xsize.m4
new file mode 100644
index 00000000..85bb721e
--- /dev/null
+++ b/gl/m4/xsize.m4
@@ -0,0 +1,13 @@
1# xsize.m4 serial 3
2dnl Copyright (C) 2003-2004 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_XSIZE],
8[
9 dnl Prerequisites of lib/xsize.h.
10 AC_REQUIRE([gl_SIZE_MAX])
11 AC_REQUIRE([AC_C_INLINE])
12 AC_CHECK_HEADERS(stdint.h)
13])
diff --git a/gl/m4/xstrndup.m4 b/gl/m4/xstrndup.m4
new file mode 100644
index 00000000..8a30ab15
--- /dev/null
+++ b/gl/m4/xstrndup.m4
@@ -0,0 +1,15 @@
1# xstrndup.m4 serial 2
2dnl Copyright (C) 2003 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_XSTRNDUP],
8[
9 gl_PREREQ_XSTRNDUP
10])
11
12# Prerequisites of lib/xstrndup.c.
13AC_DEFUN([gl_PREREQ_XSTRNDUP], [
14 :
15])
diff --git a/gl/malloc.c b/gl/malloc.c
new file mode 100644
index 00000000..d4dae3e1
--- /dev/null
+++ b/gl/malloc.c
@@ -0,0 +1,35 @@
1/* malloc() function that is glibc compatible.
2
3 Copyright (C) 1997, 1998, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* written by Jim Meyering */
20
21#include <config.h>
22#undef malloc
23
24#include <stdlib.h>
25
26/* Allocate an N-byte block of memory from the heap.
27 If N is zero, allocate a 1-byte block. */
28
29void *
30rpl_malloc (size_t n)
31{
32 if (n == 0)
33 n = 1;
34 return malloc (n);
35}
diff --git a/gl/mbchar.c b/gl/mbchar.c
new file mode 100644
index 00000000..95373f58
--- /dev/null
+++ b/gl/mbchar.c
@@ -0,0 +1,36 @@
1/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software Foundation,
15 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
16
17
18#include <config.h>
19
20#include <limits.h>
21
22#include "mbchar.h"
23
24#if IS_BASIC_ASCII
25
26/* Bit table of characters in the ISO C "basic character set". */
27const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
28{
29 0x00001a00, /* '\t' '\v' '\f' */
30 0xffffffef, /* ' '...'#' '%'...'?' */
31 0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
32 0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
33 /* The remaining bits are 0. */
34};
35
36#endif /* IS_BASIC_ASCII */
diff --git a/gl/mbchar.h b/gl/mbchar.h
new file mode 100644
index 00000000..f3e28ef5
--- /dev/null
+++ b/gl/mbchar.h
@@ -0,0 +1,353 @@
1/* Multibyte character data type.
2 Copyright (C) 2001, 2005-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18/* Written by Bruno Haible <bruno@clisp.org>. */
19
20/* A multibyte character is a short subsequence of a char* string,
21 representing a single wide character.
22
23 We use multibyte characters instead of wide characters because of
24 the following goals:
25 1) correct multibyte handling, i.e. operate according to the LC_CTYPE
26 locale,
27 2) ease of maintenance, i.e. the maintainer needs not know all details
28 of the ISO C 99 standard,
29 3) don't fail grossly if the input is not in the encoding set by the
30 locale, because often different encodings are in use in the same
31 countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...),
32 4) fast in the case of ASCII characters,
33 5) portability, i.e. don't make unportable assumptions about wchar_t.
34
35 Multibyte characters are only accessed through the mb* macros.
36
37 mb_ptr (mbc)
38 return a pointer to the beginning of the multibyte sequence.
39
40 mb_len (mbc)
41 returns the number of bytes occupied by the multibyte sequence.
42 Always > 0.
43
44 mb_iseq (mbc, sc)
45 returns true if mbc is the standard ASCII character sc.
46
47 mb_isnul (mbc)
48 returns true if mbc is the nul character.
49
50 mb_cmp (mbc1, mbc2)
51 returns a positive, zero, or negative value depending on whether mbc1
52 sorts after, same or before mbc2.
53
54 mb_casecmp (mbc1, mbc2)
55 returns a positive, zero, or negative value depending on whether mbc1
56 sorts after, same or before mbc2, modulo upper/lowercase conversion.
57
58 mb_equal (mbc1, mbc2)
59 returns true if mbc1 and mbc2 are equal.
60
61 mb_caseequal (mbc1, mbc2)
62 returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion.
63
64 mb_isalnum (mbc)
65 returns true if mbc is alphanumeric.
66
67 mb_isalpha (mbc)
68 returns true if mbc is alphabetic.
69
70 mb_isascii(mbc)
71 returns true if mbc is plain ASCII.
72
73 mb_isblank (mbc)
74 returns true if mbc is a blank.
75
76 mb_iscntrl (mbc)
77 returns true if mbc is a control character.
78
79 mb_isdigit (mbc)
80 returns true if mbc is a decimal digit.
81
82 mb_isgraph (mbc)
83 returns true if mbc is a graphic character.
84
85 mb_islower (mbc)
86 returns true if mbc is lowercase.
87
88 mb_isprint (mbc)
89 returns true if mbc is a printable character.
90
91 mb_ispunct (mbc)
92 returns true if mbc is a punctuation character.
93
94 mb_isspace (mbc)
95 returns true if mbc is a space character.
96
97 mb_isupper (mbc)
98 returns true if mbc is uppercase.
99
100 mb_isxdigit (mbc)
101 returns true if mbc is a hexadecimal digit.
102
103 mb_width (mbc)
104 returns the number of columns on the output device occupied by mbc.
105 Always >= 0.
106
107 mb_putc (mbc, stream)
108 outputs mbc on stream, a byte oriented FILE stream opened for output.
109
110 mb_setascii (&mbc, sc)
111 assigns the standard ASCII character sc to mbc.
112
113 mb_copy (&destmbc, &srcmbc)
114 copies srcmbc to destmbc.
115
116 Here are the function prototypes of the macros.
117
118 extern const char * mb_ptr (const mbchar_t mbc);
119 extern size_t mb_len (const mbchar_t mbc);
120 extern bool mb_iseq (const mbchar_t mbc, char sc);
121 extern bool mb_isnul (const mbchar_t mbc);
122 extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2);
123 extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2);
124 extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2);
125 extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2);
126 extern bool mb_isalnum (const mbchar_t mbc);
127 extern bool mb_isalpha (const mbchar_t mbc);
128 extern bool mb_isascii (const mbchar_t mbc);
129 extern bool mb_isblank (const mbchar_t mbc);
130 extern bool mb_iscntrl (const mbchar_t mbc);
131 extern bool mb_isdigit (const mbchar_t mbc);
132 extern bool mb_isgraph (const mbchar_t mbc);
133 extern bool mb_islower (const mbchar_t mbc);
134 extern bool mb_isprint (const mbchar_t mbc);
135 extern bool mb_ispunct (const mbchar_t mbc);
136 extern bool mb_isspace (const mbchar_t mbc);
137 extern bool mb_isupper (const mbchar_t mbc);
138 extern bool mb_isxdigit (const mbchar_t mbc);
139 extern int mb_width (const mbchar_t mbc);
140 extern void mb_putc (const mbchar_t mbc, FILE *stream);
141 extern void mb_setascii (mbchar_t *new, char sc);
142 extern void mb_copy (mbchar_t *new, const mbchar_t *old);
143 */
144
145#ifndef _MBCHAR_H
146#define _MBCHAR_H 1
147
148#include <stdbool.h>
149#include <string.h>
150
151/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
152 <wchar.h>.
153 BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
154 <wchar.h>. */
155#include <stdio.h>
156#include <time.h>
157#include <wchar.h>
158#include <wctype.h>
159
160#include "wcwidth.h"
161
162#define MBCHAR_BUF_SIZE 24
163
164struct mbchar
165{
166 const char *ptr; /* pointer to current character */
167 size_t bytes; /* number of bytes of current character, > 0 */
168 bool wc_valid; /* true if wc is a valid wide character */
169 wchar_t wc; /* if wc_valid: the current character */
170 char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */
171};
172
173/* EOF (not a real character) is represented with bytes = 0 and
174 wc_valid = false. */
175
176typedef struct mbchar mbchar_t;
177
178/* Access the current character. */
179#define mb_ptr(mbc) ((mbc).ptr)
180#define mb_len(mbc) ((mbc).bytes)
181
182/* Comparison of characters. */
183#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc))
184#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0)
185#define mb_cmp(mbc1, mbc2) \
186 ((mbc1).wc_valid \
187 ? ((mbc2).wc_valid \
188 ? (int) (mbc1).wc - (int) (mbc2).wc \
189 : -1) \
190 : ((mbc2).wc_valid \
191 ? 1 \
192 : (mbc1).bytes == (mbc2).bytes \
193 ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
194 : (mbc1).bytes < (mbc2).bytes \
195 ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
196 : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
197#define mb_casecmp(mbc1, mbc2) \
198 ((mbc1).wc_valid \
199 ? ((mbc2).wc_valid \
200 ? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \
201 : -1) \
202 : ((mbc2).wc_valid \
203 ? 1 \
204 : (mbc1).bytes == (mbc2).bytes \
205 ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
206 : (mbc1).bytes < (mbc2).bytes \
207 ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
208 : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
209#define mb_equal(mbc1, mbc2) \
210 ((mbc1).wc_valid && (mbc2).wc_valid \
211 ? (mbc1).wc == (mbc2).wc \
212 : (mbc1).bytes == (mbc2).bytes \
213 && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
214#define mb_caseequal(mbc1, mbc2) \
215 ((mbc1).wc_valid && (mbc2).wc_valid \
216 ? towlower ((mbc1).wc) == towlower ((mbc2).wc) \
217 : (mbc1).bytes == (mbc2).bytes \
218 && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
219
220/* <ctype.h>, <wctype.h> classification. */
221#define mb_isascii(mbc) \
222 ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127)
223#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc))
224#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc))
225#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc))
226#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc))
227#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc))
228#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc))
229#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc))
230#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc))
231#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc))
232#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc))
233#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc))
234#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc))
235
236/* Extra <wchar.h> function. */
237
238/* Unprintable characters appear as a small box of width 1. */
239#define MB_UNPRINTABLE_WIDTH 1
240
241static inline int
242mb_width_aux (wint_t wc)
243{
244 int w = wcwidth (wc);
245 /* For unprintable characters, arbitrarily return 0 for control characters
246 and MB_UNPRINTABLE_WIDTH otherwise. */
247 return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH);
248}
249
250#define mb_width(mbc) \
251 ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH)
252
253/* Output. */
254#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream))
255
256/* Assignment. */
257#define mb_setascii(mbc, sc) \
258 ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \
259 (mbc)->wc = (mbc)->buf[0] = (sc))
260
261/* Copying a character. */
262static inline void
263mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc)
264{
265 if (old_mbc->ptr == &old_mbc->buf[0])
266 {
267 memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes);
268 new_mbc->ptr = &new_mbc->buf[0];
269 }
270 else
271 new_mbc->ptr = old_mbc->ptr;
272 new_mbc->bytes = old_mbc->bytes;
273 if ((new_mbc->wc_valid = old_mbc->wc_valid))
274 new_mbc->wc = old_mbc->wc;
275}
276
277
278/* is_basic(c) tests whether the single-byte character c is in the
279 ISO C "basic character set".
280 This is a convenience function, and is in this file only to share code
281 between mbiter_multi.h and mbfile_multi.h. */
282#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
283 && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
284 && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
285 && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
286 && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
287 && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
288 && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
289 && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
290 && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
291 && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
292 && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
293 && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
294 && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
295 && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
296 && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
297 && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
298 && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
299 && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
300 && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
301 && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
302 && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
303 && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
304 && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
305/* The character set is ISO-646, not EBCDIC. */
306# define IS_BASIC_ASCII 1
307
308extern const unsigned int is_basic_table[];
309
310static inline bool
311is_basic (char c)
312{
313 return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
314 & 1;
315}
316
317#else
318
319static inline bool
320is_basic (char c)
321{
322 switch (c)
323 {
324 case '\t': case '\v': case '\f':
325 case ' ': case '!': case '"': case '#': case '%':
326 case '&': case '\'': case '(': case ')': case '*':
327 case '+': case ',': case '-': case '.': case '/':
328 case '0': case '1': case '2': case '3': case '4':
329 case '5': case '6': case '7': case '8': case '9':
330 case ':': case ';': case '<': case '=': case '>':
331 case '?':
332 case 'A': case 'B': case 'C': case 'D': case 'E':
333 case 'F': case 'G': case 'H': case 'I': case 'J':
334 case 'K': case 'L': case 'M': case 'N': case 'O':
335 case 'P': case 'Q': case 'R': case 'S': case 'T':
336 case 'U': case 'V': case 'W': case 'X': case 'Y':
337 case 'Z':
338 case '[': case '\\': case ']': case '^': case '_':
339 case 'a': case 'b': case 'c': case 'd': case 'e':
340 case 'f': case 'g': case 'h': case 'i': case 'j':
341 case 'k': case 'l': case 'm': case 'n': case 'o':
342 case 'p': case 'q': case 'r': case 's': case 't':
343 case 'u': case 'v': case 'w': case 'x': case 'y':
344 case 'z': case '{': case '|': case '}': case '~':
345 return 1;
346 default:
347 return 0;
348 }
349}
350
351#endif
352
353#endif /* _MBCHAR_H */
diff --git a/gl/mbuiter.h b/gl/mbuiter.h
new file mode 100644
index 00000000..9da3a6c7
--- /dev/null
+++ b/gl/mbuiter.h
@@ -0,0 +1,203 @@
1/* Iterating through multibyte strings: macros for multi-byte encodings.
2 Copyright (C) 2001, 2005 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18/* Written by Bruno Haible <bruno@clisp.org>. */
19
20/* The macros in this file implement forward iteration through a
21 multi-byte string, without knowing its length a-priori.
22
23 With these macros, an iteration loop that looks like
24
25 char *iter;
26 for (iter = buf; *iter != '\0'; iter++)
27 {
28 do_something (*iter);
29 }
30
31 becomes
32
33 mbui_iterator_t iter;
34 for (mbui_init (iter, buf); mbui_avail (iter); mbui_advance (iter))
35 {
36 do_something (mbui_cur_ptr (iter), mb_len (mbui_cur (iter)));
37 }
38
39 The benefit of these macros over plain use of mbrtowc is:
40 - Handling of invalid multibyte sequences is possible without
41 making the code more complicated, while still preserving the
42 invalid multibyte sequences.
43
44 Compared to mbiter.h, the macros here don't need to know the string's
45 length a-priori. The downside is that at each step, the look-ahead
46 that guards against overrunning the terminating '\0' is more expensive.
47 The mbui_* macros are therefore suitable when there is a high probability
48 that only the first few multibyte characters need to be inspected.
49 Whereas the mbi_* macros are better if usually the iteration runs
50 through the entire string.
51
52 mbui_iterator_t
53 is a type usable for variable declarations.
54
55 mbui_init (iter, startptr)
56 initializes the iterator, starting at startptr.
57
58 mbui_avail (iter)
59 returns true if there are more multibyte chracters available before
60 the end of string is reached. In this case, mbui_cur (iter) is
61 initialized to the next multibyte chracter.
62
63 mbui_advance (iter)
64 advances the iterator by one multibyte character.
65
66 mbui_cur (iter)
67 returns the current multibyte character, of type mbchar_t. All the
68 macros defined in mbchar.h can be used on it.
69
70 mbui_cur_ptr (iter)
71 return a pointer to the beginning of the current multibyte character.
72
73 mbui_reloc (iter, ptrdiff)
74 relocates iterator when the string is moved by ptrdiff bytes.
75
76 Here are the function prototypes of the macros.
77
78 extern void mbui_init (mbui_iterator_t iter, const char *startptr);
79 extern bool mbui_avail (mbui_iterator_t iter);
80 extern void mbui_advance (mbui_iterator_t iter);
81 extern mbchar_t mbui_cur (mbui_iterator_t iter);
82 extern const char * mbui_cur_ptr (mbui_iterator_t iter);
83 extern void mbui_reloc (mbui_iterator_t iter, ptrdiff_t ptrdiff);
84 */
85
86#ifndef _MBUITER_H
87#define _MBUITER_H 1
88
89#include <assert.h>
90#include <stdbool.h>
91#include <stdlib.h>
92
93/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
94 <wchar.h>.
95 BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
96 <wchar.h>. */
97#include <stdio.h>
98#include <time.h>
99#include <wchar.h>
100
101#include "mbchar.h"
102#include "strnlen1.h"
103
104struct mbuiter_multi
105{
106 bool in_shift; /* true if next byte may not be interpreted as ASCII */
107 mbstate_t state; /* if in_shift: current shift state */
108 bool next_done; /* true if mbui_avail has already filled the following */
109 struct mbchar cur; /* the current character:
110 const char *cur.ptr pointer to current character
111 The following are only valid after mbui_avail.
112 size_t cur.bytes number of bytes of current character
113 bool cur.wc_valid true if wc is a valid wide character
114 wchar_t cur.wc if wc_valid: the current character
115 */
116};
117
118static inline void
119mbuiter_multi_next (struct mbuiter_multi *iter)
120{
121 if (iter->next_done)
122 return;
123 if (iter->in_shift)
124 goto with_shift;
125 /* Handle most ASCII characters quickly, without calling mbrtowc(). */
126 if (is_basic (*iter->cur.ptr))
127 {
128 /* These characters are part of the basic character set. ISO C 99
129 guarantees that their wide character code is identical to their
130 char code. */
131 iter->cur.bytes = 1;
132 iter->cur.wc = *iter->cur.ptr;
133 iter->cur.wc_valid = true;
134 }
135 else
136 {
137 assert (mbsinit (&iter->state));
138 iter->in_shift = true;
139 with_shift:
140 iter->cur.bytes = mbrtowc (&iter->cur.wc, iter->cur.ptr,
141 strnlen1 (iter->cur.ptr, MB_CUR_MAX),
142 &iter->state);
143 if (iter->cur.bytes == (size_t) -1)
144 {
145 /* An invalid multibyte sequence was encountered. */
146 iter->cur.bytes = 1;
147 iter->cur.wc_valid = false;
148 /* Whether to set iter->in_shift = false and reset iter->state
149 or not is not very important; the string is bogus anyway. */
150 }
151 else if (iter->cur.bytes == (size_t) -2)
152 {
153 /* An incomplete multibyte character at the end. */
154 iter->cur.bytes = strlen (iter->cur.ptr);
155 iter->cur.wc_valid = false;
156 /* Whether to set iter->in_shift = false and reset iter->state
157 or not is not important; the string end is reached anyway. */
158 }
159 else
160 {
161 if (iter->cur.bytes == 0)
162 {
163 /* A null wide character was encountered. */
164 iter->cur.bytes = 1;
165 assert (*iter->cur.ptr == '\0');
166 assert (iter->cur.wc == 0);
167 }
168 iter->cur.wc_valid = true;
169
170 /* When in the initial state, we can go back treating ASCII
171 characters more quickly. */
172 if (mbsinit (&iter->state))
173 iter->in_shift = false;
174 }
175 }
176 iter->next_done = true;
177}
178
179static inline void
180mbuiter_multi_reloc (struct mbuiter_multi *iter, ptrdiff_t ptrdiff)
181{
182 iter->cur.ptr += ptrdiff;
183}
184
185/* Iteration macros. */
186typedef struct mbuiter_multi mbui_iterator_t;
187#define mbui_init(iter, startptr) \
188 ((iter).cur.ptr = (startptr), \
189 (iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \
190 (iter).next_done = false)
191#define mbui_avail(iter) \
192 (mbuiter_multi_next (&(iter)), !mb_isnul ((iter).cur))
193#define mbui_advance(iter) \
194 ((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false)
195
196/* Access to the current character. */
197#define mbui_cur(iter) (iter).cur
198#define mbui_cur_ptr(iter) (iter).cur.ptr
199
200/* Relocation. */
201#define mbui_reloc(iter, ptrdiff) mbuiter_multi_reloc (&iter, ptrdiff)
202
203#endif /* _MBUITER_H */
diff --git a/gl/memchr.c b/gl/memchr.c
new file mode 100644
index 00000000..d44ad6de
--- /dev/null
+++ b/gl/memchr.c
@@ -0,0 +1,201 @@
1/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006 Free
2 Software Foundation, Inc.
3
4 Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
5 with help from Dan Sahlin (dan@sics.se) and
6 commentary by Jim Blandy (jimb@ai.mit.edu);
7 adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
8 and implemented by Roland McGrath (roland@ai.mit.edu).
9
10NOTE: The canonical source of this file is maintained with the GNU C Library.
11Bugs can be reported to bug-glibc@prep.ai.mit.edu.
12
13This program is free software; you can redistribute it and/or modify it
14under the terms of the GNU General Public License as published by the
15Free Software Foundation; either version 2, or (at your option) any
16later version.
17
18This program is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software Foundation,
25Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26
27#ifndef _LIBC
28# include <config.h>
29#endif
30
31#include <string.h>
32
33#include <stddef.h>
34
35#if defined _LIBC
36# include <memcopy.h>
37#else
38# define reg_char char
39#endif
40
41#include <limits.h>
42
43#if HAVE_BP_SYM_H || defined _LIBC
44# include <bp-sym.h>
45#else
46# define BP_SYM(sym) sym
47#endif
48
49#undef memchr
50#undef __memchr
51
52/* Search no more than N bytes of S for C. */
53void *
54__memchr (void const *s, int c_in, size_t n)
55{
56 const unsigned char *char_ptr;
57 const unsigned long int *longword_ptr;
58 unsigned long int longword, magic_bits, charmask;
59 unsigned reg_char c;
60 int i;
61
62 c = (unsigned char) c_in;
63
64 /* Handle the first few characters by reading one character at a time.
65 Do this until CHAR_PTR is aligned on a longword boundary. */
66 for (char_ptr = (const unsigned char *) s;
67 n > 0 && (size_t) char_ptr % sizeof longword != 0;
68 --n, ++char_ptr)
69 if (*char_ptr == c)
70 return (void *) char_ptr;
71
72 /* All these elucidatory comments refer to 4-byte longwords,
73 but the theory applies equally well to any size longwords. */
74
75 longword_ptr = (const unsigned long int *) char_ptr;
76
77 /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
78 the "holes." Note that there is a hole just to the left of
79 each byte, with an extra at the end:
80
81 bits: 01111110 11111110 11111110 11111111
82 bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
83
84 The 1-bits make sure that carries propagate to the next 0-bit.
85 The 0-bits provide holes for carries to fall into. */
86
87 /* Set MAGIC_BITS to be this pattern of 1 and 0 bits.
88 Set CHARMASK to be a longword, each of whose bytes is C. */
89
90 magic_bits = 0xfefefefe;
91 charmask = c | (c << 8);
92 charmask |= charmask << 16;
93#if 0xffffffffU < ULONG_MAX
94 magic_bits |= magic_bits << 32;
95 charmask |= charmask << 32;
96 if (8 < sizeof longword)
97 for (i = 64; i < sizeof longword * 8; i *= 2)
98 {
99 magic_bits |= magic_bits << i;
100 charmask |= charmask << i;
101 }
102#endif
103 magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1);
104
105 /* Instead of the traditional loop which tests each character,
106 we will test a longword at a time. The tricky part is testing
107 if *any of the four* bytes in the longword in question are zero. */
108 while (n >= sizeof longword)
109 {
110 /* We tentatively exit the loop if adding MAGIC_BITS to
111 LONGWORD fails to change any of the hole bits of LONGWORD.
112
113 1) Is this safe? Will it catch all the zero bytes?
114 Suppose there is a byte with all zeros. Any carry bits
115 propagating from its left will fall into the hole at its
116 least significant bit and stop. Since there will be no
117 carry from its most significant bit, the LSB of the
118 byte to the left will be unchanged, and the zero will be
119 detected.
120
121 2) Is this worthwhile? Will it ignore everything except
122 zero bytes? Suppose every byte of LONGWORD has a bit set
123 somewhere. There will be a carry into bit 8. If bit 8
124 is set, this will carry into bit 16. If bit 8 is clear,
125 one of bits 9-15 must be set, so there will be a carry
126 into bit 16. Similarly, there will be a carry into bit
127 24. If one of bits 24-30 is set, there will be a carry
128 into bit 31, so all of the hole bits will be changed.
129
130 The one misfire occurs when bits 24-30 are clear and bit
131 31 is set; in this case, the hole at bit 31 is not
132 changed. If we had access to the processor carry flag,
133 we could close this loophole by putting the fourth hole
134 at bit 32!
135
136 So it ignores everything except 128's, when they're aligned
137 properly.
138
139 3) But wait! Aren't we looking for C, not zero?
140 Good point. So what we do is XOR LONGWORD with a longword,
141 each of whose bytes is C. This turns each byte that is C
142 into a zero. */
143
144 longword = *longword_ptr++ ^ charmask;
145
146 /* Add MAGIC_BITS to LONGWORD. */
147 if ((((longword + magic_bits)
148
149 /* Set those bits that were unchanged by the addition. */
150 ^ ~longword)
151
152 /* Look at only the hole bits. If any of the hole bits
153 are unchanged, most likely one of the bytes was a
154 zero. */
155 & ~magic_bits) != 0)
156 {
157 /* Which of the bytes was C? If none of them were, it was
158 a misfire; continue the search. */
159
160 const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
161
162 if (cp[0] == c)
163 return (void *) cp;
164 if (cp[1] == c)
165 return (void *) &cp[1];
166 if (cp[2] == c)
167 return (void *) &cp[2];
168 if (cp[3] == c)
169 return (void *) &cp[3];
170 if (4 < sizeof longword && cp[4] == c)
171 return (void *) &cp[4];
172 if (5 < sizeof longword && cp[5] == c)
173 return (void *) &cp[5];
174 if (6 < sizeof longword && cp[6] == c)
175 return (void *) &cp[6];
176 if (7 < sizeof longword && cp[7] == c)
177 return (void *) &cp[7];
178 if (8 < sizeof longword)
179 for (i = 8; i < sizeof longword; i++)
180 if (cp[i] == c)
181 return (void *) &cp[i];
182 }
183
184 n -= sizeof longword;
185 }
186
187 char_ptr = (const unsigned char *) longword_ptr;
188
189 while (n-- > 0)
190 {
191 if (*char_ptr == c)
192 return (void *) char_ptr;
193 else
194 ++char_ptr;
195 }
196
197 return 0;
198}
199#ifdef weak_alias
200weak_alias (__memchr, BP_SYM (memchr))
201#endif
diff --git a/gl/minmax.h b/gl/minmax.h
new file mode 100644
index 00000000..975ea76d
--- /dev/null
+++ b/gl/minmax.h
@@ -0,0 +1,60 @@
1/* MIN, MAX macros.
2 Copyright (C) 1995, 1998, 2001, 2003, 2005 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _MINMAX_H
19#define _MINMAX_H
20
21/* Note: MIN, MAX are also defined in <sys/param.h> on some systems
22 (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about
23 MIN, MAX macro redefinitions on some systems; the workaround is to
24 #include this file as the last one among the #include list. */
25
26/* Before we define the following symbols we get the <limits.h> file
27 since otherwise we get redefinitions on some systems if <limits.h> is
28 included after this file. Likewise for <sys/param.h>.
29 If more than one of these system headers define MIN and MAX, pick just
30 one of the headers (because the definitions most likely are the same). */
31#if HAVE_MINMAX_IN_LIMITS_H
32# include <limits.h>
33#elif HAVE_MINMAX_IN_SYS_PARAM_H
34# include <sys/param.h>
35#endif
36
37/* Note: MIN and MAX should be used with two arguments of the
38 same type. They might not return the minimum and maximum of their two
39 arguments, if the arguments have different types or have unusual
40 floating-point values. For example, on a typical host with 32-bit 'int',
41 64-bit 'long long', and 64-bit IEEE 754 'double' types:
42
43 MAX (-1, 2147483648) returns 4294967295.
44 MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0.
45 MAX (NaN, 0.0) returns 0.0.
46 MAX (+0.0, -0.0) returns -0.0.
47
48 and in each case the answer is in some sense bogus. */
49
50/* MAX(a,b) returns the maximum of A and B. */
51#ifndef MAX
52# define MAX(a,b) ((a) > (b) ? (a) : (b))
53#endif
54
55/* MIN(a,b) returns the minimum of A and B. */
56#ifndef MIN
57# define MIN(a,b) ((a) < (b) ? (a) : (b))
58#endif
59
60#endif /* _MINMAX_H */
diff --git a/gl/mountlist.c b/gl/mountlist.c
new file mode 100644
index 00000000..bb01f91e
--- /dev/null
+++ b/gl/mountlist.c
@@ -0,0 +1,889 @@
1/* mountlist.c -- return a list of mounted file systems
2
3 Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
4 2004, 2005, 2006 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "mountlist.h"
23
24#include <limits.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "xalloc.h"
30
31#ifndef strstr
32char *strstr ();
33#endif
34
35#include <errno.h>
36
37#include <fcntl.h>
38
39#include <unistd.h>
40
41#if HAVE_SYS_PARAM_H
42# include <sys/param.h>
43#endif
44
45#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
46# if HAVE_SYS_UCRED_H
47# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
48 NGROUPS is used as an array dimension in ucred.h */
49# include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
50# endif
51# if HAVE_SYS_MOUNT_H
52# include <sys/mount.h>
53# endif
54# if HAVE_SYS_FS_TYPES_H
55# include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
56# endif
57# if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
58# define FS_TYPE(Ent) ((Ent).f_fstypename)
59# else
60# define FS_TYPE(Ent) mnt_names[(Ent).f_type]
61# endif
62#endif /* MOUNTED_GETFSSTAT */
63
64#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
65# include <mntent.h>
66# if !defined MOUNTED
67# if defined _PATH_MOUNTED /* GNU libc */
68# define MOUNTED _PATH_MOUNTED
69# endif
70# if defined MNT_MNTTAB /* HP-UX. */
71# define MOUNTED MNT_MNTTAB
72# endif
73# if defined MNTTABNAME /* Dynix. */
74# define MOUNTED MNTTABNAME
75# endif
76# endif
77#endif
78
79#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
80# include <sys/mount.h>
81#endif
82
83#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
84# include <sys/statvfs.h>
85#endif
86
87#ifdef MOUNTED_GETMNT /* Ultrix. */
88# include <sys/mount.h>
89# include <sys/fs_types.h>
90#endif
91
92#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
93# include <fs_info.h>
94# include <dirent.h>
95#endif
96
97#ifdef MOUNTED_FREAD /* SVR2. */
98# include <mnttab.h>
99#endif
100
101#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
102# include <mnttab.h>
103# include <sys/fstyp.h>
104# include <sys/statfs.h>
105#endif
106
107#ifdef MOUNTED_LISTMNTENT
108# include <mntent.h>
109#endif
110
111#ifdef MOUNTED_GETMNTENT2 /* SVR4. */
112# include <sys/mnttab.h>
113#endif
114
115#ifdef MOUNTED_VMOUNT /* AIX. */
116# include <fshelp.h>
117# include <sys/vfs.h>
118#endif
119
120#ifdef DOLPHIN
121/* So special that it's not worth putting this in autoconf. */
122# undef MOUNTED_FREAD_FSTYP
123# define MOUNTED_GETMNTTBL
124#endif
125
126#if HAVE_SYS_MNTENT_H
127/* This is to get MNTOPT_IGNORE on e.g. SVR4. */
128# include <sys/mntent.h>
129#endif
130
131#undef MNT_IGNORE
132#if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
133# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
134#else
135# define MNT_IGNORE(M) 0
136#endif
137
138#if USE_UNLOCKED_IO
139# include "unlocked-io.h"
140#endif
141
142#ifndef SIZE_MAX
143# define SIZE_MAX ((size_t) -1)
144#endif
145
146/* The results of open() in this file are not used with fchdir,
147 therefore save some unnecessary work in fchdir.c. */
148#undef open
149#undef close
150
151/* The results of opendir() in this file are not used with dirfd and fchdir,
152 therefore save some unnecessary work in fchdir.c. */
153#undef opendir
154#undef closedir
155
156#ifndef ME_DUMMY
157# define ME_DUMMY(Fs_name, Fs_type) \
158 (strcmp (Fs_type, "autofs") == 0 \
159 || strcmp (Fs_type, "none") == 0 \
160 || strcmp (Fs_type, "proc") == 0 \
161 || strcmp (Fs_type, "subfs") == 0 \
162 /* for NetBSD 3.0 */ \
163 || strcmp (Fs_type, "kernfs") == 0 \
164 /* for Irix 6.5 */ \
165 || strcmp (Fs_type, "ignore") == 0)
166#endif
167
168#ifndef ME_REMOTE
169/* A file system is `remote' if its Fs_name contains a `:'
170 or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */
171# define ME_REMOTE(Fs_name, Fs_type) \
172 (strchr (Fs_name, ':') != NULL \
173 || ((Fs_name)[0] == '/' \
174 && (Fs_name)[1] == '/' \
175 && (strcmp (Fs_type, "smbfs") == 0 \
176 || strcmp (Fs_type, "cifs") == 0)))
177#endif
178
179#if MOUNTED_GETMNTINFO
180
181# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
182static char *
183fstype_to_string (short int t)
184{
185 switch (t)
186 {
187# ifdef MOUNT_PC
188 case MOUNT_PC:
189 return "pc";
190# endif
191# ifdef MOUNT_MFS
192 case MOUNT_MFS:
193 return "mfs";
194# endif
195# ifdef MOUNT_LO
196 case MOUNT_LO:
197 return "lo";
198# endif
199# ifdef MOUNT_TFS
200 case MOUNT_TFS:
201 return "tfs";
202# endif
203# ifdef MOUNT_TMP
204 case MOUNT_TMP:
205 return "tmp";
206# endif
207# ifdef MOUNT_UFS
208 case MOUNT_UFS:
209 return "ufs" ;
210# endif
211# ifdef MOUNT_NFS
212 case MOUNT_NFS:
213 return "nfs" ;
214# endif
215# ifdef MOUNT_MSDOS
216 case MOUNT_MSDOS:
217 return "msdos" ;
218# endif
219# ifdef MOUNT_LFS
220 case MOUNT_LFS:
221 return "lfs" ;
222# endif
223# ifdef MOUNT_LOFS
224 case MOUNT_LOFS:
225 return "lofs" ;
226# endif
227# ifdef MOUNT_FDESC
228 case MOUNT_FDESC:
229 return "fdesc" ;
230# endif
231# ifdef MOUNT_PORTAL
232 case MOUNT_PORTAL:
233 return "portal" ;
234# endif
235# ifdef MOUNT_NULL
236 case MOUNT_NULL:
237 return "null" ;
238# endif
239# ifdef MOUNT_UMAP
240 case MOUNT_UMAP:
241 return "umap" ;
242# endif
243# ifdef MOUNT_KERNFS
244 case MOUNT_KERNFS:
245 return "kernfs" ;
246# endif
247# ifdef MOUNT_PROCFS
248 case MOUNT_PROCFS:
249 return "procfs" ;
250# endif
251# ifdef MOUNT_AFS
252 case MOUNT_AFS:
253 return "afs" ;
254# endif
255# ifdef MOUNT_CD9660
256 case MOUNT_CD9660:
257 return "cd9660" ;
258# endif
259# ifdef MOUNT_UNION
260 case MOUNT_UNION:
261 return "union" ;
262# endif
263# ifdef MOUNT_DEVFS
264 case MOUNT_DEVFS:
265 return "devfs" ;
266# endif
267# ifdef MOUNT_EXT2FS
268 case MOUNT_EXT2FS:
269 return "ext2fs" ;
270# endif
271 default:
272 return "?";
273 }
274}
275# endif
276
277static char *
278fsp_to_string (const struct statfs *fsp)
279{
280# if HAVE_STRUCT_STATFS_F_FSTYPENAME
281 return (char *) (fsp->f_fstypename);
282# else
283 return fstype_to_string (fsp->f_type);
284# endif
285}
286
287#endif /* MOUNTED_GETMNTINFO */
288
289#ifdef MOUNTED_VMOUNT /* AIX. */
290static char *
291fstype_to_string (int t)
292{
293 struct vfs_ent *e;
294
295 e = getvfsbytype (t);
296 if (!e || !e->vfsent_name)
297 return "none";
298 else
299 return e->vfsent_name;
300}
301#endif /* MOUNTED_VMOUNT */
302
303
304#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
305
306/* Return the device number from MOUNT_OPTIONS, if possible.
307 Otherwise return (dev_t) -1. */
308
309static dev_t
310dev_from_mount_options (char const *mount_options)
311{
312 /* GNU/Linux allows file system implementations to define their own
313 meaning for "dev=" mount options, so don't trust the meaning
314 here. */
315# ifndef __linux__
316
317 static char const dev_pattern[] = ",dev=";
318 char const *devopt = strstr (mount_options, dev_pattern);
319
320 if (devopt)
321 {
322 char const *optval = devopt + sizeof dev_pattern - 1;
323 char *optvalend;
324 unsigned long int dev;
325 errno = 0;
326 dev = strtoul (optval, &optvalend, 16);
327 if (optval != optvalend
328 && (*optvalend == '\0' || *optvalend == ',')
329 && ! (dev == ULONG_MAX && errno == ERANGE)
330 && dev == (dev_t) dev)
331 return dev;
332 }
333
334# endif
335
336 return -1;
337}
338
339#endif
340
341/* Return a list of the currently mounted file systems, or NULL on error.
342 Add each entry to the tail of the list so that they stay in order.
343 If NEED_FS_TYPE is true, ensure that the file system type fields in
344 the returned list are valid. Otherwise, they might not be. */
345
346struct mount_entry *
347read_file_system_list (bool need_fs_type)
348{
349 struct mount_entry *mount_list;
350 struct mount_entry *me;
351 struct mount_entry **mtail = &mount_list;
352
353#ifdef MOUNTED_LISTMNTENT
354 {
355 struct tabmntent *mntlist, *p;
356 struct mntent *mnt;
357 struct mount_entry *me;
358
359 /* the third and fourth arguments could be used to filter mounts,
360 but Crays doesn't seem to have any mounts that we want to
361 remove. Specifically, automount create normal NFS mounts.
362 */
363
364 if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
365 return NULL;
366 for (p = mntlist; p; p = p->next) {
367 mnt = p->ment;
368 me = xmalloc (sizeof *me);
369 me->me_devname = xstrdup (mnt->mnt_fsname);
370 me->me_mountdir = xstrdup (mnt->mnt_dir);
371 me->me_type = xstrdup (mnt->mnt_type);
372 me->me_type_malloced = 1;
373 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
374 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
375 me->me_dev = -1;
376 *mtail = me;
377 mtail = &me->me_next;
378 }
379 freemntlist (mntlist);
380 }
381#endif
382
383#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
384 {
385 struct mntent *mnt;
386 char *table = MOUNTED;
387 FILE *fp;
388
389 fp = setmntent (table, "r");
390 if (fp == NULL)
391 return NULL;
392
393 while ((mnt = getmntent (fp)))
394 {
395 me = xmalloc (sizeof *me);
396 me->me_devname = xstrdup (mnt->mnt_fsname);
397 me->me_mountdir = xstrdup (mnt->mnt_dir);
398 me->me_type = xstrdup (mnt->mnt_type);
399 me->me_type_malloced = 1;
400 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
401 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
402 me->me_dev = dev_from_mount_options (mnt->mnt_opts);
403
404 /* Add to the linked list. */
405 *mtail = me;
406 mtail = &me->me_next;
407 }
408
409 if (endmntent (fp) == 0)
410 goto free_then_fail;
411 }
412#endif /* MOUNTED_GETMNTENT1. */
413
414#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
415 {
416 struct statfs *fsp;
417 int entries;
418
419 entries = getmntinfo (&fsp, MNT_NOWAIT);
420 if (entries < 0)
421 return NULL;
422 for (; entries-- > 0; fsp++)
423 {
424 char *fs_type = fsp_to_string (fsp);
425
426 me = xmalloc (sizeof *me);
427 me->me_devname = xstrdup (fsp->f_mntfromname);
428 me->me_mountdir = xstrdup (fsp->f_mntonname);
429 me->me_type = fs_type;
430 me->me_type_malloced = 0;
431 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
432 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
433 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
434
435 /* Add to the linked list. */
436 *mtail = me;
437 mtail = &me->me_next;
438 }
439 }
440#endif /* MOUNTED_GETMNTINFO */
441
442#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
443 {
444 struct statvfs *fsp;
445 int entries;
446
447 entries = getmntinfo (&fsp, MNT_NOWAIT);
448 if (entries < 0)
449 return NULL;
450 for (; entries-- > 0; fsp++)
451 {
452 me = xmalloc (sizeof *me);
453 me->me_devname = xstrdup (fsp->f_mntfromname);
454 me->me_mountdir = xstrdup (fsp->f_mntonname);
455 me->me_type = xstrdup (fsp->f_fstypename);
456 me->me_type_malloced = 1;
457 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
458 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
459 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
460
461 /* Add to the linked list. */
462 *mtail = me;
463 mtail = &me->me_next;
464 }
465 }
466#endif /* MOUNTED_GETMNTINFO2 */
467
468#ifdef MOUNTED_GETMNT /* Ultrix. */
469 {
470 int offset = 0;
471 int val;
472 struct fs_data fsd;
473
474 while (errno = 0,
475 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
476 (char *) 0)))
477 {
478 me = xmalloc (sizeof *me);
479 me->me_devname = xstrdup (fsd.fd_req.devname);
480 me->me_mountdir = xstrdup (fsd.fd_req.path);
481 me->me_type = gt_names[fsd.fd_req.fstype];
482 me->me_type_malloced = 0;
483 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
484 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
485 me->me_dev = fsd.fd_req.dev;
486
487 /* Add to the linked list. */
488 *mtail = me;
489 mtail = &me->me_next;
490 }
491 if (val < 0)
492 goto free_then_fail;
493 }
494#endif /* MOUNTED_GETMNT. */
495
496#if defined MOUNTED_FS_STAT_DEV /* BeOS */
497 {
498 /* The next_dev() and fs_stat_dev() system calls give the list of
499 all file systems, including the information returned by statvfs()
500 (fs type, total blocks, free blocks etc.), but without the mount
501 point. But on BeOS all file systems except / are mounted in the
502 rootfs, directly under /.
503 The directory name of the mount point is often, but not always,
504 identical to the volume name of the device.
505 We therefore get the list of subdirectories of /, and the list
506 of all file systems, and match the two lists. */
507
508 DIR *dirp;
509 struct rootdir_entry
510 {
511 char *name;
512 dev_t dev;
513 ino_t ino;
514 struct rootdir_entry *next;
515 };
516 struct rootdir_entry *rootdir_list;
517 struct rootdir_entry **rootdir_tail;
518 int32 pos;
519 dev_t dev;
520 fs_info fi;
521
522 /* All volumes are mounted in the rootfs, directly under /. */
523 rootdir_list = NULL;
524 rootdir_tail = &rootdir_list;
525 dirp = opendir ("/");
526 if (dirp)
527 {
528 struct dirent *d;
529
530 while ((d = readdir (dirp)) != NULL)
531 {
532 char *name;
533 struct stat statbuf;
534
535 if (strcmp (d->d_name, "..") == 0)
536 continue;
537
538 if (strcmp (d->d_name, ".") == 0)
539 name = xstrdup ("/");
540 else
541 {
542 name = xmalloc (1 + strlen (d->d_name) + 1);
543 name[0] = '/';
544 strcpy (name + 1, d->d_name);
545 }
546
547 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
548 {
549 struct rootdir_entry *re = xmalloc (sizeof *re);
550 re->name = name;
551 re->dev = statbuf.st_dev;
552 re->ino = statbuf.st_ino;
553
554 /* Add to the linked list. */
555 *rootdir_tail = re;
556 rootdir_tail = &re->next;
557 }
558 else
559 free (name);
560 }
561 closedir (dirp);
562 }
563 *rootdir_tail = NULL;
564
565 for (pos = 0; (dev = next_dev (&pos)) >= 0; )
566 if (fs_stat_dev (dev, &fi) >= 0)
567 {
568 /* Note: fi.dev == dev. */
569 struct rootdir_entry *re;
570
571 for (re = rootdir_list; re; re = re->next)
572 if (re->dev == fi.dev && re->ino == fi.root)
573 break;
574
575 me = xmalloc (sizeof *me);
576 me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
577 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
578 me->me_type = xstrdup (fi.fsh_name);
579 me->me_type_malloced = 1;
580 me->me_dev = fi.dev;
581 me->me_dummy = 0;
582 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
583
584 /* Add to the linked list. */
585 *mtail = me;
586 mtail = &me->me_next;
587 }
588 *mtail = NULL;
589
590 while (rootdir_list != NULL)
591 {
592 struct rootdir_entry *re = rootdir_list;
593 rootdir_list = re->next;
594 free (re->name);
595 free (re);
596 }
597 }
598#endif /* MOUNTED_FS_STAT_DEV */
599
600#if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
601 {
602 int numsys, counter;
603 size_t bufsize;
604 struct statfs *stats;
605
606 numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
607 if (numsys < 0)
608 return (NULL);
609 if (SIZE_MAX / sizeof *stats <= numsys)
610 xalloc_die ();
611
612 bufsize = (1 + numsys) * sizeof *stats;
613 stats = xmalloc (bufsize);
614 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
615
616 if (numsys < 0)
617 {
618 free (stats);
619 return (NULL);
620 }
621
622 for (counter = 0; counter < numsys; counter++)
623 {
624 me = xmalloc (sizeof *me);
625 me->me_devname = xstrdup (stats[counter].f_mntfromname);
626 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
627 me->me_type = xstrdup (FS_TYPE (stats[counter]));
628 me->me_type_malloced = 1;
629 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
630 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
631 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
632
633 /* Add to the linked list. */
634 *mtail = me;
635 mtail = &me->me_next;
636 }
637
638 free (stats);
639 }
640#endif /* MOUNTED_GETFSSTAT */
641
642#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
643 {
644 struct mnttab mnt;
645 char *table = "/etc/mnttab";
646 FILE *fp;
647
648 fp = fopen (table, "r");
649 if (fp == NULL)
650 return NULL;
651
652 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
653 {
654 me = xmalloc (sizeof *me);
655# ifdef GETFSTYP /* SVR3. */
656 me->me_devname = xstrdup (mnt.mt_dev);
657# else
658 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
659 strcpy (me->me_devname, "/dev/");
660 strcpy (me->me_devname + 5, mnt.mt_dev);
661# endif
662 me->me_mountdir = xstrdup (mnt.mt_filsys);
663 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
664 me->me_type = "";
665 me->me_type_malloced = 0;
666# ifdef GETFSTYP /* SVR3. */
667 if (need_fs_type)
668 {
669 struct statfs fsd;
670 char typebuf[FSTYPSZ];
671
672 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
673 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
674 {
675 me->me_type = xstrdup (typebuf);
676 me->me_type_malloced = 1;
677 }
678 }
679# endif
680 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
681 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
682
683 /* Add to the linked list. */
684 *mtail = me;
685 mtail = &me->me_next;
686 }
687
688 if (ferror (fp))
689 {
690 /* The last fread() call must have failed. */
691 int saved_errno = errno;
692 fclose (fp);
693 errno = saved_errno;
694 goto free_then_fail;
695 }
696
697 if (fclose (fp) == EOF)
698 goto free_then_fail;
699 }
700#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
701
702#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
703 {
704 struct mntent **mnttbl = getmnttbl (), **ent;
705 for (ent=mnttbl;*ent;ent++)
706 {
707 me = xmalloc (sizeof *me);
708 me->me_devname = xstrdup ( (*ent)->mt_resource);
709 me->me_mountdir = xstrdup ( (*ent)->mt_directory);
710 me->me_type = xstrdup ((*ent)->mt_fstype);
711 me->me_type_malloced = 1;
712 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
713 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
714 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
715
716 /* Add to the linked list. */
717 *mtail = me;
718 mtail = &me->me_next;
719 }
720 endmnttbl ();
721 }
722#endif
723
724#ifdef MOUNTED_GETMNTENT2 /* SVR4. */
725 {
726 struct mnttab mnt;
727 char *table = MNTTAB;
728 FILE *fp;
729 int ret;
730 int lockfd = -1;
731
732# if defined F_RDLCK && defined F_SETLKW
733 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
734 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
735 for this file name, we should use their macro name instead.
736 (Why not just lock MNTTAB directly? We don't know.) */
737# ifndef MNTTAB_LOCK
738# define MNTTAB_LOCK "/etc/.mnttab.lock"
739# endif
740 lockfd = open (MNTTAB_LOCK, O_RDONLY);
741 if (0 <= lockfd)
742 {
743 struct flock flock;
744 flock.l_type = F_RDLCK;
745 flock.l_whence = SEEK_SET;
746 flock.l_start = 0;
747 flock.l_len = 0;
748 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
749 if (errno != EINTR)
750 {
751 int saved_errno = errno;
752 close (lockfd);
753 errno = saved_errno;
754 return NULL;
755 }
756 }
757 else if (errno != ENOENT)
758 return NULL;
759# endif
760
761 errno = 0;
762 fp = fopen (table, "r");
763 if (fp == NULL)
764 ret = errno;
765 else
766 {
767 while ((ret = getmntent (fp, &mnt)) == 0)
768 {
769 me = xmalloc (sizeof *me);
770 me->me_devname = xstrdup (mnt.mnt_special);
771 me->me_mountdir = xstrdup (mnt.mnt_mountp);
772 me->me_type = xstrdup (mnt.mnt_fstype);
773 me->me_type_malloced = 1;
774 me->me_dummy = MNT_IGNORE (&mnt) != 0;
775 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
776 me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
777
778 /* Add to the linked list. */
779 *mtail = me;
780 mtail = &me->me_next;
781 }
782
783 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
784 }
785
786 if (0 <= lockfd && close (lockfd) != 0)
787 ret = errno;
788
789 if (0 <= ret)
790 {
791 errno = ret;
792 goto free_then_fail;
793 }
794 }
795#endif /* MOUNTED_GETMNTENT2. */
796
797#ifdef MOUNTED_VMOUNT /* AIX. */
798 {
799 int bufsize;
800 char *entries, *thisent;
801 struct vmount *vmp;
802 int n_entries;
803 int i;
804
805 /* Ask how many bytes to allocate for the mounted file system info. */
806 if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
807 return NULL;
808 entries = xmalloc (bufsize);
809
810 /* Get the list of mounted file systems. */
811 n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
812 if (n_entries < 0)
813 {
814 int saved_errno = errno;
815 free (entries);
816 errno = saved_errno;
817 return NULL;
818 }
819
820 for (i = 0, thisent = entries;
821 i < n_entries;
822 i++, thisent += vmp->vmt_length)
823 {
824 char *options, *ignore;
825
826 vmp = (struct vmount *) thisent;
827 me = xmalloc (sizeof *me);
828 if (vmp->vmt_flags & MNT_REMOTE)
829 {
830 char *host, *dir;
831
832 me->me_remote = 1;
833 /* Prepend the remote dirname. */
834 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
835 dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
836 me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
837 strcpy (me->me_devname, host);
838 strcat (me->me_devname, ":");
839 strcat (me->me_devname, dir);
840 }
841 else
842 {
843 me->me_remote = 0;
844 me->me_devname = xstrdup (thisent +
845 vmp->vmt_data[VMT_OBJECT].vmt_off);
846 }
847 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
848 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
849 me->me_type_malloced = 1;
850 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
851 ignore = strstr (options, "ignore");
852 me->me_dummy = (ignore
853 && (ignore == options || ignore[-1] == ',')
854 && (ignore[sizeof "ignore" - 1] == ','
855 || ignore[sizeof "ignore" - 1] == '\0'));
856 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
857
858 /* Add to the linked list. */
859 *mtail = me;
860 mtail = &me->me_next;
861 }
862 free (entries);
863 }
864#endif /* MOUNTED_VMOUNT. */
865
866 *mtail = NULL;
867 return mount_list;
868
869
870 free_then_fail:
871 {
872 int saved_errno = errno;
873 *mtail = NULL;
874
875 while (mount_list)
876 {
877 me = mount_list->me_next;
878 free (mount_list->me_devname);
879 free (mount_list->me_mountdir);
880 if (mount_list->me_type_malloced)
881 free (mount_list->me_type);
882 free (mount_list);
883 mount_list = me;
884 }
885
886 errno = saved_errno;
887 return NULL;
888 }
889}
diff --git a/gl/mountlist.h b/gl/mountlist.h
new file mode 100644
index 00000000..7f5a6f77
--- /dev/null
+++ b/gl/mountlist.h
@@ -0,0 +1,41 @@
1/* mountlist.h -- declarations for list of mounted file systems
2
3 Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005
4 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef MOUNTLIST_H_
21# define MOUNTLIST_H_
22
23# include <stdbool.h>
24# include <sys/types.h>
25
26/* A mount table entry. */
27struct mount_entry
28{
29 char *me_devname; /* Device node name, including "/dev/". */
30 char *me_mountdir; /* Mount point directory name. */
31 char *me_type; /* "nfs", "4.2", etc. */
32 dev_t me_dev; /* Device number of me_mountdir. */
33 unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */
34 unsigned int me_remote : 1; /* Nonzero for remote fileystems. */
35 unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */
36 struct mount_entry *me_next;
37};
38
39struct mount_entry *read_file_system_list (bool need_fs_type);
40
41#endif
diff --git a/gl/open-safer.c b/gl/open-safer.c
new file mode 100644
index 00000000..04a72eb7
--- /dev/null
+++ b/gl/open-safer.c
@@ -0,0 +1,50 @@
1/* Invoke open, but avoid some glitches.
2
3 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <config.h>
22
23#include "fcntl-safer.h"
24
25#include <fcntl.h>
26#include <stdarg.h>
27#include "unistd-safer.h"
28
29int
30open_safer (char const *file, int flags, ...)
31{
32 mode_t mode = 0;
33
34 if (flags & O_CREAT)
35 {
36 va_list ap;
37 va_start (ap, flags);
38
39 /* Assume mode_t promotes to int if and only if it is smaller.
40 This assumption isn't guaranteed by the C standard, but we
41 don't know of any real-world counterexamples. */
42 mode = (sizeof (mode_t) < sizeof (int)
43 ? va_arg (ap, int)
44 : va_arg (ap, mode_t));
45
46 va_end (ap);
47 }
48
49 return fd_safer (open (file, flags, mode));
50}
diff --git a/gl/pipe-safer.c b/gl/pipe-safer.c
new file mode 100644
index 00000000..e4431b33
--- /dev/null
+++ b/gl/pipe-safer.c
@@ -0,0 +1,57 @@
1/* Invoke pipe, but avoid some glitches.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/* Written by Jim Meyering. */
19
20#include <config.h>
21
22#include "unistd-safer.h"
23
24#include <unistd.h>
25#include <errno.h>
26
27/* Like pipe, but ensure that neither of the file descriptors is
28 STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on
29 platforms that lack pipe. */
30
31int
32pipe_safer (int fd[2])
33{
34#if HAVE_PIPE
35 if (pipe (fd) == 0)
36 {
37 int i;
38 for (i = 0; i < 2; i++)
39 {
40 fd[i] = fd_safer (fd[i]);
41 if (fd[i] < 0)
42 {
43 int e = errno;
44 close (fd[1 - i]);
45 errno = e;
46 return -1;
47 }
48 }
49
50 return 0;
51 }
52#else
53 errno = ENOSYS;
54#endif
55
56 return -1;
57}
diff --git a/gl/printf-args.c b/gl/printf-args.c
new file mode 100644
index 00000000..358801c9
--- /dev/null
+++ b/gl/printf-args.c
@@ -0,0 +1,141 @@
1/* Decomposed printf argument list.
2 Copyright (C) 1999, 2002-2003, 2005-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "printf-args.h"
22
23#ifdef STATIC
24STATIC
25#endif
26int
27printf_fetchargs (va_list args, arguments *a)
28{
29 size_t i;
30 argument *ap;
31
32 for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
33 switch (ap->type)
34 {
35 case TYPE_SCHAR:
36 ap->a.a_schar = va_arg (args, /*signed char*/ int);
37 break;
38 case TYPE_UCHAR:
39 ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
40 break;
41 case TYPE_SHORT:
42 ap->a.a_short = va_arg (args, /*short*/ int);
43 break;
44 case TYPE_USHORT:
45 ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
46 break;
47 case TYPE_INT:
48 ap->a.a_int = va_arg (args, int);
49 break;
50 case TYPE_UINT:
51 ap->a.a_uint = va_arg (args, unsigned int);
52 break;
53 case TYPE_LONGINT:
54 ap->a.a_longint = va_arg (args, long int);
55 break;
56 case TYPE_ULONGINT:
57 ap->a.a_ulongint = va_arg (args, unsigned long int);
58 break;
59#ifdef HAVE_LONG_LONG_INT
60 case TYPE_LONGLONGINT:
61 ap->a.a_longlongint = va_arg (args, long long int);
62 break;
63 case TYPE_ULONGLONGINT:
64 ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
65 break;
66#endif
67 case TYPE_DOUBLE:
68 ap->a.a_double = va_arg (args, double);
69 break;
70#ifdef HAVE_LONG_DOUBLE
71 case TYPE_LONGDOUBLE:
72 ap->a.a_longdouble = va_arg (args, long double);
73 break;
74#endif
75 case TYPE_CHAR:
76 ap->a.a_char = va_arg (args, int);
77 break;
78#ifdef HAVE_WINT_T
79 case TYPE_WIDE_CHAR:
80 /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
81 default argument promotions", this is not the case in mingw32,
82 where wint_t is 'unsigned short'. */
83 ap->a.a_wide_char =
84 (sizeof (wint_t) < sizeof (int)
85 ? va_arg (args, int)
86 : va_arg (args, wint_t));
87 break;
88#endif
89 case TYPE_STRING:
90 ap->a.a_string = va_arg (args, const char *);
91 /* A null pointer is an invalid argument for "%s", but in practice
92 it occurs quite frequently in printf statements that produce
93 debug output. Use a fallback in this case. */
94 if (ap->a.a_string == NULL)
95 ap->a.a_string = "(NULL)";
96 break;
97#ifdef HAVE_WCHAR_T
98 case TYPE_WIDE_STRING:
99 ap->a.a_wide_string = va_arg (args, const wchar_t *);
100 /* A null pointer is an invalid argument for "%ls", but in practice
101 it occurs quite frequently in printf statements that produce
102 debug output. Use a fallback in this case. */
103 if (ap->a.a_wide_string == NULL)
104 {
105 static const wchar_t wide_null_string[] =
106 {
107 (wchar_t)'(',
108 (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
109 (wchar_t)')',
110 (wchar_t)0
111 };
112 ap->a.a_wide_string = wide_null_string;
113 }
114 break;
115#endif
116 case TYPE_POINTER:
117 ap->a.a_pointer = va_arg (args, void *);
118 break;
119 case TYPE_COUNT_SCHAR_POINTER:
120 ap->a.a_count_schar_pointer = va_arg (args, signed char *);
121 break;
122 case TYPE_COUNT_SHORT_POINTER:
123 ap->a.a_count_short_pointer = va_arg (args, short *);
124 break;
125 case TYPE_COUNT_INT_POINTER:
126 ap->a.a_count_int_pointer = va_arg (args, int *);
127 break;
128 case TYPE_COUNT_LONGINT_POINTER:
129 ap->a.a_count_longint_pointer = va_arg (args, long int *);
130 break;
131#ifdef HAVE_LONG_LONG_INT
132 case TYPE_COUNT_LONGLONGINT_POINTER:
133 ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
134 break;
135#endif
136 default:
137 /* Unknown type. */
138 return -1;
139 }
140 return 0;
141}
diff --git a/gl/printf-args.h b/gl/printf-args.h
new file mode 100644
index 00000000..5759da0e
--- /dev/null
+++ b/gl/printf-args.h
@@ -0,0 +1,136 @@
1/* Decomposed printf argument list.
2 Copyright (C) 1999, 2002-2003, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _PRINTF_ARGS_H
19#define _PRINTF_ARGS_H
20
21/* Get size_t. */
22#include <stddef.h>
23
24/* Get wchar_t. */
25#ifdef HAVE_WCHAR_T
26# include <stddef.h>
27#endif
28
29/* Get wint_t. */
30#ifdef HAVE_WINT_T
31# include <wchar.h>
32#endif
33
34/* Get va_list. */
35#include <stdarg.h>
36
37
38/* Argument types */
39typedef enum
40{
41 TYPE_NONE,
42 TYPE_SCHAR,
43 TYPE_UCHAR,
44 TYPE_SHORT,
45 TYPE_USHORT,
46 TYPE_INT,
47 TYPE_UINT,
48 TYPE_LONGINT,
49 TYPE_ULONGINT,
50#ifdef HAVE_LONG_LONG_INT
51 TYPE_LONGLONGINT,
52 TYPE_ULONGLONGINT,
53#endif
54 TYPE_DOUBLE,
55#ifdef HAVE_LONG_DOUBLE
56 TYPE_LONGDOUBLE,
57#endif
58 TYPE_CHAR,
59#ifdef HAVE_WINT_T
60 TYPE_WIDE_CHAR,
61#endif
62 TYPE_STRING,
63#ifdef HAVE_WCHAR_T
64 TYPE_WIDE_STRING,
65#endif
66 TYPE_POINTER,
67 TYPE_COUNT_SCHAR_POINTER,
68 TYPE_COUNT_SHORT_POINTER,
69 TYPE_COUNT_INT_POINTER,
70 TYPE_COUNT_LONGINT_POINTER
71#ifdef HAVE_LONG_LONG_INT
72, TYPE_COUNT_LONGLONGINT_POINTER
73#endif
74} arg_type;
75
76/* Polymorphic argument */
77typedef struct
78{
79 arg_type type;
80 union
81 {
82 signed char a_schar;
83 unsigned char a_uchar;
84 short a_short;
85 unsigned short a_ushort;
86 int a_int;
87 unsigned int a_uint;
88 long int a_longint;
89 unsigned long int a_ulongint;
90#ifdef HAVE_LONG_LONG_INT
91 long long int a_longlongint;
92 unsigned long long int a_ulonglongint;
93#endif
94 float a_float;
95 double a_double;
96#ifdef HAVE_LONG_DOUBLE
97 long double a_longdouble;
98#endif
99 int a_char;
100#ifdef HAVE_WINT_T
101 wint_t a_wide_char;
102#endif
103 const char* a_string;
104#ifdef HAVE_WCHAR_T
105 const wchar_t* a_wide_string;
106#endif
107 void* a_pointer;
108 signed char * a_count_schar_pointer;
109 short * a_count_short_pointer;
110 int * a_count_int_pointer;
111 long int * a_count_longint_pointer;
112#ifdef HAVE_LONG_LONG_INT
113 long long int * a_count_longlongint_pointer;
114#endif
115 }
116 a;
117}
118argument;
119
120typedef struct
121{
122 size_t count;
123 argument *arg;
124}
125arguments;
126
127
128/* Fetch the arguments, putting them into a. */
129#ifdef STATIC
130STATIC
131#else
132extern
133#endif
134int printf_fetchargs (va_list args, arguments *a);
135
136#endif /* _PRINTF_ARGS_H */
diff --git a/gl/printf-parse.c b/gl/printf-parse.c
new file mode 100644
index 00000000..9a86f773
--- /dev/null
+++ b/gl/printf-parse.c
@@ -0,0 +1,543 @@
1/* Formatted output to strings.
2 Copyright (C) 1999-2000, 2002-2003, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#if WIDE_CHAR_VERSION
22# include "wprintf-parse.h"
23#else
24# include "printf-parse.h"
25#endif
26
27/* Get size_t, NULL. */
28#include <stddef.h>
29
30/* Get intmax_t. */
31#if HAVE_STDINT_H_WITH_UINTMAX
32# include <stdint.h>
33#endif
34#if HAVE_INTTYPES_H_WITH_UINTMAX
35# include <inttypes.h>
36#endif
37
38/* malloc(), realloc(), free(). */
39#include <stdlib.h>
40
41/* Checked size_t computations. */
42#include "xsize.h"
43
44#if WIDE_CHAR_VERSION
45# define PRINTF_PARSE wprintf_parse
46# define CHAR_T wchar_t
47# define DIRECTIVE wchar_t_directive
48# define DIRECTIVES wchar_t_directives
49#else
50# define PRINTF_PARSE printf_parse
51# define CHAR_T char
52# define DIRECTIVE char_directive
53# define DIRECTIVES char_directives
54#endif
55
56#ifdef STATIC
57STATIC
58#endif
59int
60PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
61{
62 const CHAR_T *cp = format; /* pointer into format */
63 size_t arg_posn = 0; /* number of regular arguments consumed */
64 size_t d_allocated; /* allocated elements of d->dir */
65 size_t a_allocated; /* allocated elements of a->arg */
66 size_t max_width_length = 0;
67 size_t max_precision_length = 0;
68
69 d->count = 0;
70 d_allocated = 1;
71 d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
72 if (d->dir == NULL)
73 /* Out of memory. */
74 return -1;
75
76 a->count = 0;
77 a_allocated = 0;
78 a->arg = NULL;
79
80#define REGISTER_ARG(_index_,_type_) \
81 { \
82 size_t n = (_index_); \
83 if (n >= a_allocated) \
84 { \
85 size_t memory_size; \
86 argument *memory; \
87 \
88 a_allocated = xtimes (a_allocated, 2); \
89 if (a_allocated <= n) \
90 a_allocated = xsum (n, 1); \
91 memory_size = xtimes (a_allocated, sizeof (argument)); \
92 if (size_overflow_p (memory_size)) \
93 /* Overflow, would lead to out of memory. */ \
94 goto error; \
95 memory = (argument *) (a->arg \
96 ? realloc (a->arg, memory_size) \
97 : malloc (memory_size)); \
98 if (memory == NULL) \
99 /* Out of memory. */ \
100 goto error; \
101 a->arg = memory; \
102 } \
103 while (a->count <= n) \
104 a->arg[a->count++].type = TYPE_NONE; \
105 if (a->arg[n].type == TYPE_NONE) \
106 a->arg[n].type = (_type_); \
107 else if (a->arg[n].type != (_type_)) \
108 /* Ambiguous type for positional argument. */ \
109 goto error; \
110 }
111
112 while (*cp != '\0')
113 {
114 CHAR_T c = *cp++;
115 if (c == '%')
116 {
117 size_t arg_index = ARG_NONE;
118 DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
119
120 /* Initialize the next directive. */
121 dp->dir_start = cp - 1;
122 dp->flags = 0;
123 dp->width_start = NULL;
124 dp->width_end = NULL;
125 dp->width_arg_index = ARG_NONE;
126 dp->precision_start = NULL;
127 dp->precision_end = NULL;
128 dp->precision_arg_index = ARG_NONE;
129 dp->arg_index = ARG_NONE;
130
131 /* Test for positional argument. */
132 if (*cp >= '0' && *cp <= '9')
133 {
134 const CHAR_T *np;
135
136 for (np = cp; *np >= '0' && *np <= '9'; np++)
137 ;
138 if (*np == '$')
139 {
140 size_t n = 0;
141
142 for (np = cp; *np >= '0' && *np <= '9'; np++)
143 n = xsum (xtimes (n, 10), *np - '0');
144 if (n == 0)
145 /* Positional argument 0. */
146 goto error;
147 if (size_overflow_p (n))
148 /* n too large, would lead to out of memory later. */
149 goto error;
150 arg_index = n - 1;
151 cp = np + 1;
152 }
153 }
154
155 /* Read the flags. */
156 for (;;)
157 {
158 if (*cp == '\'')
159 {
160 dp->flags |= FLAG_GROUP;
161 cp++;
162 }
163 else if (*cp == '-')
164 {
165 dp->flags |= FLAG_LEFT;
166 cp++;
167 }
168 else if (*cp == '+')
169 {
170 dp->flags |= FLAG_SHOWSIGN;
171 cp++;
172 }
173 else if (*cp == ' ')
174 {
175 dp->flags |= FLAG_SPACE;
176 cp++;
177 }
178 else if (*cp == '#')
179 {
180 dp->flags |= FLAG_ALT;
181 cp++;
182 }
183 else if (*cp == '0')
184 {
185 dp->flags |= FLAG_ZERO;
186 cp++;
187 }
188 else
189 break;
190 }
191
192 /* Parse the field width. */
193 if (*cp == '*')
194 {
195 dp->width_start = cp;
196 cp++;
197 dp->width_end = cp;
198 if (max_width_length < 1)
199 max_width_length = 1;
200
201 /* Test for positional argument. */
202 if (*cp >= '0' && *cp <= '9')
203 {
204 const CHAR_T *np;
205
206 for (np = cp; *np >= '0' && *np <= '9'; np++)
207 ;
208 if (*np == '$')
209 {
210 size_t n = 0;
211
212 for (np = cp; *np >= '0' && *np <= '9'; np++)
213 n = xsum (xtimes (n, 10), *np - '0');
214 if (n == 0)
215 /* Positional argument 0. */
216 goto error;
217 if (size_overflow_p (n))
218 /* n too large, would lead to out of memory later. */
219 goto error;
220 dp->width_arg_index = n - 1;
221 cp = np + 1;
222 }
223 }
224 if (dp->width_arg_index == ARG_NONE)
225 {
226 dp->width_arg_index = arg_posn++;
227 if (dp->width_arg_index == ARG_NONE)
228 /* arg_posn wrapped around. */
229 goto error;
230 }
231 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
232 }
233 else if (*cp >= '0' && *cp <= '9')
234 {
235 size_t width_length;
236
237 dp->width_start = cp;
238 for (; *cp >= '0' && *cp <= '9'; cp++)
239 ;
240 dp->width_end = cp;
241 width_length = dp->width_end - dp->width_start;
242 if (max_width_length < width_length)
243 max_width_length = width_length;
244 }
245
246 /* Parse the precision. */
247 if (*cp == '.')
248 {
249 cp++;
250 if (*cp == '*')
251 {
252 dp->precision_start = cp - 1;
253 cp++;
254 dp->precision_end = cp;
255 if (max_precision_length < 2)
256 max_precision_length = 2;
257
258 /* Test for positional argument. */
259 if (*cp >= '0' && *cp <= '9')
260 {
261 const CHAR_T *np;
262
263 for (np = cp; *np >= '0' && *np <= '9'; np++)
264 ;
265 if (*np == '$')
266 {
267 size_t n = 0;
268
269 for (np = cp; *np >= '0' && *np <= '9'; np++)
270 n = xsum (xtimes (n, 10), *np - '0');
271 if (n == 0)
272 /* Positional argument 0. */
273 goto error;
274 if (size_overflow_p (n))
275 /* n too large, would lead to out of memory
276 later. */
277 goto error;
278 dp->precision_arg_index = n - 1;
279 cp = np + 1;
280 }
281 }
282 if (dp->precision_arg_index == ARG_NONE)
283 {
284 dp->precision_arg_index = arg_posn++;
285 if (dp->precision_arg_index == ARG_NONE)
286 /* arg_posn wrapped around. */
287 goto error;
288 }
289 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
290 }
291 else
292 {
293 size_t precision_length;
294
295 dp->precision_start = cp - 1;
296 for (; *cp >= '0' && *cp <= '9'; cp++)
297 ;
298 dp->precision_end = cp;
299 precision_length = dp->precision_end - dp->precision_start;
300 if (max_precision_length < precision_length)
301 max_precision_length = precision_length;
302 }
303 }
304
305 {
306 arg_type type;
307
308 /* Parse argument type/size specifiers. */
309 {
310 int flags = 0;
311
312 for (;;)
313 {
314 if (*cp == 'h')
315 {
316 flags |= (1 << (flags & 1));
317 cp++;
318 }
319 else if (*cp == 'L')
320 {
321 flags |= 4;
322 cp++;
323 }
324 else if (*cp == 'l')
325 {
326 flags += 8;
327 cp++;
328 }
329#ifdef HAVE_INTMAX_T
330 else if (*cp == 'j')
331 {
332 if (sizeof (intmax_t) > sizeof (long))
333 {
334 /* intmax_t = long long */
335 flags += 16;
336 }
337 else if (sizeof (intmax_t) > sizeof (int))
338 {
339 /* intmax_t = long */
340 flags += 8;
341 }
342 cp++;
343 }
344#endif
345 else if (*cp == 'z' || *cp == 'Z')
346 {
347 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
348 because the warning facility in gcc-2.95.2 understands
349 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
350 if (sizeof (size_t) > sizeof (long))
351 {
352 /* size_t = long long */
353 flags += 16;
354 }
355 else if (sizeof (size_t) > sizeof (int))
356 {
357 /* size_t = long */
358 flags += 8;
359 }
360 cp++;
361 }
362 else if (*cp == 't')
363 {
364 if (sizeof (ptrdiff_t) > sizeof (long))
365 {
366 /* ptrdiff_t = long long */
367 flags += 16;
368 }
369 else if (sizeof (ptrdiff_t) > sizeof (int))
370 {
371 /* ptrdiff_t = long */
372 flags += 8;
373 }
374 cp++;
375 }
376 else
377 break;
378 }
379
380 /* Read the conversion character. */
381 c = *cp++;
382 switch (c)
383 {
384 case 'd': case 'i':
385#ifdef HAVE_LONG_LONG_INT
386 /* If 'long long' exists and is larger than 'long': */
387 if (flags >= 16 || (flags & 4))
388 type = TYPE_LONGLONGINT;
389 else
390#endif
391 /* If 'long long' exists and is the same as 'long', we parse
392 "lld" into TYPE_LONGINT. */
393 if (flags >= 8)
394 type = TYPE_LONGINT;
395 else if (flags & 2)
396 type = TYPE_SCHAR;
397 else if (flags & 1)
398 type = TYPE_SHORT;
399 else
400 type = TYPE_INT;
401 break;
402 case 'o': case 'u': case 'x': case 'X':
403#ifdef HAVE_LONG_LONG_INT
404 /* If 'long long' exists and is larger than 'long': */
405 if (flags >= 16 || (flags & 4))
406 type = TYPE_ULONGLONGINT;
407 else
408#endif
409 /* If 'unsigned long long' exists and is the same as
410 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
411 if (flags >= 8)
412 type = TYPE_ULONGINT;
413 else if (flags & 2)
414 type = TYPE_UCHAR;
415 else if (flags & 1)
416 type = TYPE_USHORT;
417 else
418 type = TYPE_UINT;
419 break;
420 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
421 case 'a': case 'A':
422#ifdef HAVE_LONG_DOUBLE
423 if (flags >= 16 || (flags & 4))
424 type = TYPE_LONGDOUBLE;
425 else
426#endif
427 type = TYPE_DOUBLE;
428 break;
429 case 'c':
430 if (flags >= 8)
431#ifdef HAVE_WINT_T
432 type = TYPE_WIDE_CHAR;
433#else
434 goto error;
435#endif
436 else
437 type = TYPE_CHAR;
438 break;
439#ifdef HAVE_WINT_T
440 case 'C':
441 type = TYPE_WIDE_CHAR;
442 c = 'c';
443 break;
444#endif
445 case 's':
446 if (flags >= 8)
447#ifdef HAVE_WCHAR_T
448 type = TYPE_WIDE_STRING;
449#else
450 goto error;
451#endif
452 else
453 type = TYPE_STRING;
454 break;
455#ifdef HAVE_WCHAR_T
456 case 'S':
457 type = TYPE_WIDE_STRING;
458 c = 's';
459 break;
460#endif
461 case 'p':
462 type = TYPE_POINTER;
463 break;
464 case 'n':
465#ifdef HAVE_LONG_LONG_INT
466 /* If 'long long' exists and is larger than 'long': */
467 if (flags >= 16 || (flags & 4))
468 type = TYPE_COUNT_LONGLONGINT_POINTER;
469 else
470#endif
471 /* If 'long long' exists and is the same as 'long', we parse
472 "lln" into TYPE_COUNT_LONGINT_POINTER. */
473 if (flags >= 8)
474 type = TYPE_COUNT_LONGINT_POINTER;
475 else if (flags & 2)
476 type = TYPE_COUNT_SCHAR_POINTER;
477 else if (flags & 1)
478 type = TYPE_COUNT_SHORT_POINTER;
479 else
480 type = TYPE_COUNT_INT_POINTER;
481 break;
482 case '%':
483 type = TYPE_NONE;
484 break;
485 default:
486 /* Unknown conversion character. */
487 goto error;
488 }
489 }
490
491 if (type != TYPE_NONE)
492 {
493 dp->arg_index = arg_index;
494 if (dp->arg_index == ARG_NONE)
495 {
496 dp->arg_index = arg_posn++;
497 if (dp->arg_index == ARG_NONE)
498 /* arg_posn wrapped around. */
499 goto error;
500 }
501 REGISTER_ARG (dp->arg_index, type);
502 }
503 dp->conversion = c;
504 dp->dir_end = cp;
505 }
506
507 d->count++;
508 if (d->count >= d_allocated)
509 {
510 size_t memory_size;
511 DIRECTIVE *memory;
512
513 d_allocated = xtimes (d_allocated, 2);
514 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
515 if (size_overflow_p (memory_size))
516 /* Overflow, would lead to out of memory. */
517 goto error;
518 memory = (DIRECTIVE *) realloc (d->dir, memory_size);
519 if (memory == NULL)
520 /* Out of memory. */
521 goto error;
522 d->dir = memory;
523 }
524 }
525 }
526 d->dir[d->count].dir_start = cp;
527
528 d->max_width_length = max_width_length;
529 d->max_precision_length = max_precision_length;
530 return 0;
531
532error:
533 if (a->arg)
534 free (a->arg);
535 if (d->dir)
536 free (d->dir);
537 return -1;
538}
539
540#undef DIRECTIVES
541#undef DIRECTIVE
542#undef CHAR_T
543#undef PRINTF_PARSE
diff --git a/gl/printf-parse.h b/gl/printf-parse.h
new file mode 100644
index 00000000..82a0d37c
--- /dev/null
+++ b/gl/printf-parse.h
@@ -0,0 +1,74 @@
1/* Parse printf format string.
2 Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _PRINTF_PARSE_H
19#define _PRINTF_PARSE_H
20
21#include "printf-args.h"
22
23
24/* Flags */
25#define FLAG_GROUP 1 /* ' flag */
26#define FLAG_LEFT 2 /* - flag */
27#define FLAG_SHOWSIGN 4 /* + flag */
28#define FLAG_SPACE 8 /* space flag */
29#define FLAG_ALT 16 /* # flag */
30#define FLAG_ZERO 32
31
32/* arg_index value indicating that no argument is consumed. */
33#define ARG_NONE (~(size_t)0)
34
35/* A parsed directive. */
36typedef struct
37{
38 const char* dir_start;
39 const char* dir_end;
40 int flags;
41 const char* width_start;
42 const char* width_end;
43 size_t width_arg_index;
44 const char* precision_start;
45 const char* precision_end;
46 size_t precision_arg_index;
47 char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
48 size_t arg_index;
49}
50char_directive;
51
52/* A parsed format string. */
53typedef struct
54{
55 size_t count;
56 char_directive *dir;
57 size_t max_width_length;
58 size_t max_precision_length;
59}
60char_directives;
61
62
63/* Parses the format string. Fills in the number N of directives, and fills
64 in directives[0], ..., directives[N-1], and sets directives[N].dir_start
65 to the end of the format string. Also fills in the arg_type fields of the
66 arguments and the needed count of arguments. */
67#ifdef STATIC
68STATIC
69#else
70extern
71#endif
72int printf_parse (const char *format, char_directives *d, arguments *a);
73
74#endif /* _PRINTF_PARSE_H */
diff --git a/gl/regcomp.c b/gl/regcomp.c
new file mode 100644
index 00000000..8df6bb80
--- /dev/null
+++ b/gl/regcomp.c
@@ -0,0 +1,3858 @@
1/* Extended regular expression matching and search library.
2 Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
21 size_t length, reg_syntax_t syntax);
22static void re_compile_fastmap_iter (regex_t *bufp,
23 const re_dfastate_t *init_state,
24 char *fastmap);
25static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
26#ifdef RE_ENABLE_I18N
27static void free_charset (re_charset_t *cset);
28#endif /* RE_ENABLE_I18N */
29static void free_workarea_compile (regex_t *preg);
30static reg_errcode_t create_initial_state (re_dfa_t *dfa);
31#ifdef RE_ENABLE_I18N
32static void optimize_utf8 (re_dfa_t *dfa);
33#endif
34static reg_errcode_t analyze (regex_t *preg);
35static reg_errcode_t preorder (bin_tree_t *root,
36 reg_errcode_t (fn (void *, bin_tree_t *)),
37 void *extra);
38static reg_errcode_t postorder (bin_tree_t *root,
39 reg_errcode_t (fn (void *, bin_tree_t *)),
40 void *extra);
41static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
42static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
43static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
44 bin_tree_t *node);
45static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
46static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
47static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
48static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint);
49static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
50 unsigned int constraint);
51static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
52static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
53 Idx node, bool root);
54static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
55static Idx fetch_number (re_string_t *input, re_token_t *token,
56 reg_syntax_t syntax);
57static int peek_token (re_token_t *token, re_string_t *input,
58 reg_syntax_t syntax) internal_function;
59static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
60 reg_syntax_t syntax, reg_errcode_t *err);
61static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
62 re_token_t *token, reg_syntax_t syntax,
63 Idx nest, reg_errcode_t *err);
64static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
65 re_token_t *token, reg_syntax_t syntax,
66 Idx nest, reg_errcode_t *err);
67static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
68 re_token_t *token, reg_syntax_t syntax,
69 Idx nest, reg_errcode_t *err);
70static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
71 re_token_t *token, reg_syntax_t syntax,
72 Idx nest, reg_errcode_t *err);
73static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
74 re_dfa_t *dfa, re_token_t *token,
75 reg_syntax_t syntax, reg_errcode_t *err);
76static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
77 re_token_t *token, reg_syntax_t syntax,
78 reg_errcode_t *err);
79static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
80 re_string_t *regexp,
81 re_token_t *token, int token_len,
82 re_dfa_t *dfa,
83 reg_syntax_t syntax,
84 bool accept_hyphen);
85static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
86 re_string_t *regexp,
87 re_token_t *token);
88#ifdef RE_ENABLE_I18N
89static reg_errcode_t build_equiv_class (bitset_t sbcset,
90 re_charset_t *mbcset,
91 Idx *equiv_class_alloc,
92 const unsigned char *name);
93static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
94 bitset_t sbcset,
95 re_charset_t *mbcset,
96 Idx *char_class_alloc,
97 const unsigned char *class_name,
98 reg_syntax_t syntax);
99#else /* not RE_ENABLE_I18N */
100static reg_errcode_t build_equiv_class (bitset_t sbcset,
101 const unsigned char *name);
102static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
103 bitset_t sbcset,
104 const unsigned char *class_name,
105 reg_syntax_t syntax);
106#endif /* not RE_ENABLE_I18N */
107static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
108 RE_TRANSLATE_TYPE trans,
109 const unsigned char *class_name,
110 const unsigned char *extra,
111 bool non_match, reg_errcode_t *err);
112static bin_tree_t *create_tree (re_dfa_t *dfa,
113 bin_tree_t *left, bin_tree_t *right,
114 re_token_type_t type);
115static bin_tree_t *create_token_tree (re_dfa_t *dfa,
116 bin_tree_t *left, bin_tree_t *right,
117 const re_token_t *token);
118static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
119static void free_token (re_token_t *node);
120static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
121static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
122
123/* This table gives an error message for each of the error codes listed
124 in regex.h. Obviously the order here has to be same as there.
125 POSIX doesn't require that we do anything for REG_NOERROR,
126 but why not be nice? */
127
128static const char __re_error_msgid[] =
129 {
130#define REG_NOERROR_IDX 0
131 gettext_noop ("Success") /* REG_NOERROR */
132 "\0"
133#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
134 gettext_noop ("No match") /* REG_NOMATCH */
135 "\0"
136#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
137 gettext_noop ("Invalid regular expression") /* REG_BADPAT */
138 "\0"
139#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
140 gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
141 "\0"
142#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
143 gettext_noop ("Invalid character class name") /* REG_ECTYPE */
144 "\0"
145#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
146 gettext_noop ("Trailing backslash") /* REG_EESCAPE */
147 "\0"
148#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
149 gettext_noop ("Invalid back reference") /* REG_ESUBREG */
150 "\0"
151#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
152 gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
153 "\0"
154#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
155 gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
156 "\0"
157#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
158 gettext_noop ("Unmatched \\{") /* REG_EBRACE */
159 "\0"
160#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
161 gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
162 "\0"
163#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
164 gettext_noop ("Invalid range end") /* REG_ERANGE */
165 "\0"
166#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
167 gettext_noop ("Memory exhausted") /* REG_ESPACE */
168 "\0"
169#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
170 gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
171 "\0"
172#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
173 gettext_noop ("Premature end of regular expression") /* REG_EEND */
174 "\0"
175#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
176 gettext_noop ("Regular expression too big") /* REG_ESIZE */
177 "\0"
178#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
179 gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
180 };
181
182static const size_t __re_error_msgid_idx[] =
183 {
184 REG_NOERROR_IDX,
185 REG_NOMATCH_IDX,
186 REG_BADPAT_IDX,
187 REG_ECOLLATE_IDX,
188 REG_ECTYPE_IDX,
189 REG_EESCAPE_IDX,
190 REG_ESUBREG_IDX,
191 REG_EBRACK_IDX,
192 REG_EPAREN_IDX,
193 REG_EBRACE_IDX,
194 REG_BADBR_IDX,
195 REG_ERANGE_IDX,
196 REG_ESPACE_IDX,
197 REG_BADRPT_IDX,
198 REG_EEND_IDX,
199 REG_ESIZE_IDX,
200 REG_ERPAREN_IDX
201 };
202
203/* Entry points for GNU code. */
204
205/* re_compile_pattern is the GNU regular expression compiler: it
206 compiles PATTERN (of length LENGTH) and puts the result in BUFP.
207 Returns 0 if the pattern was valid, otherwise an error string.
208
209 Assumes the `allocated' (and perhaps `buffer') and `translate' fields
210 are set in BUFP on entry. */
211
212#ifdef _LIBC
213const char *
214re_compile_pattern (pattern, length, bufp)
215 const char *pattern;
216 size_t length;
217 struct re_pattern_buffer *bufp;
218#else /* size_t might promote */
219const char *
220re_compile_pattern (const char *pattern, size_t length,
221 struct re_pattern_buffer *bufp)
222#endif
223{
224 reg_errcode_t ret;
225
226 /* And GNU code determines whether or not to get register information
227 by passing null for the REGS argument to re_match, etc., not by
228 setting no_sub, unless RE_NO_SUB is set. */
229 bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
230
231 /* Match anchors at newline. */
232 bufp->newline_anchor = 1;
233
234 ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
235
236 if (!ret)
237 return NULL;
238 return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
239}
240#ifdef _LIBC
241weak_alias (__re_compile_pattern, re_compile_pattern)
242#endif
243
244/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
245 also be assigned to arbitrarily: each pattern buffer stores its own
246 syntax, so it can be changed between regex compilations. */
247/* This has no initializer because initialized variables in Emacs
248 become read-only after dumping. */
249reg_syntax_t re_syntax_options;
250
251
252/* Specify the precise syntax of regexps for compilation. This provides
253 for compatibility for various utilities which historically have
254 different, incompatible syntaxes.
255
256 The argument SYNTAX is a bit mask comprised of the various bits
257 defined in regex.h. We return the old syntax. */
258
259reg_syntax_t
260re_set_syntax (syntax)
261 reg_syntax_t syntax;
262{
263 reg_syntax_t ret = re_syntax_options;
264
265 re_syntax_options = syntax;
266 return ret;
267}
268#ifdef _LIBC
269weak_alias (__re_set_syntax, re_set_syntax)
270#endif
271
272int
273re_compile_fastmap (bufp)
274 struct re_pattern_buffer *bufp;
275{
276 re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
277 char *fastmap = bufp->fastmap;
278
279 memset (fastmap, '\0', sizeof (char) * SBC_MAX);
280 re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
281 if (dfa->init_state != dfa->init_state_word)
282 re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
283 if (dfa->init_state != dfa->init_state_nl)
284 re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
285 if (dfa->init_state != dfa->init_state_begbuf)
286 re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
287 bufp->fastmap_accurate = 1;
288 return 0;
289}
290#ifdef _LIBC
291weak_alias (__re_compile_fastmap, re_compile_fastmap)
292#endif
293
294static inline void
295__attribute ((always_inline))
296re_set_fastmap (char *fastmap, bool icase, int ch)
297{
298 fastmap[ch] = 1;
299 if (icase)
300 fastmap[tolower (ch)] = 1;
301}
302
303/* Helper function for re_compile_fastmap.
304 Compile fastmap for the initial_state INIT_STATE. */
305
306static void
307re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
308 char *fastmap)
309{
310 re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
311 Idx node_cnt;
312 bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
313 for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
314 {
315 Idx node = init_state->nodes.elems[node_cnt];
316 re_token_type_t type = dfa->nodes[node].type;
317
318 if (type == CHARACTER)
319 {
320 re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
321#ifdef RE_ENABLE_I18N
322 if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
323 {
324 unsigned char buf[MB_LEN_MAX];
325 unsigned char *p;
326 wchar_t wc;
327 mbstate_t state;
328
329 p = buf;
330 *p++ = dfa->nodes[node].opr.c;
331 while (++node < dfa->nodes_len
332 && dfa->nodes[node].type == CHARACTER
333 && dfa->nodes[node].mb_partial)
334 *p++ = dfa->nodes[node].opr.c;
335 memset (&state, '\0', sizeof (state));
336 if (mbrtowc (&wc, (const char *) buf, p - buf,
337 &state) == p - buf
338 && (__wcrtomb ((char *) buf, towlower (wc), &state)
339 != (size_t) -1))
340 re_set_fastmap (fastmap, false, buf[0]);
341 }
342#endif
343 }
344 else if (type == SIMPLE_BRACKET)
345 {
346 int i, ch;
347 for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
348 {
349 int j;
350 bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
351 for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
352 if (w & ((bitset_word_t) 1 << j))
353 re_set_fastmap (fastmap, icase, ch);
354 }
355 }
356#ifdef RE_ENABLE_I18N
357 else if (type == COMPLEX_BRACKET)
358 {
359 Idx i;
360 re_charset_t *cset = dfa->nodes[node].opr.mbcset;
361 if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
362 || cset->nranges || cset->nchar_classes)
363 {
364# ifdef _LIBC
365 if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
366 {
367 /* In this case we want to catch the bytes which are
368 the first byte of any collation elements.
369 e.g. In da_DK, we want to catch 'a' since "aa"
370 is a valid collation element, and don't catch
371 'b' since 'b' is the only collation element
372 which starts from 'b'. */
373 const int32_t *table = (const int32_t *)
374 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
375 for (i = 0; i < SBC_MAX; ++i)
376 if (table[i] < 0)
377 re_set_fastmap (fastmap, icase, i);
378 }
379# else
380 if (dfa->mb_cur_max > 1)
381 for (i = 0; i < SBC_MAX; ++i)
382 if (__btowc (i) == WEOF)
383 re_set_fastmap (fastmap, icase, i);
384# endif /* not _LIBC */
385 }
386 for (i = 0; i < cset->nmbchars; ++i)
387 {
388 char buf[256];
389 mbstate_t state;
390 memset (&state, '\0', sizeof (state));
391 if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
392 re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
393 if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
394 {
395 if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
396 != (size_t) -1)
397 re_set_fastmap (fastmap, false, *(unsigned char *) buf);
398 }
399 }
400 }
401#endif /* RE_ENABLE_I18N */
402 else if (type == OP_PERIOD
403#ifdef RE_ENABLE_I18N
404 || type == OP_UTF8_PERIOD
405#endif /* RE_ENABLE_I18N */
406 || type == END_OF_RE)
407 {
408 memset (fastmap, '\1', sizeof (char) * SBC_MAX);
409 if (type == END_OF_RE)
410 bufp->can_be_null = 1;
411 return;
412 }
413 }
414}
415
416/* Entry point for POSIX code. */
417/* regcomp takes a regular expression as a string and compiles it.
418
419 PREG is a regex_t *. We do not expect any fields to be initialized,
420 since POSIX says we shouldn't. Thus, we set
421
422 `buffer' to the compiled pattern;
423 `used' to the length of the compiled pattern;
424 `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
425 REG_EXTENDED bit in CFLAGS is set; otherwise, to
426 RE_SYNTAX_POSIX_BASIC;
427 `newline_anchor' to REG_NEWLINE being set in CFLAGS;
428 `fastmap' to an allocated space for the fastmap;
429 `fastmap_accurate' to zero;
430 `re_nsub' to the number of subexpressions in PATTERN.
431
432 PATTERN is the address of the pattern string.
433
434 CFLAGS is a series of bits which affect compilation.
435
436 If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
437 use POSIX basic syntax.
438
439 If REG_NEWLINE is set, then . and [^...] don't match newline.
440 Also, regexec will try a match beginning after every newline.
441
442 If REG_ICASE is set, then we considers upper- and lowercase
443 versions of letters to be equivalent when matching.
444
445 If REG_NOSUB is set, then when PREG is passed to regexec, that
446 routine will report only success or failure, and nothing about the
447 registers.
448
449 It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
450 the return codes and their meanings.) */
451
452int
453regcomp (preg, pattern, cflags)
454 regex_t *__restrict preg;
455 const char *__restrict pattern;
456 int cflags;
457{
458 reg_errcode_t ret;
459 reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
460 : RE_SYNTAX_POSIX_BASIC);
461
462 preg->buffer = NULL;
463 preg->allocated = 0;
464 preg->used = 0;
465
466 /* Try to allocate space for the fastmap. */
467 preg->fastmap = re_malloc (char, SBC_MAX);
468 if (BE (preg->fastmap == NULL, 0))
469 return REG_ESPACE;
470
471 syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
472
473 /* If REG_NEWLINE is set, newlines are treated differently. */
474 if (cflags & REG_NEWLINE)
475 { /* REG_NEWLINE implies neither . nor [^...] match newline. */
476 syntax &= ~RE_DOT_NEWLINE;
477 syntax |= RE_HAT_LISTS_NOT_NEWLINE;
478 /* It also changes the matching behavior. */
479 preg->newline_anchor = 1;
480 }
481 else
482 preg->newline_anchor = 0;
483 preg->no_sub = !!(cflags & REG_NOSUB);
484 preg->translate = NULL;
485
486 ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
487
488 /* POSIX doesn't distinguish between an unmatched open-group and an
489 unmatched close-group: both are REG_EPAREN. */
490 if (ret == REG_ERPAREN)
491 ret = REG_EPAREN;
492
493 /* We have already checked preg->fastmap != NULL. */
494 if (BE (ret == REG_NOERROR, 1))
495 /* Compute the fastmap now, since regexec cannot modify the pattern
496 buffer. This function never fails in this implementation. */
497 (void) re_compile_fastmap (preg);
498 else
499 {
500 /* Some error occurred while compiling the expression. */
501 re_free (preg->fastmap);
502 preg->fastmap = NULL;
503 }
504
505 return (int) ret;
506}
507#ifdef _LIBC
508weak_alias (__regcomp, regcomp)
509#endif
510
511/* Returns a message corresponding to an error code, ERRCODE, returned
512 from either regcomp or regexec. We don't use PREG here. */
513
514#ifdef _LIBC
515size_t
516regerror (errcode, preg, errbuf, errbuf_size)
517 int errcode;
518 const regex_t *__restrict preg;
519 char *__restrict errbuf;
520 size_t errbuf_size;
521#else /* size_t might promote */
522size_t
523regerror (int errcode, const regex_t *__restrict preg,
524 char *__restrict errbuf, size_t errbuf_size)
525#endif
526{
527 const char *msg;
528 size_t msg_size;
529
530 if (BE (errcode < 0
531 || errcode >= (int) (sizeof (__re_error_msgid_idx)
532 / sizeof (__re_error_msgid_idx[0])), 0))
533 /* Only error codes returned by the rest of the code should be passed
534 to this routine. If we are given anything else, or if other regex
535 code generates an invalid error code, then the program has a bug.
536 Dump core so we can fix it. */
537 abort ();
538
539 msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
540
541 msg_size = strlen (msg) + 1; /* Includes the null. */
542
543 if (BE (errbuf_size != 0, 1))
544 {
545 if (BE (msg_size > errbuf_size, 0))
546 {
547#if defined HAVE_MEMPCPY || defined _LIBC
548 *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
549#else
550 memcpy (errbuf, msg, errbuf_size - 1);
551 errbuf[errbuf_size - 1] = 0;
552#endif
553 }
554 else
555 memcpy (errbuf, msg, msg_size);
556 }
557
558 return msg_size;
559}
560#ifdef _LIBC
561weak_alias (__regerror, regerror)
562#endif
563
564
565#ifdef RE_ENABLE_I18N
566/* This static array is used for the map to single-byte characters when
567 UTF-8 is used. Otherwise we would allocate memory just to initialize
568 it the same all the time. UTF-8 is the preferred encoding so this is
569 a worthwhile optimization. */
570static const bitset_t utf8_sb_map =
571{
572 /* Set the first 128 bits. */
573# if 4 * BITSET_WORD_BITS < ASCII_CHARS
574# error "bitset_word_t is narrower than 32 bits"
575# elif 3 * BITSET_WORD_BITS < ASCII_CHARS
576 BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX,
577# elif 2 * BITSET_WORD_BITS < ASCII_CHARS
578 BITSET_WORD_MAX, BITSET_WORD_MAX,
579# elif 1 * BITSET_WORD_BITS < ASCII_CHARS
580 BITSET_WORD_MAX,
581# endif
582 (BITSET_WORD_MAX
583 >> (SBC_MAX % BITSET_WORD_BITS == 0
584 ? 0
585 : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
586};
587#endif
588
589
590static void
591free_dfa_content (re_dfa_t *dfa)
592{
593 Idx i, j;
594
595 if (dfa->nodes)
596 for (i = 0; i < dfa->nodes_len; ++i)
597 free_token (dfa->nodes + i);
598 re_free (dfa->nexts);
599 for (i = 0; i < dfa->nodes_len; ++i)
600 {
601 if (dfa->eclosures != NULL)
602 re_node_set_free (dfa->eclosures + i);
603 if (dfa->inveclosures != NULL)
604 re_node_set_free (dfa->inveclosures + i);
605 if (dfa->edests != NULL)
606 re_node_set_free (dfa->edests + i);
607 }
608 re_free (dfa->edests);
609 re_free (dfa->eclosures);
610 re_free (dfa->inveclosures);
611 re_free (dfa->nodes);
612
613 if (dfa->state_table)
614 for (i = 0; i <= dfa->state_hash_mask; ++i)
615 {
616 struct re_state_table_entry *entry = dfa->state_table + i;
617 for (j = 0; j < entry->num; ++j)
618 {
619 re_dfastate_t *state = entry->array[j];
620 free_state (state);
621 }
622 re_free (entry->array);
623 }
624 re_free (dfa->state_table);
625#ifdef RE_ENABLE_I18N
626 if (dfa->sb_char != utf8_sb_map)
627 re_free (dfa->sb_char);
628#endif
629 re_free (dfa->subexp_map);
630#ifdef DEBUG
631 re_free (dfa->re_str);
632#endif
633
634 re_free (dfa);
635}
636
637
638/* Free dynamically allocated space used by PREG. */
639
640void
641regfree (preg)
642 regex_t *preg;
643{
644 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
645 if (BE (dfa != NULL, 1))
646 free_dfa_content (dfa);
647 preg->buffer = NULL;
648 preg->allocated = 0;
649
650 re_free (preg->fastmap);
651 preg->fastmap = NULL;
652
653 re_free (preg->translate);
654 preg->translate = NULL;
655}
656#ifdef _LIBC
657weak_alias (__regfree, regfree)
658#endif
659
660/* Entry points compatible with 4.2 BSD regex library. We don't define
661 them unless specifically requested. */
662
663#if defined _REGEX_RE_COMP || defined _LIBC
664
665/* BSD has one and only one pattern buffer. */
666static struct re_pattern_buffer re_comp_buf;
667
668char *
669# ifdef _LIBC
670/* Make these definitions weak in libc, so POSIX programs can redefine
671 these names if they don't use our functions, and still use
672 regcomp/regexec above without link errors. */
673weak_function
674# endif
675re_comp (s)
676 const char *s;
677{
678 reg_errcode_t ret;
679 char *fastmap;
680
681 if (!s)
682 {
683 if (!re_comp_buf.buffer)
684 return gettext ("No previous regular expression");
685 return 0;
686 }
687
688 if (re_comp_buf.buffer)
689 {
690 fastmap = re_comp_buf.fastmap;
691 re_comp_buf.fastmap = NULL;
692 __regfree (&re_comp_buf);
693 memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
694 re_comp_buf.fastmap = fastmap;
695 }
696
697 if (re_comp_buf.fastmap == NULL)
698 {
699 re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
700 if (re_comp_buf.fastmap == NULL)
701 return (char *) gettext (__re_error_msgid
702 + __re_error_msgid_idx[(int) REG_ESPACE]);
703 }
704
705 /* Since `re_exec' always passes NULL for the `regs' argument, we
706 don't need to initialize the pattern buffer fields which affect it. */
707
708 /* Match anchors at newlines. */
709 re_comp_buf.newline_anchor = 1;
710
711 ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
712
713 if (!ret)
714 return NULL;
715
716 /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
717 return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
718}
719
720#ifdef _LIBC
721libc_freeres_fn (free_mem)
722{
723 __regfree (&re_comp_buf);
724}
725#endif
726
727#endif /* _REGEX_RE_COMP */
728
729/* Internal entry point.
730 Compile the regular expression PATTERN, whose length is LENGTH.
731 SYNTAX indicate regular expression's syntax. */
732
733static reg_errcode_t
734re_compile_internal (regex_t *preg, const char * pattern, size_t length,
735 reg_syntax_t syntax)
736{
737 reg_errcode_t err = REG_NOERROR;
738 re_dfa_t *dfa;
739 re_string_t regexp;
740
741 /* Initialize the pattern buffer. */
742 preg->fastmap_accurate = 0;
743 preg->syntax = syntax;
744 preg->not_bol = preg->not_eol = 0;
745 preg->used = 0;
746 preg->re_nsub = 0;
747 preg->can_be_null = 0;
748 preg->regs_allocated = REGS_UNALLOCATED;
749
750 /* Initialize the dfa. */
751 dfa = (re_dfa_t *) preg->buffer;
752 if (BE (preg->allocated < sizeof (re_dfa_t), 0))
753 {
754 /* If zero allocated, but buffer is non-null, try to realloc
755 enough space. This loses if buffer's address is bogus, but
756 that is the user's responsibility. If ->buffer is NULL this
757 is a simple allocation. */
758 dfa = re_realloc (preg->buffer, re_dfa_t, 1);
759 if (dfa == NULL)
760 return REG_ESPACE;
761 preg->allocated = sizeof (re_dfa_t);
762 preg->buffer = (unsigned char *) dfa;
763 }
764 preg->used = sizeof (re_dfa_t);
765
766 err = init_dfa (dfa, length);
767 if (BE (err != REG_NOERROR, 0))
768 {
769 free_dfa_content (dfa);
770 preg->buffer = NULL;
771 preg->allocated = 0;
772 return err;
773 }
774#ifdef DEBUG
775 /* Note: length+1 will not overflow since it is checked in init_dfa. */
776 dfa->re_str = re_malloc (char, length + 1);
777 strncpy (dfa->re_str, pattern, length + 1);
778#endif
779
780 __libc_lock_init (dfa->lock);
781
782 err = re_string_construct (&regexp, pattern, length, preg->translate,
783 syntax & RE_ICASE, dfa);
784 if (BE (err != REG_NOERROR, 0))
785 {
786 re_compile_internal_free_return:
787 free_workarea_compile (preg);
788 re_string_destruct (&regexp);
789 free_dfa_content (dfa);
790 preg->buffer = NULL;
791 preg->allocated = 0;
792 return err;
793 }
794
795 /* Parse the regular expression, and build a structure tree. */
796 preg->re_nsub = 0;
797 dfa->str_tree = parse (&regexp, preg, syntax, &err);
798 if (BE (dfa->str_tree == NULL, 0))
799 goto re_compile_internal_free_return;
800
801 /* Analyze the tree and create the nfa. */
802 err = analyze (preg);
803 if (BE (err != REG_NOERROR, 0))
804 goto re_compile_internal_free_return;
805
806#ifdef RE_ENABLE_I18N
807 /* If possible, do searching in single byte encoding to speed things up. */
808 if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
809 optimize_utf8 (dfa);
810#endif
811
812 /* Then create the initial state of the dfa. */
813 err = create_initial_state (dfa);
814
815 /* Release work areas. */
816 free_workarea_compile (preg);
817 re_string_destruct (&regexp);
818
819 if (BE (err != REG_NOERROR, 0))
820 {
821 free_dfa_content (dfa);
822 preg->buffer = NULL;
823 preg->allocated = 0;
824 }
825
826 return err;
827}
828
829/* Initialize DFA. We use the length of the regular expression PAT_LEN
830 as the initial length of some arrays. */
831
832static reg_errcode_t
833init_dfa (re_dfa_t *dfa, size_t pat_len)
834{
835 __re_size_t table_size;
836#ifndef _LIBC
837 char *codeset_name;
838#endif
839#ifdef RE_ENABLE_I18N
840 size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t));
841#else
842 size_t max_i18n_object_size = 0;
843#endif
844 size_t max_object_size =
845 MAX (sizeof (struct re_state_table_entry),
846 MAX (sizeof (re_token_t),
847 MAX (sizeof (re_node_set),
848 MAX (sizeof (regmatch_t),
849 max_i18n_object_size))));
850
851 memset (dfa, '\0', sizeof (re_dfa_t));
852
853 /* Force allocation of str_tree_storage the first time. */
854 dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
855
856 /* Avoid overflows. The extra "/ 2" is for the table_size doubling
857 calculation below, and for similar doubling calculations
858 elsewhere. And it's <= rather than <, because some of the
859 doubling calculations add 1 afterwards. */
860 if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0))
861 return REG_ESPACE;
862
863 dfa->nodes_alloc = pat_len + 1;
864 dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
865
866 /* table_size = 2 ^ ceil(log pat_len) */
867 for (table_size = 1; ; table_size <<= 1)
868 if (table_size > pat_len)
869 break;
870
871 dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
872 dfa->state_hash_mask = table_size - 1;
873
874 dfa->mb_cur_max = MB_CUR_MAX;
875#ifdef _LIBC
876 if (dfa->mb_cur_max == 6
877 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
878 dfa->is_utf8 = 1;
879 dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
880 != 0);
881#else
882# ifdef HAVE_LANGINFO_CODESET
883 codeset_name = nl_langinfo (CODESET);
884# else
885 codeset_name = getenv ("LC_ALL");
886 if (codeset_name == NULL || codeset_name[0] == '\0')
887 codeset_name = getenv ("LC_CTYPE");
888 if (codeset_name == NULL || codeset_name[0] == '\0')
889 codeset_name = getenv ("LANG");
890 if (codeset_name == NULL)
891 codeset_name = "";
892 else if (strchr (codeset_name, '.') != NULL)
893 codeset_name = strchr (codeset_name, '.') + 1;
894# endif
895
896 if (strcasecmp (codeset_name, "UTF-8") == 0
897 || strcasecmp (codeset_name, "UTF8") == 0)
898 dfa->is_utf8 = 1;
899
900 /* We check exhaustively in the loop below if this charset is a
901 superset of ASCII. */
902 dfa->map_notascii = 0;
903#endif
904
905#ifdef RE_ENABLE_I18N
906 if (dfa->mb_cur_max > 1)
907 {
908 if (dfa->is_utf8)
909 dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
910 else
911 {
912 int i, j, ch;
913
914 dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
915 if (BE (dfa->sb_char == NULL, 0))
916 return REG_ESPACE;
917
918 /* Set the bits corresponding to single byte chars. */
919 for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
920 for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
921 {
922 wint_t wch = __btowc (ch);
923 if (wch != WEOF)
924 dfa->sb_char[i] |= (bitset_word_t) 1 << j;
925# ifndef _LIBC
926 if (isascii (ch) && wch != ch)
927 dfa->map_notascii = 1;
928# endif
929 }
930 }
931 }
932#endif
933
934 if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
935 return REG_ESPACE;
936 return REG_NOERROR;
937}
938
939/* Initialize WORD_CHAR table, which indicate which character is
940 "word". In this case "word" means that it is the word construction
941 character used by some operators like "\<", "\>", etc. */
942
943static void
944internal_function
945init_word_char (re_dfa_t *dfa)
946{
947 int i, j, ch;
948 dfa->word_ops_used = 1;
949 for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
950 for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
951 if (isalnum (ch) || ch == '_')
952 dfa->word_char[i] |= (bitset_word_t) 1 << j;
953}
954
955/* Free the work area which are only used while compiling. */
956
957static void
958free_workarea_compile (regex_t *preg)
959{
960 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
961 bin_tree_storage_t *storage, *next;
962 for (storage = dfa->str_tree_storage; storage; storage = next)
963 {
964 next = storage->next;
965 re_free (storage);
966 }
967 dfa->str_tree_storage = NULL;
968 dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
969 dfa->str_tree = NULL;
970 re_free (dfa->org_indices);
971 dfa->org_indices = NULL;
972}
973
974/* Create initial states for all contexts. */
975
976static reg_errcode_t
977create_initial_state (re_dfa_t *dfa)
978{
979 Idx first, i;
980 reg_errcode_t err;
981 re_node_set init_nodes;
982
983 /* Initial states have the epsilon closure of the node which is
984 the first node of the regular expression. */
985 first = dfa->str_tree->first->node_idx;
986 dfa->init_node = first;
987 err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
988 if (BE (err != REG_NOERROR, 0))
989 return err;
990
991 /* The back-references which are in initial states can epsilon transit,
992 since in this case all of the subexpressions can be null.
993 Then we add epsilon closures of the nodes which are the next nodes of
994 the back-references. */
995 if (dfa->nbackref > 0)
996 for (i = 0; i < init_nodes.nelem; ++i)
997 {
998 Idx node_idx = init_nodes.elems[i];
999 re_token_type_t type = dfa->nodes[node_idx].type;
1000
1001 Idx clexp_idx;
1002 if (type != OP_BACK_REF)
1003 continue;
1004 for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
1005 {
1006 re_token_t *clexp_node;
1007 clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
1008 if (clexp_node->type == OP_CLOSE_SUBEXP
1009 && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
1010 break;
1011 }
1012 if (clexp_idx == init_nodes.nelem)
1013 continue;
1014
1015 if (type == OP_BACK_REF)
1016 {
1017 Idx dest_idx = dfa->edests[node_idx].elems[0];
1018 if (!re_node_set_contains (&init_nodes, dest_idx))
1019 {
1020 re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
1021 i = 0;
1022 }
1023 }
1024 }
1025
1026 /* It must be the first time to invoke acquire_state. */
1027 dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
1028 /* We don't check ERR here, since the initial state must not be NULL. */
1029 if (BE (dfa->init_state == NULL, 0))
1030 return err;
1031 if (dfa->init_state->has_constraint)
1032 {
1033 dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
1034 CONTEXT_WORD);
1035 dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
1036 CONTEXT_NEWLINE);
1037 dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
1038 &init_nodes,
1039 CONTEXT_NEWLINE
1040 | CONTEXT_BEGBUF);
1041 if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
1042 || dfa->init_state_begbuf == NULL, 0))
1043 return err;
1044 }
1045 else
1046 dfa->init_state_word = dfa->init_state_nl
1047 = dfa->init_state_begbuf = dfa->init_state;
1048
1049 re_node_set_free (&init_nodes);
1050 return REG_NOERROR;
1051}
1052
1053#ifdef RE_ENABLE_I18N
1054/* If it is possible to do searching in single byte encoding instead of UTF-8
1055 to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
1056 DFA nodes where needed. */
1057
1058static void
1059optimize_utf8 (re_dfa_t *dfa)
1060{
1061 Idx node;
1062 int i;
1063 bool mb_chars = false;
1064 bool has_period = false;
1065
1066 for (node = 0; node < dfa->nodes_len; ++node)
1067 switch (dfa->nodes[node].type)
1068 {
1069 case CHARACTER:
1070 if (dfa->nodes[node].opr.c >= ASCII_CHARS)
1071 mb_chars = true;
1072 break;
1073 case ANCHOR:
1074 switch (dfa->nodes[node].opr.idx)
1075 {
1076 case LINE_FIRST:
1077 case LINE_LAST:
1078 case BUF_FIRST:
1079 case BUF_LAST:
1080 break;
1081 default:
1082 /* Word anchors etc. cannot be handled. */
1083 return;
1084 }
1085 break;
1086 case OP_PERIOD:
1087 has_period = true;
1088 break;
1089 case OP_BACK_REF:
1090 case OP_ALT:
1091 case END_OF_RE:
1092 case OP_DUP_ASTERISK:
1093 case OP_OPEN_SUBEXP:
1094 case OP_CLOSE_SUBEXP:
1095 break;
1096 case COMPLEX_BRACKET:
1097 return;
1098 case SIMPLE_BRACKET:
1099 /* Just double check. */
1100 {
1101 int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0
1102 ? 0
1103 : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS);
1104 for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
1105 {
1106 if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0)
1107 return;
1108 rshift = 0;
1109 }
1110 }
1111 break;
1112 default:
1113 abort ();
1114 }
1115
1116 if (mb_chars || has_period)
1117 for (node = 0; node < dfa->nodes_len; ++node)
1118 {
1119 if (dfa->nodes[node].type == CHARACTER
1120 && dfa->nodes[node].opr.c >= ASCII_CHARS)
1121 dfa->nodes[node].mb_partial = 0;
1122 else if (dfa->nodes[node].type == OP_PERIOD)
1123 dfa->nodes[node].type = OP_UTF8_PERIOD;
1124 }
1125
1126 /* The search can be in single byte locale. */
1127 dfa->mb_cur_max = 1;
1128 dfa->is_utf8 = 0;
1129 dfa->has_mb_node = dfa->nbackref > 0 || has_period;
1130}
1131#endif
1132
1133/* Analyze the structure tree, and calculate "first", "next", "edest",
1134 "eclosure", and "inveclosure". */
1135
1136static reg_errcode_t
1137analyze (regex_t *preg)
1138{
1139 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
1140 reg_errcode_t ret;
1141
1142 /* Allocate arrays. */
1143 dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
1144 dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
1145 dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
1146 dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
1147 if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
1148 || dfa->eclosures == NULL, 0))
1149 return REG_ESPACE;
1150
1151 dfa->subexp_map = re_malloc (Idx, preg->re_nsub);
1152 if (dfa->subexp_map != NULL)
1153 {
1154 Idx i;
1155 for (i = 0; i < preg->re_nsub; i++)
1156 dfa->subexp_map[i] = i;
1157 preorder (dfa->str_tree, optimize_subexps, dfa);
1158 for (i = 0; i < preg->re_nsub; i++)
1159 if (dfa->subexp_map[i] != i)
1160 break;
1161 if (i == preg->re_nsub)
1162 {
1163 free (dfa->subexp_map);
1164 dfa->subexp_map = NULL;
1165 }
1166 }
1167
1168 ret = postorder (dfa->str_tree, lower_subexps, preg);
1169 if (BE (ret != REG_NOERROR, 0))
1170 return ret;
1171 ret = postorder (dfa->str_tree, calc_first, dfa);
1172 if (BE (ret != REG_NOERROR, 0))
1173 return ret;
1174 preorder (dfa->str_tree, calc_next, dfa);
1175 ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
1176 if (BE (ret != REG_NOERROR, 0))
1177 return ret;
1178 ret = calc_eclosure (dfa);
1179 if (BE (ret != REG_NOERROR, 0))
1180 return ret;
1181
1182 /* We only need this during the prune_impossible_nodes pass in regexec.c;
1183 skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */
1184 if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
1185 || dfa->nbackref)
1186 {
1187 dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
1188 if (BE (dfa->inveclosures == NULL, 0))
1189 return REG_ESPACE;
1190 ret = calc_inveclosure (dfa);
1191 }
1192
1193 return ret;
1194}
1195
1196/* Our parse trees are very unbalanced, so we cannot use a stack to
1197 implement parse tree visits. Instead, we use parent pointers and
1198 some hairy code in these two functions. */
1199static reg_errcode_t
1200postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
1201 void *extra)
1202{
1203 bin_tree_t *node, *prev;
1204
1205 for (node = root; ; )
1206 {
1207 /* Descend down the tree, preferably to the left (or to the right
1208 if that's the only child). */
1209 while (node->left || node->right)
1210 if (node->left)
1211 node = node->left;
1212 else
1213 node = node->right;
1214
1215 do
1216 {
1217 reg_errcode_t err = fn (extra, node);
1218 if (BE (err != REG_NOERROR, 0))
1219 return err;
1220 if (node->parent == NULL)
1221 return REG_NOERROR;
1222 prev = node;
1223 node = node->parent;
1224 }
1225 /* Go up while we have a node that is reached from the right. */
1226 while (node->right == prev || node->right == NULL);
1227 node = node->right;
1228 }
1229}
1230
1231static reg_errcode_t
1232preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
1233 void *extra)
1234{
1235 bin_tree_t *node;
1236
1237 for (node = root; ; )
1238 {
1239 reg_errcode_t err = fn (extra, node);
1240 if (BE (err != REG_NOERROR, 0))
1241 return err;
1242
1243 /* Go to the left node, or up and to the right. */
1244 if (node->left)
1245 node = node->left;
1246 else
1247 {
1248 bin_tree_t *prev = NULL;
1249 while (node->right == prev || node->right == NULL)
1250 {
1251 prev = node;
1252 node = node->parent;
1253 if (!node)
1254 return REG_NOERROR;
1255 }
1256 node = node->right;
1257 }
1258 }
1259}
1260
1261/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
1262 re_search_internal to map the inner one's opr.idx to this one's. Adjust
1263 backreferences as well. Requires a preorder visit. */
1264static reg_errcode_t
1265optimize_subexps (void *extra, bin_tree_t *node)
1266{
1267 re_dfa_t *dfa = (re_dfa_t *) extra;
1268
1269 if (node->token.type == OP_BACK_REF && dfa->subexp_map)
1270 {
1271 int idx = node->token.opr.idx;
1272 node->token.opr.idx = dfa->subexp_map[idx];
1273 dfa->used_bkref_map |= 1 << node->token.opr.idx;
1274 }
1275
1276 else if (node->token.type == SUBEXP
1277 && node->left && node->left->token.type == SUBEXP)
1278 {
1279 Idx other_idx = node->left->token.opr.idx;
1280
1281 node->left = node->left->left;
1282 if (node->left)
1283 node->left->parent = node;
1284
1285 dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
1286 if (other_idx < BITSET_WORD_BITS)
1287 dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
1288 }
1289
1290 return REG_NOERROR;
1291}
1292
1293/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
1294 of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */
1295static reg_errcode_t
1296lower_subexps (void *extra, bin_tree_t *node)
1297{
1298 regex_t *preg = (regex_t *) extra;
1299 reg_errcode_t err = REG_NOERROR;
1300
1301 if (node->left && node->left->token.type == SUBEXP)
1302 {
1303 node->left = lower_subexp (&err, preg, node->left);
1304 if (node->left)
1305 node->left->parent = node;
1306 }
1307 if (node->right && node->right->token.type == SUBEXP)
1308 {
1309 node->right = lower_subexp (&err, preg, node->right);
1310 if (node->right)
1311 node->right->parent = node;
1312 }
1313
1314 return err;
1315}
1316
1317static bin_tree_t *
1318lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
1319{
1320 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
1321 bin_tree_t *body = node->left;
1322 bin_tree_t *op, *cls, *tree1, *tree;
1323
1324 if (preg->no_sub
1325 /* We do not optimize empty subexpressions, because otherwise we may
1326 have bad CONCAT nodes with NULL children. This is obviously not
1327 very common, so we do not lose much. An example that triggers
1328 this case is the sed "script" /\(\)/x. */
1329 && node->left != NULL
1330 && (node->token.opr.idx >= BITSET_WORD_BITS
1331 || !(dfa->used_bkref_map
1332 & ((bitset_word_t) 1 << node->token.opr.idx))))
1333 return node->left;
1334
1335 /* Convert the SUBEXP node to the concatenation of an
1336 OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */
1337 op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
1338 cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
1339 tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
1340 tree = create_tree (dfa, op, tree1, CONCAT);
1341 if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
1342 {
1343 *err = REG_ESPACE;
1344 return NULL;
1345 }
1346
1347 op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
1348 op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
1349 return tree;
1350}
1351
1352/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
1353 nodes. Requires a postorder visit. */
1354static reg_errcode_t
1355calc_first (void *extra, bin_tree_t *node)
1356{
1357 re_dfa_t *dfa = (re_dfa_t *) extra;
1358 if (node->token.type == CONCAT)
1359 {
1360 node->first = node->left->first;
1361 node->node_idx = node->left->node_idx;
1362 }
1363 else
1364 {
1365 node->first = node;
1366 node->node_idx = re_dfa_add_node (dfa, node->token);
1367 if (BE (node->node_idx == REG_MISSING, 0))
1368 return REG_ESPACE;
1369 }
1370 return REG_NOERROR;
1371}
1372
1373/* Pass 2: compute NEXT on the tree. Preorder visit. */
1374static reg_errcode_t
1375calc_next (void *extra, bin_tree_t *node)
1376{
1377 switch (node->token.type)
1378 {
1379 case OP_DUP_ASTERISK:
1380 node->left->next = node;
1381 break;
1382 case CONCAT:
1383 node->left->next = node->right->first;
1384 node->right->next = node->next;
1385 break;
1386 default:
1387 if (node->left)
1388 node->left->next = node->next;
1389 if (node->right)
1390 node->right->next = node->next;
1391 break;
1392 }
1393 return REG_NOERROR;
1394}
1395
1396/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */
1397static reg_errcode_t
1398link_nfa_nodes (void *extra, bin_tree_t *node)
1399{
1400 re_dfa_t *dfa = (re_dfa_t *) extra;
1401 Idx idx = node->node_idx;
1402 reg_errcode_t err = REG_NOERROR;
1403
1404 switch (node->token.type)
1405 {
1406 case CONCAT:
1407 break;
1408
1409 case END_OF_RE:
1410 assert (node->next == NULL);
1411 break;
1412
1413 case OP_DUP_ASTERISK:
1414 case OP_ALT:
1415 {
1416 Idx left, right;
1417 dfa->has_plural_match = 1;
1418 if (node->left != NULL)
1419 left = node->left->first->node_idx;
1420 else
1421 left = node->next->node_idx;
1422 if (node->right != NULL)
1423 right = node->right->first->node_idx;
1424 else
1425 right = node->next->node_idx;
1426 assert (REG_VALID_INDEX (left));
1427 assert (REG_VALID_INDEX (right));
1428 err = re_node_set_init_2 (dfa->edests + idx, left, right);
1429 }
1430 break;
1431
1432 case ANCHOR:
1433 case OP_OPEN_SUBEXP:
1434 case OP_CLOSE_SUBEXP:
1435 err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
1436 break;
1437
1438 case OP_BACK_REF:
1439 dfa->nexts[idx] = node->next->node_idx;
1440 if (node->token.type == OP_BACK_REF)
1441 re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
1442 break;
1443
1444 default:
1445 assert (!IS_EPSILON_NODE (node->token.type));
1446 dfa->nexts[idx] = node->next->node_idx;
1447 break;
1448 }
1449
1450 return err;
1451}
1452
1453/* Duplicate the epsilon closure of the node ROOT_NODE.
1454 Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
1455 to their own constraint. */
1456
1457static reg_errcode_t
1458internal_function
1459duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node,
1460 Idx root_node, unsigned int init_constraint)
1461{
1462 Idx org_node, clone_node;
1463 bool ok;
1464 unsigned int constraint = init_constraint;
1465 for (org_node = top_org_node, clone_node = top_clone_node;;)
1466 {
1467 Idx org_dest, clone_dest;
1468 if (dfa->nodes[org_node].type == OP_BACK_REF)
1469 {
1470 /* If the back reference epsilon-transit, its destination must
1471 also have the constraint. Then duplicate the epsilon closure
1472 of the destination of the back reference, and store it in
1473 edests of the back reference. */
1474 org_dest = dfa->nexts[org_node];
1475 re_node_set_empty (dfa->edests + clone_node);
1476 clone_dest = duplicate_node (dfa, org_dest, constraint);
1477 if (BE (clone_dest == REG_MISSING, 0))
1478 return REG_ESPACE;
1479 dfa->nexts[clone_node] = dfa->nexts[org_node];
1480 ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1481 if (BE (! ok, 0))
1482 return REG_ESPACE;
1483 }
1484 else if (dfa->edests[org_node].nelem == 0)
1485 {
1486 /* In case of the node can't epsilon-transit, don't duplicate the
1487 destination and store the original destination as the
1488 destination of the node. */
1489 dfa->nexts[clone_node] = dfa->nexts[org_node];
1490 break;
1491 }
1492 else if (dfa->edests[org_node].nelem == 1)
1493 {
1494 /* In case of the node can epsilon-transit, and it has only one
1495 destination. */
1496 org_dest = dfa->edests[org_node].elems[0];
1497 re_node_set_empty (dfa->edests + clone_node);
1498 if (dfa->nodes[org_node].type == ANCHOR)
1499 {
1500 /* In case of the node has another constraint, append it. */
1501 if (org_node == root_node && clone_node != org_node)
1502 {
1503 /* ...but if the node is root_node itself, it means the
1504 epsilon closure have a loop, then tie it to the
1505 destination of the root_node. */
1506 ok = re_node_set_insert (dfa->edests + clone_node, org_dest);
1507 if (BE (! ok, 0))
1508 return REG_ESPACE;
1509 break;
1510 }
1511 constraint |= dfa->nodes[org_node].opr.ctx_type;
1512 }
1513 clone_dest = duplicate_node (dfa, org_dest, constraint);
1514 if (BE (clone_dest == REG_MISSING, 0))
1515 return REG_ESPACE;
1516 ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1517 if (BE (! ok, 0))
1518 return REG_ESPACE;
1519 }
1520 else /* dfa->edests[org_node].nelem == 2 */
1521 {
1522 /* In case of the node can epsilon-transit, and it has two
1523 destinations. In the bin_tree_t and DFA, that's '|' and '*'. */
1524 org_dest = dfa->edests[org_node].elems[0];
1525 re_node_set_empty (dfa->edests + clone_node);
1526 /* Search for a duplicated node which satisfies the constraint. */
1527 clone_dest = search_duplicated_node (dfa, org_dest, constraint);
1528 if (clone_dest == REG_MISSING)
1529 {
1530 /* There are no such a duplicated node, create a new one. */
1531 reg_errcode_t err;
1532 clone_dest = duplicate_node (dfa, org_dest, constraint);
1533 if (BE (clone_dest == REG_MISSING, 0))
1534 return REG_ESPACE;
1535 ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1536 if (BE (! ok, 0))
1537 return REG_ESPACE;
1538 err = duplicate_node_closure (dfa, org_dest, clone_dest,
1539 root_node, constraint);
1540 if (BE (err != REG_NOERROR, 0))
1541 return err;
1542 }
1543 else
1544 {
1545 /* There are a duplicated node which satisfy the constraint,
1546 use it to avoid infinite loop. */
1547 ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1548 if (BE (! ok, 0))
1549 return REG_ESPACE;
1550 }
1551
1552 org_dest = dfa->edests[org_node].elems[1];
1553 clone_dest = duplicate_node (dfa, org_dest, constraint);
1554 if (BE (clone_dest == REG_MISSING, 0))
1555 return REG_ESPACE;
1556 ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1557 if (BE (! ok, 0))
1558 return REG_ESPACE;
1559 }
1560 org_node = org_dest;
1561 clone_node = clone_dest;
1562 }
1563 return REG_NOERROR;
1564}
1565
1566/* Search for a node which is duplicated from the node ORG_NODE, and
1567 satisfies the constraint CONSTRAINT. */
1568
1569static Idx
1570search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
1571 unsigned int constraint)
1572{
1573 Idx idx;
1574 for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
1575 {
1576 if (org_node == dfa->org_indices[idx]
1577 && constraint == dfa->nodes[idx].constraint)
1578 return idx; /* Found. */
1579 }
1580 return REG_MISSING; /* Not found. */
1581}
1582
1583/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
1584 Return the index of the new node, or REG_MISSING if insufficient storage is
1585 available. */
1586
1587static Idx
1588duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint)
1589{
1590 Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
1591 if (BE (dup_idx != REG_MISSING, 1))
1592 {
1593 dfa->nodes[dup_idx].constraint = constraint;
1594 if (dfa->nodes[org_idx].type == ANCHOR)
1595 dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
1596 dfa->nodes[dup_idx].duplicated = 1;
1597
1598 /* Store the index of the original node. */
1599 dfa->org_indices[dup_idx] = org_idx;
1600 }
1601 return dup_idx;
1602}
1603
1604static reg_errcode_t
1605calc_inveclosure (re_dfa_t *dfa)
1606{
1607 Idx src, idx;
1608 bool ok;
1609 for (idx = 0; idx < dfa->nodes_len; ++idx)
1610 re_node_set_init_empty (dfa->inveclosures + idx);
1611
1612 for (src = 0; src < dfa->nodes_len; ++src)
1613 {
1614 Idx *elems = dfa->eclosures[src].elems;
1615 for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
1616 {
1617 ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
1618 if (BE (! ok, 0))
1619 return REG_ESPACE;
1620 }
1621 }
1622
1623 return REG_NOERROR;
1624}
1625
1626/* Calculate "eclosure" for all the node in DFA. */
1627
1628static reg_errcode_t
1629calc_eclosure (re_dfa_t *dfa)
1630{
1631 Idx node_idx;
1632 bool incomplete;
1633#ifdef DEBUG
1634 assert (dfa->nodes_len > 0);
1635#endif
1636 incomplete = false;
1637 /* For each nodes, calculate epsilon closure. */
1638 for (node_idx = 0; ; ++node_idx)
1639 {
1640 reg_errcode_t err;
1641 re_node_set eclosure_elem;
1642 if (node_idx == dfa->nodes_len)
1643 {
1644 if (!incomplete)
1645 break;
1646 incomplete = false;
1647 node_idx = 0;
1648 }
1649
1650#ifdef DEBUG
1651 assert (dfa->eclosures[node_idx].nelem != REG_MISSING);
1652#endif
1653
1654 /* If we have already calculated, skip it. */
1655 if (dfa->eclosures[node_idx].nelem != 0)
1656 continue;
1657 /* Calculate epsilon closure of `node_idx'. */
1658 err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true);
1659 if (BE (err != REG_NOERROR, 0))
1660 return err;
1661
1662 if (dfa->eclosures[node_idx].nelem == 0)
1663 {
1664 incomplete = true;
1665 re_node_set_free (&eclosure_elem);
1666 }
1667 }
1668 return REG_NOERROR;
1669}
1670
1671/* Calculate epsilon closure of NODE. */
1672
1673static reg_errcode_t
1674calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
1675{
1676 reg_errcode_t err;
1677 unsigned int constraint;
1678 Idx i;
1679 bool incomplete;
1680 bool ok;
1681 re_node_set eclosure;
1682 incomplete = false;
1683 err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
1684 if (BE (err != REG_NOERROR, 0))
1685 return err;
1686
1687 /* This indicates that we are calculating this node now.
1688 We reference this value to avoid infinite loop. */
1689 dfa->eclosures[node].nelem = REG_MISSING;
1690
1691 constraint = ((dfa->nodes[node].type == ANCHOR)
1692 ? dfa->nodes[node].opr.ctx_type : 0);
1693 /* If the current node has constraints, duplicate all nodes.
1694 Since they must inherit the constraints. */
1695 if (constraint
1696 && dfa->edests[node].nelem
1697 && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
1698 {
1699 err = duplicate_node_closure (dfa, node, node, node, constraint);
1700 if (BE (err != REG_NOERROR, 0))
1701 return err;
1702 }
1703
1704 /* Expand each epsilon destination nodes. */
1705 if (IS_EPSILON_NODE(dfa->nodes[node].type))
1706 for (i = 0; i < dfa->edests[node].nelem; ++i)
1707 {
1708 re_node_set eclosure_elem;
1709 Idx edest = dfa->edests[node].elems[i];
1710 /* If calculating the epsilon closure of `edest' is in progress,
1711 return intermediate result. */
1712 if (dfa->eclosures[edest].nelem == REG_MISSING)
1713 {
1714 incomplete = true;
1715 continue;
1716 }
1717 /* If we haven't calculated the epsilon closure of `edest' yet,
1718 calculate now. Otherwise use calculated epsilon closure. */
1719 if (dfa->eclosures[edest].nelem == 0)
1720 {
1721 err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
1722 if (BE (err != REG_NOERROR, 0))
1723 return err;
1724 }
1725 else
1726 eclosure_elem = dfa->eclosures[edest];
1727 /* Merge the epsilon closure of `edest'. */
1728 re_node_set_merge (&eclosure, &eclosure_elem);
1729 /* If the epsilon closure of `edest' is incomplete,
1730 the epsilon closure of this node is also incomplete. */
1731 if (dfa->eclosures[edest].nelem == 0)
1732 {
1733 incomplete = true;
1734 re_node_set_free (&eclosure_elem);
1735 }
1736 }
1737
1738 /* Epsilon closures include itself. */
1739 ok = re_node_set_insert (&eclosure, node);
1740 if (BE (! ok, 0))
1741 return REG_ESPACE;
1742 if (incomplete && !root)
1743 dfa->eclosures[node].nelem = 0;
1744 else
1745 dfa->eclosures[node] = eclosure;
1746 *new_set = eclosure;
1747 return REG_NOERROR;
1748}
1749
1750/* Functions for token which are used in the parser. */
1751
1752/* Fetch a token from INPUT.
1753 We must not use this function inside bracket expressions. */
1754
1755static void
1756internal_function
1757fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
1758{
1759 re_string_skip_bytes (input, peek_token (result, input, syntax));
1760}
1761
1762/* Peek a token from INPUT, and return the length of the token.
1763 We must not use this function inside bracket expressions. */
1764
1765static int
1766internal_function
1767peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
1768{
1769 unsigned char c;
1770
1771 if (re_string_eoi (input))
1772 {
1773 token->type = END_OF_RE;
1774 return 0;
1775 }
1776
1777 c = re_string_peek_byte (input, 0);
1778 token->opr.c = c;
1779
1780 token->word_char = 0;
1781#ifdef RE_ENABLE_I18N
1782 token->mb_partial = 0;
1783 if (input->mb_cur_max > 1 &&
1784 !re_string_first_byte (input, re_string_cur_idx (input)))
1785 {
1786 token->type = CHARACTER;
1787 token->mb_partial = 1;
1788 return 1;
1789 }
1790#endif
1791 if (c == '\\')
1792 {
1793 unsigned char c2;
1794 if (re_string_cur_idx (input) + 1 >= re_string_length (input))
1795 {
1796 token->type = BACK_SLASH;
1797 return 1;
1798 }
1799
1800 c2 = re_string_peek_byte_case (input, 1);
1801 token->opr.c = c2;
1802 token->type = CHARACTER;
1803#ifdef RE_ENABLE_I18N
1804 if (input->mb_cur_max > 1)
1805 {
1806 wint_t wc = re_string_wchar_at (input,
1807 re_string_cur_idx (input) + 1);
1808 token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
1809 }
1810 else
1811#endif
1812 token->word_char = IS_WORD_CHAR (c2) != 0;
1813
1814 switch (c2)
1815 {
1816 case '|':
1817 if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
1818 token->type = OP_ALT;
1819 break;
1820 case '1': case '2': case '3': case '4': case '5':
1821 case '6': case '7': case '8': case '9':
1822 if (!(syntax & RE_NO_BK_REFS))
1823 {
1824 token->type = OP_BACK_REF;
1825 token->opr.idx = c2 - '1';
1826 }
1827 break;
1828 case '<':
1829 if (!(syntax & RE_NO_GNU_OPS))
1830 {
1831 token->type = ANCHOR;
1832 token->opr.ctx_type = WORD_FIRST;
1833 }
1834 break;
1835 case '>':
1836 if (!(syntax & RE_NO_GNU_OPS))
1837 {
1838 token->type = ANCHOR;
1839 token->opr.ctx_type = WORD_LAST;
1840 }
1841 break;
1842 case 'b':
1843 if (!(syntax & RE_NO_GNU_OPS))
1844 {
1845 token->type = ANCHOR;
1846 token->opr.ctx_type = WORD_DELIM;
1847 }
1848 break;
1849 case 'B':
1850 if (!(syntax & RE_NO_GNU_OPS))
1851 {
1852 token->type = ANCHOR;
1853 token->opr.ctx_type = NOT_WORD_DELIM;
1854 }
1855 break;
1856 case 'w':
1857 if (!(syntax & RE_NO_GNU_OPS))
1858 token->type = OP_WORD;
1859 break;
1860 case 'W':
1861 if (!(syntax & RE_NO_GNU_OPS))
1862 token->type = OP_NOTWORD;
1863 break;
1864 case 's':
1865 if (!(syntax & RE_NO_GNU_OPS))
1866 token->type = OP_SPACE;
1867 break;
1868 case 'S':
1869 if (!(syntax & RE_NO_GNU_OPS))
1870 token->type = OP_NOTSPACE;
1871 break;
1872 case '`':
1873 if (!(syntax & RE_NO_GNU_OPS))
1874 {
1875 token->type = ANCHOR;
1876 token->opr.ctx_type = BUF_FIRST;
1877 }
1878 break;
1879 case '\'':
1880 if (!(syntax & RE_NO_GNU_OPS))
1881 {
1882 token->type = ANCHOR;
1883 token->opr.ctx_type = BUF_LAST;
1884 }
1885 break;
1886 case '(':
1887 if (!(syntax & RE_NO_BK_PARENS))
1888 token->type = OP_OPEN_SUBEXP;
1889 break;
1890 case ')':
1891 if (!(syntax & RE_NO_BK_PARENS))
1892 token->type = OP_CLOSE_SUBEXP;
1893 break;
1894 case '+':
1895 if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
1896 token->type = OP_DUP_PLUS;
1897 break;
1898 case '?':
1899 if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
1900 token->type = OP_DUP_QUESTION;
1901 break;
1902 case '{':
1903 if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
1904 token->type = OP_OPEN_DUP_NUM;
1905 break;
1906 case '}':
1907 if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
1908 token->type = OP_CLOSE_DUP_NUM;
1909 break;
1910 default:
1911 break;
1912 }
1913 return 2;
1914 }
1915
1916 token->type = CHARACTER;
1917#ifdef RE_ENABLE_I18N
1918 if (input->mb_cur_max > 1)
1919 {
1920 wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
1921 token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
1922 }
1923 else
1924#endif
1925 token->word_char = IS_WORD_CHAR (token->opr.c);
1926
1927 switch (c)
1928 {
1929 case '\n':
1930 if (syntax & RE_NEWLINE_ALT)
1931 token->type = OP_ALT;
1932 break;
1933 case '|':
1934 if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
1935 token->type = OP_ALT;
1936 break;
1937 case '*':
1938 token->type = OP_DUP_ASTERISK;
1939 break;
1940 case '+':
1941 if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
1942 token->type = OP_DUP_PLUS;
1943 break;
1944 case '?':
1945 if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
1946 token->type = OP_DUP_QUESTION;
1947 break;
1948 case '{':
1949 if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1950 token->type = OP_OPEN_DUP_NUM;
1951 break;
1952 case '}':
1953 if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1954 token->type = OP_CLOSE_DUP_NUM;
1955 break;
1956 case '(':
1957 if (syntax & RE_NO_BK_PARENS)
1958 token->type = OP_OPEN_SUBEXP;
1959 break;
1960 case ')':
1961 if (syntax & RE_NO_BK_PARENS)
1962 token->type = OP_CLOSE_SUBEXP;
1963 break;
1964 case '[':
1965 token->type = OP_OPEN_BRACKET;
1966 break;
1967 case '.':
1968 token->type = OP_PERIOD;
1969 break;
1970 case '^':
1971 if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
1972 re_string_cur_idx (input) != 0)
1973 {
1974 char prev = re_string_peek_byte (input, -1);
1975 if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
1976 break;
1977 }
1978 token->type = ANCHOR;
1979 token->opr.ctx_type = LINE_FIRST;
1980 break;
1981 case '$':
1982 if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
1983 re_string_cur_idx (input) + 1 != re_string_length (input))
1984 {
1985 re_token_t next;
1986 re_string_skip_bytes (input, 1);
1987 peek_token (&next, input, syntax);
1988 re_string_skip_bytes (input, -1);
1989 if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
1990 break;
1991 }
1992 token->type = ANCHOR;
1993 token->opr.ctx_type = LINE_LAST;
1994 break;
1995 default:
1996 break;
1997 }
1998 return 1;
1999}
2000
2001/* Peek a token from INPUT, and return the length of the token.
2002 We must not use this function out of bracket expressions. */
2003
2004static int
2005internal_function
2006peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
2007{
2008 unsigned char c;
2009 if (re_string_eoi (input))
2010 {
2011 token->type = END_OF_RE;
2012 return 0;
2013 }
2014 c = re_string_peek_byte (input, 0);
2015 token->opr.c = c;
2016
2017#ifdef RE_ENABLE_I18N
2018 if (input->mb_cur_max > 1 &&
2019 !re_string_first_byte (input, re_string_cur_idx (input)))
2020 {
2021 token->type = CHARACTER;
2022 return 1;
2023 }
2024#endif /* RE_ENABLE_I18N */
2025
2026 if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
2027 && re_string_cur_idx (input) + 1 < re_string_length (input))
2028 {
2029 /* In this case, '\' escape a character. */
2030 unsigned char c2;
2031 re_string_skip_bytes (input, 1);
2032 c2 = re_string_peek_byte (input, 0);
2033 token->opr.c = c2;
2034 token->type = CHARACTER;
2035 return 1;
2036 }
2037 if (c == '[') /* '[' is a special char in a bracket exps. */
2038 {
2039 unsigned char c2;
2040 int token_len;
2041 if (re_string_cur_idx (input) + 1 < re_string_length (input))
2042 c2 = re_string_peek_byte (input, 1);
2043 else
2044 c2 = 0;
2045 token->opr.c = c2;
2046 token_len = 2;
2047 switch (c2)
2048 {
2049 case '.':
2050 token->type = OP_OPEN_COLL_ELEM;
2051 break;
2052 case '=':
2053 token->type = OP_OPEN_EQUIV_CLASS;
2054 break;
2055 case ':':
2056 if (syntax & RE_CHAR_CLASSES)
2057 {
2058 token->type = OP_OPEN_CHAR_CLASS;
2059 break;
2060 }
2061 /* else fall through. */
2062 default:
2063 token->type = CHARACTER;
2064 token->opr.c = c;
2065 token_len = 1;
2066 break;
2067 }
2068 return token_len;
2069 }
2070 switch (c)
2071 {
2072 case '-':
2073 token->type = OP_CHARSET_RANGE;
2074 break;
2075 case ']':
2076 token->type = OP_CLOSE_BRACKET;
2077 break;
2078 case '^':
2079 token->type = OP_NON_MATCH_LIST;
2080 break;
2081 default:
2082 token->type = CHARACTER;
2083 }
2084 return 1;
2085}
2086
2087/* Functions for parser. */
2088
2089/* Entry point of the parser.
2090 Parse the regular expression REGEXP and return the structure tree.
2091 If an error is occured, ERR is set by error code, and return NULL.
2092 This function build the following tree, from regular expression <reg_exp>:
2093 CAT
2094 / \
2095 / \
2096 <reg_exp> EOR
2097
2098 CAT means concatenation.
2099 EOR means end of regular expression. */
2100
2101static bin_tree_t *
2102parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
2103 reg_errcode_t *err)
2104{
2105 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
2106 bin_tree_t *tree, *eor, *root;
2107 re_token_t current_token;
2108 dfa->syntax = syntax;
2109 fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2110 tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
2111 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2112 return NULL;
2113 eor = create_tree (dfa, NULL, NULL, END_OF_RE);
2114 if (tree != NULL)
2115 root = create_tree (dfa, tree, eor, CONCAT);
2116 else
2117 root = eor;
2118 if (BE (eor == NULL || root == NULL, 0))
2119 {
2120 *err = REG_ESPACE;
2121 return NULL;
2122 }
2123 return root;
2124}
2125
2126/* This function build the following tree, from regular expression
2127 <branch1>|<branch2>:
2128 ALT
2129 / \
2130 / \
2131 <branch1> <branch2>
2132
2133 ALT means alternative, which represents the operator `|'. */
2134
2135static bin_tree_t *
2136parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
2137 reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2138{
2139 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
2140 bin_tree_t *tree, *branch = NULL;
2141 tree = parse_branch (regexp, preg, token, syntax, nest, err);
2142 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2143 return NULL;
2144
2145 while (token->type == OP_ALT)
2146 {
2147 fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2148 if (token->type != OP_ALT && token->type != END_OF_RE
2149 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
2150 {
2151 branch = parse_branch (regexp, preg, token, syntax, nest, err);
2152 if (BE (*err != REG_NOERROR && branch == NULL, 0))
2153 return NULL;
2154 }
2155 else
2156 branch = NULL;
2157 tree = create_tree (dfa, tree, branch, OP_ALT);
2158 if (BE (tree == NULL, 0))
2159 {
2160 *err = REG_ESPACE;
2161 return NULL;
2162 }
2163 }
2164 return tree;
2165}
2166
2167/* This function build the following tree, from regular expression
2168 <exp1><exp2>:
2169 CAT
2170 / \
2171 / \
2172 <exp1> <exp2>
2173
2174 CAT means concatenation. */
2175
2176static bin_tree_t *
2177parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
2178 reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2179{
2180 bin_tree_t *tree, *expr;
2181 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
2182 tree = parse_expression (regexp, preg, token, syntax, nest, err);
2183 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2184 return NULL;
2185
2186 while (token->type != OP_ALT && token->type != END_OF_RE
2187 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
2188 {
2189 expr = parse_expression (regexp, preg, token, syntax, nest, err);
2190 if (BE (*err != REG_NOERROR && expr == NULL, 0))
2191 {
2192 return NULL;
2193 }
2194 if (tree != NULL && expr != NULL)
2195 {
2196 tree = create_tree (dfa, tree, expr, CONCAT);
2197 if (tree == NULL)
2198 {
2199 *err = REG_ESPACE;
2200 return NULL;
2201 }
2202 }
2203 else if (tree == NULL)
2204 tree = expr;
2205 /* Otherwise expr == NULL, we don't need to create new tree. */
2206 }
2207 return tree;
2208}
2209
2210/* This function build the following tree, from regular expression a*:
2211 *
2212 |
2213 a
2214*/
2215
2216static bin_tree_t *
2217parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
2218 reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2219{
2220 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
2221 bin_tree_t *tree;
2222 switch (token->type)
2223 {
2224 case CHARACTER:
2225 tree = create_token_tree (dfa, NULL, NULL, token);
2226 if (BE (tree == NULL, 0))
2227 {
2228 *err = REG_ESPACE;
2229 return NULL;
2230 }
2231#ifdef RE_ENABLE_I18N
2232 if (dfa->mb_cur_max > 1)
2233 {
2234 while (!re_string_eoi (regexp)
2235 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
2236 {
2237 bin_tree_t *mbc_remain;
2238 fetch_token (token, regexp, syntax);
2239 mbc_remain = create_token_tree (dfa, NULL, NULL, token);
2240 tree = create_tree (dfa, tree, mbc_remain, CONCAT);
2241 if (BE (mbc_remain == NULL || tree == NULL, 0))
2242 {
2243 *err = REG_ESPACE;
2244 return NULL;
2245 }
2246 }
2247 }
2248#endif
2249 break;
2250 case OP_OPEN_SUBEXP:
2251 tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
2252 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2253 return NULL;
2254 break;
2255 case OP_OPEN_BRACKET:
2256 tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
2257 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2258 return NULL;
2259 break;
2260 case OP_BACK_REF:
2261 if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
2262 {
2263 *err = REG_ESUBREG;
2264 return NULL;
2265 }
2266 dfa->used_bkref_map |= 1 << token->opr.idx;
2267 tree = create_token_tree (dfa, NULL, NULL, token);
2268 if (BE (tree == NULL, 0))
2269 {
2270 *err = REG_ESPACE;
2271 return NULL;
2272 }
2273 ++dfa->nbackref;
2274 dfa->has_mb_node = 1;
2275 break;
2276 case OP_OPEN_DUP_NUM:
2277 if (syntax & RE_CONTEXT_INVALID_DUP)
2278 {
2279 *err = REG_BADRPT;
2280 return NULL;
2281 }
2282 /* FALLTHROUGH */
2283 case OP_DUP_ASTERISK:
2284 case OP_DUP_PLUS:
2285 case OP_DUP_QUESTION:
2286 if (syntax & RE_CONTEXT_INVALID_OPS)
2287 {
2288 *err = REG_BADRPT;
2289 return NULL;
2290 }
2291 else if (syntax & RE_CONTEXT_INDEP_OPS)
2292 {
2293 fetch_token (token, regexp, syntax);
2294 return parse_expression (regexp, preg, token, syntax, nest, err);
2295 }
2296 /* else fall through */
2297 case OP_CLOSE_SUBEXP:
2298 if ((token->type == OP_CLOSE_SUBEXP) &&
2299 !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
2300 {
2301 *err = REG_ERPAREN;
2302 return NULL;
2303 }
2304 /* else fall through */
2305 case OP_CLOSE_DUP_NUM:
2306 /* We treat it as a normal character. */
2307
2308 /* Then we can these characters as normal characters. */
2309 token->type = CHARACTER;
2310 /* mb_partial and word_char bits should be initialized already
2311 by peek_token. */
2312 tree = create_token_tree (dfa, NULL, NULL, token);
2313 if (BE (tree == NULL, 0))
2314 {
2315 *err = REG_ESPACE;
2316 return NULL;
2317 }
2318 break;
2319 case ANCHOR:
2320 if ((token->opr.ctx_type
2321 & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
2322 && dfa->word_ops_used == 0)
2323 init_word_char (dfa);
2324 if (token->opr.ctx_type == WORD_DELIM
2325 || token->opr.ctx_type == NOT_WORD_DELIM)
2326 {
2327 bin_tree_t *tree_first, *tree_last;
2328 if (token->opr.ctx_type == WORD_DELIM)
2329 {
2330 token->opr.ctx_type = WORD_FIRST;
2331 tree_first = create_token_tree (dfa, NULL, NULL, token);
2332 token->opr.ctx_type = WORD_LAST;
2333 }
2334 else
2335 {
2336 token->opr.ctx_type = INSIDE_WORD;
2337 tree_first = create_token_tree (dfa, NULL, NULL, token);
2338 token->opr.ctx_type = INSIDE_NOTWORD;
2339 }
2340 tree_last = create_token_tree (dfa, NULL, NULL, token);
2341 tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
2342 if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
2343 {
2344 *err = REG_ESPACE;
2345 return NULL;
2346 }
2347 }
2348 else
2349 {
2350 tree = create_token_tree (dfa, NULL, NULL, token);
2351 if (BE (tree == NULL, 0))
2352 {
2353 *err = REG_ESPACE;
2354 return NULL;
2355 }
2356 }
2357 /* We must return here, since ANCHORs can't be followed
2358 by repetition operators.
2359 eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
2360 it must not be "<ANCHOR(^)><REPEAT(*)>". */
2361 fetch_token (token, regexp, syntax);
2362 return tree;
2363 case OP_PERIOD:
2364 tree = create_token_tree (dfa, NULL, NULL, token);
2365 if (BE (tree == NULL, 0))
2366 {
2367 *err = REG_ESPACE;
2368 return NULL;
2369 }
2370 if (dfa->mb_cur_max > 1)
2371 dfa->has_mb_node = 1;
2372 break;
2373 case OP_WORD:
2374 case OP_NOTWORD:
2375 tree = build_charclass_op (dfa, regexp->trans,
2376 (const unsigned char *) "alnum",
2377 (const unsigned char *) "_",
2378 token->type == OP_NOTWORD, err);
2379 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2380 return NULL;
2381 break;
2382 case OP_SPACE:
2383 case OP_NOTSPACE:
2384 tree = build_charclass_op (dfa, regexp->trans,
2385 (const unsigned char *) "space",
2386 (const unsigned char *) "",
2387 token->type == OP_NOTSPACE, err);
2388 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2389 return NULL;
2390 break;
2391 case OP_ALT:
2392 case END_OF_RE:
2393 return NULL;
2394 case BACK_SLASH:
2395 *err = REG_EESCAPE;
2396 return NULL;
2397 default:
2398 /* Must not happen? */
2399#ifdef DEBUG
2400 assert (0);
2401#endif
2402 return NULL;
2403 }
2404 fetch_token (token, regexp, syntax);
2405
2406 while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
2407 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
2408 {
2409 tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
2410 if (BE (*err != REG_NOERROR && tree == NULL, 0))
2411 return NULL;
2412 /* In BRE consecutive duplications are not allowed. */
2413 if ((syntax & RE_CONTEXT_INVALID_DUP)
2414 && (token->type == OP_DUP_ASTERISK
2415 || token->type == OP_OPEN_DUP_NUM))
2416 {
2417 *err = REG_BADRPT;
2418 return NULL;
2419 }
2420 }
2421
2422 return tree;
2423}
2424
2425/* This function build the following tree, from regular expression
2426 (<reg_exp>):
2427 SUBEXP
2428 |
2429 <reg_exp>
2430*/
2431
2432static bin_tree_t *
2433parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
2434 reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2435{
2436 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
2437 bin_tree_t *tree;
2438 size_t cur_nsub;
2439 cur_nsub = preg->re_nsub++;
2440
2441 fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2442
2443 /* The subexpression may be a null string. */
2444 if (token->type == OP_CLOSE_SUBEXP)
2445 tree = NULL;
2446 else
2447 {
2448 tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
2449 if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
2450 *err = REG_EPAREN;
2451 if (BE (*err != REG_NOERROR, 0))
2452 return NULL;
2453 }
2454
2455 if (cur_nsub <= '9' - '1')
2456 dfa->completed_bkref_map |= 1 << cur_nsub;
2457
2458 tree = create_tree (dfa, tree, NULL, SUBEXP);
2459 if (BE (tree == NULL, 0))
2460 {
2461 *err = REG_ESPACE;
2462 return NULL;
2463 }
2464 tree->token.opr.idx = cur_nsub;
2465 return tree;
2466}
2467
2468/* This function parse repetition operators like "*", "+", "{1,3}" etc. */
2469
2470static bin_tree_t *
2471parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
2472 re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
2473{
2474 bin_tree_t *tree = NULL, *old_tree = NULL;
2475 Idx i, start, end, start_idx = re_string_cur_idx (regexp);
2476 re_token_t start_token = *token;
2477
2478 if (token->type == OP_OPEN_DUP_NUM)
2479 {
2480 end = 0;
2481 start = fetch_number (regexp, token, syntax);
2482 if (start == REG_MISSING)
2483 {
2484 if (token->type == CHARACTER && token->opr.c == ',')
2485 start = 0; /* We treat "{,m}" as "{0,m}". */
2486 else
2487 {
2488 *err = REG_BADBR; /* <re>{} is invalid. */
2489 return NULL;
2490 }
2491 }
2492 if (BE (start != REG_ERROR, 1))
2493 {
2494 /* We treat "{n}" as "{n,n}". */
2495 end = ((token->type == OP_CLOSE_DUP_NUM) ? start
2496 : ((token->type == CHARACTER && token->opr.c == ',')
2497 ? fetch_number (regexp, token, syntax) : REG_ERROR));
2498 }
2499 if (BE (start == REG_ERROR || end == REG_ERROR, 0))
2500 {
2501 /* Invalid sequence. */
2502 if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
2503 {
2504 if (token->type == END_OF_RE)
2505 *err = REG_EBRACE;
2506 else
2507 *err = REG_BADBR;
2508
2509 return NULL;
2510 }
2511
2512 /* If the syntax bit is set, rollback. */
2513 re_string_set_index (regexp, start_idx);
2514 *token = start_token;
2515 token->type = CHARACTER;
2516 /* mb_partial and word_char bits should be already initialized by
2517 peek_token. */
2518 return elem;
2519 }
2520
2521 if (BE (end != REG_MISSING && start > end, 0))
2522 {
2523 /* First number greater than second. */
2524 *err = REG_BADBR;
2525 return NULL;
2526 }
2527 }
2528 else
2529 {
2530 start = (token->type == OP_DUP_PLUS) ? 1 : 0;
2531 end = (token->type == OP_DUP_QUESTION) ? 1 : REG_MISSING;
2532 }
2533
2534 fetch_token (token, regexp, syntax);
2535
2536 if (BE (elem == NULL, 0))
2537 return NULL;
2538 if (BE (start == 0 && end == 0, 0))
2539 {
2540 postorder (elem, free_tree, NULL);
2541 return NULL;
2542 }
2543
2544 /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
2545 if (BE (start > 0, 0))
2546 {
2547 tree = elem;
2548 for (i = 2; i <= start; ++i)
2549 {
2550 elem = duplicate_tree (elem, dfa);
2551 tree = create_tree (dfa, tree, elem, CONCAT);
2552 if (BE (elem == NULL || tree == NULL, 0))
2553 goto parse_dup_op_espace;
2554 }
2555
2556 if (start == end)
2557 return tree;
2558
2559 /* Duplicate ELEM before it is marked optional. */
2560 elem = duplicate_tree (elem, dfa);
2561 old_tree = tree;
2562 }
2563 else
2564 old_tree = NULL;
2565
2566 if (elem->token.type == SUBEXP)
2567 postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
2568
2569 tree = create_tree (dfa, elem, NULL,
2570 (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT));
2571 if (BE (tree == NULL, 0))
2572 goto parse_dup_op_espace;
2573
2574 /* This loop is actually executed only when end != REG_MISSING,
2575 to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
2576 already created the start+1-th copy. */
2577 if ((Idx) -1 < 0 || end != REG_MISSING)
2578 for (i = start + 2; i <= end; ++i)
2579 {
2580 elem = duplicate_tree (elem, dfa);
2581 tree = create_tree (dfa, tree, elem, CONCAT);
2582 if (BE (elem == NULL || tree == NULL, 0))
2583 goto parse_dup_op_espace;
2584
2585 tree = create_tree (dfa, tree, NULL, OP_ALT);
2586 if (BE (tree == NULL, 0))
2587 goto parse_dup_op_espace;
2588 }
2589
2590 if (old_tree)
2591 tree = create_tree (dfa, old_tree, tree, CONCAT);
2592
2593 return tree;
2594
2595 parse_dup_op_espace:
2596 *err = REG_ESPACE;
2597 return NULL;
2598}
2599
2600/* Size of the names for collating symbol/equivalence_class/character_class.
2601 I'm not sure, but maybe enough. */
2602#define BRACKET_NAME_BUF_SIZE 32
2603
2604#ifndef _LIBC
2605 /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
2606 Build the range expression which starts from START_ELEM, and ends
2607 at END_ELEM. The result are written to MBCSET and SBCSET.
2608 RANGE_ALLOC is the allocated size of mbcset->range_starts, and
2609 mbcset->range_ends, is a pointer argument sinse we may
2610 update it. */
2611
2612static reg_errcode_t
2613internal_function
2614# ifdef RE_ENABLE_I18N
2615build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc,
2616 bracket_elem_t *start_elem, bracket_elem_t *end_elem)
2617# else /* not RE_ENABLE_I18N */
2618build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
2619 bracket_elem_t *end_elem)
2620# endif /* not RE_ENABLE_I18N */
2621{
2622 unsigned int start_ch, end_ch;
2623 /* Equivalence Classes and Character Classes can't be a range start/end. */
2624 if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
2625 || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
2626 0))
2627 return REG_ERANGE;
2628
2629 /* We can handle no multi character collating elements without libc
2630 support. */
2631 if (BE ((start_elem->type == COLL_SYM
2632 && strlen ((char *) start_elem->opr.name) > 1)
2633 || (end_elem->type == COLL_SYM
2634 && strlen ((char *) end_elem->opr.name) > 1), 0))
2635 return REG_ECOLLATE;
2636
2637# ifdef RE_ENABLE_I18N
2638 {
2639 wchar_t wc;
2640 wint_t start_wc;
2641 wint_t end_wc;
2642 wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
2643
2644 start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
2645 : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
2646 : 0));
2647 end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
2648 : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
2649 : 0));
2650 start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
2651 ? __btowc (start_ch) : start_elem->opr.wch);
2652 end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
2653 ? __btowc (end_ch) : end_elem->opr.wch);
2654 if (start_wc == WEOF || end_wc == WEOF)
2655 return REG_ECOLLATE;
2656 cmp_buf[0] = start_wc;
2657 cmp_buf[4] = end_wc;
2658 if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
2659 return REG_ERANGE;
2660
2661 /* Got valid collation sequence values, add them as a new entry.
2662 However, for !_LIBC we have no collation elements: if the
2663 character set is single byte, the single byte character set
2664 that we build below suffices. parse_bracket_exp passes
2665 no MBCSET if dfa->mb_cur_max == 1. */
2666 if (mbcset)
2667 {
2668 /* Check the space of the arrays. */
2669 if (BE (*range_alloc == mbcset->nranges, 0))
2670 {
2671 /* There is not enough space, need realloc. */
2672 wchar_t *new_array_start, *new_array_end;
2673 Idx new_nranges;
2674
2675 /* +1 in case of mbcset->nranges is 0. */
2676 new_nranges = 2 * mbcset->nranges + 1;
2677 /* Use realloc since mbcset->range_starts and mbcset->range_ends
2678 are NULL if *range_alloc == 0. */
2679 new_array_start = re_realloc (mbcset->range_starts, wchar_t,
2680 new_nranges);
2681 new_array_end = re_realloc (mbcset->range_ends, wchar_t,
2682 new_nranges);
2683
2684 if (BE (new_array_start == NULL || new_array_end == NULL, 0))
2685 return REG_ESPACE;
2686
2687 mbcset->range_starts = new_array_start;
2688 mbcset->range_ends = new_array_end;
2689 *range_alloc = new_nranges;
2690 }
2691
2692 mbcset->range_starts[mbcset->nranges] = start_wc;
2693 mbcset->range_ends[mbcset->nranges++] = end_wc;
2694 }
2695
2696 /* Build the table for single byte characters. */
2697 for (wc = 0; wc < SBC_MAX; ++wc)
2698 {
2699 cmp_buf[2] = wc;
2700 if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
2701 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
2702 bitset_set (sbcset, wc);
2703 }
2704 }
2705# else /* not RE_ENABLE_I18N */
2706 {
2707 unsigned int ch;
2708 start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
2709 : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
2710 : 0));
2711 end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
2712 : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
2713 : 0));
2714 if (start_ch > end_ch)
2715 return REG_ERANGE;
2716 /* Build the table for single byte characters. */
2717 for (ch = 0; ch < SBC_MAX; ++ch)
2718 if (start_ch <= ch && ch <= end_ch)
2719 bitset_set (sbcset, ch);
2720 }
2721# endif /* not RE_ENABLE_I18N */
2722 return REG_NOERROR;
2723}
2724#endif /* not _LIBC */
2725
2726#ifndef _LIBC
2727/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
2728 Build the collating element which is represented by NAME.
2729 The result are written to MBCSET and SBCSET.
2730 COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
2731 pointer argument since we may update it. */
2732
2733static reg_errcode_t
2734internal_function
2735build_collating_symbol (bitset_t sbcset,
2736# ifdef RE_ENABLE_I18N
2737 re_charset_t *mbcset, Idx *coll_sym_alloc,
2738# endif
2739 const unsigned char *name)
2740{
2741 size_t name_len = strlen ((const char *) name);
2742 if (BE (name_len != 1, 0))
2743 return REG_ECOLLATE;
2744 else
2745 {
2746 bitset_set (sbcset, name[0]);
2747 return REG_NOERROR;
2748 }
2749}
2750#endif /* not _LIBC */
2751
2752/* This function parse bracket expression like "[abc]", "[a-c]",
2753 "[[.a-a.]]" etc. */
2754
2755static bin_tree_t *
2756parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
2757 reg_syntax_t syntax, reg_errcode_t *err)
2758{
2759#ifdef _LIBC
2760 const unsigned char *collseqmb;
2761 const char *collseqwc;
2762 uint32_t nrules;
2763 int32_t table_size;
2764 const int32_t *symb_table;
2765 const unsigned char *extra;
2766
2767 /* Local function for parse_bracket_exp used in _LIBC environement.
2768 Seek the collating symbol entry correspondings to NAME.
2769 Return the index of the symbol in the SYMB_TABLE. */
2770
2771 auto inline int32_t
2772 __attribute ((always_inline))
2773 seek_collating_symbol_entry (name, name_len)
2774 const unsigned char *name;
2775 size_t name_len;
2776 {
2777 int32_t hash = elem_hash ((const char *) name, name_len);
2778 int32_t elem = hash % table_size;
2779 if (symb_table[2 * elem] != 0)
2780 {
2781 int32_t second = hash % (table_size - 2) + 1;
2782
2783 do
2784 {
2785 /* First compare the hashing value. */
2786 if (symb_table[2 * elem] == hash
2787 /* Compare the length of the name. */
2788 && name_len == extra[symb_table[2 * elem + 1]]
2789 /* Compare the name. */
2790 && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
2791 name_len) == 0)
2792 {
2793 /* Yep, this is the entry. */
2794 break;
2795 }
2796
2797 /* Next entry. */
2798 elem += second;
2799 }
2800 while (symb_table[2 * elem] != 0);
2801 }
2802 return elem;
2803 }
2804
2805 /* Local function for parse_bracket_exp used in _LIBC environement.
2806 Look up the collation sequence value of BR_ELEM.
2807 Return the value if succeeded, UINT_MAX otherwise. */
2808
2809 auto inline unsigned int
2810 __attribute ((always_inline))
2811 lookup_collation_sequence_value (br_elem)
2812 bracket_elem_t *br_elem;
2813 {
2814 if (br_elem->type == SB_CHAR)
2815 {
2816 /*
2817 if (MB_CUR_MAX == 1)
2818 */
2819 if (nrules == 0)
2820 return collseqmb[br_elem->opr.ch];
2821 else
2822 {
2823 wint_t wc = __btowc (br_elem->opr.ch);
2824 return __collseq_table_lookup (collseqwc, wc);
2825 }
2826 }
2827 else if (br_elem->type == MB_CHAR)
2828 {
2829 return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
2830 }
2831 else if (br_elem->type == COLL_SYM)
2832 {
2833 size_t sym_name_len = strlen ((char *) br_elem->opr.name);
2834 if (nrules != 0)
2835 {
2836 int32_t elem, idx;
2837 elem = seek_collating_symbol_entry (br_elem->opr.name,
2838 sym_name_len);
2839 if (symb_table[2 * elem] != 0)
2840 {
2841 /* We found the entry. */
2842 idx = symb_table[2 * elem + 1];
2843 /* Skip the name of collating element name. */
2844 idx += 1 + extra[idx];
2845 /* Skip the byte sequence of the collating element. */
2846 idx += 1 + extra[idx];
2847 /* Adjust for the alignment. */
2848 idx = (idx + 3) & ~3;
2849 /* Skip the multibyte collation sequence value. */
2850 idx += sizeof (unsigned int);
2851 /* Skip the wide char sequence of the collating element. */
2852 idx += sizeof (unsigned int) *
2853 (1 + *(unsigned int *) (extra + idx));
2854 /* Return the collation sequence value. */
2855 return *(unsigned int *) (extra + idx);
2856 }
2857 else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
2858 {
2859 /* No valid character. Match it as a single byte
2860 character. */
2861 return collseqmb[br_elem->opr.name[0]];
2862 }
2863 }
2864 else if (sym_name_len == 1)
2865 return collseqmb[br_elem->opr.name[0]];
2866 }
2867 return UINT_MAX;
2868 }
2869
2870 /* Local function for parse_bracket_exp used in _LIBC environement.
2871 Build the range expression which starts from START_ELEM, and ends
2872 at END_ELEM. The result are written to MBCSET and SBCSET.
2873 RANGE_ALLOC is the allocated size of mbcset->range_starts, and
2874 mbcset->range_ends, is a pointer argument sinse we may
2875 update it. */
2876
2877 auto inline reg_errcode_t
2878 __attribute ((always_inline))
2879 build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
2880 re_charset_t *mbcset;
2881 Idx *range_alloc;
2882 bitset_t sbcset;
2883 bracket_elem_t *start_elem, *end_elem;
2884 {
2885 unsigned int ch;
2886 uint32_t start_collseq;
2887 uint32_t end_collseq;
2888
2889 /* Equivalence Classes and Character Classes can't be a range
2890 start/end. */
2891 if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
2892 || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
2893 0))
2894 return REG_ERANGE;
2895
2896 start_collseq = lookup_collation_sequence_value (start_elem);
2897 end_collseq = lookup_collation_sequence_value (end_elem);
2898 /* Check start/end collation sequence values. */
2899 if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
2900 return REG_ECOLLATE;
2901 if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
2902 return REG_ERANGE;
2903
2904 /* Got valid collation sequence values, add them as a new entry.
2905 However, if we have no collation elements, and the character set
2906 is single byte, the single byte character set that we
2907 build below suffices. */
2908 if (nrules > 0 || dfa->mb_cur_max > 1)
2909 {
2910 /* Check the space of the arrays. */
2911 if (BE (*range_alloc == mbcset->nranges, 0))
2912 {
2913 /* There is not enough space, need realloc. */
2914 uint32_t *new_array_start;
2915 uint32_t *new_array_end;
2916 Idx new_nranges;
2917
2918 /* +1 in case of mbcset->nranges is 0. */
2919 new_nranges = 2 * mbcset->nranges + 1;
2920 new_array_start = re_realloc (mbcset->range_starts, uint32_t,
2921 new_nranges);
2922 new_array_end = re_realloc (mbcset->range_ends, uint32_t,
2923 new_nranges);
2924
2925 if (BE (new_array_start == NULL || new_array_end == NULL, 0))
2926 return REG_ESPACE;
2927
2928 mbcset->range_starts = new_array_start;
2929 mbcset->range_ends = new_array_end;
2930 *range_alloc = new_nranges;
2931 }
2932
2933 mbcset->range_starts[mbcset->nranges] = start_collseq;
2934 mbcset->range_ends[mbcset->nranges++] = end_collseq;
2935 }
2936
2937 /* Build the table for single byte characters. */
2938 for (ch = 0; ch < SBC_MAX; ch++)
2939 {
2940 uint32_t ch_collseq;
2941 /*
2942 if (MB_CUR_MAX == 1)
2943 */
2944 if (nrules == 0)
2945 ch_collseq = collseqmb[ch];
2946 else
2947 ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
2948 if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
2949 bitset_set (sbcset, ch);
2950 }
2951 return REG_NOERROR;
2952 }
2953
2954 /* Local function for parse_bracket_exp used in _LIBC environement.
2955 Build the collating element which is represented by NAME.
2956 The result are written to MBCSET and SBCSET.
2957 COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
2958 pointer argument sinse we may update it. */
2959
2960 auto inline reg_errcode_t
2961 __attribute ((always_inline))
2962 build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
2963 re_charset_t *mbcset;
2964 Idx *coll_sym_alloc;
2965 bitset_t sbcset;
2966 const unsigned char *name;
2967 {
2968 int32_t elem, idx;
2969 size_t name_len = strlen ((const char *) name);
2970 if (nrules != 0)
2971 {
2972 elem = seek_collating_symbol_entry (name, name_len);
2973 if (symb_table[2 * elem] != 0)
2974 {
2975 /* We found the entry. */
2976 idx = symb_table[2 * elem + 1];
2977 /* Skip the name of collating element name. */
2978 idx += 1 + extra[idx];
2979 }
2980 else if (symb_table[2 * elem] == 0 && name_len == 1)
2981 {
2982 /* No valid character, treat it as a normal
2983 character. */
2984 bitset_set (sbcset, name[0]);
2985 return REG_NOERROR;
2986 }
2987 else
2988 return REG_ECOLLATE;
2989
2990 /* Got valid collation sequence, add it as a new entry. */
2991 /* Check the space of the arrays. */
2992 if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
2993 {
2994 /* Not enough, realloc it. */
2995 /* +1 in case of mbcset->ncoll_syms is 0. */
2996 Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
2997 /* Use realloc since mbcset->coll_syms is NULL
2998 if *alloc == 0. */
2999 int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
3000 new_coll_sym_alloc);
3001 if (BE (new_coll_syms == NULL, 0))
3002 return REG_ESPACE;
3003 mbcset->coll_syms = new_coll_syms;
3004 *coll_sym_alloc = new_coll_sym_alloc;
3005 }
3006 mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
3007 return REG_NOERROR;
3008 }
3009 else
3010 {
3011 if (BE (name_len != 1, 0))
3012 return REG_ECOLLATE;
3013 else
3014 {
3015 bitset_set (sbcset, name[0]);
3016 return REG_NOERROR;
3017 }
3018 }
3019 }
3020#endif
3021
3022 re_token_t br_token;
3023 re_bitset_ptr_t sbcset;
3024#ifdef RE_ENABLE_I18N
3025 re_charset_t *mbcset;
3026 Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
3027 Idx equiv_class_alloc = 0, char_class_alloc = 0;
3028#endif /* not RE_ENABLE_I18N */
3029 bool non_match = false;
3030 bin_tree_t *work_tree;
3031 int token_len;
3032 bool first_round = true;
3033#ifdef _LIBC
3034 collseqmb = (const unsigned char *)
3035 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
3036 nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
3037 if (nrules)
3038 {
3039 /*
3040 if (MB_CUR_MAX > 1)
3041 */
3042 collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
3043 table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
3044 symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
3045 _NL_COLLATE_SYMB_TABLEMB);
3046 extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3047 _NL_COLLATE_SYMB_EXTRAMB);
3048 }
3049#endif
3050 sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3051#ifdef RE_ENABLE_I18N
3052 mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3053#endif /* RE_ENABLE_I18N */
3054#ifdef RE_ENABLE_I18N
3055 if (BE (sbcset == NULL || mbcset == NULL, 0))
3056#else
3057 if (BE (sbcset == NULL, 0))
3058#endif /* RE_ENABLE_I18N */
3059 {
3060 *err = REG_ESPACE;
3061 return NULL;
3062 }
3063
3064 token_len = peek_token_bracket (token, regexp, syntax);
3065 if (BE (token->type == END_OF_RE, 0))
3066 {
3067 *err = REG_BADPAT;
3068 goto parse_bracket_exp_free_return;
3069 }
3070 if (token->type == OP_NON_MATCH_LIST)
3071 {
3072#ifdef RE_ENABLE_I18N
3073 mbcset->non_match = 1;
3074#endif /* not RE_ENABLE_I18N */
3075 non_match = true;
3076 if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
3077 bitset_set (sbcset, '\0');
3078 re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3079 token_len = peek_token_bracket (token, regexp, syntax);
3080 if (BE (token->type == END_OF_RE, 0))
3081 {
3082 *err = REG_BADPAT;
3083 goto parse_bracket_exp_free_return;
3084 }
3085 }
3086
3087 /* We treat the first ']' as a normal character. */
3088 if (token->type == OP_CLOSE_BRACKET)
3089 token->type = CHARACTER;
3090
3091 while (1)
3092 {
3093 bracket_elem_t start_elem, end_elem;
3094 unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
3095 unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
3096 reg_errcode_t ret;
3097 int token_len2 = 0;
3098 bool is_range_exp = false;
3099 re_token_t token2;
3100
3101 start_elem.opr.name = start_name_buf;
3102 ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
3103 syntax, first_round);
3104 if (BE (ret != REG_NOERROR, 0))
3105 {
3106 *err = ret;
3107 goto parse_bracket_exp_free_return;
3108 }
3109 first_round = false;
3110
3111 /* Get information about the next token. We need it in any case. */
3112 token_len = peek_token_bracket (token, regexp, syntax);
3113
3114 /* Do not check for ranges if we know they are not allowed. */
3115 if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
3116 {
3117 if (BE (token->type == END_OF_RE, 0))
3118 {
3119 *err = REG_EBRACK;
3120 goto parse_bracket_exp_free_return;
3121 }
3122 if (token->type == OP_CHARSET_RANGE)
3123 {
3124 re_string_skip_bytes (regexp, token_len); /* Skip '-'. */
3125 token_len2 = peek_token_bracket (&token2, regexp, syntax);
3126 if (BE (token2.type == END_OF_RE, 0))
3127 {
3128 *err = REG_EBRACK;
3129 goto parse_bracket_exp_free_return;
3130 }
3131 if (token2.type == OP_CLOSE_BRACKET)
3132 {
3133 /* We treat the last '-' as a normal character. */
3134 re_string_skip_bytes (regexp, -token_len);
3135 token->type = CHARACTER;
3136 }
3137 else
3138 is_range_exp = true;
3139 }
3140 }
3141
3142 if (is_range_exp == true)
3143 {
3144 end_elem.opr.name = end_name_buf;
3145 ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
3146 dfa, syntax, true);
3147 if (BE (ret != REG_NOERROR, 0))
3148 {
3149 *err = ret;
3150 goto parse_bracket_exp_free_return;
3151 }
3152
3153 token_len = peek_token_bracket (token, regexp, syntax);
3154
3155#ifdef _LIBC
3156 *err = build_range_exp (sbcset, mbcset, &range_alloc,
3157 &start_elem, &end_elem);
3158#else
3159# ifdef RE_ENABLE_I18N
3160 *err = build_range_exp (sbcset,
3161 dfa->mb_cur_max > 1 ? mbcset : NULL,
3162 &range_alloc, &start_elem, &end_elem);
3163# else
3164 *err = build_range_exp (sbcset, &start_elem, &end_elem);
3165# endif
3166#endif /* RE_ENABLE_I18N */
3167 if (BE (*err != REG_NOERROR, 0))
3168 goto parse_bracket_exp_free_return;
3169 }
3170 else
3171 {
3172 switch (start_elem.type)
3173 {
3174 case SB_CHAR:
3175 bitset_set (sbcset, start_elem.opr.ch);
3176 break;
3177#ifdef RE_ENABLE_I18N
3178 case MB_CHAR:
3179 /* Check whether the array has enough space. */
3180 if (BE (mbchar_alloc == mbcset->nmbchars, 0))
3181 {
3182 wchar_t *new_mbchars;
3183 /* Not enough, realloc it. */
3184 /* +1 in case of mbcset->nmbchars is 0. */
3185 mbchar_alloc = 2 * mbcset->nmbchars + 1;
3186 /* Use realloc since array is NULL if *alloc == 0. */
3187 new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
3188 mbchar_alloc);
3189 if (BE (new_mbchars == NULL, 0))
3190 goto parse_bracket_exp_espace;
3191 mbcset->mbchars = new_mbchars;
3192 }
3193 mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
3194 break;
3195#endif /* RE_ENABLE_I18N */
3196 case EQUIV_CLASS:
3197 *err = build_equiv_class (sbcset,
3198#ifdef RE_ENABLE_I18N
3199 mbcset, &equiv_class_alloc,
3200#endif /* RE_ENABLE_I18N */
3201 start_elem.opr.name);
3202 if (BE (*err != REG_NOERROR, 0))
3203 goto parse_bracket_exp_free_return;
3204 break;
3205 case COLL_SYM:
3206 *err = build_collating_symbol (sbcset,
3207#ifdef RE_ENABLE_I18N
3208 mbcset, &coll_sym_alloc,
3209#endif /* RE_ENABLE_I18N */
3210 start_elem.opr.name);
3211 if (BE (*err != REG_NOERROR, 0))
3212 goto parse_bracket_exp_free_return;
3213 break;
3214 case CHAR_CLASS:
3215 *err = build_charclass (regexp->trans, sbcset,
3216#ifdef RE_ENABLE_I18N
3217 mbcset, &char_class_alloc,
3218#endif /* RE_ENABLE_I18N */
3219 start_elem.opr.name, syntax);
3220 if (BE (*err != REG_NOERROR, 0))
3221 goto parse_bracket_exp_free_return;
3222 break;
3223 default:
3224 assert (0);
3225 break;
3226 }
3227 }
3228 if (BE (token->type == END_OF_RE, 0))
3229 {
3230 *err = REG_EBRACK;
3231 goto parse_bracket_exp_free_return;
3232 }
3233 if (token->type == OP_CLOSE_BRACKET)
3234 break;
3235 }
3236
3237 re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3238
3239 /* If it is non-matching list. */
3240 if (non_match)
3241 bitset_not (sbcset);
3242
3243#ifdef RE_ENABLE_I18N
3244 /* Ensure only single byte characters are set. */
3245 if (dfa->mb_cur_max > 1)
3246 bitset_mask (sbcset, dfa->sb_char);
3247
3248 if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
3249 || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
3250 || mbcset->non_match)))
3251 {
3252 bin_tree_t *mbc_tree;
3253 int sbc_idx;
3254 /* Build a tree for complex bracket. */
3255 dfa->has_mb_node = 1;
3256 br_token.type = COMPLEX_BRACKET;
3257 br_token.opr.mbcset = mbcset;
3258 mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3259 if (BE (mbc_tree == NULL, 0))
3260 goto parse_bracket_exp_espace;
3261 for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
3262 if (sbcset[sbc_idx])
3263 break;
3264 /* If there are no bits set in sbcset, there is no point
3265 of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */
3266 if (sbc_idx < BITSET_WORDS)
3267 {
3268 /* Build a tree for simple bracket. */
3269 br_token.type = SIMPLE_BRACKET;
3270 br_token.opr.sbcset = sbcset;
3271 work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3272 if (BE (work_tree == NULL, 0))
3273 goto parse_bracket_exp_espace;
3274
3275 /* Then join them by ALT node. */
3276 work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
3277 if (BE (work_tree == NULL, 0))
3278 goto parse_bracket_exp_espace;
3279 }
3280 else
3281 {
3282 re_free (sbcset);
3283 work_tree = mbc_tree;
3284 }
3285 }
3286 else
3287#endif /* not RE_ENABLE_I18N */
3288 {
3289#ifdef RE_ENABLE_I18N
3290 free_charset (mbcset);
3291#endif
3292 /* Build a tree for simple bracket. */
3293 br_token.type = SIMPLE_BRACKET;
3294 br_token.opr.sbcset = sbcset;
3295 work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3296 if (BE (work_tree == NULL, 0))
3297 goto parse_bracket_exp_espace;
3298 }
3299 return work_tree;
3300
3301 parse_bracket_exp_espace:
3302 *err = REG_ESPACE;
3303 parse_bracket_exp_free_return:
3304 re_free (sbcset);
3305#ifdef RE_ENABLE_I18N
3306 free_charset (mbcset);
3307#endif /* RE_ENABLE_I18N */
3308 return NULL;
3309}
3310
3311/* Parse an element in the bracket expression. */
3312
3313static reg_errcode_t
3314parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
3315 re_token_t *token, int token_len, re_dfa_t *dfa,
3316 reg_syntax_t syntax, bool accept_hyphen)
3317{
3318#ifdef RE_ENABLE_I18N
3319 int cur_char_size;
3320 cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
3321 if (cur_char_size > 1)
3322 {
3323 elem->type = MB_CHAR;
3324 elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
3325 re_string_skip_bytes (regexp, cur_char_size);
3326 return REG_NOERROR;
3327 }
3328#endif /* RE_ENABLE_I18N */
3329 re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3330 if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
3331 || token->type == OP_OPEN_EQUIV_CLASS)
3332 return parse_bracket_symbol (elem, regexp, token);
3333 if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
3334 {
3335 /* A '-' must only appear as anything but a range indicator before
3336 the closing bracket. Everything else is an error. */
3337 re_token_t token2;
3338 (void) peek_token_bracket (&token2, regexp, syntax);
3339 if (token2.type != OP_CLOSE_BRACKET)
3340 /* The actual error value is not standardized since this whole
3341 case is undefined. But ERANGE makes good sense. */
3342 return REG_ERANGE;
3343 }
3344 elem->type = SB_CHAR;
3345 elem->opr.ch = token->opr.c;
3346 return REG_NOERROR;
3347}
3348
3349/* Parse a bracket symbol in the bracket expression. Bracket symbols are
3350 such as [:<character_class>:], [.<collating_element>.], and
3351 [=<equivalent_class>=]. */
3352
3353static reg_errcode_t
3354parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
3355 re_token_t *token)
3356{
3357 unsigned char ch, delim = token->opr.c;
3358 int i = 0;
3359 if (re_string_eoi(regexp))
3360 return REG_EBRACK;
3361 for (;; ++i)
3362 {
3363 if (i >= BRACKET_NAME_BUF_SIZE)
3364 return REG_EBRACK;
3365 if (token->type == OP_OPEN_CHAR_CLASS)
3366 ch = re_string_fetch_byte_case (regexp);
3367 else
3368 ch = re_string_fetch_byte (regexp);
3369 if (re_string_eoi(regexp))
3370 return REG_EBRACK;
3371 if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
3372 break;
3373 elem->opr.name[i] = ch;
3374 }
3375 re_string_skip_bytes (regexp, 1);
3376 elem->opr.name[i] = '\0';
3377 switch (token->type)
3378 {
3379 case OP_OPEN_COLL_ELEM:
3380 elem->type = COLL_SYM;
3381 break;
3382 case OP_OPEN_EQUIV_CLASS:
3383 elem->type = EQUIV_CLASS;
3384 break;
3385 case OP_OPEN_CHAR_CLASS:
3386 elem->type = CHAR_CLASS;
3387 break;
3388 default:
3389 break;
3390 }
3391 return REG_NOERROR;
3392}
3393
3394 /* Helper function for parse_bracket_exp.
3395 Build the equivalence class which is represented by NAME.
3396 The result are written to MBCSET and SBCSET.
3397 EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
3398 is a pointer argument sinse we may update it. */
3399
3400static reg_errcode_t
3401#ifdef RE_ENABLE_I18N
3402build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
3403 Idx *equiv_class_alloc, const unsigned char *name)
3404#else /* not RE_ENABLE_I18N */
3405build_equiv_class (bitset_t sbcset, const unsigned char *name)
3406#endif /* not RE_ENABLE_I18N */
3407{
3408#ifdef _LIBC
3409 uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
3410 if (nrules != 0)
3411 {
3412 const int32_t *table, *indirect;
3413 const unsigned char *weights, *extra, *cp;
3414 unsigned char char_buf[2];
3415 int32_t idx1, idx2;
3416 unsigned int ch;
3417 size_t len;
3418 /* This #include defines a local function! */
3419# include <locale/weight.h>
3420 /* Calculate the index for equivalence class. */
3421 cp = name;
3422 table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
3423 weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3424 _NL_COLLATE_WEIGHTMB);
3425 extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3426 _NL_COLLATE_EXTRAMB);
3427 indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
3428 _NL_COLLATE_INDIRECTMB);
3429 idx1 = findidx (&cp);
3430 if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
3431 /* This isn't a valid character. */
3432 return REG_ECOLLATE;
3433
3434 /* Build single byte matcing table for this equivalence class. */
3435 char_buf[1] = (unsigned char) '\0';
3436 len = weights[idx1];
3437 for (ch = 0; ch < SBC_MAX; ++ch)
3438 {
3439 char_buf[0] = ch;
3440 cp = char_buf;
3441 idx2 = findidx (&cp);
3442/*
3443 idx2 = table[ch];
3444*/
3445 if (idx2 == 0)
3446 /* This isn't a valid character. */
3447 continue;
3448 if (len == weights[idx2])
3449 {
3450 int cnt = 0;
3451 while (cnt <= len &&
3452 weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
3453 ++cnt;
3454
3455 if (cnt > len)
3456 bitset_set (sbcset, ch);
3457 }
3458 }
3459 /* Check whether the array has enough space. */
3460 if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
3461 {
3462 /* Not enough, realloc it. */
3463 /* +1 in case of mbcset->nequiv_classes is 0. */
3464 Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
3465 /* Use realloc since the array is NULL if *alloc == 0. */
3466 int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
3467 int32_t,
3468 new_equiv_class_alloc);
3469 if (BE (new_equiv_classes == NULL, 0))
3470 return REG_ESPACE;
3471 mbcset->equiv_classes = new_equiv_classes;
3472 *equiv_class_alloc = new_equiv_class_alloc;
3473 }
3474 mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
3475 }
3476 else
3477#endif /* _LIBC */
3478 {
3479 if (BE (strlen ((const char *) name) != 1, 0))
3480 return REG_ECOLLATE;
3481 bitset_set (sbcset, *name);
3482 }
3483 return REG_NOERROR;
3484}
3485
3486 /* Helper function for parse_bracket_exp.
3487 Build the character class which is represented by NAME.
3488 The result are written to MBCSET and SBCSET.
3489 CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
3490 is a pointer argument sinse we may update it. */
3491
3492static reg_errcode_t
3493#ifdef RE_ENABLE_I18N
3494build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
3495 re_charset_t *mbcset, Idx *char_class_alloc,
3496 const unsigned char *class_name, reg_syntax_t syntax)
3497#else /* not RE_ENABLE_I18N */
3498build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
3499 const unsigned char *class_name, reg_syntax_t syntax)
3500#endif /* not RE_ENABLE_I18N */
3501{
3502 int i;
3503 const char *name = (const char *) class_name;
3504
3505 /* In case of REG_ICASE "upper" and "lower" match the both of
3506 upper and lower cases. */
3507 if ((syntax & RE_ICASE)
3508 && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
3509 name = "alpha";
3510
3511#ifdef RE_ENABLE_I18N
3512 /* Check the space of the arrays. */
3513 if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
3514 {
3515 /* Not enough, realloc it. */
3516 /* +1 in case of mbcset->nchar_classes is 0. */
3517 Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
3518 /* Use realloc since array is NULL if *alloc == 0. */
3519 wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
3520 new_char_class_alloc);
3521 if (BE (new_char_classes == NULL, 0))
3522 return REG_ESPACE;
3523 mbcset->char_classes = new_char_classes;
3524 *char_class_alloc = new_char_class_alloc;
3525 }
3526 mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
3527#endif /* RE_ENABLE_I18N */
3528
3529#define BUILD_CHARCLASS_LOOP(ctype_func) \
3530 do { \
3531 if (BE (trans != NULL, 0)) \
3532 { \
3533 for (i = 0; i < SBC_MAX; ++i) \
3534 if (ctype_func (i)) \
3535 bitset_set (sbcset, trans[i]); \
3536 } \
3537 else \
3538 { \
3539 for (i = 0; i < SBC_MAX; ++i) \
3540 if (ctype_func (i)) \
3541 bitset_set (sbcset, i); \
3542 } \
3543 } while (0)
3544
3545 if (strcmp (name, "alnum") == 0)
3546 BUILD_CHARCLASS_LOOP (isalnum);
3547 else if (strcmp (name, "cntrl") == 0)
3548 BUILD_CHARCLASS_LOOP (iscntrl);
3549 else if (strcmp (name, "lower") == 0)
3550 BUILD_CHARCLASS_LOOP (islower);
3551 else if (strcmp (name, "space") == 0)
3552 BUILD_CHARCLASS_LOOP (isspace);
3553 else if (strcmp (name, "alpha") == 0)
3554 BUILD_CHARCLASS_LOOP (isalpha);
3555 else if (strcmp (name, "digit") == 0)
3556 BUILD_CHARCLASS_LOOP (isdigit);
3557 else if (strcmp (name, "print") == 0)
3558 BUILD_CHARCLASS_LOOP (isprint);
3559 else if (strcmp (name, "upper") == 0)
3560 BUILD_CHARCLASS_LOOP (isupper);
3561 else if (strcmp (name, "blank") == 0)
3562 BUILD_CHARCLASS_LOOP (isblank);
3563 else if (strcmp (name, "graph") == 0)
3564 BUILD_CHARCLASS_LOOP (isgraph);
3565 else if (strcmp (name, "punct") == 0)
3566 BUILD_CHARCLASS_LOOP (ispunct);
3567 else if (strcmp (name, "xdigit") == 0)
3568 BUILD_CHARCLASS_LOOP (isxdigit);
3569 else
3570 return REG_ECTYPE;
3571
3572 return REG_NOERROR;
3573}
3574
3575static bin_tree_t *
3576build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
3577 const unsigned char *class_name,
3578 const unsigned char *extra, bool non_match,
3579 reg_errcode_t *err)
3580{
3581 re_bitset_ptr_t sbcset;
3582#ifdef RE_ENABLE_I18N
3583 re_charset_t *mbcset;
3584 Idx alloc = 0;
3585#endif /* not RE_ENABLE_I18N */
3586 reg_errcode_t ret;
3587 re_token_t br_token;
3588 bin_tree_t *tree;
3589
3590 sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3591#ifdef RE_ENABLE_I18N
3592 mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3593#endif /* RE_ENABLE_I18N */
3594
3595#ifdef RE_ENABLE_I18N
3596 if (BE (sbcset == NULL || mbcset == NULL, 0))
3597#else /* not RE_ENABLE_I18N */
3598 if (BE (sbcset == NULL, 0))
3599#endif /* not RE_ENABLE_I18N */
3600 {
3601 *err = REG_ESPACE;
3602 return NULL;
3603 }
3604
3605 if (non_match)
3606 {
3607#ifdef RE_ENABLE_I18N
3608 /*
3609 if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
3610 bitset_set(cset->sbcset, '\0');
3611 */
3612 mbcset->non_match = 1;
3613#endif /* not RE_ENABLE_I18N */
3614 }
3615
3616 /* We don't care the syntax in this case. */
3617 ret = build_charclass (trans, sbcset,
3618#ifdef RE_ENABLE_I18N
3619 mbcset, &alloc,
3620#endif /* RE_ENABLE_I18N */
3621 class_name, 0);
3622
3623 if (BE (ret != REG_NOERROR, 0))
3624 {
3625 re_free (sbcset);
3626#ifdef RE_ENABLE_I18N
3627 free_charset (mbcset);
3628#endif /* RE_ENABLE_I18N */
3629 *err = ret;
3630 return NULL;
3631 }
3632 /* \w match '_' also. */
3633 for (; *extra; extra++)
3634 bitset_set (sbcset, *extra);
3635
3636 /* If it is non-matching list. */
3637 if (non_match)
3638 bitset_not (sbcset);
3639
3640#ifdef RE_ENABLE_I18N
3641 /* Ensure only single byte characters are set. */
3642 if (dfa->mb_cur_max > 1)
3643 bitset_mask (sbcset, dfa->sb_char);
3644#endif
3645
3646 /* Build a tree for simple bracket. */
3647 br_token.type = SIMPLE_BRACKET;
3648 br_token.opr.sbcset = sbcset;
3649 tree = create_token_tree (dfa, NULL, NULL, &br_token);
3650 if (BE (tree == NULL, 0))
3651 goto build_word_op_espace;
3652
3653#ifdef RE_ENABLE_I18N
3654 if (dfa->mb_cur_max > 1)
3655 {
3656 bin_tree_t *mbc_tree;
3657 /* Build a tree for complex bracket. */
3658 br_token.type = COMPLEX_BRACKET;
3659 br_token.opr.mbcset = mbcset;
3660 dfa->has_mb_node = 1;
3661 mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3662 if (BE (mbc_tree == NULL, 0))
3663 goto build_word_op_espace;
3664 /* Then join them by ALT node. */
3665 tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
3666 if (BE (mbc_tree != NULL, 1))
3667 return tree;
3668 }
3669 else
3670 {
3671 free_charset (mbcset);
3672 return tree;
3673 }
3674#else /* not RE_ENABLE_I18N */
3675 return tree;
3676#endif /* not RE_ENABLE_I18N */
3677
3678 build_word_op_espace:
3679 re_free (sbcset);
3680#ifdef RE_ENABLE_I18N
3681 free_charset (mbcset);
3682#endif /* RE_ENABLE_I18N */
3683 *err = REG_ESPACE;
3684 return NULL;
3685}
3686
3687/* This is intended for the expressions like "a{1,3}".
3688 Fetch a number from `input', and return the number.
3689 Return REG_MISSING if the number field is empty like "{,1}".
3690 Return REG_ERROR if an error occurred. */
3691
3692static Idx
3693fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
3694{
3695 Idx num = REG_MISSING;
3696 unsigned char c;
3697 while (1)
3698 {
3699 fetch_token (token, input, syntax);
3700 c = token->opr.c;
3701 if (BE (token->type == END_OF_RE, 0))
3702 return REG_ERROR;
3703 if (token->type == OP_CLOSE_DUP_NUM || c == ',')
3704 break;
3705 num = ((token->type != CHARACTER || c < '0' || '9' < c
3706 || num == REG_ERROR)
3707 ? REG_ERROR
3708 : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0'));
3709 num = (num > RE_DUP_MAX) ? REG_ERROR : num;
3710 }
3711 return num;
3712}
3713
3714#ifdef RE_ENABLE_I18N
3715static void
3716free_charset (re_charset_t *cset)
3717{
3718 re_free (cset->mbchars);
3719# ifdef _LIBC
3720 re_free (cset->coll_syms);
3721 re_free (cset->equiv_classes);
3722 re_free (cset->range_starts);
3723 re_free (cset->range_ends);
3724# endif
3725 re_free (cset->char_classes);
3726 re_free (cset);
3727}
3728#endif /* RE_ENABLE_I18N */
3729
3730/* Functions for binary tree operation. */
3731
3732/* Create a tree node. */
3733
3734static bin_tree_t *
3735create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
3736 re_token_type_t type)
3737{
3738 re_token_t t;
3739 t.type = type;
3740 return create_token_tree (dfa, left, right, &t);
3741}
3742
3743static bin_tree_t *
3744create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
3745 const re_token_t *token)
3746{
3747 bin_tree_t *tree;
3748 if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
3749 {
3750 bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
3751
3752 if (storage == NULL)
3753 return NULL;
3754 storage->next = dfa->str_tree_storage;
3755 dfa->str_tree_storage = storage;
3756 dfa->str_tree_storage_idx = 0;
3757 }
3758 tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
3759
3760 tree->parent = NULL;
3761 tree->left = left;
3762 tree->right = right;
3763 tree->token = *token;
3764 tree->token.duplicated = 0;
3765 tree->token.opt_subexp = 0;
3766 tree->first = NULL;
3767 tree->next = NULL;
3768 tree->node_idx = REG_MISSING;
3769
3770 if (left != NULL)
3771 left->parent = tree;
3772 if (right != NULL)
3773 right->parent = tree;
3774 return tree;
3775}
3776
3777/* Mark the tree SRC as an optional subexpression.
3778 To be called from preorder or postorder. */
3779
3780static reg_errcode_t
3781mark_opt_subexp (void *extra, bin_tree_t *node)
3782{
3783 Idx idx = (Idx) (long) extra;
3784 if (node->token.type == SUBEXP && node->token.opr.idx == idx)
3785 node->token.opt_subexp = 1;
3786
3787 return REG_NOERROR;
3788}
3789
3790/* Free the allocated memory inside NODE. */
3791
3792static void
3793free_token (re_token_t *node)
3794{
3795#ifdef RE_ENABLE_I18N
3796 if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
3797 free_charset (node->opr.mbcset);
3798 else
3799#endif /* RE_ENABLE_I18N */
3800 if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
3801 re_free (node->opr.sbcset);
3802}
3803
3804/* Worker function for tree walking. Free the allocated memory inside NODE
3805 and its children. */
3806
3807static reg_errcode_t
3808free_tree (void *extra, bin_tree_t *node)
3809{
3810 free_token (&node->token);
3811 return REG_NOERROR;
3812}
3813
3814
3815/* Duplicate the node SRC, and return new node. This is a preorder
3816 visit similar to the one implemented by the generic visitor, but
3817 we need more infrastructure to maintain two parallel trees --- so,
3818 it's easier to duplicate. */
3819
3820static bin_tree_t *
3821duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
3822{
3823 const bin_tree_t *node;
3824 bin_tree_t *dup_root;
3825 bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
3826
3827 for (node = root; ; )
3828 {
3829 /* Create a new tree and link it back to the current parent. */
3830 *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
3831 if (*p_new == NULL)
3832 return NULL;
3833 (*p_new)->parent = dup_node;
3834 (*p_new)->token.duplicated = 1;
3835 dup_node = *p_new;
3836
3837 /* Go to the left node, or up and to the right. */
3838 if (node->left)
3839 {
3840 node = node->left;
3841 p_new = &dup_node->left;
3842 }
3843 else
3844 {
3845 const bin_tree_t *prev = NULL;
3846 while (node->right == prev || node->right == NULL)
3847 {
3848 prev = node;
3849 node = node->parent;
3850 dup_node = dup_node->parent;
3851 if (!node)
3852 return dup_root;
3853 }
3854 node = node->right;
3855 p_new = &dup_node->right;
3856 }
3857 }
3858}
diff --git a/gl/regex.c b/gl/regex.c
new file mode 100644
index 00000000..d4eb726b
--- /dev/null
+++ b/gl/regex.c
@@ -0,0 +1,71 @@
1/* Extended regular expression matching and search library.
2 Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22/* Make sure noone compiles this code with a C++ compiler. */
23#if defined __cplusplus && defined _LIBC
24# error "This is C code, use a C compiler"
25#endif
26
27#ifdef _LIBC
28/* We have to keep the namespace clean. */
29# define regfree(preg) __regfree (preg)
30# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
31# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
32# define regerror(errcode, preg, errbuf, errbuf_size) \
33 __regerror(errcode, preg, errbuf, errbuf_size)
34# define re_set_registers(bu, re, nu, st, en) \
35 __re_set_registers (bu, re, nu, st, en)
36# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
37 __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
38# define re_match(bufp, string, size, pos, regs) \
39 __re_match (bufp, string, size, pos, regs)
40# define re_search(bufp, string, size, startpos, range, regs) \
41 __re_search (bufp, string, size, startpos, range, regs)
42# define re_compile_pattern(pattern, length, bufp) \
43 __re_compile_pattern (pattern, length, bufp)
44# define re_set_syntax(syntax) __re_set_syntax (syntax)
45# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
46 __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
47# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
48
49# include "../locale/localeinfo.h"
50#endif
51
52/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
53 GNU regex allows. Include it before <regex.h>, which correctly
54 #undefs RE_DUP_MAX and sets it to the right value. */
55#include <limits.h>
56
57#include <regex.h>
58#include "regex_internal.h"
59
60#include "regex_internal.c"
61#include "regcomp.c"
62#include "regexec.c"
63
64/* Binary backward compatibility. */
65#if _LIBC
66# include <shlib-compat.h>
67# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
68link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
69int re_max_failures = 2000;
70# endif
71#endif
diff --git a/gl/regex.h b/gl/regex.h
new file mode 100644
index 00000000..6885ebdf
--- /dev/null
+++ b/gl/regex.h
@@ -0,0 +1,671 @@
1/* Definitions for data structures and routines for the regular
2 expression library.
3 Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006
4 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program 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 General Public License along
18 with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#ifndef _REGEX_H
22#define _REGEX_H 1
23
24#include <sys/types.h>
25
26/* Allow the use in C++ code. */
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/* Define __USE_GNU_REGEX to declare GNU extensions that violate the
32 POSIX name space rules. */
33#undef __USE_GNU_REGEX
34#if (defined _GNU_SOURCE \
35 || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \
36 && !defined _XOPEN_SOURCE))
37# define __USE_GNU_REGEX 1
38#endif
39
40#ifdef _REGEX_LARGE_OFFSETS
41
42/* Use types and values that are wide enough to represent signed and
43 unsigned byte offsets in memory. This currently works only when
44 the regex code is used outside of the GNU C library; it is not yet
45 supported within glibc itself, and glibc users should not define
46 _REGEX_LARGE_OFFSETS. */
47
48/* The type of the offset of a byte within a string.
49 For historical reasons POSIX 1003.1-2004 requires that regoff_t be
50 at least as wide as off_t. However, many common POSIX platforms set
51 regoff_t to the more-sensible ssize_t and the Open Group has
52 signalled its intention to change the requirement to be that
53 regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN
54 60 (2005-08-25). We don't know of any hosts where ssize_t or
55 ptrdiff_t is wider than ssize_t, so ssize_t is safe. */
56typedef ssize_t regoff_t;
57
58/* The type of nonnegative object indexes. Traditionally, GNU regex
59 uses 'int' for these. Code that uses __re_idx_t should work
60 regardless of whether the type is signed. */
61typedef size_t __re_idx_t;
62
63/* The type of object sizes. */
64typedef size_t __re_size_t;
65
66/* The type of object sizes, in places where the traditional code
67 uses unsigned long int. */
68typedef size_t __re_long_size_t;
69
70#else
71
72/* Use types that are binary-compatible with the traditional GNU regex
73 implementation, which mishandles strings longer than INT_MAX. */
74
75typedef int regoff_t;
76typedef int __re_idx_t;
77typedef unsigned int __re_size_t;
78typedef unsigned long int __re_long_size_t;
79
80#endif
81
82/* The following two types have to be signed and unsigned integer type
83 wide enough to hold a value of a pointer. For most ANSI compilers
84 ptrdiff_t and size_t should be likely OK. Still size of these two
85 types is 2 for Microsoft C. Ugh... */
86typedef long int s_reg_t;
87typedef unsigned long int active_reg_t;
88
89/* The following bits are used to determine the regexp syntax we
90 recognize. The set/not-set meanings are chosen so that Emacs syntax
91 remains the value 0. The bits are given in alphabetical order, and
92 the definitions shifted by one from the previous bit; thus, when we
93 add or remove a bit, only one other definition need change. */
94typedef unsigned long int reg_syntax_t;
95
96#ifdef __USE_GNU_REGEX
97
98/* If this bit is not set, then \ inside a bracket expression is literal.
99 If set, then such a \ quotes the following character. */
100# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
101
102/* If this bit is not set, then + and ? are operators, and \+ and \? are
103 literals.
104 If set, then \+ and \? are operators and + and ? are literals. */
105# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
106
107/* If this bit is set, then character classes are supported. They are:
108 [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
109 [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
110 If not set, then character classes are not supported. */
111# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
112
113/* If this bit is set, then ^ and $ are always anchors (outside bracket
114 expressions, of course).
115 If this bit is not set, then it depends:
116 ^ is an anchor if it is at the beginning of a regular
117 expression or after an open-group or an alternation operator;
118 $ is an anchor if it is at the end of a regular expression, or
119 before a close-group or an alternation operator.
120
121 This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
122 POSIX draft 11.2 says that * etc. in leading positions is undefined.
123 We already implemented a previous draft which made those constructs
124 invalid, though, so we haven't changed the code back. */
125# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
126
127/* If this bit is set, then special characters are always special
128 regardless of where they are in the pattern.
129 If this bit is not set, then special characters are special only in
130 some contexts; otherwise they are ordinary. Specifically,
131 * + ? and intervals are only special when not after the beginning,
132 open-group, or alternation operator. */
133# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
134
135/* If this bit is set, then *, +, ?, and { cannot be first in an re or
136 immediately after an alternation or begin-group operator. */
137# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
138
139/* If this bit is set, then . matches newline.
140 If not set, then it doesn't. */
141# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
142
143/* If this bit is set, then . doesn't match NUL.
144 If not set, then it does. */
145# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
146
147/* If this bit is set, nonmatching lists [^...] do not match newline.
148 If not set, they do. */
149# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
150
151/* If this bit is set, either \{...\} or {...} defines an
152 interval, depending on RE_NO_BK_BRACES.
153 If not set, \{, \}, {, and } are literals. */
154# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
155
156/* If this bit is set, +, ? and | aren't recognized as operators.
157 If not set, they are. */
158# define RE_LIMITED_OPS (RE_INTERVALS << 1)
159
160/* If this bit is set, newline is an alternation operator.
161 If not set, newline is literal. */
162# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
163
164/* If this bit is set, then `{...}' defines an interval, and \{ and \}
165 are literals.
166 If not set, then `\{...\}' defines an interval. */
167# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
168
169/* If this bit is set, (...) defines a group, and \( and \) are literals.
170 If not set, \(...\) defines a group, and ( and ) are literals. */
171# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
172
173/* If this bit is set, then \<digit> matches <digit>.
174 If not set, then \<digit> is a back-reference. */
175# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
176
177/* If this bit is set, then | is an alternation operator, and \| is literal.
178 If not set, then \| is an alternation operator, and | is literal. */
179# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
180
181/* If this bit is set, then an ending range point collating higher
182 than the starting range point, as in [z-a], is invalid.
183 If not set, then when ending range point collates higher than the
184 starting range point, the range is ignored. */
185# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
186
187/* If this bit is set, then an unmatched ) is ordinary.
188 If not set, then an unmatched ) is invalid. */
189# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
190
191/* If this bit is set, succeed as soon as we match the whole pattern,
192 without further backtracking. */
193# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
194
195/* If this bit is set, do not process the GNU regex operators.
196 If not set, then the GNU regex operators are recognized. */
197# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
198
199/* If this bit is set, turn on internal regex debugging.
200 If not set, and debugging was on, turn it off.
201 This only works if regex.c is compiled -DDEBUG.
202 We define this bit always, so that all that's needed to turn on
203 debugging is to recompile regex.c; the calling code can always have
204 this bit set, and it won't affect anything in the normal case. */
205# define RE_DEBUG (RE_NO_GNU_OPS << 1)
206
207/* If this bit is set, a syntactically invalid interval is treated as
208 a string of ordinary characters. For example, the ERE 'a{1' is
209 treated as 'a\{1'. */
210# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
211
212/* If this bit is set, then ignore case when matching.
213 If not set, then case is significant. */
214# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
215
216/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
217 for ^, because it is difficult to scan the regex backwards to find
218 whether ^ should be special. */
219# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
220
221/* If this bit is set, then \{ cannot be first in an bre or
222 immediately after an alternation or begin-group operator. */
223# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
224
225/* If this bit is set, then no_sub will be set to 1 during
226 re_compile_pattern. */
227# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
228
229#endif /* defined __USE_GNU_REGEX */
230
231/* This global variable defines the particular regexp syntax to use (for
232 some interfaces). When a regexp is compiled, the syntax used is
233 stored in the pattern buffer, so changing this does not affect
234 already-compiled regexps. */
235extern reg_syntax_t re_syntax_options;
236
237#ifdef __USE_GNU_REGEX
238/* Define combinations of the above bits for the standard possibilities.
239 (The [[[ comments delimit what gets put into the Texinfo file, so
240 don't delete them!) */
241/* [[[begin syntaxes]]] */
242# define RE_SYNTAX_EMACS 0
243
244# define RE_SYNTAX_AWK \
245 (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
246 | RE_NO_BK_PARENS | RE_NO_BK_REFS \
247 | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
248 | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
249 | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
250
251# define RE_SYNTAX_GNU_AWK \
252 ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
253 & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
254 | RE_CONTEXT_INVALID_OPS ))
255
256# define RE_SYNTAX_POSIX_AWK \
257 (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
258 | RE_INTERVALS | RE_NO_GNU_OPS)
259
260# define RE_SYNTAX_GREP \
261 (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
262 | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
263 | RE_NEWLINE_ALT)
264
265# define RE_SYNTAX_EGREP \
266 (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
267 | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
268 | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
269 | RE_NO_BK_VBAR)
270
271# define RE_SYNTAX_POSIX_EGREP \
272 (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
273 | RE_INVALID_INTERVAL_ORD)
274
275/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
276# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
277
278# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
279
280/* Syntax bits common to both basic and extended POSIX regex syntax. */
281# define _RE_SYNTAX_POSIX_COMMON \
282 (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
283 | RE_INTERVALS | RE_NO_EMPTY_RANGES)
284
285# define RE_SYNTAX_POSIX_BASIC \
286 (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
287
288/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
289 RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
290 isn't minimal, since other operators, such as \`, aren't disabled. */
291# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
292 (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
293
294# define RE_SYNTAX_POSIX_EXTENDED \
295 (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
296 | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
297 | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
298 | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
299
300/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
301 removed and RE_NO_BK_REFS is added. */
302# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
303 (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
304 | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
305 | RE_NO_BK_PARENS | RE_NO_BK_REFS \
306 | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
307/* [[[end syntaxes]]] */
308
309#endif /* defined __USE_GNU_REGEX */
310
311#ifdef __USE_GNU_REGEX
312
313/* Maximum number of duplicates an interval can allow. POSIX-conforming
314 systems might define this in <limits.h>, but we want our
315 value, so remove any previous define. */
316# ifdef RE_DUP_MAX
317# undef RE_DUP_MAX
318# endif
319
320/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
321 the counter as a 2-byte signed integer. This is no longer true, so
322 RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
323 ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined.
324 However, there would be a huge performance problem if someone
325 actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
326 its historical value. */
327# define RE_DUP_MAX (0x7fff)
328
329#endif /* defined __USE_GNU_REGEX */
330
331
332/* POSIX `cflags' bits (i.e., information for `regcomp'). */
333
334/* If this bit is set, then use extended regular expression syntax.
335 If not set, then use basic regular expression syntax. */
336#define REG_EXTENDED 1
337
338/* If this bit is set, then ignore case when matching.
339 If not set, then case is significant. */
340#define REG_ICASE (1 << 1)
341
342/* If this bit is set, then anchors do not match at newline
343 characters in the string.
344 If not set, then anchors do match at newlines. */
345#define REG_NEWLINE (1 << 2)
346
347/* If this bit is set, then report only success or fail in regexec.
348 If not set, then returns differ between not matching and errors. */
349#define REG_NOSUB (1 << 3)
350
351
352/* POSIX `eflags' bits (i.e., information for regexec). */
353
354/* If this bit is set, then the beginning-of-line operator doesn't match
355 the beginning of the string (presumably because it's not the
356 beginning of a line).
357 If not set, then the beginning-of-line operator does match the
358 beginning of the string. */
359#define REG_NOTBOL 1
360
361/* Like REG_NOTBOL, except for the end-of-line. */
362#define REG_NOTEOL (1 << 1)
363
364/* Use PMATCH[0] to delimit the start and end of the search in the
365 buffer. */
366#define REG_STARTEND (1 << 2)
367
368
369/* If any error codes are removed, changed, or added, update the
370 `__re_error_msgid' table in regcomp.c. */
371
372typedef enum
373{
374 _REG_ENOSYS = -1, /* This will never happen for this implementation. */
375 _REG_NOERROR = 0, /* Success. */
376 _REG_NOMATCH, /* Didn't find a match (for regexec). */
377
378 /* POSIX regcomp return error codes. (In the order listed in the
379 standard.) */
380 _REG_BADPAT, /* Invalid pattern. */
381 _REG_ECOLLATE, /* Invalid collating element. */
382 _REG_ECTYPE, /* Invalid character class name. */
383 _REG_EESCAPE, /* Trailing backslash. */
384 _REG_ESUBREG, /* Invalid back reference. */
385 _REG_EBRACK, /* Unmatched left bracket. */
386 _REG_EPAREN, /* Parenthesis imbalance. */
387 _REG_EBRACE, /* Unmatched \{. */
388 _REG_BADBR, /* Invalid contents of \{\}. */
389 _REG_ERANGE, /* Invalid range end. */
390 _REG_ESPACE, /* Ran out of memory. */
391 _REG_BADRPT, /* No preceding re for repetition op. */
392
393 /* Error codes we've added. */
394 _REG_EEND, /* Premature end. */
395 _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
396 _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
397} reg_errcode_t;
398
399#ifdef _XOPEN_SOURCE
400# define REG_ENOSYS _REG_ENOSYS
401#endif
402#define REG_NOERROR _REG_NOERROR
403#define REG_NOMATCH _REG_NOMATCH
404#define REG_BADPAT _REG_BADPAT
405#define REG_ECOLLATE _REG_ECOLLATE
406#define REG_ECTYPE _REG_ECTYPE
407#define REG_EESCAPE _REG_EESCAPE
408#define REG_ESUBREG _REG_ESUBREG
409#define REG_EBRACK _REG_EBRACK
410#define REG_EPAREN _REG_EPAREN
411#define REG_EBRACE _REG_EBRACE
412#define REG_BADBR _REG_BADBR
413#define REG_ERANGE _REG_ERANGE
414#define REG_ESPACE _REG_ESPACE
415#define REG_BADRPT _REG_BADRPT
416#define REG_EEND _REG_EEND
417#define REG_ESIZE _REG_ESIZE
418#define REG_ERPAREN _REG_ERPAREN
419
420/* struct re_pattern_buffer normally uses member names like `buffer'
421 that POSIX does not allow. In POSIX mode these members have names
422 with leading `re_' (e.g., `re_buffer'). */
423#ifdef __USE_GNU_REGEX
424# define _REG_RE_NAME(id) id
425# define _REG_RM_NAME(id) id
426#else
427# define _REG_RE_NAME(id) re_##id
428# define _REG_RM_NAME(id) rm_##id
429#endif
430
431/* The user can specify the type of the re_translate member by
432 defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned
433 char *. This pollutes the POSIX name space, so in POSIX mode just
434 use unsigned char *. */
435#ifdef __USE_GNU_REGEX
436# ifndef RE_TRANSLATE_TYPE
437# define RE_TRANSLATE_TYPE unsigned char *
438# endif
439# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE
440#else
441# define REG_TRANSLATE_TYPE unsigned char *
442#endif
443
444/* This data structure represents a compiled pattern. Before calling
445 the pattern compiler, the fields `buffer', `allocated', `fastmap',
446 `translate', and `no_sub' can be set. After the pattern has been
447 compiled, the `re_nsub' field is available. All other fields are
448 private to the regex routines. */
449
450struct re_pattern_buffer
451{
452 /* Space that holds the compiled pattern. It is declared as
453 `unsigned char *' because its elements are sometimes used as
454 array indexes. */
455 unsigned char *_REG_RE_NAME (buffer);
456
457 /* Number of bytes to which `buffer' points. */
458 __re_long_size_t _REG_RE_NAME (allocated);
459
460 /* Number of bytes actually used in `buffer'. */
461 __re_long_size_t _REG_RE_NAME (used);
462
463 /* Syntax setting with which the pattern was compiled. */
464 reg_syntax_t _REG_RE_NAME (syntax);
465
466 /* Pointer to a fastmap, if any, otherwise zero. re_search uses the
467 fastmap, if there is one, to skip over impossible starting points
468 for matches. */
469 char *_REG_RE_NAME (fastmap);
470
471 /* Either a translate table to apply to all characters before
472 comparing them, or zero for no translation. The translation is
473 applied to a pattern when it is compiled and to a string when it
474 is matched. */
475 REG_TRANSLATE_TYPE _REG_RE_NAME (translate);
476
477 /* Number of subexpressions found by the compiler. */
478 size_t re_nsub;
479
480 /* Zero if this pattern cannot match the empty string, one else.
481 Well, in truth it's used only in `re_search_2', to see whether or
482 not we should use the fastmap, so we don't set this absolutely
483 perfectly; see `re_compile_fastmap' (the `duplicate' case). */
484 unsigned int _REG_RE_NAME (can_be_null) : 1;
485
486 /* If REGS_UNALLOCATED, allocate space in the `regs' structure
487 for `max (RE_NREGS, re_nsub + 1)' groups.
488 If REGS_REALLOCATE, reallocate space if necessary.
489 If REGS_FIXED, use what's there. */
490#ifdef __USE_GNU_REGEX
491# define REGS_UNALLOCATED 0
492# define REGS_REALLOCATE 1
493# define REGS_FIXED 2
494#endif
495 unsigned int _REG_RE_NAME (regs_allocated) : 2;
496
497 /* Set to zero when `regex_compile' compiles a pattern; set to one
498 by `re_compile_fastmap' if it updates the fastmap. */
499 unsigned int _REG_RE_NAME (fastmap_accurate) : 1;
500
501 /* If set, `re_match_2' does not return information about
502 subexpressions. */
503 unsigned int _REG_RE_NAME (no_sub) : 1;
504
505 /* If set, a beginning-of-line anchor doesn't match at the beginning
506 of the string. */
507 unsigned int _REG_RE_NAME (not_bol) : 1;
508
509 /* Similarly for an end-of-line anchor. */
510 unsigned int _REG_RE_NAME (not_eol) : 1;
511
512 /* If true, an anchor at a newline matches. */
513 unsigned int _REG_RE_NAME (newline_anchor) : 1;
514
515/* [[[end pattern_buffer]]] */
516};
517
518typedef struct re_pattern_buffer regex_t;
519
520/* This is the structure we store register match data in. See
521 regex.texinfo for a full description of what registers match. */
522struct re_registers
523{
524 __re_size_t _REG_RM_NAME (num_regs);
525 regoff_t *_REG_RM_NAME (start);
526 regoff_t *_REG_RM_NAME (end);
527};
528
529
530/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
531 `re_match_2' returns information about at least this many registers
532 the first time a `regs' structure is passed. */
533#if !defined RE_NREGS && defined __USE_GNU_REGEX
534# define RE_NREGS 30
535#endif
536
537
538/* POSIX specification for registers. Aside from the different names than
539 `re_registers', POSIX uses an array of structures, instead of a
540 structure of arrays. */
541typedef struct
542{
543 regoff_t rm_so; /* Byte offset from string's start to substring's start. */
544 regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
545} regmatch_t;
546
547/* Declarations for routines. */
548
549/* Sets the current default syntax to SYNTAX, and return the old syntax.
550 You can also simply assign to the `re_syntax_options' variable. */
551extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
552
553/* Compile the regular expression PATTERN, with length LENGTH
554 and syntax given by the global `re_syntax_options', into the buffer
555 BUFFER. Return NULL if successful, and an error string if not. */
556extern const char *re_compile_pattern (const char *__pattern, size_t __length,
557 struct re_pattern_buffer *__buffer);
558
559
560/* Compile a fastmap for the compiled pattern in BUFFER; used to
561 accelerate searches. Return 0 if successful and -2 if was an
562 internal error. */
563extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
564
565
566/* Search in the string STRING (with length LENGTH) for the pattern
567 compiled into BUFFER. Start searching at position START, for RANGE
568 characters. Return the starting position of the match, -1 for no
569 match, or -2 for an internal error. Also return register
570 information in REGS (if REGS and BUFFER->no_sub are nonzero). */
571extern regoff_t re_search (struct re_pattern_buffer *__buffer,
572 const char *__string, __re_idx_t __length,
573 __re_idx_t __start, regoff_t __range,
574 struct re_registers *__regs);
575
576
577/* Like `re_search', but search in the concatenation of STRING1 and
578 STRING2. Also, stop searching at index START + STOP. */
579extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
580 const char *__string1, __re_idx_t __length1,
581 const char *__string2, __re_idx_t __length2,
582 __re_idx_t __start, regoff_t __range,
583 struct re_registers *__regs,
584 __re_idx_t __stop);
585
586
587/* Like `re_search', but return how many characters in STRING the regexp
588 in BUFFER matched, starting at position START. */
589extern regoff_t re_match (struct re_pattern_buffer *__buffer,
590 const char *__string, __re_idx_t __length,
591 __re_idx_t __start, struct re_registers *__regs);
592
593
594/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
595extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
596 const char *__string1, __re_idx_t __length1,
597 const char *__string2, __re_idx_t __length2,
598 __re_idx_t __start, struct re_registers *__regs,
599 __re_idx_t __stop);
600
601
602/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
603 ENDS. Subsequent matches using BUFFER and REGS will use this memory
604 for recording register information. STARTS and ENDS must be
605 allocated with malloc, and must each be at least `NUM_REGS * sizeof
606 (regoff_t)' bytes long.
607
608 If NUM_REGS == 0, then subsequent matches should allocate their own
609 register data.
610
611 Unless this function is called, the first search or match using
612 PATTERN_BUFFER will allocate its own register data, without
613 freeing the old data. */
614extern void re_set_registers (struct re_pattern_buffer *__buffer,
615 struct re_registers *__regs,
616 __re_size_t __num_regs,
617 regoff_t *__starts, regoff_t *__ends);
618
619#if defined _REGEX_RE_COMP || defined _LIBC
620# ifndef _CRAY
621/* 4.2 bsd compatibility. */
622extern char *re_comp (const char *);
623extern int re_exec (const char *);
624# endif
625#endif
626
627/* GCC 2.95 and later have "__restrict"; C99 compilers have
628 "restrict", and "configure" may have defined "restrict". */
629#ifndef __restrict
630# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
631# if defined restrict || 199901L <= __STDC_VERSION__
632# define __restrict restrict
633# else
634# define __restrict
635# endif
636# endif
637#endif
638/* gcc 3.1 and up support the [restrict] syntax. Don't trust
639 sys/cdefs.h's definition of __restrict_arr, though, as it
640 mishandles gcc -ansi -pedantic. */
641#undef __restrict_arr
642#if ((199901L <= __STDC_VERSION__ \
643 || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
644 && !__STRICT_ANSI__)) \
645 && !defined __GNUG__)
646# define __restrict_arr __restrict
647#else
648# define __restrict_arr
649#endif
650
651/* POSIX compatibility. */
652extern int regcomp (regex_t *__restrict __preg,
653 const char *__restrict __pattern,
654 int __cflags);
655
656extern int regexec (const regex_t *__restrict __preg,
657 const char *__restrict __string, size_t __nmatch,
658 regmatch_t __pmatch[__restrict_arr],
659 int __eflags);
660
661extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
662 char *__restrict __errbuf, size_t __errbuf_size);
663
664extern void regfree (regex_t *__preg);
665
666
667#ifdef __cplusplus
668}
669#endif /* C++ */
670
671#endif /* regex.h */
diff --git a/gl/regex_internal.c b/gl/regex_internal.c
new file mode 100644
index 00000000..78e16f33
--- /dev/null
+++ b/gl/regex_internal.c
@@ -0,0 +1,1742 @@
1/* Extended regular expression matching and search library.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20static void re_string_construct_common (const char *str, Idx len,
21 re_string_t *pstr,
22 RE_TRANSLATE_TYPE trans, bool icase,
23 const re_dfa_t *dfa) internal_function;
24static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
25 const re_node_set *nodes,
26 re_hashval_t hash) internal_function;
27static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
28 const re_node_set *nodes,
29 unsigned int context,
30 re_hashval_t hash) internal_function;
31
32/* Functions for string operation. */
33
34/* This function allocate the buffers. It is necessary to call
35 re_string_reconstruct before using the object. */
36
37static reg_errcode_t
38internal_function
39re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len,
40 RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
41{
42 reg_errcode_t ret;
43 Idx init_buf_len;
44
45 /* Ensure at least one character fits into the buffers. */
46 if (init_len < dfa->mb_cur_max)
47 init_len = dfa->mb_cur_max;
48 init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
49 re_string_construct_common (str, len, pstr, trans, icase, dfa);
50
51 ret = re_string_realloc_buffers (pstr, init_buf_len);
52 if (BE (ret != REG_NOERROR, 0))
53 return ret;
54
55 pstr->word_char = dfa->word_char;
56 pstr->word_ops_used = dfa->word_ops_used;
57 pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
58 pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
59 pstr->valid_raw_len = pstr->valid_len;
60 return REG_NOERROR;
61}
62
63/* This function allocate the buffers, and initialize them. */
64
65static reg_errcode_t
66internal_function
67re_string_construct (re_string_t *pstr, const char *str, Idx len,
68 RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
69{
70 reg_errcode_t ret;
71 memset (pstr, '\0', sizeof (re_string_t));
72 re_string_construct_common (str, len, pstr, trans, icase, dfa);
73
74 if (len > 0)
75 {
76 ret = re_string_realloc_buffers (pstr, len + 1);
77 if (BE (ret != REG_NOERROR, 0))
78 return ret;
79 }
80 pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
81
82 if (icase)
83 {
84#ifdef RE_ENABLE_I18N
85 if (dfa->mb_cur_max > 1)
86 {
87 while (1)
88 {
89 ret = build_wcs_upper_buffer (pstr);
90 if (BE (ret != REG_NOERROR, 0))
91 return ret;
92 if (pstr->valid_raw_len >= len)
93 break;
94 if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
95 break;
96 ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
97 if (BE (ret != REG_NOERROR, 0))
98 return ret;
99 }
100 }
101 else
102#endif /* RE_ENABLE_I18N */
103 build_upper_buffer (pstr);
104 }
105 else
106 {
107#ifdef RE_ENABLE_I18N
108 if (dfa->mb_cur_max > 1)
109 build_wcs_buffer (pstr);
110 else
111#endif /* RE_ENABLE_I18N */
112 {
113 if (trans != NULL)
114 re_string_translate_buffer (pstr);
115 else
116 {
117 pstr->valid_len = pstr->bufs_len;
118 pstr->valid_raw_len = pstr->bufs_len;
119 }
120 }
121 }
122
123 return REG_NOERROR;
124}
125
126/* Helper functions for re_string_allocate, and re_string_construct. */
127
128static reg_errcode_t
129internal_function
130re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len)
131{
132#ifdef RE_ENABLE_I18N
133 if (pstr->mb_cur_max > 1)
134 {
135 wint_t *new_wcs;
136
137 /* Avoid overflow. */
138 size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx));
139 if (BE (SIZE_MAX / max_object_size < new_buf_len, 0))
140 return REG_ESPACE;
141
142 new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
143 if (BE (new_wcs == NULL, 0))
144 return REG_ESPACE;
145 pstr->wcs = new_wcs;
146 if (pstr->offsets != NULL)
147 {
148 Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len);
149 if (BE (new_offsets == NULL, 0))
150 return REG_ESPACE;
151 pstr->offsets = new_offsets;
152 }
153 }
154#endif /* RE_ENABLE_I18N */
155 if (pstr->mbs_allocated)
156 {
157 unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
158 new_buf_len);
159 if (BE (new_mbs == NULL, 0))
160 return REG_ESPACE;
161 pstr->mbs = new_mbs;
162 }
163 pstr->bufs_len = new_buf_len;
164 return REG_NOERROR;
165}
166
167
168static void
169internal_function
170re_string_construct_common (const char *str, Idx len, re_string_t *pstr,
171 RE_TRANSLATE_TYPE trans, bool icase,
172 const re_dfa_t *dfa)
173{
174 pstr->raw_mbs = (const unsigned char *) str;
175 pstr->len = len;
176 pstr->raw_len = len;
177 pstr->trans = trans;
178 pstr->icase = icase;
179 pstr->mbs_allocated = (trans != NULL || icase);
180 pstr->mb_cur_max = dfa->mb_cur_max;
181 pstr->is_utf8 = dfa->is_utf8;
182 pstr->map_notascii = dfa->map_notascii;
183 pstr->stop = pstr->len;
184 pstr->raw_stop = pstr->stop;
185}
186
187#ifdef RE_ENABLE_I18N
188
189/* Build wide character buffer PSTR->WCS.
190 If the byte sequence of the string are:
191 <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
192 Then wide character buffer will be:
193 <wc1> , WEOF , <wc2> , WEOF , <wc3>
194 We use WEOF for padding, they indicate that the position isn't
195 a first byte of a multibyte character.
196
197 Note that this function assumes PSTR->VALID_LEN elements are already
198 built and starts from PSTR->VALID_LEN. */
199
200static void
201internal_function
202build_wcs_buffer (re_string_t *pstr)
203{
204#ifdef _LIBC
205 unsigned char buf[MB_LEN_MAX];
206 assert (MB_LEN_MAX >= pstr->mb_cur_max);
207#else
208 unsigned char buf[64];
209#endif
210 mbstate_t prev_st;
211 Idx byte_idx, end_idx, remain_len;
212 size_t mbclen;
213
214 /* Build the buffers from pstr->valid_len to either pstr->len or
215 pstr->bufs_len. */
216 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
217 for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
218 {
219 wchar_t wc;
220 const char *p;
221
222 remain_len = end_idx - byte_idx;
223 prev_st = pstr->cur_state;
224 /* Apply the translation if we need. */
225 if (BE (pstr->trans != NULL, 0))
226 {
227 int i, ch;
228
229 for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
230 {
231 ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
232 buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
233 }
234 p = (const char *) buf;
235 }
236 else
237 p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
238 mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
239 if (BE (mbclen == (size_t) -2, 0))
240 {
241 /* The buffer doesn't have enough space, finish to build. */
242 pstr->cur_state = prev_st;
243 break;
244 }
245 else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
246 {
247 /* We treat these cases as a singlebyte character. */
248 mbclen = 1;
249 wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
250 if (BE (pstr->trans != NULL, 0))
251 wc = pstr->trans[wc];
252 pstr->cur_state = prev_st;
253 }
254
255 /* Write wide character and padding. */
256 pstr->wcs[byte_idx++] = wc;
257 /* Write paddings. */
258 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
259 pstr->wcs[byte_idx++] = WEOF;
260 }
261 pstr->valid_len = byte_idx;
262 pstr->valid_raw_len = byte_idx;
263}
264
265/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
266 but for REG_ICASE. */
267
268static reg_errcode_t
269internal_function
270build_wcs_upper_buffer (re_string_t *pstr)
271{
272 mbstate_t prev_st;
273 Idx src_idx, byte_idx, end_idx, remain_len;
274 size_t mbclen;
275#ifdef _LIBC
276 char buf[MB_LEN_MAX];
277 assert (MB_LEN_MAX >= pstr->mb_cur_max);
278#else
279 char buf[64];
280#endif
281
282 byte_idx = pstr->valid_len;
283 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
284
285 /* The following optimization assumes that ASCII characters can be
286 mapped to wide characters with a simple cast. */
287 if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
288 {
289 while (byte_idx < end_idx)
290 {
291 wchar_t wc;
292
293 if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
294 && mbsinit (&pstr->cur_state))
295 {
296 /* In case of a singlebyte character. */
297 pstr->mbs[byte_idx]
298 = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
299 /* The next step uses the assumption that wchar_t is encoded
300 ASCII-safe: all ASCII values can be converted like this. */
301 pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
302 ++byte_idx;
303 continue;
304 }
305
306 remain_len = end_idx - byte_idx;
307 prev_st = pstr->cur_state;
308 mbclen = mbrtowc (&wc,
309 ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
310 + byte_idx), remain_len, &pstr->cur_state);
311 if (BE (mbclen < (size_t) -2, 1))
312 {
313 wchar_t wcu = wc;
314 if (iswlower (wc))
315 {
316 size_t mbcdlen;
317
318 wcu = towupper (wc);
319 mbcdlen = wcrtomb (buf, wcu, &prev_st);
320 if (BE (mbclen == mbcdlen, 1))
321 memcpy (pstr->mbs + byte_idx, buf, mbclen);
322 else
323 {
324 src_idx = byte_idx;
325 goto offsets_needed;
326 }
327 }
328 else
329 memcpy (pstr->mbs + byte_idx,
330 pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
331 pstr->wcs[byte_idx++] = wcu;
332 /* Write paddings. */
333 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
334 pstr->wcs[byte_idx++] = WEOF;
335 }
336 else if (mbclen == (size_t) -1 || mbclen == 0)
337 {
338 /* It is an invalid character or '\0'. Just use the byte. */
339 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
340 pstr->mbs[byte_idx] = ch;
341 /* And also cast it to wide char. */
342 pstr->wcs[byte_idx++] = (wchar_t) ch;
343 if (BE (mbclen == (size_t) -1, 0))
344 pstr->cur_state = prev_st;
345 }
346 else
347 {
348 /* The buffer doesn't have enough space, finish to build. */
349 pstr->cur_state = prev_st;
350 break;
351 }
352 }
353 pstr->valid_len = byte_idx;
354 pstr->valid_raw_len = byte_idx;
355 return REG_NOERROR;
356 }
357 else
358 for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
359 {
360 wchar_t wc;
361 const char *p;
362 offsets_needed:
363 remain_len = end_idx - byte_idx;
364 prev_st = pstr->cur_state;
365 if (BE (pstr->trans != NULL, 0))
366 {
367 int i, ch;
368
369 for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
370 {
371 ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
372 buf[i] = pstr->trans[ch];
373 }
374 p = (const char *) buf;
375 }
376 else
377 p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
378 mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
379 if (BE (mbclen < (size_t) -2, 1))
380 {
381 wchar_t wcu = wc;
382 if (iswlower (wc))
383 {
384 size_t mbcdlen;
385
386 wcu = towupper (wc);
387 mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
388 if (BE (mbclen == mbcdlen, 1))
389 memcpy (pstr->mbs + byte_idx, buf, mbclen);
390 else if (mbcdlen != (size_t) -1)
391 {
392 size_t i;
393
394 if (byte_idx + mbcdlen > pstr->bufs_len)
395 {
396 pstr->cur_state = prev_st;
397 break;
398 }
399
400 if (pstr->offsets == NULL)
401 {
402 pstr->offsets = re_malloc (Idx, pstr->bufs_len);
403
404 if (pstr->offsets == NULL)
405 return REG_ESPACE;
406 }
407 if (!pstr->offsets_needed)
408 {
409 for (i = 0; i < (size_t) byte_idx; ++i)
410 pstr->offsets[i] = i;
411 pstr->offsets_needed = 1;
412 }
413
414 memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
415 pstr->wcs[byte_idx] = wcu;
416 pstr->offsets[byte_idx] = src_idx;
417 for (i = 1; i < mbcdlen; ++i)
418 {
419 pstr->offsets[byte_idx + i]
420 = src_idx + (i < mbclen ? i : mbclen - 1);
421 pstr->wcs[byte_idx + i] = WEOF;
422 }
423 pstr->len += mbcdlen - mbclen;
424 if (pstr->raw_stop > src_idx)
425 pstr->stop += mbcdlen - mbclen;
426 end_idx = (pstr->bufs_len > pstr->len)
427 ? pstr->len : pstr->bufs_len;
428 byte_idx += mbcdlen;
429 src_idx += mbclen;
430 continue;
431 }
432 else
433 memcpy (pstr->mbs + byte_idx, p, mbclen);
434 }
435 else
436 memcpy (pstr->mbs + byte_idx, p, mbclen);
437
438 if (BE (pstr->offsets_needed != 0, 0))
439 {
440 size_t i;
441 for (i = 0; i < mbclen; ++i)
442 pstr->offsets[byte_idx + i] = src_idx + i;
443 }
444 src_idx += mbclen;
445
446 pstr->wcs[byte_idx++] = wcu;
447 /* Write paddings. */
448 for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
449 pstr->wcs[byte_idx++] = WEOF;
450 }
451 else if (mbclen == (size_t) -1 || mbclen == 0)
452 {
453 /* It is an invalid character or '\0'. Just use the byte. */
454 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
455
456 if (BE (pstr->trans != NULL, 0))
457 ch = pstr->trans [ch];
458 pstr->mbs[byte_idx] = ch;
459
460 if (BE (pstr->offsets_needed != 0, 0))
461 pstr->offsets[byte_idx] = src_idx;
462 ++src_idx;
463
464 /* And also cast it to wide char. */
465 pstr->wcs[byte_idx++] = (wchar_t) ch;
466 if (BE (mbclen == (size_t) -1, 0))
467 pstr->cur_state = prev_st;
468 }
469 else
470 {
471 /* The buffer doesn't have enough space, finish to build. */
472 pstr->cur_state = prev_st;
473 break;
474 }
475 }
476 pstr->valid_len = byte_idx;
477 pstr->valid_raw_len = src_idx;
478 return REG_NOERROR;
479}
480
481/* Skip characters until the index becomes greater than NEW_RAW_IDX.
482 Return the index. */
483
484static Idx
485internal_function
486re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc)
487{
488 mbstate_t prev_st;
489 Idx rawbuf_idx;
490 size_t mbclen;
491 wint_t wc = WEOF;
492
493 /* Skip the characters which are not necessary to check. */
494 for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
495 rawbuf_idx < new_raw_idx;)
496 {
497 wchar_t wc2;
498 Idx remain_len;
499 remain_len = pstr->len - rawbuf_idx;
500 prev_st = pstr->cur_state;
501 mbclen = mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
502 remain_len, &pstr->cur_state);
503 if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
504 {
505 /* We treat these cases as a single byte character. */
506 if (mbclen == 0 || remain_len == 0)
507 wc = L'\0';
508 else
509 wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
510 mbclen = 1;
511 pstr->cur_state = prev_st;
512 }
513 else
514 wc = wc2;
515 /* Then proceed the next character. */
516 rawbuf_idx += mbclen;
517 }
518 *last_wc = wc;
519 return rawbuf_idx;
520}
521#endif /* RE_ENABLE_I18N */
522
523/* Build the buffer PSTR->MBS, and apply the translation if we need.
524 This function is used in case of REG_ICASE. */
525
526static void
527internal_function
528build_upper_buffer (re_string_t *pstr)
529{
530 Idx char_idx, end_idx;
531 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
532
533 for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
534 {
535 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
536 if (BE (pstr->trans != NULL, 0))
537 ch = pstr->trans[ch];
538 if (islower (ch))
539 pstr->mbs[char_idx] = toupper (ch);
540 else
541 pstr->mbs[char_idx] = ch;
542 }
543 pstr->valid_len = char_idx;
544 pstr->valid_raw_len = char_idx;
545}
546
547/* Apply TRANS to the buffer in PSTR. */
548
549static void
550internal_function
551re_string_translate_buffer (re_string_t *pstr)
552{
553 Idx buf_idx, end_idx;
554 end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
555
556 for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
557 {
558 int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
559 pstr->mbs[buf_idx] = pstr->trans[ch];
560 }
561
562 pstr->valid_len = buf_idx;
563 pstr->valid_raw_len = buf_idx;
564}
565
566/* This function re-construct the buffers.
567 Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
568 convert to upper case in case of REG_ICASE, apply translation. */
569
570static reg_errcode_t
571internal_function
572re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
573{
574 Idx offset;
575
576 if (BE (pstr->raw_mbs_idx <= idx, 0))
577 offset = idx - pstr->raw_mbs_idx;
578 else
579 {
580 /* Reset buffer. */
581#ifdef RE_ENABLE_I18N
582 if (pstr->mb_cur_max > 1)
583 memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
584#endif /* RE_ENABLE_I18N */
585 pstr->len = pstr->raw_len;
586 pstr->stop = pstr->raw_stop;
587 pstr->valid_len = 0;
588 pstr->raw_mbs_idx = 0;
589 pstr->valid_raw_len = 0;
590 pstr->offsets_needed = 0;
591 pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
592 : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
593 if (!pstr->mbs_allocated)
594 pstr->mbs = (unsigned char *) pstr->raw_mbs;
595 offset = idx;
596 }
597
598 if (BE (offset != 0, 1))
599 {
600 /* Should the already checked characters be kept? */
601 if (BE (offset < pstr->valid_raw_len, 1))
602 {
603 /* Yes, move them to the front of the buffer. */
604#ifdef RE_ENABLE_I18N
605 if (BE (pstr->offsets_needed, 0))
606 {
607 Idx low = 0, high = pstr->valid_len, mid;
608 do
609 {
610 mid = (high + low) / 2;
611 if (pstr->offsets[mid] > offset)
612 high = mid;
613 else if (pstr->offsets[mid] < offset)
614 low = mid + 1;
615 else
616 break;
617 }
618 while (low < high);
619 if (pstr->offsets[mid] < offset)
620 ++mid;
621 pstr->tip_context = re_string_context_at (pstr, mid - 1,
622 eflags);
623 /* This can be quite complicated, so handle specially
624 only the common and easy case where the character with
625 different length representation of lower and upper
626 case is present at or after offset. */
627 if (pstr->valid_len > offset
628 && mid == offset && pstr->offsets[mid] == offset)
629 {
630 memmove (pstr->wcs, pstr->wcs + offset,
631 (pstr->valid_len - offset) * sizeof (wint_t));
632 memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
633 pstr->valid_len -= offset;
634 pstr->valid_raw_len -= offset;
635 for (low = 0; low < pstr->valid_len; low++)
636 pstr->offsets[low] = pstr->offsets[low + offset] - offset;
637 }
638 else
639 {
640 /* Otherwise, just find out how long the partial multibyte
641 character at offset is and fill it with WEOF/255. */
642 pstr->len = pstr->raw_len - idx + offset;
643 pstr->stop = pstr->raw_stop - idx + offset;
644 pstr->offsets_needed = 0;
645 while (mid > 0 && pstr->offsets[mid - 1] == offset)
646 --mid;
647 while (mid < pstr->valid_len)
648 if (pstr->wcs[mid] != WEOF)
649 break;
650 else
651 ++mid;
652 if (mid == pstr->valid_len)
653 pstr->valid_len = 0;
654 else
655 {
656 pstr->valid_len = pstr->offsets[mid] - offset;
657 if (pstr->valid_len)
658 {
659 for (low = 0; low < pstr->valid_len; ++low)
660 pstr->wcs[low] = WEOF;
661 memset (pstr->mbs, 255, pstr->valid_len);
662 }
663 }
664 pstr->valid_raw_len = pstr->valid_len;
665 }
666 }
667 else
668#endif
669 {
670 pstr->tip_context = re_string_context_at (pstr, offset - 1,
671 eflags);
672#ifdef RE_ENABLE_I18N
673 if (pstr->mb_cur_max > 1)
674 memmove (pstr->wcs, pstr->wcs + offset,
675 (pstr->valid_len - offset) * sizeof (wint_t));
676#endif /* RE_ENABLE_I18N */
677 if (BE (pstr->mbs_allocated, 0))
678 memmove (pstr->mbs, pstr->mbs + offset,
679 pstr->valid_len - offset);
680 pstr->valid_len -= offset;
681 pstr->valid_raw_len -= offset;
682#if DEBUG
683 assert (pstr->valid_len > 0);
684#endif
685 }
686 }
687 else
688 {
689 /* No, skip all characters until IDX. */
690 Idx prev_valid_len = pstr->valid_len;
691
692#ifdef RE_ENABLE_I18N
693 if (BE (pstr->offsets_needed, 0))
694 {
695 pstr->len = pstr->raw_len - idx + offset;
696 pstr->stop = pstr->raw_stop - idx + offset;
697 pstr->offsets_needed = 0;
698 }
699#endif
700 pstr->valid_len = 0;
701#ifdef RE_ENABLE_I18N
702 if (pstr->mb_cur_max > 1)
703 {
704 Idx wcs_idx;
705 wint_t wc = WEOF;
706
707 if (pstr->is_utf8)
708 {
709 const unsigned char *raw, *p, *q, *end;
710
711 /* Special case UTF-8. Multi-byte chars start with any
712 byte other than 0x80 - 0xbf. */
713 raw = pstr->raw_mbs + pstr->raw_mbs_idx;
714 end = raw + (offset - pstr->mb_cur_max);
715 if (end < pstr->raw_mbs)
716 end = pstr->raw_mbs;
717 p = raw + offset - 1;
718#ifdef _LIBC
719 /* We know the wchar_t encoding is UCS4, so for the simple
720 case, ASCII characters, skip the conversion step. */
721 if (isascii (*p) && BE (pstr->trans == NULL, 1))
722 {
723 memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
724 /* pstr->valid_len = 0; */
725 wc = (wchar_t) *p;
726 }
727 else
728#endif
729 for (; p >= end; --p)
730 if ((*p & 0xc0) != 0x80)
731 {
732 mbstate_t cur_state;
733 wchar_t wc2;
734 Idx mlen = raw + pstr->len - p;
735 unsigned char buf[6];
736 size_t mbclen;
737
738 q = p;
739 if (BE (pstr->trans != NULL, 0))
740 {
741 int i = mlen < 6 ? mlen : 6;
742 while (--i >= 0)
743 buf[i] = pstr->trans[p[i]];
744 q = buf;
745 }
746 /* XXX Don't use mbrtowc, we know which conversion
747 to use (UTF-8 -> UCS4). */
748 memset (&cur_state, 0, sizeof (cur_state));
749 mbclen = mbrtowc (&wc2, (const char *) p, mlen,
750 &cur_state);
751 if (raw + offset - p <= mbclen
752 && mbclen < (size_t) -2)
753 {
754 memset (&pstr->cur_state, '\0',
755 sizeof (mbstate_t));
756 pstr->valid_len = mbclen - (raw + offset - p);
757 wc = wc2;
758 }
759 break;
760 }
761 }
762
763 if (wc == WEOF)
764 pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
765 if (wc == WEOF)
766 pstr->tip_context
767 = re_string_context_at (pstr, prev_valid_len - 1, eflags);
768 else
769 pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
770 && IS_WIDE_WORD_CHAR (wc))
771 ? CONTEXT_WORD
772 : ((IS_WIDE_NEWLINE (wc)
773 && pstr->newline_anchor)
774 ? CONTEXT_NEWLINE : 0));
775 if (BE (pstr->valid_len, 0))
776 {
777 for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
778 pstr->wcs[wcs_idx] = WEOF;
779 if (pstr->mbs_allocated)
780 memset (pstr->mbs, 255, pstr->valid_len);
781 }
782 pstr->valid_raw_len = pstr->valid_len;
783 }
784 else
785#endif /* RE_ENABLE_I18N */
786 {
787 int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
788 pstr->valid_raw_len = 0;
789 if (pstr->trans)
790 c = pstr->trans[c];
791 pstr->tip_context = (bitset_contain (pstr->word_char, c)
792 ? CONTEXT_WORD
793 : ((IS_NEWLINE (c) && pstr->newline_anchor)
794 ? CONTEXT_NEWLINE : 0));
795 }
796 }
797 if (!BE (pstr->mbs_allocated, 0))
798 pstr->mbs += offset;
799 }
800 pstr->raw_mbs_idx = idx;
801 pstr->len -= offset;
802 pstr->stop -= offset;
803
804 /* Then build the buffers. */
805#ifdef RE_ENABLE_I18N
806 if (pstr->mb_cur_max > 1)
807 {
808 if (pstr->icase)
809 {
810 reg_errcode_t ret = build_wcs_upper_buffer (pstr);
811 if (BE (ret != REG_NOERROR, 0))
812 return ret;
813 }
814 else
815 build_wcs_buffer (pstr);
816 }
817 else
818#endif /* RE_ENABLE_I18N */
819 if (BE (pstr->mbs_allocated, 0))
820 {
821 if (pstr->icase)
822 build_upper_buffer (pstr);
823 else if (pstr->trans != NULL)
824 re_string_translate_buffer (pstr);
825 }
826 else
827 pstr->valid_len = pstr->len;
828
829 pstr->cur_idx = 0;
830 return REG_NOERROR;
831}
832
833static unsigned char
834internal_function __attribute ((pure))
835re_string_peek_byte_case (const re_string_t *pstr, Idx idx)
836{
837 int ch;
838 Idx off;
839
840 /* Handle the common (easiest) cases first. */
841 if (BE (!pstr->mbs_allocated, 1))
842 return re_string_peek_byte (pstr, idx);
843
844#ifdef RE_ENABLE_I18N
845 if (pstr->mb_cur_max > 1
846 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
847 return re_string_peek_byte (pstr, idx);
848#endif
849
850 off = pstr->cur_idx + idx;
851#ifdef RE_ENABLE_I18N
852 if (pstr->offsets_needed)
853 off = pstr->offsets[off];
854#endif
855
856 ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
857
858#ifdef RE_ENABLE_I18N
859 /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
860 this function returns CAPITAL LETTER I instead of first byte of
861 DOTLESS SMALL LETTER I. The latter would confuse the parser,
862 since peek_byte_case doesn't advance cur_idx in any way. */
863 if (pstr->offsets_needed && !isascii (ch))
864 return re_string_peek_byte (pstr, idx);
865#endif
866
867 return ch;
868}
869
870static unsigned char
871internal_function __attribute ((pure))
872re_string_fetch_byte_case (re_string_t *pstr)
873{
874 if (BE (!pstr->mbs_allocated, 1))
875 return re_string_fetch_byte (pstr);
876
877#ifdef RE_ENABLE_I18N
878 if (pstr->offsets_needed)
879 {
880 Idx off;
881 int ch;
882
883 /* For tr_TR.UTF-8 [[:islower:]] there is
884 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip
885 in that case the whole multi-byte character and return
886 the original letter. On the other side, with
887 [[: DOTLESS SMALL LETTER I return [[:I, as doing
888 anything else would complicate things too much. */
889
890 if (!re_string_first_byte (pstr, pstr->cur_idx))
891 return re_string_fetch_byte (pstr);
892
893 off = pstr->offsets[pstr->cur_idx];
894 ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
895
896 if (! isascii (ch))
897 return re_string_fetch_byte (pstr);
898
899 re_string_skip_bytes (pstr,
900 re_string_char_size_at (pstr, pstr->cur_idx));
901 return ch;
902 }
903#endif
904
905 return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
906}
907
908static void
909internal_function
910re_string_destruct (re_string_t *pstr)
911{
912#ifdef RE_ENABLE_I18N
913 re_free (pstr->wcs);
914 re_free (pstr->offsets);
915#endif /* RE_ENABLE_I18N */
916 if (pstr->mbs_allocated)
917 re_free (pstr->mbs);
918}
919
920/* Return the context at IDX in INPUT. */
921
922static unsigned int
923internal_function
924re_string_context_at (const re_string_t *input, Idx idx, int eflags)
925{
926 int c;
927 if (BE (! REG_VALID_INDEX (idx), 0))
928 /* In this case, we use the value stored in input->tip_context,
929 since we can't know the character in input->mbs[-1] here. */
930 return input->tip_context;
931 if (BE (idx == input->len, 0))
932 return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
933 : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
934#ifdef RE_ENABLE_I18N
935 if (input->mb_cur_max > 1)
936 {
937 wint_t wc;
938 Idx wc_idx = idx;
939 while(input->wcs[wc_idx] == WEOF)
940 {
941#ifdef DEBUG
942 /* It must not happen. */
943 assert (REG_VALID_INDEX (wc_idx));
944#endif
945 --wc_idx;
946 if (! REG_VALID_INDEX (wc_idx))
947 return input->tip_context;
948 }
949 wc = input->wcs[wc_idx];
950 if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
951 return CONTEXT_WORD;
952 return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
953 ? CONTEXT_NEWLINE : 0);
954 }
955 else
956#endif
957 {
958 c = re_string_byte_at (input, idx);
959 if (bitset_contain (input->word_char, c))
960 return CONTEXT_WORD;
961 return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
962 }
963}
964
965/* Functions for set operation. */
966
967static reg_errcode_t
968internal_function
969re_node_set_alloc (re_node_set *set, Idx size)
970{
971 set->alloc = size;
972 set->nelem = 0;
973 set->elems = re_malloc (Idx, size);
974 if (BE (set->elems == NULL, 0))
975 return REG_ESPACE;
976 return REG_NOERROR;
977}
978
979static reg_errcode_t
980internal_function
981re_node_set_init_1 (re_node_set *set, Idx elem)
982{
983 set->alloc = 1;
984 set->nelem = 1;
985 set->elems = re_malloc (Idx, 1);
986 if (BE (set->elems == NULL, 0))
987 {
988 set->alloc = set->nelem = 0;
989 return REG_ESPACE;
990 }
991 set->elems[0] = elem;
992 return REG_NOERROR;
993}
994
995static reg_errcode_t
996internal_function
997re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2)
998{
999 set->alloc = 2;
1000 set->elems = re_malloc (Idx, 2);
1001 if (BE (set->elems == NULL, 0))
1002 return REG_ESPACE;
1003 if (elem1 == elem2)
1004 {
1005 set->nelem = 1;
1006 set->elems[0] = elem1;
1007 }
1008 else
1009 {
1010 set->nelem = 2;
1011 if (elem1 < elem2)
1012 {
1013 set->elems[0] = elem1;
1014 set->elems[1] = elem2;
1015 }
1016 else
1017 {
1018 set->elems[0] = elem2;
1019 set->elems[1] = elem1;
1020 }
1021 }
1022 return REG_NOERROR;
1023}
1024
1025static reg_errcode_t
1026internal_function
1027re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
1028{
1029 dest->nelem = src->nelem;
1030 if (src->nelem > 0)
1031 {
1032 dest->alloc = dest->nelem;
1033 dest->elems = re_malloc (Idx, dest->alloc);
1034 if (BE (dest->elems == NULL, 0))
1035 {
1036 dest->alloc = dest->nelem = 0;
1037 return REG_ESPACE;
1038 }
1039 memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
1040 }
1041 else
1042 re_node_set_init_empty (dest);
1043 return REG_NOERROR;
1044}
1045
1046/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
1047 DEST. Return value indicate the error code or REG_NOERROR if succeeded.
1048 Note: We assume dest->elems is NULL, when dest->alloc is 0. */
1049
1050static reg_errcode_t
1051internal_function
1052re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
1053 const re_node_set *src2)
1054{
1055 Idx i1, i2, is, id, delta, sbase;
1056 if (src1->nelem == 0 || src2->nelem == 0)
1057 return REG_NOERROR;
1058
1059 /* We need dest->nelem + 2 * elems_in_intersection; this is a
1060 conservative estimate. */
1061 if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
1062 {
1063 Idx new_alloc = src1->nelem + src2->nelem + dest->alloc;
1064 Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc);
1065 if (BE (new_elems == NULL, 0))
1066 return REG_ESPACE;
1067 dest->elems = new_elems;
1068 dest->alloc = new_alloc;
1069 }
1070
1071 /* Find the items in the intersection of SRC1 and SRC2, and copy
1072 into the top of DEST those that are not already in DEST itself. */
1073 sbase = dest->nelem + src1->nelem + src2->nelem;
1074 i1 = src1->nelem - 1;
1075 i2 = src2->nelem - 1;
1076 id = dest->nelem - 1;
1077 for (;;)
1078 {
1079 if (src1->elems[i1] == src2->elems[i2])
1080 {
1081 /* Try to find the item in DEST. Maybe we could binary search? */
1082 while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1])
1083 --id;
1084
1085 if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1])
1086 dest->elems[--sbase] = src1->elems[i1];
1087
1088 if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2))
1089 break;
1090 }
1091
1092 /* Lower the highest of the two items. */
1093 else if (src1->elems[i1] < src2->elems[i2])
1094 {
1095 if (! REG_VALID_INDEX (--i2))
1096 break;
1097 }
1098 else
1099 {
1100 if (! REG_VALID_INDEX (--i1))
1101 break;
1102 }
1103 }
1104
1105 id = dest->nelem - 1;
1106 is = dest->nelem + src1->nelem + src2->nelem - 1;
1107 delta = is - sbase + 1;
1108
1109 /* Now copy. When DELTA becomes zero, the remaining
1110 DEST elements are already in place; this is more or
1111 less the same loop that is in re_node_set_merge. */
1112 dest->nelem += delta;
1113 if (delta > 0 && REG_VALID_INDEX (id))
1114 for (;;)
1115 {
1116 if (dest->elems[is] > dest->elems[id])
1117 {
1118 /* Copy from the top. */
1119 dest->elems[id + delta--] = dest->elems[is--];
1120 if (delta == 0)
1121 break;
1122 }
1123 else
1124 {
1125 /* Slide from the bottom. */
1126 dest->elems[id + delta] = dest->elems[id];
1127 if (! REG_VALID_INDEX (--id))
1128 break;
1129 }
1130 }
1131
1132 /* Copy remaining SRC elements. */
1133 memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx));
1134
1135 return REG_NOERROR;
1136}
1137
1138/* Calculate the union set of the sets SRC1 and SRC2. And store it to
1139 DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
1140
1141static reg_errcode_t
1142internal_function
1143re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
1144 const re_node_set *src2)
1145{
1146 Idx i1, i2, id;
1147 if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
1148 {
1149 dest->alloc = src1->nelem + src2->nelem;
1150 dest->elems = re_malloc (Idx, dest->alloc);
1151 if (BE (dest->elems == NULL, 0))
1152 return REG_ESPACE;
1153 }
1154 else
1155 {
1156 if (src1 != NULL && src1->nelem > 0)
1157 return re_node_set_init_copy (dest, src1);
1158 else if (src2 != NULL && src2->nelem > 0)
1159 return re_node_set_init_copy (dest, src2);
1160 else
1161 re_node_set_init_empty (dest);
1162 return REG_NOERROR;
1163 }
1164 for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
1165 {
1166 if (src1->elems[i1] > src2->elems[i2])
1167 {
1168 dest->elems[id++] = src2->elems[i2++];
1169 continue;
1170 }
1171 if (src1->elems[i1] == src2->elems[i2])
1172 ++i2;
1173 dest->elems[id++] = src1->elems[i1++];
1174 }
1175 if (i1 < src1->nelem)
1176 {
1177 memcpy (dest->elems + id, src1->elems + i1,
1178 (src1->nelem - i1) * sizeof (Idx));
1179 id += src1->nelem - i1;
1180 }
1181 else if (i2 < src2->nelem)
1182 {
1183 memcpy (dest->elems + id, src2->elems + i2,
1184 (src2->nelem - i2) * sizeof (Idx));
1185 id += src2->nelem - i2;
1186 }
1187 dest->nelem = id;
1188 return REG_NOERROR;
1189}
1190
1191/* Calculate the union set of the sets DEST and SRC. And store it to
1192 DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
1193
1194static reg_errcode_t
1195internal_function
1196re_node_set_merge (re_node_set *dest, const re_node_set *src)
1197{
1198 Idx is, id, sbase, delta;
1199 if (src == NULL || src->nelem == 0)
1200 return REG_NOERROR;
1201 if (dest->alloc < 2 * src->nelem + dest->nelem)
1202 {
1203 Idx new_alloc = 2 * (src->nelem + dest->alloc);
1204 Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc);
1205 if (BE (new_buffer == NULL, 0))
1206 return REG_ESPACE;
1207 dest->elems = new_buffer;
1208 dest->alloc = new_alloc;
1209 }
1210
1211 if (BE (dest->nelem == 0, 0))
1212 {
1213 dest->nelem = src->nelem;
1214 memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
1215 return REG_NOERROR;
1216 }
1217
1218 /* Copy into the top of DEST the items of SRC that are not
1219 found in DEST. Maybe we could binary search in DEST? */
1220 for (sbase = dest->nelem + 2 * src->nelem,
1221 is = src->nelem - 1, id = dest->nelem - 1;
1222 REG_VALID_INDEX (is) && REG_VALID_INDEX (id); )
1223 {
1224 if (dest->elems[id] == src->elems[is])
1225 is--, id--;
1226 else if (dest->elems[id] < src->elems[is])
1227 dest->elems[--sbase] = src->elems[is--];
1228 else /* if (dest->elems[id] > src->elems[is]) */
1229 --id;
1230 }
1231
1232 if (REG_VALID_INDEX (is))
1233 {
1234 /* If DEST is exhausted, the remaining items of SRC must be unique. */
1235 sbase -= is + 1;
1236 memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx));
1237 }
1238
1239 id = dest->nelem - 1;
1240 is = dest->nelem + 2 * src->nelem - 1;
1241 delta = is - sbase + 1;
1242 if (delta == 0)
1243 return REG_NOERROR;
1244
1245 /* Now copy. When DELTA becomes zero, the remaining
1246 DEST elements are already in place. */
1247 dest->nelem += delta;
1248 for (;;)
1249 {
1250 if (dest->elems[is] > dest->elems[id])
1251 {
1252 /* Copy from the top. */
1253 dest->elems[id + delta--] = dest->elems[is--];
1254 if (delta == 0)
1255 break;
1256 }
1257 else
1258 {
1259 /* Slide from the bottom. */
1260 dest->elems[id + delta] = dest->elems[id];
1261 if (! REG_VALID_INDEX (--id))
1262 {
1263 /* Copy remaining SRC elements. */
1264 memcpy (dest->elems, dest->elems + sbase,
1265 delta * sizeof (Idx));
1266 break;
1267 }
1268 }
1269 }
1270
1271 return REG_NOERROR;
1272}
1273
1274/* Insert the new element ELEM to the re_node_set* SET.
1275 SET should not already have ELEM.
1276 Return true if successful. */
1277
1278static bool
1279internal_function
1280re_node_set_insert (re_node_set *set, Idx elem)
1281{
1282 Idx idx;
1283 /* In case the set is empty. */
1284 if (set->alloc == 0)
1285 return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1);
1286
1287 if (BE (set->nelem, 0) == 0)
1288 {
1289 /* We already guaranteed above that set->alloc != 0. */
1290 set->elems[0] = elem;
1291 ++set->nelem;
1292 return true;
1293 }
1294
1295 /* Realloc if we need. */
1296 if (set->alloc == set->nelem)
1297 {
1298 Idx *new_elems;
1299 set->alloc = set->alloc * 2;
1300 new_elems = re_realloc (set->elems, Idx, set->alloc);
1301 if (BE (new_elems == NULL, 0))
1302 return false;
1303 set->elems = new_elems;
1304 }
1305
1306 /* Move the elements which follows the new element. Test the
1307 first element separately to skip a check in the inner loop. */
1308 if (elem < set->elems[0])
1309 {
1310 idx = 0;
1311 for (idx = set->nelem; idx > 0; idx--)
1312 set->elems[idx] = set->elems[idx - 1];
1313 }
1314 else
1315 {
1316 for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
1317 set->elems[idx] = set->elems[idx - 1];
1318 }
1319
1320 /* Insert the new element. */
1321 set->elems[idx] = elem;
1322 ++set->nelem;
1323 return true;
1324}
1325
1326/* Insert the new element ELEM to the re_node_set* SET.
1327 SET should not already have any element greater than or equal to ELEM.
1328 Return true if successful. */
1329
1330static bool
1331internal_function
1332re_node_set_insert_last (re_node_set *set, Idx elem)
1333{
1334 /* Realloc if we need. */
1335 if (set->alloc == set->nelem)
1336 {
1337 Idx *new_elems;
1338 set->alloc = (set->alloc + 1) * 2;
1339 new_elems = re_realloc (set->elems, Idx, set->alloc);
1340 if (BE (new_elems == NULL, 0))
1341 return false;
1342 set->elems = new_elems;
1343 }
1344
1345 /* Insert the new element. */
1346 set->elems[set->nelem++] = elem;
1347 return true;
1348}
1349
1350/* Compare two node sets SET1 and SET2.
1351 Return true if SET1 and SET2 are equivalent. */
1352
1353static bool
1354internal_function __attribute ((pure))
1355re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
1356{
1357 Idx i;
1358 if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
1359 return false;
1360 for (i = set1->nelem ; REG_VALID_INDEX (--i) ; )
1361 if (set1->elems[i] != set2->elems[i])
1362 return false;
1363 return true;
1364}
1365
1366/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
1367
1368static Idx
1369internal_function __attribute ((pure))
1370re_node_set_contains (const re_node_set *set, Idx elem)
1371{
1372 __re_size_t idx, right, mid;
1373 if (! REG_VALID_NONZERO_INDEX (set->nelem))
1374 return 0;
1375
1376 /* Binary search the element. */
1377 idx = 0;
1378 right = set->nelem - 1;
1379 while (idx < right)
1380 {
1381 mid = (idx + right) / 2;
1382 if (set->elems[mid] < elem)
1383 idx = mid + 1;
1384 else
1385 right = mid;
1386 }
1387 return set->elems[idx] == elem ? idx + 1 : 0;
1388}
1389
1390static void
1391internal_function
1392re_node_set_remove_at (re_node_set *set, Idx idx)
1393{
1394 if (idx < 0 || idx >= set->nelem)
1395 return;
1396 --set->nelem;
1397 for (; idx < set->nelem; idx++)
1398 set->elems[idx] = set->elems[idx + 1];
1399}
1400
1401
1402/* Add the token TOKEN to dfa->nodes, and return the index of the token.
1403 Or return REG_MISSING if an error occurred. */
1404
1405static Idx
1406internal_function
1407re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
1408{
1409 if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
1410 {
1411 size_t new_nodes_alloc = dfa->nodes_alloc * 2;
1412 Idx *new_nexts, *new_indices;
1413 re_node_set *new_edests, *new_eclosures;
1414 re_token_t *new_nodes;
1415 size_t max_object_size =
1416 MAX (sizeof (re_token_t),
1417 MAX (sizeof (re_node_set),
1418 sizeof (Idx)));
1419
1420 /* Avoid overflows. */
1421 if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0))
1422 return REG_MISSING;
1423
1424 new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
1425 if (BE (new_nodes == NULL, 0))
1426 return REG_MISSING;
1427 dfa->nodes = new_nodes;
1428 new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc);
1429 new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc);
1430 new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
1431 new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
1432 if (BE (new_nexts == NULL || new_indices == NULL
1433 || new_edests == NULL || new_eclosures == NULL, 0))
1434 return REG_MISSING;
1435 dfa->nexts = new_nexts;
1436 dfa->org_indices = new_indices;
1437 dfa->edests = new_edests;
1438 dfa->eclosures = new_eclosures;
1439 dfa->nodes_alloc = new_nodes_alloc;
1440 }
1441 dfa->nodes[dfa->nodes_len] = token;
1442 dfa->nodes[dfa->nodes_len].constraint = 0;
1443#ifdef RE_ENABLE_I18N
1444 {
1445 int type = token.type;
1446 dfa->nodes[dfa->nodes_len].accept_mb =
1447 (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
1448 }
1449#endif
1450 dfa->nexts[dfa->nodes_len] = REG_MISSING;
1451 re_node_set_init_empty (dfa->edests + dfa->nodes_len);
1452 re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
1453 return dfa->nodes_len++;
1454}
1455
1456static inline re_hashval_t
1457internal_function
1458calc_state_hash (const re_node_set *nodes, unsigned int context)
1459{
1460 re_hashval_t hash = nodes->nelem + context;
1461 Idx i;
1462 for (i = 0 ; i < nodes->nelem ; i++)
1463 hash += nodes->elems[i];
1464 return hash;
1465}
1466
1467/* Search for the state whose node_set is equivalent to NODES.
1468 Return the pointer to the state, if we found it in the DFA.
1469 Otherwise create the new one and return it. In case of an error
1470 return NULL and set the error code in ERR.
1471 Note: - We assume NULL as the invalid state, then it is possible that
1472 return value is NULL and ERR is REG_NOERROR.
1473 - We never return non-NULL value in case of any errors, it is for
1474 optimization. */
1475
1476static re_dfastate_t *
1477internal_function
1478re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
1479 const re_node_set *nodes)
1480{
1481 re_hashval_t hash;
1482 re_dfastate_t *new_state;
1483 struct re_state_table_entry *spot;
1484 Idx i;
1485#ifdef lint
1486 /* Suppress bogus uninitialized-variable warnings. */
1487 *err = REG_NOERROR;
1488#endif
1489 if (BE (nodes->nelem == 0, 0))
1490 {
1491 *err = REG_NOERROR;
1492 return NULL;
1493 }
1494 hash = calc_state_hash (nodes, 0);
1495 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1496
1497 for (i = 0 ; i < spot->num ; i++)
1498 {
1499 re_dfastate_t *state = spot->array[i];
1500 if (hash != state->hash)
1501 continue;
1502 if (re_node_set_compare (&state->nodes, nodes))
1503 return state;
1504 }
1505
1506 /* There are no appropriate state in the dfa, create the new one. */
1507 new_state = create_ci_newstate (dfa, nodes, hash);
1508 if (BE (new_state == NULL, 0))
1509 *err = REG_ESPACE;
1510
1511 return new_state;
1512}
1513
1514/* Search for the state whose node_set is equivalent to NODES and
1515 whose context is equivalent to CONTEXT.
1516 Return the pointer to the state, if we found it in the DFA.
1517 Otherwise create the new one and return it. In case of an error
1518 return NULL and set the error code in ERR.
1519 Note: - We assume NULL as the invalid state, then it is possible that
1520 return value is NULL and ERR is REG_NOERROR.
1521 - We never return non-NULL value in case of any errors, it is for
1522 optimization. */
1523
1524static re_dfastate_t *
1525internal_function
1526re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
1527 const re_node_set *nodes, unsigned int context)
1528{
1529 re_hashval_t hash;
1530 re_dfastate_t *new_state;
1531 struct re_state_table_entry *spot;
1532 Idx i;
1533#ifdef lint
1534 /* Suppress bogus uninitialized-variable warnings. */
1535 *err = REG_NOERROR;
1536#endif
1537 if (nodes->nelem == 0)
1538 {
1539 *err = REG_NOERROR;
1540 return NULL;
1541 }
1542 hash = calc_state_hash (nodes, context);
1543 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1544
1545 for (i = 0 ; i < spot->num ; i++)
1546 {
1547 re_dfastate_t *state = spot->array[i];
1548 if (state->hash == hash
1549 && state->context == context
1550 && re_node_set_compare (state->entrance_nodes, nodes))
1551 return state;
1552 }
1553 /* There are no appropriate state in `dfa', create the new one. */
1554 new_state = create_cd_newstate (dfa, nodes, context, hash);
1555 if (BE (new_state == NULL, 0))
1556 *err = REG_ESPACE;
1557
1558 return new_state;
1559}
1560
1561/* Finish initialization of the new state NEWSTATE, and using its hash value
1562 HASH put in the appropriate bucket of DFA's state table. Return value
1563 indicates the error code if failed. */
1564
1565static reg_errcode_t
1566register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
1567 re_hashval_t hash)
1568{
1569 struct re_state_table_entry *spot;
1570 reg_errcode_t err;
1571 Idx i;
1572
1573 newstate->hash = hash;
1574 err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
1575 if (BE (err != REG_NOERROR, 0))
1576 return REG_ESPACE;
1577 for (i = 0; i < newstate->nodes.nelem; i++)
1578 {
1579 Idx elem = newstate->nodes.elems[i];
1580 if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
1581 if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0))
1582 return REG_ESPACE;
1583 }
1584
1585 spot = dfa->state_table + (hash & dfa->state_hash_mask);
1586 if (BE (spot->alloc <= spot->num, 0))
1587 {
1588 Idx new_alloc = 2 * spot->num + 2;
1589 re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
1590 new_alloc);
1591 if (BE (new_array == NULL, 0))
1592 return REG_ESPACE;
1593 spot->array = new_array;
1594 spot->alloc = new_alloc;
1595 }
1596 spot->array[spot->num++] = newstate;
1597 return REG_NOERROR;
1598}
1599
1600static void
1601free_state (re_dfastate_t *state)
1602{
1603 re_node_set_free (&state->non_eps_nodes);
1604 re_node_set_free (&state->inveclosure);
1605 if (state->entrance_nodes != &state->nodes)
1606 {
1607 re_node_set_free (state->entrance_nodes);
1608 re_free (state->entrance_nodes);
1609 }
1610 re_node_set_free (&state->nodes);
1611 re_free (state->word_trtable);
1612 re_free (state->trtable);
1613 re_free (state);
1614}
1615
1616/* Create the new state which is independ of contexts.
1617 Return the new state if succeeded, otherwise return NULL. */
1618
1619static re_dfastate_t *
1620internal_function
1621create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
1622 re_hashval_t hash)
1623{
1624 Idx i;
1625 reg_errcode_t err;
1626 re_dfastate_t *newstate;
1627
1628 newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
1629 if (BE (newstate == NULL, 0))
1630 return NULL;
1631 err = re_node_set_init_copy (&newstate->nodes, nodes);
1632 if (BE (err != REG_NOERROR, 0))
1633 {
1634 re_free (newstate);
1635 return NULL;
1636 }
1637
1638 newstate->entrance_nodes = &newstate->nodes;
1639 for (i = 0 ; i < nodes->nelem ; i++)
1640 {
1641 re_token_t *node = dfa->nodes + nodes->elems[i];
1642 re_token_type_t type = node->type;
1643 if (type == CHARACTER && !node->constraint)
1644 continue;
1645#ifdef RE_ENABLE_I18N
1646 newstate->accept_mb |= node->accept_mb;
1647#endif /* RE_ENABLE_I18N */
1648
1649 /* If the state has the halt node, the state is a halt state. */
1650 if (type == END_OF_RE)
1651 newstate->halt = 1;
1652 else if (type == OP_BACK_REF)
1653 newstate->has_backref = 1;
1654 else if (type == ANCHOR || node->constraint)
1655 newstate->has_constraint = 1;
1656 }
1657 err = register_state (dfa, newstate, hash);
1658 if (BE (err != REG_NOERROR, 0))
1659 {
1660 free_state (newstate);
1661 newstate = NULL;
1662 }
1663 return newstate;
1664}
1665
1666/* Create the new state which is depend on the context CONTEXT.
1667 Return the new state if succeeded, otherwise return NULL. */
1668
1669static re_dfastate_t *
1670internal_function
1671create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
1672 unsigned int context, re_hashval_t hash)
1673{
1674 Idx i, nctx_nodes = 0;
1675 reg_errcode_t err;
1676 re_dfastate_t *newstate;
1677
1678 newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
1679 if (BE (newstate == NULL, 0))
1680 return NULL;
1681 err = re_node_set_init_copy (&newstate->nodes, nodes);
1682 if (BE (err != REG_NOERROR, 0))
1683 {
1684 re_free (newstate);
1685 return NULL;
1686 }
1687
1688 newstate->context = context;
1689 newstate->entrance_nodes = &newstate->nodes;
1690
1691 for (i = 0 ; i < nodes->nelem ; i++)
1692 {
1693 unsigned int constraint = 0;
1694 re_token_t *node = dfa->nodes + nodes->elems[i];
1695 re_token_type_t type = node->type;
1696 if (node->constraint)
1697 constraint = node->constraint;
1698
1699 if (type == CHARACTER && !constraint)
1700 continue;
1701#ifdef RE_ENABLE_I18N
1702 newstate->accept_mb |= node->accept_mb;
1703#endif /* RE_ENABLE_I18N */
1704
1705 /* If the state has the halt node, the state is a halt state. */
1706 if (type == END_OF_RE)
1707 newstate->halt = 1;
1708 else if (type == OP_BACK_REF)
1709 newstate->has_backref = 1;
1710 else if (type == ANCHOR)
1711 constraint = node->opr.ctx_type;
1712
1713 if (constraint)
1714 {
1715 if (newstate->entrance_nodes == &newstate->nodes)
1716 {
1717 newstate->entrance_nodes = re_malloc (re_node_set, 1);
1718 if (BE (newstate->entrance_nodes == NULL, 0))
1719 {
1720 free_state (newstate);
1721 return NULL;
1722 }
1723 re_node_set_init_copy (newstate->entrance_nodes, nodes);
1724 nctx_nodes = 0;
1725 newstate->has_constraint = 1;
1726 }
1727
1728 if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
1729 {
1730 re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
1731 ++nctx_nodes;
1732 }
1733 }
1734 }
1735 err = register_state (dfa, newstate, hash);
1736 if (BE (err != REG_NOERROR, 0))
1737 {
1738 free_state (newstate);
1739 newstate = NULL;
1740 }
1741 return newstate;
1742}
diff --git a/gl/regex_internal.h b/gl/regex_internal.h
new file mode 100644
index 00000000..b0f7e657
--- /dev/null
+++ b/gl/regex_internal.h
@@ -0,0 +1,862 @@
1/* Extended regular expression matching and search library.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef _REGEX_INTERNAL_H
21#define _REGEX_INTERNAL_H 1
22
23#include <assert.h>
24#include <ctype.h>
25#include <stdbool.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#ifndef _LIBC
31# include "strcase.h"
32#endif
33
34#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
35# include <langinfo.h>
36#endif
37#if defined HAVE_LOCALE_H || defined _LIBC
38# include <locale.h>
39#endif
40
41#include <wchar.h>
42#include <wctype.h>
43#include <stdint.h>
44#if defined _LIBC
45# include <bits/libc-lock.h>
46#else
47# define __libc_lock_init(NAME) do { } while (0)
48# define __libc_lock_lock(NAME) do { } while (0)
49# define __libc_lock_unlock(NAME) do { } while (0)
50#endif
51
52/* In case that the system doesn't have isblank(). */
53#if !defined _LIBC && !HAVE_DECL_ISBLANK && !defined isblank
54# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
55#endif
56
57#ifdef _LIBC
58# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
59# define _RE_DEFINE_LOCALE_FUNCTIONS 1
60# include <locale/localeinfo.h>
61# include <locale/elem-hash.h>
62# include <locale/coll-lookup.h>
63# endif
64#endif
65
66/* This is for other GNU distributions with internationalized messages. */
67#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
68# include <libintl.h>
69# ifdef _LIBC
70# undef gettext
71# define gettext(msgid) \
72 INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)
73# endif
74#else
75# define gettext(msgid) (msgid)
76#endif
77
78#ifndef gettext_noop
79/* This define is so xgettext can find the internationalizable
80 strings. */
81# define gettext_noop(String) String
82#endif
83
84/* For loser systems without the definition. */
85#ifndef SIZE_MAX
86# define SIZE_MAX ((size_t) -1)
87#endif
88
89#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
90# define RE_ENABLE_I18N
91#endif
92
93#if __GNUC__ >= 3
94# define BE(expr, val) __builtin_expect (expr, val)
95#else
96# define BE(expr, val) (expr)
97# ifdef _LIBC
98# define inline
99# endif
100#endif
101
102/* Number of ASCII characters. */
103#define ASCII_CHARS 0x80
104
105/* Number of single byte characters. */
106#define SBC_MAX (UCHAR_MAX + 1)
107
108#define COLL_ELEM_LEN_MAX 8
109
110/* The character which represents newline. */
111#define NEWLINE_CHAR '\n'
112#define WIDE_NEWLINE_CHAR L'\n'
113
114/* Rename to standard API for using out of glibc. */
115#ifndef _LIBC
116# define __wctype wctype
117# define __iswctype iswctype
118# define __btowc btowc
119# ifndef __mempcpy
120# define __mempcpy mempcpy
121# endif
122# define __wcrtomb wcrtomb
123# define __regfree regfree
124# define attribute_hidden
125#endif /* not _LIBC */
126
127#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
128# define __attribute(arg) __attribute__ (arg)
129#else
130# define __attribute(arg)
131#endif
132
133typedef __re_idx_t Idx;
134
135/* Special return value for failure to match. */
136#define REG_MISSING ((Idx) -1)
137
138/* Special return value for internal error. */
139#define REG_ERROR ((Idx) -2)
140
141/* Test whether N is a valid index, and is not one of the above. */
142#ifdef _REGEX_LARGE_OFFSETS
143# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR)
144#else
145# define REG_VALID_INDEX(n) (0 <= (n))
146#endif
147
148/* Test whether N is a valid nonzero index. */
149#ifdef _REGEX_LARGE_OFFSETS
150# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1))
151#else
152# define REG_VALID_NONZERO_INDEX(n) (0 < (n))
153#endif
154
155/* A hash value, suitable for computing hash tables. */
156typedef __re_size_t re_hashval_t;
157
158/* An integer used to represent a set of bits. It must be unsigned,
159 and must be at least as wide as unsigned int. */
160typedef unsigned long int bitset_word_t;
161/* All bits set in a bitset_word_t. */
162#define BITSET_WORD_MAX ULONG_MAX
163
164/* Number of bits in a bitset_word_t. For portability to hosts with
165 padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)';
166 instead, deduce it directly from BITSET_WORD_MAX. Avoid
167 greater-than-32-bit integers and unconditional shifts by more than
168 31 bits, as they're not portable. */
169#if BITSET_WORD_MAX == 0xffffffff
170# define BITSET_WORD_BITS 32
171#elif BITSET_WORD_MAX >> 31 >> 5 == 1
172# define BITSET_WORD_BITS 36
173#elif BITSET_WORD_MAX >> 31 >> 16 == 1
174# define BITSET_WORD_BITS 48
175#elif BITSET_WORD_MAX >> 31 >> 28 == 1
176# define BITSET_WORD_BITS 60
177#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
178# define BITSET_WORD_BITS 64
179#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
180# define BITSET_WORD_BITS 72
181#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
182# define BITSET_WORD_BITS 128
183#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
184# define BITSET_WORD_BITS 256
185#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
186# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
187# if BITSET_WORD_BITS <= SBC_MAX
188# error "Invalid SBC_MAX"
189# endif
190#elif BITSET_WORD_MAX == (0xffffffff + 2) * 0xffffffff
191/* Work around a bug in 64-bit PGC (before version 6.1-2), where the
192 preprocessor mishandles large unsigned values as if they were signed. */
193# define BITSET_WORD_BITS 64
194#else
195# error "Add case for new bitset_word_t size"
196#endif
197
198/* Number of bitset_word_t values in a bitset_t. */
199#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
200
201typedef bitset_word_t bitset_t[BITSET_WORDS];
202typedef bitset_word_t *re_bitset_ptr_t;
203typedef const bitset_word_t *re_const_bitset_ptr_t;
204
205#define PREV_WORD_CONSTRAINT 0x0001
206#define PREV_NOTWORD_CONSTRAINT 0x0002
207#define NEXT_WORD_CONSTRAINT 0x0004
208#define NEXT_NOTWORD_CONSTRAINT 0x0008
209#define PREV_NEWLINE_CONSTRAINT 0x0010
210#define NEXT_NEWLINE_CONSTRAINT 0x0020
211#define PREV_BEGBUF_CONSTRAINT 0x0040
212#define NEXT_ENDBUF_CONSTRAINT 0x0080
213#define WORD_DELIM_CONSTRAINT 0x0100
214#define NOT_WORD_DELIM_CONSTRAINT 0x0200
215
216typedef enum
217{
218 INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
219 WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
220 WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
221 INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
222 LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
223 LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
224 BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
225 BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
226 WORD_DELIM = WORD_DELIM_CONSTRAINT,
227 NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
228} re_context_type;
229
230typedef struct
231{
232 Idx alloc;
233 Idx nelem;
234 Idx *elems;
235} re_node_set;
236
237typedef enum
238{
239 NON_TYPE = 0,
240
241 /* Node type, These are used by token, node, tree. */
242 CHARACTER = 1,
243 END_OF_RE = 2,
244 SIMPLE_BRACKET = 3,
245 OP_BACK_REF = 4,
246 OP_PERIOD = 5,
247#ifdef RE_ENABLE_I18N
248 COMPLEX_BRACKET = 6,
249 OP_UTF8_PERIOD = 7,
250#endif /* RE_ENABLE_I18N */
251
252 /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
253 when the debugger shows values of this enum type. */
254#define EPSILON_BIT 8
255 OP_OPEN_SUBEXP = EPSILON_BIT | 0,
256 OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
257 OP_ALT = EPSILON_BIT | 2,
258 OP_DUP_ASTERISK = EPSILON_BIT | 3,
259 ANCHOR = EPSILON_BIT | 4,
260
261 /* Tree type, these are used only by tree. */
262 CONCAT = 16,
263 SUBEXP = 17,
264
265 /* Token type, these are used only by token. */
266 OP_DUP_PLUS = 18,
267 OP_DUP_QUESTION,
268 OP_OPEN_BRACKET,
269 OP_CLOSE_BRACKET,
270 OP_CHARSET_RANGE,
271 OP_OPEN_DUP_NUM,
272 OP_CLOSE_DUP_NUM,
273 OP_NON_MATCH_LIST,
274 OP_OPEN_COLL_ELEM,
275 OP_CLOSE_COLL_ELEM,
276 OP_OPEN_EQUIV_CLASS,
277 OP_CLOSE_EQUIV_CLASS,
278 OP_OPEN_CHAR_CLASS,
279 OP_CLOSE_CHAR_CLASS,
280 OP_WORD,
281 OP_NOTWORD,
282 OP_SPACE,
283 OP_NOTSPACE,
284 BACK_SLASH
285
286} re_token_type_t;
287
288#ifdef RE_ENABLE_I18N
289typedef struct
290{
291 /* Multibyte characters. */
292 wchar_t *mbchars;
293
294 /* Collating symbols. */
295# ifdef _LIBC
296 int32_t *coll_syms;
297# endif
298
299 /* Equivalence classes. */
300# ifdef _LIBC
301 int32_t *equiv_classes;
302# endif
303
304 /* Range expressions. */
305# ifdef _LIBC
306 uint32_t *range_starts;
307 uint32_t *range_ends;
308# else /* not _LIBC */
309 wchar_t *range_starts;
310 wchar_t *range_ends;
311# endif /* not _LIBC */
312
313 /* Character classes. */
314 wctype_t *char_classes;
315
316 /* If this character set is the non-matching list. */
317 unsigned int non_match : 1;
318
319 /* # of multibyte characters. */
320 Idx nmbchars;
321
322 /* # of collating symbols. */
323 Idx ncoll_syms;
324
325 /* # of equivalence classes. */
326 Idx nequiv_classes;
327
328 /* # of range expressions. */
329 Idx nranges;
330
331 /* # of character classes. */
332 Idx nchar_classes;
333} re_charset_t;
334#endif /* RE_ENABLE_I18N */
335
336typedef struct
337{
338 union
339 {
340 unsigned char c; /* for CHARACTER */
341 re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
342#ifdef RE_ENABLE_I18N
343 re_charset_t *mbcset; /* for COMPLEX_BRACKET */
344#endif /* RE_ENABLE_I18N */
345 Idx idx; /* for BACK_REF */
346 re_context_type ctx_type; /* for ANCHOR */
347 } opr;
348#if __GNUC__ >= 2 && !__STRICT_ANSI__
349 re_token_type_t type : 8;
350#else
351 re_token_type_t type;
352#endif
353 unsigned int constraint : 10; /* context constraint */
354 unsigned int duplicated : 1;
355 unsigned int opt_subexp : 1;
356#ifdef RE_ENABLE_I18N
357 unsigned int accept_mb : 1;
358 /* These 2 bits can be moved into the union if needed (e.g. if running out
359 of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
360 unsigned int mb_partial : 1;
361#endif
362 unsigned int word_char : 1;
363} re_token_t;
364
365#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
366
367struct re_string_t
368{
369 /* Indicate the raw buffer which is the original string passed as an
370 argument of regexec(), re_search(), etc.. */
371 const unsigned char *raw_mbs;
372 /* Store the multibyte string. In case of "case insensitive mode" like
373 REG_ICASE, upper cases of the string are stored, otherwise MBS points
374 the same address that RAW_MBS points. */
375 unsigned char *mbs;
376#ifdef RE_ENABLE_I18N
377 /* Store the wide character string which is corresponding to MBS. */
378 wint_t *wcs;
379 Idx *offsets;
380 mbstate_t cur_state;
381#endif
382 /* Index in RAW_MBS. Each character mbs[i] corresponds to
383 raw_mbs[raw_mbs_idx + i]. */
384 Idx raw_mbs_idx;
385 /* The length of the valid characters in the buffers. */
386 Idx valid_len;
387 /* The corresponding number of bytes in raw_mbs array. */
388 Idx valid_raw_len;
389 /* The length of the buffers MBS and WCS. */
390 Idx bufs_len;
391 /* The index in MBS, which is updated by re_string_fetch_byte. */
392 Idx cur_idx;
393 /* length of RAW_MBS array. */
394 Idx raw_len;
395 /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
396 Idx len;
397 /* End of the buffer may be shorter than its length in the cases such
398 as re_match_2, re_search_2. Then, we use STOP for end of the buffer
399 instead of LEN. */
400 Idx raw_stop;
401 /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
402 Idx stop;
403
404 /* The context of mbs[0]. We store the context independently, since
405 the context of mbs[0] may be different from raw_mbs[0], which is
406 the beginning of the input string. */
407 unsigned int tip_context;
408 /* The translation passed as a part of an argument of re_compile_pattern. */
409 RE_TRANSLATE_TYPE trans;
410 /* Copy of re_dfa_t's word_char. */
411 re_const_bitset_ptr_t word_char;
412 /* true if REG_ICASE. */
413 unsigned char icase;
414 unsigned char is_utf8;
415 unsigned char map_notascii;
416 unsigned char mbs_allocated;
417 unsigned char offsets_needed;
418 unsigned char newline_anchor;
419 unsigned char word_ops_used;
420 int mb_cur_max;
421};
422typedef struct re_string_t re_string_t;
423
424
425struct re_dfa_t;
426typedef struct re_dfa_t re_dfa_t;
427
428#ifndef _LIBC
429# ifdef __i386__
430# define internal_function __attribute ((regparm (3), stdcall))
431# else
432# define internal_function
433# endif
434#endif
435
436static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
437 Idx new_buf_len)
438 internal_function;
439#ifdef RE_ENABLE_I18N
440static void build_wcs_buffer (re_string_t *pstr) internal_function;
441static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr)
442 internal_function;
443#endif /* RE_ENABLE_I18N */
444static void build_upper_buffer (re_string_t *pstr) internal_function;
445static void re_string_translate_buffer (re_string_t *pstr) internal_function;
446static unsigned int re_string_context_at (const re_string_t *input, Idx idx,
447 int eflags)
448 internal_function __attribute ((pure));
449#define re_string_peek_byte(pstr, offset) \
450 ((pstr)->mbs[(pstr)->cur_idx + offset])
451#define re_string_fetch_byte(pstr) \
452 ((pstr)->mbs[(pstr)->cur_idx++])
453#define re_string_first_byte(pstr, idx) \
454 ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
455#define re_string_is_single_byte_char(pstr, idx) \
456 ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
457 || (pstr)->wcs[(idx) + 1] != WEOF))
458#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
459#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
460#define re_string_get_buffer(pstr) ((pstr)->mbs)
461#define re_string_length(pstr) ((pstr)->len)
462#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
463#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
464#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
465
466#include <alloca.h>
467
468#ifndef _LIBC
469# if HAVE_ALLOCA
470/* The OS usually guarantees only one guard page at the bottom of the stack,
471 and a page size can be as small as 4096 bytes. So we cannot safely
472 allocate anything larger than 4096 bytes. Also care for the possibility
473 of a few compiler-allocated temporary stack slots. */
474# define __libc_use_alloca(n) ((n) < 4032)
475# else
476/* alloca is implemented with malloc, so just use malloc. */
477# define __libc_use_alloca(n) 0
478# endif
479#endif
480
481#ifndef MAX
482# define MAX(a,b) ((a) < (b) ? (b) : (a))
483#endif
484
485#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
486#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
487#define re_free(p) free (p)
488
489struct bin_tree_t
490{
491 struct bin_tree_t *parent;
492 struct bin_tree_t *left;
493 struct bin_tree_t *right;
494 struct bin_tree_t *first;
495 struct bin_tree_t *next;
496
497 re_token_t token;
498
499 /* `node_idx' is the index in dfa->nodes, if `type' == 0.
500 Otherwise `type' indicate the type of this node. */
501 Idx node_idx;
502};
503typedef struct bin_tree_t bin_tree_t;
504
505#define BIN_TREE_STORAGE_SIZE \
506 ((1024 - sizeof (void *)) / sizeof (bin_tree_t))
507
508struct bin_tree_storage_t
509{
510 struct bin_tree_storage_t *next;
511 bin_tree_t data[BIN_TREE_STORAGE_SIZE];
512};
513typedef struct bin_tree_storage_t bin_tree_storage_t;
514
515#define CONTEXT_WORD 1
516#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
517#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
518#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
519
520#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
521#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
522#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
523#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
524#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
525
526#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
527#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
528#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
529#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
530
531#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
532 ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
533 || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
534 || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
535 || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
536
537#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
538 ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
539 || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
540 || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
541 || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
542
543struct re_dfastate_t
544{
545 re_hashval_t hash;
546 re_node_set nodes;
547 re_node_set non_eps_nodes;
548 re_node_set inveclosure;
549 re_node_set *entrance_nodes;
550 struct re_dfastate_t **trtable, **word_trtable;
551 unsigned int context : 4;
552 unsigned int halt : 1;
553 /* If this state can accept `multi byte'.
554 Note that we refer to multibyte characters, and multi character
555 collating elements as `multi byte'. */
556 unsigned int accept_mb : 1;
557 /* If this state has backreference node(s). */
558 unsigned int has_backref : 1;
559 unsigned int has_constraint : 1;
560};
561typedef struct re_dfastate_t re_dfastate_t;
562
563struct re_state_table_entry
564{
565 Idx num;
566 Idx alloc;
567 re_dfastate_t **array;
568};
569
570/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
571
572typedef struct
573{
574 Idx next_idx;
575 Idx alloc;
576 re_dfastate_t **array;
577} state_array_t;
578
579/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
580
581typedef struct
582{
583 Idx node;
584 Idx str_idx; /* The position NODE match at. */
585 state_array_t path;
586} re_sub_match_last_t;
587
588/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
589 And information about the node, whose type is OP_CLOSE_SUBEXP,
590 corresponding to NODE is stored in LASTS. */
591
592typedef struct
593{
594 Idx str_idx;
595 Idx node;
596 state_array_t *path;
597 Idx alasts; /* Allocation size of LASTS. */
598 Idx nlasts; /* The number of LASTS. */
599 re_sub_match_last_t **lasts;
600} re_sub_match_top_t;
601
602struct re_backref_cache_entry
603{
604 Idx node;
605 Idx str_idx;
606 Idx subexp_from;
607 Idx subexp_to;
608 char more;
609 char unused;
610 unsigned short int eps_reachable_subexps_map;
611};
612
613typedef struct
614{
615 /* The string object corresponding to the input string. */
616 re_string_t input;
617#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
618 const re_dfa_t *const dfa;
619#else
620 const re_dfa_t *dfa;
621#endif
622 /* EFLAGS of the argument of regexec. */
623 int eflags;
624 /* Where the matching ends. */
625 Idx match_last;
626 Idx last_node;
627 /* The state log used by the matcher. */
628 re_dfastate_t **state_log;
629 Idx state_log_top;
630 /* Back reference cache. */
631 Idx nbkref_ents;
632 Idx abkref_ents;
633 struct re_backref_cache_entry *bkref_ents;
634 int max_mb_elem_len;
635 Idx nsub_tops;
636 Idx asub_tops;
637 re_sub_match_top_t **sub_tops;
638} re_match_context_t;
639
640typedef struct
641{
642 re_dfastate_t **sifted_states;
643 re_dfastate_t **limited_states;
644 Idx last_node;
645 Idx last_str_idx;
646 re_node_set limits;
647} re_sift_context_t;
648
649struct re_fail_stack_ent_t
650{
651 Idx idx;
652 Idx node;
653 regmatch_t *regs;
654 re_node_set eps_via_nodes;
655};
656
657struct re_fail_stack_t
658{
659 Idx num;
660 Idx alloc;
661 struct re_fail_stack_ent_t *stack;
662};
663
664struct re_dfa_t
665{
666 re_token_t *nodes;
667 size_t nodes_alloc;
668 size_t nodes_len;
669 Idx *nexts;
670 Idx *org_indices;
671 re_node_set *edests;
672 re_node_set *eclosures;
673 re_node_set *inveclosures;
674 struct re_state_table_entry *state_table;
675 re_dfastate_t *init_state;
676 re_dfastate_t *init_state_word;
677 re_dfastate_t *init_state_nl;
678 re_dfastate_t *init_state_begbuf;
679 bin_tree_t *str_tree;
680 bin_tree_storage_t *str_tree_storage;
681 re_bitset_ptr_t sb_char;
682 int str_tree_storage_idx;
683
684 /* number of subexpressions `re_nsub' is in regex_t. */
685 re_hashval_t state_hash_mask;
686 Idx init_node;
687 Idx nbackref; /* The number of backreference in this dfa. */
688
689 /* Bitmap expressing which backreference is used. */
690 bitset_word_t used_bkref_map;
691 bitset_word_t completed_bkref_map;
692
693 unsigned int has_plural_match : 1;
694 /* If this dfa has "multibyte node", which is a backreference or
695 a node which can accept multibyte character or multi character
696 collating element. */
697 unsigned int has_mb_node : 1;
698 unsigned int is_utf8 : 1;
699 unsigned int map_notascii : 1;
700 unsigned int word_ops_used : 1;
701 int mb_cur_max;
702 bitset_t word_char;
703 reg_syntax_t syntax;
704 Idx *subexp_map;
705#ifdef DEBUG
706 char* re_str;
707#endif
708#ifdef _LIBC
709 __libc_lock_define (, lock)
710#endif
711};
712
713#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
714#define re_node_set_remove(set,id) \
715 (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
716#define re_node_set_empty(p) ((p)->nelem = 0)
717#define re_node_set_free(set) re_free ((set)->elems)
718
719
720typedef enum
721{
722 SB_CHAR,
723 MB_CHAR,
724 EQUIV_CLASS,
725 COLL_SYM,
726 CHAR_CLASS
727} bracket_elem_type;
728
729typedef struct
730{
731 bracket_elem_type type;
732 union
733 {
734 unsigned char ch;
735 unsigned char *name;
736 wchar_t wch;
737 } opr;
738} bracket_elem_t;
739
740
741/* Inline functions for bitset_t operation. */
742
743static inline void
744bitset_set (bitset_t set, Idx i)
745{
746 set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS;
747}
748
749static inline void
750bitset_clear (bitset_t set, Idx i)
751{
752 set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS);
753}
754
755static inline bool
756bitset_contain (const bitset_t set, Idx i)
757{
758 return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
759}
760
761static inline void
762bitset_empty (bitset_t set)
763{
764 memset (set, '\0', sizeof (bitset_t));
765}
766
767static inline void
768bitset_set_all (bitset_t set)
769{
770 memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS));
771 if (SBC_MAX % BITSET_WORD_BITS != 0)
772 set[BITSET_WORDS - 1] =
773 ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
774}
775
776static inline void
777bitset_copy (bitset_t dest, const bitset_t src)
778{
779 memcpy (dest, src, sizeof (bitset_t));
780}
781
782static inline void
783bitset_not (bitset_t set)
784{
785 int bitset_i;
786 for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i)
787 set[bitset_i] = ~set[bitset_i];
788 if (SBC_MAX % BITSET_WORD_BITS != 0)
789 set[BITSET_WORDS - 1] =
790 ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
791 & ~set[BITSET_WORDS - 1]);
792}
793
794static inline void
795bitset_merge (bitset_t dest, const bitset_t src)
796{
797 int bitset_i;
798 for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
799 dest[bitset_i] |= src[bitset_i];
800}
801
802static inline void
803bitset_mask (bitset_t dest, const bitset_t src)
804{
805 int bitset_i;
806 for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
807 dest[bitset_i] &= src[bitset_i];
808}
809
810#ifdef RE_ENABLE_I18N
811/* Inline functions for re_string. */
812static inline int
813internal_function __attribute ((pure))
814re_string_char_size_at (const re_string_t *pstr, Idx idx)
815{
816 int byte_idx;
817 if (pstr->mb_cur_max == 1)
818 return 1;
819 for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
820 if (pstr->wcs[idx + byte_idx] != WEOF)
821 break;
822 return byte_idx;
823}
824
825static inline wint_t
826internal_function __attribute ((pure))
827re_string_wchar_at (const re_string_t *pstr, Idx idx)
828{
829 if (pstr->mb_cur_max == 1)
830 return (wint_t) pstr->mbs[idx];
831 return (wint_t) pstr->wcs[idx];
832}
833
834static int
835internal_function __attribute ((pure))
836re_string_elem_size_at (const re_string_t *pstr, Idx idx)
837{
838# ifdef _LIBC
839 const unsigned char *p, *extra;
840 const int32_t *table, *indirect;
841 int32_t tmp;
842# include <locale/weight.h>
843 uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
844
845 if (nrules != 0)
846 {
847 table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
848 extra = (const unsigned char *)
849 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
850 indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
851 _NL_COLLATE_INDIRECTMB);
852 p = pstr->mbs + idx;
853 tmp = findidx (&p);
854 return p - pstr->mbs - idx;
855 }
856 else
857# endif /* _LIBC */
858 return 1;
859}
860#endif /* RE_ENABLE_I18N */
861
862#endif /* _REGEX_INTERNAL_H */
diff --git a/gl/regexec.c b/gl/regexec.c
new file mode 100644
index 00000000..7c186aa2
--- /dev/null
+++ b/gl/regexec.c
@@ -0,0 +1,4398 @@
1/* Extended regular expression matching and search library.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
21 Idx n) internal_function;
22static void match_ctx_clean (re_match_context_t *mctx) internal_function;
23static void match_ctx_free (re_match_context_t *cache) internal_function;
24static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node,
25 Idx str_idx, Idx from, Idx to)
26 internal_function;
27static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx)
28 internal_function;
29static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node,
30 Idx str_idx) internal_function;
31static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
32 Idx node, Idx str_idx)
33 internal_function;
34static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
35 re_dfastate_t **limited_sts, Idx last_node,
36 Idx last_str_idx)
37 internal_function;
38static reg_errcode_t re_search_internal (const regex_t *preg,
39 const char *string, Idx length,
40 Idx start, Idx last_start, Idx stop,
41 size_t nmatch, regmatch_t pmatch[],
42 int eflags) internal_function;
43static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp,
44 const char *string1, Idx length1,
45 const char *string2, Idx length2,
46 Idx start, regoff_t range,
47 struct re_registers *regs,
48 Idx stop, bool ret_len) internal_function;
49static regoff_t re_search_stub (struct re_pattern_buffer *bufp,
50 const char *string, Idx length, Idx start,
51 regoff_t range, Idx stop,
52 struct re_registers *regs,
53 bool ret_len) internal_function;
54static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
55 Idx nregs, int regs_allocated)
56 internal_function;
57static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)
58 internal_function;
59static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match,
60 Idx *p_match_first) internal_function;
61static Idx check_halt_state_context (const re_match_context_t *mctx,
62 const re_dfastate_t *state, Idx idx)
63 internal_function;
64static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
65 regmatch_t *prev_idx_match, Idx cur_node,
66 Idx cur_idx, Idx nmatch) internal_function;
67static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
68 Idx str_idx, Idx dest_node, Idx nregs,
69 regmatch_t *regs,
70 re_node_set *eps_via_nodes)
71 internal_function;
72static reg_errcode_t set_regs (const regex_t *preg,
73 const re_match_context_t *mctx,
74 size_t nmatch, regmatch_t *pmatch,
75 bool fl_backtrack) internal_function;
76static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
77 internal_function;
78
79#ifdef RE_ENABLE_I18N
80static int sift_states_iter_mb (const re_match_context_t *mctx,
81 re_sift_context_t *sctx,
82 Idx node_idx, Idx str_idx, Idx max_str_idx)
83 internal_function;
84#endif /* RE_ENABLE_I18N */
85static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
86 re_sift_context_t *sctx)
87 internal_function;
88static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
89 re_sift_context_t *sctx, Idx str_idx,
90 re_node_set *cur_dest)
91 internal_function;
92static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
93 re_sift_context_t *sctx,
94 Idx str_idx,
95 re_node_set *dest_nodes)
96 internal_function;
97static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
98 re_node_set *dest_nodes,
99 const re_node_set *candidates)
100 internal_function;
101static bool check_dst_limits (const re_match_context_t *mctx,
102 const re_node_set *limits,
103 Idx dst_node, Idx dst_idx, Idx src_node,
104 Idx src_idx) internal_function;
105static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
106 int boundaries, Idx subexp_idx,
107 Idx from_node, Idx bkref_idx)
108 internal_function;
109static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
110 Idx limit, Idx subexp_idx,
111 Idx node, Idx str_idx,
112 Idx bkref_idx) internal_function;
113static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
114 re_node_set *dest_nodes,
115 const re_node_set *candidates,
116 re_node_set *limits,
117 struct re_backref_cache_entry *bkref_ents,
118 Idx str_idx) internal_function;
119static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
120 re_sift_context_t *sctx,
121 Idx str_idx, const re_node_set *candidates)
122 internal_function;
123static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
124 re_dfastate_t **dst,
125 re_dfastate_t **src, Idx num)
126 internal_function;
127static re_dfastate_t *find_recover_state (reg_errcode_t *err,
128 re_match_context_t *mctx) internal_function;
129static re_dfastate_t *transit_state (reg_errcode_t *err,
130 re_match_context_t *mctx,
131 re_dfastate_t *state) internal_function;
132static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
133 re_match_context_t *mctx,
134 re_dfastate_t *next_state)
135 internal_function;
136static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
137 re_node_set *cur_nodes,
138 Idx str_idx) internal_function;
139#if 0
140static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
141 re_match_context_t *mctx,
142 re_dfastate_t *pstate)
143 internal_function;
144#endif
145#ifdef RE_ENABLE_I18N
146static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
147 re_dfastate_t *pstate)
148 internal_function;
149#endif /* RE_ENABLE_I18N */
150static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
151 const re_node_set *nodes)
152 internal_function;
153static reg_errcode_t get_subexp (re_match_context_t *mctx,
154 Idx bkref_node, Idx bkref_str_idx)
155 internal_function;
156static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
157 const re_sub_match_top_t *sub_top,
158 re_sub_match_last_t *sub_last,
159 Idx bkref_node, Idx bkref_str)
160 internal_function;
161static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
162 Idx subexp_idx, int type) internal_function;
163static reg_errcode_t check_arrival (re_match_context_t *mctx,
164 state_array_t *path, Idx top_node,
165 Idx top_str, Idx last_node, Idx last_str,
166 int type) internal_function;
167static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
168 Idx str_idx,
169 re_node_set *cur_nodes,
170 re_node_set *next_nodes)
171 internal_function;
172static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
173 re_node_set *cur_nodes,
174 Idx ex_subexp, int type)
175 internal_function;
176static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
177 re_node_set *dst_nodes,
178 Idx target, Idx ex_subexp,
179 int type) internal_function;
180static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
181 re_node_set *cur_nodes, Idx cur_str,
182 Idx subexp_num, int type)
183 internal_function;
184static bool build_trtable (const re_dfa_t *dfa,
185 re_dfastate_t *state) internal_function;
186#ifdef RE_ENABLE_I18N
187static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
188 const re_string_t *input, Idx idx)
189 internal_function;
190# ifdef _LIBC
191static unsigned int find_collation_sequence_value (const unsigned char *mbs,
192 size_t name_len)
193 internal_function;
194# endif /* _LIBC */
195#endif /* RE_ENABLE_I18N */
196static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa,
197 const re_dfastate_t *state,
198 re_node_set *states_node,
199 bitset_t *states_ch) internal_function;
200static bool check_node_accept (const re_match_context_t *mctx,
201 const re_token_t *node, Idx idx)
202 internal_function;
203static reg_errcode_t extend_buffers (re_match_context_t *mctx)
204 internal_function;
205
206/* Entry point for POSIX code. */
207
208/* regexec searches for a given pattern, specified by PREG, in the
209 string STRING.
210
211 If NMATCH is zero or REG_NOSUB was set in the cflags argument to
212 `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
213 least NMATCH elements, and we set them to the offsets of the
214 corresponding matched substrings.
215
216 EFLAGS specifies `execution flags' which affect matching: if
217 REG_NOTBOL is set, then ^ does not match at the beginning of the
218 string; if REG_NOTEOL is set, then $ does not match at the end.
219
220 We return 0 if we find a match and REG_NOMATCH if not. */
221
222int
223regexec (preg, string, nmatch, pmatch, eflags)
224 const regex_t *__restrict preg;
225 const char *__restrict string;
226 size_t nmatch;
227 regmatch_t pmatch[];
228 int eflags;
229{
230 reg_errcode_t err;
231 Idx start, length;
232#ifdef _LIBC
233 re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
234#endif
235
236 if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
237 return REG_BADPAT;
238
239 if (eflags & REG_STARTEND)
240 {
241 start = pmatch[0].rm_so;
242 length = pmatch[0].rm_eo;
243 }
244 else
245 {
246 start = 0;
247 length = strlen (string);
248 }
249
250 __libc_lock_lock (dfa->lock);
251 if (preg->no_sub)
252 err = re_search_internal (preg, string, length, start, length,
253 length, 0, NULL, eflags);
254 else
255 err = re_search_internal (preg, string, length, start, length,
256 length, nmatch, pmatch, eflags);
257 __libc_lock_unlock (dfa->lock);
258 return err != REG_NOERROR;
259}
260
261#ifdef _LIBC
262# include <shlib-compat.h>
263versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
264
265# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
266__typeof__ (__regexec) __compat_regexec;
267
268int
269attribute_compat_text_section
270__compat_regexec (const regex_t *__restrict preg,
271 const char *__restrict string, size_t nmatch,
272 regmatch_t pmatch[], int eflags)
273{
274 return regexec (preg, string, nmatch, pmatch,
275 eflags & (REG_NOTBOL | REG_NOTEOL));
276}
277compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
278# endif
279#endif
280
281/* Entry points for GNU code. */
282
283/* re_match, re_search, re_match_2, re_search_2
284
285 The former two functions operate on STRING with length LENGTH,
286 while the later two operate on concatenation of STRING1 and STRING2
287 with lengths LENGTH1 and LENGTH2, respectively.
288
289 re_match() matches the compiled pattern in BUFP against the string,
290 starting at index START.
291
292 re_search() first tries matching at index START, then it tries to match
293 starting from index START + 1, and so on. The last start position tried
294 is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same
295 way as re_match().)
296
297 The parameter STOP of re_{match,search}_2 specifies that no match exceeding
298 the first STOP characters of the concatenation of the strings should be
299 concerned.
300
301 If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
302 and all groups is stored in REGS. (For the "_2" variants, the offsets are
303 computed relative to the concatenation, not relative to the individual
304 strings.)
305
306 On success, re_match* functions return the length of the match, re_search*
307 return the position of the start of the match. Return value -1 means no
308 match was found and -2 indicates an internal error. */
309
310regoff_t
311re_match (bufp, string, length, start, regs)
312 struct re_pattern_buffer *bufp;
313 const char *string;
314 Idx length, start;
315 struct re_registers *regs;
316{
317 return re_search_stub (bufp, string, length, start, 0, length, regs, true);
318}
319#ifdef _LIBC
320weak_alias (__re_match, re_match)
321#endif
322
323regoff_t
324re_search (bufp, string, length, start, range, regs)
325 struct re_pattern_buffer *bufp;
326 const char *string;
327 Idx length, start;
328 regoff_t range;
329 struct re_registers *regs;
330{
331 return re_search_stub (bufp, string, length, start, range, length, regs,
332 false);
333}
334#ifdef _LIBC
335weak_alias (__re_search, re_search)
336#endif
337
338regoff_t
339re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)
340 struct re_pattern_buffer *bufp;
341 const char *string1, *string2;
342 Idx length1, length2, start, stop;
343 struct re_registers *regs;
344{
345 return re_search_2_stub (bufp, string1, length1, string2, length2,
346 start, 0, regs, stop, true);
347}
348#ifdef _LIBC
349weak_alias (__re_match_2, re_match_2)
350#endif
351
352regoff_t
353re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)
354 struct re_pattern_buffer *bufp;
355 const char *string1, *string2;
356 Idx length1, length2, start, stop;
357 regoff_t range;
358 struct re_registers *regs;
359{
360 return re_search_2_stub (bufp, string1, length1, string2, length2,
361 start, range, regs, stop, false);
362}
363#ifdef _LIBC
364weak_alias (__re_search_2, re_search_2)
365#endif
366
367static regoff_t
368internal_function
369re_search_2_stub (struct re_pattern_buffer *bufp,
370 const char *string1, Idx length1,
371 const char *string2, Idx length2,
372 Idx start, regoff_t range, struct re_registers *regs,
373 Idx stop, bool ret_len)
374{
375 const char *str;
376 regoff_t rval;
377 Idx len = length1 + length2;
378 char *s = NULL;
379
380 if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0))
381 return -2;
382
383 /* Concatenate the strings. */
384 if (length2 > 0)
385 if (length1 > 0)
386 {
387 s = re_malloc (char, len);
388
389 if (BE (s == NULL, 0))
390 return -2;
391#ifdef _LIBC
392 memcpy (__mempcpy (s, string1, length1), string2, length2);
393#else
394 memcpy (s, string1, length1);
395 memcpy (s + length1, string2, length2);
396#endif
397 str = s;
398 }
399 else
400 str = string2;
401 else
402 str = string1;
403
404 rval = re_search_stub (bufp, str, len, start, range, stop, regs,
405 ret_len);
406 re_free (s);
407 return rval;
408}
409
410/* The parameters have the same meaning as those of re_search.
411 Additional parameters:
412 If RET_LEN is true the length of the match is returned (re_match style);
413 otherwise the position of the match is returned. */
414
415static regoff_t
416internal_function
417re_search_stub (struct re_pattern_buffer *bufp,
418 const char *string, Idx length,
419 Idx start, regoff_t range, Idx stop, struct re_registers *regs,
420 bool ret_len)
421{
422 reg_errcode_t result;
423 regmatch_t *pmatch;
424 Idx nregs;
425 regoff_t rval;
426 int eflags = 0;
427#ifdef _LIBC
428 re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
429#endif
430 Idx last_start = start + range;
431
432 /* Check for out-of-range. */
433 if (BE (start < 0 || start > length, 0))
434 return -1;
435 if (BE (length < last_start || (0 <= range && last_start < start), 0))
436 last_start = length;
437 else if (BE (last_start < 0 || (range < 0 && start <= last_start), 0))
438 last_start = 0;
439
440 __libc_lock_lock (dfa->lock);
441
442 eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
443 eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
444
445 /* Compile fastmap if we haven't yet. */
446 if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate)
447 re_compile_fastmap (bufp);
448
449 if (BE (bufp->no_sub, 0))
450 regs = NULL;
451
452 /* We need at least 1 register. */
453 if (regs == NULL)
454 nregs = 1;
455 else if (BE (bufp->regs_allocated == REGS_FIXED
456 && regs->num_regs <= bufp->re_nsub, 0))
457 {
458 nregs = regs->num_regs;
459 if (BE (nregs < 1, 0))
460 {
461 /* Nothing can be copied to regs. */
462 regs = NULL;
463 nregs = 1;
464 }
465 }
466 else
467 nregs = bufp->re_nsub + 1;
468 pmatch = re_malloc (regmatch_t, nregs);
469 if (BE (pmatch == NULL, 0))
470 {
471 rval = -2;
472 goto out;
473 }
474
475 result = re_search_internal (bufp, string, length, start, last_start, stop,
476 nregs, pmatch, eflags);
477
478 rval = 0;
479
480 /* I hope we needn't fill ther regs with -1's when no match was found. */
481 if (result != REG_NOERROR)
482 rval = -1;
483 else if (regs != NULL)
484 {
485 /* If caller wants register contents data back, copy them. */
486 bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
487 bufp->regs_allocated);
488 if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
489 rval = -2;
490 }
491
492 if (BE (rval == 0, 1))
493 {
494 if (ret_len)
495 {
496 assert (pmatch[0].rm_so == start);
497 rval = pmatch[0].rm_eo - start;
498 }
499 else
500 rval = pmatch[0].rm_so;
501 }
502 re_free (pmatch);
503 out:
504 __libc_lock_unlock (dfa->lock);
505 return rval;
506}
507
508static unsigned int
509internal_function
510re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs,
511 int regs_allocated)
512{
513 int rval = REGS_REALLOCATE;
514 Idx i;
515 Idx need_regs = nregs + 1;
516 /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
517 uses. */
518
519 /* Have the register data arrays been allocated? */
520 if (regs_allocated == REGS_UNALLOCATED)
521 { /* No. So allocate them with malloc. */
522 regs->start = re_malloc (regoff_t, need_regs);
523 if (BE (regs->start == NULL, 0))
524 return REGS_UNALLOCATED;
525 regs->end = re_malloc (regoff_t, need_regs);
526 if (BE (regs->end == NULL, 0))
527 {
528 re_free (regs->start);
529 return REGS_UNALLOCATED;
530 }
531 regs->num_regs = need_regs;
532 }
533 else if (regs_allocated == REGS_REALLOCATE)
534 { /* Yes. If we need more elements than were already
535 allocated, reallocate them. If we need fewer, just
536 leave it alone. */
537 if (BE (need_regs > regs->num_regs, 0))
538 {
539 regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
540 regoff_t *new_end;
541 if (BE (new_start == NULL, 0))
542 return REGS_UNALLOCATED;
543 new_end = re_realloc (regs->end, regoff_t, need_regs);
544 if (BE (new_end == NULL, 0))
545 {
546 re_free (new_start);
547 return REGS_UNALLOCATED;
548 }
549 regs->start = new_start;
550 regs->end = new_end;
551 regs->num_regs = need_regs;
552 }
553 }
554 else
555 {
556 assert (regs_allocated == REGS_FIXED);
557 /* This function may not be called with REGS_FIXED and nregs too big. */
558 assert (regs->num_regs >= nregs);
559 rval = REGS_FIXED;
560 }
561
562 /* Copy the regs. */
563 for (i = 0; i < nregs; ++i)
564 {
565 regs->start[i] = pmatch[i].rm_so;
566 regs->end[i] = pmatch[i].rm_eo;
567 }
568 for ( ; i < regs->num_regs; ++i)
569 regs->start[i] = regs->end[i] = -1;
570
571 return rval;
572}
573
574/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
575 ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
576 this memory for recording register information. STARTS and ENDS
577 must be allocated using the malloc library routine, and must each
578 be at least NUM_REGS * sizeof (regoff_t) bytes long.
579
580 If NUM_REGS == 0, then subsequent matches should allocate their own
581 register data.
582
583 Unless this function is called, the first search or match using
584 PATTERN_BUFFER will allocate its own register data, without
585 freeing the old data. */
586
587void
588re_set_registers (bufp, regs, num_regs, starts, ends)
589 struct re_pattern_buffer *bufp;
590 struct re_registers *regs;
591 __re_size_t num_regs;
592 regoff_t *starts, *ends;
593{
594 if (num_regs)
595 {
596 bufp->regs_allocated = REGS_REALLOCATE;
597 regs->num_regs = num_regs;
598 regs->start = starts;
599 regs->end = ends;
600 }
601 else
602 {
603 bufp->regs_allocated = REGS_UNALLOCATED;
604 regs->num_regs = 0;
605 regs->start = regs->end = NULL;
606 }
607}
608#ifdef _LIBC
609weak_alias (__re_set_registers, re_set_registers)
610#endif
611
612/* Entry points compatible with 4.2 BSD regex library. We don't define
613 them unless specifically requested. */
614
615#if defined _REGEX_RE_COMP || defined _LIBC
616int
617# ifdef _LIBC
618weak_function
619# endif
620re_exec (s)
621 const char *s;
622{
623 return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
624}
625#endif /* _REGEX_RE_COMP */
626
627/* Internal entry point. */
628
629/* Searches for a compiled pattern PREG in the string STRING, whose
630 length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same
631 meaning as with regexec. LAST_START is START + RANGE, where
632 START and RANGE have the same meaning as with re_search.
633 Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
634 otherwise return the error code.
635 Note: We assume front end functions already check ranges.
636 (0 <= LAST_START && LAST_START <= LENGTH) */
637
638static reg_errcode_t
639internal_function
640re_search_internal (const regex_t *preg,
641 const char *string, Idx length,
642 Idx start, Idx last_start, Idx stop,
643 size_t nmatch, regmatch_t pmatch[],
644 int eflags)
645{
646 reg_errcode_t err;
647 const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
648 Idx left_lim, right_lim;
649 int incr;
650 bool fl_longest_match;
651 int match_kind;
652 Idx match_first;
653 Idx match_last = REG_MISSING;
654 Idx extra_nmatch;
655 bool sb;
656 int ch;
657#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
658 re_match_context_t mctx = { .dfa = dfa };
659#else
660 re_match_context_t mctx;
661#endif
662 char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
663 && start != last_start && !preg->can_be_null)
664 ? preg->fastmap : NULL);
665 RE_TRANSLATE_TYPE t = preg->translate;
666
667#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
668 memset (&mctx, '\0', sizeof (re_match_context_t));
669 mctx.dfa = dfa;
670#endif
671
672 extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
673 nmatch -= extra_nmatch;
674
675 /* Check if the DFA haven't been compiled. */
676 if (BE (preg->used == 0 || dfa->init_state == NULL
677 || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
678 || dfa->init_state_begbuf == NULL, 0))
679 return REG_NOMATCH;
680
681#ifdef DEBUG
682 /* We assume front-end functions already check them. */
683 assert (0 <= last_start && last_start <= length);
684#endif
685
686 /* If initial states with non-begbuf contexts have no elements,
687 the regex must be anchored. If preg->newline_anchor is set,
688 we'll never use init_state_nl, so do not check it. */
689 if (dfa->init_state->nodes.nelem == 0
690 && dfa->init_state_word->nodes.nelem == 0
691 && (dfa->init_state_nl->nodes.nelem == 0
692 || !preg->newline_anchor))
693 {
694 if (start != 0 && last_start != 0)
695 return REG_NOMATCH;
696 start = last_start = 0;
697 }
698
699 /* We must check the longest matching, if nmatch > 0. */
700 fl_longest_match = (nmatch != 0 || dfa->nbackref);
701
702 err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
703 preg->translate, preg->syntax & RE_ICASE, dfa);
704 if (BE (err != REG_NOERROR, 0))
705 goto free_return;
706 mctx.input.stop = stop;
707 mctx.input.raw_stop = stop;
708 mctx.input.newline_anchor = preg->newline_anchor;
709
710 err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
711 if (BE (err != REG_NOERROR, 0))
712 goto free_return;
713
714 /* We will log all the DFA states through which the dfa pass,
715 if nmatch > 1, or this dfa has "multibyte node", which is a
716 back-reference or a node which can accept multibyte character or
717 multi character collating element. */
718 if (nmatch > 1 || dfa->has_mb_node)
719 {
720 /* Avoid overflow. */
721 if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0))
722 {
723 err = REG_ESPACE;
724 goto free_return;
725 }
726
727 mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
728 if (BE (mctx.state_log == NULL, 0))
729 {
730 err = REG_ESPACE;
731 goto free_return;
732 }
733 }
734 else
735 mctx.state_log = NULL;
736
737 match_first = start;
738 mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
739 : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
740
741 /* Check incrementally whether of not the input string match. */
742 incr = (last_start < start) ? -1 : 1;
743 left_lim = (last_start < start) ? last_start : start;
744 right_lim = (last_start < start) ? start : last_start;
745 sb = dfa->mb_cur_max == 1;
746 match_kind =
747 (fastmap
748 ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
749 | (start <= last_start ? 2 : 0)
750 | (t != NULL ? 1 : 0))
751 : 8);
752
753 for (;; match_first += incr)
754 {
755 err = REG_NOMATCH;
756 if (match_first < left_lim || right_lim < match_first)
757 goto free_return;
758
759 /* Advance as rapidly as possible through the string, until we
760 find a plausible place to start matching. This may be done
761 with varying efficiency, so there are various possibilities:
762 only the most common of them are specialized, in order to
763 save on code size. We use a switch statement for speed. */
764 switch (match_kind)
765 {
766 case 8:
767 /* No fastmap. */
768 break;
769
770 case 7:
771 /* Fastmap with single-byte translation, match forward. */
772 while (BE (match_first < right_lim, 1)
773 && !fastmap[t[(unsigned char) string[match_first]]])
774 ++match_first;
775 goto forward_match_found_start_or_reached_end;
776
777 case 6:
778 /* Fastmap without translation, match forward. */
779 while (BE (match_first < right_lim, 1)
780 && !fastmap[(unsigned char) string[match_first]])
781 ++match_first;
782
783 forward_match_found_start_or_reached_end:
784 if (BE (match_first == right_lim, 0))
785 {
786 ch = match_first >= length
787 ? 0 : (unsigned char) string[match_first];
788 if (!fastmap[t ? t[ch] : ch])
789 goto free_return;
790 }
791 break;
792
793 case 4:
794 case 5:
795 /* Fastmap without multi-byte translation, match backwards. */
796 while (match_first >= left_lim)
797 {
798 ch = match_first >= length
799 ? 0 : (unsigned char) string[match_first];
800 if (fastmap[t ? t[ch] : ch])
801 break;
802 --match_first;
803 }
804 if (match_first < left_lim)
805 goto free_return;
806 break;
807
808 default:
809 /* In this case, we can't determine easily the current byte,
810 since it might be a component byte of a multibyte
811 character. Then we use the constructed buffer instead. */
812 for (;;)
813 {
814 /* If MATCH_FIRST is out of the valid range, reconstruct the
815 buffers. */
816 __re_size_t offset = match_first - mctx.input.raw_mbs_idx;
817 if (BE (offset >= (__re_size_t) mctx.input.valid_raw_len, 0))
818 {
819 err = re_string_reconstruct (&mctx.input, match_first,
820 eflags);
821 if (BE (err != REG_NOERROR, 0))
822 goto free_return;
823
824 offset = match_first - mctx.input.raw_mbs_idx;
825 }
826 /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
827 Note that MATCH_FIRST must not be smaller than 0. */
828 ch = (match_first >= length
829 ? 0 : re_string_byte_at (&mctx.input, offset));
830 if (fastmap[ch])
831 break;
832 match_first += incr;
833 if (match_first < left_lim || match_first > right_lim)
834 {
835 err = REG_NOMATCH;
836 goto free_return;
837 }
838 }
839 break;
840 }
841
842 /* Reconstruct the buffers so that the matcher can assume that
843 the matching starts from the beginning of the buffer. */
844 err = re_string_reconstruct (&mctx.input, match_first, eflags);
845 if (BE (err != REG_NOERROR, 0))
846 goto free_return;
847
848#ifdef RE_ENABLE_I18N
849 /* Don't consider this char as a possible match start if it part,
850 yet isn't the head, of a multibyte character. */
851 if (!sb && !re_string_first_byte (&mctx.input, 0))
852 continue;
853#endif
854
855 /* It seems to be appropriate one, then use the matcher. */
856 /* We assume that the matching starts from 0. */
857 mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
858 match_last = check_matching (&mctx, fl_longest_match,
859 start <= last_start ? &match_first : NULL);
860 if (match_last != REG_MISSING)
861 {
862 if (BE (match_last == REG_ERROR, 0))
863 {
864 err = REG_ESPACE;
865 goto free_return;
866 }
867 else
868 {
869 mctx.match_last = match_last;
870 if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
871 {
872 re_dfastate_t *pstate = mctx.state_log[match_last];
873 mctx.last_node = check_halt_state_context (&mctx, pstate,
874 match_last);
875 }
876 if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
877 || dfa->nbackref)
878 {
879 err = prune_impossible_nodes (&mctx);
880 if (err == REG_NOERROR)
881 break;
882 if (BE (err != REG_NOMATCH, 0))
883 goto free_return;
884 match_last = REG_MISSING;
885 }
886 else
887 break; /* We found a match. */
888 }
889 }
890
891 match_ctx_clean (&mctx);
892 }
893
894#ifdef DEBUG
895 assert (match_last != REG_MISSING);
896 assert (err == REG_NOERROR);
897#endif
898
899 /* Set pmatch[] if we need. */
900 if (nmatch > 0)
901 {
902 Idx reg_idx;
903
904 /* Initialize registers. */
905 for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
906 pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
907
908 /* Set the points where matching start/end. */
909 pmatch[0].rm_so = 0;
910 pmatch[0].rm_eo = mctx.match_last;
911 /* FIXME: This function should fail if mctx.match_last exceeds
912 the maximum possible regoff_t value. We need a new error
913 code REG_OVERFLOW. */
914
915 if (!preg->no_sub && nmatch > 1)
916 {
917 err = set_regs (preg, &mctx, nmatch, pmatch,
918 dfa->has_plural_match && dfa->nbackref > 0);
919 if (BE (err != REG_NOERROR, 0))
920 goto free_return;
921 }
922
923 /* At last, add the offset to the each registers, since we slided
924 the buffers so that we could assume that the matching starts
925 from 0. */
926 for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
927 if (pmatch[reg_idx].rm_so != -1)
928 {
929#ifdef RE_ENABLE_I18N
930 if (BE (mctx.input.offsets_needed != 0, 0))
931 {
932 pmatch[reg_idx].rm_so =
933 (pmatch[reg_idx].rm_so == mctx.input.valid_len
934 ? mctx.input.valid_raw_len
935 : mctx.input.offsets[pmatch[reg_idx].rm_so]);
936 pmatch[reg_idx].rm_eo =
937 (pmatch[reg_idx].rm_eo == mctx.input.valid_len
938 ? mctx.input.valid_raw_len
939 : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
940 }
941#else
942 assert (mctx.input.offsets_needed == 0);
943#endif
944 pmatch[reg_idx].rm_so += match_first;
945 pmatch[reg_idx].rm_eo += match_first;
946 }
947 for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
948 {
949 pmatch[nmatch + reg_idx].rm_so = -1;
950 pmatch[nmatch + reg_idx].rm_eo = -1;
951 }
952
953 if (dfa->subexp_map)
954 for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
955 if (dfa->subexp_map[reg_idx] != reg_idx)
956 {
957 pmatch[reg_idx + 1].rm_so
958 = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
959 pmatch[reg_idx + 1].rm_eo
960 = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
961 }
962 }
963
964 free_return:
965 re_free (mctx.state_log);
966 if (dfa->nbackref)
967 match_ctx_free (&mctx);
968 re_string_destruct (&mctx.input);
969 return err;
970}
971
972static reg_errcode_t
973internal_function
974prune_impossible_nodes (re_match_context_t *mctx)
975{
976 const re_dfa_t *const dfa = mctx->dfa;
977 Idx halt_node, match_last;
978 reg_errcode_t ret;
979 re_dfastate_t **sifted_states;
980 re_dfastate_t **lim_states = NULL;
981 re_sift_context_t sctx;
982#ifdef DEBUG
983 assert (mctx->state_log != NULL);
984#endif
985 match_last = mctx->match_last;
986 halt_node = mctx->last_node;
987
988 /* Avoid overflow. */
989 if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0))
990 return REG_ESPACE;
991
992 sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
993 if (BE (sifted_states == NULL, 0))
994 {
995 ret = REG_ESPACE;
996 goto free_return;
997 }
998 if (dfa->nbackref)
999 {
1000 lim_states = re_malloc (re_dfastate_t *, match_last + 1);
1001 if (BE (lim_states == NULL, 0))
1002 {
1003 ret = REG_ESPACE;
1004 goto free_return;
1005 }
1006 while (1)
1007 {
1008 memset (lim_states, '\0',
1009 sizeof (re_dfastate_t *) * (match_last + 1));
1010 sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
1011 match_last);
1012 ret = sift_states_backward (mctx, &sctx);
1013 re_node_set_free (&sctx.limits);
1014 if (BE (ret != REG_NOERROR, 0))
1015 goto free_return;
1016 if (sifted_states[0] != NULL || lim_states[0] != NULL)
1017 break;
1018 do
1019 {
1020 --match_last;
1021 if (! REG_VALID_INDEX (match_last))
1022 {
1023 ret = REG_NOMATCH;
1024 goto free_return;
1025 }
1026 } while (mctx->state_log[match_last] == NULL
1027 || !mctx->state_log[match_last]->halt);
1028 halt_node = check_halt_state_context (mctx,
1029 mctx->state_log[match_last],
1030 match_last);
1031 }
1032 ret = merge_state_array (dfa, sifted_states, lim_states,
1033 match_last + 1);
1034 re_free (lim_states);
1035 lim_states = NULL;
1036 if (BE (ret != REG_NOERROR, 0))
1037 goto free_return;
1038 }
1039 else
1040 {
1041 sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
1042 ret = sift_states_backward (mctx, &sctx);
1043 re_node_set_free (&sctx.limits);
1044 if (BE (ret != REG_NOERROR, 0))
1045 goto free_return;
1046 }
1047 re_free (mctx->state_log);
1048 mctx->state_log = sifted_states;
1049 sifted_states = NULL;
1050 mctx->last_node = halt_node;
1051 mctx->match_last = match_last;
1052 ret = REG_NOERROR;
1053 free_return:
1054 re_free (sifted_states);
1055 re_free (lim_states);
1056 return ret;
1057}
1058
1059/* Acquire an initial state and return it.
1060 We must select appropriate initial state depending on the context,
1061 since initial states may have constraints like "\<", "^", etc.. */
1062
1063static inline re_dfastate_t *
1064__attribute ((always_inline)) internal_function
1065acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
1066 Idx idx)
1067{
1068 const re_dfa_t *const dfa = mctx->dfa;
1069 if (dfa->init_state->has_constraint)
1070 {
1071 unsigned int context;
1072 context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
1073 if (IS_WORD_CONTEXT (context))
1074 return dfa->init_state_word;
1075 else if (IS_ORDINARY_CONTEXT (context))
1076 return dfa->init_state;
1077 else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
1078 return dfa->init_state_begbuf;
1079 else if (IS_NEWLINE_CONTEXT (context))
1080 return dfa->init_state_nl;
1081 else if (IS_BEGBUF_CONTEXT (context))
1082 {
1083 /* It is relatively rare case, then calculate on demand. */
1084 return re_acquire_state_context (err, dfa,
1085 dfa->init_state->entrance_nodes,
1086 context);
1087 }
1088 else
1089 /* Must not happen? */
1090 return dfa->init_state;
1091 }
1092 else
1093 return dfa->init_state;
1094}
1095
1096/* Check whether the regular expression match input string INPUT or not,
1097 and return the index where the matching end. Return REG_MISSING if
1098 there is no match, and return REG_ERROR in case of an error.
1099 FL_LONGEST_MATCH means we want the POSIX longest matching.
1100 If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
1101 next place where we may want to try matching.
1102 Note that the matcher assume that the maching starts from the current
1103 index of the buffer. */
1104
1105static Idx
1106internal_function
1107check_matching (re_match_context_t *mctx, bool fl_longest_match,
1108 Idx *p_match_first)
1109{
1110 const re_dfa_t *const dfa = mctx->dfa;
1111 reg_errcode_t err;
1112 Idx match = 0;
1113 Idx match_last = REG_MISSING;
1114 Idx cur_str_idx = re_string_cur_idx (&mctx->input);
1115 re_dfastate_t *cur_state;
1116 bool at_init_state = p_match_first != NULL;
1117 Idx next_start_idx = cur_str_idx;
1118
1119 err = REG_NOERROR;
1120 cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
1121 /* An initial state must not be NULL (invalid). */
1122 if (BE (cur_state == NULL, 0))
1123 {
1124 assert (err == REG_ESPACE);
1125 return REG_ERROR;
1126 }
1127
1128 if (mctx->state_log != NULL)
1129 {
1130 mctx->state_log[cur_str_idx] = cur_state;
1131
1132 /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
1133 later. E.g. Processing back references. */
1134 if (BE (dfa->nbackref, 0))
1135 {
1136 at_init_state = false;
1137 err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
1138 if (BE (err != REG_NOERROR, 0))
1139 return err;
1140
1141 if (cur_state->has_backref)
1142 {
1143 err = transit_state_bkref (mctx, &cur_state->nodes);
1144 if (BE (err != REG_NOERROR, 0))
1145 return err;
1146 }
1147 }
1148 }
1149
1150 /* If the RE accepts NULL string. */
1151 if (BE (cur_state->halt, 0))
1152 {
1153 if (!cur_state->has_constraint
1154 || check_halt_state_context (mctx, cur_state, cur_str_idx))
1155 {
1156 if (!fl_longest_match)
1157 return cur_str_idx;
1158 else
1159 {
1160 match_last = cur_str_idx;
1161 match = 1;
1162 }
1163 }
1164 }
1165
1166 while (!re_string_eoi (&mctx->input))
1167 {
1168 re_dfastate_t *old_state = cur_state;
1169 Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1;
1170
1171 if (BE (next_char_idx >= mctx->input.bufs_len, 0)
1172 || (BE (next_char_idx >= mctx->input.valid_len, 0)
1173 && mctx->input.valid_len < mctx->input.len))
1174 {
1175 err = extend_buffers (mctx);
1176 if (BE (err != REG_NOERROR, 0))
1177 {
1178 assert (err == REG_ESPACE);
1179 return REG_ERROR;
1180 }
1181 }
1182
1183 cur_state = transit_state (&err, mctx, cur_state);
1184 if (mctx->state_log != NULL)
1185 cur_state = merge_state_with_log (&err, mctx, cur_state);
1186
1187 if (cur_state == NULL)
1188 {
1189 /* Reached the invalid state or an error. Try to recover a valid
1190 state using the state log, if available and if we have not
1191 already found a valid (even if not the longest) match. */
1192 if (BE (err != REG_NOERROR, 0))
1193 return REG_ERROR;
1194
1195 if (mctx->state_log == NULL
1196 || (match && !fl_longest_match)
1197 || (cur_state = find_recover_state (&err, mctx)) == NULL)
1198 break;
1199 }
1200
1201 if (BE (at_init_state, 0))
1202 {
1203 if (old_state == cur_state)
1204 next_start_idx = next_char_idx;
1205 else
1206 at_init_state = false;
1207 }
1208
1209 if (cur_state->halt)
1210 {
1211 /* Reached a halt state.
1212 Check the halt state can satisfy the current context. */
1213 if (!cur_state->has_constraint
1214 || check_halt_state_context (mctx, cur_state,
1215 re_string_cur_idx (&mctx->input)))
1216 {
1217 /* We found an appropriate halt state. */
1218 match_last = re_string_cur_idx (&mctx->input);
1219 match = 1;
1220
1221 /* We found a match, do not modify match_first below. */
1222 p_match_first = NULL;
1223 if (!fl_longest_match)
1224 break;
1225 }
1226 }
1227 }
1228
1229 if (p_match_first)
1230 *p_match_first += next_start_idx;
1231
1232 return match_last;
1233}
1234
1235/* Check NODE match the current context. */
1236
1237static bool
1238internal_function
1239check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context)
1240{
1241 re_token_type_t type = dfa->nodes[node].type;
1242 unsigned int constraint = dfa->nodes[node].constraint;
1243 if (type != END_OF_RE)
1244 return false;
1245 if (!constraint)
1246 return true;
1247 if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
1248 return false;
1249 return true;
1250}
1251
1252/* Check the halt state STATE match the current context.
1253 Return 0 if not match, if the node, STATE has, is a halt node and
1254 match the context, return the node. */
1255
1256static Idx
1257internal_function
1258check_halt_state_context (const re_match_context_t *mctx,
1259 const re_dfastate_t *state, Idx idx)
1260{
1261 Idx i;
1262 unsigned int context;
1263#ifdef DEBUG
1264 assert (state->halt);
1265#endif
1266 context = re_string_context_at (&mctx->input, idx, mctx->eflags);
1267 for (i = 0; i < state->nodes.nelem; ++i)
1268 if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
1269 return state->nodes.elems[i];
1270 return 0;
1271}
1272
1273/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
1274 corresponding to the DFA).
1275 Return the destination node, and update EPS_VIA_NODES;
1276 return REG_MISSING in case of errors. */
1277
1278static Idx
1279internal_function
1280proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
1281 Idx *pidx, Idx node, re_node_set *eps_via_nodes,
1282 struct re_fail_stack_t *fs)
1283{
1284 const re_dfa_t *const dfa = mctx->dfa;
1285 Idx i;
1286 bool ok;
1287 if (IS_EPSILON_NODE (dfa->nodes[node].type))
1288 {
1289 re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
1290 re_node_set *edests = &dfa->edests[node];
1291 Idx dest_node;
1292 ok = re_node_set_insert (eps_via_nodes, node);
1293 if (BE (! ok, 0))
1294 return REG_ERROR;
1295 /* Pick up a valid destination, or return REG_MISSING if none
1296 is found. */
1297 for (dest_node = REG_MISSING, i = 0; i < edests->nelem; ++i)
1298 {
1299 Idx candidate = edests->elems[i];
1300 if (!re_node_set_contains (cur_nodes, candidate))
1301 continue;
1302 if (dest_node == REG_MISSING)
1303 dest_node = candidate;
1304
1305 else
1306 {
1307 /* In order to avoid infinite loop like "(a*)*", return the second
1308 epsilon-transition if the first was already considered. */
1309 if (re_node_set_contains (eps_via_nodes, dest_node))
1310 return candidate;
1311
1312 /* Otherwise, push the second epsilon-transition on the fail stack. */
1313 else if (fs != NULL
1314 && push_fail_stack (fs, *pidx, candidate, nregs, regs,
1315 eps_via_nodes))
1316 return REG_ERROR;
1317
1318 /* We know we are going to exit. */
1319 break;
1320 }
1321 }
1322 return dest_node;
1323 }
1324 else
1325 {
1326 Idx naccepted = 0;
1327 re_token_type_t type = dfa->nodes[node].type;
1328
1329#ifdef RE_ENABLE_I18N
1330 if (dfa->nodes[node].accept_mb)
1331 naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
1332 else
1333#endif /* RE_ENABLE_I18N */
1334 if (type == OP_BACK_REF)
1335 {
1336 Idx subexp_idx = dfa->nodes[node].opr.idx + 1;
1337 naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
1338 if (fs != NULL)
1339 {
1340 if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
1341 return REG_MISSING;
1342 else if (naccepted)
1343 {
1344 char *buf = (char *) re_string_get_buffer (&mctx->input);
1345 if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
1346 naccepted) != 0)
1347 return REG_MISSING;
1348 }
1349 }
1350
1351 if (naccepted == 0)
1352 {
1353 Idx dest_node;
1354 ok = re_node_set_insert (eps_via_nodes, node);
1355 if (BE (! ok, 0))
1356 return REG_ERROR;
1357 dest_node = dfa->edests[node].elems[0];
1358 if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
1359 dest_node))
1360 return dest_node;
1361 }
1362 }
1363
1364 if (naccepted != 0
1365 || check_node_accept (mctx, dfa->nodes + node, *pidx))
1366 {
1367 Idx dest_node = dfa->nexts[node];
1368 *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
1369 if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
1370 || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
1371 dest_node)))
1372 return REG_MISSING;
1373 re_node_set_empty (eps_via_nodes);
1374 return dest_node;
1375 }
1376 }
1377 return REG_MISSING;
1378}
1379
1380static reg_errcode_t
1381internal_function
1382push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
1383 Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
1384{
1385 reg_errcode_t err;
1386 Idx num = fs->num++;
1387 if (fs->num == fs->alloc)
1388 {
1389 struct re_fail_stack_ent_t *new_array;
1390 new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
1391 * fs->alloc * 2));
1392 if (new_array == NULL)
1393 return REG_ESPACE;
1394 fs->alloc *= 2;
1395 fs->stack = new_array;
1396 }
1397 fs->stack[num].idx = str_idx;
1398 fs->stack[num].node = dest_node;
1399 fs->stack[num].regs = re_malloc (regmatch_t, nregs);
1400 if (fs->stack[num].regs == NULL)
1401 return REG_ESPACE;
1402 memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
1403 err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
1404 return err;
1405}
1406
1407static Idx
1408internal_function
1409pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
1410 regmatch_t *regs, re_node_set *eps_via_nodes)
1411{
1412 Idx num = --fs->num;
1413 assert (REG_VALID_INDEX (num));
1414 *pidx = fs->stack[num].idx;
1415 memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
1416 re_node_set_free (eps_via_nodes);
1417 re_free (fs->stack[num].regs);
1418 *eps_via_nodes = fs->stack[num].eps_via_nodes;
1419 return fs->stack[num].node;
1420}
1421
1422/* Set the positions where the subexpressions are starts/ends to registers
1423 PMATCH.
1424 Note: We assume that pmatch[0] is already set, and
1425 pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */
1426
1427static reg_errcode_t
1428internal_function
1429set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
1430 regmatch_t *pmatch, bool fl_backtrack)
1431{
1432 const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
1433 Idx idx, cur_node;
1434 re_node_set eps_via_nodes;
1435 struct re_fail_stack_t *fs;
1436 struct re_fail_stack_t fs_body = { 0, 2, NULL };
1437 regmatch_t *prev_idx_match;
1438 bool prev_idx_match_malloced = false;
1439
1440#ifdef DEBUG
1441 assert (nmatch > 1);
1442 assert (mctx->state_log != NULL);
1443#endif
1444 if (fl_backtrack)
1445 {
1446 fs = &fs_body;
1447 fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
1448 if (fs->stack == NULL)
1449 return REG_ESPACE;
1450 }
1451 else
1452 fs = NULL;
1453
1454 cur_node = dfa->init_node;
1455 re_node_set_init_empty (&eps_via_nodes);
1456
1457 if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
1458 prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
1459 else
1460 {
1461 prev_idx_match = re_malloc (regmatch_t, nmatch);
1462 if (prev_idx_match == NULL)
1463 {
1464 free_fail_stack_return (fs);
1465 return REG_ESPACE;
1466 }
1467 prev_idx_match_malloced = true;
1468 }
1469 memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
1470
1471 for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
1472 {
1473 update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
1474
1475 if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
1476 {
1477 Idx reg_idx;
1478 if (fs)
1479 {
1480 for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
1481 if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
1482 break;
1483 if (reg_idx == nmatch)
1484 {
1485 re_node_set_free (&eps_via_nodes);
1486 if (prev_idx_match_malloced)
1487 re_free (prev_idx_match);
1488 return free_fail_stack_return (fs);
1489 }
1490 cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
1491 &eps_via_nodes);
1492 }
1493 else
1494 {
1495 re_node_set_free (&eps_via_nodes);
1496 if (prev_idx_match_malloced)
1497 re_free (prev_idx_match);
1498 return REG_NOERROR;
1499 }
1500 }
1501
1502 /* Proceed to next node. */
1503 cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
1504 &eps_via_nodes, fs);
1505
1506 if (BE (! REG_VALID_INDEX (cur_node), 0))
1507 {
1508 if (BE (cur_node == REG_ERROR, 0))
1509 {
1510 re_node_set_free (&eps_via_nodes);
1511 if (prev_idx_match_malloced)
1512 re_free (prev_idx_match);
1513 free_fail_stack_return (fs);
1514 return REG_ESPACE;
1515 }
1516 if (fs)
1517 cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
1518 &eps_via_nodes);
1519 else
1520 {
1521 re_node_set_free (&eps_via_nodes);
1522 if (prev_idx_match_malloced)
1523 re_free (prev_idx_match);
1524 return REG_NOMATCH;
1525 }
1526 }
1527 }
1528 re_node_set_free (&eps_via_nodes);
1529 if (prev_idx_match_malloced)
1530 re_free (prev_idx_match);
1531 return free_fail_stack_return (fs);
1532}
1533
1534static reg_errcode_t
1535internal_function
1536free_fail_stack_return (struct re_fail_stack_t *fs)
1537{
1538 if (fs)
1539 {
1540 Idx fs_idx;
1541 for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
1542 {
1543 re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
1544 re_free (fs->stack[fs_idx].regs);
1545 }
1546 re_free (fs->stack);
1547 }
1548 return REG_NOERROR;
1549}
1550
1551static void
1552internal_function
1553update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
1554 regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch)
1555{
1556 int type = dfa->nodes[cur_node].type;
1557 if (type == OP_OPEN_SUBEXP)
1558 {
1559 Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
1560
1561 /* We are at the first node of this sub expression. */
1562 if (reg_num < nmatch)
1563 {
1564 pmatch[reg_num].rm_so = cur_idx;
1565 pmatch[reg_num].rm_eo = -1;
1566 }
1567 }
1568 else if (type == OP_CLOSE_SUBEXP)
1569 {
1570 Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
1571 if (reg_num < nmatch)
1572 {
1573 /* We are at the last node of this sub expression. */
1574 if (pmatch[reg_num].rm_so < cur_idx)
1575 {
1576 pmatch[reg_num].rm_eo = cur_idx;
1577 /* This is a non-empty match or we are not inside an optional
1578 subexpression. Accept this right away. */
1579 memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
1580 }
1581 else
1582 {
1583 if (dfa->nodes[cur_node].opt_subexp
1584 && prev_idx_match[reg_num].rm_so != -1)
1585 /* We transited through an empty match for an optional
1586 subexpression, like (a?)*, and this is not the subexp's
1587 first match. Copy back the old content of the registers
1588 so that matches of an inner subexpression are undone as
1589 well, like in ((a?))*. */
1590 memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
1591 else
1592 /* We completed a subexpression, but it may be part of
1593 an optional one, so do not update PREV_IDX_MATCH. */
1594 pmatch[reg_num].rm_eo = cur_idx;
1595 }
1596 }
1597 }
1598}
1599
1600/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
1601 and sift the nodes in each states according to the following rules.
1602 Updated state_log will be wrote to STATE_LOG.
1603
1604 Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
1605 1. When STR_IDX == MATCH_LAST(the last index in the state_log):
1606 If `a' isn't the LAST_NODE and `a' can't epsilon transit to
1607 the LAST_NODE, we throw away the node `a'.
1608 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
1609 string `s' and transit to `b':
1610 i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
1611 away the node `a'.
1612 ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
1613 thrown away, we throw away the node `a'.
1614 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
1615 i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
1616 node `a'.
1617 ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
1618 we throw away the node `a'. */
1619
1620#define STATE_NODE_CONTAINS(state,node) \
1621 ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
1622
1623static reg_errcode_t
1624internal_function
1625sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
1626{
1627 reg_errcode_t err;
1628 int null_cnt = 0;
1629 Idx str_idx = sctx->last_str_idx;
1630 re_node_set cur_dest;
1631
1632#ifdef DEBUG
1633 assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
1634#endif
1635
1636 /* Build sifted state_log[str_idx]. It has the nodes which can epsilon
1637 transit to the last_node and the last_node itself. */
1638 err = re_node_set_init_1 (&cur_dest, sctx->last_node);
1639 if (BE (err != REG_NOERROR, 0))
1640 return err;
1641 err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
1642 if (BE (err != REG_NOERROR, 0))
1643 goto free_return;
1644
1645 /* Then check each states in the state_log. */
1646 while (str_idx > 0)
1647 {
1648 /* Update counters. */
1649 null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
1650 if (null_cnt > mctx->max_mb_elem_len)
1651 {
1652 memset (sctx->sifted_states, '\0',
1653 sizeof (re_dfastate_t *) * str_idx);
1654 re_node_set_free (&cur_dest);
1655 return REG_NOERROR;
1656 }
1657 re_node_set_empty (&cur_dest);
1658 --str_idx;
1659
1660 if (mctx->state_log[str_idx])
1661 {
1662 err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
1663 if (BE (err != REG_NOERROR, 0))
1664 goto free_return;
1665 }
1666
1667 /* Add all the nodes which satisfy the following conditions:
1668 - It can epsilon transit to a node in CUR_DEST.
1669 - It is in CUR_SRC.
1670 And update state_log. */
1671 err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
1672 if (BE (err != REG_NOERROR, 0))
1673 goto free_return;
1674 }
1675 err = REG_NOERROR;
1676 free_return:
1677 re_node_set_free (&cur_dest);
1678 return err;
1679}
1680
1681static reg_errcode_t
1682internal_function
1683build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
1684 Idx str_idx, re_node_set *cur_dest)
1685{
1686 const re_dfa_t *const dfa = mctx->dfa;
1687 const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
1688 Idx i;
1689
1690 /* Then build the next sifted state.
1691 We build the next sifted state on `cur_dest', and update
1692 `sifted_states[str_idx]' with `cur_dest'.
1693 Note:
1694 `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
1695 `cur_src' points the node_set of the old `state_log[str_idx]'
1696 (with the epsilon nodes pre-filtered out). */
1697 for (i = 0; i < cur_src->nelem; i++)
1698 {
1699 Idx prev_node = cur_src->elems[i];
1700 int naccepted = 0;
1701 bool ok;
1702
1703#ifdef DEBUG
1704 re_token_type_t type = dfa->nodes[prev_node].type;
1705 assert (!IS_EPSILON_NODE (type));
1706#endif
1707#ifdef RE_ENABLE_I18N
1708 /* If the node may accept `multi byte'. */
1709 if (dfa->nodes[prev_node].accept_mb)
1710 naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
1711 str_idx, sctx->last_str_idx);
1712#endif /* RE_ENABLE_I18N */
1713
1714 /* We don't check backreferences here.
1715 See update_cur_sifted_state(). */
1716 if (!naccepted
1717 && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
1718 && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
1719 dfa->nexts[prev_node]))
1720 naccepted = 1;
1721
1722 if (naccepted == 0)
1723 continue;
1724
1725 if (sctx->limits.nelem)
1726 {
1727 Idx to_idx = str_idx + naccepted;
1728 if (check_dst_limits (mctx, &sctx->limits,
1729 dfa->nexts[prev_node], to_idx,
1730 prev_node, str_idx))
1731 continue;
1732 }
1733 ok = re_node_set_insert (cur_dest, prev_node);
1734 if (BE (! ok, 0))
1735 return REG_ESPACE;
1736 }
1737
1738 return REG_NOERROR;
1739}
1740
1741/* Helper functions. */
1742
1743static reg_errcode_t
1744internal_function
1745clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx)
1746{
1747 Idx top = mctx->state_log_top;
1748
1749 if (next_state_log_idx >= mctx->input.bufs_len
1750 || (next_state_log_idx >= mctx->input.valid_len
1751 && mctx->input.valid_len < mctx->input.len))
1752 {
1753 reg_errcode_t err;
1754 err = extend_buffers (mctx);
1755 if (BE (err != REG_NOERROR, 0))
1756 return err;
1757 }
1758
1759 if (top < next_state_log_idx)
1760 {
1761 memset (mctx->state_log + top + 1, '\0',
1762 sizeof (re_dfastate_t *) * (next_state_log_idx - top));
1763 mctx->state_log_top = next_state_log_idx;
1764 }
1765 return REG_NOERROR;
1766}
1767
1768static reg_errcode_t
1769internal_function
1770merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
1771 re_dfastate_t **src, Idx num)
1772{
1773 Idx st_idx;
1774 reg_errcode_t err;
1775 for (st_idx = 0; st_idx < num; ++st_idx)
1776 {
1777 if (dst[st_idx] == NULL)
1778 dst[st_idx] = src[st_idx];
1779 else if (src[st_idx] != NULL)
1780 {
1781 re_node_set merged_set;
1782 err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
1783 &src[st_idx]->nodes);
1784 if (BE (err != REG_NOERROR, 0))
1785 return err;
1786 dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
1787 re_node_set_free (&merged_set);
1788 if (BE (err != REG_NOERROR, 0))
1789 return err;
1790 }
1791 }
1792 return REG_NOERROR;
1793}
1794
1795static reg_errcode_t
1796internal_function
1797update_cur_sifted_state (const re_match_context_t *mctx,
1798 re_sift_context_t *sctx, Idx str_idx,
1799 re_node_set *dest_nodes)
1800{
1801 const re_dfa_t *const dfa = mctx->dfa;
1802 reg_errcode_t err = REG_NOERROR;
1803 const re_node_set *candidates;
1804 candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
1805 : &mctx->state_log[str_idx]->nodes);
1806
1807 if (dest_nodes->nelem == 0)
1808 sctx->sifted_states[str_idx] = NULL;
1809 else
1810 {
1811 if (candidates)
1812 {
1813 /* At first, add the nodes which can epsilon transit to a node in
1814 DEST_NODE. */
1815 err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
1816 if (BE (err != REG_NOERROR, 0))
1817 return err;
1818
1819 /* Then, check the limitations in the current sift_context. */
1820 if (sctx->limits.nelem)
1821 {
1822 err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
1823 mctx->bkref_ents, str_idx);
1824 if (BE (err != REG_NOERROR, 0))
1825 return err;
1826 }
1827 }
1828
1829 sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
1830 if (BE (err != REG_NOERROR, 0))
1831 return err;
1832 }
1833
1834 if (candidates && mctx->state_log[str_idx]->has_backref)
1835 {
1836 err = sift_states_bkref (mctx, sctx, str_idx, candidates);
1837 if (BE (err != REG_NOERROR, 0))
1838 return err;
1839 }
1840 return REG_NOERROR;
1841}
1842
1843static reg_errcode_t
1844internal_function
1845add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
1846 const re_node_set *candidates)
1847{
1848 reg_errcode_t err = REG_NOERROR;
1849 Idx i;
1850
1851 re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
1852 if (BE (err != REG_NOERROR, 0))
1853 return err;
1854
1855 if (!state->inveclosure.alloc)
1856 {
1857 err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
1858 if (BE (err != REG_NOERROR, 0))
1859 return REG_ESPACE;
1860 for (i = 0; i < dest_nodes->nelem; i++)
1861 re_node_set_merge (&state->inveclosure,
1862 dfa->inveclosures + dest_nodes->elems[i]);
1863 }
1864 return re_node_set_add_intersect (dest_nodes, candidates,
1865 &state->inveclosure);
1866}
1867
1868static reg_errcode_t
1869internal_function
1870sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes,
1871 const re_node_set *candidates)
1872{
1873 Idx ecl_idx;
1874 reg_errcode_t err;
1875 re_node_set *inv_eclosure = dfa->inveclosures + node;
1876 re_node_set except_nodes;
1877 re_node_set_init_empty (&except_nodes);
1878 for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
1879 {
1880 Idx cur_node = inv_eclosure->elems[ecl_idx];
1881 if (cur_node == node)
1882 continue;
1883 if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
1884 {
1885 Idx edst1 = dfa->edests[cur_node].elems[0];
1886 Idx edst2 = ((dfa->edests[cur_node].nelem > 1)
1887 ? dfa->edests[cur_node].elems[1] : REG_MISSING);
1888 if ((!re_node_set_contains (inv_eclosure, edst1)
1889 && re_node_set_contains (dest_nodes, edst1))
1890 || (REG_VALID_NONZERO_INDEX (edst2)
1891 && !re_node_set_contains (inv_eclosure, edst2)
1892 && re_node_set_contains (dest_nodes, edst2)))
1893 {
1894 err = re_node_set_add_intersect (&except_nodes, candidates,
1895 dfa->inveclosures + cur_node);
1896 if (BE (err != REG_NOERROR, 0))
1897 {
1898 re_node_set_free (&except_nodes);
1899 return err;
1900 }
1901 }
1902 }
1903 }
1904 for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
1905 {
1906 Idx cur_node = inv_eclosure->elems[ecl_idx];
1907 if (!re_node_set_contains (&except_nodes, cur_node))
1908 {
1909 Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1;
1910 re_node_set_remove_at (dest_nodes, idx);
1911 }
1912 }
1913 re_node_set_free (&except_nodes);
1914 return REG_NOERROR;
1915}
1916
1917static bool
1918internal_function
1919check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits,
1920 Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx)
1921{
1922 const re_dfa_t *const dfa = mctx->dfa;
1923 Idx lim_idx, src_pos, dst_pos;
1924
1925 Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
1926 Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
1927 for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
1928 {
1929 Idx subexp_idx;
1930 struct re_backref_cache_entry *ent;
1931 ent = mctx->bkref_ents + limits->elems[lim_idx];
1932 subexp_idx = dfa->nodes[ent->node].opr.idx;
1933
1934 dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
1935 subexp_idx, dst_node, dst_idx,
1936 dst_bkref_idx);
1937 src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
1938 subexp_idx, src_node, src_idx,
1939 src_bkref_idx);
1940
1941 /* In case of:
1942 <src> <dst> ( <subexp> )
1943 ( <subexp> ) <src> <dst>
1944 ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */
1945 if (src_pos == dst_pos)
1946 continue; /* This is unrelated limitation. */
1947 else
1948 return true;
1949 }
1950 return false;
1951}
1952
1953static int
1954internal_function
1955check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
1956 Idx subexp_idx, Idx from_node, Idx bkref_idx)
1957{
1958 const re_dfa_t *const dfa = mctx->dfa;
1959 const re_node_set *eclosures = dfa->eclosures + from_node;
1960 Idx node_idx;
1961
1962 /* Else, we are on the boundary: examine the nodes on the epsilon
1963 closure. */
1964 for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
1965 {
1966 Idx node = eclosures->elems[node_idx];
1967 switch (dfa->nodes[node].type)
1968 {
1969 case OP_BACK_REF:
1970 if (bkref_idx != REG_MISSING)
1971 {
1972 struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
1973 do
1974 {
1975 Idx dst;
1976 int cpos;
1977
1978 if (ent->node != node)
1979 continue;
1980
1981 if (subexp_idx < BITSET_WORD_BITS
1982 && !(ent->eps_reachable_subexps_map
1983 & ((bitset_word_t) 1 << subexp_idx)))
1984 continue;
1985
1986 /* Recurse trying to reach the OP_OPEN_SUBEXP and
1987 OP_CLOSE_SUBEXP cases below. But, if the
1988 destination node is the same node as the source
1989 node, don't recurse because it would cause an
1990 infinite loop: a regex that exhibits this behavior
1991 is ()\1*\1* */
1992 dst = dfa->edests[node].elems[0];
1993 if (dst == from_node)
1994 {
1995 if (boundaries & 1)
1996 return -1;
1997 else /* if (boundaries & 2) */
1998 return 0;
1999 }
2000
2001 cpos =
2002 check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
2003 dst, bkref_idx);
2004 if (cpos == -1 /* && (boundaries & 1) */)
2005 return -1;
2006 if (cpos == 0 && (boundaries & 2))
2007 return 0;
2008
2009 if (subexp_idx < BITSET_WORD_BITS)
2010 ent->eps_reachable_subexps_map
2011 &= ~((bitset_word_t) 1 << subexp_idx);
2012 }
2013 while (ent++->more);
2014 }
2015 break;
2016
2017 case OP_OPEN_SUBEXP:
2018 if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
2019 return -1;
2020 break;
2021
2022 case OP_CLOSE_SUBEXP:
2023 if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
2024 return 0;
2025 break;
2026
2027 default:
2028 break;
2029 }
2030 }
2031
2032 return (boundaries & 2) ? 1 : 0;
2033}
2034
2035static int
2036internal_function
2037check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit,
2038 Idx subexp_idx, Idx from_node, Idx str_idx,
2039 Idx bkref_idx)
2040{
2041 struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
2042 int boundaries;
2043
2044 /* If we are outside the range of the subexpression, return -1 or 1. */
2045 if (str_idx < lim->subexp_from)
2046 return -1;
2047
2048 if (lim->subexp_to < str_idx)
2049 return 1;
2050
2051 /* If we are within the subexpression, return 0. */
2052 boundaries = (str_idx == lim->subexp_from);
2053 boundaries |= (str_idx == lim->subexp_to) << 1;
2054 if (boundaries == 0)
2055 return 0;
2056
2057 /* Else, examine epsilon closure. */
2058 return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
2059 from_node, bkref_idx);
2060}
2061
2062/* Check the limitations of sub expressions LIMITS, and remove the nodes
2063 which are against limitations from DEST_NODES. */
2064
2065static reg_errcode_t
2066internal_function
2067check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
2068 const re_node_set *candidates, re_node_set *limits,
2069 struct re_backref_cache_entry *bkref_ents, Idx str_idx)
2070{
2071 reg_errcode_t err;
2072 Idx node_idx, lim_idx;
2073
2074 for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
2075 {
2076 Idx subexp_idx;
2077 struct re_backref_cache_entry *ent;
2078 ent = bkref_ents + limits->elems[lim_idx];
2079
2080 if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
2081 continue; /* This is unrelated limitation. */
2082
2083 subexp_idx = dfa->nodes[ent->node].opr.idx;
2084 if (ent->subexp_to == str_idx)
2085 {
2086 Idx ops_node = REG_MISSING;
2087 Idx cls_node = REG_MISSING;
2088 for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
2089 {
2090 Idx node = dest_nodes->elems[node_idx];
2091 re_token_type_t type = dfa->nodes[node].type;
2092 if (type == OP_OPEN_SUBEXP
2093 && subexp_idx == dfa->nodes[node].opr.idx)
2094 ops_node = node;
2095 else if (type == OP_CLOSE_SUBEXP
2096 && subexp_idx == dfa->nodes[node].opr.idx)
2097 cls_node = node;
2098 }
2099
2100 /* Check the limitation of the open subexpression. */
2101 /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */
2102 if (REG_VALID_INDEX (ops_node))
2103 {
2104 err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
2105 candidates);
2106 if (BE (err != REG_NOERROR, 0))
2107 return err;
2108 }
2109
2110 /* Check the limitation of the close subexpression. */
2111 if (REG_VALID_INDEX (cls_node))
2112 for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
2113 {
2114 Idx node = dest_nodes->elems[node_idx];
2115 if (!re_node_set_contains (dfa->inveclosures + node,
2116 cls_node)
2117 && !re_node_set_contains (dfa->eclosures + node,
2118 cls_node))
2119 {
2120 /* It is against this limitation.
2121 Remove it form the current sifted state. */
2122 err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
2123 candidates);
2124 if (BE (err != REG_NOERROR, 0))
2125 return err;
2126 --node_idx;
2127 }
2128 }
2129 }
2130 else /* (ent->subexp_to != str_idx) */
2131 {
2132 for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
2133 {
2134 Idx node = dest_nodes->elems[node_idx];
2135 re_token_type_t type = dfa->nodes[node].type;
2136 if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
2137 {
2138 if (subexp_idx != dfa->nodes[node].opr.idx)
2139 continue;
2140 /* It is against this limitation.
2141 Remove it form the current sifted state. */
2142 err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
2143 candidates);
2144 if (BE (err != REG_NOERROR, 0))
2145 return err;
2146 }
2147 }
2148 }
2149 }
2150 return REG_NOERROR;
2151}
2152
2153static reg_errcode_t
2154internal_function
2155sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
2156 Idx str_idx, const re_node_set *candidates)
2157{
2158 const re_dfa_t *const dfa = mctx->dfa;
2159 reg_errcode_t err;
2160 Idx node_idx, node;
2161 re_sift_context_t local_sctx;
2162 Idx first_idx = search_cur_bkref_entry (mctx, str_idx);
2163
2164 if (first_idx == REG_MISSING)
2165 return REG_NOERROR;
2166
2167 local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */
2168
2169 for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
2170 {
2171 Idx enabled_idx;
2172 re_token_type_t type;
2173 struct re_backref_cache_entry *entry;
2174 node = candidates->elems[node_idx];
2175 type = dfa->nodes[node].type;
2176 /* Avoid infinite loop for the REs like "()\1+". */
2177 if (node == sctx->last_node && str_idx == sctx->last_str_idx)
2178 continue;
2179 if (type != OP_BACK_REF)
2180 continue;
2181
2182 entry = mctx->bkref_ents + first_idx;
2183 enabled_idx = first_idx;
2184 do
2185 {
2186 Idx subexp_len;
2187 Idx to_idx;
2188 Idx dst_node;
2189 bool ok;
2190 re_dfastate_t *cur_state;
2191
2192 if (entry->node != node)
2193 continue;
2194 subexp_len = entry->subexp_to - entry->subexp_from;
2195 to_idx = str_idx + subexp_len;
2196 dst_node = (subexp_len ? dfa->nexts[node]
2197 : dfa->edests[node].elems[0]);
2198
2199 if (to_idx > sctx->last_str_idx
2200 || sctx->sifted_states[to_idx] == NULL
2201 || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
2202 || check_dst_limits (mctx, &sctx->limits, node,
2203 str_idx, dst_node, to_idx))
2204 continue;
2205
2206 if (local_sctx.sifted_states == NULL)
2207 {
2208 local_sctx = *sctx;
2209 err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
2210 if (BE (err != REG_NOERROR, 0))
2211 goto free_return;
2212 }
2213 local_sctx.last_node = node;
2214 local_sctx.last_str_idx = str_idx;
2215 ok = re_node_set_insert (&local_sctx.limits, enabled_idx);
2216 if (BE (! ok, 0))
2217 {
2218 err = REG_ESPACE;
2219 goto free_return;
2220 }
2221 cur_state = local_sctx.sifted_states[str_idx];
2222 err = sift_states_backward (mctx, &local_sctx);
2223 if (BE (err != REG_NOERROR, 0))
2224 goto free_return;
2225 if (sctx->limited_states != NULL)
2226 {
2227 err = merge_state_array (dfa, sctx->limited_states,
2228 local_sctx.sifted_states,
2229 str_idx + 1);
2230 if (BE (err != REG_NOERROR, 0))
2231 goto free_return;
2232 }
2233 local_sctx.sifted_states[str_idx] = cur_state;
2234 re_node_set_remove (&local_sctx.limits, enabled_idx);
2235
2236 /* mctx->bkref_ents may have changed, reload the pointer. */
2237 entry = mctx->bkref_ents + enabled_idx;
2238 }
2239 while (enabled_idx++, entry++->more);
2240 }
2241 err = REG_NOERROR;
2242 free_return:
2243 if (local_sctx.sifted_states != NULL)
2244 {
2245 re_node_set_free (&local_sctx.limits);
2246 }
2247
2248 return err;
2249}
2250
2251
2252#ifdef RE_ENABLE_I18N
2253static int
2254internal_function
2255sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
2256 Idx node_idx, Idx str_idx, Idx max_str_idx)
2257{
2258 const re_dfa_t *const dfa = mctx->dfa;
2259 int naccepted;
2260 /* Check the node can accept `multi byte'. */
2261 naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
2262 if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
2263 !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
2264 dfa->nexts[node_idx]))
2265 /* The node can't accept the `multi byte', or the
2266 destination was already thrown away, then the node
2267 could't accept the current input `multi byte'. */
2268 naccepted = 0;
2269 /* Otherwise, it is sure that the node could accept
2270 `naccepted' bytes input. */
2271 return naccepted;
2272}
2273#endif /* RE_ENABLE_I18N */
2274
2275
2276/* Functions for state transition. */
2277
2278/* Return the next state to which the current state STATE will transit by
2279 accepting the current input byte, and update STATE_LOG if necessary.
2280 If STATE can accept a multibyte char/collating element/back reference
2281 update the destination of STATE_LOG. */
2282
2283static re_dfastate_t *
2284internal_function
2285transit_state (reg_errcode_t *err, re_match_context_t *mctx,
2286 re_dfastate_t *state)
2287{
2288 re_dfastate_t **trtable;
2289 unsigned char ch;
2290
2291#ifdef RE_ENABLE_I18N
2292 /* If the current state can accept multibyte. */
2293 if (BE (state->accept_mb, 0))
2294 {
2295 *err = transit_state_mb (mctx, state);
2296 if (BE (*err != REG_NOERROR, 0))
2297 return NULL;
2298 }
2299#endif /* RE_ENABLE_I18N */
2300
2301 /* Then decide the next state with the single byte. */
2302#if 0
2303 if (0)
2304 /* don't use transition table */
2305 return transit_state_sb (err, mctx, state);
2306#endif
2307
2308 /* Use transition table */
2309 ch = re_string_fetch_byte (&mctx->input);
2310 for (;;)
2311 {
2312 trtable = state->trtable;
2313 if (BE (trtable != NULL, 1))
2314 return trtable[ch];
2315
2316 trtable = state->word_trtable;
2317 if (BE (trtable != NULL, 1))
2318 {
2319 unsigned int context;
2320 context
2321 = re_string_context_at (&mctx->input,
2322 re_string_cur_idx (&mctx->input) - 1,
2323 mctx->eflags);
2324 if (IS_WORD_CONTEXT (context))
2325 return trtable[ch + SBC_MAX];
2326 else
2327 return trtable[ch];
2328 }
2329
2330 if (!build_trtable (mctx->dfa, state))
2331 {
2332 *err = REG_ESPACE;
2333 return NULL;
2334 }
2335
2336 /* Retry, we now have a transition table. */
2337 }
2338}
2339
2340/* Update the state_log if we need */
2341re_dfastate_t *
2342internal_function
2343merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
2344 re_dfastate_t *next_state)
2345{
2346 const re_dfa_t *const dfa = mctx->dfa;
2347 Idx cur_idx = re_string_cur_idx (&mctx->input);
2348
2349 if (cur_idx > mctx->state_log_top)
2350 {
2351 mctx->state_log[cur_idx] = next_state;
2352 mctx->state_log_top = cur_idx;
2353 }
2354 else if (mctx->state_log[cur_idx] == 0)
2355 {
2356 mctx->state_log[cur_idx] = next_state;
2357 }
2358 else
2359 {
2360 re_dfastate_t *pstate;
2361 unsigned int context;
2362 re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
2363 /* If (state_log[cur_idx] != 0), it implies that cur_idx is
2364 the destination of a multibyte char/collating element/
2365 back reference. Then the next state is the union set of
2366 these destinations and the results of the transition table. */
2367 pstate = mctx->state_log[cur_idx];
2368 log_nodes = pstate->entrance_nodes;
2369 if (next_state != NULL)
2370 {
2371 table_nodes = next_state->entrance_nodes;
2372 *err = re_node_set_init_union (&next_nodes, table_nodes,
2373 log_nodes);
2374 if (BE (*err != REG_NOERROR, 0))
2375 return NULL;
2376 }
2377 else
2378 next_nodes = *log_nodes;
2379 /* Note: We already add the nodes of the initial state,
2380 then we don't need to add them here. */
2381
2382 context = re_string_context_at (&mctx->input,
2383 re_string_cur_idx (&mctx->input) - 1,
2384 mctx->eflags);
2385 next_state = mctx->state_log[cur_idx]
2386 = re_acquire_state_context (err, dfa, &next_nodes, context);
2387 /* We don't need to check errors here, since the return value of
2388 this function is next_state and ERR is already set. */
2389
2390 if (table_nodes != NULL)
2391 re_node_set_free (&next_nodes);
2392 }
2393
2394 if (BE (dfa->nbackref, 0) && next_state != NULL)
2395 {
2396 /* Check OP_OPEN_SUBEXP in the current state in case that we use them
2397 later. We must check them here, since the back references in the
2398 next state might use them. */
2399 *err = check_subexp_matching_top (mctx, &next_state->nodes,
2400 cur_idx);
2401 if (BE (*err != REG_NOERROR, 0))
2402 return NULL;
2403
2404 /* If the next state has back references. */
2405 if (next_state->has_backref)
2406 {
2407 *err = transit_state_bkref (mctx, &next_state->nodes);
2408 if (BE (*err != REG_NOERROR, 0))
2409 return NULL;
2410 next_state = mctx->state_log[cur_idx];
2411 }
2412 }
2413
2414 return next_state;
2415}
2416
2417/* Skip bytes in the input that correspond to part of a
2418 multi-byte match, then look in the log for a state
2419 from which to restart matching. */
2420static re_dfastate_t *
2421internal_function
2422find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
2423{
2424 re_dfastate_t *cur_state;
2425 do
2426 {
2427 Idx max = mctx->state_log_top;
2428 Idx cur_str_idx = re_string_cur_idx (&mctx->input);
2429
2430 do
2431 {
2432 if (++cur_str_idx > max)
2433 return NULL;
2434 re_string_skip_bytes (&mctx->input, 1);
2435 }
2436 while (mctx->state_log[cur_str_idx] == NULL);
2437
2438 cur_state = merge_state_with_log (err, mctx, NULL);
2439 }
2440 while (*err == REG_NOERROR && cur_state == NULL);
2441 return cur_state;
2442}
2443
2444/* Helper functions for transit_state. */
2445
2446/* From the node set CUR_NODES, pick up the nodes whose types are
2447 OP_OPEN_SUBEXP and which have corresponding back references in the regular
2448 expression. And register them to use them later for evaluating the
2449 correspoding back references. */
2450
2451static reg_errcode_t
2452internal_function
2453check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
2454 Idx str_idx)
2455{
2456 const re_dfa_t *const dfa = mctx->dfa;
2457 Idx node_idx;
2458 reg_errcode_t err;
2459
2460 /* TODO: This isn't efficient.
2461 Because there might be more than one nodes whose types are
2462 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
2463 nodes.
2464 E.g. RE: (a){2} */
2465 for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
2466 {
2467 Idx node = cur_nodes->elems[node_idx];
2468 if (dfa->nodes[node].type == OP_OPEN_SUBEXP
2469 && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
2470 && (dfa->used_bkref_map
2471 & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
2472 {
2473 err = match_ctx_add_subtop (mctx, node, str_idx);
2474 if (BE (err != REG_NOERROR, 0))
2475 return err;
2476 }
2477 }
2478 return REG_NOERROR;
2479}
2480
2481#if 0
2482/* Return the next state to which the current state STATE will transit by
2483 accepting the current input byte. */
2484
2485static re_dfastate_t *
2486transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
2487 re_dfastate_t *state)
2488{
2489 const re_dfa_t *const dfa = mctx->dfa;
2490 re_node_set next_nodes;
2491 re_dfastate_t *next_state;
2492 Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
2493 unsigned int context;
2494
2495 *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
2496 if (BE (*err != REG_NOERROR, 0))
2497 return NULL;
2498 for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
2499 {
2500 Idx cur_node = state->nodes.elems[node_cnt];
2501 if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
2502 {
2503 *err = re_node_set_merge (&next_nodes,
2504 dfa->eclosures + dfa->nexts[cur_node]);
2505 if (BE (*err != REG_NOERROR, 0))
2506 {
2507 re_node_set_free (&next_nodes);
2508 return NULL;
2509 }
2510 }
2511 }
2512 context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
2513 next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
2514 /* We don't need to check errors here, since the return value of
2515 this function is next_state and ERR is already set. */
2516
2517 re_node_set_free (&next_nodes);
2518 re_string_skip_bytes (&mctx->input, 1);
2519 return next_state;
2520}
2521#endif
2522
2523#ifdef RE_ENABLE_I18N
2524static reg_errcode_t
2525internal_function
2526transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
2527{
2528 const re_dfa_t *const dfa = mctx->dfa;
2529 reg_errcode_t err;
2530 Idx i;
2531
2532 for (i = 0; i < pstate->nodes.nelem; ++i)
2533 {
2534 re_node_set dest_nodes, *new_nodes;
2535 Idx cur_node_idx = pstate->nodes.elems[i];
2536 int naccepted;
2537 Idx dest_idx;
2538 unsigned int context;
2539 re_dfastate_t *dest_state;
2540
2541 if (!dfa->nodes[cur_node_idx].accept_mb)
2542 continue;
2543
2544 if (dfa->nodes[cur_node_idx].constraint)
2545 {
2546 context = re_string_context_at (&mctx->input,
2547 re_string_cur_idx (&mctx->input),
2548 mctx->eflags);
2549 if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
2550 context))
2551 continue;
2552 }
2553
2554 /* How many bytes the node can accept? */
2555 naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
2556 re_string_cur_idx (&mctx->input));
2557 if (naccepted == 0)
2558 continue;
2559
2560 /* The node can accepts `naccepted' bytes. */
2561 dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
2562 mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
2563 : mctx->max_mb_elem_len);
2564 err = clean_state_log_if_needed (mctx, dest_idx);
2565 if (BE (err != REG_NOERROR, 0))
2566 return err;
2567#ifdef DEBUG
2568 assert (dfa->nexts[cur_node_idx] != REG_MISSING);
2569#endif
2570 new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
2571
2572 dest_state = mctx->state_log[dest_idx];
2573 if (dest_state == NULL)
2574 dest_nodes = *new_nodes;
2575 else
2576 {
2577 err = re_node_set_init_union (&dest_nodes,
2578 dest_state->entrance_nodes, new_nodes);
2579 if (BE (err != REG_NOERROR, 0))
2580 return err;
2581 }
2582 context = re_string_context_at (&mctx->input, dest_idx - 1,
2583 mctx->eflags);
2584 mctx->state_log[dest_idx]
2585 = re_acquire_state_context (&err, dfa, &dest_nodes, context);
2586 if (dest_state != NULL)
2587 re_node_set_free (&dest_nodes);
2588 if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
2589 return err;
2590 }
2591 return REG_NOERROR;
2592}
2593#endif /* RE_ENABLE_I18N */
2594
2595static reg_errcode_t
2596internal_function
2597transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
2598{
2599 const re_dfa_t *const dfa = mctx->dfa;
2600 reg_errcode_t err;
2601 Idx i;
2602 Idx cur_str_idx = re_string_cur_idx (&mctx->input);
2603
2604 for (i = 0; i < nodes->nelem; ++i)
2605 {
2606 Idx dest_str_idx, prev_nelem, bkc_idx;
2607 Idx node_idx = nodes->elems[i];
2608 unsigned int context;
2609 const re_token_t *node = dfa->nodes + node_idx;
2610 re_node_set *new_dest_nodes;
2611
2612 /* Check whether `node' is a backreference or not. */
2613 if (node->type != OP_BACK_REF)
2614 continue;
2615
2616 if (node->constraint)
2617 {
2618 context = re_string_context_at (&mctx->input, cur_str_idx,
2619 mctx->eflags);
2620 if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
2621 continue;
2622 }
2623
2624 /* `node' is a backreference.
2625 Check the substring which the substring matched. */
2626 bkc_idx = mctx->nbkref_ents;
2627 err = get_subexp (mctx, node_idx, cur_str_idx);
2628 if (BE (err != REG_NOERROR, 0))
2629 goto free_return;
2630
2631 /* And add the epsilon closures (which is `new_dest_nodes') of
2632 the backreference to appropriate state_log. */
2633#ifdef DEBUG
2634 assert (dfa->nexts[node_idx] != REG_MISSING);
2635#endif
2636 for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
2637 {
2638 Idx subexp_len;
2639 re_dfastate_t *dest_state;
2640 struct re_backref_cache_entry *bkref_ent;
2641 bkref_ent = mctx->bkref_ents + bkc_idx;
2642 if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
2643 continue;
2644 subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
2645 new_dest_nodes = (subexp_len == 0
2646 ? dfa->eclosures + dfa->edests[node_idx].elems[0]
2647 : dfa->eclosures + dfa->nexts[node_idx]);
2648 dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
2649 - bkref_ent->subexp_from);
2650 context = re_string_context_at (&mctx->input, dest_str_idx - 1,
2651 mctx->eflags);
2652 dest_state = mctx->state_log[dest_str_idx];
2653 prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
2654 : mctx->state_log[cur_str_idx]->nodes.nelem);
2655 /* Add `new_dest_node' to state_log. */
2656 if (dest_state == NULL)
2657 {
2658 mctx->state_log[dest_str_idx]
2659 = re_acquire_state_context (&err, dfa, new_dest_nodes,
2660 context);
2661 if (BE (mctx->state_log[dest_str_idx] == NULL
2662 && err != REG_NOERROR, 0))
2663 goto free_return;
2664 }
2665 else
2666 {
2667 re_node_set dest_nodes;
2668 err = re_node_set_init_union (&dest_nodes,
2669 dest_state->entrance_nodes,
2670 new_dest_nodes);
2671 if (BE (err != REG_NOERROR, 0))
2672 {
2673 re_node_set_free (&dest_nodes);
2674 goto free_return;
2675 }
2676 mctx->state_log[dest_str_idx]
2677 = re_acquire_state_context (&err, dfa, &dest_nodes, context);
2678 re_node_set_free (&dest_nodes);
2679 if (BE (mctx->state_log[dest_str_idx] == NULL
2680 && err != REG_NOERROR, 0))
2681 goto free_return;
2682 }
2683 /* We need to check recursively if the backreference can epsilon
2684 transit. */
2685 if (subexp_len == 0
2686 && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
2687 {
2688 err = check_subexp_matching_top (mctx, new_dest_nodes,
2689 cur_str_idx);
2690 if (BE (err != REG_NOERROR, 0))
2691 goto free_return;
2692 err = transit_state_bkref (mctx, new_dest_nodes);
2693 if (BE (err != REG_NOERROR, 0))
2694 goto free_return;
2695 }
2696 }
2697 }
2698 err = REG_NOERROR;
2699 free_return:
2700 return err;
2701}
2702
2703/* Enumerate all the candidates which the backreference BKREF_NODE can match
2704 at BKREF_STR_IDX, and register them by match_ctx_add_entry().
2705 Note that we might collect inappropriate candidates here.
2706 However, the cost of checking them strictly here is too high, then we
2707 delay these checking for prune_impossible_nodes(). */
2708
2709static reg_errcode_t
2710internal_function
2711get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx)
2712{
2713 const re_dfa_t *const dfa = mctx->dfa;
2714 Idx subexp_num, sub_top_idx;
2715 const char *buf = (const char *) re_string_get_buffer (&mctx->input);
2716 /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */
2717 Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
2718 if (cache_idx != REG_MISSING)
2719 {
2720 const struct re_backref_cache_entry *entry
2721 = mctx->bkref_ents + cache_idx;
2722 do
2723 if (entry->node == bkref_node)
2724 return REG_NOERROR; /* We already checked it. */
2725 while (entry++->more);
2726 }
2727
2728 subexp_num = dfa->nodes[bkref_node].opr.idx;
2729
2730 /* For each sub expression */
2731 for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
2732 {
2733 reg_errcode_t err;
2734 re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
2735 re_sub_match_last_t *sub_last;
2736 Idx sub_last_idx, sl_str, bkref_str_off;
2737
2738 if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
2739 continue; /* It isn't related. */
2740
2741 sl_str = sub_top->str_idx;
2742 bkref_str_off = bkref_str_idx;
2743 /* At first, check the last node of sub expressions we already
2744 evaluated. */
2745 for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
2746 {
2747 regoff_t sl_str_diff;
2748 sub_last = sub_top->lasts[sub_last_idx];
2749 sl_str_diff = sub_last->str_idx - sl_str;
2750 /* The matched string by the sub expression match with the substring
2751 at the back reference? */
2752 if (sl_str_diff > 0)
2753 {
2754 if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))
2755 {
2756 /* Not enough chars for a successful match. */
2757 if (bkref_str_off + sl_str_diff > mctx->input.len)
2758 break;
2759
2760 err = clean_state_log_if_needed (mctx,
2761 bkref_str_off
2762 + sl_str_diff);
2763 if (BE (err != REG_NOERROR, 0))
2764 return err;
2765 buf = (const char *) re_string_get_buffer (&mctx->input);
2766 }
2767 if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
2768 /* We don't need to search this sub expression any more. */
2769 break;
2770 }
2771 bkref_str_off += sl_str_diff;
2772 sl_str += sl_str_diff;
2773 err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
2774 bkref_str_idx);
2775
2776 /* Reload buf, since the preceding call might have reallocated
2777 the buffer. */
2778 buf = (const char *) re_string_get_buffer (&mctx->input);
2779
2780 if (err == REG_NOMATCH)
2781 continue;
2782 if (BE (err != REG_NOERROR, 0))
2783 return err;
2784 }
2785
2786 if (sub_last_idx < sub_top->nlasts)
2787 continue;
2788 if (sub_last_idx > 0)
2789 ++sl_str;
2790 /* Then, search for the other last nodes of the sub expression. */
2791 for (; sl_str <= bkref_str_idx; ++sl_str)
2792 {
2793 Idx cls_node;
2794 regoff_t sl_str_off;
2795 const re_node_set *nodes;
2796 sl_str_off = sl_str - sub_top->str_idx;
2797 /* The matched string by the sub expression match with the substring
2798 at the back reference? */
2799 if (sl_str_off > 0)
2800 {
2801 if (BE (bkref_str_off >= mctx->input.valid_len, 0))
2802 {
2803 /* If we are at the end of the input, we cannot match. */
2804 if (bkref_str_off >= mctx->input.len)
2805 break;
2806
2807 err = extend_buffers (mctx);
2808 if (BE (err != REG_NOERROR, 0))
2809 return err;
2810
2811 buf = (const char *) re_string_get_buffer (&mctx->input);
2812 }
2813 if (buf [bkref_str_off++] != buf[sl_str - 1])
2814 break; /* We don't need to search this sub expression
2815 any more. */
2816 }
2817 if (mctx->state_log[sl_str] == NULL)
2818 continue;
2819 /* Does this state have a ')' of the sub expression? */
2820 nodes = &mctx->state_log[sl_str]->nodes;
2821 cls_node = find_subexp_node (dfa, nodes, subexp_num,
2822 OP_CLOSE_SUBEXP);
2823 if (cls_node == REG_MISSING)
2824 continue; /* No. */
2825 if (sub_top->path == NULL)
2826 {
2827 sub_top->path = calloc (sizeof (state_array_t),
2828 sl_str - sub_top->str_idx + 1);
2829 if (sub_top->path == NULL)
2830 return REG_ESPACE;
2831 }
2832 /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
2833 in the current context? */
2834 err = check_arrival (mctx, sub_top->path, sub_top->node,
2835 sub_top->str_idx, cls_node, sl_str,
2836 OP_CLOSE_SUBEXP);
2837 if (err == REG_NOMATCH)
2838 continue;
2839 if (BE (err != REG_NOERROR, 0))
2840 return err;
2841 sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
2842 if (BE (sub_last == NULL, 0))
2843 return REG_ESPACE;
2844 err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
2845 bkref_str_idx);
2846 if (err == REG_NOMATCH)
2847 continue;
2848 }
2849 }
2850 return REG_NOERROR;
2851}
2852
2853/* Helper functions for get_subexp(). */
2854
2855/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
2856 If it can arrive, register the sub expression expressed with SUB_TOP
2857 and SUB_LAST. */
2858
2859static reg_errcode_t
2860internal_function
2861get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
2862 re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str)
2863{
2864 reg_errcode_t err;
2865 Idx to_idx;
2866 /* Can the subexpression arrive the back reference? */
2867 err = check_arrival (mctx, &sub_last->path, sub_last->node,
2868 sub_last->str_idx, bkref_node, bkref_str,
2869 OP_OPEN_SUBEXP);
2870 if (err != REG_NOERROR)
2871 return err;
2872 err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
2873 sub_last->str_idx);
2874 if (BE (err != REG_NOERROR, 0))
2875 return err;
2876 to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
2877 return clean_state_log_if_needed (mctx, to_idx);
2878}
2879
2880/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
2881 Search '(' if FL_OPEN, or search ')' otherwise.
2882 TODO: This function isn't efficient...
2883 Because there might be more than one nodes whose types are
2884 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
2885 nodes.
2886 E.g. RE: (a){2} */
2887
2888static Idx
2889internal_function
2890find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
2891 Idx subexp_idx, int type)
2892{
2893 Idx cls_idx;
2894 for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
2895 {
2896 Idx cls_node = nodes->elems[cls_idx];
2897 const re_token_t *node = dfa->nodes + cls_node;
2898 if (node->type == type
2899 && node->opr.idx == subexp_idx)
2900 return cls_node;
2901 }
2902 return REG_MISSING;
2903}
2904
2905/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
2906 LAST_NODE at LAST_STR. We record the path onto PATH since it will be
2907 heavily reused.
2908 Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */
2909
2910static reg_errcode_t
2911internal_function
2912check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node,
2913 Idx top_str, Idx last_node, Idx last_str, int type)
2914{
2915 const re_dfa_t *const dfa = mctx->dfa;
2916 reg_errcode_t err = REG_NOERROR;
2917 Idx subexp_num, backup_cur_idx, str_idx, null_cnt;
2918 re_dfastate_t *cur_state = NULL;
2919 re_node_set *cur_nodes, next_nodes;
2920 re_dfastate_t **backup_state_log;
2921 unsigned int context;
2922
2923 subexp_num = dfa->nodes[top_node].opr.idx;
2924 /* Extend the buffer if we need. */
2925 if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
2926 {
2927 re_dfastate_t **new_array;
2928 Idx old_alloc = path->alloc;
2929 Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1;
2930 if (BE (new_alloc < old_alloc, 0)
2931 || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0))
2932 return REG_ESPACE;
2933 new_array = re_realloc (path->array, re_dfastate_t *, new_alloc);
2934 if (BE (new_array == NULL, 0))
2935 return REG_ESPACE;
2936 path->array = new_array;
2937 path->alloc = new_alloc;
2938 memset (new_array + old_alloc, '\0',
2939 sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
2940 }
2941
2942 str_idx = path->next_idx ? path->next_idx : top_str;
2943
2944 /* Temporary modify MCTX. */
2945 backup_state_log = mctx->state_log;
2946 backup_cur_idx = mctx->input.cur_idx;
2947 mctx->state_log = path->array;
2948 mctx->input.cur_idx = str_idx;
2949
2950 /* Setup initial node set. */
2951 context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
2952 if (str_idx == top_str)
2953 {
2954 err = re_node_set_init_1 (&next_nodes, top_node);
2955 if (BE (err != REG_NOERROR, 0))
2956 return err;
2957 err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
2958 if (BE (err != REG_NOERROR, 0))
2959 {
2960 re_node_set_free (&next_nodes);
2961 return err;
2962 }
2963 }
2964 else
2965 {
2966 cur_state = mctx->state_log[str_idx];
2967 if (cur_state && cur_state->has_backref)
2968 {
2969 err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
2970 if (BE (err != REG_NOERROR, 0))
2971 return err;
2972 }
2973 else
2974 re_node_set_init_empty (&next_nodes);
2975 }
2976 if (str_idx == top_str || (cur_state && cur_state->has_backref))
2977 {
2978 if (next_nodes.nelem)
2979 {
2980 err = expand_bkref_cache (mctx, &next_nodes, str_idx,
2981 subexp_num, type);
2982 if (BE (err != REG_NOERROR, 0))
2983 {
2984 re_node_set_free (&next_nodes);
2985 return err;
2986 }
2987 }
2988 cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
2989 if (BE (cur_state == NULL && err != REG_NOERROR, 0))
2990 {
2991 re_node_set_free (&next_nodes);
2992 return err;
2993 }
2994 mctx->state_log[str_idx] = cur_state;
2995 }
2996
2997 for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
2998 {
2999 re_node_set_empty (&next_nodes);
3000 if (mctx->state_log[str_idx + 1])
3001 {
3002 err = re_node_set_merge (&next_nodes,
3003 &mctx->state_log[str_idx + 1]->nodes);
3004 if (BE (err != REG_NOERROR, 0))
3005 {
3006 re_node_set_free (&next_nodes);
3007 return err;
3008 }
3009 }
3010 if (cur_state)
3011 {
3012 err = check_arrival_add_next_nodes (mctx, str_idx,
3013 &cur_state->non_eps_nodes,
3014 &next_nodes);
3015 if (BE (err != REG_NOERROR, 0))
3016 {
3017 re_node_set_free (&next_nodes);
3018 return err;
3019 }
3020 }
3021 ++str_idx;
3022 if (next_nodes.nelem)
3023 {
3024 err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
3025 if (BE (err != REG_NOERROR, 0))
3026 {
3027 re_node_set_free (&next_nodes);
3028 return err;
3029 }
3030 err = expand_bkref_cache (mctx, &next_nodes, str_idx,
3031 subexp_num, type);
3032 if (BE (err != REG_NOERROR, 0))
3033 {
3034 re_node_set_free (&next_nodes);
3035 return err;
3036 }
3037 }
3038 context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
3039 cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
3040 if (BE (cur_state == NULL && err != REG_NOERROR, 0))
3041 {
3042 re_node_set_free (&next_nodes);
3043 return err;
3044 }
3045 mctx->state_log[str_idx] = cur_state;
3046 null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
3047 }
3048 re_node_set_free (&next_nodes);
3049 cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
3050 : &mctx->state_log[last_str]->nodes);
3051 path->next_idx = str_idx;
3052
3053 /* Fix MCTX. */
3054 mctx->state_log = backup_state_log;
3055 mctx->input.cur_idx = backup_cur_idx;
3056
3057 /* Then check the current node set has the node LAST_NODE. */
3058 if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
3059 return REG_NOERROR;
3060
3061 return REG_NOMATCH;
3062}
3063
3064/* Helper functions for check_arrival. */
3065
3066/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
3067 to NEXT_NODES.
3068 TODO: This function is similar to the functions transit_state*(),
3069 however this function has many additional works.
3070 Can't we unify them? */
3071
3072static reg_errcode_t
3073internal_function
3074check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx,
3075 re_node_set *cur_nodes, re_node_set *next_nodes)
3076{
3077 const re_dfa_t *const dfa = mctx->dfa;
3078 bool ok;
3079 Idx cur_idx;
3080 reg_errcode_t err = REG_NOERROR;
3081 re_node_set union_set;
3082 re_node_set_init_empty (&union_set);
3083 for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
3084 {
3085 int naccepted = 0;
3086 Idx cur_node = cur_nodes->elems[cur_idx];
3087#ifdef DEBUG
3088 re_token_type_t type = dfa->nodes[cur_node].type;
3089 assert (!IS_EPSILON_NODE (type));
3090#endif
3091#ifdef RE_ENABLE_I18N
3092 /* If the node may accept `multi byte'. */
3093 if (dfa->nodes[cur_node].accept_mb)
3094 {
3095 naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
3096 str_idx);
3097 if (naccepted > 1)
3098 {
3099 re_dfastate_t *dest_state;
3100 Idx next_node = dfa->nexts[cur_node];
3101 Idx next_idx = str_idx + naccepted;
3102 dest_state = mctx->state_log[next_idx];
3103 re_node_set_empty (&union_set);
3104 if (dest_state)
3105 {
3106 err = re_node_set_merge (&union_set, &dest_state->nodes);
3107 if (BE (err != REG_NOERROR, 0))
3108 {
3109 re_node_set_free (&union_set);
3110 return err;
3111 }
3112 }
3113 ok = re_node_set_insert (&union_set, next_node);
3114 if (BE (! ok, 0))
3115 {
3116 re_node_set_free (&union_set);
3117 return REG_ESPACE;
3118 }
3119 mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
3120 &union_set);
3121 if (BE (mctx->state_log[next_idx] == NULL
3122 && err != REG_NOERROR, 0))
3123 {
3124 re_node_set_free (&union_set);
3125 return err;
3126 }
3127 }
3128 }
3129#endif /* RE_ENABLE_I18N */
3130 if (naccepted
3131 || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
3132 {
3133 ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
3134 if (BE (! ok, 0))
3135 {
3136 re_node_set_free (&union_set);
3137 return REG_ESPACE;
3138 }
3139 }
3140 }
3141 re_node_set_free (&union_set);
3142 return REG_NOERROR;
3143}
3144
3145/* For all the nodes in CUR_NODES, add the epsilon closures of them to
3146 CUR_NODES, however exclude the nodes which are:
3147 - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
3148 - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
3149*/
3150
3151static reg_errcode_t
3152internal_function
3153check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
3154 Idx ex_subexp, int type)
3155{
3156 reg_errcode_t err;
3157 Idx idx, outside_node;
3158 re_node_set new_nodes;
3159#ifdef DEBUG
3160 assert (cur_nodes->nelem);
3161#endif
3162 err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
3163 if (BE (err != REG_NOERROR, 0))
3164 return err;
3165 /* Create a new node set NEW_NODES with the nodes which are epsilon
3166 closures of the node in CUR_NODES. */
3167
3168 for (idx = 0; idx < cur_nodes->nelem; ++idx)
3169 {
3170 Idx cur_node = cur_nodes->elems[idx];
3171 const re_node_set *eclosure = dfa->eclosures + cur_node;
3172 outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
3173 if (outside_node == REG_MISSING)
3174 {
3175 /* There are no problematic nodes, just merge them. */
3176 err = re_node_set_merge (&new_nodes, eclosure);
3177 if (BE (err != REG_NOERROR, 0))
3178 {
3179 re_node_set_free (&new_nodes);
3180 return err;
3181 }
3182 }
3183 else
3184 {
3185 /* There are problematic nodes, re-calculate incrementally. */
3186 err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
3187 ex_subexp, type);
3188 if (BE (err != REG_NOERROR, 0))
3189 {
3190 re_node_set_free (&new_nodes);
3191 return err;
3192 }
3193 }
3194 }
3195 re_node_set_free (cur_nodes);
3196 *cur_nodes = new_nodes;
3197 return REG_NOERROR;
3198}
3199
3200/* Helper function for check_arrival_expand_ecl.
3201 Check incrementally the epsilon closure of TARGET, and if it isn't
3202 problematic append it to DST_NODES. */
3203
3204static reg_errcode_t
3205internal_function
3206check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
3207 Idx target, Idx ex_subexp, int type)
3208{
3209 Idx cur_node;
3210 for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
3211 {
3212 bool ok;
3213
3214 if (dfa->nodes[cur_node].type == type
3215 && dfa->nodes[cur_node].opr.idx == ex_subexp)
3216 {
3217 if (type == OP_CLOSE_SUBEXP)
3218 {
3219 ok = re_node_set_insert (dst_nodes, cur_node);
3220 if (BE (! ok, 0))
3221 return REG_ESPACE;
3222 }
3223 break;
3224 }
3225 ok = re_node_set_insert (dst_nodes, cur_node);
3226 if (BE (! ok, 0))
3227 return REG_ESPACE;
3228 if (dfa->edests[cur_node].nelem == 0)
3229 break;
3230 if (dfa->edests[cur_node].nelem == 2)
3231 {
3232 reg_errcode_t err;
3233 err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
3234 dfa->edests[cur_node].elems[1],
3235 ex_subexp, type);
3236 if (BE (err != REG_NOERROR, 0))
3237 return err;
3238 }
3239 cur_node = dfa->edests[cur_node].elems[0];
3240 }
3241 return REG_NOERROR;
3242}
3243
3244
3245/* For all the back references in the current state, calculate the
3246 destination of the back references by the appropriate entry
3247 in MCTX->BKREF_ENTS. */
3248
3249static reg_errcode_t
3250internal_function
3251expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
3252 Idx cur_str, Idx subexp_num, int type)
3253{
3254 const re_dfa_t *const dfa = mctx->dfa;
3255 reg_errcode_t err;
3256 Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
3257 struct re_backref_cache_entry *ent;
3258
3259 if (cache_idx_start == REG_MISSING)
3260 return REG_NOERROR;
3261
3262 restart:
3263 ent = mctx->bkref_ents + cache_idx_start;
3264 do
3265 {
3266 Idx to_idx, next_node;
3267
3268 /* Is this entry ENT is appropriate? */
3269 if (!re_node_set_contains (cur_nodes, ent->node))
3270 continue; /* No. */
3271
3272 to_idx = cur_str + ent->subexp_to - ent->subexp_from;
3273 /* Calculate the destination of the back reference, and append it
3274 to MCTX->STATE_LOG. */
3275 if (to_idx == cur_str)
3276 {
3277 /* The backreference did epsilon transit, we must re-check all the
3278 node in the current state. */
3279 re_node_set new_dests;
3280 reg_errcode_t err2, err3;
3281 next_node = dfa->edests[ent->node].elems[0];
3282 if (re_node_set_contains (cur_nodes, next_node))
3283 continue;
3284 err = re_node_set_init_1 (&new_dests, next_node);
3285 err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);
3286 err3 = re_node_set_merge (cur_nodes, &new_dests);
3287 re_node_set_free (&new_dests);
3288 if (BE (err != REG_NOERROR || err2 != REG_NOERROR
3289 || err3 != REG_NOERROR, 0))
3290 {
3291 err = (err != REG_NOERROR ? err
3292 : (err2 != REG_NOERROR ? err2 : err3));
3293 return err;
3294 }
3295 /* TODO: It is still inefficient... */
3296 goto restart;
3297 }
3298 else
3299 {
3300 re_node_set union_set;
3301 next_node = dfa->nexts[ent->node];
3302 if (mctx->state_log[to_idx])
3303 {
3304 bool ok;
3305 if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
3306 next_node))
3307 continue;
3308 err = re_node_set_init_copy (&union_set,
3309 &mctx->state_log[to_idx]->nodes);
3310 ok = re_node_set_insert (&union_set, next_node);
3311 if (BE (err != REG_NOERROR || ! ok, 0))
3312 {
3313 re_node_set_free (&union_set);
3314 err = err != REG_NOERROR ? err : REG_ESPACE;
3315 return err;
3316 }
3317 }
3318 else
3319 {
3320 err = re_node_set_init_1 (&union_set, next_node);
3321 if (BE (err != REG_NOERROR, 0))
3322 return err;
3323 }
3324 mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
3325 re_node_set_free (&union_set);
3326 if (BE (mctx->state_log[to_idx] == NULL
3327 && err != REG_NOERROR, 0))
3328 return err;
3329 }
3330 }
3331 while (ent++->more);
3332 return REG_NOERROR;
3333}
3334
3335/* Build transition table for the state.
3336 Return true if successful. */
3337
3338static bool
3339internal_function
3340build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
3341{
3342 reg_errcode_t err;
3343 Idx i, j;
3344 int ch;
3345 bool need_word_trtable = false;
3346 bitset_word_t elem, mask;
3347 bool dests_node_malloced = false;
3348 bool dest_states_malloced = false;
3349 Idx ndests; /* Number of the destination states from `state'. */
3350 re_dfastate_t **trtable;
3351 re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
3352 re_node_set follows, *dests_node;
3353 bitset_t *dests_ch;
3354 bitset_t acceptable;
3355
3356 struct dests_alloc
3357 {
3358 re_node_set dests_node[SBC_MAX];
3359 bitset_t dests_ch[SBC_MAX];
3360 } *dests_alloc;
3361
3362 /* We build DFA states which corresponds to the destination nodes
3363 from `state'. `dests_node[i]' represents the nodes which i-th
3364 destination state contains, and `dests_ch[i]' represents the
3365 characters which i-th destination state accepts. */
3366 if (__libc_use_alloca (sizeof (struct dests_alloc)))
3367 dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
3368 else
3369 {
3370 dests_alloc = re_malloc (struct dests_alloc, 1);
3371 if (BE (dests_alloc == NULL, 0))
3372 return false;
3373 dests_node_malloced = true;
3374 }
3375 dests_node = dests_alloc->dests_node;
3376 dests_ch = dests_alloc->dests_ch;
3377
3378 /* Initialize transiton table. */
3379 state->word_trtable = state->trtable = NULL;
3380
3381 /* At first, group all nodes belonging to `state' into several
3382 destinations. */
3383 ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
3384 if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0))
3385 {
3386 if (dests_node_malloced)
3387 free (dests_alloc);
3388 if (ndests == 0)
3389 {
3390 state->trtable = (re_dfastate_t **)
3391 calloc (sizeof (re_dfastate_t *), SBC_MAX);
3392 return true;
3393 }
3394 return false;
3395 }
3396
3397 err = re_node_set_alloc (&follows, ndests + 1);
3398 if (BE (err != REG_NOERROR, 0))
3399 goto out_free;
3400
3401 /* Avoid arithmetic overflow in size calculation. */
3402 if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
3403 / (3 * sizeof (re_dfastate_t *)))
3404 < ndests),
3405 0))
3406 goto out_free;
3407
3408 if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
3409 + ndests * 3 * sizeof (re_dfastate_t *)))
3410 dest_states = (re_dfastate_t **)
3411 alloca (ndests * 3 * sizeof (re_dfastate_t *));
3412 else
3413 {
3414 dest_states = (re_dfastate_t **)
3415 malloc (ndests * 3 * sizeof (re_dfastate_t *));
3416 if (BE (dest_states == NULL, 0))
3417 {
3418out_free:
3419 if (dest_states_malloced)
3420 free (dest_states);
3421 re_node_set_free (&follows);
3422 for (i = 0; i < ndests; ++i)
3423 re_node_set_free (dests_node + i);
3424 if (dests_node_malloced)
3425 free (dests_alloc);
3426 return false;
3427 }
3428 dest_states_malloced = true;
3429 }
3430 dest_states_word = dest_states + ndests;
3431 dest_states_nl = dest_states_word + ndests;
3432 bitset_empty (acceptable);
3433
3434 /* Then build the states for all destinations. */
3435 for (i = 0; i < ndests; ++i)
3436 {
3437 Idx next_node;
3438 re_node_set_empty (&follows);
3439 /* Merge the follows of this destination states. */
3440 for (j = 0; j < dests_node[i].nelem; ++j)
3441 {
3442 next_node = dfa->nexts[dests_node[i].elems[j]];
3443 if (next_node != REG_MISSING)
3444 {
3445 err = re_node_set_merge (&follows, dfa->eclosures + next_node);
3446 if (BE (err != REG_NOERROR, 0))
3447 goto out_free;
3448 }
3449 }
3450 dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
3451 if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
3452 goto out_free;
3453 /* If the new state has context constraint,
3454 build appropriate states for these contexts. */
3455 if (dest_states[i]->has_constraint)
3456 {
3457 dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
3458 CONTEXT_WORD);
3459 if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
3460 goto out_free;
3461
3462 if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
3463 need_word_trtable = true;
3464
3465 dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
3466 CONTEXT_NEWLINE);
3467 if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
3468 goto out_free;
3469 }
3470 else
3471 {
3472 dest_states_word[i] = dest_states[i];
3473 dest_states_nl[i] = dest_states[i];
3474 }
3475 bitset_merge (acceptable, dests_ch[i]);
3476 }
3477
3478 if (!BE (need_word_trtable, 0))
3479 {
3480 /* We don't care about whether the following character is a word
3481 character, or we are in a single-byte character set so we can
3482 discern by looking at the character code: allocate a
3483 256-entry transition table. */
3484 trtable = state->trtable =
3485 (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
3486 if (BE (trtable == NULL, 0))
3487 goto out_free;
3488
3489 /* For all characters ch...: */
3490 for (i = 0; i < BITSET_WORDS; ++i)
3491 for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
3492 elem;
3493 mask <<= 1, elem >>= 1, ++ch)
3494 if (BE (elem & 1, 0))
3495 {
3496 /* There must be exactly one destination which accepts
3497 character ch. See group_nodes_into_DFAstates. */
3498 for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
3499 ;
3500
3501 /* j-th destination accepts the word character ch. */
3502 if (dfa->word_char[i] & mask)
3503 trtable[ch] = dest_states_word[j];
3504 else
3505 trtable[ch] = dest_states[j];
3506 }
3507 }
3508 else
3509 {
3510 /* We care about whether the following character is a word
3511 character, and we are in a multi-byte character set: discern
3512 by looking at the character code: build two 256-entry
3513 transition tables, one starting at trtable[0] and one
3514 starting at trtable[SBC_MAX]. */
3515 trtable = state->word_trtable =
3516 (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
3517 if (BE (trtable == NULL, 0))
3518 goto out_free;
3519
3520 /* For all characters ch...: */
3521 for (i = 0; i < BITSET_WORDS; ++i)
3522 for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
3523 elem;
3524 mask <<= 1, elem >>= 1, ++ch)
3525 if (BE (elem & 1, 0))
3526 {
3527 /* There must be exactly one destination which accepts
3528 character ch. See group_nodes_into_DFAstates. */
3529 for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
3530 ;
3531
3532 /* j-th destination accepts the word character ch. */
3533 trtable[ch] = dest_states[j];
3534 trtable[ch + SBC_MAX] = dest_states_word[j];
3535 }
3536 }
3537
3538 /* new line */
3539 if (bitset_contain (acceptable, NEWLINE_CHAR))
3540 {
3541 /* The current state accepts newline character. */
3542 for (j = 0; j < ndests; ++j)
3543 if (bitset_contain (dests_ch[j], NEWLINE_CHAR))
3544 {
3545 /* k-th destination accepts newline character. */
3546 trtable[NEWLINE_CHAR] = dest_states_nl[j];
3547 if (need_word_trtable)
3548 trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];
3549 /* There must be only one destination which accepts
3550 newline. See group_nodes_into_DFAstates. */
3551 break;
3552 }
3553 }
3554
3555 if (dest_states_malloced)
3556 free (dest_states);
3557
3558 re_node_set_free (&follows);
3559 for (i = 0; i < ndests; ++i)
3560 re_node_set_free (dests_node + i);
3561
3562 if (dests_node_malloced)
3563 free (dests_alloc);
3564
3565 return true;
3566}
3567
3568/* Group all nodes belonging to STATE into several destinations.
3569 Then for all destinations, set the nodes belonging to the destination
3570 to DESTS_NODE[i] and set the characters accepted by the destination
3571 to DEST_CH[i]. This function return the number of destinations. */
3572
3573static Idx
3574internal_function
3575group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
3576 re_node_set *dests_node, bitset_t *dests_ch)
3577{
3578 reg_errcode_t err;
3579 bool ok;
3580 Idx i, j, k;
3581 Idx ndests; /* Number of the destinations from `state'. */
3582 bitset_t accepts; /* Characters a node can accept. */
3583 const re_node_set *cur_nodes = &state->nodes;
3584 bitset_empty (accepts);
3585 ndests = 0;
3586
3587 /* For all the nodes belonging to `state', */
3588 for (i = 0; i < cur_nodes->nelem; ++i)
3589 {
3590 re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
3591 re_token_type_t type = node->type;
3592 unsigned int constraint = node->constraint;
3593
3594 /* Enumerate all single byte character this node can accept. */
3595 if (type == CHARACTER)
3596 bitset_set (accepts, node->opr.c);
3597 else if (type == SIMPLE_BRACKET)
3598 {
3599 bitset_merge (accepts, node->opr.sbcset);
3600 }
3601 else if (type == OP_PERIOD)
3602 {
3603#ifdef RE_ENABLE_I18N
3604 if (dfa->mb_cur_max > 1)
3605 bitset_merge (accepts, dfa->sb_char);
3606 else
3607#endif
3608 bitset_set_all (accepts);
3609 if (!(dfa->syntax & RE_DOT_NEWLINE))
3610 bitset_clear (accepts, '\n');
3611 if (dfa->syntax & RE_DOT_NOT_NULL)
3612 bitset_clear (accepts, '\0');
3613 }
3614#ifdef RE_ENABLE_I18N
3615 else if (type == OP_UTF8_PERIOD)
3616 {
3617 if (ASCII_CHARS % BITSET_WORD_BITS == 0)
3618 memset (accepts, -1, ASCII_CHARS / CHAR_BIT);
3619 else
3620 bitset_merge (accepts, utf8_sb_map);
3621 if (!(dfa->syntax & RE_DOT_NEWLINE))
3622 bitset_clear (accepts, '\n');
3623 if (dfa->syntax & RE_DOT_NOT_NULL)
3624 bitset_clear (accepts, '\0');
3625 }
3626#endif
3627 else
3628 continue;
3629
3630 /* Check the `accepts' and sift the characters which are not
3631 match it the context. */
3632 if (constraint)
3633 {
3634 if (constraint & NEXT_NEWLINE_CONSTRAINT)
3635 {
3636 bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
3637 bitset_empty (accepts);
3638 if (accepts_newline)
3639 bitset_set (accepts, NEWLINE_CHAR);
3640 else
3641 continue;
3642 }
3643 if (constraint & NEXT_ENDBUF_CONSTRAINT)
3644 {
3645 bitset_empty (accepts);
3646 continue;
3647 }
3648
3649 if (constraint & NEXT_WORD_CONSTRAINT)
3650 {
3651 bitset_word_t any_set = 0;
3652 if (type == CHARACTER && !node->word_char)
3653 {
3654 bitset_empty (accepts);
3655 continue;
3656 }
3657#ifdef RE_ENABLE_I18N
3658 if (dfa->mb_cur_max > 1)
3659 for (j = 0; j < BITSET_WORDS; ++j)
3660 any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
3661 else
3662#endif
3663 for (j = 0; j < BITSET_WORDS; ++j)
3664 any_set |= (accepts[j] &= dfa->word_char[j]);
3665 if (!any_set)
3666 continue;
3667 }
3668 if (constraint & NEXT_NOTWORD_CONSTRAINT)
3669 {
3670 bitset_word_t any_set = 0;
3671 if (type == CHARACTER && node->word_char)
3672 {
3673 bitset_empty (accepts);
3674 continue;
3675 }
3676#ifdef RE_ENABLE_I18N
3677 if (dfa->mb_cur_max > 1)
3678 for (j = 0; j < BITSET_WORDS; ++j)
3679 any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
3680 else
3681#endif
3682 for (j = 0; j < BITSET_WORDS; ++j)
3683 any_set |= (accepts[j] &= ~dfa->word_char[j]);
3684 if (!any_set)
3685 continue;
3686 }
3687 }
3688
3689 /* Then divide `accepts' into DFA states, or create a new
3690 state. Above, we make sure that accepts is not empty. */
3691 for (j = 0; j < ndests; ++j)
3692 {
3693 bitset_t intersec; /* Intersection sets, see below. */
3694 bitset_t remains;
3695 /* Flags, see below. */
3696 bitset_word_t has_intersec, not_subset, not_consumed;
3697
3698 /* Optimization, skip if this state doesn't accept the character. */
3699 if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
3700 continue;
3701
3702 /* Enumerate the intersection set of this state and `accepts'. */
3703 has_intersec = 0;
3704 for (k = 0; k < BITSET_WORDS; ++k)
3705 has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
3706 /* And skip if the intersection set is empty. */
3707 if (!has_intersec)
3708 continue;
3709
3710 /* Then check if this state is a subset of `accepts'. */
3711 not_subset = not_consumed = 0;
3712 for (k = 0; k < BITSET_WORDS; ++k)
3713 {
3714 not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
3715 not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
3716 }
3717
3718 /* If this state isn't a subset of `accepts', create a
3719 new group state, which has the `remains'. */
3720 if (not_subset)
3721 {
3722 bitset_copy (dests_ch[ndests], remains);
3723 bitset_copy (dests_ch[j], intersec);
3724 err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
3725 if (BE (err != REG_NOERROR, 0))
3726 goto error_return;
3727 ++ndests;
3728 }
3729
3730 /* Put the position in the current group. */
3731 ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
3732 if (BE (! ok, 0))
3733 goto error_return;
3734
3735 /* If all characters are consumed, go to next node. */
3736 if (!not_consumed)
3737 break;
3738 }
3739 /* Some characters remain, create a new group. */
3740 if (j == ndests)
3741 {
3742 bitset_copy (dests_ch[ndests], accepts);
3743 err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
3744 if (BE (err != REG_NOERROR, 0))
3745 goto error_return;
3746 ++ndests;
3747 bitset_empty (accepts);
3748 }
3749 }
3750 return ndests;
3751 error_return:
3752 for (j = 0; j < ndests; ++j)
3753 re_node_set_free (dests_node + j);
3754 return REG_MISSING;
3755}
3756
3757#ifdef RE_ENABLE_I18N
3758/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
3759 Return the number of the bytes the node accepts.
3760 STR_IDX is the current index of the input string.
3761
3762 This function handles the nodes which can accept one character, or
3763 one collating element like '.', '[a-z]', opposite to the other nodes
3764 can only accept one byte. */
3765
3766static int
3767internal_function
3768check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
3769 const re_string_t *input, Idx str_idx)
3770{
3771 const re_token_t *node = dfa->nodes + node_idx;
3772 int char_len, elem_len;
3773 Idx i;
3774
3775 if (BE (node->type == OP_UTF8_PERIOD, 0))
3776 {
3777 unsigned char c = re_string_byte_at (input, str_idx), d;
3778 if (BE (c < 0xc2, 1))
3779 return 0;
3780
3781 if (str_idx + 2 > input->len)
3782 return 0;
3783
3784 d = re_string_byte_at (input, str_idx + 1);
3785 if (c < 0xe0)
3786 return (d < 0x80 || d > 0xbf) ? 0 : 2;
3787 else if (c < 0xf0)
3788 {
3789 char_len = 3;
3790 if (c == 0xe0 && d < 0xa0)
3791 return 0;
3792 }
3793 else if (c < 0xf8)
3794 {
3795 char_len = 4;
3796 if (c == 0xf0 && d < 0x90)
3797 return 0;
3798 }
3799 else if (c < 0xfc)
3800 {
3801 char_len = 5;
3802 if (c == 0xf8 && d < 0x88)
3803 return 0;
3804 }
3805 else if (c < 0xfe)
3806 {
3807 char_len = 6;
3808 if (c == 0xfc && d < 0x84)
3809 return 0;
3810 }
3811 else
3812 return 0;
3813
3814 if (str_idx + char_len > input->len)
3815 return 0;
3816
3817 for (i = 1; i < char_len; ++i)
3818 {
3819 d = re_string_byte_at (input, str_idx + i);
3820 if (d < 0x80 || d > 0xbf)
3821 return 0;
3822 }
3823 return char_len;
3824 }
3825
3826 char_len = re_string_char_size_at (input, str_idx);
3827 if (node->type == OP_PERIOD)
3828 {
3829 if (char_len <= 1)
3830 return 0;
3831 /* FIXME: I don't think this if is needed, as both '\n'
3832 and '\0' are char_len == 1. */
3833 /* '.' accepts any one character except the following two cases. */
3834 if ((!(dfa->syntax & RE_DOT_NEWLINE) &&
3835 re_string_byte_at (input, str_idx) == '\n') ||
3836 ((dfa->syntax & RE_DOT_NOT_NULL) &&
3837 re_string_byte_at (input, str_idx) == '\0'))
3838 return 0;
3839 return char_len;
3840 }
3841
3842 elem_len = re_string_elem_size_at (input, str_idx);
3843 if ((elem_len <= 1 && char_len <= 1) || char_len == 0)
3844 return 0;
3845
3846 if (node->type == COMPLEX_BRACKET)
3847 {
3848 const re_charset_t *cset = node->opr.mbcset;
3849# ifdef _LIBC
3850 const unsigned char *pin
3851 = ((const unsigned char *) re_string_get_buffer (input) + str_idx);
3852 Idx j;
3853 uint32_t nrules;
3854# endif /* _LIBC */
3855 int match_len = 0;
3856 wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
3857 ? re_string_wchar_at (input, str_idx) : 0);
3858
3859 /* match with multibyte character? */
3860 for (i = 0; i < cset->nmbchars; ++i)
3861 if (wc == cset->mbchars[i])
3862 {
3863 match_len = char_len;
3864 goto check_node_accept_bytes_match;
3865 }
3866 /* match with character_class? */
3867 for (i = 0; i < cset->nchar_classes; ++i)
3868 {
3869 wctype_t wt = cset->char_classes[i];
3870 if (__iswctype (wc, wt))
3871 {
3872 match_len = char_len;
3873 goto check_node_accept_bytes_match;
3874 }
3875 }
3876
3877# ifdef _LIBC
3878 nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
3879 if (nrules != 0)
3880 {
3881 unsigned int in_collseq = 0;
3882 const int32_t *table, *indirect;
3883 const unsigned char *weights, *extra;
3884 const char *collseqwc;
3885 int32_t idx;
3886 /* This #include defines a local function! */
3887# include <locale/weight.h>
3888
3889 /* match with collating_symbol? */
3890 if (cset->ncoll_syms)
3891 extra = (const unsigned char *)
3892 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
3893 for (i = 0; i < cset->ncoll_syms; ++i)
3894 {
3895 const unsigned char *coll_sym = extra + cset->coll_syms[i];
3896 /* Compare the length of input collating element and
3897 the length of current collating element. */
3898 if (*coll_sym != elem_len)
3899 continue;
3900 /* Compare each bytes. */
3901 for (j = 0; j < *coll_sym; j++)
3902 if (pin[j] != coll_sym[1 + j])
3903 break;
3904 if (j == *coll_sym)
3905 {
3906 /* Match if every bytes is equal. */
3907 match_len = j;
3908 goto check_node_accept_bytes_match;
3909 }
3910 }
3911
3912 if (cset->nranges)
3913 {
3914 if (elem_len <= char_len)
3915 {
3916 collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
3917 in_collseq = __collseq_table_lookup (collseqwc, wc);
3918 }
3919 else
3920 in_collseq = find_collation_sequence_value (pin, elem_len);
3921 }
3922 /* match with range expression? */
3923 for (i = 0; i < cset->nranges; ++i)
3924 if (cset->range_starts[i] <= in_collseq
3925 && in_collseq <= cset->range_ends[i])
3926 {
3927 match_len = elem_len;
3928 goto check_node_accept_bytes_match;
3929 }
3930
3931 /* match with equivalence_class? */
3932 if (cset->nequiv_classes)
3933 {
3934 const unsigned char *cp = pin;
3935 table = (const int32_t *)
3936 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
3937 weights = (const unsigned char *)
3938 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
3939 extra = (const unsigned char *)
3940 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
3941 indirect = (const int32_t *)
3942 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
3943 idx = findidx (&cp);
3944 if (idx > 0)
3945 for (i = 0; i < cset->nequiv_classes; ++i)
3946 {
3947 int32_t equiv_class_idx = cset->equiv_classes[i];
3948 size_t weight_len = weights[idx];
3949 if (weight_len == weights[equiv_class_idx])
3950 {
3951 Idx cnt = 0;
3952 while (cnt <= weight_len
3953 && (weights[equiv_class_idx + 1 + cnt]
3954 == weights[idx + 1 + cnt]))
3955 ++cnt;
3956 if (cnt > weight_len)
3957 {
3958 match_len = elem_len;
3959 goto check_node_accept_bytes_match;
3960 }
3961 }
3962 }
3963 }
3964 }
3965 else
3966# endif /* _LIBC */
3967 {
3968 /* match with range expression? */
3969#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && __STRICT_ANSI__)
3970 wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
3971#else
3972 wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
3973 cmp_buf[2] = wc;
3974#endif
3975 for (i = 0; i < cset->nranges; ++i)
3976 {
3977 cmp_buf[0] = cset->range_starts[i];
3978 cmp_buf[4] = cset->range_ends[i];
3979 if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
3980 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
3981 {
3982 match_len = char_len;
3983 goto check_node_accept_bytes_match;
3984 }
3985 }
3986 }
3987 check_node_accept_bytes_match:
3988 if (!cset->non_match)
3989 return match_len;
3990 else
3991 {
3992 if (match_len > 0)
3993 return 0;
3994 else
3995 return (elem_len > char_len) ? elem_len : char_len;
3996 }
3997 }
3998 return 0;
3999}
4000
4001# ifdef _LIBC
4002static unsigned int
4003internal_function
4004find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
4005{
4006 uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
4007 if (nrules == 0)
4008 {
4009 if (mbs_len == 1)
4010 {
4011 /* No valid character. Match it as a single byte character. */
4012 const unsigned char *collseq = (const unsigned char *)
4013 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
4014 return collseq[mbs[0]];
4015 }
4016 return UINT_MAX;
4017 }
4018 else
4019 {
4020 int32_t idx;
4021 const unsigned char *extra = (const unsigned char *)
4022 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
4023 int32_t extrasize = (const unsigned char *)
4024 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;
4025
4026 for (idx = 0; idx < extrasize;)
4027 {
4028 int mbs_cnt;
4029 bool found = false;
4030 int32_t elem_mbs_len;
4031 /* Skip the name of collating element name. */
4032 idx = idx + extra[idx] + 1;
4033 elem_mbs_len = extra[idx++];
4034 if (mbs_len == elem_mbs_len)
4035 {
4036 for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
4037 if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
4038 break;
4039 if (mbs_cnt == elem_mbs_len)
4040 /* Found the entry. */
4041 found = true;
4042 }
4043 /* Skip the byte sequence of the collating element. */
4044 idx += elem_mbs_len;
4045 /* Adjust for the alignment. */
4046 idx = (idx + 3) & ~3;
4047 /* Skip the collation sequence value. */
4048 idx += sizeof (uint32_t);
4049 /* Skip the wide char sequence of the collating element. */
4050 idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
4051 /* If we found the entry, return the sequence value. */
4052 if (found)
4053 return *(uint32_t *) (extra + idx);
4054 /* Skip the collation sequence value. */
4055 idx += sizeof (uint32_t);
4056 }
4057 return UINT_MAX;
4058 }
4059}
4060# endif /* _LIBC */
4061#endif /* RE_ENABLE_I18N */
4062
4063/* Check whether the node accepts the byte which is IDX-th
4064 byte of the INPUT. */
4065
4066static bool
4067internal_function
4068check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
4069 Idx idx)
4070{
4071 unsigned char ch;
4072 ch = re_string_byte_at (&mctx->input, idx);
4073 switch (node->type)
4074 {
4075 case CHARACTER:
4076 if (node->opr.c != ch)
4077 return false;
4078 break;
4079
4080 case SIMPLE_BRACKET:
4081 if (!bitset_contain (node->opr.sbcset, ch))
4082 return false;
4083 break;
4084
4085#ifdef RE_ENABLE_I18N
4086 case OP_UTF8_PERIOD:
4087 if (ch >= ASCII_CHARS)
4088 return false;
4089 /* FALLTHROUGH */
4090#endif
4091 case OP_PERIOD:
4092 if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
4093 || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
4094 return false;
4095 break;
4096
4097 default:
4098 return false;
4099 }
4100
4101 if (node->constraint)
4102 {
4103 /* The node has constraints. Check whether the current context
4104 satisfies the constraints. */
4105 unsigned int context = re_string_context_at (&mctx->input, idx,
4106 mctx->eflags);
4107 if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
4108 return false;
4109 }
4110
4111 return true;
4112}
4113
4114/* Extend the buffers, if the buffers have run out. */
4115
4116static reg_errcode_t
4117internal_function
4118extend_buffers (re_match_context_t *mctx)
4119{
4120 reg_errcode_t ret;
4121 re_string_t *pstr = &mctx->input;
4122
4123 /* Avoid overflow. */
4124 if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
4125 return REG_ESPACE;
4126
4127 /* Double the lengthes of the buffers. */
4128 ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
4129 if (BE (ret != REG_NOERROR, 0))
4130 return ret;
4131
4132 if (mctx->state_log != NULL)
4133 {
4134 /* And double the length of state_log. */
4135 /* XXX We have no indication of the size of this buffer. If this
4136 allocation fail we have no indication that the state_log array
4137 does not have the right size. */
4138 re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
4139 pstr->bufs_len + 1);
4140 if (BE (new_array == NULL, 0))
4141 return REG_ESPACE;
4142 mctx->state_log = new_array;
4143 }
4144
4145 /* Then reconstruct the buffers. */
4146 if (pstr->icase)
4147 {
4148#ifdef RE_ENABLE_I18N
4149 if (pstr->mb_cur_max > 1)
4150 {
4151 ret = build_wcs_upper_buffer (pstr);
4152 if (BE (ret != REG_NOERROR, 0))
4153 return ret;
4154 }
4155 else
4156#endif /* RE_ENABLE_I18N */
4157 build_upper_buffer (pstr);
4158 }
4159 else
4160 {
4161#ifdef RE_ENABLE_I18N
4162 if (pstr->mb_cur_max > 1)
4163 build_wcs_buffer (pstr);
4164 else
4165#endif /* RE_ENABLE_I18N */
4166 {
4167 if (pstr->trans != NULL)
4168 re_string_translate_buffer (pstr);
4169 }
4170 }
4171 return REG_NOERROR;
4172}
4173
4174
4175/* Functions for matching context. */
4176
4177/* Initialize MCTX. */
4178
4179static reg_errcode_t
4180internal_function
4181match_ctx_init (re_match_context_t *mctx, int eflags, Idx n)
4182{
4183 mctx->eflags = eflags;
4184 mctx->match_last = REG_MISSING;
4185 if (n > 0)
4186 {
4187 /* Avoid overflow. */
4188 size_t max_object_size =
4189 MAX (sizeof (struct re_backref_cache_entry),
4190 sizeof (re_sub_match_top_t *));
4191 if (BE (SIZE_MAX / max_object_size < n, 0))
4192 return REG_ESPACE;
4193
4194 mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
4195 mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
4196 if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
4197 return REG_ESPACE;
4198 }
4199 /* Already zero-ed by the caller.
4200 else
4201 mctx->bkref_ents = NULL;
4202 mctx->nbkref_ents = 0;
4203 mctx->nsub_tops = 0; */
4204 mctx->abkref_ents = n;
4205 mctx->max_mb_elem_len = 1;
4206 mctx->asub_tops = n;
4207 return REG_NOERROR;
4208}
4209
4210/* Clean the entries which depend on the current input in MCTX.
4211 This function must be invoked when the matcher changes the start index
4212 of the input, or changes the input string. */
4213
4214static void
4215internal_function
4216match_ctx_clean (re_match_context_t *mctx)
4217{
4218 Idx st_idx;
4219 for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
4220 {
4221 Idx sl_idx;
4222 re_sub_match_top_t *top = mctx->sub_tops[st_idx];
4223 for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
4224 {
4225 re_sub_match_last_t *last = top->lasts[sl_idx];
4226 re_free (last->path.array);
4227 re_free (last);
4228 }
4229 re_free (top->lasts);
4230 if (top->path)
4231 {
4232 re_free (top->path->array);
4233 re_free (top->path);
4234 }
4235 free (top);
4236 }
4237
4238 mctx->nsub_tops = 0;
4239 mctx->nbkref_ents = 0;
4240}
4241
4242/* Free all the memory associated with MCTX. */
4243
4244static void
4245internal_function
4246match_ctx_free (re_match_context_t *mctx)
4247{
4248 /* First, free all the memory associated with MCTX->SUB_TOPS. */
4249 match_ctx_clean (mctx);
4250 re_free (mctx->sub_tops);
4251 re_free (mctx->bkref_ents);
4252}
4253
4254/* Add a new backreference entry to MCTX.
4255 Note that we assume that caller never call this function with duplicate
4256 entry, and call with STR_IDX which isn't smaller than any existing entry.
4257*/
4258
4259static reg_errcode_t
4260internal_function
4261match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from,
4262 Idx to)
4263{
4264 if (mctx->nbkref_ents >= mctx->abkref_ents)
4265 {
4266 struct re_backref_cache_entry* new_entry;
4267 new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
4268 mctx->abkref_ents * 2);
4269 if (BE (new_entry == NULL, 0))
4270 {
4271 re_free (mctx->bkref_ents);
4272 return REG_ESPACE;
4273 }
4274 mctx->bkref_ents = new_entry;
4275 memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
4276 sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
4277 mctx->abkref_ents *= 2;
4278 }
4279 if (mctx->nbkref_ents > 0
4280 && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
4281 mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;
4282
4283 mctx->bkref_ents[mctx->nbkref_ents].node = node;
4284 mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
4285 mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
4286 mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
4287
4288 /* This is a cache that saves negative results of check_dst_limits_calc_pos.
4289 If bit N is clear, means that this entry won't epsilon-transition to
4290 an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If
4291 it is set, check_dst_limits_calc_pos_1 will recurse and try to find one
4292 such node.
4293
4294 A backreference does not epsilon-transition unless it is empty, so set
4295 to all zeros if FROM != TO. */
4296 mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
4297 = (from == to ? -1 : 0);
4298
4299 mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
4300 if (mctx->max_mb_elem_len < to - from)
4301 mctx->max_mb_elem_len = to - from;
4302 return REG_NOERROR;
4303}
4304
4305/* Return the first entry with the same str_idx, or REG_MISSING if none is
4306 found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */
4307
4308static Idx
4309internal_function
4310search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx)
4311{
4312 Idx left, right, mid, last;
4313 last = right = mctx->nbkref_ents;
4314 for (left = 0; left < right;)
4315 {
4316 mid = (left + right) / 2;
4317 if (mctx->bkref_ents[mid].str_idx < str_idx)
4318 left = mid + 1;
4319 else
4320 right = mid;
4321 }
4322 if (left < last && mctx->bkref_ents[left].str_idx == str_idx)
4323 return left;
4324 else
4325 return REG_MISSING;
4326}
4327
4328/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
4329 at STR_IDX. */
4330
4331static reg_errcode_t
4332internal_function
4333match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx)
4334{
4335#ifdef DEBUG
4336 assert (mctx->sub_tops != NULL);
4337 assert (mctx->asub_tops > 0);
4338#endif
4339 if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
4340 {
4341 Idx new_asub_tops = mctx->asub_tops * 2;
4342 re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
4343 re_sub_match_top_t *,
4344 new_asub_tops);
4345 if (BE (new_array == NULL, 0))
4346 return REG_ESPACE;
4347 mctx->sub_tops = new_array;
4348 mctx->asub_tops = new_asub_tops;
4349 }
4350 mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
4351 if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0))
4352 return REG_ESPACE;
4353 mctx->sub_tops[mctx->nsub_tops]->node = node;
4354 mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
4355 return REG_NOERROR;
4356}
4357
4358/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
4359 at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */
4360
4361static re_sub_match_last_t *
4362internal_function
4363match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx)
4364{
4365 re_sub_match_last_t *new_entry;
4366 if (BE (subtop->nlasts == subtop->alasts, 0))
4367 {
4368 Idx new_alasts = 2 * subtop->alasts + 1;
4369 re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
4370 re_sub_match_last_t *,
4371 new_alasts);
4372 if (BE (new_array == NULL, 0))
4373 return NULL;
4374 subtop->lasts = new_array;
4375 subtop->alasts = new_alasts;
4376 }
4377 new_entry = calloc (1, sizeof (re_sub_match_last_t));
4378 if (BE (new_entry != NULL, 1))
4379 {
4380 subtop->lasts[subtop->nlasts] = new_entry;
4381 new_entry->node = node;
4382 new_entry->str_idx = str_idx;
4383 ++subtop->nlasts;
4384 }
4385 return new_entry;
4386}
4387
4388static void
4389internal_function
4390sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
4391 re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx)
4392{
4393 sctx->sifted_states = sifted_sts;
4394 sctx->limited_states = limited_sts;
4395 sctx->last_node = last_node;
4396 sctx->last_str_idx = last_str_idx;
4397 re_node_set_init_empty (&sctx->limits);
4398}
diff --git a/gl/safe-read.c b/gl/safe-read.c
new file mode 100644
index 00000000..b7bf1d5c
--- /dev/null
+++ b/gl/safe-read.c
@@ -0,0 +1,78 @@
1/* An interface to read and write that retries after interrupts.
2
3 Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free
4 Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22/* Specification. */
23#ifdef SAFE_WRITE
24# include "safe-write.h"
25#else
26# include "safe-read.h"
27#endif
28
29/* Get ssize_t. */
30#include <sys/types.h>
31#include <unistd.h>
32
33#include <errno.h>
34
35#ifdef EINTR
36# define IS_EINTR(x) ((x) == EINTR)
37#else
38# define IS_EINTR(x) 0
39#endif
40
41#include <limits.h>
42
43#ifdef SAFE_WRITE
44# define safe_rw safe_write
45# define rw write
46#else
47# define safe_rw safe_read
48# define rw read
49# undef const
50# define const /* empty */
51#endif
52
53/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
54 interrupted. Return the actual number of bytes read(written), zero for EOF,
55 or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */
56size_t
57safe_rw (int fd, void const *buf, size_t count)
58{
59 /* Work around a bug in Tru64 5.1. Attempting to read more than
60 INT_MAX bytes fails with errno == EINVAL. See
61 <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
62 When decreasing COUNT, keep it block-aligned. */
63 enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 };
64
65 for (;;)
66 {
67 ssize_t result = rw (fd, buf, count);
68
69 if (0 <= result)
70 return result;
71 else if (IS_EINTR (errno))
72 continue;
73 else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count)
74 count = BUGGY_READ_MAXIMUM;
75 else
76 return result;
77 }
78}
diff --git a/gl/safe-read.h b/gl/safe-read.h
new file mode 100644
index 00000000..3451955a
--- /dev/null
+++ b/gl/safe-read.h
@@ -0,0 +1,35 @@
1/* An interface to read() that retries after interrupts.
2 Copyright (C) 2002, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <stddef.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24
25#define SAFE_READ_ERROR ((size_t) -1)
26
27/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
28 Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
29 upon error. */
30extern size_t safe_read (int fd, void *buf, size_t count);
31
32
33#ifdef __cplusplus
34}
35#endif
diff --git a/gl/safe-write.c b/gl/safe-write.c
new file mode 100644
index 00000000..4c375a6c
--- /dev/null
+++ b/gl/safe-write.c
@@ -0,0 +1,19 @@
1/* An interface to write that retries after interrupts.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#define SAFE_WRITE
19#include "safe-read.c"
diff --git a/gl/safe-write.h b/gl/safe-write.h
new file mode 100644
index 00000000..c1946362
--- /dev/null
+++ b/gl/safe-write.h
@@ -0,0 +1,25 @@
1/* An interface to write() that retries after interrupts.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <stddef.h>
19
20#define SAFE_WRITE_ERROR ((size_t) -1)
21
22/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
23 Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR
24 upon error. */
25extern size_t safe_write (int fd, const void *buf, size_t count);
diff --git a/gl/size_max.h b/gl/size_max.h
new file mode 100644
index 00000000..ed0bc137
--- /dev/null
+++ b/gl/size_max.h
@@ -0,0 +1,31 @@
1/* size_max.h -- declare SIZE_MAX through system headers
2 Copyright (C) 2005-2006 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef GNULIB_SIZE_MAX_H
20#define GNULIB_SIZE_MAX_H
21
22/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */
23# include <limits.h>
24/* Get SIZE_MAX declaration on systems like glibc 2. */
25# if HAVE_STDINT_H
26# include <stdint.h>
27# endif
28/* On systems where these include files don't define it, SIZE_MAX is defined
29 in config.h. */
30
31#endif /* GNULIB_SIZE_MAX_H */
diff --git a/gl/snprintf.c b/gl/snprintf.c
new file mode 100644
index 00000000..db1ca9af
--- /dev/null
+++ b/gl/snprintf.c
@@ -0,0 +1,76 @@
1/* Formatted output to strings.
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3 Written by Simon Josefsson and Paul Eggert.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <config.h>
20
21#include "snprintf.h"
22
23#include <errno.h>
24#include <limits.h>
25#include <stdarg.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "vasnprintf.h"
30
31/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
32#ifndef EOVERFLOW
33# define EOVERFLOW E2BIG
34#endif
35
36/* Print formatted output to string STR. Similar to sprintf, but
37 additional length SIZE limit how much is written into STR. Returns
38 string length of formatted string (which may be larger than SIZE).
39 STR may be NULL, in which case nothing will be written. On error,
40 return a negative value. */
41int
42snprintf (char *str, size_t size, const char *format, ...)
43{
44 char *output;
45 size_t len;
46 size_t lenbuf = size;
47 va_list args;
48
49 va_start (args, format);
50 output = vasnprintf (str, &lenbuf, format, args);
51 len = lenbuf;
52 va_end (args);
53
54 if (!output)
55 return -1;
56
57 if (output != str)
58 {
59 if (size)
60 {
61 size_t pruned_len = (len < size ? len : size - 1);
62 memcpy (str, output, pruned_len);
63 str[pruned_len] = '\0';
64 }
65
66 free (output);
67 }
68
69 if (INT_MAX < len)
70 {
71 errno = EOVERFLOW;
72 return -1;
73 }
74
75 return len;
76}
diff --git a/gl/snprintf.h b/gl/snprintf.h
new file mode 100644
index 00000000..5032b9e8
--- /dev/null
+++ b/gl/snprintf.h
@@ -0,0 +1,29 @@
1/* Formatted output to strings.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef SNPRINTF_H
20#define SNPRINTF_H
21
22/* Get snprintf declaration, if available. */
23#include <stdio.h>
24
25#if defined HAVE_DECL_SNPRINTF && !HAVE_DECL_SNPRINTF
26int snprintf (char *str, size_t size, const char *format, ...);
27#endif
28
29#endif /* SNPRINTF_H */
diff --git a/gl/socket_.h b/gl/socket_.h
new file mode 100644
index 00000000..8b28b5ed
--- /dev/null
+++ b/gl/socket_.h
@@ -0,0 +1,70 @@
1/* Provide a sys/socket header file for systems lacking it (read: MinGW).
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _SYS_SOCKET_H
20#define _SYS_SOCKET_H
21
22/* This file is supposed to be used on platforms that lack
23 sys/socket.h. It is intended to provide definitions and prototypes
24 needed by an application.
25
26 Currently only MinGW is supported. See the gnulib manual regarding
27 Windows sockets. MinGW has the header files winsock2.h and
28 ws2tcpip.h that declare the sys/socket.h definitions we need. Note
29 that you can influence which definitions you get by setting the
30 WINVER symbol before including these two files. For example,
31 getaddrinfo is only available if _WIN32_WINNT >= 0x0501 (that
32 symbol is set indiriectly through WINVER). You can set this by
33 adding AC_DEFINE(WINVER, 0x0501) to configure.ac. Note that your
34 code may not run on older Windows releases then. My Windows 2000
35 box was not able to run the code, for example. The situation is
36 slightly confusing because:
37 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/getaddrinfo_2.asp
38 suggests that getaddrinfo should be available on all Windows
39 releases. */
40
41
42#if HAVE_WINSOCK2_H
43# include <winsock2.h>
44#endif
45#if HAVE_WS2TCPIP_H
46# include <ws2tcpip.h>
47#endif
48
49/* For shutdown(). */
50#if !defined SHUT_RD && defined SD_RECEIVE
51# define SHUT_RD SD_RECEIVE
52#endif
53#if !defined SHUT_WR && defined SD_SEND
54# define SHUT_WR SD_SEND
55#endif
56#if !defined SHUT_RDWR && defined SD_BOTH
57# define SHUT_RDWR SD_BOTH
58#endif
59
60#if defined _WIN32 || defined __WIN32__
61# define ENOTSOCK WSAENOTSOCK
62# define EADDRINUSE WSAEADDRINUSE
63# define ENETRESET WSAENETRESET
64# define ECONNABORTED WSAECONNABORTED
65# define ECONNRESET WSAECONNRESET
66# define ENOTCONN WSAENOTCONN
67# define ESHUTDOWN WSAESHUTDOWN
68#endif
69
70#endif /* _SYS_SOCKET_H */
diff --git a/gl/stdbool_.h b/gl/stdbool_.h
new file mode 100644
index 00000000..efa80ba9
--- /dev/null
+++ b/gl/stdbool_.h
@@ -0,0 +1,115 @@
1/* Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
2 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _STDBOOL_H
19#define _STDBOOL_H
20
21/* ISO C 99 <stdbool.h> for platforms that lack it. */
22
23/* Usage suggestions:
24
25 Programs that use <stdbool.h> should be aware of some limitations
26 and standards compliance issues.
27
28 Standards compliance:
29
30 - <stdbool.h> must be #included before 'bool', 'false', 'true'
31 can be used.
32
33 - You cannot assume that sizeof (bool) == 1.
34
35 - Programs should not undefine the macros bool, true, and false,
36 as C99 lists that as an "obsolescent feature".
37
38 Limitations of this substitute, when used in a C89 environment:
39
40 - <stdbool.h> must be #included before the '_Bool' type can be used.
41
42 - You cannot assume that _Bool is a typedef; it might be a macro.
43
44 - In C99, casts and automatic conversions to '_Bool' or 'bool' are
45 performed in such a way that every nonzero value gets converted
46 to 'true', and zero gets converted to 'false'. This doesn't work
47 with this substitute. With this substitute, only the values 0 and 1
48 give the expected result when converted to _Bool' or 'bool'.
49
50 Also, it is suggested that programs use 'bool' rather than '_Bool';
51 this isn't required, but 'bool' is more common. */
52
53
54/* 7.16. Boolean type and values */
55
56/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same
57 definitions below, but temporarily we have to #undef them. */
58#ifdef __BEOS__
59# include <OS.h> /* defines bool but not _Bool */
60# undef false
61# undef true
62#endif
63
64/* For the sake of symbolic names in gdb, we define true and false as
65 enum constants, not only as macros.
66 It is tempting to write
67 typedef enum { false = 0, true = 1 } _Bool;
68 so that gdb prints values of type 'bool' symbolically. But if we do
69 this, values of type '_Bool' may promote to 'int' or 'unsigned int'
70 (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
71 (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the
72 enum; this ensures that '_Bool' promotes to 'int'. */
73#if defined __cplusplus || defined __BEOS__
74 /* A compiler known to have 'bool'. */
75 /* If the compiler already has both 'bool' and '_Bool', we can assume they
76 are the same types. */
77# if !@HAVE__BOOL@
78typedef bool _Bool;
79# endif
80#else
81# if !defined __GNUC__
82 /* If @HAVE__BOOL@:
83 Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
84 the built-in _Bool type is used. See
85 http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
86 http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
87 http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
88 Similar bugs are likely with other compilers as well; this file
89 wouldn't be used if <stdbool.h> was working.
90 So we override the _Bool type.
91 If !@HAVE__BOOL@:
92 Need to define _Bool ourselves. As 'signed char' or as an enum type?
93 Use of a typedef, with SunPRO C, leads to a stupid
94 "warning: _Bool is a keyword in ISO C99".
95 Use of an enum type, with IRIX cc, leads to a stupid
96 "warning(1185): enumerated type mixed with another type".
97 The only benefit of the enum type, debuggability, is not important
98 with these compilers. So use 'signed char' and no typedef. */
99# define _Bool signed char
100enum { false = 0, true = 1 };
101# else
102 /* With this compiler, trust the _Bool type if the compiler has it. */
103# if !@HAVE__BOOL@
104typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
105# endif
106# endif
107#endif
108#define bool _Bool
109
110/* The other macros must be usable in preprocessor directives. */
111#define false 0
112#define true 1
113#define __bool_true_false_are_defined 1
114
115#endif /* _STDBOOL_H */
diff --git a/gl/stdint_.h b/gl/stdint_.h
new file mode 100644
index 00000000..64ec8c5b
--- /dev/null
+++ b/gl/stdint_.h
@@ -0,0 +1,489 @@
1/* Copyright (C) 2001-2002, 2004-2007 Free Software Foundation, Inc.
2 Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
3 This file is part of gnulib.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _GL_STDINT_H
20#define _GL_STDINT_H
21
22/*
23 * ISO C 99 <stdint.h> for platforms that lack it.
24 * <http://www.opengroup.org/susv3xbd/stdint.h.html>
25 */
26
27/* Get those types that are already defined in other system include
28 files, so that we can "#define int8_t signed char" below without
29 worrying about a later system include file containing a "typedef
30 signed char int8_t;" that will get messed up by our macro. Our
31 macros should all be consistent with the system versions, except
32 for the "fast" types and macros, which we recommend against using
33 in public interfaces due to compiler differences. */
34
35#if @HAVE_STDINT_H@
36# if defined __sgi && ! defined __c99
37 /* Bypass IRIX's <stdint.h> if in C89 mode, since it merely annoys users
38 with "This header file is to be used only for c99 mode compilations"
39 diagnostics. */
40# define __STDINT_H__
41# endif
42 /* Other systems may have an incomplete or buggy <stdint.h>.
43 Include it before <inttypes.h>, since any "#include <stdint.h>"
44 in <inttypes.h> would reinclude us, skipping our contents because
45 _GL_STDINT_H is defined. */
46# include @ABSOLUTE_STDINT_H@
47#endif
48
49/* <sys/types.h> defines some of the stdint.h types as well, on glibc,
50 IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>).
51 AIX 5.2 <sys/types.h> isn't needed and causes troubles.
52 MacOS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but
53 relies on the system <stdint.h> definitions, so include
54 <sys/types.h> after @ABSOLUTE_STDINT_H@. */
55#if @HAVE_SYS_TYPES_H@ && ! defined _AIX
56# include <sys/types.h>
57#endif
58
59/* Get LONG_MIN, LONG_MAX, ULONG_MAX. */
60#include <limits.h>
61
62#if @HAVE_INTTYPES_H@
63 /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines
64 int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
65 <inttypes.h> also defines intptr_t and uintptr_t. */
66# define _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
67# include <inttypes.h>
68# undef _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
69#elif @HAVE_SYS_INTTYPES_H@
70 /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
71 the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */
72# include <sys/inttypes.h>
73#endif
74
75#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__
76 /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines
77 int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is
78 included by <sys/types.h>. */
79# include <sys/bitypes.h>
80#endif
81
82#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS
83
84/* Get WCHAR_MIN, WCHAR_MAX. */
85# if ! (defined WCHAR_MIN && defined WCHAR_MAX)
86# include <wchar.h>
87# endif
88
89#endif
90
91/* Minimum and maximum values for a integer type under the usual assumption.
92 Return an unspecified value if BITS == 0, adding a check to pacify
93 picky compilers. */
94
95#define _STDINT_MIN(signed, bits, zero) \
96 ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero))
97
98#define _STDINT_MAX(signed, bits, zero) \
99 ((signed) \
100 ? ~ _STDINT_MIN (signed, bits, zero) \
101 : ((((zero) + 1) << ((bits) ? (bits) - 1 : 0)) - 1) * 2 + 1)
102
103/* 7.18.1.1. Exact-width integer types */
104
105/* Here we assume a standard architecture where the hardware integer
106 types have 8, 16, 32, optionally 64 bits. */
107
108#undef int8_t
109#undef uint8_t
110#define int8_t signed char
111#define uint8_t unsigned char
112
113#undef int16_t
114#undef uint16_t
115#define int16_t short int
116#define uint16_t unsigned short int
117
118#undef int32_t
119#undef uint32_t
120#define int32_t int
121#define uint32_t unsigned int
122
123#undef int64_t
124#if LONG_MAX >> 31 >> 31 == 1
125# define int64_t long int
126#elif defined _MSC_VER
127# define int64_t __int64
128#elif @HAVE_LONG_LONG_INT@
129# define int64_t long long int
130#endif
131
132#undef uint64_t
133#if ULONG_MAX >> 31 >> 31 >> 1 == 1
134# define uint64_t unsigned long int
135#elif defined _MSC_VER
136# define uint64_t unsigned __int64
137#elif @HAVE_UNSIGNED_LONG_LONG_INT@
138# define uint64_t unsigned long long int
139#endif
140
141/* Avoid collision with Solaris 2.5.1 <pthread.h> etc. */
142#define _UINT8_T
143#define _UINT32_T
144#define _UINT64_T
145
146
147/* 7.18.1.2. Minimum-width integer types */
148
149/* Here we assume a standard architecture where the hardware integer
150 types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
151 are the same as the corresponding N_t types. */
152
153#undef int_least8_t
154#undef uint_least8_t
155#undef int_least16_t
156#undef uint_least16_t
157#undef int_least32_t
158#undef uint_least32_t
159#undef int_least64_t
160#undef uint_least64_t
161#define int_least8_t int8_t
162#define uint_least8_t uint8_t
163#define int_least16_t int16_t
164#define uint_least16_t uint16_t
165#define int_least32_t int32_t
166#define uint_least32_t uint32_t
167#ifdef int64_t
168# define int_least64_t int64_t
169#endif
170#ifdef uint64_t
171# define uint_least64_t uint64_t
172#endif
173
174/* 7.18.1.3. Fastest minimum-width integer types */
175
176/* Note: Other <stdint.h> substitutes may define these types differently.
177 It is not recommended to use these types in public header files. */
178
179/* Here we assume a standard architecture where the hardware integer
180 types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
181 are taken from the same list of types. Assume that 'long int'
182 is fast enough for all narrower integers. */
183
184#undef int_fast8_t
185#undef uint_fast8_t
186#undef int_fast16_t
187#undef uint_fast16_t
188#undef int_fast32_t
189#undef uint_fast32_t
190#undef int_fast64_t
191#undef uint_fast64_t
192#define int_fast8_t long int
193#define uint_fast8_t unsigned int_fast8_t
194#define int_fast16_t long int
195#define uint_fast16_t unsigned int_fast16_t
196#define int_fast32_t long int
197#define uint_fast32_t unsigned int_fast32_t
198#ifdef int64_t
199# define int_fast64_t int64_t
200#endif
201#ifdef uint64_t
202# define uint_fast64_t uint64_t
203#endif
204
205/* 7.18.1.4. Integer types capable of holding object pointers */
206
207#undef intptr_t
208#undef uintptr_t
209#define intptr_t long int
210#define uintptr_t unsigned long int
211
212/* 7.18.1.5. Greatest-width integer types */
213
214/* Note: These types are compiler dependent. It may be unwise to use them in
215 public header files. */
216
217#undef intmax_t
218#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
219# define intmax_t long long int
220#elif defined int64_t
221# define intmax_t int64_t
222#else
223# define intmax_t long int
224#endif
225
226#undef uintmax_t
227#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
228# define uintmax_t unsigned long long int
229#elif defined uint64_t
230# define uintmax_t uint64_t
231#else
232# define uintmax_t unsigned long int
233#endif
234
235/* 7.18.2. Limits of specified-width integer types */
236
237#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS
238
239/* 7.18.2.1. Limits of exact-width integer types */
240
241/* Here we assume a standard architecture where the hardware integer
242 types have 8, 16, 32, optionally 64 bits. */
243
244#undef INT8_MIN
245#undef INT8_MAX
246#undef UINT8_MAX
247#define INT8_MIN (~ INT8_MAX)
248#define INT8_MAX 127
249#define UINT8_MAX 255
250
251#undef INT16_MIN
252#undef INT16_MAX
253#undef UINT16_MAX
254#define INT16_MIN (~ INT16_MAX)
255#define INT16_MAX 32767
256#define UINT16_MAX 65535
257
258#undef INT32_MIN
259#undef INT32_MAX
260#undef UINT32_MAX
261#define INT32_MIN (~ INT32_MAX)
262#define INT32_MAX 2147483647
263#define UINT32_MAX 4294967295U
264
265#undef INT64_MIN
266#undef INT64_MAX
267#ifdef int64_t
268# define INT64_MIN (~ INT64_MAX)
269# define INT64_MAX INTMAX_C (9223372036854775807)
270#endif
271
272#undef UINT64_MAX
273#ifdef uint64_t
274# define UINT64_MAX UINTMAX_C (18446744073709551615)
275#endif
276
277/* 7.18.2.2. Limits of minimum-width integer types */
278
279/* Here we assume a standard architecture where the hardware integer
280 types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
281 are the same as the corresponding N_t types. */
282
283#undef INT_LEAST8_MIN
284#undef INT_LEAST8_MAX
285#undef UINT_LEAST8_MAX
286#define INT_LEAST8_MIN INT8_MIN
287#define INT_LEAST8_MAX INT8_MAX
288#define UINT_LEAST8_MAX UINT8_MAX
289
290#undef INT_LEAST16_MIN
291#undef INT_LEAST16_MAX
292#undef UINT_LEAST16_MAX
293#define INT_LEAST16_MIN INT16_MIN
294#define INT_LEAST16_MAX INT16_MAX
295#define UINT_LEAST16_MAX UINT16_MAX
296
297#undef INT_LEAST32_MIN
298#undef INT_LEAST32_MAX
299#undef UINT_LEAST32_MAX
300#define INT_LEAST32_MIN INT32_MIN
301#define INT_LEAST32_MAX INT32_MAX
302#define UINT_LEAST32_MAX UINT32_MAX
303
304#undef INT_LEAST64_MIN
305#undef INT_LEAST64_MAX
306#ifdef int64_t
307# define INT_LEAST64_MIN INT64_MIN
308# define INT_LEAST64_MAX INT64_MAX
309#endif
310
311#undef UINT_LEAST64_MAX
312#ifdef uint64_t
313# define UINT_LEAST64_MAX UINT64_MAX
314#endif
315
316/* 7.18.2.3. Limits of fastest minimum-width integer types */
317
318/* Here we assume a standard architecture where the hardware integer
319 types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
320 are taken from the same list of types. */
321
322#undef INT_FAST8_MIN
323#undef INT_FAST8_MAX
324#undef UINT_FAST8_MAX
325#define INT_FAST8_MIN LONG_MIN
326#define INT_FAST8_MAX LONG_MAX
327#define UINT_FAST8_MAX ULONG_MAX
328
329#undef INT_FAST16_MIN
330#undef INT_FAST16_MAX
331#undef UINT_FAST16_MAX
332#define INT_FAST16_MIN LONG_MIN
333#define INT_FAST16_MAX LONG_MAX
334#define UINT_FAST16_MAX ULONG_MAX
335
336#undef INT_FAST32_MIN
337#undef INT_FAST32_MAX
338#undef UINT_FAST32_MAX
339#define INT_FAST32_MIN LONG_MIN
340#define INT_FAST32_MAX LONG_MAX
341#define UINT_FAST32_MAX ULONG_MAX
342
343#undef INT_FAST64_MIN
344#undef INT_FAST64_MAX
345#ifdef int64_t
346# define INT_FAST64_MIN INT64_MIN
347# define INT_FAST64_MAX INT64_MAX
348#endif
349
350#undef UINT_FAST64_MAX
351#ifdef uint64_t
352# define UINT_FAST64_MAX UINT64_MAX
353#endif
354
355/* 7.18.2.4. Limits of integer types capable of holding object pointers */
356
357#undef INTPTR_MIN
358#undef INTPTR_MAX
359#undef UINTPTR_MAX
360#define INTPTR_MIN LONG_MIN
361#define INTPTR_MAX LONG_MAX
362#define UINTPTR_MAX ULONG_MAX
363
364/* 7.18.2.5. Limits of greatest-width integer types */
365
366#undef INTMAX_MIN
367#undef INTMAX_MAX
368#define INTMAX_MIN (~ INTMAX_MAX)
369#ifdef INT64_MAX
370# define INTMAX_MAX INT64_MAX
371#else
372# define INTMAX_MAX INT32_MAX
373#endif
374
375#undef UINTMAX_MAX
376#ifdef UINT64_MAX
377# define UINTMAX_MAX UINT64_MAX
378#else
379# define UINTMAX_MAX UINT32_MAX
380#endif
381
382/* 7.18.3. Limits of other integer types */
383
384/* ptrdiff_t limits */
385#undef PTRDIFF_MIN
386#undef PTRDIFF_MAX
387#define PTRDIFF_MIN \
388 _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
389#define PTRDIFF_MAX \
390 _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
391
392/* sig_atomic_t limits */
393#undef SIG_ATOMIC_MIN
394#undef SIG_ATOMIC_MAX
395#define SIG_ATOMIC_MIN \
396 _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
397 0@SIG_ATOMIC_T_SUFFIX@)
398#define SIG_ATOMIC_MAX \
399 _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
400 0@SIG_ATOMIC_T_SUFFIX@)
401
402
403/* size_t limit */
404#undef SIZE_MAX
405#define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@)
406
407/* wchar_t limits */
408#undef WCHAR_MIN
409#undef WCHAR_MAX
410#define WCHAR_MIN \
411 _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
412#define WCHAR_MAX \
413 _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
414
415/* wint_t limits */
416#undef WINT_MIN
417#undef WINT_MAX
418#define WINT_MIN \
419 _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
420#define WINT_MAX \
421 _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
422
423#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */
424
425/* 7.18.4. Macros for integer constants */
426
427#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS
428
429/* 7.18.4.1. Macros for minimum-width integer constants */
430/* According to ISO C 99 Technical Corrigendum 1 */
431
432/* Here we assume a standard architecture where the hardware integer
433 types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */
434
435#undef INT8_C
436#undef UINT8_C
437#define INT8_C(x) x
438#define UINT8_C(x) x
439
440#undef INT16_C
441#undef UINT16_C
442#define INT16_C(x) x
443#define UINT16_C(x) x
444
445#undef INT32_C
446#undef UINT32_C
447#define INT32_C(x) x
448#define UINT32_C(x) x ## U
449
450#undef INT64_C
451#undef UINT64_C
452#if LONG_MAX >> 31 >> 31 == 1
453# define INT64_C(x) x##L
454#elif defined _MSC_VER
455# define INT64_C(x) x##i64
456#elif @HAVE_LONG_LONG_INT@
457# define INT64_C(x) x##LL
458#endif
459#if ULONG_MAX >> 31 >> 31 >> 1 == 1
460# define UINT64_C(x) x##UL
461#elif defined _MSC_VER
462# define UINT64_C(x) x##ui64
463#elif @HAVE_UNSIGNED_LONG_LONG_INT@
464# define UINT64_C(x) x##ULL
465#endif
466
467/* 7.18.4.2. Macros for greatest-width integer constants */
468
469#undef INTMAX_C
470#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
471# define INTMAX_C(x) x##LL
472#elif defined int64_t
473# define INTMAX_C(x) INT64_C(x)
474#else
475# define INTMAX_C(x) x##L
476#endif
477
478#undef UINTMAX_C
479#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
480# define UINTMAX_C(x) x##ULL
481#elif defined uint64_t
482# define UINTMAX_C(x) UINT64_C(x)
483#else
484# define UINTMAX_C(x) x##UL
485#endif
486
487#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */
488
489#endif /* _GL_STDINT_H */
diff --git a/gl/strcase.h b/gl/strcase.h
new file mode 100644
index 00000000..07d4c9a4
--- /dev/null
+++ b/gl/strcase.h
@@ -0,0 +1,56 @@
1/* Case-insensitive string comparison functions.
2 Copyright (C) 1995-1996, 2001, 2003, 2005-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _STRCASE_H
19#define _STRCASE_H
20
21#include <stddef.h>
22/* Include header files with a possibly conflicting declarations of strcasecmp
23 before we define it as a macro, so that they will be no-ops if included
24 after strcasecmp is defined as a macro. */
25#include <string.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31
32/* No known system has a strcasecmp() function that works correctly in
33 multibyte locales. Therefore we use our version always. */
34#define strcasecmp rpl_strcasecmp
35/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
36 greater than zero if S1 is lexicographically less than, equal to or greater
37 than S2.
38 Note: This function may, in multibyte locales, return 0 for strings of
39 different lengths! */
40extern int strcasecmp (const char *s1, const char *s2);
41
42/* Compare no more than N characters of strings S1 and S2, ignoring case,
43 returning less than, equal to or greater than zero if S1 is
44 lexicographically less than, equal to or greater than S2.
45 Note: This function can not work correctly in multibyte locales. */
46#if ! HAVE_DECL_STRNCASECMP
47extern int strncasecmp (const char *s1, const char *s2, size_t n);
48#endif
49
50
51#ifdef __cplusplus
52}
53#endif
54
55
56#endif /* _STRCASE_H */
diff --git a/gl/strcasecmp.c b/gl/strcasecmp.c
new file mode 100644
index 00000000..99d5dd22
--- /dev/null
+++ b/gl/strcasecmp.c
@@ -0,0 +1,103 @@
1/* Case-insensitive string comparison function.
2 Copyright (C) 1998-1999, 2005-2006 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2005,
4 based on earlier glibc code.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22/* Specification. */
23#include "strcase.h"
24
25#include <ctype.h>
26#include <limits.h>
27
28#if HAVE_MBRTOWC
29# include "mbuiter.h"
30#endif
31
32#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
33
34/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
35 greater than zero if S1 is lexicographically less than, equal to or greater
36 than S2.
37 Note: This function may, in multibyte locales, return 0 for strings of
38 different lengths! */
39int
40strcasecmp (const char *s1, const char *s2)
41{
42 if (s1 == s2)
43 return 0;
44
45 /* Be careful not to look at the entire extent of s1 or s2 until needed.
46 This is useful because when two strings differ, the difference is
47 most often already in the very few first characters. */
48#if HAVE_MBRTOWC
49 if (MB_CUR_MAX > 1)
50 {
51 mbui_iterator_t iter1;
52 mbui_iterator_t iter2;
53
54 mbui_init (iter1, s1);
55 mbui_init (iter2, s2);
56
57 while (mbui_avail (iter1) && mbui_avail (iter2))
58 {
59 int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
60
61 if (cmp != 0)
62 return cmp;
63
64 mbui_advance (iter1);
65 mbui_advance (iter2);
66 }
67 if (mbui_avail (iter1))
68 /* s2 terminated before s1. */
69 return 1;
70 if (mbui_avail (iter2))
71 /* s1 terminated before s2. */
72 return -1;
73 return 0;
74 }
75 else
76#endif
77 {
78 const unsigned char *p1 = (const unsigned char *) s1;
79 const unsigned char *p2 = (const unsigned char *) s2;
80 unsigned char c1, c2;
81
82 do
83 {
84 c1 = TOLOWER (*p1);
85 c2 = TOLOWER (*p2);
86
87 if (c1 == '\0')
88 break;
89
90 ++p1;
91 ++p2;
92 }
93 while (c1 == c2);
94
95 if (UCHAR_MAX <= INT_MAX)
96 return c1 - c2;
97 else
98 /* On machines where 'char' and 'int' are types of the same size, the
99 difference of two 'unsigned char' values - including the sign bit -
100 doesn't fit in an 'int'. */
101 return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
102 }
103}
diff --git a/gl/strdup.c b/gl/strdup.c
new file mode 100644
index 00000000..17d40d62
--- /dev/null
+++ b/gl/strdup.c
@@ -0,0 +1,55 @@
1/* Copyright (C) 1991, 1996, 1997, 1998, 2002, 2003, 2004, 2006 Free
2 Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef _LIBC
21# include <config.h>
22/* Get specification. */
23# include "strdup.h"
24#endif
25
26#include <stdlib.h>
27#include <string.h>
28
29#undef __strdup
30#ifdef _LIBC
31# undef strdup
32#endif
33
34#ifndef weak_alias
35# define __strdup strdup
36#endif
37
38/* Duplicate S, returning an identical malloc'd string. */
39char *
40__strdup (const char *s)
41{
42 size_t len = strlen (s) + 1;
43 void *new = malloc (len);
44
45 if (new == NULL)
46 return NULL;
47
48 return (char *) memcpy (new, s, len);
49}
50#ifdef libc_hidden_def
51libc_hidden_def (__strdup)
52#endif
53#ifdef weak_alias
54weak_alias (__strdup, strdup)
55#endif
diff --git a/gl/strdup.h b/gl/strdup.h
new file mode 100644
index 00000000..73e66e3d
--- /dev/null
+++ b/gl/strdup.h
@@ -0,0 +1,39 @@
1/* strdup.h -- duplicate a string
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef STRDUP_H_
19#define STRDUP_H_
20
21/* Get strdup declaration, if available. */
22#include <string.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28
29#if defined HAVE_DECL_STRDUP && !HAVE_DECL_STRDUP && !defined strdup
30/* Duplicate S, returning an identical malloc'd string. */
31extern char *strdup (const char *s);
32#endif
33
34
35#ifdef __cplusplus
36}
37#endif
38
39#endif /* STRDUP_H_ */
diff --git a/gl/stripslash.c b/gl/stripslash.c
new file mode 100644
index 00000000..342d497c
--- /dev/null
+++ b/gl/stripslash.c
@@ -0,0 +1,45 @@
1/* stripslash.c -- remove redundant trailing slashes from a file name
2
3 Copyright (C) 1990, 2001, 2003-2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <config.h>
20
21#include "dirname.h"
22
23/* Remove trailing slashes from FILE. Return true if a trailing slash
24 was removed. This is useful when using file name completion from a
25 shell that adds a "/" after directory names (such as tcsh and
26 bash), because on symlinks to directories, several system calls
27 have different semantics according to whether a trailing slash is
28 present. */
29
30bool
31strip_trailing_slashes (char *file)
32{
33 char *base = last_component (file);
34 char *base_lim;
35 bool had_slash;
36
37 /* last_component returns "" for file system roots, but we need to turn
38 `///' into `/'. */
39 if (! *base)
40 base = file;
41 base_lim = base + base_len (base);
42 had_slash = (*base_lim != '\0');
43 *base_lim = '\0';
44 return had_slash;
45}
diff --git a/gl/strncasecmp.c b/gl/strncasecmp.c
new file mode 100644
index 00000000..f59b953a
--- /dev/null
+++ b/gl/strncasecmp.c
@@ -0,0 +1,63 @@
1/* strncasecmp.c -- case insensitive string comparator
2 Copyright (C) 1998-1999, 2005-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "strcase.h"
22
23#include <ctype.h>
24#include <limits.h>
25
26#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
27
28/* Compare no more than N bytes of strings S1 and S2,
29 ignoring case, returning less than, equal to or
30 greater than zero if S1 is lexicographically less
31 than, equal to or greater than S2. */
32
33int
34strncasecmp (const char *s1, const char *s2, size_t n)
35{
36 register const unsigned char *p1 = (const unsigned char *) s1;
37 register const unsigned char *p2 = (const unsigned char *) s2;
38 unsigned char c1, c2;
39
40 if (p1 == p2 || n == 0)
41 return 0;
42
43 do
44 {
45 c1 = TOLOWER (*p1);
46 c2 = TOLOWER (*p2);
47
48 if (--n == 0 || c1 == '\0')
49 break;
50
51 ++p1;
52 ++p2;
53 }
54 while (c1 == c2);
55
56 if (UCHAR_MAX <= INT_MAX)
57 return c1 - c2;
58 else
59 /* On machines where 'char' and 'int' are types of the same size, the
60 difference of two 'unsigned char' values - including the sign bit -
61 doesn't fit in an 'int'. */
62 return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
63}
diff --git a/gl/strndup.c b/gl/strndup.c
new file mode 100644
index 00000000..290f494f
--- /dev/null
+++ b/gl/strndup.c
@@ -0,0 +1,39 @@
1/* A replacement function, for systems that lack strndup.
2
3 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006 Free
4 Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21#include "strndup.h"
22
23#include <stdlib.h>
24#include <string.h>
25
26#include "strnlen.h"
27
28char *
29strndup (char const *s, size_t n)
30{
31 size_t len = strnlen (s, n);
32 char *new = malloc (len + 1);
33
34 if (new == NULL)
35 return NULL;
36
37 new[len] = '\0';
38 return memcpy (new, s, len);
39}
diff --git a/gl/strndup.h b/gl/strndup.h
new file mode 100644
index 00000000..b983dd22
--- /dev/null
+++ b/gl/strndup.h
@@ -0,0 +1,32 @@
1/* Duplicate a size-bounded string.
2 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/* Get size_t. */
19#include <stddef.h>
20/* If HAVE_STRNDUP, get the strndup declaration.
21 If !HAVE_STRNDUP, include <string.h> now so that it doesn't cause
22 trouble if included later. */
23#include <string.h>
24
25#if !HAVE_STRNDUP
26# undef strndup
27# define strndup rpl_strndup
28# if !HAVE_DECL_STRNDUP /* Don't risk conflicting declarations. */
29/* Return a newly allocated copy of at most N bytes of STRING. */
30extern char *strndup (const char *string, size_t n);
31# endif
32#endif
diff --git a/gl/strnlen.c b/gl/strnlen.c
new file mode 100644
index 00000000..593fd1b7
--- /dev/null
+++ b/gl/strnlen.c
@@ -0,0 +1,31 @@
1/* Find the length of STRING, but scan at most MAXLEN characters.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <config.h>
20
21#include "strnlen.h"
22
23/* Find the length of STRING, but scan at most MAXLEN characters.
24 If no '\0' terminator is found in that many characters, return MAXLEN. */
25
26size_t
27strnlen (const char *string, size_t maxlen)
28{
29 const char *end = memchr (string, '\0', maxlen);
30 return end ? (size_t) (end - string) : maxlen;
31}
diff --git a/gl/strnlen.h b/gl/strnlen.h
new file mode 100644
index 00000000..ba74dba7
--- /dev/null
+++ b/gl/strnlen.h
@@ -0,0 +1,32 @@
1/* Find the length of STRING, but scan at most MAXLEN characters.
2 Copyright (C) 2005 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef STRNLEN_H
20#define STRNLEN_H
21
22/* Get strnlen declaration, if available. */
23#include <string.h>
24
25#if defined HAVE_DECL_STRNLEN && !HAVE_DECL_STRNLEN
26/* Find the length (number of bytes) of STRING, but scan at most
27 MAXLEN bytes. If no '\0' terminator is found in that many bytes,
28 return MAXLEN. */
29extern size_t strnlen(const char *string, size_t maxlen);
30#endif
31
32#endif /* STRNLEN_H */
diff --git a/gl/strnlen1.c b/gl/strnlen1.c
new file mode 100644
index 00000000..422ed9e8
--- /dev/null
+++ b/gl/strnlen1.c
@@ -0,0 +1,36 @@
1/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
2 Copyright (C) 2005-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "strnlen1.h"
22
23#include <string.h>
24
25/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
26 If no '\0' terminator is found in that many characters, return MAXLEN. */
27/* This is the same as strnlen (string, maxlen - 1) + 1. */
28size_t
29strnlen1 (const char *string, size_t maxlen)
30{
31 const char *end = (const char *) memchr (string, '\0', maxlen);
32 if (end != NULL)
33 return end - string + 1;
34 else
35 return maxlen;
36}
diff --git a/gl/strnlen1.h b/gl/strnlen1.h
new file mode 100644
index 00000000..7ce7d0c8
--- /dev/null
+++ b/gl/strnlen1.h
@@ -0,0 +1,40 @@
1/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
2 Copyright (C) 2005 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _STRNLEN1_H
19#define _STRNLEN1_H
20
21#include <stddef.h>
22
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28
29/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
30 If no '\0' terminator is found in that many characters, return MAXLEN. */
31/* This is the same as strnlen (string, maxlen - 1) + 1. */
32extern size_t strnlen1 (const char *string, size_t maxlen);
33
34
35#ifdef __cplusplus
36}
37#endif
38
39
40#endif /* _STRNLEN1_H */
diff --git a/gl/unistd--.h b/gl/unistd--.h
new file mode 100644
index 00000000..1fe6ce8b
--- /dev/null
+++ b/gl/unistd--.h
@@ -0,0 +1,28 @@
1/* Like unistd.h, but redefine some names to avoid glitches.
2
3 Copyright (C) 2005 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21#include <unistd.h>
22#include "unistd-safer.h"
23
24#undef dup
25#define dup dup_safer
26
27#undef pipe
28#define pipe pipe_safer
diff --git a/gl/unistd-safer.h b/gl/unistd-safer.h
new file mode 100644
index 00000000..f95999d3
--- /dev/null
+++ b/gl/unistd-safer.h
@@ -0,0 +1,23 @@
1/* Invoke unistd-like functions, but avoid some glitches.
2
3 Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Paul Eggert. */
20
21int dup_safer (int);
22int fd_safer (int);
23int pipe_safer (int[2]);
diff --git a/gl/unistd_.h b/gl/unistd_.h
new file mode 100644
index 00000000..36fa6731
--- /dev/null
+++ b/gl/unistd_.h
@@ -0,0 +1,52 @@
1/* Substitute for and wrapper around <unistd.h>.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _GL_UNISTD_H
19#define _GL_UNISTD_H
20
21#if HAVE_UNISTD_H
22# include @ABSOLUTE_UNISTD_H@
23#endif
24
25
26/* Declare overridden functions. */
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32#ifdef FCHDIR_REPLACEMENT
33
34/* Change the process' current working directory to the directory on which
35 the given file descriptor is open. */
36extern int fchdir (int /*fd*/);
37
38# define close rpl_close
39extern int close (int);
40# define dup rpl_dup
41extern int dup (int);
42# define dup2 rpl_dup2
43extern int dup2 (int, int);
44
45#endif
46
47#ifdef __cplusplus
48}
49#endif
50
51
52#endif /* _GL_UNISTD_H */
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
new file mode 100644
index 00000000..0fe2aada
--- /dev/null
+++ b/gl/vasnprintf.c
@@ -0,0 +1,889 @@
1/* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
19 This must come before <config.h> because <config.h> may include
20 <features.h>, and once <features.h> has been included, it's too late. */
21#ifndef _GNU_SOURCE
22# define _GNU_SOURCE 1
23#endif
24
25#include <config.h>
26#ifndef IN_LIBINTL
27# include <alloca.h>
28#endif
29
30/* Specification. */
31#if WIDE_CHAR_VERSION
32# include "vasnwprintf.h"
33#else
34# include "vasnprintf.h"
35#endif
36
37#include <stdio.h> /* snprintf(), sprintf() */
38#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
39#include <string.h> /* memcpy(), strlen() */
40#include <errno.h> /* errno */
41#include <limits.h> /* CHAR_BIT */
42#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
43#if WIDE_CHAR_VERSION
44# include "wprintf-parse.h"
45#else
46# include "printf-parse.h"
47#endif
48
49/* Checked size_t computations. */
50#include "xsize.h"
51
52#ifdef HAVE_WCHAR_T
53# ifdef HAVE_WCSLEN
54# define local_wcslen wcslen
55# else
56 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
57 a dependency towards this library, here is a local substitute.
58 Define this substitute only once, even if this file is included
59 twice in the same compilation unit. */
60# ifndef local_wcslen_defined
61# define local_wcslen_defined 1
62static size_t
63local_wcslen (const wchar_t *s)
64{
65 const wchar_t *ptr;
66
67 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
68 ;
69 return ptr - s;
70}
71# endif
72# endif
73#endif
74
75#if WIDE_CHAR_VERSION
76# define VASNPRINTF vasnwprintf
77# define CHAR_T wchar_t
78# define DIRECTIVE wchar_t_directive
79# define DIRECTIVES wchar_t_directives
80# define PRINTF_PARSE wprintf_parse
81# define USE_SNPRINTF 1
82# if HAVE_DECL__SNWPRINTF
83 /* On Windows, the function swprintf() has a different signature than
84 on Unix; we use the _snwprintf() function instead. */
85# define SNPRINTF _snwprintf
86# else
87 /* Unix. */
88# define SNPRINTF swprintf
89# endif
90#else
91# define VASNPRINTF vasnprintf
92# define CHAR_T char
93# define DIRECTIVE char_directive
94# define DIRECTIVES char_directives
95# define PRINTF_PARSE printf_parse
96# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
97# if HAVE_DECL__SNPRINTF
98 /* Windows. */
99# define SNPRINTF _snprintf
100# else
101 /* Unix. */
102# define SNPRINTF snprintf
103# endif
104#endif
105
106CHAR_T *
107VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
108{
109 DIRECTIVES d;
110 arguments a;
111
112 if (PRINTF_PARSE (format, &d, &a) < 0)
113 {
114 errno = EINVAL;
115 return NULL;
116 }
117
118#define CLEANUP() \
119 free (d.dir); \
120 if (a.arg) \
121 free (a.arg);
122
123 if (printf_fetchargs (args, &a) < 0)
124 {
125 CLEANUP ();
126 errno = EINVAL;
127 return NULL;
128 }
129
130 {
131 size_t buf_neededlength;
132 CHAR_T *buf;
133 CHAR_T *buf_malloced;
134 const CHAR_T *cp;
135 size_t i;
136 DIRECTIVE *dp;
137 /* Output string accumulator. */
138 CHAR_T *result;
139 size_t allocated;
140 size_t length;
141
142 /* Allocate a small buffer that will hold a directive passed to
143 sprintf or snprintf. */
144 buf_neededlength =
145 xsum4 (7, d.max_width_length, d.max_precision_length, 6);
146#if HAVE_ALLOCA
147 if (buf_neededlength < 4000 / sizeof (CHAR_T))
148 {
149 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
150 buf_malloced = NULL;
151 }
152 else
153#endif
154 {
155 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
156 if (size_overflow_p (buf_memsize))
157 goto out_of_memory_1;
158 buf = (CHAR_T *) malloc (buf_memsize);
159 if (buf == NULL)
160 goto out_of_memory_1;
161 buf_malloced = buf;
162 }
163
164 if (resultbuf != NULL)
165 {
166 result = resultbuf;
167 allocated = *lengthp;
168 }
169 else
170 {
171 result = NULL;
172 allocated = 0;
173 }
174 length = 0;
175 /* Invariants:
176 result is either == resultbuf or == NULL or malloc-allocated.
177 If length > 0, then result != NULL. */
178
179 /* Ensures that allocated >= needed. Aborts through a jump to
180 out_of_memory if needed is SIZE_MAX or otherwise too big. */
181#define ENSURE_ALLOCATION(needed) \
182 if ((needed) > allocated) \
183 { \
184 size_t memory_size; \
185 CHAR_T *memory; \
186 \
187 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
188 if ((needed) > allocated) \
189 allocated = (needed); \
190 memory_size = xtimes (allocated, sizeof (CHAR_T)); \
191 if (size_overflow_p (memory_size)) \
192 goto out_of_memory; \
193 if (result == resultbuf || result == NULL) \
194 memory = (CHAR_T *) malloc (memory_size); \
195 else \
196 memory = (CHAR_T *) realloc (result, memory_size); \
197 if (memory == NULL) \
198 goto out_of_memory; \
199 if (result == resultbuf && length > 0) \
200 memcpy (memory, result, length * sizeof (CHAR_T)); \
201 result = memory; \
202 }
203
204 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
205 {
206 if (cp != dp->dir_start)
207 {
208 size_t n = dp->dir_start - cp;
209 size_t augmented_length = xsum (length, n);
210
211 ENSURE_ALLOCATION (augmented_length);
212 memcpy (result + length, cp, n * sizeof (CHAR_T));
213 length = augmented_length;
214 }
215 if (i == d.count)
216 break;
217
218 /* Execute a single directive. */
219 if (dp->conversion == '%')
220 {
221 size_t augmented_length;
222
223 if (!(dp->arg_index == ARG_NONE))
224 abort ();
225 augmented_length = xsum (length, 1);
226 ENSURE_ALLOCATION (augmented_length);
227 result[length] = '%';
228 length = augmented_length;
229 }
230 else
231 {
232 if (!(dp->arg_index != ARG_NONE))
233 abort ();
234
235 if (dp->conversion == 'n')
236 {
237 switch (a.arg[dp->arg_index].type)
238 {
239 case TYPE_COUNT_SCHAR_POINTER:
240 *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
241 break;
242 case TYPE_COUNT_SHORT_POINTER:
243 *a.arg[dp->arg_index].a.a_count_short_pointer = length;
244 break;
245 case TYPE_COUNT_INT_POINTER:
246 *a.arg[dp->arg_index].a.a_count_int_pointer = length;
247 break;
248 case TYPE_COUNT_LONGINT_POINTER:
249 *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
250 break;
251#ifdef HAVE_LONG_LONG_INT
252 case TYPE_COUNT_LONGLONGINT_POINTER:
253 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
254 break;
255#endif
256 default:
257 abort ();
258 }
259 }
260 else
261 {
262 arg_type type = a.arg[dp->arg_index].type;
263 CHAR_T *p;
264 unsigned int prefix_count;
265 int prefixes[2];
266#if !USE_SNPRINTF
267 size_t tmp_length;
268 CHAR_T tmpbuf[700];
269 CHAR_T *tmp;
270
271 /* Allocate a temporary buffer of sufficient size for calling
272 sprintf. */
273 {
274 size_t width;
275 size_t precision;
276
277 width = 0;
278 if (dp->width_start != dp->width_end)
279 {
280 if (dp->width_arg_index != ARG_NONE)
281 {
282 int arg;
283
284 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
285 abort ();
286 arg = a.arg[dp->width_arg_index].a.a_int;
287 width = (arg < 0 ? (unsigned int) (-arg) : arg);
288 }
289 else
290 {
291 const CHAR_T *digitp = dp->width_start;
292
293 do
294 width = xsum (xtimes (width, 10), *digitp++ - '0');
295 while (digitp != dp->width_end);
296 }
297 }
298
299 precision = 6;
300 if (dp->precision_start != dp->precision_end)
301 {
302 if (dp->precision_arg_index != ARG_NONE)
303 {
304 int arg;
305
306 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
307 abort ();
308 arg = a.arg[dp->precision_arg_index].a.a_int;
309 precision = (arg < 0 ? 0 : arg);
310 }
311 else
312 {
313 const CHAR_T *digitp = dp->precision_start + 1;
314
315 precision = 0;
316 while (digitp != dp->precision_end)
317 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
318 }
319 }
320
321 switch (dp->conversion)
322 {
323
324 case 'd': case 'i': case 'u':
325# ifdef HAVE_LONG_LONG_INT
326 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
327 tmp_length =
328 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
329 * 0.30103 /* binary -> decimal */
330 )
331 + 1; /* turn floor into ceil */
332 else
333# endif
334 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
335 tmp_length =
336 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
337 * 0.30103 /* binary -> decimal */
338 )
339 + 1; /* turn floor into ceil */
340 else
341 tmp_length =
342 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
343 * 0.30103 /* binary -> decimal */
344 )
345 + 1; /* turn floor into ceil */
346 if (tmp_length < precision)
347 tmp_length = precision;
348 /* Multiply by 2, as an estimate for FLAG_GROUP. */
349 tmp_length = xsum (tmp_length, tmp_length);
350 /* Add 1, to account for a leading sign. */
351 tmp_length = xsum (tmp_length, 1);
352 break;
353
354 case 'o':
355# ifdef HAVE_LONG_LONG_INT
356 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
357 tmp_length =
358 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
359 * 0.333334 /* binary -> octal */
360 )
361 + 1; /* turn floor into ceil */
362 else
363# endif
364 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
365 tmp_length =
366 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
367 * 0.333334 /* binary -> octal */
368 )
369 + 1; /* turn floor into ceil */
370 else
371 tmp_length =
372 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
373 * 0.333334 /* binary -> octal */
374 )
375 + 1; /* turn floor into ceil */
376 if (tmp_length < precision)
377 tmp_length = precision;
378 /* Add 1, to account for a leading sign. */
379 tmp_length = xsum (tmp_length, 1);
380 break;
381
382 case 'x': case 'X':
383# ifdef HAVE_LONG_LONG_INT
384 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
385 tmp_length =
386 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
387 * 0.25 /* binary -> hexadecimal */
388 )
389 + 1; /* turn floor into ceil */
390 else
391# endif
392 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
393 tmp_length =
394 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
395 * 0.25 /* binary -> hexadecimal */
396 )
397 + 1; /* turn floor into ceil */
398 else
399 tmp_length =
400 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
401 * 0.25 /* binary -> hexadecimal */
402 )
403 + 1; /* turn floor into ceil */
404 if (tmp_length < precision)
405 tmp_length = precision;
406 /* Add 2, to account for a leading sign or alternate form. */
407 tmp_length = xsum (tmp_length, 2);
408 break;
409
410 case 'f': case 'F':
411# ifdef HAVE_LONG_DOUBLE
412 if (type == TYPE_LONGDOUBLE)
413 tmp_length =
414 (unsigned int) (LDBL_MAX_EXP
415 * 0.30103 /* binary -> decimal */
416 * 2 /* estimate for FLAG_GROUP */
417 )
418 + 1 /* turn floor into ceil */
419 + 10; /* sign, decimal point etc. */
420 else
421# endif
422 tmp_length =
423 (unsigned int) (DBL_MAX_EXP
424 * 0.30103 /* binary -> decimal */
425 * 2 /* estimate for FLAG_GROUP */
426 )
427 + 1 /* turn floor into ceil */
428 + 10; /* sign, decimal point etc. */
429 tmp_length = xsum (tmp_length, precision);
430 break;
431
432 case 'e': case 'E': case 'g': case 'G':
433 case 'a': case 'A':
434 tmp_length =
435 12; /* sign, decimal point, exponent etc. */
436 tmp_length = xsum (tmp_length, precision);
437 break;
438
439 case 'c':
440# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
441 if (type == TYPE_WIDE_CHAR)
442 tmp_length = MB_CUR_MAX;
443 else
444# endif
445 tmp_length = 1;
446 break;
447
448 case 's':
449# ifdef HAVE_WCHAR_T
450 if (type == TYPE_WIDE_STRING)
451 {
452 tmp_length =
453 local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
454
455# if !WIDE_CHAR_VERSION
456 tmp_length = xtimes (tmp_length, MB_CUR_MAX);
457# endif
458 }
459 else
460# endif
461 tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
462 break;
463
464 case 'p':
465 tmp_length =
466 (unsigned int) (sizeof (void *) * CHAR_BIT
467 * 0.25 /* binary -> hexadecimal */
468 )
469 + 1 /* turn floor into ceil */
470 + 2; /* account for leading 0x */
471 break;
472
473 default:
474 abort ();
475 }
476
477 if (tmp_length < width)
478 tmp_length = width;
479
480 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
481 }
482
483 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
484 tmp = tmpbuf;
485 else
486 {
487 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
488
489 if (size_overflow_p (tmp_memsize))
490 /* Overflow, would lead to out of memory. */
491 goto out_of_memory;
492 tmp = (CHAR_T *) malloc (tmp_memsize);
493 if (tmp == NULL)
494 /* Out of memory. */
495 goto out_of_memory;
496 }
497#endif
498
499 /* Construct the format string for calling snprintf or
500 sprintf. */
501 p = buf;
502 *p++ = '%';
503 if (dp->flags & FLAG_GROUP)
504 *p++ = '\'';
505 if (dp->flags & FLAG_LEFT)
506 *p++ = '-';
507 if (dp->flags & FLAG_SHOWSIGN)
508 *p++ = '+';
509 if (dp->flags & FLAG_SPACE)
510 *p++ = ' ';
511 if (dp->flags & FLAG_ALT)
512 *p++ = '#';
513 if (dp->flags & FLAG_ZERO)
514 *p++ = '0';
515 if (dp->width_start != dp->width_end)
516 {
517 size_t n = dp->width_end - dp->width_start;
518 memcpy (p, dp->width_start, n * sizeof (CHAR_T));
519 p += n;
520 }
521 if (dp->precision_start != dp->precision_end)
522 {
523 size_t n = dp->precision_end - dp->precision_start;
524 memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
525 p += n;
526 }
527
528 switch (type)
529 {
530#ifdef HAVE_LONG_LONG_INT
531 case TYPE_LONGLONGINT:
532 case TYPE_ULONGLONGINT:
533 *p++ = 'l';
534 /*FALLTHROUGH*/
535#endif
536 case TYPE_LONGINT:
537 case TYPE_ULONGINT:
538#ifdef HAVE_WINT_T
539 case TYPE_WIDE_CHAR:
540#endif
541#ifdef HAVE_WCHAR_T
542 case TYPE_WIDE_STRING:
543#endif
544 *p++ = 'l';
545 break;
546#ifdef HAVE_LONG_DOUBLE
547 case TYPE_LONGDOUBLE:
548 *p++ = 'L';
549 break;
550#endif
551 default:
552 break;
553 }
554 *p = dp->conversion;
555#if USE_SNPRINTF
556 p[1] = '%';
557 p[2] = 'n';
558 p[3] = '\0';
559#else
560 p[1] = '\0';
561#endif
562
563 /* Construct the arguments for calling snprintf or sprintf. */
564 prefix_count = 0;
565 if (dp->width_arg_index != ARG_NONE)
566 {
567 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
568 abort ();
569 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
570 }
571 if (dp->precision_arg_index != ARG_NONE)
572 {
573 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
574 abort ();
575 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
576 }
577
578#if USE_SNPRINTF
579 /* Prepare checking whether snprintf returns the count
580 via %n. */
581 ENSURE_ALLOCATION (xsum (length, 1));
582 result[length] = '\0';
583#endif
584
585 for (;;)
586 {
587 size_t maxlen;
588 int count;
589 int retcount;
590
591 maxlen = allocated - length;
592 count = -1;
593 retcount = 0;
594
595#if USE_SNPRINTF
596# define SNPRINTF_BUF(arg) \
597 switch (prefix_count) \
598 { \
599 case 0: \
600 retcount = SNPRINTF (result + length, maxlen, buf, \
601 arg, &count); \
602 break; \
603 case 1: \
604 retcount = SNPRINTF (result + length, maxlen, buf, \
605 prefixes[0], arg, &count); \
606 break; \
607 case 2: \
608 retcount = SNPRINTF (result + length, maxlen, buf, \
609 prefixes[0], prefixes[1], arg, \
610 &count); \
611 break; \
612 default: \
613 abort (); \
614 }
615#else
616# define SNPRINTF_BUF(arg) \
617 switch (prefix_count) \
618 { \
619 case 0: \
620 count = sprintf (tmp, buf, arg); \
621 break; \
622 case 1: \
623 count = sprintf (tmp, buf, prefixes[0], arg); \
624 break; \
625 case 2: \
626 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
627 arg); \
628 break; \
629 default: \
630 abort (); \
631 }
632#endif
633
634 switch (type)
635 {
636 case TYPE_SCHAR:
637 {
638 int arg = a.arg[dp->arg_index].a.a_schar;
639 SNPRINTF_BUF (arg);
640 }
641 break;
642 case TYPE_UCHAR:
643 {
644 unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
645 SNPRINTF_BUF (arg);
646 }
647 break;
648 case TYPE_SHORT:
649 {
650 int arg = a.arg[dp->arg_index].a.a_short;
651 SNPRINTF_BUF (arg);
652 }
653 break;
654 case TYPE_USHORT:
655 {
656 unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
657 SNPRINTF_BUF (arg);
658 }
659 break;
660 case TYPE_INT:
661 {
662 int arg = a.arg[dp->arg_index].a.a_int;
663 SNPRINTF_BUF (arg);
664 }
665 break;
666 case TYPE_UINT:
667 {
668 unsigned int arg = a.arg[dp->arg_index].a.a_uint;
669 SNPRINTF_BUF (arg);
670 }
671 break;
672 case TYPE_LONGINT:
673 {
674 long int arg = a.arg[dp->arg_index].a.a_longint;
675 SNPRINTF_BUF (arg);
676 }
677 break;
678 case TYPE_ULONGINT:
679 {
680 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
681 SNPRINTF_BUF (arg);
682 }
683 break;
684#ifdef HAVE_LONG_LONG_INT
685 case TYPE_LONGLONGINT:
686 {
687 long long int arg = a.arg[dp->arg_index].a.a_longlongint;
688 SNPRINTF_BUF (arg);
689 }
690 break;
691 case TYPE_ULONGLONGINT:
692 {
693 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
694 SNPRINTF_BUF (arg);
695 }
696 break;
697#endif
698 case TYPE_DOUBLE:
699 {
700 double arg = a.arg[dp->arg_index].a.a_double;
701 SNPRINTF_BUF (arg);
702 }
703 break;
704#ifdef HAVE_LONG_DOUBLE
705 case TYPE_LONGDOUBLE:
706 {
707 long double arg = a.arg[dp->arg_index].a.a_longdouble;
708 SNPRINTF_BUF (arg);
709 }
710 break;
711#endif
712 case TYPE_CHAR:
713 {
714 int arg = a.arg[dp->arg_index].a.a_char;
715 SNPRINTF_BUF (arg);
716 }
717 break;
718#ifdef HAVE_WINT_T
719 case TYPE_WIDE_CHAR:
720 {
721 wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
722 SNPRINTF_BUF (arg);
723 }
724 break;
725#endif
726 case TYPE_STRING:
727 {
728 const char *arg = a.arg[dp->arg_index].a.a_string;
729 SNPRINTF_BUF (arg);
730 }
731 break;
732#ifdef HAVE_WCHAR_T
733 case TYPE_WIDE_STRING:
734 {
735 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
736 SNPRINTF_BUF (arg);
737 }
738 break;
739#endif
740 case TYPE_POINTER:
741 {
742 void *arg = a.arg[dp->arg_index].a.a_pointer;
743 SNPRINTF_BUF (arg);
744 }
745 break;
746 default:
747 abort ();
748 }
749
750#if USE_SNPRINTF
751 /* Portability: Not all implementations of snprintf()
752 are ISO C 99 compliant. Determine the number of
753 bytes that snprintf() has produced or would have
754 produced. */
755 if (count >= 0)
756 {
757 /* Verify that snprintf() has NUL-terminated its
758 result. */
759 if (count < maxlen && result[length + count] != '\0')
760 abort ();
761 /* Portability hack. */
762 if (retcount > count)
763 count = retcount;
764 }
765 else
766 {
767 /* snprintf() doesn't understand the '%n'
768 directive. */
769 if (p[1] != '\0')
770 {
771 /* Don't use the '%n' directive; instead, look
772 at the snprintf() return value. */
773 p[1] = '\0';
774 continue;
775 }
776 else
777 {
778 /* Look at the snprintf() return value. */
779 if (retcount < 0)
780 {
781 /* HP-UX 10.20 snprintf() is doubly deficient:
782 It doesn't understand the '%n' directive,
783 *and* it returns -1 (rather than the length
784 that would have been required) when the
785 buffer is too small. */
786 size_t bigger_need =
787 xsum (xtimes (allocated, 2), 12);
788 ENSURE_ALLOCATION (bigger_need);
789 continue;
790 }
791 else
792 count = retcount;
793 }
794 }
795#endif
796
797 /* Attempt to handle failure. */
798 if (count < 0)
799 {
800 if (!(result == resultbuf || result == NULL))
801 free (result);
802 if (buf_malloced != NULL)
803 free (buf_malloced);
804 CLEANUP ();
805 errno = EINVAL;
806 return NULL;
807 }
808
809#if !USE_SNPRINTF
810 if (count >= tmp_length)
811 /* tmp_length was incorrectly calculated - fix the
812 code above! */
813 abort ();
814#endif
815
816 /* Make room for the result. */
817 if (count >= maxlen)
818 {
819 /* Need at least count bytes. But allocate
820 proportionally, to avoid looping eternally if
821 snprintf() reports a too small count. */
822 size_t n =
823 xmax (xsum (length, count), xtimes (allocated, 2));
824
825 ENSURE_ALLOCATION (n);
826#if USE_SNPRINTF
827 continue;
828#endif
829 }
830
831#if USE_SNPRINTF
832 /* The snprintf() result did fit. */
833#else
834 /* Append the sprintf() result. */
835 memcpy (result + length, tmp, count * sizeof (CHAR_T));
836 if (tmp != tmpbuf)
837 free (tmp);
838#endif
839
840 length += count;
841 break;
842 }
843 }
844 }
845 }
846
847 /* Add the final NUL. */
848 ENSURE_ALLOCATION (xsum (length, 1));
849 result[length] = '\0';
850
851 if (result != resultbuf && length + 1 < allocated)
852 {
853 /* Shrink the allocated memory if possible. */
854 CHAR_T *memory;
855
856 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
857 if (memory != NULL)
858 result = memory;
859 }
860
861 if (buf_malloced != NULL)
862 free (buf_malloced);
863 CLEANUP ();
864 *lengthp = length;
865 /* Note that we can produce a big string of a length > INT_MAX. POSIX
866 says that snprintf() fails with errno = EOVERFLOW in this case, but
867 that's only because snprintf() returns an 'int'. This function does
868 not have this limitation. */
869 return result;
870
871 out_of_memory:
872 if (!(result == resultbuf || result == NULL))
873 free (result);
874 if (buf_malloced != NULL)
875 free (buf_malloced);
876 out_of_memory_1:
877 CLEANUP ();
878 errno = ENOMEM;
879 return NULL;
880 }
881}
882
883#undef SNPRINTF
884#undef USE_SNPRINTF
885#undef PRINTF_PARSE
886#undef DIRECTIVES
887#undef DIRECTIVE
888#undef CHAR_T
889#undef VASNPRINTF
diff --git a/gl/vasnprintf.h b/gl/vasnprintf.h
new file mode 100644
index 00000000..894008ca
--- /dev/null
+++ b/gl/vasnprintf.h
@@ -0,0 +1,77 @@
1/* vsprintf with automatic memory allocation.
2 Copyright (C) 2002-2004 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _VASNPRINTF_H
19#define _VASNPRINTF_H
20
21/* Get va_list. */
22#include <stdarg.h>
23
24/* Get size_t. */
25#include <stddef.h>
26
27#ifndef __attribute__
28/* This feature is available in gcc versions 2.5 and later. */
29# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
30# define __attribute__(Spec) /* empty */
31# endif
32/* The __-protected variants of `format' and `printf' attributes
33 are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
34# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
35# define __format__ format
36# define __printf__ printf
37# endif
38#endif
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44/* Write formatted output to a string dynamically allocated with malloc().
45 You can pass a preallocated buffer for the result in RESULTBUF and its
46 size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
47 If successful, return the address of the string (this may be = RESULTBUF
48 if no dynamic memory allocation was necessary) and set *LENGTHP to the
49 number of resulting bytes, excluding the trailing NUL. Upon error, set
50 errno and return NULL.
51
52 When dynamic memory allocation occurs, the preallocated buffer is left
53 alone (with possibly modified contents). This makes it possible to use
54 a statically allocated or stack-allocated buffer, like this:
55
56 char buf[100];
57 size_t len = sizeof (buf);
58 char *output = vasnprintf (buf, &len, format, args);
59 if (output == NULL)
60 ... error handling ...;
61 else
62 {
63 ... use the output string ...;
64 if (output != buf)
65 free (output);
66 }
67 */
68extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
69 __attribute__ ((__format__ (__printf__, 3, 4)));
70extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
71 __attribute__ ((__format__ (__printf__, 3, 0)));
72
73#ifdef __cplusplus
74}
75#endif
76
77#endif /* _VASNPRINTF_H */
diff --git a/gl/vasprintf.c b/gl/vasprintf.c
new file mode 100644
index 00000000..82470734
--- /dev/null
+++ b/gl/vasprintf.c
@@ -0,0 +1,52 @@
1/* Formatted output to strings.
2 Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <config.h>
19
20/* Specification. */
21#include "vasprintf.h"
22
23#include <errno.h>
24#include <limits.h>
25#include <stdlib.h>
26
27#include "vasnprintf.h"
28
29/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
30#ifndef EOVERFLOW
31# define EOVERFLOW E2BIG
32#endif
33
34int
35vasprintf (char **resultp, const char *format, va_list args)
36{
37 size_t length;
38 char *result = vasnprintf (NULL, &length, format, args);
39 if (result == NULL)
40 return -1;
41
42 if (length > INT_MAX)
43 {
44 free (result);
45 errno = EOVERFLOW;
46 return -1;
47 }
48
49 *resultp = result;
50 /* Return the number of resulting bytes, excluding the trailing NUL. */
51 return length;
52}
diff --git a/gl/vasprintf.h b/gl/vasprintf.h
new file mode 100644
index 00000000..ab5515ce
--- /dev/null
+++ b/gl/vasprintf.h
@@ -0,0 +1,63 @@
1/* vsprintf with automatic memory allocation.
2 Copyright (C) 2002-2003 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _VASPRINTF_H
19#define _VASPRINTF_H
20
21#if HAVE_VASPRINTF
22
23/* Get asprintf(), vasprintf() declarations. */
24#include <stdio.h>
25
26#else
27
28/* Get va_list. */
29#include <stdarg.h>
30
31#ifndef __attribute__
32/* This feature is available in gcc versions 2.5 and later. */
33# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
34# define __attribute__(Spec) /* empty */
35# endif
36/* The __-protected variants of `format' and `printf' attributes
37 are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
38# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
39# define __format__ format
40# define __printf__ printf
41# endif
42#endif
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/* Write formatted output to a string dynamically allocated with malloc().
49 If the memory allocation succeeds, store the address of the string in
50 *RESULT and return the number of resulting bytes, excluding the trailing
51 NUL. Upon memory allocation error, or some other error, return -1. */
52extern int asprintf (char **result, const char *format, ...)
53 __attribute__ ((__format__ (__printf__, 2, 3)));
54extern int vasprintf (char **result, const char *format, va_list args)
55 __attribute__ ((__format__ (__printf__, 2, 0)));
56
57#ifdef __cplusplus
58}
59#endif
60
61#endif
62
63#endif /* _VASPRINTF_H */
diff --git a/gl/vsnprintf.c b/gl/vsnprintf.c
new file mode 100644
index 00000000..af567d2c
--- /dev/null
+++ b/gl/vsnprintf.c
@@ -0,0 +1,77 @@
1/* Formatted output to strings.
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3 Written by Simon Josefsson and Yoann Vandoorselaere <yoann@prelude-ids.org>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23/* Specification. */
24#include "vsnprintf.h"
25
26#include <errno.h>
27#include <limits.h>
28#include <stdarg.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "vasnprintf.h"
34
35/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
36#ifndef EOVERFLOW
37# define EOVERFLOW E2BIG
38#endif
39
40/* Print formatted output to string STR. Similar to vsprintf, but
41 additional length SIZE limit how much is written into STR. Returns
42 string length of formatted string (which may be larger than SIZE).
43 STR may be NULL, in which case nothing will be written. On error,
44 return a negative value. */
45int
46vsnprintf (char *str, size_t size, const char *format, va_list args)
47{
48 char *output;
49 size_t len;
50 size_t lenbuf = size;
51
52 output = vasnprintf (str, &lenbuf, format, args);
53 len = lenbuf;
54
55 if (!output)
56 return -1;
57
58 if (output != str)
59 {
60 if (size)
61 {
62 size_t pruned_len = (len < size ? len : size - 1);
63 memcpy (str, output, pruned_len);
64 str[pruned_len] = '\0';
65 }
66
67 free (output);
68 }
69
70 if (len > INT_MAX)
71 {
72 errno = EOVERFLOW;
73 return -1;
74 }
75
76 return len;
77}
diff --git a/gl/vsnprintf.h b/gl/vsnprintf.h
new file mode 100644
index 00000000..f80c77a9
--- /dev/null
+++ b/gl/vsnprintf.h
@@ -0,0 +1,31 @@
1/* Formatted output to strings.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Written by Simon Josefsson and Yoann Vandoorselaere <yoann@prelude-ids.org>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef VSNPRINTF_H
20#define VSNPRINTF_H
21
22#include <stdarg.h>
23
24/* Get vsnprintf declaration, if available. */
25#include <stdio.h>
26
27#if defined HAVE_DECL_VSNPRINTF && !HAVE_DECL_VSNPRINTF
28int vsnprintf (char *str, size_t size, const char *format, va_list args);
29#endif
30
31#endif /* VSNPRINTF_H */
diff --git a/gl/wchar_.h b/gl/wchar_.h
new file mode 100644
index 00000000..6813a211
--- /dev/null
+++ b/gl/wchar_.h
@@ -0,0 +1,42 @@
1/* A substitute for ISO C99 <wchar.h>, for platforms that have issues.
2
3 Copyright (C) 2007 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Eric Blake. */
20
21/*
22 * ISO C 99 <wchar.h> for platforms that have issues.
23 * <http://www.opengroup.org/susv3xbd/wchar.h.html>
24 *
25 * For now, this just ensures proper prerequisite inclusion order.
26 */
27
28#ifndef _GL_WCHAR_H
29#define _GL_WCHAR_H
30
31/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
32 <wchar.h>.
33 BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
34 included before <wchar.h>. */
35#include <stddef.h>
36#include <stdio.h>
37#include <time.h>
38
39/* Include the original <wchar.h>. */
40#include @ABSOLUTE_WCHAR_H@
41
42#endif /* _GL_WCHAR_H */
diff --git a/gl/wctype_.h b/gl/wctype_.h
new file mode 100644
index 00000000..1297c61e
--- /dev/null
+++ b/gl/wctype_.h
@@ -0,0 +1,154 @@
1/* A substitute for ISO C99 <wctype.h>, for platforms that lack it.
2
3 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* Written by Bruno Haible and Paul Eggert. */
20
21/*
22 * ISO C 99 <wctype.h> for platforms that lack it.
23 * <http://www.opengroup.org/susv3xbd/wctype.h.html>
24 *
25 * iswctype, towctrans, towlower, towupper, wctrans, wctype,
26 * wctrans_t, and wctype_t are not yet implemented.
27 */
28
29#ifndef _GL_WCTYPE_H
30#define _GL_WCTYPE_H
31
32#if @HAVE_WINT_T@
33/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.
34 Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
35 <wchar.h>.
36 BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
37 included before <wchar.h>. */
38# include <stddef.h>
39# include <stdio.h>
40# include <time.h>
41# include <wchar.h>
42typedef wint_t __wctype_wint_t;
43#else
44typedef int __wctype_wint_t;
45#endif
46
47/* Include the original <wctype.h> if it exists.
48 BeOS 5 has the functions but no <wctype.h>. */
49#if @HAVE_WCTYPE_H@
50# include @ABSOLUTE_WCTYPE_H@
51#endif
52
53/* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
54 Assume all 12 functions are implemented the same way, or not at all. */
55#if ! HAVE_ISWCNTRL
56
57/* IRIX 5.3 has macros but no functions, its isw* macros refer to an
58 undefined variable _ctmp_ and to <ctype.h> macros like _P, and they
59 refer to system functions like _iswctype that are not in the
60 standard C library. Rather than try to get ancient buggy
61 implementations like this to work, just disable them. */
62# undef iswalnum
63# undef iswalpha
64# undef iswblank
65# undef iswcntrl
66# undef iswdigit
67# undef iswgraph
68# undef iswlower
69# undef iswprint
70# undef iswpunct
71# undef iswspace
72# undef iswupper
73# undef iswxdigit
74
75static inline int
76iswalnum (__wctype_wint_t wc)
77{
78 return ((wc >= '0' && wc <= '9')
79 || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'));
80}
81
82static inline int
83iswalpha (__wctype_wint_t wc)
84{
85 return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z';
86}
87
88static inline int
89iswblank (__wctype_wint_t wc)
90{
91 return wc == ' ' || wc == '\t';
92}
93
94static inline int
95iswcntrl (__wctype_wint_t wc)
96{
97 return (wc & ~0x1f) == 0 || wc == 0x7f;
98}
99
100static inline int
101iswdigit (__wctype_wint_t wc)
102{
103 return wc >= '0' && wc <= '9';
104}
105
106static inline int
107iswgraph (__wctype_wint_t wc)
108{
109 return wc >= '!' && wc <= '~';
110}
111
112static inline int
113iswlower (__wctype_wint_t wc)
114{
115 return wc >= 'a' && wc <= 'z';
116}
117
118static inline int
119iswprint (__wctype_wint_t wc)
120{
121 return wc >= ' ' && wc <= '~';
122}
123
124static inline int
125iswpunct (__wctype_wint_t wc)
126{
127 return (wc >= '!' && wc <= '~'
128 && !((wc >= '0' && wc <= '9')
129 || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')));
130}
131
132static inline int
133iswspace (__wctype_wint_t wc)
134{
135 return (wc == ' ' || wc == '\t'
136 || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r');
137}
138
139static inline int
140iswupper (__wctype_wint_t wc)
141{
142 return wc >= 'A' && wc <= 'Z';
143}
144
145static inline int
146iswxdigit (__wctype_wint_t wc)
147{
148 return ((wc >= '0' && wc <= '9')
149 || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F'));
150}
151
152# endif /* ! HAVE_ISWCNTRL */
153
154#endif /* _GL_WCTYPE_H */
diff --git a/gl/wcwidth.h b/gl/wcwidth.h
new file mode 100644
index 00000000..8ed5ff8c
--- /dev/null
+++ b/gl/wcwidth.h
@@ -0,0 +1,57 @@
1/* Determine the number of screen columns needed for a character.
2 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _gl_WCWIDTH_H
19#define _gl_WCWIDTH_H
20
21#if HAVE_WCHAR_T
22
23/* Get wcwidth if available, along with wchar_t. */
24# include <wchar.h>
25
26/* Get iswprint. */
27# include <wctype.h>
28
29# ifndef HAVE_DECL_WCWIDTH
30"this configure-time declaration test was not run"
31# endif
32# ifndef wcwidth
33# if !HAVE_WCWIDTH
34
35/* wcwidth doesn't exist, so assume all printable characters have
36 width 1. */
37static inline int
38wcwidth (wchar_t wc)
39{
40 return wc == 0 ? 0 : iswprint (wc) ? 1 : -1;
41}
42
43# elif !HAVE_DECL_WCWIDTH
44
45/* wcwidth exists but is not declared. */
46extern
47# ifdef __cplusplus
48"C"
49# endif
50int wcwidth (int /* actually wchar_t */);
51
52# endif
53# endif
54
55#endif /* HAVE_WCHAR_T */
56
57#endif /* _gl_WCWIDTH_H */
diff --git a/gl/xalloc-die.c b/gl/xalloc-die.c
new file mode 100644
index 00000000..090f060d
--- /dev/null
+++ b/gl/xalloc-die.c
@@ -0,0 +1,42 @@
1/* Report a memory allocation failure and exit.
2
3 Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 Free
4 Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#include <config.h>
21
22#include "xalloc.h"
23
24#include <stdlib.h>
25
26#include "error.h"
27#include "exitfail.h"
28
29#include "gettext.h"
30#define _(msgid) gettext (msgid)
31
32void
33xalloc_die (void)
34{
35 error (exit_failure, 0, "%s", _("memory exhausted"));
36
37 /* The `noreturn' cannot be given to error, since it may return if
38 its first argument is 0. To help compilers understand the
39 xalloc_die does not return, call abort. Also, the abort is a
40 safety feature if exit_failure is 0 (which shouldn't happen). */
41 abort ();
42}
diff --git a/gl/xalloc.h b/gl/xalloc.h
new file mode 100644
index 00000000..17ab5142
--- /dev/null
+++ b/gl/xalloc.h
@@ -0,0 +1,267 @@
1/* xalloc.h -- malloc with out-of-memory checking
2
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20#ifndef XALLOC_H_
21# define XALLOC_H_
22
23# include <stddef.h>
24
25
26# ifdef __cplusplus
27extern "C" {
28# endif
29
30
31# ifndef __attribute__
32# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
33# define __attribute__(x)
34# endif
35# endif
36
37# ifndef ATTRIBUTE_NORETURN
38# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
39# endif
40
41/* This function is always triggered when memory is exhausted.
42 It must be defined by the application, either explicitly
43 or by using gnulib's xalloc-die module. This is the
44 function to call when one wants the program to die because of a
45 memory allocation failure. */
46extern void xalloc_die (void) ATTRIBUTE_NORETURN;
47
48void *xmalloc (size_t s);
49void *xzalloc (size_t s);
50void *xcalloc (size_t n, size_t s);
51void *xrealloc (void *p, size_t s);
52void *x2realloc (void *p, size_t *pn);
53void *xmemdup (void const *p, size_t s);
54char *xstrdup (char const *str);
55
56/* Return 1 if an array of N objects, each of size S, cannot exist due
57 to size arithmetic overflow. S must be positive and N must be
58 nonnegative. This is a macro, not an inline function, so that it
59 works correctly even when SIZE_MAX < N.
60
61 By gnulib convention, SIZE_MAX represents overflow in size
62 calculations, so the conservative dividend to use here is
63 SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
64 However, malloc (SIZE_MAX) fails on all known hosts where
65 sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
66 exactly-SIZE_MAX allocations on such hosts; this avoids a test and
67 branch when S is known to be 1. */
68# define xalloc_oversized(n, s) \
69 ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
70
71
72/* In the following macros, T must be an elementary or structure/union or
73 typedef'ed type, or a pointer to such a type. To apply one of the
74 following macros to a function pointer or array type, you need to typedef
75 it first and use the typedef name. */
76
77/* Allocate an object of type T dynamically, with error checking. */
78/* extern t *XMALLOC (typename t); */
79# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
80
81/* Allocate memory for N elements of type T, with error checking. */
82/* extern t *XNMALLOC (size_t n, typename t); */
83# define XNMALLOC(n, t) \
84 ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
85
86/* Allocate an object of type T dynamically, with error checking,
87 and zero it. */
88/* extern t *XZALLOC (typename t); */
89# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
90
91/* Allocate memory for N elements of type T, with error checking,
92 and zero it. */
93/* extern t *XCALLOC (size_t n, typename t); */
94# define XCALLOC(n, t) \
95 ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
96
97
98# if HAVE_INLINE
99# define static_inline static inline
100# else
101 void *xnmalloc (size_t n, size_t s);
102 void *xnrealloc (void *p, size_t n, size_t s);
103 void *x2nrealloc (void *p, size_t *pn, size_t s);
104 char *xcharalloc (size_t n);
105# endif
106
107# ifdef static_inline
108
109/* Allocate an array of N objects, each with S bytes of memory,
110 dynamically, with error checking. S must be nonzero. */
111
112static_inline void *
113xnmalloc (size_t n, size_t s)
114{
115 if (xalloc_oversized (n, s))
116 xalloc_die ();
117 return xmalloc (n * s);
118}
119
120/* Change the size of an allocated block of memory P to an array of N
121 objects each of S bytes, with error checking. S must be nonzero. */
122
123static_inline void *
124xnrealloc (void *p, size_t n, size_t s)
125{
126 if (xalloc_oversized (n, s))
127 xalloc_die ();
128 return xrealloc (p, n * s);
129}
130
131/* If P is null, allocate a block of at least *PN such objects;
132 otherwise, reallocate P so that it contains more than *PN objects
133 each of S bytes. *PN must be nonzero unless P is null, and S must
134 be nonzero. Set *PN to the new number of objects, and return the
135 pointer to the new block. *PN is never set to zero, and the
136 returned pointer is never null.
137
138 Repeated reallocations are guaranteed to make progress, either by
139 allocating an initial block with a nonzero size, or by allocating a
140 larger block.
141
142 In the following implementation, nonzero sizes are doubled so that
143 repeated reallocations have O(N log N) overall cost rather than
144 O(N**2) cost, but the specification for this function does not
145 guarantee that sizes are doubled.
146
147 Here is an example of use:
148
149 int *p = NULL;
150 size_t used = 0;
151 size_t allocated = 0;
152
153 void
154 append_int (int value)
155 {
156 if (used == allocated)
157 p = x2nrealloc (p, &allocated, sizeof *p);
158 p[used++] = value;
159 }
160
161 This causes x2nrealloc to allocate a block of some nonzero size the
162 first time it is called.
163
164 To have finer-grained control over the initial size, set *PN to a
165 nonzero value before calling this function with P == NULL. For
166 example:
167
168 int *p = NULL;
169 size_t used = 0;
170 size_t allocated = 0;
171 size_t allocated1 = 1000;
172
173 void
174 append_int (int value)
175 {
176 if (used == allocated)
177 {
178 p = x2nrealloc (p, &allocated1, sizeof *p);
179 allocated = allocated1;
180 }
181 p[used++] = value;
182 }
183
184 */
185
186static_inline void *
187x2nrealloc (void *p, size_t *pn, size_t s)
188{
189 size_t n = *pn;
190
191 if (! p)
192 {
193 if (! n)
194 {
195 /* The approximate size to use for initial small allocation
196 requests, when the invoking code specifies an old size of
197 zero. 64 bytes is the largest "small" request for the
198 GNU C library malloc. */
199 enum { DEFAULT_MXFAST = 64 };
200
201 n = DEFAULT_MXFAST / s;
202 n += !n;
203 }
204 }
205 else
206 {
207 if (((size_t) -1) / 2 / s < n)
208 xalloc_die ();
209 n *= 2;
210 }
211
212 *pn = n;
213 return xrealloc (p, n * s);
214}
215
216/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
217 except it returns char *. */
218
219static_inline char *
220xcharalloc (size_t n)
221{
222 return XNMALLOC (n, char);
223}
224
225# endif
226
227# ifdef __cplusplus
228}
229
230/* C++ does not allow conversions from void * to other pointer types
231 without a cast. Use templates to work around the problem when
232 possible. */
233
234template <typename T> inline T *
235xrealloc (T *p, size_t s)
236{
237 return (T *) xrealloc ((void *) p, s);
238}
239
240template <typename T> inline T *
241xnrealloc (T *p, size_t n, size_t s)
242{
243 return (T *) xnrealloc ((void *) p, n, s);
244}
245
246template <typename T> inline T *
247x2realloc (T *p, size_t *pn)
248{
249 return (T *) x2realloc ((void *) p, pn);
250}
251
252template <typename T> inline T *
253x2nrealloc (T *p, size_t *pn, size_t s)
254{
255 return (T *) x2nrealloc ((void *) p, pn, s);
256}
257
258template <typename T> inline T *
259xmemdup (T const *p, size_t s)
260{
261 return (T *) xmemdup ((void const *) p, s);
262}
263
264# endif
265
266
267#endif /* !XALLOC_H_ */
diff --git a/gl/xmalloc.c b/gl/xmalloc.c
new file mode 100644
index 00000000..318e0ddb
--- /dev/null
+++ b/gl/xmalloc.c
@@ -0,0 +1,123 @@
1/* xmalloc.c -- malloc with out of memory checking
2
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
5 Inc.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program 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 General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include <config.h>
22
23#if ! HAVE_INLINE
24# define static_inline
25#endif
26#include "xalloc.h"
27#undef static_inline
28
29#include <stdlib.h>
30#include <string.h>
31
32#ifndef SIZE_MAX
33# define SIZE_MAX ((size_t) -1)
34#endif
35
36/* 1 if calloc is known to be compatible with GNU calloc. This
37 matters if we are not also using the calloc module, which defines
38 HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
39#if defined HAVE_CALLOC || defined __GLIBC__
40enum { HAVE_GNU_CALLOC = 1 };
41#else
42enum { HAVE_GNU_CALLOC = 0 };
43#endif
44
45/* Allocate N bytes of memory dynamically, with error checking. */
46
47void *
48xmalloc (size_t n)
49{
50 void *p = malloc (n);
51 if (!p && n != 0)
52 xalloc_die ();
53 return p;
54}
55
56/* Change the size of an allocated block of memory P to N bytes,
57 with error checking. */
58
59void *
60xrealloc (void *p, size_t n)
61{
62 p = realloc (p, n);
63 if (!p && n != 0)
64 xalloc_die ();
65 return p;
66}
67
68/* If P is null, allocate a block of at least *PN bytes; otherwise,
69 reallocate P so that it contains more than *PN bytes. *PN must be
70 nonzero unless P is null. Set *PN to the new block's size, and
71 return the pointer to the new block. *PN is never set to zero, and
72 the returned pointer is never null. */
73
74void *
75x2realloc (void *p, size_t *pn)
76{
77 return x2nrealloc (p, pn, 1);
78}
79
80/* Allocate S bytes of zeroed memory dynamically, with error checking.
81 There's no need for xnzalloc (N, S), since it would be equivalent
82 to xcalloc (N, S). */
83
84void *
85xzalloc (size_t s)
86{
87 return memset (xmalloc (s), 0, s);
88}
89
90/* Allocate zeroed memory for N elements of S bytes, with error
91 checking. S must be nonzero. */
92
93void *
94xcalloc (size_t n, size_t s)
95{
96 void *p;
97 /* Test for overflow, since some calloc implementations don't have
98 proper overflow checks. But omit overflow and size-zero tests if
99 HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
100 returns NULL if successful. */
101 if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
102 || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
103 xalloc_die ();
104 return p;
105}
106
107/* Clone an object P of size S, with error checking. There's no need
108 for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
109 need for an arithmetic overflow check. */
110
111void *
112xmemdup (void const *p, size_t s)
113{
114 return memcpy (xmalloc (s), p, s);
115}
116
117/* Clone STRING. */
118
119char *
120xstrdup (char const *string)
121{
122 return xmemdup (string, strlen (string) + 1);
123}
diff --git a/gl/xsize.h b/gl/xsize.h
new file mode 100644
index 00000000..341fb16c
--- /dev/null
+++ b/gl/xsize.h
@@ -0,0 +1,108 @@
1/* xsize.h -- Checked size_t computations.
2
3 Copyright (C) 2003 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#ifndef _XSIZE_H
20#define _XSIZE_H
21
22/* Get size_t. */
23#include <stddef.h>
24
25/* Get SIZE_MAX. */
26#include <limits.h>
27#if HAVE_STDINT_H
28# include <stdint.h>
29#endif
30
31/* The size of memory objects is often computed through expressions of
32 type size_t. Example:
33 void* p = malloc (header_size + n * element_size).
34 These computations can lead to overflow. When this happens, malloc()
35 returns a piece of memory that is way too small, and the program then
36 crashes while attempting to fill the memory.
37 To avoid this, the functions and macros in this file check for overflow.
38 The convention is that SIZE_MAX represents overflow.
39 malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
40 implementation that uses mmap --, it's recommended to use size_overflow_p()
41 or size_in_bounds_p() before invoking malloc().
42 The example thus becomes:
43 size_t size = xsum (header_size, xtimes (n, element_size));
44 void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
45*/
46
47/* Convert an arbitrary value >= 0 to type size_t. */
48#define xcast_size_t(N) \
49 ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
50
51/* Sum of two sizes, with overflow check. */
52static inline size_t
53#if __GNUC__ >= 3
54__attribute__ ((__pure__))
55#endif
56xsum (size_t size1, size_t size2)
57{
58 size_t sum = size1 + size2;
59 return (sum >= size1 ? sum : SIZE_MAX);
60}
61
62/* Sum of three sizes, with overflow check. */
63static inline size_t
64#if __GNUC__ >= 3
65__attribute__ ((__pure__))
66#endif
67xsum3 (size_t size1, size_t size2, size_t size3)
68{
69 return xsum (xsum (size1, size2), size3);
70}
71
72/* Sum of four sizes, with overflow check. */
73static inline size_t
74#if __GNUC__ >= 3
75__attribute__ ((__pure__))
76#endif
77xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
78{
79 return xsum (xsum (xsum (size1, size2), size3), size4);
80}
81
82/* Maximum of two sizes, with overflow check. */
83static inline size_t
84#if __GNUC__ >= 3
85__attribute__ ((__pure__))
86#endif
87xmax (size_t size1, size_t size2)
88{
89 /* No explicit check is needed here, because for any n:
90 max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
91 return (size1 >= size2 ? size1 : size2);
92}
93
94/* Multiplication of a count with an element size, with overflow check.
95 The count must be >= 0 and the element size must be > 0.
96 This is a macro, not an inline function, so that it works correctly even
97 when N is of a wider tupe and N > SIZE_MAX. */
98#define xtimes(N, ELSIZE) \
99 ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
100
101/* Check for overflow. */
102#define size_overflow_p(SIZE) \
103 ((SIZE) == SIZE_MAX)
104/* Check against overflow. */
105#define size_in_bounds_p(SIZE) \
106 ((SIZE) != SIZE_MAX)
107
108#endif /* _XSIZE_H */
diff --git a/gl/xstrndup.c b/gl/xstrndup.c
new file mode 100644
index 00000000..afcbc1ab
--- /dev/null
+++ b/gl/xstrndup.c
@@ -0,0 +1,37 @@
1/* Duplicate a bounded initial segment of a string, with out-of-memory
2 checking.
3 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <config.h>
20
21/* Specification. */
22#include "xstrndup.h"
23
24#include "strndup.h"
25#include "xalloc.h"
26
27/* Return a newly allocated copy of at most N bytes of STRING.
28 In other words, return a copy of the initial segment of length N of
29 STRING. */
30char *
31xstrndup (const char *string, size_t n)
32{
33 char *s = strndup (string, n);
34 if (! s)
35 xalloc_die ();
36 return s;
37}
diff --git a/gl/xstrndup.h b/gl/xstrndup.h
new file mode 100644
index 00000000..88354cfd
--- /dev/null
+++ b/gl/xstrndup.h
@@ -0,0 +1,24 @@
1/* Duplicate a bounded initial segment of a string, with out-of-memory
2 checking.
3 Copyright (C) 2003 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <stddef.h>
20
21/* Return a newly allocated copy of at most N bytes of STRING.
22 In other words, return a copy of the initial segment of length N of
23 STRING. */
24extern char *xstrndup (const char *string, size_t n);