Added to the repository by gnulib-sync
Showing
15 changed files
with
2345 additions
and
0 deletions
lib/allocsa.c
0 → 100644
1 | /* Safe automatic memory allocation. | ||
2 | Copyright (C) 2003 Free Software Foundation, Inc. | ||
3 | Written by Bruno Haible <bruno@clisp.org>, 2003. | ||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | /* Specification. */ | ||
24 | #include "allocsa.h" | ||
25 | |||
26 | /* The speed critical point in this file is freesa() applied to an alloca() | ||
27 | result: it must be fast, to match the speed of alloca(). The speed of | ||
28 | mallocsa() and freesa() in the other case are not critical, because they | ||
29 | are only invoked for big memory sizes. */ | ||
30 | |||
31 | #if HAVE_ALLOCA | ||
32 | |||
33 | /* Store the mallocsa() results in a hash table. This is needed to reliably | ||
34 | distinguish a mallocsa() result and an alloca() result. | ||
35 | |||
36 | Although it is possible that the same pointer is returned by alloca() and | ||
37 | by mallocsa() at different times in the same application, it does not lead | ||
38 | to a bug in freesa(), because: | ||
39 | - Before a pointer returned by alloca() can point into malloc()ed memory, | ||
40 | the function must return, and once this has happened the programmer must | ||
41 | not call freesa() on it anyway. | ||
42 | - Before a pointer returned by mallocsa() can point into the stack, it | ||
43 | must be freed. The only function that can free it is freesa(), and | ||
44 | when freesa() frees it, it also removes it from the hash table. */ | ||
45 | |||
46 | #define MAGIC_NUMBER 0x1415fb4a | ||
47 | #define MAGIC_SIZE sizeof (int) | ||
48 | /* This is how the header info would look like without any alignment | ||
49 | considerations. */ | ||
50 | struct preliminary_header { void *next; char room[MAGIC_SIZE]; }; | ||
51 | /* But the header's size must be a multiple of sa_alignment_max. */ | ||
52 | #define HEADER_SIZE \ | ||
53 | (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) | ||
54 | struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; }; | ||
55 | /* Verify that HEADER_SIZE == sizeof (struct header). */ | ||
56 | typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1]; | ||
57 | /* We make the hash table quite big, so that during lookups the probability | ||
58 | of empty hash buckets is quite high. There is no need to make the hash | ||
59 | table resizable, because when the hash table gets filled so much that the | ||
60 | lookup becomes slow, it means that the application has memory leaks. */ | ||
61 | #define HASH_TABLE_SIZE 257 | ||
62 | static void * mallocsa_results[HASH_TABLE_SIZE]; | ||
63 | |||
64 | #endif | ||
65 | |||
66 | void * | ||
67 | mallocsa (size_t n) | ||
68 | { | ||
69 | #if HAVE_ALLOCA | ||
70 | /* Allocate one more word, that serves as an indicator for malloc()ed | ||
71 | memory, so that freesa() of an alloca() result is fast. */ | ||
72 | size_t nplus = n + HEADER_SIZE; | ||
73 | |||
74 | if (nplus >= n) | ||
75 | { | ||
76 | char *p = (char *) malloc (nplus); | ||
77 | |||
78 | if (p != NULL) | ||
79 | { | ||
80 | size_t slot; | ||
81 | |||
82 | p += HEADER_SIZE; | ||
83 | |||
84 | /* Put a magic number into the indicator word. */ | ||
85 | ((int *) p)[-1] = MAGIC_NUMBER; | ||
86 | |||
87 | /* Enter p into the hash table. */ | ||
88 | slot = (unsigned long) p % HASH_TABLE_SIZE; | ||
89 | ((struct header *) (p - HEADER_SIZE))->next = mallocsa_results[slot]; | ||
90 | mallocsa_results[slot] = p; | ||
91 | |||
92 | return p; | ||
93 | } | ||
94 | } | ||
95 | /* Out of memory. */ | ||
96 | return NULL; | ||
97 | #else | ||
98 | # if !MALLOC_0_IS_NONNULL | ||
99 | if (n == 0) | ||
100 | n = 1; | ||
101 | # endif | ||
102 | return malloc (n); | ||
103 | #endif | ||
104 | } | ||
105 | |||
106 | #if HAVE_ALLOCA | ||
107 | void | ||
108 | freesa (void *p) | ||
109 | { | ||
110 | /* mallocsa() may have returned NULL. */ | ||
111 | if (p != NULL) | ||
112 | { | ||
113 | /* Attempt to quickly distinguish the mallocsa() result - which has | ||
114 | a magic indicator word - and the alloca() result - which has an | ||
115 | uninitialized indicator word. It is for this test that sa_increment | ||
116 | additional bytes are allocated in the alloca() case. */ | ||
117 | if (((int *) p)[-1] == MAGIC_NUMBER) | ||
118 | { | ||
119 | /* Looks like a mallocsa() result. To see whether it really is one, | ||
120 | perform a lookup in the hash table. */ | ||
121 | size_t slot = (unsigned long) p % HASH_TABLE_SIZE; | ||
122 | void **chain = &mallocsa_results[slot]; | ||
123 | for (; *chain != NULL;) | ||
124 | { | ||
125 | if (*chain == p) | ||
126 | { | ||
127 | /* Found it. Remove it from the hash table and free it. */ | ||
128 | char *p_begin = (char *) p - HEADER_SIZE; | ||
129 | *chain = ((struct header *) p_begin)->next; | ||
130 | free (p_begin); | ||
131 | return; | ||
132 | } | ||
133 | chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next; | ||
134 | } | ||
135 | } | ||
136 | /* At this point, we know it was not a mallocsa() result. */ | ||
137 | } | ||
138 | } | ||
139 | #endif |
lib/allocsa.h
0 → 100644
1 | /* Safe automatic memory allocation. | ||
2 | Copyright (C) 2003-2004 Free Software Foundation, Inc. | ||
3 | Written by Bruno Haible <bruno@clisp.org>, 2003. | ||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
18 | |||
19 | #ifndef _ALLOCSA_H | ||
20 | #define _ALLOCSA_H | ||
21 | |||
22 | #include <alloca.h> | ||
23 | #include <stddef.h> | ||
24 | #include <stdlib.h> | ||
25 | |||
26 | /* safe_alloca(N) is equivalent to alloca(N) when it is safe to call | ||
27 | alloca(N); otherwise it returns NULL. It either returns N bytes of | ||
28 | memory allocated on the stack, that lasts until the function returns, | ||
29 | or NULL. | ||
30 | Use of safe_alloca should be avoided: | ||
31 | - inside arguments of function calls - undefined behaviour, | ||
32 | - in inline functions - the allocation may actually last until the | ||
33 | calling function returns. | ||
34 | */ | ||
35 | #if HAVE_ALLOCA | ||
36 | /* The OS usually guarantees only one guard page at the bottom of the stack, | ||
37 | and a page size can be as small as 4096 bytes. So we cannot safely | ||
38 | allocate anything larger than 4096 bytes. Also care for the possibility | ||
39 | of a few compiler-allocated temporary stack slots. | ||
40 | This must be a macro, not an inline function. */ | ||
41 | # define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) | ||
42 | #else | ||
43 | # define safe_alloca(N) ((N), NULL) | ||
44 | #endif | ||
45 | |||
46 | /* allocsa(N) is a safe variant of alloca(N). It allocates N bytes of | ||
47 | memory allocated on the stack, that must be freed using freesa() before | ||
48 | the function returns. Upon failure, it returns NULL. */ | ||
49 | #if HAVE_ALLOCA | ||
50 | # define allocsa(N) \ | ||
51 | ((N) < 4032 - sa_increment \ | ||
52 | ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ | ||
53 | : mallocsa (N)) | ||
54 | #else | ||
55 | # define allocsa(N) \ | ||
56 | mallocsa (N) | ||
57 | #endif | ||
58 | extern void * mallocsa (size_t n); | ||
59 | |||
60 | /* Free a block of memory allocated through allocsa(). */ | ||
61 | #if HAVE_ALLOCA | ||
62 | extern void freesa (void *p); | ||
63 | #else | ||
64 | # define freesa free | ||
65 | #endif | ||
66 | |||
67 | /* Maybe we should also define a variant | ||
68 | nallocsa (size_t n, size_t s) - behaves like allocsa (n * s) | ||
69 | If this would be useful in your application. please speak up. */ | ||
70 | |||
71 | |||
72 | /* ------------------- Auxiliary, non-public definitions ------------------- */ | ||
73 | |||
74 | /* Determine the alignment of a type at compile time. */ | ||
75 | #if defined __GNUC__ | ||
76 | # define sa_alignof __alignof__ | ||
77 | #elif defined __cplusplus | ||
78 | template <class type> struct sa_alignof_helper { char __slot1; type __slot2; }; | ||
79 | # define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2) | ||
80 | #elif defined __hpux | ||
81 | /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof | ||
82 | values. */ | ||
83 | # define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) | ||
84 | #else | ||
85 | # define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) | ||
86 | #endif | ||
87 | |||
88 | enum | ||
89 | { | ||
90 | /* The desired alignment of memory allocations is the maximum alignment | ||
91 | among all elementary types. */ | ||
92 | sa_alignment_long = sa_alignof (long), | ||
93 | sa_alignment_double = sa_alignof (double), | ||
94 | #ifdef HAVE_LONG_LONG | ||
95 | sa_alignment_longlong = sa_alignof (long long), | ||
96 | #endif | ||
97 | #ifdef HAVE_LONG_DOUBLE | ||
98 | sa_alignment_longdouble = sa_alignof (long double), | ||
99 | #endif | ||
100 | sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) | ||
101 | #ifdef HAVE_LONG_LONG | ||
102 | | (sa_alignment_longlong - 1) | ||
103 | #endif | ||
104 | #ifdef HAVE_LONG_DOUBLE | ||
105 | | (sa_alignment_longdouble - 1) | ||
106 | #endif | ||
107 | ) + 1, | ||
108 | /* The increment that guarantees room for a magic word must be >= sizeof (int) | ||
109 | and a multiple of sa_alignment_max. */ | ||
110 | sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max | ||
111 | }; | ||
112 | |||
113 | #endif /* _ALLOCSA_H */ |
lib/allocsa.valgrind
0 → 100644
lib/error.c
0 → 100644
1 | /* Error handler for noninteractive utilities | ||
2 | Copyright (C) 1990-1998, 2000-2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
18 | |||
19 | /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | ||
20 | |||
21 | #ifdef HAVE_CONFIG_H | ||
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 <wchar.h> | ||
38 | # define mbsrtowcs __mbsrtowcs | ||
39 | #endif | ||
40 | |||
41 | #if USE_UNLOCKED_IO | ||
42 | # include "unlocked-io.h" | ||
43 | #endif | ||
44 | |||
45 | #ifndef _ | ||
46 | # define _(String) String | ||
47 | #endif | ||
48 | |||
49 | /* If NULL, error will flush stdout, then print on stderr the program | ||
50 | name, a colon and a space. Otherwise, error will call this | ||
51 | function without parameters instead. */ | ||
52 | void (*error_print_progname) (void); | ||
53 | |||
54 | /* This variable is incremented each time `error' is called. */ | ||
55 | unsigned int error_message_count; | ||
56 | |||
57 | #ifdef _LIBC | ||
58 | /* In the GNU C library, there is a predefined variable for this. */ | ||
59 | |||
60 | # define program_name program_invocation_name | ||
61 | # include <errno.h> | ||
62 | # include <libio/libioP.h> | ||
63 | |||
64 | /* In GNU libc we want do not want to use the common name `error' directly. | ||
65 | Instead make it a weak alias. */ | ||
66 | extern void __error (int status, int errnum, const char *message, ...) | ||
67 | __attribute__ ((__format__ (__printf__, 3, 4))); | ||
68 | extern void __error_at_line (int status, int errnum, const char *file_name, | ||
69 | unsigned int line_number, const char *message, | ||
70 | ...) | ||
71 | __attribute__ ((__format__ (__printf__, 5, 6)));; | ||
72 | # define error __error | ||
73 | # define error_at_line __error_at_line | ||
74 | |||
75 | # include <libio/iolibio.h> | ||
76 | # define fflush(s) INTUSE(_IO_fflush) (s) | ||
77 | # undef putc | ||
78 | # define putc(c, fp) INTUSE(_IO_putc) (c, fp) | ||
79 | |||
80 | # include <bits/libc-lock.h> | ||
81 | |||
82 | #else /* not _LIBC */ | ||
83 | |||
84 | # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P | ||
85 | # ifndef HAVE_DECL_STRERROR_R | ||
86 | "this configure-time declaration test was not run" | ||
87 | # endif | ||
88 | char *strerror_r (); | ||
89 | # endif | ||
90 | |||
91 | # ifndef SIZE_MAX | ||
92 | # define SIZE_MAX ((size_t) -1) | ||
93 | # endif | ||
94 | |||
95 | /* The calling program should define program_name and set it to the | ||
96 | name of the executing program. */ | ||
97 | extern char *program_name; | ||
98 | |||
99 | # if HAVE_STRERROR_R || defined strerror_r | ||
100 | # define __strerror_r strerror_r | ||
101 | # endif | ||
102 | #endif /* not _LIBC */ | ||
103 | |||
104 | static void | ||
105 | print_errno_message (int errnum) | ||
106 | { | ||
107 | char const *s = NULL; | ||
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 | # endif | ||
117 | #endif | ||
118 | |||
119 | #if !_LIBC | ||
120 | if (! s && ! (s = strerror (errnum))) | ||
121 | s = _("Unknown system error"); | ||
122 | #endif | ||
123 | |||
124 | #if _LIBC | ||
125 | if (_IO_fwide (stderr, 0) > 0) | ||
126 | { | ||
127 | __fwprintf (stderr, L": %s", s); | ||
128 | return; | ||
129 | } | ||
130 | #endif | ||
131 | |||
132 | fprintf (stderr, ": %s", s); | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | error_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 | const wchar_t *wmessage = L"out of memory"; | ||
144 | wchar_t *wbuf = (len < ALLOCA_LIMIT | ||
145 | ? alloca (len * sizeof *wbuf) | ||
146 | : len <= SIZE_MAX / sizeof *wbuf | ||
147 | ? malloc (len * sizeof *wbuf) | ||
148 | : NULL); | ||
149 | |||
150 | if (wbuf) | ||
151 | { | ||
152 | size_t res; | ||
153 | mbstate_t st; | ||
154 | const char *tmp = message; | ||
155 | memset (&st, '\0', sizeof (st)); | ||
156 | res = mbsrtowcs (wbuf, &tmp, len, &st); | ||
157 | wmessage = res == (size_t) -1 ? L"???" : wbuf; | ||
158 | } | ||
159 | |||
160 | __vfwprintf (stderr, wmessage, args); | ||
161 | if (! (len < ALLOCA_LIMIT)) | ||
162 | free (wbuf); | ||
163 | } | ||
164 | else | ||
165 | #endif | ||
166 | vfprintf (stderr, message, args); | ||
167 | va_end (args); | ||
168 | |||
169 | ++error_message_count; | ||
170 | if (errnum) | ||
171 | print_errno_message (errnum); | ||
172 | #if _LIBC | ||
173 | if (_IO_fwide (stderr, 0) > 0) | ||
174 | putwc (L'\n', stderr); | ||
175 | else | ||
176 | #endif | ||
177 | putc ('\n', stderr); | ||
178 | fflush (stderr); | ||
179 | if (status) | ||
180 | exit (status); | ||
181 | } | ||
182 | |||
183 | |||
184 | /* Print the program name and error message MESSAGE, which is a printf-style | ||
185 | format string with optional args. | ||
186 | If ERRNUM is nonzero, print its corresponding system error message. | ||
187 | Exit with status STATUS if it is nonzero. */ | ||
188 | void | ||
189 | error (int status, int errnum, const char *message, ...) | ||
190 | { | ||
191 | va_list args; | ||
192 | |||
193 | #if defined _LIBC && defined __libc_ptf_call | ||
194 | /* We do not want this call to be cut short by a thread | ||
195 | cancellation. Therefore disable cancellation for now. */ | ||
196 | int state = PTHREAD_CANCEL_ENABLE; | ||
197 | __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), | ||
198 | 0); | ||
199 | #endif | ||
200 | |||
201 | fflush (stdout); | ||
202 | #ifdef _LIBC | ||
203 | _IO_flockfile (stderr); | ||
204 | #endif | ||
205 | if (error_print_progname) | ||
206 | (*error_print_progname) (); | ||
207 | else | ||
208 | { | ||
209 | #if _LIBC | ||
210 | if (_IO_fwide (stderr, 0) > 0) | ||
211 | __fwprintf (stderr, L"%s: ", program_name); | ||
212 | else | ||
213 | #endif | ||
214 | fprintf (stderr, "%s: ", program_name); | ||
215 | } | ||
216 | |||
217 | va_start (args, message); | ||
218 | error_tail (status, errnum, message, args); | ||
219 | |||
220 | #ifdef _LIBC | ||
221 | _IO_funlockfile (stderr); | ||
222 | # ifdef __libc_ptf_call | ||
223 | __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); | ||
224 | # endif | ||
225 | #endif | ||
226 | } | ||
227 | |||
228 | /* Sometimes we want to have at most one error per line. This | ||
229 | variable controls whether this mode is selected or not. */ | ||
230 | int error_one_per_line; | ||
231 | |||
232 | void | ||
233 | error_at_line (int status, int errnum, const char *file_name, | ||
234 | unsigned int line_number, const char *message, ...) | ||
235 | { | ||
236 | va_list args; | ||
237 | |||
238 | if (error_one_per_line) | ||
239 | { | ||
240 | static const char *old_file_name; | ||
241 | static unsigned int old_line_number; | ||
242 | |||
243 | if (old_line_number == line_number | ||
244 | && (file_name == old_file_name | ||
245 | || strcmp (old_file_name, file_name) == 0)) | ||
246 | /* Simply return and print nothing. */ | ||
247 | return; | ||
248 | |||
249 | old_file_name = file_name; | ||
250 | old_line_number = line_number; | ||
251 | } | ||
252 | |||
253 | #if defined _LIBC && defined __libc_ptf_call | ||
254 | /* We do not want this call to be cut short by a thread | ||
255 | cancellation. Therefore disable cancellation for now. */ | ||
256 | int state = PTHREAD_CANCEL_ENABLE; | ||
257 | __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), | ||
258 | 0); | ||
259 | #endif | ||
260 | |||
261 | fflush (stdout); | ||
262 | #ifdef _LIBC | ||
263 | _IO_flockfile (stderr); | ||
264 | #endif | ||
265 | if (error_print_progname) | ||
266 | (*error_print_progname) (); | ||
267 | else | ||
268 | { | ||
269 | #if _LIBC | ||
270 | if (_IO_fwide (stderr, 0) > 0) | ||
271 | __fwprintf (stderr, L"%s: ", program_name); | ||
272 | else | ||
273 | #endif | ||
274 | fprintf (stderr, "%s:", program_name); | ||
275 | } | ||
276 | |||
277 | if (file_name != NULL) | ||
278 | { | ||
279 | #if _LIBC | ||
280 | if (_IO_fwide (stderr, 0) > 0) | ||
281 | __fwprintf (stderr, L"%s:%d: ", file_name, line_number); | ||
282 | else | ||
283 | #endif | ||
284 | fprintf (stderr, "%s:%d: ", file_name, line_number); | ||
285 | } | ||
286 | |||
287 | va_start (args, message); | ||
288 | error_tail (status, errnum, message, args); | ||
289 | |||
290 | #ifdef _LIBC | ||
291 | _IO_funlockfile (stderr); | ||
292 | # ifdef __libc_ptf_call | ||
293 | __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); | ||
294 | # endif | ||
295 | #endif | ||
296 | } | ||
297 | |||
298 | #ifdef _LIBC | ||
299 | /* Make the weak alias. */ | ||
300 | # undef error | ||
301 | # undef error_at_line | ||
302 | weak_alias (__error, error) | ||
303 | weak_alias (__error_at_line, error_at_line) | ||
304 | #endif |
lib/exit.h
0 → 100644
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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_*, even with STDC_HEADERS. */ | ||
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 */ |
lib/exitfail.c
0 → 100644
1 | /* Failure exit status | ||
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; see the file COPYING. | ||
17 | If not, write to the Free Software Foundation, | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
19 | |||
20 | #if HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include "exitfail.h" | ||
25 | #include "exit.h" | ||
26 | |||
27 | int volatile exit_failure = EXIT_FAILURE; |
lib/exitfail.h
0 → 100644
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 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
19 | |||
20 | extern int volatile exit_failure; |
lib/fnmatch_.h
0 → 100644
1 | /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003 | ||
2 | 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 | #ifndef _FNMATCH_H | ||
19 | # define _FNMATCH_H 1 | ||
20 | |||
21 | # ifdef __cplusplus | ||
22 | extern "C" { | ||
23 | # endif | ||
24 | |||
25 | /* We #undef these before defining them because some losing systems | ||
26 | (HP-UX A.08.07 for example) define these in <unistd.h>. */ | ||
27 | # undef FNM_PATHNAME | ||
28 | # undef FNM_NOESCAPE | ||
29 | # undef FNM_PERIOD | ||
30 | |||
31 | /* Bits set in the FLAGS argument to `fnmatch'. */ | ||
32 | # define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ | ||
33 | # define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ | ||
34 | # define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ | ||
35 | |||
36 | # if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE | ||
37 | # define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ | ||
38 | # define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ | ||
39 | # define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ | ||
40 | # define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ | ||
41 | # endif | ||
42 | |||
43 | /* Value returned by `fnmatch' if STRING does not match PATTERN. */ | ||
44 | # define FNM_NOMATCH 1 | ||
45 | |||
46 | /* This value is returned if the implementation does not support | ||
47 | `fnmatch'. Since this is not the case here it will never be | ||
48 | returned but the conformance test suites still require the symbol | ||
49 | to be defined. */ | ||
50 | # ifdef _XOPEN_SOURCE | ||
51 | # define FNM_NOSYS (-1) | ||
52 | # endif | ||
53 | |||
54 | /* Match NAME against the filename pattern PATTERN, | ||
55 | returning zero if it matches, FNM_NOMATCH if not. */ | ||
56 | extern int fnmatch (const char *__pattern, const char *__name, | ||
57 | int __flags); | ||
58 | |||
59 | # ifdef __cplusplus | ||
60 | } | ||
61 | # endif | ||
62 | |||
63 | #endif /* fnmatch.h */ |
lib/fnmatch_loop.c
0 → 100644
1 | /* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004 | ||
2 | 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 | /* Match STRING against the filename pattern PATTERN, returning zero if | ||
19 | it matches, nonzero if not. */ | ||
20 | static int EXT (INT opt, const CHAR *pattern, const CHAR *string, | ||
21 | const CHAR *string_end, bool no_leading_period, int flags) | ||
22 | internal_function; | ||
23 | static const CHAR *END (const CHAR *patternp) internal_function; | ||
24 | |||
25 | static int | ||
26 | internal_function | ||
27 | FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, | ||
28 | bool no_leading_period, int flags) | ||
29 | { | ||
30 | register const CHAR *p = pattern, *n = string; | ||
31 | register UCHAR c; | ||
32 | #ifdef _LIBC | ||
33 | # if WIDE_CHAR_VERSION | ||
34 | const char *collseq = (const char *) | ||
35 | _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); | ||
36 | # else | ||
37 | const UCHAR *collseq = (const UCHAR *) | ||
38 | _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); | ||
39 | # endif | ||
40 | #endif | ||
41 | |||
42 | while ((c = *p++) != L('\0')) | ||
43 | { | ||
44 | bool new_no_leading_period = false; | ||
45 | c = FOLD (c); | ||
46 | |||
47 | switch (c) | ||
48 | { | ||
49 | case L('?'): | ||
50 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | ||
51 | { | ||
52 | int res; | ||
53 | |||
54 | res = EXT (c, p, n, string_end, no_leading_period, | ||
55 | flags); | ||
56 | if (res != -1) | ||
57 | return res; | ||
58 | } | ||
59 | |||
60 | if (n == string_end) | ||
61 | return FNM_NOMATCH; | ||
62 | else if (*n == L('/') && (flags & FNM_FILE_NAME)) | ||
63 | return FNM_NOMATCH; | ||
64 | else if (*n == L('.') && no_leading_period) | ||
65 | return FNM_NOMATCH; | ||
66 | break; | ||
67 | |||
68 | case L('\\'): | ||
69 | if (!(flags & FNM_NOESCAPE)) | ||
70 | { | ||
71 | c = *p++; | ||
72 | if (c == L('\0')) | ||
73 | /* Trailing \ loses. */ | ||
74 | return FNM_NOMATCH; | ||
75 | c = FOLD (c); | ||
76 | } | ||
77 | if (n == string_end || FOLD ((UCHAR) *n) != c) | ||
78 | return FNM_NOMATCH; | ||
79 | break; | ||
80 | |||
81 | case L('*'): | ||
82 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | ||
83 | { | ||
84 | int res; | ||
85 | |||
86 | res = EXT (c, p, n, string_end, no_leading_period, | ||
87 | flags); | ||
88 | if (res != -1) | ||
89 | return res; | ||
90 | } | ||
91 | |||
92 | if (n != string_end && *n == L('.') && no_leading_period) | ||
93 | return FNM_NOMATCH; | ||
94 | |||
95 | for (c = *p++; c == L('?') || c == L('*'); c = *p++) | ||
96 | { | ||
97 | if (*p == L('(') && (flags & FNM_EXTMATCH) != 0) | ||
98 | { | ||
99 | const CHAR *endp = END (p); | ||
100 | if (endp != p) | ||
101 | { | ||
102 | /* This is a pattern. Skip over it. */ | ||
103 | p = endp; | ||
104 | continue; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | if (c == L('?')) | ||
109 | { | ||
110 | /* A ? needs to match one character. */ | ||
111 | if (n == string_end) | ||
112 | /* There isn't another character; no match. */ | ||
113 | return FNM_NOMATCH; | ||
114 | else if (*n == L('/') | ||
115 | && __builtin_expect (flags & FNM_FILE_NAME, 0)) | ||
116 | /* A slash does not match a wildcard under | ||
117 | FNM_FILE_NAME. */ | ||
118 | return FNM_NOMATCH; | ||
119 | else | ||
120 | /* One character of the string is consumed in matching | ||
121 | this ? wildcard, so *??? won't match if there are | ||
122 | less than three characters. */ | ||
123 | ++n; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (c == L('\0')) | ||
128 | /* The wildcard(s) is/are the last element of the pattern. | ||
129 | If the name is a file name and contains another slash | ||
130 | this means it cannot match, unless the FNM_LEADING_DIR | ||
131 | flag is set. */ | ||
132 | { | ||
133 | int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; | ||
134 | |||
135 | if (flags & FNM_FILE_NAME) | ||
136 | { | ||
137 | if (flags & FNM_LEADING_DIR) | ||
138 | result = 0; | ||
139 | else | ||
140 | { | ||
141 | if (MEMCHR (n, L('/'), string_end - n) == NULL) | ||
142 | result = 0; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | return result; | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | const CHAR *endp; | ||
151 | |||
152 | endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'), | ||
153 | string_end - n); | ||
154 | if (endp == NULL) | ||
155 | endp = string_end; | ||
156 | |||
157 | if (c == L('[') | ||
158 | || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 | ||
159 | && (c == L('@') || c == L('+') || c == L('!')) | ||
160 | && *p == L('('))) | ||
161 | { | ||
162 | int flags2 = ((flags & FNM_FILE_NAME) | ||
163 | ? flags : (flags & ~FNM_PERIOD)); | ||
164 | bool no_leading_period2 = no_leading_period; | ||
165 | |||
166 | for (--p; n < endp; ++n, no_leading_period2 = false) | ||
167 | if (FCT (p, n, string_end, no_leading_period2, flags2) | ||
168 | == 0) | ||
169 | return 0; | ||
170 | } | ||
171 | else if (c == L('/') && (flags & FNM_FILE_NAME)) | ||
172 | { | ||
173 | while (n < string_end && *n != L('/')) | ||
174 | ++n; | ||
175 | if (n < string_end && *n == L('/') | ||
176 | && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) | ||
177 | == 0)) | ||
178 | return 0; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | int flags2 = ((flags & FNM_FILE_NAME) | ||
183 | ? flags : (flags & ~FNM_PERIOD)); | ||
184 | int no_leading_period2 = no_leading_period; | ||
185 | |||
186 | if (c == L('\\') && !(flags & FNM_NOESCAPE)) | ||
187 | c = *p; | ||
188 | c = FOLD (c); | ||
189 | for (--p; n < endp; ++n, no_leading_period2 = false) | ||
190 | if (FOLD ((UCHAR) *n) == c | ||
191 | && (FCT (p, n, string_end, no_leading_period2, flags2) | ||
192 | == 0)) | ||
193 | return 0; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* If we come here no match is possible with the wildcard. */ | ||
198 | return FNM_NOMATCH; | ||
199 | |||
200 | case L('['): | ||
201 | { | ||
202 | /* Nonzero if the sense of the character class is inverted. */ | ||
203 | register bool not; | ||
204 | CHAR cold; | ||
205 | UCHAR fn; | ||
206 | |||
207 | if (posixly_correct == 0) | ||
208 | posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; | ||
209 | |||
210 | if (n == string_end) | ||
211 | return FNM_NOMATCH; | ||
212 | |||
213 | if (*n == L('.') && no_leading_period) | ||
214 | return FNM_NOMATCH; | ||
215 | |||
216 | if (*n == L('/') && (flags & FNM_FILE_NAME)) | ||
217 | /* `/' cannot be matched. */ | ||
218 | return FNM_NOMATCH; | ||
219 | |||
220 | not = (*p == L('!') || (posixly_correct < 0 && *p == L('^'))); | ||
221 | if (not) | ||
222 | ++p; | ||
223 | |||
224 | fn = FOLD ((UCHAR) *n); | ||
225 | |||
226 | c = *p++; | ||
227 | for (;;) | ||
228 | { | ||
229 | if (!(flags & FNM_NOESCAPE) && c == L('\\')) | ||
230 | { | ||
231 | if (*p == L('\0')) | ||
232 | return FNM_NOMATCH; | ||
233 | c = FOLD ((UCHAR) *p); | ||
234 | ++p; | ||
235 | |||
236 | if (c == fn) | ||
237 | goto matched; | ||
238 | } | ||
239 | else if (c == L('[') && *p == L(':')) | ||
240 | { | ||
241 | /* Leave room for the null. */ | ||
242 | CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; | ||
243 | size_t c1 = 0; | ||
244 | #if defined _LIBC || WIDE_CHAR_SUPPORT | ||
245 | wctype_t wt; | ||
246 | #endif | ||
247 | const CHAR *startp = p; | ||
248 | |||
249 | for (;;) | ||
250 | { | ||
251 | if (c1 == CHAR_CLASS_MAX_LENGTH) | ||
252 | /* The name is too long and therefore the pattern | ||
253 | is ill-formed. */ | ||
254 | return FNM_NOMATCH; | ||
255 | |||
256 | c = *++p; | ||
257 | if (c == L(':') && p[1] == L(']')) | ||
258 | { | ||
259 | p += 2; | ||
260 | break; | ||
261 | } | ||
262 | if (c < L('a') || c >= L('z')) | ||
263 | { | ||
264 | /* This cannot possibly be a character class name. | ||
265 | Match it as a normal range. */ | ||
266 | p = startp; | ||
267 | c = L('['); | ||
268 | goto normal_bracket; | ||
269 | } | ||
270 | str[c1++] = c; | ||
271 | } | ||
272 | str[c1] = L('\0'); | ||
273 | |||
274 | #if defined _LIBC || WIDE_CHAR_SUPPORT | ||
275 | wt = IS_CHAR_CLASS (str); | ||
276 | if (wt == 0) | ||
277 | /* Invalid character class name. */ | ||
278 | return FNM_NOMATCH; | ||
279 | |||
280 | # if defined _LIBC && ! WIDE_CHAR_VERSION | ||
281 | /* The following code is glibc specific but does | ||
282 | there a good job in speeding up the code since | ||
283 | we can avoid the btowc() call. */ | ||
284 | if (_ISCTYPE ((UCHAR) *n, wt)) | ||
285 | goto matched; | ||
286 | # else | ||
287 | if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) | ||
288 | goto matched; | ||
289 | # endif | ||
290 | #else | ||
291 | if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n)) | ||
292 | || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n)) | ||
293 | || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n)) | ||
294 | || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n)) | ||
295 | || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n)) | ||
296 | || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n)) | ||
297 | || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n)) | ||
298 | || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n)) | ||
299 | || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n)) | ||
300 | || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n)) | ||
301 | || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n)) | ||
302 | || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n))) | ||
303 | goto matched; | ||
304 | #endif | ||
305 | c = *p++; | ||
306 | } | ||
307 | #ifdef _LIBC | ||
308 | else if (c == L('[') && *p == L('=')) | ||
309 | { | ||
310 | UCHAR str[1]; | ||
311 | uint32_t nrules = | ||
312 | _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); | ||
313 | const CHAR *startp = p; | ||
314 | |||
315 | c = *++p; | ||
316 | if (c == L('\0')) | ||
317 | { | ||
318 | p = startp; | ||
319 | c = L('['); | ||
320 | goto normal_bracket; | ||
321 | } | ||
322 | str[0] = c; | ||
323 | |||
324 | c = *++p; | ||
325 | if (c != L('=') || p[1] != L(']')) | ||
326 | { | ||
327 | p = startp; | ||
328 | c = L('['); | ||
329 | goto normal_bracket; | ||
330 | } | ||
331 | p += 2; | ||
332 | |||
333 | if (nrules == 0) | ||
334 | { | ||
335 | if ((UCHAR) *n == str[0]) | ||
336 | goto matched; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | const int32_t *table; | ||
341 | # if WIDE_CHAR_VERSION | ||
342 | const int32_t *weights; | ||
343 | const int32_t *extra; | ||
344 | # else | ||
345 | const unsigned char *weights; | ||
346 | const unsigned char *extra; | ||
347 | # endif | ||
348 | const int32_t *indirect; | ||
349 | int32_t idx; | ||
350 | const UCHAR *cp = (const UCHAR *) str; | ||
351 | |||
352 | /* This #include defines a local function! */ | ||
353 | # if WIDE_CHAR_VERSION | ||
354 | # include <locale/weightwc.h> | ||
355 | # else | ||
356 | # include <locale/weight.h> | ||
357 | # endif | ||
358 | |||
359 | # if WIDE_CHAR_VERSION | ||
360 | table = (const int32_t *) | ||
361 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); | ||
362 | weights = (const int32_t *) | ||
363 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); | ||
364 | extra = (const int32_t *) | ||
365 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); | ||
366 | indirect = (const int32_t *) | ||
367 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); | ||
368 | # else | ||
369 | table = (const int32_t *) | ||
370 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); | ||
371 | weights = (const unsigned char *) | ||
372 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); | ||
373 | extra = (const unsigned char *) | ||
374 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); | ||
375 | indirect = (const int32_t *) | ||
376 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); | ||
377 | # endif | ||
378 | |||
379 | idx = findidx (&cp); | ||
380 | if (idx != 0) | ||
381 | { | ||
382 | /* We found a table entry. Now see whether the | ||
383 | character we are currently at has the same | ||
384 | equivalance class value. */ | ||
385 | int len = weights[idx]; | ||
386 | int32_t idx2; | ||
387 | const UCHAR *np = (const UCHAR *) n; | ||
388 | |||
389 | idx2 = findidx (&np); | ||
390 | if (idx2 != 0 && len == weights[idx2]) | ||
391 | { | ||
392 | int cnt = 0; | ||
393 | |||
394 | while (cnt < len | ||
395 | && (weights[idx + 1 + cnt] | ||
396 | == weights[idx2 + 1 + cnt])) | ||
397 | ++cnt; | ||
398 | |||
399 | if (cnt == len) | ||
400 | goto matched; | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | |||
405 | c = *p++; | ||
406 | } | ||
407 | #endif | ||
408 | else if (c == L('\0')) | ||
409 | /* [ (unterminated) loses. */ | ||
410 | return FNM_NOMATCH; | ||
411 | else | ||
412 | { | ||
413 | bool is_range = false; | ||
414 | |||
415 | #ifdef _LIBC | ||
416 | bool is_seqval = false; | ||
417 | |||
418 | if (c == L('[') && *p == L('.')) | ||
419 | { | ||
420 | uint32_t nrules = | ||
421 | _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); | ||
422 | const CHAR *startp = p; | ||
423 | size_t c1 = 0; | ||
424 | |||
425 | while (1) | ||
426 | { | ||
427 | c = *++p; | ||
428 | if (c == L('.') && p[1] == L(']')) | ||
429 | { | ||
430 | p += 2; | ||
431 | break; | ||
432 | } | ||
433 | if (c == '\0') | ||
434 | return FNM_NOMATCH; | ||
435 | ++c1; | ||
436 | } | ||
437 | |||
438 | /* We have to handling the symbols differently in | ||
439 | ranges since then the collation sequence is | ||
440 | important. */ | ||
441 | is_range = *p == L('-') && p[1] != L('\0'); | ||
442 | |||
443 | if (nrules == 0) | ||
444 | { | ||
445 | /* There are no names defined in the collation | ||
446 | data. Therefore we only accept the trivial | ||
447 | names consisting of the character itself. */ | ||
448 | if (c1 != 1) | ||
449 | return FNM_NOMATCH; | ||
450 | |||
451 | if (!is_range && *n == startp[1]) | ||
452 | goto matched; | ||
453 | |||
454 | cold = startp[1]; | ||
455 | c = *p++; | ||
456 | } | ||
457 | else | ||
458 | { | ||
459 | int32_t table_size; | ||
460 | const int32_t *symb_table; | ||
461 | # ifdef WIDE_CHAR_VERSION | ||
462 | char str[c1]; | ||
463 | size_t strcnt; | ||
464 | # else | ||
465 | # define str (startp + 1) | ||
466 | # endif | ||
467 | const unsigned char *extra; | ||
468 | int32_t idx; | ||
469 | int32_t elem; | ||
470 | int32_t second; | ||
471 | int32_t hash; | ||
472 | |||
473 | # ifdef WIDE_CHAR_VERSION | ||
474 | /* We have to convert the name to a single-byte | ||
475 | string. This is possible since the names | ||
476 | consist of ASCII characters and the internal | ||
477 | representation is UCS4. */ | ||
478 | for (strcnt = 0; strcnt < c1; ++strcnt) | ||
479 | str[strcnt] = startp[1 + strcnt]; | ||
480 | # endif | ||
481 | |||
482 | table_size = | ||
483 | _NL_CURRENT_WORD (LC_COLLATE, | ||
484 | _NL_COLLATE_SYMB_HASH_SIZEMB); | ||
485 | symb_table = (const int32_t *) | ||
486 | _NL_CURRENT (LC_COLLATE, | ||
487 | _NL_COLLATE_SYMB_TABLEMB); | ||
488 | extra = (const unsigned char *) | ||
489 | _NL_CURRENT (LC_COLLATE, | ||
490 | _NL_COLLATE_SYMB_EXTRAMB); | ||
491 | |||
492 | /* Locate the character in the hashing table. */ | ||
493 | hash = elem_hash (str, c1); | ||
494 | |||
495 | idx = 0; | ||
496 | elem = hash % table_size; | ||
497 | second = hash % (table_size - 2); | ||
498 | while (symb_table[2 * elem] != 0) | ||
499 | { | ||
500 | /* First compare the hashing value. */ | ||
501 | if (symb_table[2 * elem] == hash | ||
502 | && c1 == extra[symb_table[2 * elem + 1]] | ||
503 | && memcmp (str, | ||
504 | &extra[symb_table[2 * elem + 1] | ||
505 | + 1], c1) == 0) | ||
506 | { | ||
507 | /* Yep, this is the entry. */ | ||
508 | idx = symb_table[2 * elem + 1]; | ||
509 | idx += 1 + extra[idx]; | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | /* Next entry. */ | ||
514 | elem += second; | ||
515 | } | ||
516 | |||
517 | if (symb_table[2 * elem] != 0) | ||
518 | { | ||
519 | /* Compare the byte sequence but only if | ||
520 | this is not part of a range. */ | ||
521 | # ifdef WIDE_CHAR_VERSION | ||
522 | int32_t *wextra; | ||
523 | |||
524 | idx += 1 + extra[idx]; | ||
525 | /* Adjust for the alignment. */ | ||
526 | idx = (idx + 3) & ~3; | ||
527 | |||
528 | wextra = (int32_t *) &extra[idx + 4]; | ||
529 | # endif | ||
530 | |||
531 | if (! is_range) | ||
532 | { | ||
533 | # ifdef WIDE_CHAR_VERSION | ||
534 | for (c1 = 0; | ||
535 | (int32_t) c1 < wextra[idx]; | ||
536 | ++c1) | ||
537 | if (n[c1] != wextra[1 + c1]) | ||
538 | break; | ||
539 | |||
540 | if ((int32_t) c1 == wextra[idx]) | ||
541 | goto matched; | ||
542 | # else | ||
543 | for (c1 = 0; c1 < extra[idx]; ++c1) | ||
544 | if (n[c1] != extra[1 + c1]) | ||
545 | break; | ||
546 | |||
547 | if (c1 == extra[idx]) | ||
548 | goto matched; | ||
549 | # endif | ||
550 | } | ||
551 | |||
552 | /* Get the collation sequence value. */ | ||
553 | is_seqval = true; | ||
554 | # ifdef WIDE_CHAR_VERSION | ||
555 | cold = wextra[1 + wextra[idx]]; | ||
556 | # else | ||
557 | /* Adjust for the alignment. */ | ||
558 | idx += 1 + extra[idx]; | ||
559 | idx = (idx + 3) & ~4; | ||
560 | cold = *((int32_t *) &extra[idx]); | ||
561 | # endif | ||
562 | |||
563 | c = *p++; | ||
564 | } | ||
565 | else if (c1 == 1) | ||
566 | { | ||
567 | /* No valid character. Match it as a | ||
568 | single byte. */ | ||
569 | if (!is_range && *n == str[0]) | ||
570 | goto matched; | ||
571 | |||
572 | cold = str[0]; | ||
573 | c = *p++; | ||
574 | } | ||
575 | else | ||
576 | return FNM_NOMATCH; | ||
577 | } | ||
578 | } | ||
579 | else | ||
580 | # undef str | ||
581 | #endif | ||
582 | { | ||
583 | c = FOLD (c); | ||
584 | normal_bracket: | ||
585 | |||
586 | /* We have to handling the symbols differently in | ||
587 | ranges since then the collation sequence is | ||
588 | important. */ | ||
589 | is_range = (*p == L('-') && p[1] != L('\0') | ||
590 | && p[1] != L(']')); | ||
591 | |||
592 | if (!is_range && c == fn) | ||
593 | goto matched; | ||
594 | |||
595 | cold = c; | ||
596 | c = *p++; | ||
597 | } | ||
598 | |||
599 | if (c == L('-') && *p != L(']')) | ||
600 | { | ||
601 | #if _LIBC | ||
602 | /* We have to find the collation sequence | ||
603 | value for C. Collation sequence is nothing | ||
604 | we can regularly access. The sequence | ||
605 | value is defined by the order in which the | ||
606 | definitions of the collation values for the | ||
607 | various characters appear in the source | ||
608 | file. A strange concept, nowhere | ||
609 | documented. */ | ||
610 | uint32_t fcollseq; | ||
611 | uint32_t lcollseq; | ||
612 | UCHAR cend = *p++; | ||
613 | |||
614 | # ifdef WIDE_CHAR_VERSION | ||
615 | /* Search in the `names' array for the characters. */ | ||
616 | fcollseq = __collseq_table_lookup (collseq, fn); | ||
617 | if (fcollseq == ~((uint32_t) 0)) | ||
618 | /* XXX We don't know anything about the character | ||
619 | we are supposed to match. This means we are | ||
620 | failing. */ | ||
621 | goto range_not_matched; | ||
622 | |||
623 | if (is_seqval) | ||
624 | lcollseq = cold; | ||
625 | else | ||
626 | lcollseq = __collseq_table_lookup (collseq, cold); | ||
627 | # else | ||
628 | fcollseq = collseq[fn]; | ||
629 | lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; | ||
630 | # endif | ||
631 | |||
632 | is_seqval = false; | ||
633 | if (cend == L('[') && *p == L('.')) | ||
634 | { | ||
635 | uint32_t nrules = | ||
636 | _NL_CURRENT_WORD (LC_COLLATE, | ||
637 | _NL_COLLATE_NRULES); | ||
638 | const CHAR *startp = p; | ||
639 | size_t c1 = 0; | ||
640 | |||
641 | while (1) | ||
642 | { | ||
643 | c = *++p; | ||
644 | if (c == L('.') && p[1] == L(']')) | ||
645 | { | ||
646 | p += 2; | ||
647 | break; | ||
648 | } | ||
649 | if (c == '\0') | ||
650 | return FNM_NOMATCH; | ||
651 | ++c1; | ||
652 | } | ||
653 | |||
654 | if (nrules == 0) | ||
655 | { | ||
656 | /* There are no names defined in the | ||
657 | collation data. Therefore we only | ||
658 | accept the trivial names consisting | ||
659 | of the character itself. */ | ||
660 | if (c1 != 1) | ||
661 | return FNM_NOMATCH; | ||
662 | |||
663 | cend = startp[1]; | ||
664 | } | ||
665 | else | ||
666 | { | ||
667 | int32_t table_size; | ||
668 | const int32_t *symb_table; | ||
669 | # ifdef WIDE_CHAR_VERSION | ||
670 | char str[c1]; | ||
671 | size_t strcnt; | ||
672 | # else | ||
673 | # define str (startp + 1) | ||
674 | # endif | ||
675 | const unsigned char *extra; | ||
676 | int32_t idx; | ||
677 | int32_t elem; | ||
678 | int32_t second; | ||
679 | int32_t hash; | ||
680 | |||
681 | # ifdef WIDE_CHAR_VERSION | ||
682 | /* We have to convert the name to a single-byte | ||
683 | string. This is possible since the names | ||
684 | consist of ASCII characters and the internal | ||
685 | representation is UCS4. */ | ||
686 | for (strcnt = 0; strcnt < c1; ++strcnt) | ||
687 | str[strcnt] = startp[1 + strcnt]; | ||
688 | # endif | ||
689 | |||
690 | table_size = | ||
691 | _NL_CURRENT_WORD (LC_COLLATE, | ||
692 | _NL_COLLATE_SYMB_HASH_SIZEMB); | ||
693 | symb_table = (const int32_t *) | ||
694 | _NL_CURRENT (LC_COLLATE, | ||
695 | _NL_COLLATE_SYMB_TABLEMB); | ||
696 | extra = (const unsigned char *) | ||
697 | _NL_CURRENT (LC_COLLATE, | ||
698 | _NL_COLLATE_SYMB_EXTRAMB); | ||
699 | |||
700 | /* Locate the character in the hashing | ||
701 | table. */ | ||
702 | hash = elem_hash (str, c1); | ||
703 | |||
704 | idx = 0; | ||
705 | elem = hash % table_size; | ||
706 | second = hash % (table_size - 2); | ||
707 | while (symb_table[2 * elem] != 0) | ||
708 | { | ||
709 | /* First compare the hashing value. */ | ||
710 | if (symb_table[2 * elem] == hash | ||
711 | && (c1 | ||
712 | == extra[symb_table[2 * elem + 1]]) | ||
713 | && memcmp (str, | ||
714 | &extra[symb_table[2 * elem + 1] | ||
715 | + 1], c1) == 0) | ||
716 | { | ||
717 | /* Yep, this is the entry. */ | ||
718 | idx = symb_table[2 * elem + 1]; | ||
719 | idx += 1 + extra[idx]; | ||
720 | break; | ||
721 | } | ||
722 | |||
723 | /* Next entry. */ | ||
724 | elem += second; | ||
725 | } | ||
726 | |||
727 | if (symb_table[2 * elem] != 0) | ||
728 | { | ||
729 | /* Compare the byte sequence but only if | ||
730 | this is not part of a range. */ | ||
731 | # ifdef WIDE_CHAR_VERSION | ||
732 | int32_t *wextra; | ||
733 | |||
734 | idx += 1 + extra[idx]; | ||
735 | /* Adjust for the alignment. */ | ||
736 | idx = (idx + 3) & ~4; | ||
737 | |||
738 | wextra = (int32_t *) &extra[idx + 4]; | ||
739 | # endif | ||
740 | /* Get the collation sequence value. */ | ||
741 | is_seqval = true; | ||
742 | # ifdef WIDE_CHAR_VERSION | ||
743 | cend = wextra[1 + wextra[idx]]; | ||
744 | # else | ||
745 | /* Adjust for the alignment. */ | ||
746 | idx += 1 + extra[idx]; | ||
747 | idx = (idx + 3) & ~4; | ||
748 | cend = *((int32_t *) &extra[idx]); | ||
749 | # endif | ||
750 | } | ||
751 | else if (symb_table[2 * elem] != 0 && c1 == 1) | ||
752 | { | ||
753 | cend = str[0]; | ||
754 | c = *p++; | ||
755 | } | ||
756 | else | ||
757 | return FNM_NOMATCH; | ||
758 | } | ||
759 | # undef str | ||
760 | } | ||
761 | else | ||
762 | { | ||
763 | if (!(flags & FNM_NOESCAPE) && cend == L('\\')) | ||
764 | cend = *p++; | ||
765 | if (cend == L('\0')) | ||
766 | return FNM_NOMATCH; | ||
767 | cend = FOLD (cend); | ||
768 | } | ||
769 | |||
770 | /* XXX It is not entirely clear to me how to handle | ||
771 | characters which are not mentioned in the | ||
772 | collation specification. */ | ||
773 | if ( | ||
774 | # ifdef WIDE_CHAR_VERSION | ||
775 | lcollseq == 0xffffffff || | ||
776 | # endif | ||
777 | lcollseq <= fcollseq) | ||
778 | { | ||
779 | /* We have to look at the upper bound. */ | ||
780 | uint32_t hcollseq; | ||
781 | |||
782 | if (is_seqval) | ||
783 | hcollseq = cend; | ||
784 | else | ||
785 | { | ||
786 | # ifdef WIDE_CHAR_VERSION | ||
787 | hcollseq = | ||
788 | __collseq_table_lookup (collseq, cend); | ||
789 | if (hcollseq == ~((uint32_t) 0)) | ||
790 | { | ||
791 | /* Hum, no information about the upper | ||
792 | bound. The matching succeeds if the | ||
793 | lower bound is matched exactly. */ | ||
794 | if (lcollseq != fcollseq) | ||
795 | goto range_not_matched; | ||
796 | |||
797 | goto matched; | ||
798 | } | ||
799 | # else | ||
800 | hcollseq = collseq[cend]; | ||
801 | # endif | ||
802 | } | ||
803 | |||
804 | if (lcollseq <= hcollseq && fcollseq <= hcollseq) | ||
805 | goto matched; | ||
806 | } | ||
807 | # ifdef WIDE_CHAR_VERSION | ||
808 | range_not_matched: | ||
809 | # endif | ||
810 | #else | ||
811 | /* We use a boring value comparison of the character | ||
812 | values. This is better than comparing using | ||
813 | `strcoll' since the latter would have surprising | ||
814 | and sometimes fatal consequences. */ | ||
815 | UCHAR cend = *p++; | ||
816 | |||
817 | if (!(flags & FNM_NOESCAPE) && cend == L('\\')) | ||
818 | cend = *p++; | ||
819 | if (cend == L('\0')) | ||
820 | return FNM_NOMATCH; | ||
821 | |||
822 | /* It is a range. */ | ||
823 | if (cold <= fn && fn <= cend) | ||
824 | goto matched; | ||
825 | #endif | ||
826 | |||
827 | c = *p++; | ||
828 | } | ||
829 | } | ||
830 | |||
831 | if (c == L(']')) | ||
832 | break; | ||
833 | } | ||
834 | |||
835 | if (!not) | ||
836 | return FNM_NOMATCH; | ||
837 | break; | ||
838 | |||
839 | matched: | ||
840 | /* Skip the rest of the [...] that already matched. */ | ||
841 | do | ||
842 | { | ||
843 | ignore_next: | ||
844 | c = *p++; | ||
845 | |||
846 | if (c == L('\0')) | ||
847 | /* [... (unterminated) loses. */ | ||
848 | return FNM_NOMATCH; | ||
849 | |||
850 | if (!(flags & FNM_NOESCAPE) && c == L('\\')) | ||
851 | { | ||
852 | if (*p == L('\0')) | ||
853 | return FNM_NOMATCH; | ||
854 | /* XXX 1003.2d11 is unclear if this is right. */ | ||
855 | ++p; | ||
856 | } | ||
857 | else if (c == L('[') && *p == L(':')) | ||
858 | { | ||
859 | int c1 = 0; | ||
860 | const CHAR *startp = p; | ||
861 | |||
862 | while (1) | ||
863 | { | ||
864 | c = *++p; | ||
865 | if (++c1 == CHAR_CLASS_MAX_LENGTH) | ||
866 | return FNM_NOMATCH; | ||
867 | |||
868 | if (*p == L(':') && p[1] == L(']')) | ||
869 | break; | ||
870 | |||
871 | if (c < L('a') || c >= L('z')) | ||
872 | { | ||
873 | p = startp; | ||
874 | goto ignore_next; | ||
875 | } | ||
876 | } | ||
877 | p += 2; | ||
878 | c = *p++; | ||
879 | } | ||
880 | else if (c == L('[') && *p == L('=')) | ||
881 | { | ||
882 | c = *++p; | ||
883 | if (c == L('\0')) | ||
884 | return FNM_NOMATCH; | ||
885 | c = *++p; | ||
886 | if (c != L('=') || p[1] != L(']')) | ||
887 | return FNM_NOMATCH; | ||
888 | p += 2; | ||
889 | c = *p++; | ||
890 | } | ||
891 | else if (c == L('[') && *p == L('.')) | ||
892 | { | ||
893 | ++p; | ||
894 | while (1) | ||
895 | { | ||
896 | c = *++p; | ||
897 | if (c == '\0') | ||
898 | return FNM_NOMATCH; | ||
899 | |||
900 | if (*p == L('.') && p[1] == L(']')) | ||
901 | break; | ||
902 | } | ||
903 | p += 2; | ||
904 | c = *p++; | ||
905 | } | ||
906 | } | ||
907 | while (c != L(']')); | ||
908 | if (not) | ||
909 | return FNM_NOMATCH; | ||
910 | } | ||
911 | break; | ||
912 | |||
913 | case L('+'): | ||
914 | case L('@'): | ||
915 | case L('!'): | ||
916 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | ||
917 | { | ||
918 | int res; | ||
919 | |||
920 | res = EXT (c, p, n, string_end, no_leading_period, flags); | ||
921 | if (res != -1) | ||
922 | return res; | ||
923 | } | ||
924 | goto normal_match; | ||
925 | |||
926 | case L('/'): | ||
927 | if (NO_LEADING_PERIOD (flags)) | ||
928 | { | ||
929 | if (n == string_end || c != (UCHAR) *n) | ||
930 | return FNM_NOMATCH; | ||
931 | |||
932 | new_no_leading_period = true; | ||
933 | break; | ||
934 | } | ||
935 | /* FALLTHROUGH */ | ||
936 | default: | ||
937 | normal_match: | ||
938 | if (n == string_end || c != FOLD ((UCHAR) *n)) | ||
939 | return FNM_NOMATCH; | ||
940 | } | ||
941 | |||
942 | no_leading_period = new_no_leading_period; | ||
943 | ++n; | ||
944 | } | ||
945 | |||
946 | if (n == string_end) | ||
947 | return 0; | ||
948 | |||
949 | if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/')) | ||
950 | /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ | ||
951 | return 0; | ||
952 | |||
953 | return FNM_NOMATCH; | ||
954 | } | ||
955 | |||
956 | |||
957 | static const CHAR * | ||
958 | internal_function | ||
959 | END (const CHAR *pattern) | ||
960 | { | ||
961 | const CHAR *p = pattern; | ||
962 | |||
963 | while (1) | ||
964 | if (*++p == L('\0')) | ||
965 | /* This is an invalid pattern. */ | ||
966 | return pattern; | ||
967 | else if (*p == L('[')) | ||
968 | { | ||
969 | /* Handle brackets special. */ | ||
970 | if (posixly_correct == 0) | ||
971 | posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; | ||
972 | |||
973 | /* Skip the not sign. We have to recognize it because of a possibly | ||
974 | following ']'. */ | ||
975 | if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) | ||
976 | ++p; | ||
977 | /* A leading ']' is recognized as such. */ | ||
978 | if (*p == L(']')) | ||
979 | ++p; | ||
980 | /* Skip over all characters of the list. */ | ||
981 | while (*p != L(']')) | ||
982 | if (*p++ == L('\0')) | ||
983 | /* This is no valid pattern. */ | ||
984 | return pattern; | ||
985 | } | ||
986 | else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') | ||
987 | || *p == L('!')) && p[1] == L('(')) | ||
988 | p = END (p + 1); | ||
989 | else if (*p == L(')')) | ||
990 | break; | ||
991 | |||
992 | return p + 1; | ||
993 | } | ||
994 | |||
995 | |||
996 | static int | ||
997 | internal_function | ||
998 | EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, | ||
999 | bool no_leading_period, int flags) | ||
1000 | { | ||
1001 | const CHAR *startp; | ||
1002 | size_t level; | ||
1003 | struct patternlist | ||
1004 | { | ||
1005 | struct patternlist *next; | ||
1006 | CHAR str[1]; | ||
1007 | } *list = NULL; | ||
1008 | struct patternlist **lastp = &list; | ||
1009 | size_t pattern_len = STRLEN (pattern); | ||
1010 | const CHAR *p; | ||
1011 | const CHAR *rs; | ||
1012 | enum { ALLOCA_LIMIT = 8000 }; | ||
1013 | |||
1014 | /* Parse the pattern. Store the individual parts in the list. */ | ||
1015 | level = 0; | ||
1016 | for (startp = p = pattern + 1; ; ++p) | ||
1017 | if (*p == L('\0')) | ||
1018 | /* This is an invalid pattern. */ | ||
1019 | return -1; | ||
1020 | else if (*p == L('[')) | ||
1021 | { | ||
1022 | /* Handle brackets special. */ | ||
1023 | if (posixly_correct == 0) | ||
1024 | posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; | ||
1025 | |||
1026 | /* Skip the not sign. We have to recognize it because of a possibly | ||
1027 | following ']'. */ | ||
1028 | if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) | ||
1029 | ++p; | ||
1030 | /* A leading ']' is recognized as such. */ | ||
1031 | if (*p == L(']')) | ||
1032 | ++p; | ||
1033 | /* Skip over all characters of the list. */ | ||
1034 | while (*p != L(']')) | ||
1035 | if (*p++ == L('\0')) | ||
1036 | /* This is no valid pattern. */ | ||
1037 | return -1; | ||
1038 | } | ||
1039 | else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') | ||
1040 | || *p == L('!')) && p[1] == L('(')) | ||
1041 | /* Remember the nesting level. */ | ||
1042 | ++level; | ||
1043 | else if (*p == L(')')) | ||
1044 | { | ||
1045 | if (level-- == 0) | ||
1046 | { | ||
1047 | /* This means we found the end of the pattern. */ | ||
1048 | #define NEW_PATTERN \ | ||
1049 | struct patternlist *newp; \ | ||
1050 | size_t plen; \ | ||
1051 | size_t plensize; \ | ||
1052 | size_t newpsize; \ | ||
1053 | \ | ||
1054 | plen = (opt == L('?') || opt == L('@') \ | ||
1055 | ? pattern_len \ | ||
1056 | : p - startp + 1); \ | ||
1057 | plensize = plen * sizeof (CHAR); \ | ||
1058 | newpsize = offsetof (struct patternlist, str) + plensize; \ | ||
1059 | if ((size_t) -1 / sizeof (CHAR) < plen \ | ||
1060 | || newpsize < offsetof (struct patternlist, str) \ | ||
1061 | || ALLOCA_LIMIT <= newpsize) \ | ||
1062 | return -1; \ | ||
1063 | newp = (struct patternlist *) alloca (newpsize); \ | ||
1064 | *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ | ||
1065 | newp->next = NULL; \ | ||
1066 | *lastp = newp; \ | ||
1067 | lastp = &newp->next | ||
1068 | NEW_PATTERN; | ||
1069 | break; | ||
1070 | } | ||
1071 | } | ||
1072 | else if (*p == L('|')) | ||
1073 | { | ||
1074 | if (level == 0) | ||
1075 | { | ||
1076 | NEW_PATTERN; | ||
1077 | startp = p + 1; | ||
1078 | } | ||
1079 | } | ||
1080 | assert (list != NULL); | ||
1081 | assert (p[-1] == L(')')); | ||
1082 | #undef NEW_PATTERN | ||
1083 | |||
1084 | switch (opt) | ||
1085 | { | ||
1086 | case L('*'): | ||
1087 | if (FCT (p, string, string_end, no_leading_period, flags) == 0) | ||
1088 | return 0; | ||
1089 | /* FALLTHROUGH */ | ||
1090 | |||
1091 | case L('+'): | ||
1092 | do | ||
1093 | { | ||
1094 | for (rs = string; rs <= string_end; ++rs) | ||
1095 | /* First match the prefix with the current pattern with the | ||
1096 | current pattern. */ | ||
1097 | if (FCT (list->str, string, rs, no_leading_period, | ||
1098 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 | ||
1099 | /* This was successful. Now match the rest with the rest | ||
1100 | of the pattern. */ | ||
1101 | && (FCT (p, rs, string_end, | ||
1102 | rs == string | ||
1103 | ? no_leading_period | ||
1104 | : rs[-1] == '/' && NO_LEADING_PERIOD (flags), | ||
1105 | flags & FNM_FILE_NAME | ||
1106 | ? flags : flags & ~FNM_PERIOD) == 0 | ||
1107 | /* This didn't work. Try the whole pattern. */ | ||
1108 | || (rs != string | ||
1109 | && FCT (pattern - 1, rs, string_end, | ||
1110 | rs == string | ||
1111 | ? no_leading_period | ||
1112 | : rs[-1] == '/' && NO_LEADING_PERIOD (flags), | ||
1113 | flags & FNM_FILE_NAME | ||
1114 | ? flags : flags & ~FNM_PERIOD) == 0))) | ||
1115 | /* It worked. Signal success. */ | ||
1116 | return 0; | ||
1117 | } | ||
1118 | while ((list = list->next) != NULL); | ||
1119 | |||
1120 | /* None of the patterns lead to a match. */ | ||
1121 | return FNM_NOMATCH; | ||
1122 | |||
1123 | case L('?'): | ||
1124 | if (FCT (p, string, string_end, no_leading_period, flags) == 0) | ||
1125 | return 0; | ||
1126 | /* FALLTHROUGH */ | ||
1127 | |||
1128 | case L('@'): | ||
1129 | do | ||
1130 | /* I cannot believe it but `strcat' is actually acceptable | ||
1131 | here. Match the entire string with the prefix from the | ||
1132 | pattern list and the rest of the pattern following the | ||
1133 | pattern list. */ | ||
1134 | if (FCT (STRCAT (list->str, p), string, string_end, | ||
1135 | no_leading_period, | ||
1136 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) | ||
1137 | /* It worked. Signal success. */ | ||
1138 | return 0; | ||
1139 | while ((list = list->next) != NULL); | ||
1140 | |||
1141 | /* None of the patterns lead to a match. */ | ||
1142 | return FNM_NOMATCH; | ||
1143 | |||
1144 | case L('!'): | ||
1145 | for (rs = string; rs <= string_end; ++rs) | ||
1146 | { | ||
1147 | struct patternlist *runp; | ||
1148 | |||
1149 | for (runp = list; runp != NULL; runp = runp->next) | ||
1150 | if (FCT (runp->str, string, rs, no_leading_period, | ||
1151 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) | ||
1152 | break; | ||
1153 | |||
1154 | /* If none of the patterns matched see whether the rest does. */ | ||
1155 | if (runp == NULL | ||
1156 | && (FCT (p, rs, string_end, | ||
1157 | rs == string | ||
1158 | ? no_leading_period | ||
1159 | : rs[-1] == '/' && NO_LEADING_PERIOD (flags), | ||
1160 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) | ||
1161 | == 0)) | ||
1162 | /* This is successful. */ | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | /* None of the patterns together with the rest of the pattern | ||
1167 | lead to a match. */ | ||
1168 | return FNM_NOMATCH; | ||
1169 | |||
1170 | default: | ||
1171 | assert (! "Invalid extended matching operator"); | ||
1172 | break; | ||
1173 | } | ||
1174 | |||
1175 | return -1; | ||
1176 | } | ||
1177 | |||
1178 | |||
1179 | #undef FOLD | ||
1180 | #undef CHAR | ||
1181 | #undef UCHAR | ||
1182 | #undef INT | ||
1183 | #undef FCT | ||
1184 | #undef EXT | ||
1185 | #undef END | ||
1186 | #undef MEMPCPY | ||
1187 | #undef MEMCHR | ||
1188 | #undef STRCOLL | ||
1189 | #undef STRLEN | ||
1190 | #undef STRCAT | ||
1191 | #undef L | ||
1192 | #undef BTOWC |
lib/getpass.h
0 → 100644
1 | /* getpass.h -- Read a password of arbitrary length from /dev/tty or stdin. | ||
2 | Copyright (C) 2004 Free Software Foundation, Inc. | ||
3 | Contributed by Simon Josefsson <jas@extundo.com>, 2004. | ||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
18 | |||
19 | #ifndef GETPASS_H | ||
20 | #define GETPASS_H | ||
21 | |||
22 | /* Get getpass declaration, if available. */ | ||
23 | #include <unistd.h> | ||
24 | |||
25 | #if defined HAVE_DECL_GETPASS && !HAVE_DECL_GETPASS | ||
26 | /* Read a password of arbitrary length from /dev/tty or stdin. */ | ||
27 | char *getpass (const char *prompt); | ||
28 | |||
29 | #endif | ||
30 | |||
31 | #endif /* GETPASS_H */ |
lib/setenv.h
0 → 100644
1 | /* Setting environment variables. | ||
2 | Copyright (C) 2001-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 | ||
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 | #if HAVE_SETENV || HAVE_UNSETENV | ||
19 | |||
20 | /* Get setenv(), unsetenv() declarations. */ | ||
21 | # include <stdlib.h> | ||
22 | |||
23 | #endif | ||
24 | |||
25 | #ifdef __cplusplus | ||
26 | extern "C" { | ||
27 | #endif | ||
28 | |||
29 | #if !HAVE_SETENV | ||
30 | |||
31 | /* Set NAME to VALUE in the environment. | ||
32 | If REPLACE is nonzero, overwrite an existing value. */ | ||
33 | extern int setenv (const char *name, const char *value, int replace); | ||
34 | |||
35 | #endif | ||
36 | |||
37 | #if HAVE_UNSETENV | ||
38 | |||
39 | # if VOID_UNSETENV | ||
40 | /* On some systems, unsetenv() returns void. | ||
41 | This is the case for FreeBSD 4.8, NetBSD 1.6, OpenBSD 3.4. */ | ||
42 | # define unsetenv(name) ((unsetenv)(name), 0) | ||
43 | # endif | ||
44 | |||
45 | #else | ||
46 | |||
47 | /* Remove the variable NAME from the environment. */ | ||
48 | extern int unsetenv (const char *name); | ||
49 | |||
50 | #endif | ||
51 | |||
52 | #ifdef __cplusplus | ||
53 | } | ||
54 | #endif |
lib/stdbool_.h
0 → 100644
1 | /* Copyright (C) 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 | # if !@HAVE__BOOL@ | ||
75 | # if defined __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1) | ||
76 | /* Avoid stupid "warning: _Bool is a keyword in ISO C99". */ | ||
77 | # define _Bool signed char | ||
78 | enum { false = 0, true = 1 }; | ||
79 | # else | ||
80 | typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; | ||
81 | # endif | ||
82 | # endif | ||
83 | #else | ||
84 | typedef bool _Bool; | ||
85 | #endif | ||
86 | #define bool _Bool | ||
87 | |||
88 | /* The other macros must be usable in preprocessor directives. */ | ||
89 | #define false 0 | ||
90 | #define true 1 | ||
91 | #define __bool_true_false_are_defined 1 | ||
92 | |||
93 | #endif /* _STDBOOL_H */ |
lib/unsetenv.c
0 → 100644
1 | /* Copyright (C) 1992,1995-1999,2000-2002 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
17 | |||
18 | #if HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <errno.h> | ||
23 | #if !_LIBC | ||
24 | # if !defined errno && !defined HAVE_ERRNO_DECL | ||
25 | extern int errno; | ||
26 | # endif | ||
27 | # define __set_errno(ev) ((errno) = (ev)) | ||
28 | #endif | ||
29 | |||
30 | #include <stdlib.h> | ||
31 | #include <string.h> | ||
32 | #if _LIBC || HAVE_UNISTD_H | ||
33 | # include <unistd.h> | ||
34 | #endif | ||
35 | |||
36 | #if !_LIBC | ||
37 | # define __environ environ | ||
38 | # ifndef HAVE_ENVIRON_DECL | ||
39 | extern char **environ; | ||
40 | # endif | ||
41 | #endif | ||
42 | |||
43 | #if _LIBC | ||
44 | /* This lock protects against simultaneous modifications of `environ'. */ | ||
45 | # include <bits/libc-lock.h> | ||
46 | __libc_lock_define_initialized (static, envlock) | ||
47 | # define LOCK __libc_lock_lock (envlock) | ||
48 | # define UNLOCK __libc_lock_unlock (envlock) | ||
49 | #else | ||
50 | # define LOCK | ||
51 | # define UNLOCK | ||
52 | #endif | ||
53 | |||
54 | /* In the GNU C library we must keep the namespace clean. */ | ||
55 | #ifdef _LIBC | ||
56 | # define unsetenv __unsetenv | ||
57 | #endif | ||
58 | |||
59 | |||
60 | int | ||
61 | unsetenv (const char *name) | ||
62 | { | ||
63 | size_t len; | ||
64 | char **ep; | ||
65 | |||
66 | if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) | ||
67 | { | ||
68 | __set_errno (EINVAL); | ||
69 | return -1; | ||
70 | } | ||
71 | |||
72 | len = strlen (name); | ||
73 | |||
74 | LOCK; | ||
75 | |||
76 | ep = __environ; | ||
77 | while (*ep != NULL) | ||
78 | if (!strncmp (*ep, name, len) && (*ep)[len] == '=') | ||
79 | { | ||
80 | /* Found it. Remove this pointer by moving later ones back. */ | ||
81 | char **dp = ep; | ||
82 | |||
83 | do | ||
84 | dp[0] = dp[1]; | ||
85 | while (*dp++); | ||
86 | /* Continue the loop in case NAME appears again. */ | ||
87 | } | ||
88 | else | ||
89 | ++ep; | ||
90 | |||
91 | UNLOCK; | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | #ifdef _LIBC | ||
97 | # undef unsetenv | ||
98 | weak_alias (__unsetenv, unsetenv) | ||
99 | #endif |
lib/vasprintf.h
0 → 100644
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 along | ||
15 | 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 | #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 | ||
45 | extern "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. */ | ||
52 | extern int asprintf (char **result, const char *format, ...) | ||
53 | __attribute__ ((__format__ (__printf__, 2, 3))); | ||
54 | extern 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 */ |
lib/xsize.h
0 → 100644
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */ | ||
52 | static inline size_t | ||
53 | #if __GNUC__ >= 3 | ||
54 | __attribute__ ((__pure__)) | ||
55 | #endif | ||
56 | xsum (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. */ | ||
63 | static inline size_t | ||
64 | #if __GNUC__ >= 3 | ||
65 | __attribute__ ((__pure__)) | ||
66 | #endif | ||
67 | xsum3 (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. */ | ||
73 | static inline size_t | ||
74 | #if __GNUC__ >= 3 | ||
75 | __attribute__ ((__pure__)) | ||
76 | #endif | ||
77 | xsum4 (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. */ | ||
83 | static inline size_t | ||
84 | #if __GNUC__ >= 3 | ||
85 | __attribute__ ((__pure__)) | ||
86 | #endif | ||
87 | xmax (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 */ |
-
Please register or sign in to post a comment